cerca

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

commit d9931cead4e0921dbf398e93fe9386a8c7d9d33f
parent 0d200fe99df210a5b5db73df8f9dca16eaf3c391
Author: cblgh <cblgh@cblgh.org>
Date:   Sun, 28 Jan 2024 14:15:24 +0100

go fmt

Diffstat:
Mcmd/add-admin/main.go | 2+-
Mcmd/admin-add-user/main.go | 6+++---
Mcmd/admin-reset/main.go | 2+-
Mcmd/migration-tool/main.go | 3+--
Mconstants/constants.go | 13+++++++------
Mdatabase/database.go | 39+++++++++++++++++++--------------------
Mdatabase/migrations.go | 35+++++++++++++++++++----------------
Mdatabase/moderation.go | 44++++++++++++++++++++++----------------------
Mhtml/html.go | 1+
Mi18n/i18n.go | 140+++++++++++++++++++++++++++++++++++++++----------------------------------------
Mserver/moderation.go | 44++++++++++++++++++++++----------------------
Mserver/server.go | 10+++++-----
12 files changed, 170 insertions(+), 169 deletions(-)

diff --git a/cmd/add-admin/main.go b/cmd/add-admin/main.go @@ -1,8 +1,8 @@ package main import ( - "cerca/database" "cerca/constants" + "cerca/database" "flag" "fmt" "os" diff --git a/cmd/admin-add-user/main.go b/cmd/admin-add-user/main.go @@ -1,9 +1,9 @@ package main import ( + "cerca/constants" "cerca/crypto" "cerca/database" - "cerca/constants" "cerca/util" "flag" "fmt" @@ -11,11 +11,11 @@ import ( ) type UserInfo struct { - ID int + ID int Username, Password string } -func createUser (username, password string, db *database.DB) UserInfo { +func createUser(username, password string, db *database.DB) UserInfo { ed := util.Describe("admin reset") // make sure username is not registered already var err error diff --git a/cmd/admin-reset/main.go b/cmd/admin-reset/main.go @@ -1,8 +1,8 @@ package main import ( - "cerca/database" "cerca/constants" + "cerca/database" "flag" "fmt" "os" diff --git a/cmd/migration-tool/main.go b/cmd/migration-tool/main.go @@ -24,9 +24,8 @@ func complain(msg string, args ...interface{}) { os.Exit(0) } - func main() { - migrations := map[string]func(string) error {"2024-01-password-hash-migration": database.Migration20240116_PwhashChange} + migrations := map[string]func(string) error{"2024-01-password-hash-migration": database.Migration20240116_PwhashChange} var dbPath, migration string var listMigrations bool diff --git a/constants/constants.go b/constants/constants.go @@ -1,14 +1,15 @@ package constants + import "time" const ( - MODLOG_RESETPW = iota - MODLOG_ADMIN_VETO // vetoing a proposal - MODLOG_ADMIN_MAKE // make an admin - MODLOG_REMOVE_USER // remove a user + MODLOG_RESETPW = iota + MODLOG_ADMIN_VETO // vetoing a proposal + MODLOG_ADMIN_MAKE // make an admin + MODLOG_REMOVE_USER // remove a user MODLOG_ADMIN_ADD_USER // add a new user - MODLOG_ADMIN_DEMOTE // demote an admin back to a normal user - MODLOG_ADMIN_CONFIRM // confirming a proposal + MODLOG_ADMIN_DEMOTE // demote an admin back to a normal user + MODLOG_ADMIN_CONFIRM // confirming a proposal MODLOG_ADMIN_PROPOSE_DEMOTE_ADMIN MODLOG_ADMIN_PROPOSE_MAKE_ADMIN MODLOG_ADMIN_PROPOSE_REMOVE_USER diff --git a/database/database.go b/database/database.go @@ -1,9 +1,9 @@ package database import ( + "cerca/crypto" "context" "database/sql" - "cerca/crypto" "errors" "fmt" "log" @@ -89,7 +89,7 @@ func createTables(db *sql.DB) { id INTEGER PRIMARY KEY ); `, - /* add optional columns: quorumuser quorum_action (confirm, veto)? */ + /* add optional columns: quorumuser quorum_action (confirm, veto)? */ ` CREATE TABLE IF NOT EXISTS moderation_log ( id INTEGER PRIMARY KEY AUTOINCREMENT, @@ -102,7 +102,7 @@ func createTables(db *sql.DB) { FOREIGN KEY (recipientid) REFERENCES users(id) ); `, - ` + ` CREATE TABLE IF NOT EXISTS quorum_decisions ( userid INTEGER NOT NULL, decision BOOL NOT NULL, @@ -111,7 +111,7 @@ func createTables(db *sql.DB) { FOREIGN KEY (modlogid) REFERENCES moderation_log(id) ); `, - ` + ` CREATE TABLE IF NOT EXISTS moderation_proposals ( id INTEGER PRIMARY KEY AUTOINCREMENT, proposerid INTEGER NOT NULL, @@ -513,20 +513,19 @@ func (d DB) GetUsers(includeAdmin bool) []User { } func (d DB) ResetPassword(userid int) (string, error) { - ed := util.Describe("reset password") - exists, err := d.CheckUserExists(userid) - if !exists { - return "", errors.New(fmt.Sprintf("reset password: userid %d did not exist", userid)) - } else if err != nil { - return "", fmt.Errorf("reset password encountered an error (%w)", err) - } - // generate new password for user and set it in the database - newPassword := crypto.GeneratePassword() - passwordHash, err := crypto.HashPassword(newPassword) - if err != nil { - return "", ed.Eout(err, "hash password") - } - d.UpdateUserPasswordHash(userid, passwordHash) - return newPassword, nil + ed := util.Describe("reset password") + exists, err := d.CheckUserExists(userid) + if !exists { + return "", errors.New(fmt.Sprintf("reset password: userid %d did not exist", userid)) + } else if err != nil { + return "", fmt.Errorf("reset password encountered an error (%w)", err) + } + // generate new password for user and set it in the database + newPassword := crypto.GeneratePassword() + passwordHash, err := crypto.HashPassword(newPassword) + if err != nil { + return "", ed.Eout(err, "hash password") + } + d.UpdateUserPasswordHash(userid, passwordHash) + return newPassword, nil } - diff --git a/database/migrations.go b/database/migrations.go @@ -1,18 +1,19 @@ package database import ( - "encoding/base64" - "fmt" - "regexp" + "cerca/util" "context" "database/sql" - "strconv" - "log" + "encoding/base64" "errors" - "cerca/util" + "fmt" "github.com/matthewhartstonge/argon2" + "log" + "regexp" + "strconv" ) -/* switched argon2 library to support 32 bit due to flaw in previous library. + +/* switched argon2 library to support 32 bit due to flaw in previous library. * change occurred in commits: 68a689612547ff83225f9a2727cf0c14dfbf7ceb 27c6d5684b6b464b900889c4b8a4dbae232d6b68 @@ -20,7 +21,7 @@ import ( migration of the password hashes from synacor's embedded salt format to matthewartstonge's key-val embedded format - migration details: + migration details: the old format had the following default parameters: * time = 1 @@ -54,7 +55,7 @@ import ( \$argon2id19\$1,65536,4\$(\S{66}) diff regex from old to new $argon2id$v=19$m=65536,t=${1},p=4${passwordhash} - new format example value: + new format example value: $argon2id$v=19$m=65536,t=3,p=4$222222222222222222222222222222222222222222222222222222222222222222 */ @@ -74,7 +75,7 @@ func Migration20240116_PwhashChange(filepath string) (finalErr error) { HASH_INDEX ) - // regex to parse out: + // regex to parse out: // 1. time parameter // 2. salt // 3. hash @@ -104,9 +105,11 @@ func Migration20240116_PwhashChange(filepath string) (finalErr error) { err = row.Scan(&placeholder) // we *want* to have no rows if err != nil && !errors.Is(err, sql.ErrNoRows) { - if rollbackOnErr(err) { return } + if rollbackOnErr(err) { + return + } } - // in this migration, we should *not* have any schemaversion set + // in this migration, we should *not* have any schemaversion set if placeholder > 0 { if rollbackOnErr(errors.New("schemaversion existed! there's a high likelihood that this migration has already been performed - exiting")) { return @@ -116,10 +119,10 @@ func Migration20240116_PwhashChange(filepath string) (finalErr error) { // alright onwards to the beesknees // data struct to keep passwords and ids together - dont wanna mix things up now do we type HashRecord struct { - id int + id int oldFormat string // the full encoded format of prev library. including salt and parameters, not just the hash newFormat string // the full encoded format of new library. including salt and parameters, not just the hash - valid bool // only valid records will be updated (i.e. records whose format is confirmed by the the oldPattern regex) + valid bool // only valid records will be updated (i.e. records whose format is confirmed by the the oldPattern regex) } var records []HashRecord @@ -163,7 +166,7 @@ func Migration20240116_PwhashChange(filepath string) (finalErr error) { util.Check(err, "decode hash using old format encoding") config.TimeCost = uint32(time) // note this change, to match old time cost (necessary!) - raw := argon2.Raw{Config:config, Salt: saltBuf, Hash: hashBuf} + raw := argon2.Raw{Config: config, Salt: saltBuf, Hash: hashBuf} // this is what we will store in the database instead newFormatEncoded := raw.Encode() ok := newRegex.Match(newFormatEncoded) @@ -179,7 +182,7 @@ func Migration20240116_PwhashChange(filepath string) (finalErr error) { // (if it is, we'll just ignore it. but if it's not we error out of here) ok := newRegex.MatchString(records[i].oldFormat) if !ok { - // can't parse with regex matching old format or the new format + // can't parse with regex matching old format or the new format if rollbackOnErr(errors.New(fmt.Sprintf("unknown record format: %s", records[i].oldFormat))) { return } diff --git a/database/moderation.go b/database/moderation.go @@ -1,4 +1,5 @@ package database + import ( "context" "database/sql" @@ -7,11 +8,10 @@ import ( "log" "time" - "cerca/util" "cerca/constants" + "cerca/util" _ "github.com/mattn/go-sqlite3" - ) // there are a bunch of places that reference a user's id, so i don't want to break all of those @@ -20,14 +20,14 @@ import ( // // remove user performs the following operation: // 1. checks to see if the DELETED USER exists; otherwise create it and remember its id -// +// // 2. if it exists, we swap out the userid for the DELETED_USER in tables: // - table threads authorid // - table posts authorid // - table moderation_log actingid or recipientid -// +// // the entry in registrations correlating to userid is removed -// if allowing deletion of post contents as well when removing account, +// 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_ func (d DB) RemoveUser(userid int) (finalErr error) { @@ -40,7 +40,7 @@ func (d DB) RemoveUser(userid int) (finalErr error) { } // create a transaction spanning all our removal-related ops tx, err := d.db.BeginTx(context.Background(), &sql.TxOptions{}) // proper tx options? - rollbackOnErr:= func(incomingErr error) bool { + rollbackOnErr := func(incomingErr error) bool { if incomingErr != nil { _ = tx.Rollback() log.Println(incomingErr, "rolling back") @@ -131,8 +131,8 @@ func (d DB) AddModerationLog(actingid, recipientid, action int) error { if recipientid > 0 { insert := `INSERT INTO moderation_log (actingid, recipientid, action, time) VALUES (?, ?, ?, ?)` _, err = d.Exec(insert, actingid, recipientid, action, t) - } else { - // we are not listing a recipient + } else { + // we are not listing a recipient insert := `INSERT INTO moderation_log (actingid, action, time) VALUES (?, ?, ?)` _, err = d.Exec(insert, actingid, action, t) } @@ -144,12 +144,12 @@ func (d DB) AddModerationLog(actingid, recipientid, action int) error { type ModerationEntry struct { ActingUsername, RecipientUsername, QuorumUsername string - QuorumDecision bool - Action int - Time time.Time + QuorumDecision bool + Action int + Time time.Time } -func (d DB) GetModerationLogs () []ModerationEntry { +func (d DB) GetModerationLogs() []ModerationEntry { ed := util.Describe("moderation log") query := `SELECT uact.name, urecp.name, uquorum.name, q.decision, m.action, m.time FROM moderation_LOG m @@ -202,7 +202,7 @@ func (d DB) ProposeModerationAction(proposerid, recipientid, action int) (finalE tx, err := d.db.BeginTx(context.Background(), &sql.TxOptions{}) ed.Check(err, "open transaction") - rollbackOnErr:= func(incomingErr error) bool { + rollbackOnErr := func(incomingErr error) bool { if incomingErr != nil { _ = tx.Rollback() log.Println(incomingErr, "rolling back") @@ -236,7 +236,7 @@ func (d DB) ProposeModerationAction(proposerid, recipientid, action int) (finalE return } - // TODO (2023-12-18): hmm how do we do this properly now? only have one constant per action + // TODO (2023-12-18): hmm how do we do this properly now? only have one constant per action // {demote, make admin, remove user} but vary translations for these three depending on if there is also a decision or not? // add moderation log that user x proposed action y for recipient z @@ -257,9 +257,9 @@ func (d DB) ProposeModerationAction(proposerid, recipientid, action int) (finalE type ModProposal struct { ActingUsername, RecipientUsername string - ActingID, RecipientID int - ProposalID, Action int - Time time.Time + ActingID, RecipientID int + ProposalID, Action int + Time time.Time } func (d DB) GetProposedActions() []ModProposal { @@ -295,7 +295,7 @@ func (d DB) FinalizeProposedAction(proposalid, adminid int, decision bool) (fina tx, err := d.db.BeginTx(context.Background(), &sql.TxOptions{}) ed.Check(err, "open transaction") - rollbackOnErr:= func(incomingErr error) bool { + rollbackOnErr := func(incomingErr error) bool { if incomingErr != nil { _ = tx.Rollback() log.Println(incomingErr, "rolling back") @@ -363,7 +363,7 @@ func (d DB) FinalizeProposedAction(proposalid, adminid int, decision bool) (fina return } - // add moderation log + // add moderation log stmt, err = tx.Prepare(`INSERT INTO moderation_log (actingid, recipientid, action, time) VALUES (?, ?, ?, ?)`) defer stmt.Close() if rollbackOnErr(ed.Eout(err, "prepare modlog stmt")) { @@ -418,7 +418,7 @@ func (d DB) FinalizeProposedAction(proposalid, adminid int, decision bool) (fina type User struct { Name string - ID int + ID int } func (d DB) AddAdmin(userid int) error { @@ -475,12 +475,12 @@ func (d DB) DemoteAdmin(userid int) error { return nil } -func (d DB) IsUserAdmin (userid int) (bool, error) { +func (d DB) IsUserAdmin(userid int) (bool, error) { stmt := `SELECT 1 FROM admins WHERE id = ?` return d.existsQuery(stmt, userid) } -func (d DB) QuorumActivated () bool { +func (d DB) QuorumActivated() bool { admins := d.GetAdmins() return len(admins) >= 2 } diff --git a/html/html.go b/html/html.go @@ -3,5 +3,6 @@ package html import "embed" // Templates contain the raw HTML of all of our templates. +// //go:embed *.html var Templates embed.FS diff --git a/i18n/i18n.go b/i18n/i18n.go @@ -27,61 +27,59 @@ var English = map[string]string{ "SortRecentPosts": "recent posts", "SortRecentThreads": "most recent threads", - "modlogResetPassword": `<code>{{ .Data.Time }}</code> <b>{{ .Data.ActingUsername }}</b> reset a user's password`, - "modlogResetPasswordAdmin": `<code>{{ .Data.Time }}</code> <b>{{ .Data.ActingUsername }}</b> reset <b> {{ .Data.RecipientUsername}}</b>'s password`, - "modlogRemoveUser": `<code>{{ .Data.Time }}</code> <b>{{ .Data.ActingUsername }}</b> removed a user's account`, - "modlogMakeAdmin": `<code>{{ .Data.Time }}</code> <b>{{ .Data.ActingUsername }}</b> made <b> {{ .Data.RecipientUsername}}</b> an admin`, - "modlogAddUser": `<code>{{ .Data.Time }}</code> <b>{{ .Data.ActingUsername }}</b> manually registered an account for a new user`, - "modlogAddUserAdmin": `<code>{{ .Data.Time }}</code> <b>{{ .Data.ActingUsername }}</b> manually registered an account for <b> {{ .Data.RecipientUsername }}</b>`, - "modlogDemoteAdmin": `<code>{{ .Data.Time }}</code> <b>{{ .Data.ActingUsername }}</b> demoted <b> + "modlogResetPassword": `<code>{{ .Data.Time }}</code> <b>{{ .Data.ActingUsername }}</b> reset a user's password`, + "modlogResetPasswordAdmin": `<code>{{ .Data.Time }}</code> <b>{{ .Data.ActingUsername }}</b> reset <b> {{ .Data.RecipientUsername}}</b>'s password`, + "modlogRemoveUser": `<code>{{ .Data.Time }}</code> <b>{{ .Data.ActingUsername }}</b> removed a user's account`, + "modlogMakeAdmin": `<code>{{ .Data.Time }}</code> <b>{{ .Data.ActingUsername }}</b> made <b> {{ .Data.RecipientUsername}}</b> an admin`, + "modlogAddUser": `<code>{{ .Data.Time }}</code> <b>{{ .Data.ActingUsername }}</b> manually registered an account for a new user`, + "modlogAddUserAdmin": `<code>{{ .Data.Time }}</code> <b>{{ .Data.ActingUsername }}</b> manually registered an account for <b> {{ .Data.RecipientUsername }}</b>`, + "modlogDemoteAdmin": `<code>{{ .Data.Time }}</code> <b>{{ .Data.ActingUsername }}</b> demoted <b> {{ if eq .Data.ActingUsername .Data.RecipientUsername }} themselves {{ else }} {{ .Data.RecipientUsername}} {{ end }}</b> from admin back to normal user`, - "modlogXProposedY": `<code>{{ .Data.Time }}</code> <b>{{ .Data.ActingUsername }}</b> proposed: {{ .Data.Action }}`, - "modlogProposalMakeAdmin": `Make <b> {{ .Data.RecipientUsername}}</b> admin`, + "modlogXProposedY": `<code>{{ .Data.Time }}</code> <b>{{ .Data.ActingUsername }}</b> proposed: {{ .Data.Action }}`, + "modlogProposalMakeAdmin": `Make <b> {{ .Data.RecipientUsername}}</b> admin`, "modlogProposalDemoteAdmin": `Demote <b> {{ .Data.RecipientUsername}}</b> from role admin`, - "modlogProposalRemoveUser": `Remove user <b> {{ .Data.RecipientUsername }} </b>`, - "modlogConfirm": "{{ .Data.Action }} <i>confirmed by {{ .Data.ActingUsername }}</i>", - "modlogVeto": "<s>{{ .Data.Action }}</s> <i>vetoed by {{ .Data.ActingUsername }}</i>", - - - - "Admins": "admins", - "AdminVeto": "Veto", - "AdminConfirm": "Confirm", - "AdminForumAdministration": "Forum Administration", - "AdminYou": "you!", - "AdminUsers": "Users", - "AdminNoAdmins": "There are no admins", - "AdminNoUsers": "There are no other users", - "AdminNoPendingProposals": "There are no pending proposals", - "AdminAddNewUser": "Add new user", - "AdminAddNewUserQuestion": "Does someone wish attendence? You can ", - "AdminStepDown": "Step down", - "AdminStepDownExplanation": "If you want to stop being an admin, you can", - "AdminViewPastActions": "View past actions in the", - "ModerationLog": "moderation log", - "AdminDemote": "Demote", - "DeletedUser": "deleted user", - "RemoveAccount": "remove account", - "AdminMakeAdmin": "Make admin", - "Submit": "Submit", - "AdminSelfConfirmationsHover": "a week must pass before self-confirmations are ok", - "Proposal": "Proposal", - "PendingProposals": "Pending Proposals", + "modlogProposalRemoveUser": `Remove user <b> {{ .Data.RecipientUsername }} </b>`, + "modlogConfirm": "{{ .Data.Action }} <i>confirmed by {{ .Data.ActingUsername }}</i>", + "modlogVeto": "<s>{{ .Data.Action }}</s> <i>vetoed by {{ .Data.ActingUsername }}</i>", + + "Admins": "admins", + "AdminVeto": "Veto", + "AdminConfirm": "Confirm", + "AdminForumAdministration": "Forum Administration", + "AdminYou": "you!", + "AdminUsers": "Users", + "AdminNoAdmins": "There are no admins", + "AdminNoUsers": "There are no other users", + "AdminNoPendingProposals": "There are no pending proposals", + "AdminAddNewUser": "Add new user", + "AdminAddNewUserQuestion": "Does someone wish attendence? You can ", + "AdminStepDown": "Step down", + "AdminStepDownExplanation": "If you want to stop being an admin, you can", + "AdminViewPastActions": "View past actions in the", + "ModerationLog": "moderation log", + "AdminDemote": "Demote", + "DeletedUser": "deleted user", + "RemoveAccount": "remove account", + "AdminMakeAdmin": "Make admin", + "Submit": "Submit", + "AdminSelfConfirmationsHover": "a week must pass before self-confirmations are ok", + "Proposal": "Proposal", + "PendingProposals": "Pending Proposals", "AdminSelfProposalsBecomeValid": "Date self-proposals become valid", "AdminPendingExplanation": `Two admins are required for <i>making a user an admin</i>, <i>demoting an existing admin</i>, or <i>removing a user</i>. The first proposes the action, the second confirms (or vetos) it. If enough time elapses without a veto, the proposer may confirm their own proposal.`, - - "AdminAddUserExplanation": "Register a new user account. After registering the account you will be given a generated password and instructions to pass onto the user.", - "AdminForumHasAdmins": "The forum currently has the following admins", - "AdminOnlyLoggedInMayView": "Only logged in users may view the forum's admins.", + + "AdminAddUserExplanation": "Register a new user account. After registering the account you will be given a generated password and instructions to pass onto the user.", + "AdminForumHasAdmins": "The forum currently has the following admins", + "AdminOnlyLoggedInMayView": "Only logged in users may view the forum's admins.", "AdminPasswordSuccessInstructions": `Instructions: %s's password was set to: %s. After logging in, please change your password by going to /reset`, - "ModLogNoActions": "there are no logged moderation actions", - "ModLogExplanation": `This resource lists the moderation actions taken by the forum's administrators.`, - "ModLogExplanationAdmin": `You are viewing this page as an admin, you will see slightly more details.`, + "ModLogNoActions": "there are no logged moderation actions", + "ModLogExplanation": `This resource lists the moderation actions taken by the forum's administrators.`, + "ModLogExplanationAdmin": `You are viewing this page as an admin, you will see slightly more details.`, "ModLogOnlyLoggedInMayView": "Only logged in users may view the moderation log.", "LoginNoAccount": "Don't have an account yet? <a href='/register'>Register</a> one.", @@ -96,10 +94,10 @@ var English = map[string]string{ "PasswordMin": "Must be at least 9 characters long", "PasswordForgot": "Forgot your password?", - "Threads": "threads", - "ThreadNew": "new thread", - "ThreadThe": "the thread", - "Index": "index", + "Threads": "threads", + "ThreadNew": "new thread", + "ThreadThe": "the thread", + "Index": "index", "GoBackToTheThread": "Go back to the thread", "ThreadCreate": "Create thread", @@ -139,7 +137,7 @@ var English = map[string]string{ "PromptDeleteQuestion": "Delete post for all posterity?", "Delete": "delete", "Edit": "edit", - "EditedAt": "edited at", + "EditedAt": "edited at", "Post": "post", "Save": "Save", "Author": "Author", @@ -149,7 +147,7 @@ var English = map[string]string{ "AriaHome": "Home", "ThreadStartNew": "Start a new thread", - "RegisterHTMLMessage": `You now have an account! Welcome. Visit the <a href="/">index</a> to read and reply to threads, or start a new one.`, + "RegisterHTMLMessage": `You now have an account! Welcome. Visit the <a href="/">index</a> to read and reply to threads, or start a new one.`, "RegisterVerificationCode": "Your verification code is", "RegisterVerificationInstructionsTitle": "Verification instructions", @@ -157,8 +155,8 @@ var English = map[string]string{ "RegisterConductCodeBoxOne": `I have refreshed my memory of the <a target="_blank" href="{{ .Data.Link }}">{{ .Data.Name }} Code of Conduct</a>`, "RegisterConductCodeBoxTwo": `Yes, I have actually <a target="_blank" href="{{ .Data.Link }}">read it</a>`, - "NewPassword": "new password", - "ChangePassword": "change password", + "NewPassword": "new password", + "ChangePassword": "change password", } var Swedish = map[string]string{ @@ -190,10 +188,10 @@ var Swedish = map[string]string{ "PasswordMin": "Måste vara minst 9 karaktärer långt", "PasswordForgot": "Glömt lösenordet?", - "Threads": "trådar", - "ThreadNew": "ny tråd", - "ThreadThe": "tråden", - "Index": "index", + "Threads": "trådar", + "ThreadNew": "ny tråd", + "ThreadThe": "tråden", + "Index": "index", "GoBackToTheThread": "Go back to the thread", "ThreadCreate": "Skapa en tråd", @@ -238,7 +236,7 @@ var Swedish = map[string]string{ "AriaHome": "Hem", "ThreadStartNew": "Starta ny tråd", - "RegisterHTMLMessage": `Du har nu ett konto! Välkommen. Besök <a href="/">trådindexet</a> för att läsa och svara på trådar, eller för att starta en ny.`, + "RegisterHTMLMessage": `Du har nu ett konto! Välkommen. Besök <a href="/">trådindexet</a> för att läsa och svara på trådar, eller för att starta en ny.`, "RegisterVerificationCode": "Din verifikationskod är", "RegisterVerificationInstructionsTitle": "Verification instructions", @@ -246,10 +244,10 @@ var Swedish = map[string]string{ "RegisterConductCodeBoxOne": `I have refreshed my memory of the <a target="_blank" href="{{ .Data.Link }}">{{ .Data.Name }} Code of Conduct</a>`, "RegisterConductCodeBoxTwo": `Yes, I have actually <a target="_blank" href="{{ .Data.Link }}">read it</a>`, - "PasswordResetDescription": "På denna sida går vi igenom ett par steg för att säkert nollställa ditt lösenord—utan att behöva ta till mejl!", - "PasswordResetUsernameQuestion": "För de första: hur löd användarnamnet?", - "NewPassword": "nytt lösenord", - "ChangePassword": "ändra lösenord", + "PasswordResetDescription": "På denna sida går vi igenom ett par steg för att säkert nollställa ditt lösenord—utan att behöva ta till mejl!", + "PasswordResetUsernameQuestion": "För de första: hur löd användarnamnet?", + "NewPassword": "nytt lösenord", + "ChangePassword": "ändra lösenord", } var EspanolMexicano = map[string]string{ @@ -281,10 +279,10 @@ var EspanolMexicano = map[string]string{ "PasswordMin": "Debe tener por lo menos 9 caracteres.", "PasswordForgot": "Olvidaste tu contraseña?", - "Threads": "threads", - "ThreadNew": "new thread", - "ThreadThe": "the thread", - "Index": "index", + "Threads": "threads", + "ThreadNew": "new thread", + "ThreadThe": "the thread", + "Index": "index", "GoBackToTheThread": "Go back to the thread", "ThreadCreate": "Create thread", @@ -329,7 +327,7 @@ var EspanolMexicano = map[string]string{ "Responded": "responded", "YourAnswer": "Your answer", - "RegisterHTMLMessage": `You now have an account! Welcome. Visit the <a href="/">index</a> to read and reply to threads, or start a new one.`, + "RegisterHTMLMessage": `You now have an account! Welcome. Visit the <a href="/">index</a> to read and reply to threads, or start a new one.`, "RegisterVerificationCode": "Your verification code is", "RegisterVerificationInstructionsTitle": "Verification instructions", @@ -337,10 +335,10 @@ var EspanolMexicano = map[string]string{ "RegisterConductCodeBoxOne": `I have refreshed my memory of the <a target="_blank" href="{{ .Data.Link }}">{{ .Data.Name }} Code of Conduct</a>`, "RegisterConductCodeBoxTwo": `Yes, I have actually <a target="_blank" href="{{ .Data.Link }}">read it</a>`, - "PasswordResetDescription": "On this page we'll go through a few steps to securely reset your password—without resorting to any emails!", - "PasswordResetUsernameQuestion": "First up: what was your username?", - "NewPassword": "new password", - "ChangePassword": "change password", + "PasswordResetDescription": "On this page we'll go through a few steps to securely reset your password—without resorting to any emails!", + "PasswordResetUsernameQuestion": "First up: what was your username?", + "NewPassword": "new password", + "ChangePassword": "change password", } var translations = map[string]map[string]string{ diff --git a/server/moderation.go b/server/moderation.go @@ -3,22 +3,22 @@ package server import ( "fmt" "html/template" - "strconv" "net/http" + "strconv" "time" - "cerca/database" - "cerca/crypto" "cerca/constants" + "cerca/crypto" + "cerca/database" "cerca/i18n" "cerca/util" ) type AdminData struct { - Admins []database.User - Users []database.User + Admins []database.User + Users []database.User Proposals []PendingProposal - IsAdmin bool + IsAdmin bool } type ModerationData struct { @@ -28,9 +28,9 @@ type ModerationData struct { type PendingProposal struct { // ID is the id of the proposal ID, ProposerID int - Action string - Time time.Time // the time self-confirmations become possible for proposers - TimePassed bool // self-confirmations valid or not + Action string + Time time.Time // the time self-confirmations become possible for proposers + TimePassed bool // self-confirmations valid or not } func (h RequestHandler) displayErr(res http.ResponseWriter, req *http.Request, err error, title string) { @@ -45,10 +45,10 @@ func (h RequestHandler) displayErr(res http.ResponseWriter, req *http.Request, e func (h RequestHandler) displaySuccess(res http.ResponseWriter, req *http.Request, title, message, backRoute string) { data := GenericMessageData{ - Title: title, - Message: message, + Title: title, + Message: message, LinkText: h.translator.Translate("GoBack"), - Link: backRoute, + Link: backRoute, } h.renderGenericMessage(res, req, data) } @@ -90,7 +90,7 @@ func (h RequestHandler) IsAdmin(req *http.Request) (bool, int) { // note: there is only a 2-quorum constraint imposed if there are actually 2 admins. an admin may also confirm their own // proposal if constants.PROPOSAL_SELF_CONFIRMATION_WAIT seconds have passed (1 week) -func performQuorumCheck (ed util.ErrorDescriber, db *database.DB, adminUserId, targetUserId, proposedAction int) error { +func performQuorumCheck(ed util.ErrorDescriber, db *database.DB, adminUserId, targetUserId, proposedAction int) error { // checks if a quorum is necessary for the proposed action: if a quorum constarin is in effect, a proposal is created // otherwise (if no quorum threshold has been achieved) the action is taken directly quorumActivated := db.QuorumActivated() @@ -208,7 +208,7 @@ func (h *RequestHandler) AdminManualAddUserRoute(res http.ResponseWriter, req *h loggedIn, _ := h.IsLoggedIn(req) isAdmin, adminUserId := h.IsAdmin(req) - if !isAdmin { + if !isAdmin { IndexRedirect(res, req) return } @@ -228,7 +228,7 @@ func (h *RequestHandler) AdminManualAddUserRoute(res http.ResponseWriter, req *h if req.Method == "POST" && isAdmin { username := req.PostFormValue("username") - // do a lil quick checky check to see if we already have that username registered, + // do a lil quick checky check to see if we already have that username registered, // and if we do re-render the page with an error existed, err := h.db.CheckUsernameExists(username) ed.Check(err, "check username exists") @@ -325,9 +325,9 @@ func (h *RequestHandler) ModerationLogRoute(res http.ResponseWriter, req *http.R logs := h.db.GetModerationLogs() viewData := ModerationData{Log: make([]string, 0)} - type translationData struct { + type translationData struct { Time, ActingUsername, RecipientUsername string - Action template.HTML + Action template.HTML } for _, entry := range logs { @@ -371,16 +371,16 @@ func (h *RequestHandler) ModerationLogRoute(res http.ResponseWriter, req *http.R translationString = "modlogConfirm" if !entry.QuorumDecision { translationString = "modlogVeto" - } + } proposalString := h.translator.TranslateWithData(translationString, i18n.TranslationData{Data: propdata}) viewData.Log = append(viewData.Log, proposalString) /* rendering of "X proposed: <Y>" */ - } else if entry.Action == constants.MODLOG_ADMIN_PROPOSE_DEMOTE_ADMIN || + } else if entry.Action == constants.MODLOG_ADMIN_PROPOSE_DEMOTE_ADMIN || entry.Action == constants.MODLOG_ADMIN_PROPOSE_MAKE_ADMIN || entry.Action == constants.MODLOG_ADMIN_PROPOSE_REMOVE_USER { - propXforY := translationData{Time: tdata.Time, ActingUsername: tdata.ActingUsername, Action: template.HTML(actionString)} - proposalString := h.translator.TranslateWithData("modlogXProposedY", i18n.TranslationData{Data: propXforY}) - viewData.Log = append(viewData.Log, proposalString) + propXforY := translationData{Time: tdata.Time, ActingUsername: tdata.ActingUsername, Action: template.HTML(actionString)} + proposalString := h.translator.TranslateWithData("modlogXProposedY", i18n.TranslationData{Data: propXforY}) + viewData.Log = append(viewData.Log, proposalString) } else { viewData.Log = append(viewData.Log, actionString) } diff --git a/server/server.go b/server/server.go @@ -35,8 +35,8 @@ import ( type TemplateData struct { Data interface{} QuickNav bool - LoggedIn bool - IsAdmin bool + LoggedIn bool + IsAdmin bool HasRSS bool LoggedInID int ForumName string @@ -50,7 +50,7 @@ type PasswordResetData struct { } type ChangePasswordData struct { - Action string + Action string } type IndexData struct { @@ -285,9 +285,9 @@ func (h RequestHandler) renderGenericMessage(res http.ResponseWriter, req *http. Data: incomingData, // the following two fields are defaults that usually are not set and which are cumbersome to set each time since // they don't really matter / vary across invocations - HasRSS: h.config.RSS.URL != "", + HasRSS: h.config.RSS.URL != "", LoggedIn: loggedIn, - IsAdmin: isAdmin, + IsAdmin: isAdmin, } h.renderView(res, "generic-message", data) return