From bab184d73f4c342267e3842005c8f234414a0ecb Mon Sep 17 00:00:00 2001
From: Sh1tters <justinbestworldwide@gmail.com>
Date: Sun, 21 May 2023 18:55:25 +0200
Subject: [PATCH 1/8] Removed after completion for test

---
 pkg/controllers/api-key/admin.go    | 14 --------------
 pkg/controllers/api-key/default.go  | 14 --------------
 pkg/controllers/api-key/standard.go | 14 --------------
 3 files changed, 42 deletions(-)
 delete mode 100644 pkg/controllers/api-key/admin.go
 delete mode 100644 pkg/controllers/api-key/default.go
 delete mode 100644 pkg/controllers/api-key/standard.go

diff --git a/pkg/controllers/api-key/admin.go b/pkg/controllers/api-key/admin.go
deleted file mode 100644
index 0002e89..0000000
--- a/pkg/controllers/api-key/admin.go
+++ /dev/null
@@ -1,14 +0,0 @@
-package controllers
-
-import (
-	"net/http"
-
-	"github.com/gin-gonic/gin"
-)
-
-func Admin(c *gin.Context) {
-
-	c.JSON(http.StatusOK, gin.H{
-		"message": "Admin role access",
-	})
-}
diff --git a/pkg/controllers/api-key/default.go b/pkg/controllers/api-key/default.go
deleted file mode 100644
index ce7c60a..0000000
--- a/pkg/controllers/api-key/default.go
+++ /dev/null
@@ -1,14 +0,0 @@
-package controllers
-
-import (
-	"net/http"
-
-	"github.com/gin-gonic/gin"
-)
-
-func Default(c *gin.Context) {
-
-	c.JSON(http.StatusOK, gin.H{
-		"message": "Default role access",
-	})
-}
diff --git a/pkg/controllers/api-key/standard.go b/pkg/controllers/api-key/standard.go
deleted file mode 100644
index eabc6e6..0000000
--- a/pkg/controllers/api-key/standard.go
+++ /dev/null
@@ -1,14 +0,0 @@
-package controllers
-
-import (
-	"net/http"
-
-	"github.com/gin-gonic/gin"
-)
-
-func Standard(c *gin.Context) {
-
-	c.JSON(http.StatusOK, gin.H{
-		"message": "OK",
-	})
-}

From 9e01c8b45ee5e1269d1984ebb5f7ad66e290fbb3 Mon Sep 17 00:00:00 2001
From: Sh1tters <justinbestworldwide@gmail.com>
Date: Sun, 21 May 2023 18:55:47 +0200
Subject: [PATCH 2/8] API key can now only have one role, not multiple. Might
 be supported later.

---
 pkg/controllers/api-key/generate.go | 18 +++++++++---------
 1 file changed, 9 insertions(+), 9 deletions(-)

diff --git a/pkg/controllers/api-key/generate.go b/pkg/controllers/api-key/generate.go
index d82d328..b792054 100644
--- a/pkg/controllers/api-key/generate.go
+++ b/pkg/controllers/api-key/generate.go
@@ -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

From 09cbaa550770e34cb187130c8a8c1816307cbd00 Mon Sep 17 00:00:00 2001
From: Sh1tters <justinbestworldwide@gmail.com>
Date: Sun, 21 May 2023 18:56:30 +0200
Subject: [PATCH 3/8] Changed `Role` to `PermissionLevel`

---
 pkg/models/api_key_models.go | 18 +++++++++---------
 1 file changed, 9 insertions(+), 9 deletions(-)

diff --git a/pkg/models/api_key_models.go b/pkg/models/api_key_models.go
index 6109611..9de81fc 100644
--- a/pkg/models/api_key_models.go
+++ b/pkg/models/api_key_models.go
@@ -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"`
 }

From 0ac6d4e7652059084738f687a783d30d64eb174e Mon Sep 17 00:00:00 2001
From: Sh1tters <justinbestworldwide@gmail.com>
Date: Sun, 21 May 2023 18:56:40 +0200
Subject: [PATCH 4/8] New `Role` model

---
 pkg/models/role.go | 11 +++++++++++
 1 file changed, 11 insertions(+)
 create mode 100644 pkg/models/role.go

diff --git a/pkg/models/role.go b/pkg/models/role.go
new file mode 100644
index 0000000..8aac2a0
--- /dev/null
+++ b/pkg/models/role.go
@@ -0,0 +1,11 @@
+// models/role.go
+
+package models
+
+type Role int
+
+const (
+	Default Role = iota
+	Standard
+	Admin
+)

