first commit
This commit is contained in:
@@ -0,0 +1,71 @@
|
||||
package auth
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/gissleh/stufflog/internal/slerrors"
|
||||
"net/http"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var contextKey = struct{}{}
|
||||
|
||||
func UserID(ctx context.Context) string {
|
||||
if c, ok := ctx.(*gin.Context); ok {
|
||||
return UserID(c.Request.Context())
|
||||
}
|
||||
|
||||
return ctx.Value(&contextKey).(string)
|
||||
}
|
||||
|
||||
func DummyMiddleware(uuid string) gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
c.Request = c.Request.WithContext(
|
||||
context.WithValue(c.Request.Context(), &contextKey, uuid),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
func abortRequest(c *gin.Context) {
|
||||
c.AbortWithStatusJSON(http.StatusUnauthorized, slerrors.ErrorResponse{
|
||||
Code: http.StatusUnauthorized,
|
||||
Message: "You're not supposed to be here!",
|
||||
})
|
||||
}
|
||||
|
||||
// TrustingJwtParserMiddleware is meant to be put behind an AWS API gateway that has already
|
||||
// verified this token.
|
||||
func TrustingJwtParserMiddleware() gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
auth := c.GetHeader("Authorization")
|
||||
split := strings.Split(auth, ".")
|
||||
|
||||
if len(split) >= 3 {
|
||||
data, err := base64.RawStdEncoding.DecodeString(split[1])
|
||||
if err != nil {
|
||||
abortRequest(c)
|
||||
return
|
||||
}
|
||||
|
||||
fields := make(map[string]interface{})
|
||||
err = json.Unmarshal(data, &fields)
|
||||
if err != nil {
|
||||
abortRequest(c)
|
||||
return
|
||||
}
|
||||
|
||||
if sub, ok := fields["sub"].(string); ok {
|
||||
c.Request = c.Request.WithContext(
|
||||
context.WithValue(c.Request.Context(), &contextKey, sub),
|
||||
)
|
||||
} else {
|
||||
abortRequest(c)
|
||||
return
|
||||
}
|
||||
} else {
|
||||
abortRequest(c)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
package generate
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"encoding/hex"
|
||||
"log"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func id(prefix string, length int) string {
|
||||
var id [16]byte
|
||||
var buffer [32]byte
|
||||
builder := strings.Builder{}
|
||||
builder.Grow(length + 31)
|
||||
builder.WriteString(prefix)
|
||||
|
||||
for builder.Len() < length {
|
||||
_, err := rand.Read(id[:])
|
||||
if err != nil {
|
||||
log.Panicln("generate.id: failed to use OS random:", err)
|
||||
}
|
||||
|
||||
hex.Encode(buffer[:], id[:])
|
||||
builder.Write(buffer[:])
|
||||
}
|
||||
|
||||
return builder.String()[:length]
|
||||
}
|
||||
|
||||
func GroupID() string {
|
||||
return id("G", 16)
|
||||
}
|
||||
|
||||
func ItemID() string {
|
||||
return id("I", 16)
|
||||
}
|
||||
|
||||
func ProjectID() string {
|
||||
return id("P", 16)
|
||||
}
|
||||
|
||||
func TaskID() string {
|
||||
return id("T", 16)
|
||||
}
|
||||
|
||||
func LogID() string {
|
||||
return id("L", 16)
|
||||
}
|
||||
|
||||
func GoalID() string {
|
||||
return id("A", 16)
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package slerrors
|
||||
|
||||
type badRequestError struct {
|
||||
Text string
|
||||
}
|
||||
|
||||
func (err *badRequestError) Error() string {
|
||||
return "validation failed: " + err.Text
|
||||
}
|
||||
|
||||
func BadRequest(text string) error {
|
||||
return &badRequestError{Text: text}
|
||||
}
|
||||
|
||||
func IsBadRequest(err error) bool {
|
||||
_, ok := err.(*badRequestError)
|
||||
return ok
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package slerrors
|
||||
|
||||
type forbiddenError struct {
|
||||
Message string
|
||||
}
|
||||
|
||||
func (e *forbiddenError) Error() string {
|
||||
return e.Message
|
||||
}
|
||||
|
||||
func Forbidden(message string) error {
|
||||
return &forbiddenError{Message: message}
|
||||
}
|
||||
|
||||
func IsForbidden(err error) bool {
|
||||
if err == nil {
|
||||
return false
|
||||
}
|
||||
|
||||
_, ok := err.(*forbiddenError)
|
||||
return ok
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package slerrors
|
||||
|
||||
import (
|
||||
"github.com/gin-gonic/gin"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
type ErrorResponse struct {
|
||||
Code int `json:"errorCode"`
|
||||
Message string `json:"errorMessage"`
|
||||
}
|
||||
|
||||
func Respond(c *gin.Context, err error) {
|
||||
if IsNotFound(err) {
|
||||
c.JSON(http.StatusNotFound, ErrorResponse{
|
||||
Code: http.StatusNotFound,
|
||||
Message: err.Error(),
|
||||
})
|
||||
} else if IsForbidden(err) {
|
||||
c.JSON(http.StatusForbidden, ErrorResponse{
|
||||
Code: http.StatusForbidden,
|
||||
Message: err.Error(),
|
||||
})
|
||||
} else if IsBadRequest(err) {
|
||||
c.JSON(http.StatusBadRequest, ErrorResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
Message: err.Error(),
|
||||
})
|
||||
} else {
|
||||
c.JSON(http.StatusInternalServerError, ErrorResponse{
|
||||
Code: http.StatusInternalServerError,
|
||||
Message: err.Error(),
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package slerrors
|
||||
|
||||
type notFoundError struct {
|
||||
Subject string
|
||||
}
|
||||
|
||||
func (err *notFoundError) Error() string {
|
||||
return err.Subject + " not found"
|
||||
}
|
||||
|
||||
func NotFound(subject string) error {
|
||||
return ¬FoundError{Subject: subject}
|
||||
}
|
||||
|
||||
func IsNotFound(err error) bool {
|
||||
_, ok := err.(*notFoundError)
|
||||
return ok
|
||||
}
|
||||
Reference in New Issue
Block a user