RyZ commited on
Commit
0750c92
·
unverified ·
2 Parent(s): fcc14675c3fcbb

Merge pull request #23 from orion-ai-project/dev

Browse files

fix: options database to key-based data structure

controllers/auth_controller.go CHANGED
@@ -55,7 +55,6 @@ func (c *authController) Register(ctx *gin.Context) {
55
 
56
  ctx.SetSameSite(http.SameSiteNoneMode)
57
  ctx.SetCookie("RefreshToken", resp.RefreshToken, 3600*24*7, "/", "", true, true)
58
-
59
  utils.SendResponse[dto.AuthResponse, any](ctx, nil, *resp, nil)
60
  }
61
 
 
55
 
56
  ctx.SetSameSite(http.SameSiteNoneMode)
57
  ctx.SetCookie("RefreshToken", resp.RefreshToken, 3600*24*7, "/", "", true, true)
 
58
  utils.SendResponse[dto.AuthResponse, any](ctx, nil, *resp, nil)
59
  }
60
 
models/entity/constant.go CHANGED
@@ -3,7 +3,7 @@ package models
3
  const (
4
  CONNECTION_SUCCESS_MESSAGE = "Connection initialized. Please scan the QR code in your terminal."
5
  CONNECTION_INIT_SUCCESS = "Connection process initiated successfully"
6
- QR_SCAN_INSTRUCTION = "Check terminal for QR code scanning"
7
  POSTGRES_DIALECT = "postgres"
8
  WHATSAPP_STATUS_CONNECTED = "connected"
9
  WHATSAPP_STATUS_DISCONNECTED = "disconnected"
 
3
  const (
4
  CONNECTION_SUCCESS_MESSAGE = "Connection initialized. Please scan the QR code in your terminal."
5
  CONNECTION_INIT_SUCCESS = "Connection process initiated successfully"
6
+ QR_SCAN_INSTRUCTION = "Check Screen for QR code scanning"
7
  POSTGRES_DIALECT = "postgres"
8
  WHATSAPP_STATUS_CONNECTED = "connected"
9
  WHATSAPP_STATUS_DISCONNECTED = "disconnected"
models/entity/entity.go CHANGED
@@ -7,30 +7,19 @@ import (
7
  "gorm.io/gorm"
8
  )
9
 
10
- type WhatsAppAccount struct {
11
  ID uuid.UUID `gorm:"primaryKey;type:uuid;default:gen_random_uuid()" json:"id"`
12
- AccountName string `gorm:"size:100;not null" json:"account_name"`
13
- JID string `gorm:"column:jid;size:255;uniqueIndex" json:"jid"`
 
 
 
14
  IsActive bool `gorm:"default:false" json:"is_active"`
15
  CreatedAt time.Time `json:"created_at"`
16
  UpdatedAt time.Time `json:"updated_at"`
17
  DeletedAt gorm.DeletedAt `gorm:"index" json:"deleted_at"`
18
  }
19
 
20
- func (WhatsAppAccount) TableName() string {
21
- return "whatsapp_accounts"
22
- }
23
-
24
- type User struct {
25
- ID uuid.UUID `gorm:"primaryKey;type:uuid;default:gen_random_uuid()" json:"id"`
26
- Username string `gorm:"size:100;uniqueIndex;not null" json:"username"`
27
- Password string `gorm:"not null" json:"-"`
28
- Role string `gorm:"default:'user';not null" json:"role"`
29
- CreatedAt time.Time `json:"created_at"`
30
- UpdatedAt time.Time `json:"updated_at"`
31
- DeletedAt gorm.DeletedAt `gorm:"index" json:"deleted_at"`
32
- }
33
-
34
  func (User) TableName() string {
35
  return "users"
36
  }
@@ -47,11 +36,11 @@ func (RefreshToken) TableName() string {
47
  return "refresh_tokens"
48
  }
49
 
50
- type Settings struct {
51
- ID uint `gorm:"primaryKey" json:"id"`
52
- RegistrationEnabled bool `gorm:"default:true" json:"registration_enabled"`
53
  }
54
 
55
- func (Settings) TableName() string {
56
  return "settings"
57
  }
 
7
  "gorm.io/gorm"
8
  )
9
 
10
+ type User struct {
11
  ID uuid.UUID `gorm:"primaryKey;type:uuid;default:gen_random_uuid()" json:"id"`
12
+ Username string `gorm:"size:100;uniqueIndex;not null" json:"username"`
13
+ Password string `gorm:"not null" json:"-"`
14
+ Role string `gorm:"default:'user';not null" json:"role"`
15
+ AccountName string `gorm:"size:100;default:'Default Device'" json:"account_name"`
16
+ JID string `gorm:"column:jid;size:255" json:"jid"`
17
  IsActive bool `gorm:"default:false" json:"is_active"`
18
  CreatedAt time.Time `json:"created_at"`
19
  UpdatedAt time.Time `json:"updated_at"`
20
  DeletedAt gorm.DeletedAt `gorm:"index" json:"deleted_at"`
21
  }
22
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
23
  func (User) TableName() string {
24
  return "users"
25
  }
 
36
  return "refresh_tokens"
37
  }
