Add ability for a user to delete themselves

Adds user self delete
Adds confirmation of user deletion
This commit is contained in:
gildarts 2022-06-24 17:22:01 -04:00 committed by Simon Ser
parent c69ea81999
commit 0777ca0d29
2 changed files with 34 additions and 7 deletions

View File

@ -437,8 +437,10 @@ abbreviated form, for instance *network* can be abbreviated as *net* or just
user. user.
- The _-admin_ flag is only valid when updating another user. - The _-admin_ flag is only valid when updating another user.
*user delete* <username> *user delete* <username> [confirmation token]
Delete a soju user. Only admins can delete accounts. Delete a soju user.
Only admins can delete other users.
*server status* *server status*
Show some bouncer statistics. Only admins can query this information. Show some bouncer statistics. Only admins can query this information.

View File

@ -273,10 +273,9 @@ func init() {
handle: handleUserUpdate, handle: handleUserUpdate,
}, },
"delete": { "delete": {
usage: "<username>", usage: "<username> [confirmation token]",
desc: "delete a user", desc: "delete a user",
handle: handleUserDelete, handle: handleUserDelete,
admin: true,
}, },
}, },
}, },
@ -945,23 +944,49 @@ func handleUserUpdate(ctx context.Context, dc *downstreamConn, params []string)
} }
func handleUserDelete(ctx context.Context, dc *downstreamConn, params []string) error { func handleUserDelete(ctx context.Context, dc *downstreamConn, params []string) error {
if len(params) != 1 { if len(params) != 1 && len(params) != 2 {
return fmt.Errorf("expected exactly one argument") return fmt.Errorf("expected one or two arguments")
} }
username := params[0] username := params[0]
hashBytes := sha1.Sum([]byte(username))
hash := fmt.Sprintf("%x", hashBytes[0:3])
self := dc.user.Username == username
if !dc.user.Admin && !self {
return fmt.Errorf("only admins may delete other users")
}
u := dc.srv.getUser(username) u := dc.srv.getUser(username)
if u == nil { if u == nil {
return fmt.Errorf("unknown username %q", username) return fmt.Errorf("unknown username %q", username)
} }
if len(params) < 2 {
sendServicePRIVMSG(dc, fmt.Sprintf(`To confirm user deletion, send "user delete %s %s"`, username, hash))
return nil
}
if token := params[1]; token != hash {
return fmt.Errorf("provided confirmation token doesn't match user")
}
if self {
sendServicePRIVMSG(dc, fmt.Sprintf("Goodbye %s, deleting your account. There will be no further confirmation.", username))
ctx = context.TODO()
}
u.stop() u.stop()
if err := dc.srv.db.DeleteUser(ctx, u.ID); err != nil { if err := dc.srv.db.DeleteUser(ctx, u.ID); err != nil {
return fmt.Errorf("failed to delete user: %v", err) return fmt.Errorf("failed to delete user: %v", err)
} }
sendServicePRIVMSG(dc, fmt.Sprintf("deleted user %q", username)) if !self {
sendServicePRIVMSG(dc, fmt.Sprintf("deleted user %q", username))
}
return nil return nil
} }