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
26 password, err := term.ReadPassword(syscall.Stdin)
27 if err != nil {
28 fmt.Println("Error reading password:", err)
29 os.Exit(1)
30 }
31
32 fmt.Println()
33
34 fmt.Print("Confirm password: ")
35
36 passwordConfirmation, err := term.ReadPassword(syscall.Stdin)
37 if err != nil {
38 fmt.Println("Error reading password confirmation:", err)
39 os.Exit(1)
40 }
41
42 fmt.Println()
43
44 if string(password) != string(passwordConfirmation) {
45 fmt.Println("Passwords do not match")
46 os.Exit(1)
47 }
48
49 // Both frontend and backend need to sanitise the
50 // password the same way. This feel like a code
51 // smell; user creation should all be in the user
52 // package and the cli and frontend and API and
53 // everything should use that.
54 //
55 // TODO: Abstract this
56 sanitisedPassword := bmStrict.Sanitize(string(password))
57
58 err = users.Register(dbConn, username, sanitisedPassword)
59 if err != nil {
60 fmt.Println("Error creating user:", err)
61 os.Exit(1)
62 }
63
64 fmt.Println("\nUser", username, "created successfully")
65 os.Exit(0)
66}
67
68// deleteUser is a CLI that deletes a user with the specified username.
69func deleteUser(dbConn *sql.DB, username string) {
70 fmt.Println("Deleting user", username)
71
72 err := users.Delete(dbConn, username)
73 if err != nil {
74 fmt.Println("Error deleting user:", err)
75 os.Exit(1)
76 }
77
78 fmt.Printf("User %s deleted successfully\n", username)
79 os.Exit(0)
80}
81
82// listUsers is a CLI that lists all users in the database.
83func listUsers(dbConn *sql.DB) {
84 fmt.Println("Listing all users")
85
86 dbUsers, err := users.GetUsers(dbConn)
87 if err != nil {
88 fmt.Println("Error retrieving users from the database:", err)
89 os.Exit(1)
90 }
91
92 if len(dbUsers) == 0 {
93 fmt.Println("- No users found")
94 } else {
95 for _, u := range dbUsers {
96 fmt.Println("-", u)
97 }
98 }
99
100 os.Exit(0)
101}
102
103// checkAuthorised is a CLI that checks whether the provided user/password
104// combo is authorised.
105func checkAuthorised(dbConn *sql.DB, username string) {
106 fmt.Printf("Checking whether password for user %s is correct\n", username)
107
108 fmt.Print("Enter password: ")
109
110 password, err := term.ReadPassword(syscall.Stdin)
111 if err != nil {
112 fmt.Println("Error reading password:", err)
113 os.Exit(1)
114 }
115
116 fmt.Println()
117
118 // TODO: Abstract this, refer to note in createUser()
119 sanitisedPassword := bmStrict.Sanitize(string(password))
120
121 authorised, err := users.UserAuthorised(dbConn, username, sanitisedPassword)
122 if err != nil {
123 fmt.Println("Error checking authorisation:", err)
124 os.Exit(1)
125 }
126
127 if authorised {
128 fmt.Println("User is authorised")
129 } else {
130 fmt.Println("User is not authorised")
131 }
132
133 os.Exit(0)
134}