Allow moderators to edit profiles, but don't show them the emails.
This commit is contained in:
parent
93ae21cee6
commit
f8a9909278
4 changed files with 70 additions and 48 deletions
|
|
@ -126,8 +126,11 @@ proc resetPassword(
|
|||
) {.async.} =
|
||||
# Gather some extra information to determine ident hash.
|
||||
let row = db.getRow(
|
||||
sql"select name, password, email, salt from person where email = ?",
|
||||
email
|
||||
sql"""
|
||||
select name, password, email, salt from person
|
||||
where email = ? or name = ?
|
||||
""",
|
||||
email, email
|
||||
)
|
||||
if row[0] == "":
|
||||
raise newForumError("Email not found", @["email"])
|
||||
|
|
@ -559,18 +562,22 @@ proc executeLogin(c: TForumData, username, password: string): string =
|
|||
|
||||
raise newForumError("Invalid username or password")
|
||||
|
||||
proc validateEmail(email: string, checkDuplicated: bool) =
|
||||
if not ('@' in email and '.' in email):
|
||||
raise newForumError("Invalid email", @["email"])
|
||||
if checkDuplicated:
|
||||
if getValue(
|
||||
db, sql"select email from person where email = ?", email
|
||||
).len > 0:
|
||||
raise newForumError("Email already exists", @["email"])
|
||||
|
||||
proc executeRegister(c: TForumData, name, pass, antibot, userIp,
|
||||
email: string): Future[string] {.async.} =
|
||||
## Registers a new user and returns a new session key for that user's
|
||||
## session if registration was successful. Exceptions are raised otherwise.
|
||||
|
||||
# email validation
|
||||
if not ('@' in email and '.' in email):
|
||||
raise newForumError("Invalid email", @["email"])
|
||||
if getValue(
|
||||
db, sql"select email from person where email = ?", email
|
||||
).len > 0:
|
||||
raise newForumError("Email already exists", @["email"])
|
||||
validateEmail(email, checkDuplicated=true)
|
||||
|
||||
# Username validation:
|
||||
if name.len == 0 or not allCharsInSet(name, UsernameIdent) or name.len > 20:
|
||||
|
|
@ -681,20 +688,31 @@ proc updateProfile(
|
|||
if c.username != username and c.rank < Moderator:
|
||||
raise newForumError("You can't change this profile.")
|
||||
|
||||
# Make sure the rank is set to EmailUnconfirmed when the email changes.
|
||||
if c.rank < Moderator:
|
||||
let row = getRow(
|
||||
# Check if we are only setting the rank.
|
||||
if email.len == 0:
|
||||
exec(
|
||||
db,
|
||||
sql"select name, password, email, salt from person where name = ?",
|
||||
username
|
||||
sql"update person set status = ? where name = ?;",
|
||||
$rank, username
|
||||
)
|
||||
if row[2] != email:
|
||||
if rank != EmailUnconfirmed:
|
||||
raise newForumError("Rank needs a change when setting new email.")
|
||||
return
|
||||
|
||||
await sendSecureEmail(
|
||||
mailer, ActivateEmail, c.req, row[0], row[1], row[2], row[3]
|
||||
)
|
||||
# Make sure the rank is set to EmailUnconfirmed when the email changes.
|
||||
let row = getRow(
|
||||
db,
|
||||
sql"select name, password, email, salt from person where name = ?",
|
||||
username
|
||||
)
|
||||
let wasEmailChanged = row[2] != email
|
||||
if c.rank < Moderator and wasEmailChanged:
|
||||
if rank != EmailUnconfirmed:
|
||||
raise newForumError("Rank needs a change when setting new email.")
|
||||
|
||||
await sendSecureEmail(
|
||||
mailer, ActivateEmail, c.req, row[0], row[1], row[2], row[3]
|
||||
)
|
||||
|
||||
validateEmail(email, checkDuplicated=wasEmailChanged)
|
||||
|
||||
exec(
|
||||
db,
|
||||
|
|
|
|||
|
|
@ -27,9 +27,9 @@ when defined(js):
|
|||
icon: icon
|
||||
)
|
||||
|
||||
proc newResetPasswordButton*(email: string): PostButton =
|
||||
proc newResetPasswordButton*(username: string): PostButton =
|
||||
var formData = newFormData()
|
||||
formData.append("email", email)
|
||||
formData.append("email", username)
|
||||
result = newPostButton(
|
||||
makeUri("/sendResetPassword"),
|
||||
formData,
|
||||
|
|
|
|||
|
|
@ -35,8 +35,7 @@ when defined(js):
|
|||
let profile = to(parsed, Profile)
|
||||
|
||||
state.profile = some(profile)
|
||||
if profile.email.isSome():
|
||||
state.settings = some(newProfileSettings(profile))
|
||||
state.settings = some(newProfileSettings(profile))
|
||||
|
||||
proc genPostLink(link: PostLink): VNode =
|
||||
let url = renderPostUrl(link)
|
||||
|
|
@ -106,7 +105,7 @@ when defined(js):
|
|||
|
||||
if currentUser.isSome():
|
||||
let user = currentUser.get()
|
||||
if user.name == profile.user.name or user.rank == Admin:
|
||||
if user.name == profile.user.name or user.rank >= Moderator:
|
||||
ul(class="tab"):
|
||||
li(class=class(
|
||||
{"active": state.currentTab == Overview},
|
||||
|
|
|
|||
|
|
@ -24,7 +24,9 @@ when defined(js):
|
|||
let profile = state.profile
|
||||
if profile.email.isSome():
|
||||
state.email = profile.email.get()
|
||||
state.rank = profile.user.rank
|
||||
else:
|
||||
state.email = ""
|
||||
state.rank = profile.user.rank
|
||||
|
||||
state.error = none[PostError]()
|
||||
|
||||
|
|
@ -32,7 +34,7 @@ when defined(js):
|
|||
result = ProfileSettings(
|
||||
status: Http200,
|
||||
deleteModal: newDeleteModal(nil, nil, onUserDelete),
|
||||
resetPassword: newResetPasswordButton(profile.email.get()),
|
||||
resetPassword: newResetPasswordButton(profile.user.name),
|
||||
profile: profile
|
||||
)
|
||||
resetSettings(result)
|
||||
|
|
@ -70,23 +72,25 @@ when defined(js):
|
|||
(s: int, r: kstring) => onProfilePost(s, r, state))
|
||||
|
||||
proc needsSave(state: ProfileSettings): bool =
|
||||
state.email != state.profile.email.get() or
|
||||
state.rank != state.profile.user.rank
|
||||
if state.profile.email.isSome():
|
||||
result = state.email != state.profile.email.get()
|
||||
result = result or state.rank != state.profile.user.rank
|
||||
|
||||
proc render*(state: ProfileSettings,
|
||||
currentUser: Option[User]): VNode =
|
||||
let isAdmin = currentUser.isSome() and currentUser.get().rank == Admin
|
||||
let canEditRank = currentUser.isSome() and
|
||||
currentUser.get().rank > state.profile.user.rank
|
||||
let canResetPassword = state.profile.user.rank > EmailUnconfirmed
|
||||
|
||||
let rankSelect = buildHtml(tdiv()):
|
||||
if isAdmin:
|
||||
if canEditRank:
|
||||
select(id="rank-field",
|
||||
class="form-select", value = $state.rank,
|
||||
onchange=(e: Event, n: VNode) => onRankChange(e, n, state)):
|
||||
for r in Rank:
|
||||
option(text $r)
|
||||
p(class="form-input-hint text-warning"):
|
||||
text "As an admin you can modify anyone's rank. Remember: with " &
|
||||
text "You can modify anyone's rank. Remember: with " &
|
||||
"great power comes great responsibility."
|
||||
else:
|
||||
input(id="rank-field", class="form-input",
|
||||
|
|
@ -125,23 +129,24 @@ when defined(js):
|
|||
p(class="form-input-hint"):
|
||||
text fmt("Users can refer to you by writing" &
|
||||
" @{state.profile.user.name} in their posts.")
|
||||
tdiv(class="form-group"):
|
||||
tdiv(class="col-3 col-sm-12"):
|
||||
label(class="form-label"):
|
||||
text "Email"
|
||||
tdiv(class="col-9 col-sm-12"):
|
||||
input(id="email-input", class="form-input",
|
||||
`type`="text", value=state.email,
|
||||
oninput=(e: Event, n: VNode) =>
|
||||
onEmailChange(e, n, state)
|
||||
)
|
||||
p(class="form-input-hint"):
|
||||
text "Your avatar is linked to this email and can be " &
|
||||
"changed at "
|
||||
a(href="https://gravatar.com/emails"):
|
||||
text "gravatar.com"
|
||||
text ". Note that any changes to your email will " &
|
||||
"require email verification."
|
||||
if state.profile.email.isSome():
|
||||
tdiv(class="form-group"):
|
||||
tdiv(class="col-3 col-sm-12"):
|
||||
label(class="form-label"):
|
||||
text "Email"
|
||||
tdiv(class="col-9 col-sm-12"):
|
||||
input(id="email-input", class="form-input",
|
||||
`type`="text", value=state.email,
|
||||
oninput=(e: Event, n: VNode) =>
|
||||
onEmailChange(e, n, state)
|
||||
)
|
||||
p(class="form-input-hint"):
|
||||
text "Your avatar is linked to this email and can be " &
|
||||
"changed at "
|
||||
a(href="https://gravatar.com/emails"):
|
||||
text "gravatar.com"
|
||||
text ". Note that any changes to your email will " &
|
||||
"require email verification."
|
||||
tdiv(class="form-group"):
|
||||
tdiv(class="col-3 col-sm-12"):
|
||||
label(class="form-label"):
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue