github.com/cozy/cozy-stack@v0.0.0-20240603063001-31110fa4cae1/cmd/settings.go (about)

     1  package cmd
     2  
     3  import (
     4  	"bytes"
     5  	"encoding/json"
     6  	"errors"
     7  	"fmt"
     8  	"os"
     9  	"sort"
    10  	"strings"
    11  
    12  	"github.com/cozy/cozy-stack/client"
    13  	"github.com/cozy/cozy-stack/client/request"
    14  	"github.com/cozy/cozy-stack/pkg/consts"
    15  	"github.com/spf13/cobra"
    16  )
    17  
    18  var settingsCmd = &cobra.Command{
    19  	Use:   "settings [settings]",
    20  	Short: "Display and update settings",
    21  	Long: `
    22  cozy-stack settings displays the settings.
    23  
    24  It can also take a list of settings to update.
    25  
    26  If you give a blank value, the setting will be removed.
    27  `,
    28  	Example: "$ cozy-stack settings --domain cozy.localhost:8080 context:beta,public_name:John,to_remove:",
    29  	RunE: func(cmd *cobra.Command, args []string) error {
    30  		if flagDomain == "" {
    31  			errPrintfln("%s", errMissingDomain)
    32  			return cmd.Usage()
    33  		}
    34  		c := newClient(flagDomain, consts.Settings)
    35  		res, err := c.Req(&request.Options{
    36  			Method: "GET",
    37  			Path:   "/settings/instance",
    38  		})
    39  		if err != nil {
    40  			return err
    41  		}
    42  		defer res.Body.Close()
    43  		var obj map[string]interface{}
    44  		if err = json.NewDecoder(res.Body).Decode(&obj); err != nil {
    45  			return err
    46  		}
    47  		if len(args) > 0 {
    48  			obj, err = updateSettings(c, obj, args[0])
    49  			if err != nil {
    50  				return err
    51  			}
    52  		}
    53  		printSettings(obj)
    54  		return nil
    55  	},
    56  }
    57  
    58  func printSettings(obj map[string]interface{}) {
    59  	data, ok := obj["data"].(map[string]interface{})
    60  	if !ok {
    61  		return
    62  	}
    63  	attrs, ok := data["attributes"].(map[string]interface{})
    64  	if !ok {
    65  		return
    66  	}
    67  	keys := make([]string, 0, len(attrs))
    68  	for k := range attrs {
    69  		keys = append(keys, k)
    70  	}
    71  	sort.Strings(keys)
    72  	for _, k := range keys {
    73  		fmt.Fprintf(os.Stdout, "- %s: %v\n", k, attrs[k])
    74  	}
    75  }
    76  
    77  func updateSettings(c *client.Client, obj map[string]interface{}, args string) (map[string]interface{}, error) {
    78  	data, ok := obj["data"].(map[string]interface{})
    79  	if !ok {
    80  		return nil, errors.New("data not found")
    81  	}
    82  	attrs, ok := data["attributes"].(map[string]interface{})
    83  	if !ok {
    84  		return nil, errors.New("attributes not found")
    85  	}
    86  	for _, arg := range strings.Split(args, ",") {
    87  		parts := strings.SplitN(arg, ":", 2)
    88  		k := parts[0]
    89  		if len(parts) < 2 || parts[1] == "" {
    90  			delete(attrs, k)
    91  		} else {
    92  			attrs[k] = parts[1]
    93  		}
    94  	}
    95  	delete(obj, "links")
    96  	buf, err := json.Marshal(obj)
    97  	if err != nil {
    98  		return nil, err
    99  	}
   100  	body := bytes.NewReader(buf)
   101  	res, err := c.Req(&request.Options{
   102  		Method: "PUT",
   103  		Path:   "/settings/instance",
   104  		Body:   body,
   105  	})
   106  	if err != nil {
   107  		return nil, err
   108  	}
   109  	defer res.Body.Close()
   110  	err = json.NewDecoder(res.Body).Decode(&obj)
   111  	return obj, err
   112  }
   113  
   114  func init() {
   115  	settingsCmd.PersistentFlags().StringVar(&flagDomain, "domain", cozyDomain(), "specify the domain name of the instance")
   116  	RootCmd.AddCommand(settingsCmd)
   117  }