package dbstore import ( "context" // Added for context propagation "database/sql" "errors" "fmt" "git.linuxforward.com/byop/byop-engine/models" "golang.org/x/crypto/bcrypt" ) // User operations func (s *SQLiteStore) CreateUser(ctx context.Context, user models.User) (int, error) { query := `INSERT INTO users (email, password, name, role, active) VALUES (?, ?, ?, ?, ?)` result, err := s.db.ExecContext(ctx, query, user.Email, user.Password, user.Name, user.Role, user.Active) if err != nil { // TODO: Consider checking for specific DB errors like unique constraint violations // and wrapping them in a custom error, e.g., models.NewErrConflict() return 0, err } id, err := result.LastInsertId() if err != nil { return 0, err } return int(id), nil } func (s *SQLiteStore) GetUserByEmail(ctx context.Context, email string) (models.User, error) { var user models.User query := `SELECT id, email, password, name, role, active, created_at, updated_at FROM users WHERE email = ?` fmt.Sprintf("Retrieving user with email: %s", email) err := s.db.QueryRowContext(ctx, query, email).Scan(&user.ID, &user.Email, &user.Password, &user.Name, &user.Role, &user.Active, &user.CreatedAt, &user.UpdatedAt) if err != nil { if errors.Is(err, sql.ErrNoRows) { return user, models.NewErrNotFound(fmt.Sprintf("user not found with email: %s", email), err) } return user, err } return user, nil } func (s *SQLiteStore) GetUsers(ctx context.Context) ([]*models.User, error) { query := `SELECT id, email, name, role, active, created_at, updated_at FROM users` rows, err := s.db.QueryContext(ctx, query) if err != nil { return nil, err } defer rows.Close() var users []*models.User for rows.Next() { var user models.User err := rows.Scan(&user.ID, &user.Email, &user.Name, &user.Role, &user.Active, &user.CreatedAt, &user.UpdatedAt) if err != nil { return nil, err // Error during row scan } users = append(users, &user) } if err = rows.Err(); err != nil { // Check for errors encountered during iteration return nil, err } return users, nil } // GetUserByID retrieves a user by ID func (s *SQLiteStore) GetUserByID(ctx context.Context, id int) (*models.User, error) { user := &models.User{} query := `SELECT id, email, password, name, role, active, created_at, updated_at FROM users WHERE id = ?` err := s.db.QueryRowContext(ctx, query, id).Scan(&user.ID, &user.Email, &user.Password, &user.Name, &user.Role, &user.Active, &user.CreatedAt, &user.UpdatedAt) if err != nil { if errors.Is(err, sql.ErrNoRows) { return nil, models.NewErrNotFound(fmt.Sprintf("user not found with id: %d", id), err) } return nil, err // Other error } return user, nil } // GetByUsername retrieves a user by username (assuming username is email as per original query) func (s *SQLiteStore) GetByUsername(ctx context.Context, username string) (*models.User, error) { user := &models.User{} query := `SELECT id, email, password, name, role, active, created_at, updated_at FROM users WHERE email = ?` err := s.db.QueryRowContext(ctx, query, username).Scan(&user.ID, &user.Email, &user.Password, &user.Name, &user.Role, &user.Active, &user.CreatedAt, &user.UpdatedAt) if err != nil { if errors.Is(err, sql.ErrNoRows) { return nil, models.NewErrNotFound(fmt.Sprintf("user not found with username: %s", username), err) } return nil, err } return user, nil } // UpdateUser updates an existing user func (s *SQLiteStore) UpdateUser(ctx context.Context, user *models.User) error { query := `UPDATE users SET email = ?, password = ?, name = ?, role = ?, active = ? WHERE id = ?` result, err := s.db.ExecContext(ctx, query, user.Email, user.Password, user.Name, user.Role, user.Active, user.ID) if err != nil { // TODO: Consider checking for specific DB errors like unique constraint violations return err } rowsAffected, err := result.RowsAffected() if err != nil { return err // Error retrieving RowsAffected } if rowsAffected == 0 { return models.NewErrNotFound(fmt.Sprintf("user not found with id: %d for update", user.ID), nil) // No underlying cause for not found here } return nil } // CreateDefaultAdmin creates a default admin user if none exists func (s *SQLiteStore) CreateDefaultAdmin(ctx context.Context) error { // Added context _, err := s.GetUserByEmail(ctx, "admin@byop.local") // Propagate context if err == nil { // Admin user already exists return nil } var targetNotFound *models.ErrNotFound if errors.As(err, &targetNotFound) { hashedPassword, hashErr := bcrypt.GenerateFromPassword([]byte("admin123"), bcrypt.DefaultCost) if hashErr != nil { return hashErr } admin := models.User{ Email: "admin@byop.local", Password: string(hashedPassword), Name: "Administrator", Role: "admin", Active: true, } _, createErr := s.CreateUser(ctx, admin) // Propagate context return createErr } else { return err } } func (s *SQLiteStore) DeleteUser(ctx context.Context, id int) error { query := `DELETE FROM users WHERE id = ?` result, err := s.db.ExecContext(ctx, query, id) if err != nil { return err } rowsAffected, err := result.RowsAffected() if err != nil { return err // Error retrieving RowsAffected } if rowsAffected == 0 { return models.NewErrNotFound(fmt.Sprintf("user not found with id: %d for deletion", id), nil) // No underlying cause for not found here } return nil }