Skip to content

Commit ad4f82b

Browse files
committed
Add repository methods for dealing with API keys
1 parent f24a32a commit ad4f82b

22 files changed

+296
-60
lines changed

api/pkg/di/config.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package di
22

33
import (
44
"log"
5+
"os"
56

67
"github.com/joho/godotenv"
78
)
@@ -13,3 +14,12 @@ func LoadEnv(filenames ...string) {
1314
log.Fatalf("Fatal: cannot load .env file: %v", err)
1415
}
1516
}
17+
18+
func getEnvWithDefault(key, defaultValue string) string {
19+
value := os.Getenv(key)
20+
if value == "" {
21+
return defaultValue
22+
}
23+
24+
return value
25+
}

api/pkg/di/container.go

Lines changed: 9 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -153,15 +153,6 @@ func NewContainer(projectID string, version string) (container *Container) {
153153
return container
154154
}
155155

156-
func GetEnvWithDefault(key, defaultValue string) string {
157-
value := os.Getenv(key)
158-
if value == "" {
159-
return defaultValue
160-
}
161-
162-
return value
163-
}
164-
165156
// App creates a new instance of fiber.App
166157
func (container *Container) App() (app *fiber.App) {
167158
if container.app != nil {
@@ -179,15 +170,14 @@ func (container *Container) App() (app *fiber.App) {
179170
app.Use(otelfiber.Middleware())
180171
app.Use(cors.New(
181172
cors.Config{
182-
AllowOrigins: GetEnvWithDefault("CORS_ALLOW_ORIGINS", "*"),
183-
AllowHeaders: GetEnvWithDefault("CORS_ALLOW_HEADERS", "*"),
184-
AllowMethods: GetEnvWithDefault("CORS_ALLOW_METHODS", "GET,POST,PUT,DELETE,OPTIONS"),
173+
AllowOrigins: getEnvWithDefault("CORS_ALLOW_ORIGINS", "*"),
174+
AllowHeaders: getEnvWithDefault("CORS_ALLOW_HEADERS", "*"),
175+
AllowMethods: getEnvWithDefault("CORS_ALLOW_METHODS", "GET,POST,PUT,DELETE,OPTIONS"),
185176
AllowCredentials: false,
186-
ExposeHeaders: GetEnvWithDefault("CORS_EXPOSE_HEADERS", "*"),
187-
}))
188-
177+
ExposeHeaders: getEnvWithDefault("CORS_EXPOSE_HEADERS", "*"),
178+
}),
179+
)
189180
app.Use(middlewares.HTTPRequestLogger(container.Tracer(), container.Logger()))
190-
191181
app.Use(middlewares.BearerAuth(container.Logger(), container.Tracer(), container.FirebaseAuthClient()))
192182
app.Use(middlewares.APIKeyAuth(container.Logger(), container.Tracer(), container.UserRepository()))
193183

@@ -1396,10 +1386,10 @@ func (container *Container) UserRepository() repositories.UserRepository {
13961386
)
13971387
}
13981388

