Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 0 additions & 14 deletions pkg/controllers/api-key/admin.go

This file was deleted.

14 changes: 0 additions & 14 deletions pkg/controllers/api-key/default.go

This file was deleted.

18 changes: 9 additions & 9 deletions pkg/controllers/api-key/generate.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,15 +33,15 @@ func Generate(c *gin.Context, deps dependencies.Dependencies) {

// Create an instance of the APIKey struct
apiKeyInstance := &models.APIKey{
ID: ID,
Usage: 0,
Limit: 1000,
CreatedAt: time.Now(),
ExpiresAt: time.Now().AddDate(0, 2, 1), // Example expires at time, two months and 1 day from now
LastUsed: time.Now(),
Active: true,
SubjectID: uuid,
Roles: []string{"default"},
ID: ID,
Usage: 0,
Limit: 1000,
CreatedAt: time.Now(),
ExpiresAt: time.Now().AddDate(0, 2, 1), // Example expires at time, two months and 1 day from now
LastUsed: time.Now(),
Active: true,
SubjectID: uuid,
PermissionLevel: 0,
}

// Store the APIKey in the database
Expand Down
51 changes: 51 additions & 0 deletions pkg/controllers/api-key/role/adjust.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package role

import (
"net/http"
"strconv"

"github.com/Frier03/KeyAuth-API/pkg/models"
"github.com/Frier03/KeyAuth-API/pkg/services"
"github.com/gin-gonic/gin"
)

func Adjust(c *gin.Context, badgerService *services.BadgerService) {
apiKey := c.GetHeader("X-Api-Key")
adjust, _ := c.GetQuery("permission_level")
apiKeyData, _ := c.Get("api-key-model")

// Apply model to apiKey
apiKeyModel, _ := apiKeyData.(models.APIKey)

// Validate adjust value
level, err := strconv.Atoi(adjust)
if err != nil {
c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{
"error": "Invalid adjust value",
})
return
}

// Check if level is within the allowed range
if level < int(models.Default) || level > int(models.Admin) {
c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{
"error": "Adjust value is out of range",
})
return
}

apiKeyModel.PermissionLevel = level

// Update the API key in the database
err = badgerService.PutAPIKey([]byte(apiKey), &apiKeyModel)
if err != nil {
c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{
"error": "Failed to update API key",
})
return
}

c.JSON(http.StatusOK, gin.H{
"message": "OK",
})
}
14 changes: 0 additions & 14 deletions pkg/controllers/api-key/standard.go

This file was deleted.

33 changes: 33 additions & 0 deletions pkg/middleware/api-key/role_access_control.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package middleware

import (
"net/http"

"github.com/Frier03/KeyAuth-API/pkg/models"
"github.com/gin-gonic/gin"
)

func RoleAccessControl(role models.Role) gin.HandlerFunc {
return func(c *gin.Context) {
apiKeyData, _ := c.Get("api-key-model")

// Apply model to apiKeyData
apiKeyModel, _ := apiKeyData.(models.APIKey)

// Get api key permission level
apiPermissionLevel := models.Role(apiKeyModel.PermissionLevel)

// Get requiredRole permission level
requiredPermissionLevel := role

// Check if APIPermissionLevel has less privileges than the required role
if apiPermissionLevel < requiredPermissionLevel {
c.AbortWithStatusJSON(http.StatusForbidden, gin.H{
"error": "Insufficient privileges to access this resource.",
})
return
}

c.Next()
}
}
18 changes: 9 additions & 9 deletions pkg/models/api_key_models.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,13 @@ type APIKeyGenerateRequest struct {

// APIKey struct that represents the API key table in the database
type APIKey struct {
ID string `json:"id"`
SubjectID string `json:"subject_id"`
Roles []string `json:"roles"`
Usage int `json:"usage"`
Limit int `json:"limit"`
CreatedAt time.Time `json:"created_at"`
ExpiresAt time.Time `json:"expires_at"`
LastUsed time.Time `json:"last_used"`
Active bool `json:"active"`
ID string `json:"id"`
SubjectID string `json:"subject_id"`
PermissionLevel int `json:"permission_level"`
Usage int `json:"usage"`
Limit int `json:"limit"`
CreatedAt time.Time `json:"created_at"`
ExpiresAt time.Time `json:"expires_at"`
LastUsed time.Time `json:"last_used"`
Active bool `json:"active"`
}
11 changes: 11 additions & 0 deletions pkg/models/role.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// models/role.go

package models

type Role int

const (
Default Role = iota
Standard
Admin
)
40 changes: 14 additions & 26 deletions pkg/routes/api_key.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,14 @@ package routes
import (
"github.com/gin-gonic/gin"

apiController "github.com/Frier03/KeyAuth-API/pkg/controllers/api-key"
apiKey "github.com/Frier03/KeyAuth-API/pkg/controllers/api-key"
apiKeyRole "github.com/Frier03/KeyAuth-API/pkg/controllers/api-key/role"

"github.com/Frier03/KeyAuth-API/pkg/dependencies"

middleware "github.com/Frier03/KeyAuth-API/pkg/middleware"
apiMiddleware "github.com/Frier03/KeyAuth-API/pkg/middleware/api-key"
middlewareApiKey "github.com/Frier03/KeyAuth-API/pkg/middleware/api-key"

"github.com/Frier03/KeyAuth-API/pkg/models"
)

Expand All @@ -17,39 +21,23 @@ func SetupAPIKeyRoutes(r *gin.Engine, deps dependencies.Dependencies) {
apiKeyRoutes.POST("/generate",
middleware.ValidateModel(&models.APIKeyGenerateRequest{}),
func(c *gin.Context) {
apiController.Generate(c, deps)
},
)

apiKeyRoutes.GET("/default",
apiMiddleware.ValidateKey(deps.BadgerService),
apiMiddleware.TrackKeyUsage(deps.BadgerService),
func(c *gin.Context) {
apiController.Default(c)
},
)

apiKeyRoutes.GET("/standard",
apiMiddleware.ValidateKey(deps.BadgerService),
apiMiddleware.TrackKeyUsage(deps.BadgerService),
func(c *gin.Context) {
apiController.Standard(c)
apiKey.Generate(c, deps)
},
)

apiKeyRoutes.GET("/admin",
apiMiddleware.ValidateKey(deps.BadgerService),
apiMiddleware.TrackKeyUsage(deps.BadgerService),
apiKeyRoutes.PATCH("/role/adjust",
middlewareApiKey.ValidateKey(deps.BadgerService),
middlewareApiKey.TrackKeyUsage(deps.BadgerService),
func(c *gin.Context) {
apiController.Admin(c)
apiKeyRole.Adjust(c, deps.BadgerService)
},
)

apiKeyRoutes.GET("/usage",
apiMiddleware.ValidateKey(deps.BadgerService),
apiMiddleware.TrackKeyUsage(deps.BadgerService),
middlewareApiKey.ValidateKey(deps.BadgerService),
middlewareApiKey.TrackKeyUsage(deps.BadgerService),
func(c *gin.Context) {
apiController.Usage(c)
apiKey.Usage(c)
},
)
}
Expand Down
7 changes: 6 additions & 1 deletion tests/restclients/api_key.rest
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,9 @@ Content-Type: application/json
### Check the usage of an API Key
# @name usage
GET {{baseUrl}}/api-key/usage HTTP/1.1
X-Api-Key: {{API_KEY}}
X-Api-Key: {{API_KEY}}


### Adjust the API key permission level
PATCH {{baseUrl}}/api-key/role/adjust?permission_level=1 HTTP/1.1
X-Api-Key: {{API_KEY}}