1// SPDX-FileCopyrightText: Amolith <amolith@secluded.site>
2//
3// SPDX-License-Identifier: Apache-2.0
4
5package main
6
7import (
8 "database/sql"
9 "fmt"
10 "os"
11 "syscall"
12
13 "git.sr.ht/~amolith/willow/users"
14 "github.com/microcosm-cc/bluemonday"
15 "golang.org/x/term"
16)
17
18var bmStrict = bluemonday.StrictPolicy()
19
20// createUser is a CLI that creates a new user with the specified username.
21func createUser(dbConn *sql.DB, username string) {
22 fmt.Println("Creating user", username)
23
24 fmt.Print("Enter password: ")
25 password, err := term.ReadPassword(syscall.Stdin)
26 if err != nil {
27 fmt.Println("Error reading password:", err)
28 os.Exit(1)
29 }
30 fmt.Println()
31
32 fmt.Print("Confirm password: ")
33 passwordConfirmation, err := term.ReadPassword(syscall.Stdin)
34 if err != nil {
35 fmt.Println("Error reading password confirmation:", err)
36 os.Exit(1)
37 }
38 fmt.Println()
39
40 if string(password) != string(passwordConfirmation) {
41 fmt.Println("Passwords do not match")
42 os.Exit(1)
43 }
44
45 // Both frontend and backend need to sanitise the
46 // password the same way. This feel like a code
47 // smell; user creation should all be in the user
48 // package and the cli and frontend and API and
49 // everything should use that.
50 //
51 // TODO: Abstract this
52 sanitisedPassword := bmStrict.Sanitize(string(password))
53 err = users.Register(dbConn, username, sanitisedPassword)
54 if err != nil {
55 fmt.Println("Error creating user:", err)
56 os.Exit(1)
57 }
58
59 fmt.Println("\nUser", username, "created successfully")
60 os.Exit(0)
61}
62
63// deleteUser is a CLI that deletes a user with the specified username.
64func deleteUser(dbConn *sql.DB, username string) {
65 fmt.Println("Deleting user", username)
66 err := users.Delete(dbConn, username)
67 if err != nil {
68 fmt.Println("Error deleting user:", err)
69 os.Exit(1)
70 }
71
72 fmt.Printf("User %s deleted successfully\n", username)
73 os.Exit(0)
74}
75
76// listUsers is a CLI that lists all users in the database.
77func listUsers(dbConn *sql.DB) {
78 fmt.Println("Listing all users")
79
80 dbUsers, err := users.GetUsers(dbConn)
81 if err != nil {
82 fmt.Println("Error retrieving users from the database:", err)
83 os.Exit(1)
84 }
85
86 if len(dbUsers) == 0 {
87 fmt.Println("- No users found")
88 } else {
89 for _, u := range dbUsers {
90 fmt.Println("-", u)
91 }
92 }
93 os.Exit(0)
94}
95
96// checkAuthorised is a CLI that checks whether the provided user/password
97// combo is authorised.
98func checkAuthorised(dbConn *sql.DB, username string) {
99 fmt.Printf("Checking whether password for user %s is correct\n", username)
100
101 fmt.Print("Enter password: ")
102 password, err := term.ReadPassword(syscall.Stdin)
103 if err != nil {
104 fmt.Println("Error reading password:", err)
105 os.Exit(1)
106 }
107 fmt.Println()
108
109 // TODO: Abstract this, refer to note in createUser()
110 sanitisedPassword := bmStrict.Sanitize(string(password))
111 authorised, err := users.UserAuthorised(dbConn, username, sanitisedPassword)
112 if err != nil {
113 fmt.Println("Error checking authorisation:", err)
114 os.Exit(1)
115 }
116
117 if authorised {
118 fmt.Println("User is authorised")
119 } else {
120 fmt.Println("User is not authorised")
121 }
122 os.Exit(0)
123}