1399-
// UserRistrettoCache creates an in-memory *ristretto.Cache[string, entities.AuthUser]
1400-
func (container *Container) UserRistrettoCache() (cache *ristretto.Cache[string, entities.AuthUser]) {
1389+
// UserRistrettoCache creates an in-memory *ristretto.Cache[string, entities.AuthContext]
1390+
func (container *Container) UserRistrettoCache() (cache *ristretto.Cache[string, entities.AuthContext]) {
14011391
container.logger.Debug(fmt.Sprintf("creating %T", cache))
1402-
ristrettoCache, err := ristretto.NewCache[string, entities.AuthUser](&ristretto.Config[string, entities.AuthUser]{
1392+
ristrettoCache, err := ristretto.NewCache[string, entities.AuthContext](&ristretto.Config[string, entities.AuthContext]{
14031393
MaxCost: 5000,
14041394
NumCounters: 5000 * 10,
14051395
BufferItems: 64,

api/pkg/entities/auth_context.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
package entities
2+
3+
import "github.com/google/uuid"
4+
5+
// AuthContext is the user gotten from an auth request
6+
type AuthContext struct {
7+
ID UserID `json:"id"`
8+
PhoneAPIKeyID *uuid.UUID `json:"phone_api_key_id"`
9+
PhoneNumbers []string `json:"phone_numbers"`
10+
Email string `json:"email"`
11+
}
12+
13+
// IsNoop checks if a user is empty
14+
func (user AuthContext) IsNoop() bool {
15+
return user.ID == "" || user.Email == ""
16+
}

api/pkg/entities/auth_user.go

Lines changed: 0 additions & 12 deletions
This file was deleted.

api/pkg/entities/phone_api_key.go

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
package entities
2+
3+
import (
4+
"time"
5+
6+
"github.com/google/uuid"
7+
"github.com/lib/pq"
8+
)
9+
10+
// PhoneAPIKey represents the API key for a phone
11+
type PhoneAPIKey struct {
12+
ID uuid.UUID `json:"id" gorm:"primaryKey;type:uuid;" example:"32343a19-da5e-4b1b-a767-3298a73703cb"`
13+
Name string `json:"name" example:"Business Phone Key"`
14+
UserID UserID `json:"user_id" example:"WB7DRDWrJZRGbYrv2CKGkqbzvqdC"`
15+
UserEmail string `json:"user_email" example:"[email protected]"`
16+
PhoneNumbers pq.StringArray `json:"phone_numbers" example:"[+18005550199,+18005550100]" gorm:"type:text[]" swaggertype:"array,string"`
17+
PhoneIDs pq.StringArray `json:"phone_ids" example:"[32343a19-da5e-4b1b-a767-3298a73703cb,32343a19-da5e-4b1b-a767-3298a73703cc]" gorm:"type:text[]" swaggertype:"array,string"`
18+
APIKey string `json:"api_key" example:"pk_DGW8NwQp7mxKaSZ72Xq9v67SLqSbWQvckzzmK8D6rvd7NywSEkdMJtuxKyEkYnCY"`
19+
CreatedAt time.Time `json:"created_at" example:"2022-06-05T14:26:02.302718+03:00"`
20+
UpdatedAt time.Time `json:"updated_at" example:"2022-06-05T14:26:02.302718+03:00"`
21+
}
22+
23+
// TableName overrides the table name used by PhoneAPIKey
24+
func (PhoneAPIKey) TableName() string {
25+
return "phone_api_keys"
26+
}

api/pkg/handlers/handler.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -101,8 +101,8 @@ func (h *handler) pluralize(value string, count int) string {
101101
return value + "s"
102102
}
103103

104-
func (h *handler) userFromContext(c *fiber.Ctx) entities.AuthUser {
105-
if tokenUser, ok := c.Locals(middlewares.ContextKeyAuthUserID).(entities.AuthUser); ok && !tokenUser.IsNoop() {
104+
func (h *handler) userFromContext(c *fiber.Ctx) entities.AuthContext {
105+
if tokenUser, ok := c.Locals(middlewares.ContextKeyAuthUserID).(entities.AuthContext); ok && !tokenUser.IsNoop() {
106106
return tokenUser
107107
}
108108
panic("user does not exist in context.")

api/pkg/middlewares/api_key_auth_middleware.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ func APIKeyAuth(logger telemetry.Logger, tracer telemetry.Tracer, userRepository
2525
return c.Next()
2626
}
2727

28-
authUser, err := userRepository.LoadAuthUser(ctx, apiKey)
28+
authUser, err := userRepository.LoadAuthContext(ctx, apiKey)
2929
if err != nil {
3030
ctxLogger.Error(stacktrace.Propagate(err, fmt.Sprintf("cannot load user with api key [%s]", apiKey)))
3131
return c.Next()

api/pkg/middlewares/authenticated_middlesare.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ func Authenticated(tracer telemetry.Tracer) fiber.Handler {
2323
_, span := tracer.StartFromFiberCtx(c, "middlewares.Authenticated")
2424
defer span.End()
2525

26-
if tokenUser, ok := c.Locals(ContextKeyAuthUserID).(entities.AuthUser); !ok || tokenUser.IsNoop() {
26+
if tokenUser, ok := c.Locals(ContextKeyAuthUserID).(entities.AuthContext); !ok || tokenUser.IsNoop() {
2727
return c.Status(fiber.StatusUnauthorized).JSON(fiber.Map{
2828
"status": "error",
2929
"message": "You are not authorized to carry out this request.",

api/pkg/middlewares/bearer_api_key_auth_middleware.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ func BearerAPIKeyAuth(logger telemetry.Logger, tracer telemetry.Tracer, userRepo
2626
return c.Next()
2727
}
2828

29-
authUser, err := userRepository.LoadAuthUser(ctx, apiKey)
29+
authUser, err := userRepository.LoadAuthContext(ctx, apiKey)
3030
if err != nil {
3131
ctxLogger.Error(stacktrace.Propagate(err, fmt.Sprintf("cannot load user with api key [%s] using header [%s]", apiKey, c.Get(authHeaderBearer))))
3232
return c.Next()

api/pkg/middlewares/bearer_auth_middleware.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ func BearerAuth(logger telemetry.Logger, tracer telemetry.Tracer, authClient *au
4040

4141
span.AddEvent(fmt.Sprintf("[%s] token is valid", bearerScheme))
4242

43-
authUser := entities.AuthUser{
43+
authUser := entities.AuthContext{
4444
Email: token.Claims["email"].(string),
4545
ID: entities.UserID(token.Claims["user_id"].(string)),
4646
}

0 commit comments

Comments
 (0)