38
 
39
+ type Setting struct {
40
+ Key string `gorm:"primaryKey;size:255" json:"key"`
41
+ Value string `gorm:"type:text" json:"value"`
42
  }
43
 
44
+ func (Setting) TableName() string {
45
  return "settings"
46
  }
provider/provider.go CHANGED
@@ -33,10 +33,9 @@ func NewAppProvider() AppProvider {
33
 
34
  // Auto-Migrate Entities
35
  _ = configProvider.ProvideDatabaseConfig().AutoMigrateAll(
36
- &entity.WhatsAppAccount{},
37
  &entity.User{},
38
  &entity.RefreshToken{},
39
- &entity.Settings{},
40
  )
41
 
42
  return &appProvider{
 
33
 
34
  // Auto-Migrate Entities
35
  _ = configProvider.ProvideDatabaseConfig().AutoMigrateAll(
 
36
  &entity.User{},
37
  &entity.RefreshToken{},
38
+ &entity.Setting{},
39
  )
40
 
41
  return &appProvider{
repositories/auth_repository.go CHANGED
@@ -18,7 +18,7 @@ type AuthRepository interface {
18
  RevokeAllUserRefreshTokens(userID uuid.UUID) error
19
  UpdateUser(user *entity.User) error
20
  DeleteUser(id uuid.UUID) error
21
- GetSettings() (*entity.Settings, error)
22
  SetRegistrationEnabled(enabled bool) error
23
  HasValidRefreshToken(userID uuid.UUID) (bool, error)
24
  }
@@ -85,23 +85,40 @@ func (r *authRepository) DeleteUser(id uuid.UUID) error {
85
  return r.db.Delete(&entity.User{}, id).Error
86
  }
87
 
88
- func (r *authRepository) GetSettings() (*entity.Settings, error) {
89
- var settings entity.Settings
90
- if err := r.db.First(&settings).Error; err != nil {
91
- settings = entity.Settings{ID: 1, RegistrationEnabled: true}
92
- r.db.Create(&settings)
 
 
 
 
 
 
 
93
  }
94
- return &settings, nil
95
  }
96
 
97
  func (r *authRepository) SetRegistrationEnabled(enabled bool) error {
98
- var settings entity.Settings
99
- if err := r.db.First(&settings).Error; err != nil {
100
- settings = entity.Settings{ID: 1, RegistrationEnabled: enabled}
101
- return r.db.Create(&settings).Error
102
  }
103
- settings.RegistrationEnabled = enabled
104
- return r.db.Save(&settings).Error
 
 
 
 
 
 
 
 
 
 
 
105
  }
106
 
107
  func (r *authRepository) HasValidRefreshToken(userID uuid.UUID) (bool, error) {
 
18
  RevokeAllUserRefreshTokens(userID uuid.UUID) error
19
  UpdateUser(user *entity.User) error
20
  DeleteUser(id uuid.UUID) error
21
+ GetSetting(key string) (string, error)
22
  SetRegistrationEnabled(enabled bool) error
23
  HasValidRefreshToken(userID uuid.UUID) (bool, error)
24
  }
 
85
  return r.db.Delete(&entity.User{}, id).Error
86
  }
87
 
88
+ func (r *authRepository) GetSetting(key string) (string, error) {
89
+ var setting entity.Setting
90
+ if err := r.db.Where("key = ?", key).First(&setting).Error; err != nil {
91
+ if err == gorm.ErrRecordNotFound {
92
+ // Return default "true" for registration_enabled if not found, to match original default behavior?
93
+ // The original default was true in struct tag.
94
+ if key == "registration_enabled" {
95
+ return "true", nil
96
+ }
97
+ return "", nil
98
+ }
99
+ return "", err
100
  }
101
+ return setting.Value, nil
102
  }
103
 
104
  func (r *authRepository) SetRegistrationEnabled(enabled bool) error {
105
+ value := "true"
106
+ if !enabled {
107
+ value = "false"
 
108
  }
109
+
110
+ setting := entity.Setting{
111
+ Key: "registration_enabled",
112
+ Value: value,
113
+ }
114
+
115
+ // Upsert: On conflict update value
116
+ var count int64
117
+ r.db.Model(&entity.Setting{}).Where("key = ?", "registration_enabled").Count(&count)
118
+ if count > 0 {
119
+ return r.db.Model(&entity.Setting{}).Where("key = ?", "registration_enabled").Update("value", value).Error
120
+ }
121
+ return r.db.Create(&setting).Error
122
  }
123
 
124
  func (r *authRepository) HasValidRefreshToken(userID uuid.UUID) (bool, error) {
repositories/connection_repositories.go CHANGED
@@ -20,7 +20,7 @@ type ConnectionRepository interface {
20
  InitializeClient(ctx context.Context, accountID uuid.UUID) (*whatsmeow.Client, <-chan whatsmeow.QRChannelItem, error)
21
  UpdateAccountStatus(accountID uuid.UUID, jid string, isActive bool) error
22
  DeleteDevice(accountID uuid.UUID) error
23
- FindAccountByID(accountID uuid.UUID) (*entity.WhatsAppAccount, error)
24
  IsJIDUsedByOther(jid string, currentAccountID uuid.UUID) bool
25
  }
26
 
@@ -49,21 +49,18 @@ func NewConnectionRepository(db *gorm.DB) (ConnectionRepository, error) {
49
  }
50
 
51
  func (r *connectionRepository) InitializeClient(ctx context.Context, accountID uuid.UUID) (*whatsmeow.Client, <-chan whatsmeow.QRChannelItem, error) {
52
- var acc entity.WhatsAppAccount
53
 
54
- acc = entity.WhatsAppAccount{
55
- ID: accountID,
56
- AccountName: "Default Device",
57
- }
58
- if err := r.db.FirstOrCreate(&acc, entity.WhatsAppAccount{ID: accountID}).Error; err != nil {
59
- return nil, nil, http_error.ERR_DB_CONNECTION_FAILED
60
  }
61
 
62
  var deviceStore *store.Device
63
  var err error
64
 
65
- if acc.JID != "" {
66
- jid, parseErr := types.ParseJID(acc.JID)
67
  if parseErr != nil {
68
  return nil, nil, http_error.ERR_INVALID_JID
69
  }
@@ -88,20 +85,20 @@ func (r *connectionRepository) InitializeClient(ctx context.Context, accountID u
88
  }
89
 
90
  func (r *connectionRepository) UpdateAccountStatus(accountID uuid.UUID, jid string, isActive bool) error {
91
- return r.db.Model(&entity.WhatsAppAccount{ID: accountID}).Updates(map[string]interface{}{
92
  "jid": jid,
93
  "is_active": isActive,
94
  }).Error
95
  }
96
 
97
  func (r *connectionRepository) DeleteDevice(accountID uuid.UUID) error {
98
- var acc entity.WhatsAppAccount
99
- if err := r.db.First(&acc, accountID).Error; err != nil {
100
  return err
101
  }
102
 
103
- if acc.JID != "" {
104
- jid, _ := types.ParseJID(acc.JID)
105
  device, err := r.container.GetDevice(context.Background(), jid)
106
  if err == nil && device != nil {
107
  _ = device.Delete(context.Background())
@@ -111,17 +108,17 @@ func (r *connectionRepository) DeleteDevice(accountID uuid.UUID) error {
111
  return r.UpdateAccountStatus(accountID, "", false)
112
  }
113
 
114
- func (r *connectionRepository) FindAccountByID(accountID uuid.UUID) (*entity.WhatsAppAccount, error) {
115
- var acc entity.WhatsAppAccount
116
- if err := r.db.First(&acc, accountID).Error; err != nil {
117
  return nil, err
118
  }
119
- return &acc, nil
120
  }
121
 
122
  func (r *connectionRepository) IsJIDUsedByOther(jid string, currentAccountID uuid.UUID) bool {
123
  var count int64
124
- r.db.Model(&entity.WhatsAppAccount{}).
125
  Where("jid = ? AND id != ?", jid, currentAccountID).
126
  Count(&count)
127
  return count > 0
 
20
  InitializeClient(ctx context.Context, accountID uuid.UUID) (*whatsmeow.Client, <-chan whatsmeow.QRChannelItem, error)
21
  UpdateAccountStatus(accountID uuid.UUID, jid string, isActive bool) error
22
  DeleteDevice(accountID uuid.UUID) error
23
+ FindUserByID(accountID uuid.UUID) (*entity.User, error)
24
  IsJIDUsedByOther(jid string, currentAccountID uuid.UUID) bool
25
  }
26
 
 
49
  }
50
 
51
  func (r *connectionRepository) InitializeClient(ctx context.Context, accountID uuid.UUID) (*whatsmeow.Client, <-chan whatsmeow.QRChannelItem, error) {
52
+ var user entity.User
53
 
54
+ // Check if user exists. accountID should be userID.
55
+ if err := r.db.First(&user, accountID).Error; err != nil {
56
+ return nil, nil, http_error.ERR_DB_CONNECTION_FAILED // Or user not found
 
 
 
57
  }
58
 
59
  var deviceStore *store.Device
60
  var err error
61
 
62
+ if user.JID != "" {
63
+ jid, parseErr := types.ParseJID(user.JID)
64
  if parseErr != nil {
65
  return nil, nil, http_error.ERR_INVALID_JID
66
  }
 
85
  }
86
 
87
  func (r *connectionRepository) UpdateAccountStatus(accountID uuid.UUID, jid string, isActive bool) error {
88
+ return r.db.Model(&entity.User{ID: accountID}).Updates(map[string]interface{}{
89
  "jid": jid,
90
  "is_active": isActive,
91
  }).Error
92
  }
93
 
94
  func (r *connectionRepository) DeleteDevice(accountID uuid.UUID) error {
95
+ var user entity.User
96
+ if err := r.db.First(&user, accountID).Error; err != nil {
97
  return err
98
  }
99
 
100
+ if user.JID != "" {
101
+ jid, _ := types.ParseJID(user.JID)
102
  device, err := r.container.GetDevice(context.Background(), jid)
103
  if err == nil && device != nil {
104
  _ = device.Delete(context.Background())
 
108
  return r.UpdateAccountStatus(accountID, "", false)
109
  }
110
 
111
+ func (r *connectionRepository) FindUserByID(accountID uuid.UUID) (*entity.User, error) {
112
+ var user entity.User
113
+ if err := r.db.First(&user, accountID).Error; err != nil {
114
  return nil, err
115
  }
116
+ return &user, nil
117
  }
118
 
119
  func (r *connectionRepository) IsJIDUsedByOther(jid string, currentAccountID uuid.UUID) bool {
120
  var count int64
121
+ r.db.Model(&entity.User{}).
122
  Where("jid = ? AND id != ?", jid, currentAccountID).
123
  Count(&count)
124
  return count > 0
services/auth_service.go CHANGED
@@ -41,8 +41,8 @@ func NewAuthService(authRepo repositories.AuthRepository, connectionRepo reposit
41
 
42
  func (s *authService) Register(req dto.RegisterRequest) (*dto.AuthResponse, error) {
43
  // Check if registration is enabled
44
- settings, _ := s.authRepo.GetSettings()
45
- if settings != nil && !settings.RegistrationEnabled {
46
  return nil, http_error.ERR_REGISTRATION_DISABLED
47
  }
48
 
@@ -134,23 +134,19 @@ func (s *authService) GetMe(userID uuid.UUID) (*dto.MeResponse, error) {
134
  }
135
 
136
  resp := &dto.MeResponse{
137
- UserID: user.ID,
138
- Username: user.Username,
139
- Role: user.Role,
140
- }
141
-
142
- acc, err := s.connectionRepo.FindAccountByID(userID)
143
- if err == nil {
144
- resp.JID = acc.JID
145
- resp.AccountName = acc.AccountName
146
- resp.IsActive = acc.IsActive
147
-
148
- if acc.JID != "" {
149
- parts := strings.Split(acc.JID, "@")
150
- if len(parts) > 0 {
151
- phoneUtils := strings.Split(parts[0], ":")
152
- resp.Phone = phoneUtils[0]
153
- }
154
  }
155
  }
156
 
@@ -203,9 +199,9 @@ func (s *authService) AssignRole(userID uuid.UUID, role string) error {
203
  }
204
 
205
  func (s *authService) IsRegisterEnabled() bool {
206
- settings, _ := s.authRepo.GetSettings()
207
- if settings == nil {
208
- return true
209
  }
210
- return settings.RegistrationEnabled
211
  }
 
41
 
42
  func (s *authService) Register(req dto.RegisterRequest) (*dto.AuthResponse, error) {
43
  // Check if registration is enabled
44
+ val, _ := s.authRepo.GetSetting("registration_enabled")
45
+ if val == "false" {
46
  return nil, http_error.ERR_REGISTRATION_DISABLED
47
  }
48
 
 
134
  }
135
 
136
  resp := &dto.MeResponse{
137
+ UserID: user.ID,
138
+ Username: user.Username,
139
+ Role: user.Role,
140
+ JID: user.JID,
141
+ AccountName: user.AccountName,
142
+ IsActive: user.IsActive,
143
+ }
144
+
145
+ if user.JID != "" {
146
+ parts := strings.Split(user.JID, "@")
147
+ if len(parts) > 0 {
148
+ phoneUtils := strings.Split(parts[0], ":")
149
+ resp.Phone = phoneUtils[0]
 
 
 
 
150
  }
151
  }
152
 
 
199
  }
200
 
201
  func (s *authService) IsRegisterEnabled() bool {
202
+ val, err := s.authRepo.GetSetting("registration_enabled")
203
+ if err != nil {
204
+ return true // Default to true if error fetching, or maybe false? Staying with logic of previous implementation which defaulted to true implicitly if not set.
205
  }
206
+ return val == "true"
207
  }