cerca

lean forum software (pmc local branch)
Log | Files | Refs | README | LICENSE

commit 87fa52bd7d03ff40b867d1fe8c522903226d4cdb
parent 391ef20c129638b3e67594f8182633120dea67de
Author: cblgh <cblgh@cblgh.org>
Date:   Fri, 15 Dec 2023 17:48:59 +0100

add system user CERCA_CMD for logging cmd admin actions on host

Diffstat:
Mcmd/add-admin/main.go | 13+++++++++++--
Mcmd/admin-add-user/main.go | 15+++++++++++++--
Mcmd/admin-reset/main.go | 38+++++++++++++++++++-------------------
Mdatabase/database.go | 30++++++++++++++++++++++--------
4 files changed, 65 insertions(+), 31 deletions(-)

diff --git a/cmd/add-admin/main.go b/cmd/add-admin/main.go @@ -2,6 +2,7 @@ package main import ( "cerca/database" + "cerca/constants" "flag" "fmt" "os" @@ -34,7 +35,7 @@ func main() { flag.Parse() usage := `usage - add-admin --username <username to make admin> --url <rool url to forum> + add-admin --username <username to make admin> --url <rool url to forum> --database ./data/forum.db add-admin --help for more information ` @@ -56,11 +57,19 @@ func main() { complain("username %s not in database", username) } inform("Attempting to make %s (id %d) admin...", username, userid) - // TODO (2023-12-12): log cmd actions just as admin web-actions are logged err = db.AddAdmin(userid) if err != nil { complain("Something went wrong: %s", err) } + + // log cmd actions just as admin web-actions are logged + systemUserid := db.GetSystemUserid() + err = db.AddModerationLog(systemUserid, userid, constants.MODLOG_ADMIN_MAKE) + if err != nil { + complain("adding mod log for adding new admin failed (%w)", err) + } + inform("Successfully added %s (id %d) as an admin", username, userid) inform("Please visit %s for all your administration needs (changing usernames, resetting passwords, deleting user accounts)", adminRoute) + inform("Admin action has been logged to /moderations") } diff --git a/cmd/admin-add-user/main.go b/cmd/admin-add-user/main.go @@ -3,6 +3,7 @@ package main import ( "cerca/crypto" "cerca/database" + "cerca/constants" "cerca/util" "flag" "fmt" @@ -10,6 +11,7 @@ import ( ) type UserInfo struct { + ID int Username, Password string } @@ -35,7 +37,7 @@ func createUser (username, password string, db *database.DB) UserInfo { if err = ed.Eout(err, "add registration"); err != nil { complain("Database had a problem saving user registration location") } - return UserInfo{Username: username, Password: password} + return UserInfo{ID: userID, Username: username, Password: password} } func inform(msg string, args ...interface{}) { @@ -79,8 +81,16 @@ func main() { } db := database.InitDB(dbPath) + newPassword := crypto.GeneratePassword() - _ = createUser(username, newPassword, &db) + userInfo := createUser(username, newPassword, &db) + + // log cmd actions just as admin web-actions are logged + systemUserid := db.GetSystemUserid() + err := db.AddModerationLog(systemUserid, userInfo.ID, constants.MODLOG_ADMIN_ADD_USER) + if err != nil { + complain("adding mod log for adding new user failed (%w)", err) + } loginRoute := fmt.Sprintf("%s/login", forumDomain) resetRoute := fmt.Sprintf("%s/reset", forumDomain) @@ -89,4 +99,5 @@ func main() { inform("[password]\n%s", newPassword) inform("Please login at %s\n", loginRoute) inform("After logging in, visit %s to reset your password", resetRoute) + inform("Admin action has been logged to /moderations") } diff --git a/cmd/admin-reset/main.go b/cmd/admin-reset/main.go @@ -2,7 +2,7 @@ package main import ( "cerca/database" - "cerca/util" + "cerca/constants" "flag" "fmt" "os" @@ -26,29 +26,18 @@ func complain(msg string, args ...interface{}) { } func main() { - var keypairFlag bool - var passwordFlag bool var username string var dbPath string flag.StringVar(&username, "username", "", "username whose credentials should be reset") flag.StringVar(&dbPath, "database", "./data/forum.db", "full path to the forum database; e.g. ./data/forum.db") - flag.BoolVar(&keypairFlag, "keypair", false, "reset the keypair") - flag.BoolVar(&passwordFlag, "password", false, "reset the password. if true generates a random new password") flag.Parse() usage := `usage - admin-reset --database ./data/forum.db --username <username to reset> [--keypair, --password] + admin-reset --database ./data/forum.db --username <username to reset> admin-reset --help for more information - examples: - # only reset the keypair, leaving the password intact - ./admin-reset --database ../../testdata/forum.db --username bambas --keypair - - # reset password only - ./admin-reset --database ../../testdata/forum.db --username bambas --password - - # reset both password and keypair - ./admin-reset --database ../../testdata/forum.db --username bambas --password --keypair + # example + ./admin-reset --database ../../testdata/forum.db --username bambas ` if username == "" { @@ -61,14 +50,25 @@ func main() { } db := database.InitDB(dbPath) - ed := util.Describe("admin reset") + + userid, err := db.GetUserID(username) + if err != nil { + complain("reset password failed (%w)", err) + } newPassword, err := db.ResetPassword(userid) - // TODO (2023-12-12): log cmd actions just as admin web-actions are logged if err != nil { complain("reset password failed (%w)", err) } - inform("successfully updated %s's password hash", username) - inform("new temporary password %s", newPassword) + // log cmd actions just as admin web-actions are logged + systemUserid := db.GetSystemUserid() + err = db.AddModerationLog(systemUserid, userid, constants.MODLOG_RESETPW) + if err != nil { + complain("adding mod log for password reset failed (%w)", err) + } + + inform("Successfully updated %s's password hash", username) + inform("New temporary password: %s", newPassword) + inform("Admin action has been logged to /moderations") } diff --git a/database/database.go b/database/database.go @@ -50,17 +50,21 @@ func InitDB(filepath string) DB { } const DELETED_USER_NAME = "deleted user" +const SYSTEM_USER_NAME = "CERCA_CMD" + func (d DB) makeSureDefaultUsersExist() { ed := util.Describe("create default users") - deletedUserExists, err := d.CheckUsernameExists(DELETED_USER_NAME) - if err != nil { - log.Fatalln(ed.Eout(err, "check username exists")) - } - if !deletedUserExists { - passwordHash, err := crypto.HashPassword(crypto.GeneratePassword()) - _, err = d.CreateUser(DELETED_USER_NAME, passwordHash) + for _, defaultUser := range []string{DELETED_USER_NAME, SYSTEM_USER_NAME} { + userExists, err := d.CheckUsernameExists(defaultUser) if err != nil { - log.Fatalln(ed.Eout(err, "create deleted user")) + log.Fatalln(ed.Eout(err, "check username for %s exists", defaultUser)) + } + if !userExists { + passwordHash, err := crypto.HashPassword(crypto.GeneratePassword()) + _, err = d.CreateUser(defaultUser, passwordHash) + if err != nil { + log.Fatalln(ed.Eout(err, "create %s", defaultUser)) + } } } } @@ -440,6 +444,16 @@ func (d DB) UpdateUserPasswordHash(userid int, newhash string) { // // the entry in registrations correlating to userid is removed +func (d DB) GetSystemUserid() int { + ed := util.Describe("get system user id") + systemUserid, err := d.GetUserID(SYSTEM_USER_NAME) + // it should always exist + if err != nil { + log.Fatalln(ed.Eout(err, "get system user id")) + } + return systemUserid +} + // if allowing deletion of post contents as well when removing account, // userid should be used to get all posts from table posts and change the contents // to say _deleted_