From 635559f48748b8961745a813094f0bd5522ead09 Mon Sep 17 00:00:00 2001
From: Sh1tters <justinbestworldwide@gmail.com>
Date: Sun, 21 May 2023 18:57:34 +0200
Subject: [PATCH 5/8] Update restclient

---
 tests/restclients/api_key.rest | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/tests/restclients/api_key.rest b/tests/restclients/api_key.rest
index ef8b69c..6fcabf9 100644
--- a/tests/restclients/api_key.rest
+++ b/tests/restclients/api_key.rest
@@ -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}}
\ No newline at end of file
+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}}

From f1367b78e626735982ff42bb21914b4620ed61f3 Mon Sep 17 00:00:00 2001
From: Sh1tters <justinbestworldwide@gmail.com>
Date: Sun, 21 May 2023 18:58:29 +0200
Subject: [PATCH 6/8] Add `/role/adjust` to adjust permission level of an API
 key

---
 pkg/routes/api_key.go | 40 ++++++++++++++--------------------------
 1 file changed, 14 insertions(+), 26 deletions(-)

diff --git a/pkg/routes/api_key.go b/pkg/routes/api_key.go
index c625a49..ddcf597 100644
--- a/pkg/routes/api_key.go
+++ b/pkg/routes/api_key.go
@@ -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"
 )
 
@@ -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)
 			},
 		)
 	}

From 7ea7dba1b24091d694783a1efcb5282972e41d50 Mon Sep 17 00:00:00 2001
From: Sh1tters <justinbestworldwide@gmail.com>
Date: Sun, 21 May 2023 18:59:47 +0200
Subject: [PATCH 7/8] New Feature: `Role Access Control`. See description for
 more details.

Feature includes:
- Role access based routes
- Adjustable role permissions - supports only 0-2

- Lots of bug fixes
---
 pkg/controllers/api-key/role/adjust.go        | 52 +++++++++++++++++++
 pkg/middleware/api-key/role_access_control.go | 33 ++++++++++++
 2 files changed, 85 insertions(+)
 create mode 100644 pkg/controllers/api-key/role/adjust.go
 create mode 100644 pkg/middleware/api-key/role_access_control.go

diff --git a/pkg/controllers/api-key/role/adjust.go b/pkg/controllers/api-key/role/adjust.go
new file mode 100644
index 0000000..a5a49f7
--- /dev/null
+++ b/pkg/controllers/api-key/role/adjust.go
@@ -0,0 +1,52 @@
+package role
+
+import (
+	"fmt"
+	"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, ok := c.GetQuery("permission_level")
+	apiKeyData, _ := c.Get("api-key-model")
+
+	// Apply model to apiKey
+	apiKeyModel, _ := apiKeyData.(models.APIKey)
+	fmt.Println(adjust, ok)
+	// 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",
+	})
+}
diff --git a/pkg/middleware/api-key/role_access_control.go b/pkg/middleware/api-key/role_access_control.go
new file mode 100644
index 0000000..f858ae0
--- /dev/null
+++ b/pkg/middleware/api-key/role_access_control.go
@@ -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()
+	}
+}

From 4f728640c49ba18c52ac496c9f43e15448f5abc5 Mon Sep 17 00:00:00 2001
From: Sh1tters <justinbestworldwide@gmail.com>
Date: Sun, 21 May 2023 19:01:14 +0200
Subject: [PATCH 8/8] HOT FIX for `New Feature`. See previous commit for
 details

---
 pkg/controllers/api-key/role/adjust.go | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/pkg/controllers/api-key/role/adjust.go b/pkg/controllers/api-key/role/adjust.go
index a5a49f7..803b49c 100644
--- a/pkg/controllers/api-key/role/adjust.go
+++ b/pkg/controllers/api-key/role/adjust.go
@@ -1,7 +1,6 @@
 package role
 
 import (
-	"fmt"
 	"net/http"
 	"strconv"
 
@@ -12,12 +11,12 @@ import (
 
 func Adjust(c *gin.Context, badgerService *services.BadgerService) {
 	apiKey := c.GetHeader("X-Api-Key")
-	adjust, ok := c.GetQuery("permission_level")
+	adjust, _ := c.GetQuery("permission_level")
 	apiKeyData, _ := c.Get("api-key-model")
 
 	// Apply model to apiKey
 	apiKeyModel, _ := apiKeyData.(models.APIKey)
-	fmt.Println(adjust, ok)
+
 	// Validate adjust value
 	level, err := strconv.Atoi(adjust)
 	if err != nil {
