yasshi2525/RushHour

View on GitHub
controllers/main.go

Summary

Maintainability
A
0 mins
Test Coverage
package controllers

import (
    "net/http"

    "github.com/gin-gonic/gin"
    "github.com/yasshi2525/RushHour/auth"
    "github.com/yasshi2525/RushHour/entities"
    "github.com/yasshi2525/RushHour/services"
)

var auther *auth.Auther

// keyErr is set when error occurs
const keyErr = "err"

// keyRedirect is set to redirect page
const keyRedirect = "redirect"

func abortByError(c *gin.Context, err error) {
    c.HTML(http.StatusServiceUnavailable, "error.tmpl", gin.H{"err": err.Error()})
}

// OAuthHandler handles redirect or error page
// It views error page when keyErr is set
// It redirects OAuth sites when keyRedirect is set
func OAuthHandler() gin.HandlerFunc {
    return func(c *gin.Context) {

        c.Next()

        if err, has := c.Get(keyErr); has {
            abortByError(c, err.(error))
        } else {
            c.Redirect(http.StatusFound, c.MustGet(keyRedirect).(string))
        }
    }
}

// CallbackFunc return auth information depending on each service
type CallbackFunc func(string, string) (*auth.OAuthInfo, error)

// keyAuthType is attribute name of entities.AuthType
const keyAuthType = "keyAuthType"

// KeyAuthFunc is attribute name of OAuthFunc
const keyAuthFunc = "keyAuthFunc"

// keyAuthInfo is arrtibute name of fetched data by OAuth
const keyAuthInfo = "keyAuthInfo"

// CallbackHandler parse state and code in order to sign in
func CallbackHandler() gin.HandlerFunc {
    return func(c *gin.Context) {

        c.Next()

        if err, has := c.Get(keyErr); has {
            abortByError(c, err.(error))
        } else {
            state := c.Query("state")
            code := c.Query("code")
            fn := c.MustGet(keyAuthFunc).(CallbackFunc)

            if info, err := fn(state, code); err != nil {
                abortByError(c, err)
            } else {
                c.Set(keyAuthInfo, info)
            }
        }
    }
}

// RegisterHandler sends back jwt token to client
// It should be called after CallbackHandler is called
func RegisterHandler() gin.HandlerFunc {
    return func(c *gin.Context) {

        c.Next()

        if err, has := c.Get(keyErr); has {
            abortByError(c, err.(error))
        } else {
            ty := c.MustGet(keyAuthType).(entities.AuthType)
            info := c.MustGet(keyAuthInfo).(*auth.OAuthInfo)

            if o, err := services.OAuthSignIn(ty, info); err != nil {
                abortByError(c, err)
            } else if token, err := auther.BuildJWT(o.ExportJWTInfo()); err != nil {
                abortByError(c, err)
            } else {
                c.HTML(http.StatusOK, "oauth.tmpl", gin.H{"jwt": token})
            }
        }
    }
}

// Index returns html containing under maintanance or not
func Index(c *gin.Context) {
    c.HTML(http.StatusOK, "index.tmpl", gin.H{"inOperation": services.IsInOperation()})
}

// InitController loads config
func InitController(a *auth.Auther) {
    auther = a
}