Beispiel #1
0
// Init is called to initialize the application.
func Init(configKey string) {

	// Init the configuration system.
	if err := cfg.Init(cfg.EnvProvider{Namespace: configKey}); err != nil {
		fmt.Println("Error initalizing configuration system", err)
		os.Exit(1)
	}

	// Init the log system.
	logLevel := func() int {
		ll, err := cfg.Int(cfgLoggingLevel)
		if err != nil {
			return log.USER
		}
		return ll
	}
	log.Init(os.Stderr, logLevel)

	// Log all the configuration options
	log.User("startup", "Init", "\n\nConfig Settings: %s\n%s\n", configKey, cfg.Log())

	// Init MongoDB if configured.
	if _, err := cfg.String(cfgMongoHost); err == nil {
		app.useMongo = true

		cfg := mongo.Config{
			Host:     cfg.MustString(cfgMongoHost),
			AuthDB:   cfg.MustString(cfgMongoAuthDB),
			DB:       cfg.MustString(cfgMongoDB),
			User:     cfg.MustString(cfgMongoUser),
			Password: cfg.MustString(cfgMongoPassword),
		}

		if err := mongo.Init(cfg); err != nil {
			log.Error("startup", "Init", err, "Initializing MongoDB")
			os.Exit(1)
		}
	}

	// Load user defined custom headers. HEADERS should be key:value,key:value
	if hs, err := cfg.String("HEADERS"); err == nil {
		hdrs := strings.Split(hs, ",")
		for _, hdr := range hdrs {
			if kv := strings.Split(hdr, ":"); len(kv) == 2 {
				log.User("startup", "Init", "User Headers : %s:%s", kv[0], kv[1])
				app.userHeaders[kv[0]] = kv[1]
			}
		}
	}
}
Beispiel #2
0
func main() {
	app.Init(cfg.EnvProvider{Namespace: Namespace})

	// Pull options from the config.
	var conn *db.DB
	if _, errHost := cfg.String(cfgWebHost); errHost != nil {
		xenia.Println("Configuring MongoDB")

		mongoURI := cfg.MustURL(cfgMongoURI)

		err := db.RegMasterSession("startup", mongoURI.Path, mongoURI.String(), 0)
		if err != nil {
			xenia.Println("Unable to initialize MongoDB")
			os.Exit(1)
		}

		conn, err = db.NewMGO("startup", mongoURI.Path)
		if err != nil {
			xenia.Println("Unable to get MongoDB session")
			os.Exit(1)
		}
		defer conn.CloseMGO("startup")
	}

	xenia.AddCommand(
		cmddb.GetCommands(conn),
		cmdquery.GetCommands(),
		cmdscript.GetCommands(),
		cmdregex.GetCommands(),
		cmdmask.GetCommands(),
		cmdrelationship.GetCommands(),
		cmdview.GetCommands(),
	)
	xenia.Execute()
}
Beispiel #3
0
// Init is called to initialize the application.
func Init(configKey string) {

	// Init the configuration system.
	if err := cfg.Init(cfg.EnvProvider{Namespace: configKey}); err != nil {
		fmt.Println("Error initalizing configuration system", err)
		os.Exit(1)
	}

	// Init the log system.
	logLevel := func() int {
		ll, err := cfg.Int(cfgLoggingLevel)
		if err != nil {
			return log.USER
		}
		return ll
	}
	log.Init(os.Stderr, logLevel)

	// Log all the configuration options
	log.User("startup", "Init", "\n\nConfig Settings: %s\n%s\n", configKey, cfg.Log())

	// Load user defined custom headers. HEADERS should be key:value,key:value
	if hs, err := cfg.String("HEADERS"); err == nil {
		hdrs := strings.Split(hs, ",")
		for _, hdr := range hdrs {
			if kv := strings.Split(hdr, ":"); len(kv) == 2 {
				log.User("startup", "Init", "User Headers : %s:%s", kv[0], kv[1])
				app.userHeaders[kv[0]] = kv[1]
			}
		}
	}
}
Beispiel #4
0
// Mongo handles session management.
func Mongo(h app.Handler) app.Handler {

	// Check if mongodb is configured.
	dbName, err := cfg.String(cfgMongoDB)
	if err != nil {
		return func(c *app.Context) error {
			log.Dev(c.SessionID, "Mongo", "******> Mongo Not Configured")
			return h(c)
		}
	}

	// Wrap the handlers inside a session copy/close.
	return func(c *app.Context) error {
		mgoDB, err := db.NewMGO("Mongo", dbName)
		if err != nil {
			log.Error(c.SessionID, "Mongo", err, "Method[%s] URL[%s] RADDR[%s]", c.Request.Method, c.Request.URL.Path, c.Request.RemoteAddr)
			return app.ErrDBNotConfigured
		}

		log.Dev(c.SessionID, "Mongo", "******> Capture Mongo Session")
		c.DB = mgoDB
		defer func() {
			log.Dev(c.SessionID, "Mongo", "******> Release Mongo Session")
			mgoDB.CloseMGO("Mongo")
		}()

		return h(c)
	}
}
Beispiel #5
0
// 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
}
Beispiel #6
0
// 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)
	}

	// Ensure that the database indexes are setup on the underlying MongoDB
	// database.
	if err := ensureDBIndexes(mongoURI); err != nil {
		log.Error("startup", "Init", err, "Initializing DB Indexes")
		os.Exit(1)
	}

	w := web.New(logm.Midware, errorm.Midware, mongo.Midware(mongoURI))

	// Load in the recaptcha secret from the config.
	if recaptcha, err := cfg.String(cfgRecaptchaSecret); err == nil && recaptcha != "" {
		w.Ctx["recaptcha"] = recaptcha
		log.Dev("startup", "Init", "Recaptcha Enabled")
	} else {
		log.Dev("startup", "Init", "%s is missing, recaptcha is disabled", cfgRecaptchaSecret)
	}

	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
}
Beispiel #7
0
// Run is called to start the web service.
func Run(defaultHost string, routes http.Handler) {
	log.Dev("startup", "Run", "Start : defaultHost[%s]", defaultHost)

	// Check for a configured host value.
	host, err := cfg.String(cfgHost)
	if err != nil {
		host = defaultHost
	}

	// Create this goroutine to run the web server.
	go func() {
		log.Dev("listener", "Run", "Listening on: %s", host)
		http.ListenAndServe(host, routes)
	}()

	// Listen for an interrupt signal from the OS.
	sigChan := make(chan os.Signal, 1)
	signal.Notify(sigChan, os.Interrupt)
	<-sigChan

	log.Dev("shutdown", "Run", "Complete")
}
Beispiel #8
0
func init() {
	if err := cfg.Init(cfg.EnvProvider{Namespace: "XENIA"}); err != nil {
		log.Println("Unable to initialize configuration")
		os.Exit(1)
	}

	// Insert the base url for requests by this client.
	DefaultClient.BaseURL = cfg.MustURL(cfgWebHost).String()

	platformPrivateKey, err := cfg.String(cfgPlatformPrivateKey)
	if err != nil || platformPrivateKey == "" {
		if err != nil {
			log.Printf("Downstream Auth : Disabled : %s\n", err.Error())
			return
		}

		log.Printf("Downstream Auth : Disabled\n")
		return
	}

	// If the platformPrivateKey is provided, then we should generate the token
	// signing function to be used when composing requests down to the platform.
	signer, err := auth.NewSigner(platformPrivateKey)
	if err != nil {
		log.Printf("Downstream Auth : Error : %s", err.Error())
		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.
	DefaultClient.Signer = signer

	log.Println("Downstream Auth : Enabled")
}
Beispiel #9
0
// TestExists validates the ability to load configuration values
// using the OS-level environment variables and read them back.
func TestExists(t *testing.T) {
	t.Log("Given the need to read environment variables.")
	{
		uStr := "postgres://*****:*****@127.0.0.1:8080/postgres?sslmode=disable"

		os.Setenv("MYAPP_PROC_ID", "322")
		os.Setenv("MYAPP_SOCKET", "./tmp/sockets.po")
		os.Setenv("MYAPP_PORT", "4034")
		os.Setenv("MYAPP_FLAG", "true")
		os.Setenv("MYAPP_DSN", uStr)

		cfg.Init("MYAPP")

		t.Log("\tWhen given a namspace key to search for that exists.")
		{
			proc, err := cfg.Int("PROC_ID")

			if err != nil {
				t.Errorf("\t\t%s Should not return error when valid key %q", failed, "PROC_ID")
			} else {
				t.Logf("\t\t%s Should not return error when valid key %q", succeed, "PROC_ID")

				if proc != 322 {
					t.Errorf("\t\t%s Should have key %q with value %d", failed, "PROC_ID", 322)
				} else {
					t.Logf("\t\t%s Should have key %q with value %d", succeed, "PROC_ID", 322)
				}
			}

			socket, err := cfg.String("SOCKET")

			if err != nil {
				t.Errorf("\t\t%s Should not return error when valid key %q", failed, "SOCKET")
			} else {
				t.Logf("\t\t%s Should not return error when valid key %q", succeed, "SOCKET")

				if socket != "./tmp/sockets.po" {
					t.Errorf("\t\t%s Should have key %q with value %q", failed, "SOCKET", "./tmp/sockets.po")
				} else {
					t.Logf("\t\t%s Should have key %q with value %q", succeed, "SOCKET", "./tmp/sockets.po")
				}
			}

			port, err := cfg.Int("PORT")

			if err != nil {
				t.Errorf("\t\t%s Should not return error when valid key %q", failed, "PORT")
			} else {
				t.Logf("\t\t%s Should not return error when valid key %q", succeed, "PORT")

				if port != 4034 {
					t.Errorf("\t\t%s Should have key %q with value %d", failed, "PORT", 4034)
				} else {
					t.Logf("\t\t%s Should have key %q with value %d", succeed, "PORT", 4034)
				}
			}

			flag, err := cfg.Bool("FLAG")

			if err != nil {
				t.Errorf("\t\t%s Should not return error when valid key %q", failed, "FLAG")
			} else {
				t.Logf("\t\t%s Should not return error when valid key %q", succeed, "FLAG")

				if flag == false {
					t.Errorf("\t\t%s Should have key %q with value %v", failed, "FLAG", true)
				} else {
					t.Logf("\t\t%s Should have key %q with value %v", succeed, "FLAG", true)
				}
			}

			u, err := cfg.URL("DSN")

			if err != nil {
				t.Errorf("\t\t%s Should not return error when valid key %q", failed, "DSN")
			} else {
				t.Logf("\t\t%s Should not return error when valid key %q", succeed, "DSN")

				if u.String() != uStr {
					t.Errorf("\t\t%s Should have key %q with value %v", failed, "DSN", true)
				} else {
					t.Logf("\t\t%s Should have key %q with value %v", succeed, "DSN", true)
				}
			}
		}
	}
}
Beispiel #10
0
// 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
}
Beispiel #11
0
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)
}
Beispiel #12
0
// TestSets validates the ability to manually set configuration values.
func TestSets(t *testing.T) {
	t.Log("Given the need to manually set configuration values.")
	{
		/*
					uStr := "postgres://*****:*****@127.0.0.1:8080/postgres?sslmode=disable"
			Map: map[string]string{
							"PROC_ID": "322",
							"SOCKET":  "./tmp/sockets.po",
							"PORT":    "4034",
							"FLAG":    "on",
							"DSN":     uStr,
						},
		*/

		cfg.Init(cfg.MapProvider{
			Map: map[string]string{},
		})

		t.Log("\tWhen setting values.")
		{
			key := "key1"
			strVal := "bill"
			cfg.SetString(key, strVal)

			retStrVal, err := cfg.String(key)
			if err != nil {
				t.Errorf("\t\t%s Should find a value for the specified key %q.", failed, key)
			} else {
				t.Logf("\t\t%s Should find a value for the specified key %q.", success, key)
			}
			if strVal != retStrVal {
				t.Log(strVal)
				t.Log(retStrVal)
				t.Errorf("\t\t%s Should return the string value %q that was set.", failed, strVal)
			} else {
				t.Logf("\t\t%s Should return the string value %q that was set.", success, strVal)
			}

			key = "key2"
			intVal := 223
			cfg.SetInt(key, intVal)

			retIntVal, err := cfg.Int(key)
			if err != nil {
				t.Errorf("\t\t%s Should find a value for the specified key %q.", failed, key)
			} else {
				t.Logf("\t\t%s Should find a value for the specified key %q.", success, key)
			}
			if intVal != retIntVal {
				t.Log(intVal)
				t.Log(retIntVal)
				t.Errorf("\t\t%s Should return the int value %d that was set.", failed, intVal)
			} else {
				t.Logf("\t\t%s Should return the int value %d that was set.", success, intVal)
			}

			key = "key3"
			timeVal, _ := time.Parse(time.UnixDate, "Mon Oct 27 20:18:15 EST 2016")
			cfg.SetTime(key, timeVal)

			retTimeVal, err := cfg.Time(key)
			if err != nil {
				t.Errorf("\t\t%s Should find a value for the specified key %q.", failed, key)
			} else {
				t.Logf("\t\t%s Should find a value for the specified key %q.", success, key)
			}
			if timeVal != retTimeVal {
				t.Log(timeVal)
				t.Log(retTimeVal)
				t.Errorf("\t\t%s Should return the time value %q that was set.", failed, timeVal)
			} else {
				t.Logf("\t\t%s Should return the time value %q that was set.", success, timeVal)
			}

			key = "key4"
			boolVal := true
			cfg.SetBool(key, boolVal)

			retBoolVal, err := cfg.Bool(key)
			if err != nil {
				t.Errorf("\t\t%s Should find a value for the specified key %q.", failed, key)
			} else {
				t.Logf("\t\t%s Should find a value for the specified key %q.", success, key)
			}
			if boolVal != retBoolVal {
				t.Log(boolVal)
				t.Log(retBoolVal)
				t.Errorf("\t\t%s Should return the bool value \"%v\" that was set.", failed, boolVal)
			} else {
				t.Logf("\t\t%s Should return the bool value \"%v\" that was set.", success, boolVal)
			}

			key = "key5"
			urlVal, _ := url.Parse("postgres://*****:*****@127.0.0.1:8080/postgres?sslmode=disable")
			cfg.SetURL(key, urlVal)

			retURLVal, err := cfg.URL(key)
			if err != nil {
				t.Errorf("\t\t%s Should find a value for the specified key %q.", failed, key)
			} else {
				t.Logf("\t\t%s Should find a value for the specified key %q.", success, key)
			}
			if urlVal.String() != retURLVal.String() {
				t.Log(urlVal)
				t.Log(retURLVal)
				t.Errorf("\t\t%s Should return the bool value \"%v\" that was set.", failed, urlVal)
			} else {
				t.Logf("\t\t%s Should return the bool value \"%v\" that was set.", success, urlVal)
			}
		}
	}
}