diff --git a/backend/cmd/migrate/main.go b/backend/cmd/migrate/main.go index c8fda33..a1f3519 100644 --- a/backend/cmd/migrate/main.go +++ b/backend/cmd/migrate/main.go @@ -1,7 +1,8 @@ package main import ( - "database/sql" + "bufio" + "context" "fmt" "log" "os" @@ -9,9 +10,9 @@ import ( "fr.latosa-escrima/cmd/migrate/migrations" "fr.latosa-escrima/core" + "fr.latosa-escrima/core/models" + "fr.latosa-escrima/utils" "github.com/joho/godotenv" - "github.com/uptrace/bun/dialect/pgdialect" - "github.com/uptrace/bun/driver/pgdriver" "github.com/uptrace/bun/extra/bundebug" "github.com/uptrace/bun/migrate" @@ -42,8 +43,11 @@ func main() { Password: os.Getenv("POSTGRES_PASSWORD"), } fmt.Println(dsn.ToString()) - sqldb := sql.OpenDB(pgdriver.NewConnector(pgdriver.WithDSN(dsn.ToString()))) - db := bun.NewDB(sqldb, pgdialect.New()) + + db, err := core.InitDatabase(dsn) + if err != nil { + log.Fatal(err) + } db.AddQueryHook(bundebug.NewQueryHook(bundebug.WithVerbose(true))) @@ -62,6 +66,7 @@ func main() { Commands: []*cli.Command{ newDBCommand(migrate.NewMigrator(db, migrations.Migrations)), + newAdminCommand(db), }, } if err := app.Run(os.Args); err != nil { @@ -217,3 +222,138 @@ func newDBCommand(migrator *migrate.Migrator) *cli.Command { }, } } + +func newAdminCommand(db *bun.DB) *cli.Command { + return &cli.Command{ + Name: "admin", + Usage: "Creation of admin role and super user", + Subcommands: []*cli.Command{ + { + Name: "new", + Usage: "Creates a new admin user.", + Action: func(c *cli.Context) error { + ctx := context.Background() + + /* CREATING ADMIN ROLE */ + role := models.Role{ + Name: "Admin", + } + res, err := db. + NewInsert(). + Ignore(). + Model(&role). + Returning("id"). + Exec(ctx) + if err != nil { + return fmt.Errorf("failed to create admin role: %w", err) + } + fmt.Println("Admin role created successfully.") + rowsAffected, err := res.RowsAffected() + if err != nil { + return fmt.Errorf("failed to check rows affected: %w", err) + } + + // If no rows were affected, the role already exists, so query its id + if rowsAffected == 0 { + err = db.NewSelect(). + Model(&role). + Where("name = ?", role.Name). + Scan(ctx) + if err != nil { + return fmt.Errorf("failed to fetch existing role id: %w", err) + } + } + /**/ + // } + + /* CREATING ADMIN USER */ + // Prompt user for admin details + reader := bufio.NewReader(os.Stdin) + + fmt.Print("Enter first name: ") + firstName, _ := reader.ReadString('\n') + + fmt.Print("Enter last name: ") + lastName, _ := reader.ReadString('\n') + + fmt.Print("Enter email: ") + email, _ := reader.ReadString('\n') + + fmt.Print("Enter phone: ") + phone, _ := reader.ReadString('\n') + + fmt.Print("Enter password: ") + password, _ := reader.ReadString('\n') + + // Trim newline characters + firstName = strings.TrimSpace(firstName) + lastName = strings.TrimSpace(lastName) + email = strings.TrimSpace(email) + phone = strings.TrimSpace(phone) + password = strings.TrimSpace(password) + + // Hash the password + // Create admin user + admin := &models.User{ + FirstName: firstName, + LastName: lastName, + Email: email, + Password: password, + Phone: phone, + } + + // Insert into database + if _, err := admin.Insert(db, ctx); err != nil { + return fmt.Errorf("failed to create admin user: %w", err) + } + /**/ + + /* LINKING ADMIN USER TO ADMIN ROLE */ + userRole := models.UserToRole{ + UserID: admin.UserID, + RoleID: role.ID, + } + + if _, err := db. + NewInsert(). + Model(&userRole). + Ignore(). + Exec(ctx); err != nil { + return fmt.Errorf("failed to link user to ro admin role: %w", err) + } + /**/ + + /* LINKING ALL PERMISSIONS TO ADMIN ROLE */ + var permissions []*models.Permission + if err := db.NewSelect(). + Model(&permissions). + Scan(ctx); err != nil { + return fmt.Errorf("failed to gather all permissions: %w", err) + } + + permissionsToRole := utils.Map( + permissions, + func(permission *models.Permission) *models.PermissionToRole { + return &models.PermissionToRole{ + PermissionAction: permission.Action, + PermissionResource: permission.Resource, + RoleID: role.ID, + } + }) + + if _, err := db.NewInsert(). + Model(&permissionsToRole). + Ignore(). + Exec(ctx); err != nil { + return fmt.Errorf("failed to link every permission to admin role: %w", err) + } + + /**/ + + fmt.Println("Admin user created successfully.") + return nil + }, + }, + }, + } +} diff --git a/backend/core/models/users.go b/backend/core/models/users.go index 91fe42a..d34ae5c 100644 --- a/backend/core/models/users.go +++ b/backend/core/models/users.go @@ -32,10 +32,11 @@ type User struct { } func (u *User) Insert(db *bun.DB, ctx context.Context) (sql.Result, error) { - u.Password = fmt.Sprintf("crypt('%s', gen_salt('bf'))", u.Password) return db.NewInsert(). Model(u). - Value("password", u.Password). + Value("password", "crypt(?, gen_salt('bf'))", u.Password). + Ignore(). + // Returning("user_id"). Exec(ctx) }