api.go
1 package api 2 3 import ( 4 "encoding/base64" 5 "strings" 6 7 "context" 8 9 "github.com/gofiber/fiber/v2" 10 "github.com/gofiber/fiber/v2/middleware/cors" 11 "github.com/gofiber/fiber/v2/utils" 12 v1 "github.com/mrusme/journalist/api/v1" 13 "github.com/mrusme/journalist/ent" 14 "github.com/mrusme/journalist/ent/user" 15 "github.com/mrusme/journalist/lib" 16 ) 17 18 // @title Journalist API 19 // @version 1.0 20 // @description The Journalist REST API v1 21 22 // @contact.name Marius 23 // @contact.url https://xn--gckvb8fzb.com 24 // @contact.email marius@xn--gckvb8fzb.com 25 26 // @license.name GPL-3.0 27 // @license.url https://github.com/mrusme/journalist/blob/master/LICENSE 28 29 // @host localhost:8000 30 // @BasePath /api/v1 31 // @accept json 32 // @produce json 33 // @schemes http 34 // @securityDefinitions.basic BasicAuth 35 func Register( 36 jctx *lib.JournalistContext, 37 fiberApp *fiber.App, 38 ) { 39 api := fiberApp.Group("/api") 40 api.Use(cors.New()) 41 api.Use(authorizer(jctx.EntClient)) 42 43 v1.Register( 44 jctx, 45 &api, 46 ) 47 } 48 49 // TODO: Move to `middlewares` 50 func authorizer(entClient *ent.Client) fiber.Handler { 51 return func(ctx *fiber.Ctx) error { 52 auth := ctx.Get(fiber.HeaderAuthorization) 53 54 if len(auth) <= 6 || strings.ToLower(auth[:5]) != "basic" { 55 return ctx.SendStatus(fiber.StatusUnauthorized) 56 } 57 58 raw, err := base64.StdEncoding.DecodeString(auth[6:]) 59 if err != nil { 60 return ctx.SendStatus(fiber.StatusUnauthorized) 61 } 62 63 creds := utils.UnsafeString(raw) 64 65 index := strings.Index(creds, ":") 66 if index == -1 { 67 return ctx.SendStatus(fiber.StatusUnauthorized) 68 } 69 70 username := creds[:index] 71 password := creds[index+1:] 72 73 u, err := entClient.User. 74 Query(). 75 Where(user.Username(username)). 76 Only(context.Background()) 77 if err != nil { 78 return ctx.SendStatus(fiber.StatusUnauthorized) 79 } 80 81 if u.Password != password { 82 return ctx.SendStatus(fiber.StatusUnauthorized) 83 } 84 85 ctx.Locals("user_id", u.ID.String()) 86 ctx.Locals("username", u.Username) 87 // ctx.Locals("password", u.Password) 88 ctx.Locals("role", u.Role) 89 return ctx.Next() 90 } 91 }