123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158 |
- 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
- }
|