users.go 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  1. package dbstore
  2. import (
  3. "context" // Added for context propagation
  4. "database/sql"
  5. "errors"
  6. "fmt"
  7. "git.linuxforward.com/byop/byop-engine/models"
  8. "golang.org/x/crypto/bcrypt"
  9. )
  10. // User operations
  11. func (s *SQLiteStore) CreateUser(ctx context.Context, user models.User) (int, error) {
  12. query := `INSERT INTO users (email, password, name, role, active) VALUES (?, ?, ?, ?, ?)`
  13. result, err := s.db.ExecContext(ctx, query, user.Email, user.Password, user.Name, user.Role, user.Active)
  14. if err != nil {
  15. // TODO: Consider checking for specific DB errors like unique constraint violations
  16. // and wrapping them in a custom error, e.g., models.NewErrConflict()
  17. return 0, err
  18. }
  19. id, err := result.LastInsertId()
  20. if err != nil {
  21. return 0, err
  22. }
  23. return int(id), nil
  24. }
  25. func (s *SQLiteStore) GetUserByEmail(ctx context.Context, email string) (models.User, error) {
  26. var user models.User
  27. query := `SELECT id, email, password, name, role, active, created_at, updated_at FROM users WHERE email = ?`
  28. fmt.Sprintf("Retrieving user with email: %s", email)
  29. err := s.db.QueryRowContext(ctx, query, email).Scan(&user.ID, &user.Email, &user.Password, &user.Name, &user.Role, &user.Active, &user.CreatedAt, &user.UpdatedAt)
  30. if err != nil {
  31. if errors.Is(err, sql.ErrNoRows) {
  32. return user, models.NewErrNotFound(fmt.Sprintf("user not found with email: %s", email), err)
  33. }
  34. return user, err
  35. }
  36. return user, nil
  37. }
  38. func (s *SQLiteStore) GetUsers(ctx context.Context) ([]*models.User, error) {
  39. query := `SELECT id, email, name, role, active, created_at, updated_at FROM users`
  40. rows, err := s.db.QueryContext(ctx, query)
  41. if err != nil {
  42. return nil, err
  43. }
  44. defer rows.Close()
  45. var users []*models.User
  46. for rows.Next() {
  47. var user models.User
  48. err := rows.Scan(&user.ID, &user.Email, &user.Name, &user.Role, &user.Active, &user.CreatedAt, &user.UpdatedAt)
  49. if err != nil {
  50. return nil, err // Error during row scan
  51. }
  52. users = append(users, &user)
  53. }
  54. if err = rows.Err(); err != nil { // Check for errors encountered during iteration
  55. return nil, err
  56. }
  57. return users, nil
  58. }
  59. // GetUserByID retrieves a user by ID
  60. func (s *SQLiteStore) GetUserByID(ctx context.Context, id int) (*models.User, error) {
  61. user := &models.User{}
  62. query := `SELECT id, email, password, name, role, active, created_at, updated_at FROM users WHERE id = ?`
  63. err := s.db.QueryRowContext(ctx, query, id).Scan(&user.ID, &user.Email, &user.Password, &user.Name, &user.Role, &user.Active, &user.CreatedAt, &user.UpdatedAt)
  64. if err != nil {
  65. if errors.Is(err, sql.ErrNoRows) {
  66. return nil, models.NewErrNotFound(fmt.Sprintf("user not found with id: %d", id), err)
  67. }
  68. return nil, err // Other error
  69. }
  70. return user, nil
  71. }
  72. // GetByUsername retrieves a user by username (assuming username is email as per original query)
  73. func (s *SQLiteStore) GetByUsername(ctx context.Context, username string) (*models.User, error) {
  74. user := &models.User{}
  75. query := `SELECT id, email, password, name, role, active, created_at, updated_at FROM users WHERE email = ?`
  76. err := s.db.QueryRowContext(ctx, query, username).Scan(&user.ID, &user.Email, &user.Password, &user.Name, &user.Role, &user.Active, &user.CreatedAt, &user.UpdatedAt)
  77. if err != nil {
  78. if errors.Is(err, sql.ErrNoRows) {
  79. return nil, models.NewErrNotFound(fmt.Sprintf("user not found with username: %s", username), err)
  80. }
  81. return nil, err
  82. }
  83. return user, nil
  84. }
  85. // UpdateUser updates an existing user
  86. func (s *SQLiteStore) UpdateUser(ctx context.Context, user *models.User) error {
  87. query := `UPDATE users SET email = ?, password = ?, name = ?, role = ?, active = ? WHERE id = ?`
  88. result, err := s.db.ExecContext(ctx, query, user.Email, user.Password, user.Name, user.Role, user.Active, user.ID)
  89. if err != nil {
  90. // TODO: Consider checking for specific DB errors like unique constraint violations
  91. return err
  92. }
  93. rowsAffected, err := result.RowsAffected()
  94. if err != nil {
  95. return err // Error retrieving RowsAffected
  96. }
  97. if rowsAffected == 0 {
  98. return models.NewErrNotFound(fmt.Sprintf("user not found with id: %d for update", user.ID), nil) // No underlying cause for not found here
  99. }
  100. return nil
  101. }
  102. // CreateDefaultAdmin creates a default admin user if none exists
  103. func (s *SQLiteStore) CreateDefaultAdmin(ctx context.Context) error { // Added context
  104. _, err := s.GetUserByEmail(ctx, "admin@byop.local") // Propagate context
  105. if err == nil {
  106. // Admin user already exists
  107. return nil
  108. }
  109. var targetNotFound *models.ErrNotFound
  110. if errors.As(err, &targetNotFound) {
  111. hashedPassword, hashErr := bcrypt.GenerateFromPassword([]byte("admin123"), bcrypt.DefaultCost)
  112. if hashErr != nil {
  113. return hashErr
  114. }
  115. admin := models.User{
  116. Email: "admin@byop.local",
  117. Password: string(hashedPassword),
  118. Name: "Administrator",
  119. Role: "admin",
  120. Active: true,
  121. }
  122. _, createErr := s.CreateUser(ctx, admin) // Propagate context
  123. return createErr
  124. } else {
  125. return err
  126. }
  127. }
  128. func (s *SQLiteStore) DeleteUser(ctx context.Context, id int) error {
  129. query := `DELETE FROM users WHERE id = ?`
  130. result, err := s.db.ExecContext(ctx, query, id)
  131. if err != nil {
  132. return err
  133. }
  134. rowsAffected, err := result.RowsAffected()
  135. if err != nil {
  136. return err // Error retrieving RowsAffected
  137. }
  138. if rowsAffected == 0 {
  139. return models.NewErrNotFound(fmt.Sprintf("user not found with id: %d for deletion", id), nil) // No underlying cause for not found here
  140. }
  141. return nil
  142. }