// Load returns a low-level "handler config" from the provided filename. // If the config file doesn't contain a top-level JSON key of "handlerConfig" // with boolean value true, the configuration is assumed to be a high-level // "user config" file, and transformed into a low-level config. func Load(filename string) (*Config, error) { obj, err := jsonconfig.ReadFile(filename) if err != nil { return nil, err } conf := &Config{ Obj: obj, configPath: filename, } if lowLevel := obj.OptionalBool("handlerConfig", false); !lowLevel { conf, err = genLowLevelConfig(conf) if err != nil { return nil, fmt.Errorf( "Failed to transform user config file %q into internal handler configuration: %v", filename, err) } if v, _ := strconv.ParseBool(os.Getenv("CAMLI_DEBUG_CONFIG")); v { jsconf, _ := json.MarshalIndent(conf.Obj, "", " ") log.Printf("From high-level config, generated low-level config: %s", jsconf) } } return conf, nil }
// Reads google storage config and creates a Client. Exits on error. func doConfig(t *testing.T) (gsa *Client, bucket string) { if *gsConfigPath == "" { t.Skip("Skipping manual test. Set flag --gs_config_path to test Google Storage.") } cf, err := jsonconfig.ReadFile(*gsConfigPath) if err != nil { t.Fatalf("Failed to read config: %v", err) } var config jsonconfig.Obj config = cf.RequiredObject("gsconf") if err := cf.Validate(); err != nil { t.Fatalf("Invalid config: %v", err) } auth := config.RequiredObject("auth") bucket = config.RequiredString("bucket") if err := config.Validate(); err != nil { t.Fatalf("Invalid config: %v", err) } gsa = NewClient(MakeOauthTransport(auth.RequiredString("client_id"), auth.RequiredString("client_secret"), auth.RequiredString("refresh_token"))) if err := auth.Validate(); err != nil { t.Fatalf("Invalid config: %v", err) } return }
// Reads google storage config and creates a Client. Exits on error. func doConfig(t *testing.T) (gsa *Client, bucket string) { if *gsConfigPath == "" { t.Skip("Skipping manual test. Set flag --gs_config_path to test Google Storage.") } cf, err := jsonconfig.ReadFile(*gsConfigPath) if err != nil { t.Fatalf("Failed to read config: %v", err) } var config jsonconfig.Obj config = cf.RequiredObject("gsconf") if err := cf.Validate(); err != nil { t.Fatalf("Invalid config: %v", err) } auth := config.RequiredObject("auth") bucket = config.RequiredString("bucket") if err := config.Validate(); err != nil { t.Fatalf("Invalid config: %v", err) } gsa = NewClient(oauth2.NewClient(oauth2.NoContext, oauthutil.NewRefreshTokenSource(&oauth2.Config{ Scopes: []string{Scope}, Endpoint: google.Endpoint, ClientID: auth.RequiredString("client_id"), ClientSecret: auth.RequiredString("client_secret"), RedirectURL: oauthutil.TitleBarRedirectURL, }, auth.RequiredString("refresh_token")))) if err := auth.Validate(); err != nil { t.Fatalf("Invalid config: %v", err) } return }
// Reads google storage config and creates a Client. Exits on error. func doConfig(t *testing.T) (gsa *Client, bucket string) { gsConfigPath := filepath.Join(osutil.CamliConfigDir(), "gstestconfig.json") if _, err := os.Stat(gsConfigPath); os.IsNotExist(err) { test.DependencyErrorOrSkip(t) t.Fatalf("Missing config file: %v", err) } cf, err := jsonconfig.ReadFile(gsConfigPath) if err != nil { t.Fatalf("Failed to read config: %v", err) } var config jsonconfig.Obj config = cf.RequiredObject("gsconf") if err := cf.Validate(); err != nil { t.Fatalf("Invalid config: %v", err) } auth := config.RequiredObject("auth") bucket = config.RequiredString("bucket") if err := config.Validate(); err != nil { t.Fatalf("Invalid config: %v", err) } gsa = NewClient(MakeOauthTransport(auth.RequiredString("client_id"), auth.RequiredString("client_secret"), auth.RequiredString("refresh_token"))) if err := auth.Validate(); err != nil { t.Fatalf("Invalid config: %v", err) } return }
func parseConfig() { if android.OnAndroid() { return } configPath := osutil.UserClientConfigPath() if _, err := os.Stat(configPath); os.IsNotExist(err) { errMsg := fmt.Sprintf("Client configuration file %v does not exist. See 'camput init' to generate it.", configPath) if keyId := serverKeyId(); keyId != "" { hint := fmt.Sprintf("\nThe key id %v was found in the server config %v, so you might want:\n'camput init -gpgkey %v'", keyId, osutil.UserServerConfigPath(), keyId) errMsg += hint } log.Fatal(errMsg) } conf, err := jsonconfig.ReadFile(configPath) if err != nil { log.Fatal(err.Error()) } cfg := jsonconfig.Obj(conf) config = &clientConfig{ auth: cfg.OptionalString("auth", ""), server: cfg.OptionalString("server", ""), identity: cfg.OptionalString("identity", ""), identitySecretRing: cfg.OptionalString("identitySecretRing", osutil.IdentitySecretRing()), trustedCerts: cfg.OptionalList("trustedCerts"), ignoredFiles: cfg.OptionalList("ignoredFiles"), } if err := cfg.Validate(); err != nil { printConfigChangeHelp(cfg) log.Fatalf("Error in config file: %v", err) } }
func handleSetupChange(rw http.ResponseWriter, req *http.Request) { hilevelConf, err := jsonconfig.ReadFile(osutil.UserServerConfigPath()) if err != nil { httputil.ServeError(rw, req, err) return } if !xsrftoken.Valid(req.FormValue("token"), serverKey, "user", "wizardSave") { http.Error(rw, "Form expired. Press back and reload form.", http.StatusBadRequest) log.Printf("invalid xsrf token=%q", req.FormValue("token")) return } hasChanged := false var el interface{} publish := jsonconfig.Obj{} for k, v := range req.Form { if _, ok := hilevelConf[k]; !ok { if k != "gallery" && k != "blog" { continue } } switch k { case "https", "shareHandler": b, err := strconv.ParseBool(v[0]) if err != nil { httputil.ServeError(rw, req, fmt.Errorf("%v field expects a boolean value", k)) } el = b default: el = v[0] } if reflect.DeepEqual(hilevelConf[k], el) { continue } hasChanged = true hilevelConf[k] = el } // "publish" wasn't checked yet if !reflect.DeepEqual(hilevelConf["publish"], publish) { hilevelConf["publish"] = publish hasChanged = true } if hasChanged { err = rewriteConfig(&hilevelConf, osutil.UserServerConfigPath()) if err != nil { httputil.ServeError(rw, req, err) return } err = osutil.RestartProcess() if err != nil { log.Fatal("Failed to restart: " + err.Error()) http.Error(rw, "Failed to restart process", 500) return } } sendWizard(rw, req, hasChanged) }
func parseConfig() { configPath := ConfigFilePath() var err error if config, err = jsonconfig.ReadFile(configPath); err != nil { log.Fatal(err.Error()) return } }
func parseConfig() { configPath := ConfigFilePath() if _, err := os.Stat(configPath); os.IsNotExist(err) { parseConfigErr = os.ErrNotExist return } var err error if config, err = jsonconfig.ReadFile(configPath); err != nil { log.Fatal(err.Error()) return } }
func sendWizard(rw http.ResponseWriter, req *http.Request, hasChanged bool) { config, err := jsonconfig.ReadFile(osutil.UserServerConfigPath()) if err != nil { httputil.ServeError(rw, req, err) return } err = flattenPublish(config) if err != nil { httputil.ServeError(rw, req, err) return } funcMap := template.FuncMap{ "printWizard": printWizard, "showField": func(inputName string) bool { if _, ok := ignoredFields[inputName]; ok { return false } return true }, "genXSRF": func() string { return xsrftoken.Generate(serverKey, "user", "wizardSave") }, } body := ` <form id="WizardForm" method="POST" enctype="multipart/form-data"> <table> {{range $k,$v := .}}{{if showField $k}}<tr><td>{{printf "%v" $k}}</td><td><input type="text" size="30" name ="{{printf "%v" $k}}" value="{{printWizard $v}}" ></td></tr>{{end}}{{end}} </table> <input type="hidden" name="token" value="{{genXSRF}}"> <input type="submit" form="WizardForm" value="Save"> (Will restart server.)</form>` if hasChanged { body += `<p> Configuration succesfully rewritten </p>` } tmpl, err := template.New("wizard").Funcs(funcMap).Parse(topWizard + body + bottomWizard) if err != nil { httputil.ServeError(rw, req, err) return } err = tmpl.Execute(rw, config) if err != nil { httputil.ServeError(rw, req, err) return } }
func parseConfig() { configPath := osutil.UserClientConfigPath() if _, err := os.Stat(configPath); os.IsNotExist(err) { errMsg := fmt.Sprintf("Client configuration file %v does not exist. See 'camput init' to generate it.", configPath) if keyId := serverKeyId(); keyId != "" { hint := fmt.Sprintf("\nThe key id %v was found in the server config %v, so you might want:\n'camput init -gpgkey %v'", keyId, osutil.UserServerConfigPath(), keyId) errMsg += hint } log.Fatal(errMsg) } var err error if config, err = jsonconfig.ReadFile(configPath); err != nil { log.Fatal(err.Error()) return } }
func TestS3(t *testing.T) { cfgFile := os.Getenv("CAMLI_S3_TEST_CONFIG_JSON") if cfgFile == "" { t.Skip("Skipping manual test. To enable, set the environment variable CAMLI_S3_TEST_CONFIG_JSON to the path of a JSON configuration for the s3 storage type.") } conf, err := jsonconfig.ReadFile(cfgFile) if err != nil { t.Fatalf("Error reading s3 configuration file %s: %v", cfgFile, err) } storagetest.Test(t, func(t *testing.T) (sto blobserver.Storage, cleanup func()) { sto, err := newFromConfig(nil, conf) if err != nil { t.Fatalf("newFromConfig error: %v", err) } return sto, func() {} }) }
// Load returns a low-level "handler config" from the provided filename. // If the config file doesn't contain a top-level JSON key of "handlerConfig" // with boolean value true, the configuration is assumed to be a high-level // "user config" file, and transformed into a low-level config. func Load(filename string) (*Config, error) { obj, err := jsonconfig.ReadFile(filename) if err != nil { return nil, err } conf := &Config{ Obj: obj, configPath: filename, } if lowLevel := obj.OptionalBool("handlerConfig", false); lowLevel { return conf, nil } if err := detectConfigChange(obj); err != nil { return nil, err } absConfigPath, err := filepath.Abs(filename) if err != nil { return nil, fmt.Errorf("Failed to expand absolute path for %s: %v", filename, err) } b, err := ioutil.ReadFile(absConfigPath) if err != nil { return nil, fmt.Errorf("Could not read %s: %v", absConfigPath, err) } var hiLevelConf serverconfig.Config if err := json.Unmarshal(b, &hiLevelConf); err != nil { return nil, fmt.Errorf("Could not unmarshal %s into a serverconfig.Config: %v", absConfigPath, err) } conf, err = genLowLevelConfig(&hiLevelConf) if err != nil { return nil, fmt.Errorf( "Failed to transform user config file %q into internal handler configuration: %v", filename, err) } if v, _ := strconv.ParseBool(os.Getenv("CAMLI_DEBUG_CONFIG")); v { jsconf, _ := json.MarshalIndent(conf.Obj, "", " ") log.Printf("From high-level config, generated low-level config: %s", jsconf) } conf.configPath = absConfigPath return conf, nil }
// serverKeyId returns the public gpg key id ("identity" field) // from the user's server config , if any. // It returns the empty string otherwise. func serverKeyId() string { serverConfigFile := osutil.UserServerConfigPath() if _, err := os.Stat(serverConfigFile); err != nil { if os.IsNotExist(err) { return "" } log.Fatalf("Could not stat %v: %v", serverConfigFile, err) } obj, err := jsonconfig.ReadFile(serverConfigFile) if err != nil { return "" } keyId, ok := obj["identity"].(string) if !ok { return "" } return keyId }
// Reads google storage config and creates a Client. Exits on error. func doConfig(t *testing.T) (gsa *Client, bucket string) { if _, err := os.Stat("gstestconfig.json"); os.IsNotExist(err) { testdep.CheckEnv(t) t.Fatalf("Missing config file: %v", err) } cf, err := jsonconfig.ReadFile("testconfig.json") if err != nil { t.Fatalf("Failed to read config: %v", err) } var config jsonconfig.Obj config = cf.RequiredObject("gsconf") if err := cf.Validate(); err != nil { t.Fatalf("Invalid config: %v", err) } auth := config.RequiredObject("auth") bucket = config.RequiredString("bucket") if err := config.Validate(); err != nil { t.Fatalf("Invalid config: %v", err) } gsa = NewClient(&oauth.Transport{ &oauth.Config{ ClientId: auth.RequiredString("client_id"), ClientSecret: auth.RequiredString("client_secret"), Scope: "https://www.googleapis.com/auth/devstorage.read_write", AuthURL: "https://accounts.google.com/o/oauth2/auth", TokenURL: "https://accounts.google.com/o/oauth2/token", RedirectURL: "urn:ietf:wg:oauth:2.0:oob", }, &oauth.Token{ AccessToken: "", RefreshToken: auth.RequiredString("refresh_token"), }, nil, }) if err := auth.Validate(); err != nil { t.Fatalf("Invalid config: %v", err) } return }
func sendWizard(rw http.ResponseWriter, req *http.Request, hasChanged bool) { config, err := jsonconfig.ReadFile(osutil.UserServerConfigPath()) if err != nil { httputil.ServerError(rw, req, err) return } err = flattenPublish(config) if err != nil { httputil.ServerError(rw, req, err) return } funcMap := template.FuncMap{ "printWizard": printWizard, "inputIsGallery": func(inputName string) bool { return inputName == "gallery" }, } body := `<form id="WizardForm" action="setup" method="post" enctype="multipart/form-data">` body += `{{range $k,$v := .}}{{printf "%v" $k}} <input type="text" size="30" name ="{{printf "%v" $k}}" value="{{printWizard $v}}" {{if inputIsGallery $k}}placeholder="/pics/,sha1-xxxx,pics.css"{{end}}><br />{{end}}` body += `<input type="submit" form="WizardForm" value="Save"></form>` if hasChanged { body += `<p> Configuration succesfully rewritten </p>` } tmpl, err := template.New("wizard").Funcs(funcMap).Parse(topWizard + body + bottomWizard) if err != nil { httputil.ServerError(rw, req, err) return } err = tmpl.Execute(rw, config) if err != nil { httputil.ServerError(rw, req, err) return } }
func handleSetupChange(rw http.ResponseWriter, req *http.Request) { hilevelConf, err := jsonconfig.ReadFile(osutil.UserServerConfigPath()) if err != nil { httputil.ServerError(rw, req, err) return } hasChanged := false var el interface{} publish := jsonconfig.Obj{} for k, v := range req.Form { if _, ok := hilevelConf[k]; !ok { if k != "gallery" && k != "blog" { continue } } switch k { case "https": b, err := strconv.ParseBool(v[0]) if err != nil { httputil.ServerError(rw, req, fmt.Errorf("https field expects a boolean value")) } el = b case "replicateTo": // TODO(mpl): figure out why it is always seen as different from the conf el = []interface{}{} if len(v[0]) > 0 { els := []string{} vals := strings.Split(v[0], ",") els = append(els, vals...) el = els } // TODO(mpl): "handler,rootPermanode[,style]" for each published entity for now. // we will need something more readable later probably case "gallery", "blog": if len(v[0]) > 0 { pub := strings.Split(v[0], ",") if len(pub) < 2 || len(pub) > 3 { // no need to fail loudly for now as we'll probably change this format continue } handler := jsonconfig.Obj{} handler["template"] = k handler["rootPermanode"] = pub[1] if len(pub) > 2 { handler["style"] = pub[2] } publish[pub[0]] = handler } continue default: el = v[0] } if reflect.DeepEqual(hilevelConf[k], el) { continue } hasChanged = true hilevelConf[k] = el } // "publish" wasn't checked yet if !reflect.DeepEqual(hilevelConf["publish"], publish) { hilevelConf["publish"] = publish hasChanged = true } if hasChanged { err = rewriteConfig(&hilevelConf, osutil.UserServerConfigPath()) if err != nil { httputil.ServerError(rw, req, err) return } } sendWizard(rw, req, hasChanged) return }
func parseConfig() { if android.OnAndroid() { panic("parseConfig should never have been called on Android") } configPath := osutil.UserClientConfigPath() if _, err := os.Stat(configPath); os.IsNotExist(err) { errMsg := fmt.Sprintf("Client configuration file %v does not exist. See 'camput init' to generate it.", configPath) if keyId := serverKeyId(); keyId != "" { hint := fmt.Sprintf("\nThe key id %v was found in the server config %v, so you might want:\n'camput init -gpgkey %v'", keyId, osutil.UserServerConfigPath(), keyId) errMsg += hint } log.Fatal(errMsg) } // TODO: instead of using jsonconfig, we could read the file, and unmarshall into the structs that we now have in pkg/types/clientconfig. But we'll have to add the old fields (before the name changes, and before the multi-servers change) to the structs as well for our gracefull conversion/error messages to work. conf, err := jsonconfig.ReadFile(configPath) if err != nil { log.Fatal(err.Error()) } cfg := jsonconfig.Obj(conf) if singleServerAuth := cfg.OptionalString("auth", ""); singleServerAuth != "" { newConf, err := convertToMultiServers(cfg) if err != nil { log.Print(err) } else { cfg = newConf } } config = &clientconfig.Config{ Identity: cfg.OptionalString("identity", ""), IdentitySecretRing: cfg.OptionalString("identitySecretRing", osutil.IdentitySecretRing()), IgnoredFiles: cfg.OptionalList("ignoredFiles"), } serversList := make(map[string]*clientconfig.Server) servers := cfg.OptionalObject("servers") for alias, vei := range servers { // An alias should never be confused with a host name, // so we forbid anything looking like one. if isURLOrHostPort(alias) { log.Fatalf("Server alias %q looks like a hostname; \".\" or \";\" are not allowed.", alias) } serverMap, ok := vei.(map[string]interface{}) if !ok { log.Fatalf("entry %q in servers section is a %T, want an object", alias, vei) } serverConf := jsonconfig.Obj(serverMap) server := &clientconfig.Server{ Server: cleanServer(serverConf.OptionalString("server", "")), Auth: serverConf.OptionalString("auth", ""), IsDefault: serverConf.OptionalBool("default", false), TrustedCerts: serverConf.OptionalList("trustedCerts"), } if err := serverConf.Validate(); err != nil { log.Fatalf("Error in servers section of config file for server %q: %v", alias, err) } serversList[alias] = server } config.Servers = serversList if err := cfg.Validate(); err != nil { printConfigChangeHelp(cfg) log.Fatalf("Error in config file: %v", err) } }