commit d9931cead4e0921dbf398e93fe9386a8c7d9d33f
parent 0d200fe99df210a5b5db73df8f9dca16eaf3c391
Author: cblgh <cblgh@cblgh.org>
Date: Sun, 28 Jan 2024 14:15:24 +0100
go fmt
Diffstat:
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