// API returns a handler for a set of routes. func API() http.Handler { mongoURI := cfg.MustURL(cfgMongoURI) // The web framework middleware for Mongo is using the name of the // database as the name of the master session by convention. So use // cfg.DB as the second argument when creating the master session. if err := db.RegMasterSession("startup", mongoURI.Path, mongoURI.String(), 25*time.Second); err != nil { log.Error("startup", "Init", err, "Initializing MongoDB") os.Exit(1) } w := web.New(logm.Midware, errorm.Midware) publicKey, err := cfg.String(cfgAuthPublicKey) if err != nil || publicKey == "" { log.User("startup", "Init", "%s is missing, internal authentication is disabled", cfgAuthPublicKey) } // If the public key is provided then add the auth middleware or fail using // the provided public key. if publicKey != "" { log.Dev("startup", "Init", "Initializing Auth") authm, err := authm.Midware(publicKey, authm.MidwareOpts{}) if err != nil { log.Error("startup", "Init", err, "Initializing Auth") os.Exit(1) } // Apply the authentication middleware on top of the application as the // first middleware. w.Use(authm) } // Add the Mongo and Cayley middlewares possibly after the auth middleware. w.Use(mongo.Midware(mongoURI), cayley.Midware(mongoURI)) if cors, err := cfg.Bool(cfgEnableCORS); err == nil && cors { log.Dev("startup", "Init", "Initializing CORS : CORS Enabled") w.Use(w.CORS()) } else { log.Dev("startup", "Init", "CORS Disabled") } log.Dev("startup", "Init", "Initalizing routes") routes(w) return w }
// API returns a handler for a set of routes. func API() http.Handler { w := web.New(logm.Midware, errorm.Midware) publicKey, err := cfg.String(cfgAuthPublicKey) if err != nil || publicKey == "" { log.User("startup", "Init", "%s is missing, internal authentication is disabled", cfgAuthPublicKey) } // If the public key is provided then add the auth middleware or fail using // the provided public key. if publicKey != "" { log.Dev("startup", "Init", "Initializing Auth") authm, err := authm.Midware(publicKey, authm.MidwareOpts{}) if err != nil { log.Error("startup", "Init", err, "Initializing Auth") os.Exit(1) } // Apply the authentication middleware on top of the application as the // first middleware. w.Use(authm) } platformPrivateKey, err := cfg.String(cfgPlatformPrivateKey) if err != nil || platformPrivateKey == "" { log.User("startup", "Init", "%s is missing, downstream platform authentication is disabled", cfgPlatformPrivateKey) } // If the platformPrivateKey is provided, then we should generate the token // signing function to be used when composing requests down to the platform. if platformPrivateKey != "" { log.Dev("startup", "Init", "Initializing Downstream Platform Auth") signer, err := auth.NewSigner(platformPrivateKey) if err != nil { log.Error("startup", "Init", err, "Initializing Downstream Platform Auth") os.Exit(1) } // Requests can now be signed with the given signer function which we will // save on the application wide context. In the event that a function // requires a call down to a downstream platform, we will include a signed // header using the signer function here. w.Ctx["signer"] = signer } if cors, err := cfg.Bool(cfgEnableCORS); err == nil && cors { log.Dev("startup", "Init", "Initializing CORS : CORS Enabled") w.Use(w.CORS()) } else { log.Dev("startup", "Init", "CORS Disabled") } // We need the URL for the services Sponged and Xeniad that needs to be running. spongedURL, err = cfg.String(cfgSpongedURL) if err != nil || spongedURL == "" { log.Error("startup", "Init", err, "Service Sponged needs to be setup.") os.Exit(1) } w.Ctx["spongedURL"] = cfg.MustURL(cfgSpongedURL).String() xeniadURL, err = cfg.String(cfgXeniadURL) if err != nil || xeniadURL == "" { log.Error("startup", "Init", err, "Service Xeniad needs to be setup.") os.Exit(1) } w.Ctx["xeniadURL "] = cfg.MustURL(cfgXeniadURL).String() log.Dev("startup", "Init", "Initalizing routes") routes(w) return w }
func routes(w *web.Web) { // Create a new app group which will be for internal functions that may have // an optional layer of auth added to it. internal := w.Group() // Now we will load in the public key from the config. If found, we'll add a // middleware to all internal endpoints that will ensure that we validate the // requests coming in. publicKey, err := cfg.String(cfgAuthPublicKey) if err != nil || publicKey == "" { log.User("startup", "Init", "%s is missing, internal authentication is disabled", cfgAuthPublicKey) } // If the public key is provided then add the auth middleware or fail using // the provided public key. if publicKey != "" { log.Dev("startup", "Init", "Initializing Auth") // We are allowing the query string to act as the access token provider // because this service has endpoints that are accessed directly currently // and we need someway to authenticate to these endpoints. authmOpts := auth.MidwareOpts{ AllowQueryString: true, } authm, err := auth.Midware(publicKey, authmOpts) if err != nil { log.Error("startup", "Init", err, "Initializing Auth") os.Exit(1) } // Apply the authentication middleware on top of the application as the // first middleware. internal.Use(authm) } // global internal.Handle("GET", "/v1/version", handlers.Version.List) // forms internal.Handle("POST", "/v1/form", handlers.Form.Upsert) internal.Handle("GET", "/v1/form", handlers.Form.List) internal.Handle("PUT", "/v1/form/:id", handlers.Form.Upsert) internal.Handle("PUT", "/v1/form/:id/status/:status", handlers.Form.UpdateStatus) internal.Handle("GET", "/v1/form/:id", handlers.Form.Retrieve) internal.Handle("DELETE", "/v1/form/:id", handlers.Form.Delete) // form aggregations internal.Handle("GET", "/v1/form/:form_id/digest", handlers.Aggregation.Digest) internal.Handle("GET", "/v1/form/:form_id/aggregate", handlers.Aggregation.Aggregate) internal.Handle("GET", "/v1/form/:form_id/aggregate/:group_id", handlers.Aggregation.AggregateGroup) internal.Handle("GET", "/v1/form/:form_id/aggregate/:group_id/submission", handlers.Aggregation.SubmissionGroup) // form submissions internal.Handle("GET", "/v1/form/:form_id/submission", handlers.FormSubmission.Search) internal.Handle("GET", "/v1/form/:form_id/submission/:id", handlers.FormSubmission.Retrieve) internal.Handle("PUT", "/v1/form/:form_id/submission/:id/status/:status", handlers.FormSubmission.UpdateStatus) internal.Handle("POST", "/v1/form/:form_id/submission/:id/flag/:flag", handlers.FormSubmission.AddFlag) internal.Handle("DELETE", "/v1/form/:form_id/submission/:id/flag/:flag", handlers.FormSubmission.RemoveFlag) internal.Handle("PUT", "/v1/form/:form_id/submission/:id/answer/:answer_id", handlers.FormSubmission.UpdateAnswer) internal.Handle("DELETE", "/v1/form/:form_id/submission/:id", handlers.FormSubmission.Delete) // temporal route to get CSV file - TO DO : move into a different service internal.Handle("GET", "/v1/form/:form_id/submission/export", handlers.FormSubmission.Download) // form form galleries internal.Handle("GET", "/v1/form/:form_id/gallery", handlers.FormGallery.RetrieveForForm) // form galleries internal.Handle("GET", "/v1/form_gallery/:id", handlers.FormGallery.Retrieve) internal.Handle("PUT", "/v1/form_gallery/:id", handlers.FormGallery.Update) internal.Handle("POST", "/v1/form_gallery/:id/submission/:submission_id/:answer_id", handlers.FormGallery.AddAnswer) internal.Handle("DELETE", "/v1/form_gallery/:id/submission/:submission_id/:answer_id", handlers.FormGallery.RemoveAnswer) // Create a new app group which will be for external functions that will need // to be publically exposed. external := w.Group() external.Handle("POST", "/v1/form/:form_id/submission", handlers.FormSubmission.Create) }