Skip to content

Commit 0320419

Browse files
author
farhoud.m7
committed
Update environment configuration, enhance token management, and add UUID support for user models
1 parent 3849988 commit 0320419

10 files changed

Lines changed: 66 additions & 31 deletions

File tree

.env.example

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ DB_PATH=app.db
77
AZURE_OPENAI_ENDPOINT=https://your-resource-name.openai.azure.com
88
AZURE_OPENAI_KEY=your-api-key-here
99
AZURE_OPENAI_DEPLOYMENT=your-deployment-name
10+
AZURE_OPENAI_DEPLOYMENT_VERSION=2024-12-01-preview
1011

1112
# Description of each variable:
1213
# PORT: The port number the server will listen on (default: 8080)

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,4 @@ docs/swagger.json
88
docs/swagger.yaml
99
docs/docs.go
1010
app.db
11+
.env

auth.go

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

33
import (
4+
"fmt"
45
"net/http"
56
"time"
67

@@ -39,6 +40,7 @@ func generateToken(username, tokenType string, expiresIn time.Duration) (string,
3940
func authMiddleware() gin.HandlerFunc {
4041
return func(c *gin.Context) {
4142
tokenString := c.GetHeader("Authorization")
43+
fmt.Println(tokenString)
4244
if tokenString == "" {
4345
c.JSON(http.StatusUnauthorized, models.NewErrorResponse("Authorization header is required"))
4446
c.Abort()
@@ -68,7 +70,17 @@ func authMiddleware() gin.HandlerFunc {
6870
return
6971
}
7072

73+
// Get user from database to get the ID
74+
var user database.DBUser
75+
if err := database.GetDB().Where("username = ?", claims.Username).First(&user).Error; err != nil {
76+
c.JSON(http.StatusUnauthorized, models.NewErrorResponse("User not found"))
77+
c.Abort()
78+
return
79+
}
80+
81+
// Set both username and user_id in context
7182
c.Set("username", claims.Username)
83+
c.Set("user_id", user.ID)
7284
c.Next()
7385
}
7486
}

azure/openai.go

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
"time"
99

1010
"github.com/gin-gonic/gin"
11+
"github.com/google/uuid"
1112
"github.com/vhybZApp/api/config"
1213
"github.com/vhybZApp/api/database"
1314
"github.com/vhybZApp/api/models"
@@ -79,6 +80,12 @@ func ChatCompletion(c *gin.Context) {
7980
// Initialize token quota service
8081
tokenQuotaService := services.NewTokenQuotaService(database.GetDB())
8182

83+
// Check if user has enough quota for a reasonable estimate (e.g., 1000 tokens)
84+
if err := tokenQuotaService.UpdateUsage(userID.(uuid.UUID), 1000); err != nil {
85+
c.JSON(http.StatusTooManyRequests, models.NewErrorResponse(err.Error()))
86+
return
87+
}
88+
8289
// Validate Azure OpenAI configuration
8390
if config.AppConfig.AzureOpenAIEndpoint == "" || config.AppConfig.AzureOpenAIKey == "" || config.AppConfig.AzureOpenAIDeployment == "" {
8491
c.JSON(http.StatusInternalServerError, models.NewErrorResponse("Azure OpenAI configuration is incomplete"))
@@ -94,7 +101,7 @@ func ChatCompletion(c *gin.Context) {
94101

95102
// Create HTTP client
96103
client := &http.Client{
97-
Timeout: 30 * time.Second,
104+
Timeout: 300 * time.Second,
98105
}
99106

100107
// Marshal request body
@@ -105,7 +112,9 @@ func ChatCompletion(c *gin.Context) {
105112
}
106113

107114
// Create request
108-
url := config.AppConfig.AzureOpenAIEndpoint + "/openai/deployments/" + config.AppConfig.AzureOpenAIDeployment + "/chat/completions?api-version=2023-05-15"
115+
url := config.AppConfig.AzureOpenAIEndpoint + "/openai/deployments/" +
116+
config.AppConfig.AzureOpenAIDeployment + "/chat/completions?api-version=" + config.AppConfig.AzureOpenAIDeploymentVersion
117+
109118
httpReq, err := http.NewRequest("POST", url, bytes.NewBuffer(reqBody))
110119
if err != nil {
111120
c.JSON(http.StatusInternalServerError, models.NewErrorResponse("Error creating request"))
@@ -141,14 +150,7 @@ func ChatCompletion(c *gin.Context) {
141150
var chatResp ChatCompletionResponse
142151
if err := json.Unmarshal(body, &chatResp); err != nil {
143152
c.JSON(http.StatusInternalServerError, models.NewErrorResponse("Error parsing response"))
144-
return
145-
}
146-
147-
// Update token usage
148-
if err := tokenQuotaService.UpdateUsage(userID.(string), chatResp.Usage.TotalTokens); err != nil {
149-
c.JSON(http.StatusTooManyRequests, models.NewErrorResponse(err.Error()))
150-
return
151-
}
153+
returnasdu
152154

153155
c.JSON(http.StatusOK, chatResp)
154156
}

config/config.go

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,10 @@ type Config struct {
1212
JWTSecret string
1313
DBPath string
1414
// Azure OpenAI Configuration
15-
AzureOpenAIEndpoint string
16-
AzureOpenAIKey string
17-
AzureOpenAIDeployment string
15+
AzureOpenAIEndpoint string
16+
AzureOpenAIKey string
17+
AzureOpenAIDeployment string
18+
AzureOpenAIDeploymentVersion string
1819
}
1920

2021
var AppConfig Config
@@ -27,12 +28,13 @@ func LoadConfig() {
2728

2829
// Set default values
2930
AppConfig = Config{
30-
Port: getEnv("PORT", "8080"),
31-
JWTSecret: getEnv("JWT_SECRET", "your-default-secret-key"),
32-
DBPath: getEnv("DB_PATH", "app.db"),
33-
AzureOpenAIEndpoint: getEnv("AZURE_OPENAI_ENDPOINT", ""),
34-
AzureOpenAIKey: getEnv("AZURE_OPENAI_KEY", ""),
35-
AzureOpenAIDeployment: getEnv("AZURE_OPENAI_DEPLOYMENT", ""),
31+
Port: getEnv("PORT", "8080"),
32+
JWTSecret: getEnv("JWT_SECRET", "your-default-secret-key"),
33+
DBPath: getEnv("DB_PATH", "app.db"),
34+
AzureOpenAIEndpoint: getEnv("AZURE_OPENAI_ENDPOINT", ""),
35+
AzureOpenAIKey: getEnv("AZURE_OPENAI_KEY", ""),
36+
AzureOpenAIDeployment: getEnv("AZURE_OPENAI_DEPLOYMENT", "gpt-4o"),
37+
AzureOpenAIDeploymentVersion: getEnv("AZURE_OPENAI_DEPLOYMENT_VERSION", "gpt-4o"),
3638
}
3739

3840
// Validate required configurations

database/models.go

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,32 +3,44 @@ package database
33
import (
44
"time"
55

6+
"github.com/google/uuid"
67
"golang.org/x/crypto/bcrypt"
78
"gorm.io/gorm"
89
)
910

1011
// DBUser represents the user data as stored in the database
1112
type DBUser struct {
12-
gorm.Model
13-
Username string `gorm:"uniqueIndex;not null"`
14-
Password string `gorm:"not null"`
15-
Email string `gorm:"uniqueIndex;not null"`
16-
RefreshToken string `gorm:"-"` // Not stored in DB, only used temporarily
13+
ID uuid.UUID `gorm:"type:uuid;primary_key"`
14+
CreatedAt time.Time
15+
UpdatedAt time.Time
16+
DeletedAt gorm.DeletedAt `gorm:"index"`
17+
Username string `gorm:"uniqueIndex;not null"`
18+
Password string `gorm:"not null"`
19+
Email string `gorm:"uniqueIndex;not null"`
20+
RefreshToken string `gorm:"-"` // Not stored in DB, only used temporarily
21+
}
22+
23+
// BeforeCreate will set a UUID rather than numeric ID
24+
func (u *DBUser) BeforeCreate(tx *gorm.DB) error {
25+
u.ID = uuid.New()
26+
return nil
1727
}
1828

1929
// DBTokenUsage represents the daily token usage for a user in the database
2030
type DBTokenUsage struct {
2131
gorm.Model
22-
UserID string `gorm:"index"`
32+
UserID uuid.UUID `gorm:"type:uuid;index;foreignKey:ID;references:ID;onDelete:CASCADE"`
33+
User DBUser `gorm:"foreignKey:UserID"`
2334
Date time.Time `gorm:"index"`
2435
Tokens int `gorm:"default:0"`
2536
}
2637

2738
// DBTokenQuota represents the daily token quota for a user in the database
2839
type DBTokenQuota struct {
2940
gorm.Model
30-
UserID string `gorm:"uniqueIndex"`
31-
DailyQuota int `gorm:"default:100000"` // Default 100k tokens per day
41+
UserID uuid.UUID `gorm:"type:uuid;uniqueIndex;foreignKey:ID;references:ID;onDelete:CASCADE"`
42+
User DBUser `gorm:"foreignKey:UserID"`
43+
DailyQuota int `gorm:"default:100000"` // Default 100k tokens per day
3244
}
3345

3446
// HashPassword hashes the password using bcrypt

go.mod

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ go 1.21
55
require (
66
github.com/gin-gonic/gin v1.9.1
77
github.com/golang-jwt/jwt/v5 v5.0.0
8+
github.com/google/uuid v1.6.0
89
github.com/joho/godotenv v1.5.1
910
github.com/swaggo/files v1.0.1
1011
github.com/swaggo/gin-swagger v1.6.0

go.sum

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,8 @@ github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaS
4848
github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU=
4949
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
5050
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
51+
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
52+
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
5153
github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
5254
github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
5355
github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ=

main.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,14 @@ package main
33
import (
44
"log"
55
"net/http"
6-
_ "github.com/vhybZApp/api/docs"
6+
77
"github.com/gin-gonic/gin"
88
swaggerFiles "github.com/swaggo/files"
99
ginSwagger "github.com/swaggo/gin-swagger"
1010
"github.com/vhybZApp/api/azure"
1111
"github.com/vhybZApp/api/config"
1212
"github.com/vhybZApp/api/database"
13+
_ "github.com/vhybZApp/api/docs"
1314
)
1415

1516
// @title Vhybz API

services/token_quota.go

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"errors"
55
"time"
66

7+
"github.com/google/uuid"
78
"github.com/vhybZApp/api/database"
89
"gorm.io/gorm"
910
)
@@ -17,7 +18,7 @@ func NewTokenQuotaService(db *gorm.DB) *TokenQuotaService {
1718
}
1819

1920
// GetUserQuota returns the daily token quota for a user
20-
func (s *TokenQuotaService) GetUserQuota(userID string) (*database.DBTokenQuota, error) {
21+
func (s *TokenQuotaService) GetUserQuota(userID uuid.UUID) (*database.DBTokenQuota, error) {
2122
var quota database.DBTokenQuota
2223
result := s.db.Where("user_id = ?", userID).First(&quota)
2324
if result.Error != nil {
@@ -38,7 +39,7 @@ func (s *TokenQuotaService) GetUserQuota(userID string) (*database.DBTokenQuota,
3839
}
3940

4041
// GetDailyUsage returns the token usage for a user on a specific date
41-
func (s *TokenQuotaService) GetDailyUsage(userID string, date time.Time) (*database.DBTokenUsage, error) {
42+
func (s *TokenQuotaService) GetDailyUsage(userID uuid.UUID, date time.Time) (*database.DBTokenUsage, error) {
4243
var usage database.DBTokenUsage
4344
startOfDay := time.Date(date.Year(), date.Month(), date.Day(), 0, 0, 0, 0, date.Location())
4445
result := s.db.Where("user_id = ? AND date = ?", userID, startOfDay).First(&usage)
@@ -61,7 +62,7 @@ func (s *TokenQuotaService) GetDailyUsage(userID string, date time.Time) (*datab
6162
}
6263

6364
// UpdateUsage updates the token usage for a user
64-
func (s *TokenQuotaService) UpdateUsage(userID string, tokens int) error {
65+
func (s *TokenQuotaService) UpdateUsage(userID uuid.UUID, tokens int) error {
6566
now := time.Now()
6667

6768
// Get or create daily usage

0 commit comments

Comments
 (0)