The codebase that powers boop.cat boop.cat
11
fork

Configure Feed

Select the types of activity you want to include in your feed.

at main 72 lines 1.8 kB view raw
1// Copyright 2025 boop.cat 2// Licensed under the Apache License, Version 2.0 3// See LICENSE file for details. 4 5package middleware 6 7import ( 8 "context" 9 "database/sql" 10 "net/http" 11 "strings" 12 13 "boop-cat/db" 14) 15 16type ContextKey string 17 18const ( 19 UserContextKey ContextKey = "user" 20 21 APIKeyIDContextKey ContextKey = "apiKeyId" 22) 23 24func RequireAPIKey(database *sql.DB) func(http.Handler) http.Handler { 25 return func(next http.Handler) http.Handler { 26 return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 27 authHeader := r.Header.Get("Authorization") 28 if !strings.HasPrefix(authHeader, "Bearer ") { 29 http.Error(w, `{"error":"missing-api-key","message":"Authorization header with Bearer token required"}`, http.StatusUnauthorized) 30 return 31 } 32 33 key := strings.TrimPrefix(authHeader, "Bearer ") 34 if !strings.HasPrefix(key, "sk_") { 35 http.Error(w, `{"error":"invalid-api-key","message":"Invalid or expired API key"}`, http.StatusUnauthorized) 36 return 37 } 38 39 user, keyID, err := db.ValidateAPIKey(database, key) 40 if err != nil { 41 http.Error(w, `{"error":"invalid-api-key","message":"Invalid or expired API key"}`, http.StatusUnauthorized) 42 return 43 } 44 45 ctx := context.WithValue(r.Context(), UserContextKey, user) 46 ctx = context.WithValue(ctx, APIKeyIDContextKey, keyID) 47 next.ServeHTTP(w, r.WithContext(ctx)) 48 }) 49 } 50} 51 52func GetUser(ctx context.Context) *db.User { 53 if user, ok := ctx.Value(UserContextKey).(*db.User); ok { 54 return user 55 } 56 return nil 57} 58 59func GetAPIKeyID(ctx context.Context) string { 60 if keyID, ok := ctx.Value(APIKeyIDContextKey).(string); ok { 61 return keyID 62 } 63 return "" 64} 65 66func GetUserID(ctx context.Context) string { 67 user := GetUser(ctx) 68 if user != nil { 69 return user.ID 70 } 71 return "" 72}