Skip to content
This repository has been archived by the owner on Dec 4, 2024. It is now read-only.

feat(key): Switch from OwnerID to OwnerUsername #34

Merged
merged 1 commit into from
Jul 22, 2024
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
17 changes: 8 additions & 9 deletions internal/controller/http/v1/apikey.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import (
"net/http"
"strconv"

"github.com/devkcud/arkhon-foundation/arkhon-api/internal/model"
"github.com/devkcud/arkhon-foundation/arkhon-api/internal/model/dto"
"github.com/devkcud/arkhon-foundation/arkhon-api/internal/service"
"github.com/devkcud/arkhon-foundation/arkhon-api/pkg/middleware"
Expand Down Expand Up @@ -95,7 +94,7 @@ func GetMyAPIKeys(ctx *gin.Context) {
perpage = i
}

keys, err := service.APIKey.FindByOwnerID(issuer.ID, page, perpage)
keys, err := service.APIKey.FindByOwnerUsername(issuer.Username, page, perpage)
if err != nil {
ctx.JSON(http.StatusInternalServerError, gin.H{"error": dict.InternalServerError})
return
Expand All @@ -107,17 +106,17 @@ func GetMyAPIKeys(ctx *gin.Context) {
func CreateAPIKey(ctx *gin.Context) {
dict := translations.GetTranslation(ctx)

var issuerID uint = 0
var issuerUsername string = ""
if u, exists := ctx.Get("auth_user"); exists {
issuerID = u.(*dto.ProfileSearch).ID
issuerUsername = u.(*dto.ProfileSearch).Username
}

maxUsage, err := strconv.ParseUint(ctx.Query("maxusage"), 10, 64)
if err != nil {
maxUsage = 0
}

newKey, err := service.APIKey.Create(issuerID, uint(maxUsage))
newKey, err := service.APIKey.Create(issuerUsername, uint(maxUsage))
if err != nil {
log.Printf("Error generating new API key: %v", err)
ctx.JSON(http.StatusInternalServerError, gin.H{"error": dict.InternalServerError})
Expand Down Expand Up @@ -148,21 +147,21 @@ func GetAPIKeyInfo(ctx *gin.Context) {
func DestroyAPIKey(ctx *gin.Context) {
dict := translations.GetTranslation(ctx)

if err := service.APIKey.Delete(ctx.Keys["api_key_lookup"].(*model.APIKey).Key); err != nil {
if err := service.APIKey.Delete(ctx.Keys["api_key_lookup"].(*dto.ReadAPIKey).Key); err != nil {
log.Printf("Error destroying API key: %v", err)
ctx.JSON(http.StatusInternalServerError, gin.H{"error": dict.InternalServerError})
return
}

ctx.JSON(http.StatusOK, gin.H{"message": gin.H{"error": dict.APIKeyDestroyed}})
ctx.JSON(http.StatusOK, gin.H{"message": dict.APIKeyDestroyed})
}

func UpdateAPIKey(ctx *gin.Context) {
dict := translations.GetTranslation(ctx)

key := ctx.Keys["api_key_lookup"].(*model.APIKey)
key := ctx.Keys["api_key_lookup"].(*dto.ReadAPIKey)

var body dto.APIKey
var body dto.UpdateAPIKey
if err := ctx.BindJSON(&body); err != nil {
log.Print(err)
ctx.JSON(http.StatusBadRequest, gin.H{"error": dict.InvalidBody})
Expand Down
4 changes: 2 additions & 2 deletions internal/model/apikey.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
package model

type APIKey struct {
Key string `json:"key" gorm:"primarykey"`
OwnerID uint `json:"owner_id" gorm:"index"`
Key string `json:"key" gorm:"primarykey"`
OwnerUsername string `json:"owner" gorm:"index"`

EnabledKeyManage int `json:"enabled_key_manage" gorm:"default:-1"` // Manage existing API keys
EnabledAuth int `json:"enabled_auth" gorm:"default:-1"` // Register, Login, Update, Delete
Expand Down
18 changes: 16 additions & 2 deletions internal/model/dto/apikey.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package dto

type APIKey struct {
OwnerID uint `validate:"omitempty" json:"owner_id"`
type UpdateAPIKey struct {
OwnerUsername string `validate:"omitempty" json:"owner"`

EnabledKeyManage int `validate:"omitempty,mustbenumericalboolean" json:"enabled_key_manage"`
EnabledAuth int `validate:"omitempty,mustbenumericalboolean" json:"enabled_auth"`
Expand All @@ -12,3 +12,17 @@ type APIKey struct {
TimesUsed uint `validate:"omitempty" json:"times_used"`
MaxUsage uint `validate:"omitempty" json:"max_usage"`
}

type ReadAPIKey struct {
Key string `json:"key"`
OwnerUsername string `json:"owner"`

EnabledKeyManage int `json:"enabled_key_manage"`
EnabledAuth int `json:"enabled_auth"`
EnabledSearch int `json:"enabled_search"`
EnabledUserFetch int `json:"enabled_user_fetch"`
EnabledUserActions int `json:"enabled_user_actions"`

TimesUsed uint `json:"times_used"`
MaxUsage uint `json:"max_usage"`
}
24 changes: 12 additions & 12 deletions internal/service/repository/apikey.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,11 @@ type apiKeyRepository struct {

type APIKeyRepository interface {
Store(*model.APIKey) error
Update(string, *dto.APIKey) error
Update(string, *dto.UpdateAPIKey) error
RegisterUse(string) error
FindAll(page, perPage int) (*dto.Pagination[model.APIKey], error)
Find(key string) (*model.APIKey, error)
FindByOwnerID(id uint, page, perPage int) (*dto.Pagination[model.APIKey], error)
FindAll(page, perPage int) (*dto.Pagination[dto.ReadAPIKey], error)
Find(key string) (*dto.ReadAPIKey, error)
FindByOwnerUsername(username string, page, perPage int) (*dto.Pagination[dto.ReadAPIKey], error)
Delete(string) error
}

Expand All @@ -30,30 +30,30 @@ func (a apiKeyRepository) Store(createModel *model.APIKey) error {
return a.db.Create(&createModel).Error
}

func (a apiKeyRepository) Update(key string, updateModel *dto.APIKey) error {
func (a apiKeyRepository) Update(key string, updateModel *dto.UpdateAPIKey) error {
return a.db.Model(&model.APIKey{}).Where("key = ?", key).Updates(&updateModel).Error
}

func (a apiKeyRepository) RegisterUse(key string) error {
return a.db.Exec("UPDATE api_keys SET times_used = times_used + 1 WHERE key = ?", key).Error
}

func (a apiKeyRepository) FindAll(page, perPage int) (*dto.Pagination[model.APIKey], error) {
return pagination.Generate[model.APIKey](a.db.Model(&model.APIKey{}).Exec("SELECT * FROM api_keys"), page, perPage)
func (a apiKeyRepository) FindAll(page, perPage int) (*dto.Pagination[dto.ReadAPIKey], error) {
return pagination.Generate[dto.ReadAPIKey](a.db.Model(&model.APIKey{}).Exec("SELECT * FROM api_keys"), page, perPage)
}

func (a apiKeyRepository) Find(key string) (*model.APIKey, error) {
var apikey *model.APIKey
func (a apiKeyRepository) Find(key string) (*dto.ReadAPIKey, error) {
var apikey *dto.ReadAPIKey

if err := a.db.First(&apikey, "key = ?", key).Error; err != nil {
if err := a.db.Model(&model.APIKey{}).First(&apikey, "key = ?", key).Error; err != nil {
return nil, err
}

return apikey, nil
}

func (a apiKeyRepository) FindByOwnerID(ownerID uint, page, perPage int) (*dto.Pagination[model.APIKey], error) {
return pagination.Generate[model.APIKey](a.db.Model(&model.APIKey{}).Where("owner_id = ?", ownerID), page, perPage)
func (a apiKeyRepository) FindByOwnerUsername(ownerUsername string, page, perPage int) (*dto.Pagination[dto.ReadAPIKey], error) {
return pagination.Generate[dto.ReadAPIKey](a.db.Model(&model.APIKey{}).Where("owner_username = ?", ownerUsername), page, perPage)
}

func (a apiKeyRepository) Delete(key string) error {
Expand Down
21 changes: 14 additions & 7 deletions internal/service/usecase/apikey.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,34 +16,41 @@ func NewAPIKeyUseCase() APIKeyUseCase {
return APIKeyUseCase{ar: repository.NewAPIKeyRepository()}
}

func (auc *APIKeyUseCase) Create(ownerID, maxUsage uint) (*model.APIKey, error) {
func (auc *APIKeyUseCase) Create(ownerUsername string, maxUsage uint) (*model.APIKey, error) {
key := new(model.APIKey)
key.Key = uuid.New().String()

key.OwnerID = ownerID
if ownerUsername != "" {
if _, err := NewUserUseCase().GetByUsername(ownerUsername); err != nil {
return nil, err
}

key.OwnerUsername = ownerUsername
}

key.MaxUsage = maxUsage

return key, auc.ar.Store(key)
}

func (auc *APIKeyUseCase) Update(key string, updateModel *dto.APIKey) error {
func (auc *APIKeyUseCase) Update(key string, updateModel *dto.UpdateAPIKey) error {
return auc.ar.Update(key, updateModel)
}

func (auc *APIKeyUseCase) RegisterUse(key string) error {
return auc.ar.RegisterUse(key)
}

func (auc *APIKeyUseCase) FindAll(page, perPage int) (*dto.Pagination[model.APIKey], error) {
func (auc *APIKeyUseCase) FindAll(page, perPage int) (*dto.Pagination[dto.ReadAPIKey], error) {
return auc.ar.FindAll(page, perPage)
}

func (auc *APIKeyUseCase) Find(key string) (*model.APIKey, error) {
func (auc *APIKeyUseCase) Find(key string) (*dto.ReadAPIKey, error) {
return auc.ar.Find(key)
}

func (auc *APIKeyUseCase) FindByOwnerID(id uint, page, perPage int) (*dto.Pagination[model.APIKey], error) {
return auc.ar.FindByOwnerID(id, page, perPage)
func (auc *APIKeyUseCase) FindByOwnerUsername(username string, page, perPage int) (*dto.Pagination[dto.ReadAPIKey], error) {
return auc.ar.FindByOwnerUsername(username, page, perPage)
}

func (auc *APIKeyUseCase) Delete(key string) error {
Expand Down
14 changes: 7 additions & 7 deletions pkg/middleware/apikey.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import (
"log"
"net/http"

"github.com/devkcud/arkhon-foundation/arkhon-api/internal/model"
"github.com/devkcud/arkhon-foundation/arkhon-api/internal/model/dto"
"github.com/devkcud/arkhon-foundation/arkhon-api/internal/service"
"github.com/devkcud/arkhon-foundation/arkhon-api/translations"
"github.com/gin-gonic/gin"
Expand All @@ -27,7 +27,7 @@ func GetAPIKey(ctx *gin.Context) {
func apiKeyHas(ctx *gin.Context, b int, permission string) {
dict := translations.GetTranslation(ctx)

key := ctx.Keys["api_key"].(*model.APIKey)
key := ctx.Keys["api_key"].(*dto.ReadAPIKey)

if key.MaxUsage != 0 && key.TimesUsed >= key.MaxUsage {
ctx.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{"error": dict.MaximumAPIKey})
Expand All @@ -47,26 +47,26 @@ func apiKeyHas(ctx *gin.Context, b int, permission string) {
}

func APIKeyHasEnabledKeyManage(ctx *gin.Context) {
key := ctx.Keys["api_key"].(*model.APIKey)
key := ctx.Keys["api_key"].(*dto.ReadAPIKey)
apiKeyHas(ctx, key.EnabledKeyManage, "manage.api")
}

func APIKeyHasEnabledAuth(ctx *gin.Context) {
key := ctx.Keys["api_key"].(*model.APIKey)
key := ctx.Keys["api_key"].(*dto.ReadAPIKey)
apiKeyHas(ctx, key.EnabledAuth, "manage.auth")
}

func APIKeyHasEnabledSearch(ctx *gin.Context) {
key := ctx.Keys["api_key"].(*model.APIKey)
key := ctx.Keys["api_key"].(*dto.ReadAPIKey)
apiKeyHas(ctx, key.EnabledSearch, "query.search")
}

func APIKeyHasEnabledUserFetch(ctx *gin.Context) {
key := ctx.Keys["api_key"].(*model.APIKey)
key := ctx.Keys["api_key"].(*dto.ReadAPIKey)
apiKeyHas(ctx, key.EnabledUserFetch, "query.user")
}

func APIKeyHasEnabledUserActions(ctx *gin.Context) {
key := ctx.Keys["api_key"].(*model.APIKey)
key := ctx.Keys["api_key"].(*dto.ReadAPIKey)
apiKeyHas(ctx, key.EnabledUserActions, "actions")
}
Loading