cli.go
1 // SPDX-FileCopyrightText: Amolith <amolith@secluded.site> 2 // 3 // SPDX-License-Identifier: Apache-2.0 4 5 package main 6 7 import ( 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 18 var bmStrict = bluemonday.StrictPolicy() 19 20 // createUser is a CLI that creates a new user with the specified username 21 func createUser(dbConn *sql.DB, username string) { 22 fmt.Println("Creating user", username) 23 24 fmt.Print("Enter password: ") 25 password, err := term.ReadPassword(int(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(int(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 64 func 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 77 func 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. 98 func 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(int(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 }