| [b715712] | 1 | package main
|
|---|
| 2 |
|
|---|
| 3 | import (
|
|---|
| 4 | "crypto/sha256"
|
|---|
| 5 | "database/sql"
|
|---|
| 6 | "encoding/hex"
|
|---|
| 7 | "errors"
|
|---|
| 8 | "fmt"
|
|---|
| 9 | "strings"
|
|---|
| 10 |
|
|---|
| 11 | "bp_project/server/db"
|
|---|
| 12 | )
|
|---|
| 13 |
|
|---|
| 14 | func hashPassword(pw string) string {
|
|---|
| 15 | sum := sha256.Sum256([]byte(pw))
|
|---|
| 16 | return hex.EncodeToString(sum[:])
|
|---|
| 17 | }
|
|---|
| 18 |
|
|---|
| 19 | // Register - UC0001
|
|---|
| 20 | func Register() {
|
|---|
| 21 | fmt.Println("\n-- Register --")
|
|---|
| 22 | username := prompt("Username: ")
|
|---|
| 23 | email := prompt("Email: ")
|
|---|
| 24 | fullName := prompt("Full name: ")
|
|---|
| 25 | pw := prompt("Password (min 6 chars): ")
|
|---|
| 26 |
|
|---|
| 27 | if username == "" || email == "" || pw == "" {
|
|---|
| 28 | fmt.Println("Username, email and password are required.")
|
|---|
| 29 | return
|
|---|
| 30 | }
|
|---|
| 31 | if !strings.Contains(email, "@") {
|
|---|
| 32 | fmt.Println("Invalid email.")
|
|---|
| 33 | return
|
|---|
| 34 | }
|
|---|
| 35 | if len(pw) < 6 {
|
|---|
| 36 | fmt.Println("Password must be at least 6 characters.")
|
|---|
| 37 | return
|
|---|
| 38 | }
|
|---|
| 39 |
|
|---|
| 40 | var exists bool
|
|---|
| 41 | err := db.DB.QueryRow(
|
|---|
| 42 | `SELECT EXISTS(SELECT 1 FROM users WHERE username = $1 OR email = $2)`,
|
|---|
| 43 | username, email,
|
|---|
| 44 | ).Scan(&exists)
|
|---|
| 45 | if err != nil {
|
|---|
| 46 | fmt.Println("Database error:", err)
|
|---|
| 47 | return
|
|---|
| 48 | }
|
|---|
| 49 | if exists {
|
|---|
| 50 | fmt.Println("Username or email already taken.")
|
|---|
| 51 | return
|
|---|
| 52 | }
|
|---|
| 53 |
|
|---|
| 54 | _, err = db.DB.Exec(
|
|---|
| 55 | `INSERT INTO users (username, email, full_name, password_hash, available_balance)
|
|---|
| 56 | VALUES ($1, $2, $3, $4, 0)`,
|
|---|
| 57 | username, email, fullName, hashPassword(pw),
|
|---|
| 58 | )
|
|---|
| 59 | if err != nil {
|
|---|
| 60 | fmt.Println("Failed to register:", err)
|
|---|
| 61 | return
|
|---|
| 62 | }
|
|---|
| 63 | fmt.Println("Account created. You can now log in.")
|
|---|
| 64 | }
|
|---|
| 65 |
|
|---|
| 66 | // Login - UC0002
|
|---|
| 67 | func Login(s *Session) {
|
|---|
| 68 | fmt.Println("\n-- Login --")
|
|---|
| 69 | username := prompt("Username: ")
|
|---|
| 70 | pw := prompt("Password: ")
|
|---|
| 71 | if username == "" || pw == "" {
|
|---|
| 72 | fmt.Println("Username and password are required.")
|
|---|
| 73 | return
|
|---|
| 74 | }
|
|---|
| 75 |
|
|---|
| 76 | id, err := authenticate(username, pw)
|
|---|
| 77 | if err != nil {
|
|---|
| 78 | if errors.Is(err, errInvalidCreds) {
|
|---|
| 79 | fmt.Println("Invalid credentials.")
|
|---|
| 80 | return
|
|---|
| 81 | }
|
|---|
| 82 | fmt.Println("Login error:", err)
|
|---|
| 83 | return
|
|---|
| 84 | }
|
|---|
| 85 | s.UserID = id
|
|---|
| 86 | s.Username = username
|
|---|
| 87 | fmt.Println("Login successful.")
|
|---|
| 88 | }
|
|---|
| 89 |
|
|---|
| 90 | var errInvalidCreds = errors.New("invalid credentials")
|
|---|
| 91 |
|
|---|
| 92 | func authenticate(username, pw string) (string, error) {
|
|---|
| 93 | var id, stored string
|
|---|
| 94 | err := db.DB.QueryRow(
|
|---|
| 95 | `SELECT id, password_hash FROM users WHERE username = $1`,
|
|---|
| 96 | username,
|
|---|
| 97 | ).Scan(&id, &stored)
|
|---|
| 98 | if err == sql.ErrNoRows {
|
|---|
| 99 | return "", errInvalidCreds
|
|---|
| 100 | }
|
|---|
| 101 | if err != nil {
|
|---|
| 102 | return "", err
|
|---|
| 103 | }
|
|---|
| 104 | if stored != hashPassword(pw) {
|
|---|
| 105 | return "", errInvalidCreds
|
|---|
| 106 | }
|
|---|
| 107 | return id, nil
|
|---|
| 108 | }
|
|---|