Loads of updates

This commit is contained in:
2021-06-22 22:52:48 +02:00
parent 8dc20a4eb0
commit ccafd60923
18 changed files with 1206 additions and 125 deletions

View File

@@ -4,12 +4,19 @@ import (
"github.com/gofiber/fiber/v2"
)
// Hello handler
func (h Handlers) Hello(c *fiber.Ctx) error {
return c.SendString("Hello, World!")
}
// AccountGet handler
// AccountGet godoc
// @Summary Get account
// @Description Get account
// @ID get-account-by-id
// @Accept json
// @Produce json
// @Param id path string true "Account ID"
// @Success 200 {object} db.Account
// @Failure 401 {object} ResJSONError
// @Failure 403 {object} ResJSONError
// @Failure 415 {object} ResJSONError
// @Failure 500 {object} ResJSONError
// @Router /account/{id} [get]
func (h Handlers) AccountGet(c *fiber.Ctx) error {
accountID := c.Params("accountID")
// logContext := log.WithFields(log.Fields{"accountID": accountID})

View File

@@ -7,7 +7,6 @@ import (
jwt "github.com/dgrijalva/jwt-go"
"github.com/gofiber/fiber/v2"
log "github.com/sirupsen/logrus"
"gitlab.larvit.se/power-plan/auth/src/db"
)
@@ -26,13 +25,13 @@ func (h Handlers) returnTokens(account db.Account, c *fiber.Ctx) error {
token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
tokenString, err := token.SignedString(h.JwtKey)
if err != nil {
log.Error("Could not create token string, err: " + err.Error())
h.Log.Error("Could not create token string", "err", err.Error())
return c.Status(500).JSON([]ResJSONError{{Error: "Could not create JWT token string"}})
}
renewalToken, renewalTokenErr := h.Db.RenewalTokenCreate(account.ID.String())
if renewalTokenErr != nil {
log.Error("Could not create renewal token, err: " + renewalTokenErr.Error())
h.Log.Error("Could not create renewal token", "err", renewalTokenErr.Error())
return c.Status(500).JSON([]ResJSONError{{Error: "Could not create renewal token"}})
}
@@ -43,15 +42,14 @@ func (h Handlers) returnTokens(account db.Account, c *fiber.Ctx) error {
}
func (h Handlers) parseJWT(JWT string) (Claims, error) {
logContext := log.WithFields(log.Fields{"JWT": JWT})
logContext.Trace("Parsing JWT")
h.Log.Debug("Parsing JWT", "JWT", JWT)
JWT = strings.TrimPrefix(JWT, "bearer ") // Since the Authorization header should always start with "bearer "
logContext.WithFields(log.Fields{"TrimmedJWT": JWT}).Trace("JWT trimmed")
trimmedJWT := strings.TrimPrefix(JWT, "bearer ") // Since the Authorization header should always start with "bearer "
h.Log.Debug("JWT trimmed", "JWT", JWT, "trimmedJWT", trimmedJWT)
claims := &Claims{}
token, err := jwt.ParseWithClaims(JWT, claims, func(token *jwt.Token) (interface{}, error) {
token, err := jwt.ParseWithClaims(trimmedJWT, claims, func(token *jwt.Token) (interface{}, error) {
return h.JwtKey, nil
})
if err != nil {
@@ -75,7 +73,7 @@ func (h Handlers) parseHeaders(c *fiber.Ctx) map[string]string {
lineParts := strings.Split(line, ": ")
if len(lineParts) == 1 {
log.WithFields(log.Fields{"line": line}).Trace("Ignoring header line")
h.Log.Debug("Ignoring header line", "line", line)
} else {
headersMap[lineParts[0]] = lineParts[1]
}

View File

@@ -2,15 +2,11 @@ package handlers
import (
"github.com/gofiber/fiber/v2"
log "github.com/sirupsen/logrus"
)
// Log all requests
func (h Handlers) Log(c *fiber.Ctx) error {
log.WithFields(log.Fields{
"method": c.Method(),
"url": c.OriginalURL(),
}).Debug("http request")
func (h Handlers) LogReq(c *fiber.Ctx) error {
h.Log.Debug("http request", "method", c.Method(), "url", c.OriginalURL())
c.Next()
return nil
@@ -22,7 +18,7 @@ func (h Handlers) RequireJSON(c *fiber.Ctx) error {
contentType := string(c.Request().Header.ContentType())
if contentType != "application/json" && contentType != "" {
log.WithFields(log.Fields{"content-type": contentType}).Debug("Invalid content-type in request")
h.Log.Debug("Invalid content-type in request", "content-type", contentType)
return c.Status(415).JSON([]ResJSONError{{Error: "Invalid content-type"}})
}

View File

@@ -3,15 +3,24 @@ package handlers
import (
"strings"
log "github.com/sirupsen/logrus"
"github.com/gofiber/fiber/v2"
"github.com/google/uuid"
"gitlab.larvit.se/power-plan/auth/src/db"
"gitlab.larvit.se/power-plan/auth/src/utils"
)
// AccountCreate creates a new account
// AccountCreate godoc
// @Summary Create an account
// @Description Create an account
// @ID account-create
// @Accept json
// @Produce json
// @Success 200 {object} db.CreatedAccount
// @Failure 401 {object} ResJSONError
// @Failure 403 {object} ResJSONError
// @Failure 415 {object} ResJSONError
// @Failure 500 {object} ResJSONError
// @Router /account [post]
func (h Handlers) AccountCreate(c *fiber.Ctx) error {
authErr := h.RequireAdminRole(c)
if authErr != nil {
@@ -44,12 +53,12 @@ func (h Handlers) AccountCreate(c *fiber.Ctx) error {
newAccountID, uuidErr := uuid.NewRandom()
if uuidErr != nil {
log.Fatal("Could not create new Uuid, err: " + uuidErr.Error())
h.Log.Fatal("Could not create new Uuid", "err", uuidErr.Error())
}
hashedPwd, pwdErr := utils.HashPassword(accountInput.Password)
if pwdErr != nil {
log.Fatal("Could not hash password, err: " + pwdErr.Error())
h.Log.Fatal("Could not hash password", "err", pwdErr.Error())
}
createdAccount, err := h.Db.AccountCreate(db.AccountCreateInput{
@@ -70,7 +79,18 @@ func (h Handlers) AccountCreate(c *fiber.Ctx) error {
return c.Status(201).JSON(createdAccount)
}
// AccountAuthAPIKey auths an APIKey
// AccountAuthAPIKey godoc
// @Summary Authenticate account by API Key
// @Description Authenticate account by API Key
// @ID auth-account-by-api-key
// @Accept json
// @Produce json
// @Success 200 {object} db.Account
// @Failure 401 {object} ResJSONError
// @Failure 403 {object} ResJSONError
// @Failure 415 {object} ResJSONError
// @Failure 500 {object} ResJSONError
// @Router /auth/api-key [post]
func (h Handlers) AccountAuthAPIKey(c *fiber.Ctx) error {
inputAPIKey := string(c.Request().Body())
inputAPIKey = inputAPIKey[1 : len(inputAPIKey)-1]
@@ -80,14 +100,25 @@ func (h Handlers) AccountAuthAPIKey(c *fiber.Ctx) error {
if accountErr.Error() == "no rows in result set" {
return c.Status(403).JSON([]ResJSONError{{Error: "Invalid credentials"}})
}
log.Error("Something went wrong when trying to fetch account")
h.Log.Error("Something went wrong when trying to fetch account", "err", accountErr.Error())
return c.Status(500).JSON([]ResJSONError{{Error: "Something went wrong when trying to fetch account"}})
}
return h.returnTokens(resolvedAccount, c)
}
// AccountAuthPassword auths a name/password pair
// AccountAuthPassword godoc
// @Summary Authenticate account by Password
// @Description Authenticate account by Password
// @ID auth-account-by-password
// @Accept json
// @Produce json
// @Success 200 {object} db.Account
// @Failure 401 {object} ResJSONError
// @Failure 403 {object} ResJSONError
// @Failure 415 {object} ResJSONError
// @Failure 500 {object} ResJSONError
// @Router /auth/password [post]
func (h Handlers) AccountAuthPassword(c *fiber.Ctx) error {
type AuthInput struct {
Name string `json:"name"`
@@ -115,8 +146,19 @@ func (h Handlers) AccountAuthPassword(c *fiber.Ctx) error {
return h.returnTokens(resolvedAccount, c)
}
// TokenRenew creates a new renewal token and JWT from an old renewal token
func (h Handlers) TokenRenew(c *fiber.Ctx) error {
// RenewToken godoc
// @Summary Renew token
// @Description Renew token
// @ID renew-token
// @Accept json
// @Produce json
// @Success 200 {object} db.Account
// @Failure 401 {object} ResJSONError
// @Failure 403 {object} ResJSONError
// @Failure 415 {object} ResJSONError
// @Failure 500 {object} ResJSONError
// @Router /renew-token [post]
func (h Handlers) RenewToken(c *fiber.Ctx) error {
inputToken := string(c.Request().Body())
inputToken = inputToken[1 : len(inputToken)-1]
@@ -132,13 +174,14 @@ func (h Handlers) TokenRenew(c *fiber.Ctx) error {
if accountErr.Error() == "no rows in result set" {
return c.Status(500).JSON([]ResJSONError{{Error: "Database missmatch. Token found, but account is missing."}})
}
log.Error("Something went wrong when trying to fetch account")
h.Log.Error("Something went wrong when trying to fetch account", "err", accountErr.Error())
return c.Status(500).JSON([]ResJSONError{{Error: "Something went wrong when trying to fetch account"}})
}
rmErr := h.Db.RenewalTokenRm(inputToken)
if rmErr != nil {
return c.Status(500).JSON([]ResJSONError{{Error: "Could not remove old token, err: " + rmErr.Error()}})
h.Log.Error("Something went wrong when trying to fetch account", "err", rmErr.Error())
return c.Status(500).JSON([]ResJSONError{{Error: "Could not remove old token"}})
}
return h.returnTokens(resolvedAccount, c)

View File

@@ -3,6 +3,7 @@ package handlers
import (
jwt "github.com/dgrijalva/jwt-go"
"gitlab.larvit.se/power-plan/auth/src/db"
"go.uber.org/zap"
)
// Claims is the JWT struct
@@ -17,6 +18,7 @@ type Claims struct {
type Handlers struct {
Db db.Db
JwtKey []byte
Log *zap.SugaredLogger
}
// ResJSONError is an error field that is used in JSON error responses