settings.go
3580 bytes
1package cmd
2
3import (
4 "fmt"
5 "strconv"
6
7 "github.com/charmbracelet/soft-serve/pkg/access"
8 "github.com/charmbracelet/soft-serve/pkg/backend"
9 "github.com/charmbracelet/soft-serve/pkg/config"
10 "github.com/spf13/cobra"
11)
12
13// SettingsCommand returns a command that manages server settings.
14func SettingsCommand() *cobra.Command {
15 cmd := &cobra.Command{
16 Use: "settings",
17 Short: "Manage server settings",
18 // Gate the whole command tree rather than each subcommand. Cobra
19 // runs the nearest persistent pre-run found when walking up from
20 // the invoked command, so subcommands added later are gated by
21 // default instead of silently unprotected.
22 PersistentPreRunE: checkIfServerAdmin,
23 }
24
25 cmd.AddCommand(
26 &cobra.Command{
27 Use: "allow-keyless [true|false]",
28 Short: "Set or get allow keyless access to repositories",
29 Args: cobra.RangeArgs(0, 1),
30 RunE: func(cmd *cobra.Command, args []string) error {
31 ctx := cmd.Context()
32 be := backend.FromContext(ctx)
33 cfg := config.FromContext(ctx)
34 switch len(args) {
35 case 0:
36 cmd.Println(be.AllowKeyless(ctx))
37 case 1:
38 v, _ := strconv.ParseBool(args[0])
39 if err := be.SetAllowKeyless(ctx, v); err != nil {
40 return err
41 }
42 warnIfAllowKeylessOverridden(cmd, cfg)
43 }
44
45 return nil
46 },
47 },
48 )
49
50 als := []string{access.NoAccess.String(), access.ReadOnlyAccess.String(), access.ReadWriteAccess.String(), access.AdminAccess.String()}
51 cmd.AddCommand(
52 &cobra.Command{
53 Use: "anon-access [ACCESS_LEVEL]",
54 Short: "Set or get the default access level for anonymous users",
55 Args: cobra.RangeArgs(0, 1),
56 ValidArgs: als,
57 RunE: func(cmd *cobra.Command, args []string) error {
58 ctx := cmd.Context()
59 be := backend.FromContext(ctx)
60 cfg := config.FromContext(ctx)
61 switch len(args) {
62 case 0:
63 cmd.Println(be.AnonAccess(ctx))
64 case 1:
65 al := access.ParseAccessLevel(args[0])
66 if al < 0 {
67 return fmt.Errorf("invalid access level: %s. Please choose one of the following: %s", args[0], als)
68 }
69 if err := be.SetAnonAccess(ctx, al); err != nil {
70 return err
71 }
72 warnIfAnonAccessOverridden(cmd, cfg)
73 }
74
75 return nil
76 },
77 },
78 )
79
80 return cmd
81}
82
83// warnIfAllowKeylessOverridden warns on the command's stderr if a server
84// config override is masking the allow-keyless value that was just written
85// to the database. Without this, an admin changing the setting via this
86// command would have no way to know their change has no effect.
87func warnIfAllowKeylessOverridden(cmd *cobra.Command, cfg *config.Config) {
88 if cfg == nil || cfg.AllowKeyless == nil {
89 return
90 }
91
92 fmt.Fprintf(cmd.ErrOrStderr(),
93 "Warning: allow-keyless is set to %t by server config and takes precedence over this change. "+
94 "The database was updated, but it will have no effect until the config override is removed.\n",
95 *cfg.AllowKeyless)
96}
97
98// warnIfAnonAccessOverridden warns on the command's stderr if a server
99// config override is masking the anon-access value that was just written to
100// the database. Without this, an admin changing the setting via this
101// command would have no way to know their change has no effect.
102func warnIfAnonAccessOverridden(cmd *cobra.Command, cfg *config.Config) {
103 if cfg == nil || cfg.AnonAccess == nil {
104 return
105 }
106
107 fmt.Fprintf(cmd.ErrOrStderr(),
108 "Warning: anon-access is set to %q by server config and takes precedence over this change. "+
109 "The database was updated, but it will have no effect until the config override is removed.\n",
110 cfg.AnonAccess.String())
111}