Skip to content

bradialabs/stack

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

8 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Stack

Stack is a collection of middleware, handlers, and models that help facilitate the creation of golang web services.

Dependencies

User Model

The User model is a simple struct for working with and storing users in MongoDB. It has the following structure:

type User struct {
	ID        string      `json:"id" bson:"_id,omitempty"`
	Email     string      `json:"email"`
	Password  string      `json:"-"`
	Created   time.Time   `json:"created"`
	FirstName string      `json:"first"`
	LastName  string      `json:"last"`
	Data      interface{} `json:"data"`
}

The Data property is provided for custom data that your application will store with the user. You can store any struct and it will be stored as an embedded document in MongoDB.

Functions

NewUser

NewUser creates a new User and saves it in the database

func NewUser(email string, pass string,
  firstName string, lastName string, db *mgo.Database) (*User, error)

FindUserByID

FindUserByID searches for an existing user with the passed ID

func FindUserByID(id string, db *mgo.Database) (*User, error)

FindUserByEmail

FindUserByEmail searches for an existing user with the passed Email

func FindUserByEmail(email string, db *mgo.Database) (*User, error)

Save

Save Upserts the user into the database

func (user *User) Save(db *mgo.Database) error

CheckPassword

CheckPassword will check a passed password string with the stored hash

func (user *User) CheckPassword(password string) error

Middleware

The middleware now uses the built in context functionality of go. It sets values on the request context. This allows the middleware to maintain the original handler interface.

MongoMiddleware

Creates a connection to MongoDB using the mgo library.

BasicMiddleware

Adds basic authentication to routes. Uses the User model. The route also needs to use the MongoMiddleware.

JwtAuthMiddleware

Adds JWT Bearer Authentication to routes. Uses the User model. The route also needs to use the MongoMiddleware. In order to use JWT you must set the secret key using the stack.SetJwtSecret([]byte) function.

Handlers

SignUpHandler

Handler for signing up new users from a Post request. The body of the request must have the following JSON format.

{
  first:"First Name"
  last:"Last Name"
  email:"[email protected]"
  pass:"pa$$word"
}

The handler will return JSON data back to the caller indicating success

{
  "result":"success"
}

SignInHandler

Handler for signing in users. This handler requires the BasicMiddleware and MongoMiddleware. It will verify the email and password sent via basic auth and return a signed, base64 encoded JWT token.

{
  "token":"aksdfkjasdf.ajksdfkajsldf.akjlsdfhajklsdf"
}

Context

This library uses the net.Context package for passing data through middleware to the handlers. There are a few helper functions provided for getting information out of the context.

GetDb

GetDb grabs the mgo database from the context

func GetDb(ctx context.Context) *mgo.Database

GetUser

GetUser grabs the current user from the context

func GetUser(ctx context.Context) *User

Example

Here is an example of how to use stack with the Chi router.

package main

import (
	"io/ioutil"
	"net/http"
	"encoding/json"
	"log"

	"github.com/bradialabs/stack"
	"github.com/pressly/chi"
	"github.com/pressly/chi/middleware"
	"golang.org/x/net/context"
	"gopkg.in/mgo.v2/bson"
)

type UserData struct {
	Stuff string
}

func main() {
	stack.SetJwtSecret([]byte("secret"))

	r := chi.NewRouter()

	r.Use(middleware.Logger)

	r.Post("/api/1/signup", SignupRouter())
	r.Mount("/api/1", ApiRouter())
	r.Mount("/api/1/login", LoginRouter())

	http.ListenAndServe(":3333", r)
}

func SignupRouter() chi.Router {
	r := chi.NewRouter()

	r.Use(stack.MongoMiddleware)

	r.Get("/", stack.SignUpHandler)
	return r
}

func LoginRouter() chi.Router {
	r := chi.NewRouter()

	r.Use(stack.MongoMiddleware)
	r.Use(stack.BasicMiddleware)

	r.Get("/", stack.SignInHandler)
	return r
}

func ApiRouter() chi.Router {
	r := chi.NewRouter()

	r.Use(stack.MongoMiddleware("chitest", ""))
	r.Use(stack.JwtAuthMiddleware)

	r.Get("/me", func(w http.ResponseWriter, r *http.Request) {
		user := stack.GetUser(r.Context())
		j, er := json.Marshal(&user)
		if er != nil {
			log.Fatal(er)
		}
		w.Write(j)
	})

	r.Put("/me", func(w http.ResponseWriter, r *http.Request) {
		db := stack.GetDb(r.Context())
		user := stack.GetUser(r.Context())

		body, err := ioutil.ReadAll(r.Body)
		if err != nil {
			http.Error(w, err.Error(), 400)
			return
		}

		userData := UserData{}
		err = json.Unmarshal(body, &userData)
		if err != nil {
			http.Error(w, err.Error(), 400)
			return
		}
		user.Data = userData
		user.Save(db)

		j, er := json.Marshal(&user)
		if er != nil {
			log.Fatal(er)
		}
		w.Write(j)
	})

	return r
}

About

A collection of middleware and handlers for Go web apps

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages