mirror of
https://github.com/Eggbertx/gochan.git
synced 2025-09-13 09:26:23 -07:00
Add rank updating for admins
This commit is contained in:
parent
9f34be91d2
commit
478e8a1abe
4 changed files with 97 additions and 36 deletions
|
@ -77,7 +77,11 @@ func (s *Staff) ClearSessions() error {
|
|||
|
||||
if s.ID == 0 {
|
||||
// ID field not set, get it from the DB
|
||||
if err = QueryRowContextSQL(ctx, nil, query, []any{s.Username}, []any{&s.ID}); err != nil {
|
||||
err = QueryRowContextSQL(ctx, nil, query, []any{s.Username}, []any{&s.ID})
|
||||
if errors.Is(err, sql.ErrNoRows) {
|
||||
return ErrUnrecognizedUsername
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
@ -96,11 +100,29 @@ func (s *Staff) RankTitle() string {
|
|||
return ""
|
||||
}
|
||||
|
||||
// UpdateStaff sets the rank and password of the staff account with the given username
|
||||
func UpdateStaff(username string, rank int, password string) error {
|
||||
// first check if it's a recognized username
|
||||
id, err := GetStaffID(username)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
const sqlUpdate = `UPDATE DBPREFIXstaff SET global_rank = ?, password_checksum = ? WHERE id = ?`
|
||||
checksum := gcutil.BcryptSum(password)
|
||||
_, err = ExecTimeoutSQL(nil, sqlUpdate, rank, checksum, id)
|
||||
return err
|
||||
}
|
||||
|
||||
// UpdateStaff sets the password of the staff account with the given username
|
||||
func UpdatePassword(username string, newPassword string) error {
|
||||
const sqlUPDATE = `UPDATE DBPREFIXstaff SET password_checksum = ? WHERE username = ?`
|
||||
const sqlUPDATE = `UPDATE DBPREFIXstaff SET password_checksum = ? WHERE id = ?`
|
||||
id, err := GetStaffID(username)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
checksum := gcutil.BcryptSum(newPassword)
|
||||
|
||||
_, err := ExecTimeoutSQL(nil, sqlUPDATE, checksum, username)
|
||||
_, err = ExecTimeoutSQL(nil, sqlUPDATE, checksum, id)
|
||||
return err
|
||||
}
|
||||
|
||||
|
@ -147,11 +169,15 @@ func GetStaffUsernameFromID(id int) (string, error) {
|
|||
return username, err
|
||||
}
|
||||
|
||||
// GetStaffID gets the ID of the given staff, given the username, and returns ErrUnrecognizedUsername if none match
|
||||
func GetStaffID(username string) (int, error) {
|
||||
const query = `SELECT id FROM DBPREFIXstaff WHERE username = ?`
|
||||
const query = `SELECT id FROM DBPREFIXstaff WHERE username = ?`
|
||||
var id int
|
||||
|
||||
err := QueryRowTimeoutSQL(nil, query, []any{username}, []any{&id})
|
||||
if errors.Is(err, sql.ErrNoRows) {
|
||||
err = ErrUnrecognizedUsername
|
||||
}
|
||||
return id, err
|
||||
}
|
||||
|
||||
|
|
|
@ -21,7 +21,6 @@ import (
|
|||
)
|
||||
|
||||
var (
|
||||
ErrPasswordConfirm = errors.New("passwords do not match")
|
||||
ErrInsufficientPermission = errors.New("insufficient account permission")
|
||||
)
|
||||
|
||||
|
|
|
@ -17,6 +17,10 @@ import (
|
|||
"github.com/rs/zerolog"
|
||||
)
|
||||
|
||||
var (
|
||||
ErrPasswordsDoNotMatch = errors.New("passwords do not match")
|
||||
)
|
||||
|
||||
// manage actions that require at least janitor-level permission go here
|
||||
|
||||
func logoutCallback(writer http.ResponseWriter, request *http.Request, _ *gcsql.Staff, _ bool, _ *zerolog.Event, _ *zerolog.Event) (output interface{}, err error) {
|
||||
|
@ -116,7 +120,6 @@ func announcementsCallback(_ http.ResponseWriter, _ *http.Request, _ *gcsql.Staf
|
|||
}
|
||||
|
||||
func staffCallback(writer http.ResponseWriter, request *http.Request, staff *gcsql.Staff, wantsJSON bool, _ *zerolog.Event, errEv *zerolog.Event) (output interface{}, err error) {
|
||||
var outputStr string
|
||||
do := request.FormValue("do")
|
||||
allStaff, err := getAllStaffNopass(true)
|
||||
if wantsJSON {
|
||||
|
@ -130,16 +133,21 @@ func staffCallback(writer http.ResponseWriter, request *http.Request, staff *gcs
|
|||
err = errors.New("Error getting staff list: " + err.Error())
|
||||
return "", err
|
||||
}
|
||||
warnEv := gcutil.LogWarning().
|
||||
Str("IP", gcutil.GetRealIP(request)).
|
||||
Str("userAgent", request.UserAgent()).
|
||||
Str("staff", staff.Username)
|
||||
defer warnEv.Discard()
|
||||
|
||||
updateUsername := request.FormValue("update")
|
||||
username := request.FormValue("username")
|
||||
password := request.FormValue("password")
|
||||
username := request.PostFormValue("username")
|
||||
password := request.PostFormValue("password")
|
||||
passwordConfirm := request.FormValue("passwordconfirm")
|
||||
if (do == "add" || do == "update") && password != passwordConfirm {
|
||||
return "", ErrPasswordConfirm
|
||||
return "", ErrPasswordsDoNotMatch
|
||||
}
|
||||
|
||||
rankStr := request.FormValue("rank")
|
||||
rankStr := request.PostFormValue("rank")
|
||||
var rank int
|
||||
if rankStr != "" {
|
||||
if rank, err = strconv.Atoi(rankStr); err != nil {
|
||||
|
@ -149,11 +157,32 @@ func staffCallback(writer http.ResponseWriter, request *http.Request, staff *gcs
|
|||
}
|
||||
}
|
||||
|
||||
data := map[string]any{
|
||||
"do": do,
|
||||
"updateUsername": updateUsername,
|
||||
"allstaff": allStaff,
|
||||
"currentStaff": staff,
|
||||
}
|
||||
if updateUsername != "" && staff.Rank == AdminPerms {
|
||||
var found bool
|
||||
for _, user := range allStaff {
|
||||
if user.Username == updateUsername {
|
||||
data["updateRank"] = user.Rank
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
writer.WriteHeader(http.StatusBadRequest)
|
||||
errEv.Err(gcsql.ErrUnrecognizedUsername).Caller().Str("username", updateUsername).Send()
|
||||
return "", gcsql.ErrUnrecognizedUsername
|
||||
}
|
||||
}
|
||||
|
||||
if do == "add" {
|
||||
if staff.Rank < 3 {
|
||||
writer.WriteHeader(http.StatusUnauthorized)
|
||||
errEv.Err(ErrInsufficientPermission).Caller().
|
||||
Int("rank", staff.Rank).Send()
|
||||
warnEv.Caller().Str("username", username).Msg("non-admin tried to create a new account")
|
||||
return "", ErrInsufficientPermission
|
||||
}
|
||||
if _, err = gcsql.NewStaff(username, password, rank); err != nil {
|
||||
|
@ -168,8 +197,7 @@ func staffCallback(writer http.ResponseWriter, request *http.Request, staff *gcs
|
|||
} else if do == "del" && username != "" {
|
||||
if staff.Rank < 3 {
|
||||
writer.WriteHeader(http.StatusUnauthorized)
|
||||
errEv.Err(ErrInsufficientPermission).Caller().
|
||||
Int("rank", staff.Rank).Send()
|
||||
warnEv.Msg("non-admin tried to deactivate an account")
|
||||
return "", ErrInsufficientPermission
|
||||
}
|
||||
if err = gcsql.DeactivateStaff(username); err != nil {
|
||||
|
@ -180,40 +208,46 @@ func staffCallback(writer http.ResponseWriter, request *http.Request, staff *gcs
|
|||
username, staff.Username, err.Error())
|
||||
}
|
||||
} else if do == "update" && updateUsername != "" {
|
||||
if staff.Username != updateUsername && staff.Rank < 3 {
|
||||
if (staff.Username != updateUsername || rank > 0) && staff.Rank < 3 {
|
||||
writer.WriteHeader(http.StatusUnauthorized)
|
||||
errEv.Err(ErrInsufficientPermission).Caller().
|
||||
Int("rank", staff.Rank).Send()
|
||||
warnEv.Caller().Str("username", username).Msg("non-admin tried to modify a staff account's rank")
|
||||
return "", ErrInsufficientPermission
|
||||
}
|
||||
if err = gcsql.UpdatePassword(updateUsername, password); err != nil {
|
||||
if rank > 0 {
|
||||
err = gcsql.UpdateStaff(updateUsername, rank, password)
|
||||
} else {
|
||||
err = gcsql.UpdatePassword(updateUsername, password)
|
||||
}
|
||||
if err != nil {
|
||||
logRank := rank
|
||||
if logRank == 0 {
|
||||
// user does not have admin rank and is updating their own account
|
||||
logRank = staff.Rank
|
||||
}
|
||||
errEv.Err(err).Caller().
|
||||
Str("updateStaff", username).
|
||||
Msg("Error updating password")
|
||||
return "", err
|
||||
Int("updateRank", logRank).
|
||||
Msg("Error updating account")
|
||||
writer.WriteHeader(http.StatusInternalServerError)
|
||||
return "", errors.New("unable to update staff account")
|
||||
}
|
||||
}
|
||||
if do == "add" || do == "del" {
|
||||
} else if do == "add" || do == "del" {
|
||||
allStaff, err = getAllStaffNopass(true)
|
||||
if err != nil {
|
||||
errEv.Err(err).Caller().Msg("Error getting updated staff list")
|
||||
err = errors.New("Error getting updated staff list: " + err.Error())
|
||||
writer.WriteHeader(http.StatusInternalServerError)
|
||||
err = errors.New("Unable to get updated staff list")
|
||||
return "", err
|
||||
}
|
||||
}
|
||||
|
||||
staffBuffer := bytes.NewBufferString("")
|
||||
if err = serverutil.MinifyTemplate(gctemplates.ManageStaff, map[string]interface{}{
|
||||
"do": do,
|
||||
"updateUsername": updateUsername,
|
||||
"allstaff": allStaff,
|
||||
"currentStaff": staff,
|
||||
}, staffBuffer, "text/html"); err != nil {
|
||||
if err = serverutil.MinifyTemplate(gctemplates.ManageStaff, data, staffBuffer, "text/html"); err != nil {
|
||||
errEv.Err(err).Str("template", "manage_staff.html").Send()
|
||||
return "", errors.New("Error executing staff management page template: " + err.Error())
|
||||
writer.WriteHeader(http.StatusInternalServerError)
|
||||
return "", errors.New("Unable to execute staff management page template")
|
||||
}
|
||||
outputStr += staffBuffer.String()
|
||||
return outputStr, nil
|
||||
return staffBuffer.String(), nil
|
||||
}
|
||||
|
||||
func registerJanitorPages() {
|
||||
|
|
|
@ -32,12 +32,14 @@
|
|||
<tr><td>Username:</td><td><input id="username" name="username" type="text" value="{{if $isAdmin}}{{.updateUsername}}{{else}}{{.currentStaff.Username}}{{end}}" {{if not $showNewStaffForm}}disabled{{end}}/></td></tr>
|
||||
<tr><td>Password:</td><td><input id="password" name="password" type="password"/></td></tr>
|
||||
<tr><td>Confirm password:</td><td><input id="passwordconfirm" name="passwordconfirm" type="password"/></td></tr>
|
||||
{{if $showNewStaffForm -}}
|
||||
{{if $isAdmin -}}
|
||||
<tr><td>Rank:</td><td><select id="rank" name="rank">
|
||||
<option value="3">Admin</option>
|
||||
<option value="2">Moderator</option>
|
||||
<option value="1">Janitor</option>
|
||||
<option value="3"{{with .updateRank}}{{if eq $.updateRank 3}}selected="selected"{{end}}{{end}}>Admin</option>
|
||||
<option value="2"{{with .updateRank}}{{if eq $.updateRank 2}}selected="selected"{{end}}{{end}}>Moderator</option>
|
||||
<option value="1"{{with .updateRank}}{{if eq $.updateRank 1}}selected="selected"{{end}}{{end}}>Janitor</option>
|
||||
</select></td></tr>
|
||||
{{end -}}
|
||||
{{if $showNewStaffForm -}}
|
||||
<tr><td>
|
||||
<input type="hidden" name="do" value="add" />
|
||||
<input id="submitnewstaff" type="submit" value="Add" /></td></tr>
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue