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}