Skip to content

Commit 81a5ab6

Browse files
authored
Merge pull request #63 from Plebeian-Technology/go-backend-conversion-1
Implement API Key Model Logic in Go
2 parents c1f43c1 + a0919e5 commit 81a5ab6

1 file changed

Lines changed: 70 additions & 0 deletions

File tree

go-backend/models/api_key.go

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
package models
22

33
import (
4+
"crypto/hmac"
5+
"crypto/sha512"
6+
"encoding/hex"
7+
"errors"
8+
"os"
49
"time"
510

611
"gorm.io/gorm"
@@ -14,4 +19,69 @@ type APIKey struct {
1419
Name string
1520
TokenDigest string `gorm:"not null;unique"`
1621
BearerID uint `gorm:"not null"`
22+
Token string `gorm:"-"` // Virtual attribute for raw token value
23+
}
24+
25+
// BeforeCreate is a GORM hook that generates the token digest before creating a new APIKey record
26+
func (apiKey *APIKey) BeforeCreate(tx *gorm.DB) (err error) {
27+
if apiKey.Token == "" {
28+
return errors.New("token is required")
29+
}
30+
31+
apiKey.TokenDigest, err = generateTokenHMACDigest(apiKey.Token)
32+
return
33+
}
34+
35+
// AuthenticateByToken finds an API key by its token
36+
func AuthenticateByToken(db *gorm.DB, token string) (*APIKey, error) {
37+
return authenticateByToken(db, token, false)
38+
}
39+
40+
// AuthenticateByToken finds an API key by its token and returns an error if not found
41+
func AuthenticateByTokenBang(db *gorm.DB, token string) (*APIKey, error) {
42+
return authenticateByToken(db, token, true)
43+
}
44+
45+
func authenticateByToken(db *gorm.DB, token string, bang bool) (*APIKey, error) {
46+
digest, err := generateTokenHMACDigest(token)
47+
if err != nil {
48+
return nil, err
49+
}
50+
51+
var apiKey APIKey
52+
var result *gorm.DB
53+
if bang {
54+
result = db.Where("token_digest = ?", digest).First(&apiKey)
55+
} else {
56+
result = db.Where("token_digest = ?", digest).Limit(1).Find(&apiKey)
57+
}
58+
59+
if result.Error != nil {
60+
return nil, result.Error
61+
}
62+
63+
if result.RowsAffected == 0 {
64+
return nil, nil // Return nil if no record is found
65+
}
66+
67+
return &apiKey, nil
68+
}
69+
70+
func generateTokenHMACDigest(token string) (string, error) {
71+
hmacSecretKey := os.Getenv("API_KEY_HMAC_SECRET_KEY")
72+
if hmacSecretKey == "" {
73+
// In test environment, use a default value
74+
if os.Getenv("GO_ENV") == "test" {
75+
hmacSecretKey = "test"
76+
} else {
77+
return "", errors.New("API_KEY_HMAC_SECRET_KEY is not set")
78+
}
79+
}
80+
81+
mac := hmac.New(sha512.New, []byte(hmacSecretKey))
82+
_, err := mac.Write([]byte(token))
83+
if err != nil {
84+
return "", err
85+
}
86+
return hex.EncodeToString(mac.Sum(nil)), nil
1787
}

0 commit comments

Comments
 (0)