add API boilerplate + /accounts/{accountID} and /accounts/@me endpoints

This commit is contained in:
sam 2023-09-06 02:23:06 +02:00
parent 0fa769a248
commit dfc116d828
Signed by: sam
GPG key ID: B4EF20DDE721CAA1
7 changed files with 335 additions and 0 deletions

View file

@ -3,9 +3,12 @@ package app
import (
"context"
"net/http"
"strings"
"time"
"git.sleepycat.moe/sam/mercury/internal/database"
"git.sleepycat.moe/sam/mercury/web/api"
"github.com/go-chi/render"
)
type ctxKey int
@ -42,6 +45,62 @@ func (app *App) FrontendAuth(next http.Handler) http.Handler {
return http.HandlerFunc(fn)
}
func (app *App) APIAuth(scope database.TokenScope, anonAccess bool) func(next http.Handler) http.Handler {
return func(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
header := strings.TrimPrefix(r.Header.Get("Authorization"), "Bearer ")
if header == "" {
cookie, err := r.Cookie(database.TokenCookieName)
if err != nil || cookie.Value == "" {
if anonAccess { // no token supplied, but the endpoint allows anonymous access
next.ServeHTTP(w, r)
return
}
render.Status(r, api.ErrCodeStatus(api.ErrInvalidToken))
render.JSON(w, r, api.Error{
Code: api.ErrInvalidToken,
Message: api.ErrCodeMessage(api.ErrInvalidToken),
})
return
}
}
token, err := app.ParseToken(r.Context(), header)
if err != nil {
render.Status(r, api.ErrCodeStatus(api.ErrInvalidToken))
render.JSON(w, r, api.Error{
Code: api.ErrInvalidToken,
Message: api.ErrCodeMessage(api.ErrInvalidToken),
})
return
}
if token.Expires.Before(time.Now()) {
render.Status(r, api.ErrCodeStatus(api.ErrInvalidToken))
render.JSON(w, r, api.Error{
Code: api.ErrInvalidToken,
Message: api.ErrCodeMessage(api.ErrInvalidToken),
})
return
}
if !token.Scopes.Has(scope) {
render.Status(r, api.ErrCodeStatus(api.ErrMissingScope))
render.JSON(w, r, api.Error{
Code: api.ErrMissingScope,
Message: api.ErrCodeMessage(api.ErrMissingScope),
})
return
}
ctx := context.WithValue(r.Context(), ctxKeyClaims, token)
next.ServeHTTP(w, r.WithContext(ctx))
})
}
}
func (app *App) TokenFromContext(ctx context.Context) (database.Token, bool) {
v := ctx.Value(ctxKeyClaims)
if v == nil {