#!/bin/sh
+# Copyright 2021 - 2024 Paul Hänsch
+#
+# Permission to use, copy, modify, and/or distribute this software for any
+# purpose with or without fee is hereby granted, provided that the above
+# copyright notice and this permission notice appear in all copies.
+#
+# THE SOFTWARE IS PROVIDED “AS IS” AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+# SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
+# IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
[ -n "$include_users" ] && return 0
include_users="$0"
. "${_EXEC}/cgilite/session.sh"
. "${_EXEC}/cgilite/storage.sh"
-USER_REGISTRATION="${USER_REGISTRATION:-true}"
-USER_REQUIREEMAIL="${USER_REQUIREEMAIL:-true}"
+SENDMAIL=${SENDMAIL-sendmail}
+
+USER_REGISTRATION="${USER_REGISTRATION-true}"
+USER_REQUIREEMAIL="${USER_REQUIREEMAIL-true}"
+USER_ACCOUNTPAGE="${USER_ACCOUNTPAGE}"
+
+USER_ACCOUNTEXPIRE="${USER_ACCOUNTEXPIRE:-$((86400 * 730))}"
+USER_CONFIRMEXPIRE="${USER_CONFIRMEXPIRE:-86400}"
+
+MAILFROM="${MAILDOMAIN-noreply@${HTTP_HOST%:*}}"
HTTP_HOST="$(HEADER Host)"
-MAILFROM="${MAILDOMAIN:-noreply@${HTTP_HOST%:*}}"
-user_db="${_DATA}/users.db"
-unset USER_ID USER_NAME USER_EMAIL
+[ "$HTTPS" ] && SCHEMA=https || SCHEMA=http
+
+# == FILE FORMAT ==
+# UID UNAME STATUS EMAIL PWSALT PWHASH EXPIRE DEVICES FUTUREUSE
+# (pending|active|deleted)
+
+# == GLOBALS ==
+UNSET_USER='unset \
+ USER_ID USER_NAME USER_STATUS USER_EMAIL USER_PWSALT USER_PWHASH \
+ USER_EXPIRE USER_DEVICES USER_FUTUREUSE
+'
+
+LOCAL_USER='local \
+ USER_ID USER_NAME USER_STATUS USER_EMAIL USER_PWSALT USER_PWHASH \
+ USER_EXPIRE USER_DEVICES USER_FUTUREUSE
+'
-# USER DB
-# UID UNAME STATUS (pending|active|deleted) EMAIL PWSALT PWHASH EXPIRE DEVICES FUTUREUSE
+# == TRANSLATIONS ==
+# override all functions marked with "TRANSLATION"
+# sed -n '/TRANSLATION$/,/^}/p;' <cgilite/users.sh
-user_init(){
- local user_id="$(SESSION_VAR user_id)"
- local UID UNAME STATUS EMAIL PWSALT PWHASH EXPIRE DEVICES FUTUREUSE
- [ "$user_id" ] \
- && read -r UID UNAME STATUS EMAIL PWSALT PWHASH EXPIRE DEVICES FUTUREUSE <<-EOF
- $(grep "^${user_id} " "$user_db")
+unset USER_IDMAP
+eval "$UNSET_USER"
+
+user_db="${user_db:-${_DATA}/users.db}"
+
+read_user() {
+ local user="$1"
+
+ # Global exports
+ USER_ID='' USER_NAME='' USER_STATUS='' USER_EMAIL='' USER_PWSALT=''
+ USER_PWHASH='' USER_EXPIRE='' USER_DEVICES='' USER_FUTUREUSE=''
+
+ if [ $# -eq 0 ]; then
+ read -r USER_ID USER_NAME USER_STATUS USER_EMAIL USER_PWSALT USER_PWHASH \
+ USER_EXPIRE USER_DEVICES USER_FUTUREUSE
+ elif [ "$user" -a -f "$user_db" -a -r "$user_db" ]; then
+ read -r USER_ID USER_NAME USER_STATUS USER_EMAIL USER_PWSALT USER_PWHASH \
+ USER_EXPIRE USER_DEVICES USER_FUTUREUSE <<-EOF
+ $(grep "^${user} " "${user_db}")
EOF
- [ "$STATUS" -a "$EXPIRE" ] \
- && if [ "$STATUS" = active -a "$EXPIRE" -gt "$_DATE" ]; then
- USER_ID="$UID"
- USER_NAME="$(UNSTRING "$UNAME")"
- USER_EMAIL="$(UNSTRING "$EMAIL")"
- fi
+ fi
+ if [ "$USER_ID" -a "${USER_EXPIRE:-0}" -gt "$_DATE" ]; then
+ USER_NAME="$(UNSTRING "$USER_NAME")"
+ USER_EMAIL="$(UNSTRING "$USER_EMAIL")"
+ USER_DEVICES="$(UNSTRING "$USER_DEVICES")"
+ unset USER_PWSALT USER_PWHASH
+ else
+ eval "$UNSET_USER"
+ return 1
+ fi
+}
+
+update_user() {
+ # internal function for user update
+ local uid="$1" uname status email pwsalt pwhash expire devices futureuse
+ local UID_ UNAME STATUS EMAIL PWSALT PWHASH EXPIRE DEVICES FUTUREUSE
+ local arg
+
+ for arg in "$@"; do case $arg in
+ uname=*) uname="${arg#*=}";;
+ status=*) status="${arg#*=}";;
+ email=*) email="${arg#*=}";;
+ password=*) pwsalt="$(randomid)"; pwhash="$(user_pwhash "$pwsalt" "${arg#*=}")";;
+ expire=*) expire="${arg#*=}";;
+ devices=*) devices="${arg#*=}";;
+ esac; done
+
+ if LOCK "$user_db"; then
+ while read -r UID_ UNAME STATUS EMAIL PWSALT PWHASH EXPIRE DEVICES \
+ FUTUREUSE; do
+ if [ "$UID_" = "$uid" ]; then
+ printf '%s %s %s %s %s %s %i %s %s\n' \
+ "$uid" "$(STRING "${uname-$(UNSTRING "$UNAME")}")" \
+ "${status:-${status-${STATUS}}${status+\\}}" \
+ "${email:-${email-${EMAIL}}${email+\\}}" \
+ "${pwsalt:-${PWSALT}}" "${pwhash:-${PWHASH}}" \
+ "${expire:-$((_DATE + USER_ACCOUNTEXPIRE))}" \
+ "$(STRING "${devices-$(UNSTRING "$DEVICES")}")" \
+ "${FUTUREUSE:-\\}"
+ elif [ "$STATUS" = pending -a ! "$EXPIRE" -ge "$_DATE" ]; then
+ # omit expired invitations from output
+ :
+ else
+ printf '%s %s %s %s %s %s %i %s %s\n' \
+ "$UID_" "$UNAME" "$STATUS" "$EMAIL" "$PWSALT" "$PWHASH" \
+ "$EXPIRE" "$DEVICES" "$FUTUREUSE"
+ fi
+ done <"$user_db" >"${user_db}.$$"
+ mv -- "${user_db}.$$" "$user_db"
+ RELEASE "$user_db"
+ else
+ return 1
+ fi
+}
+
+new_user(){
+ local user="${1:-$(timeid)}"
+ shift 1
+
+ if LOCK "$user_db"; then
+ if grep -q "^${user} " "$user_db"; then
+ RELEASE "$user_db"
+ return 1
+ fi
+ printf '%s \\ %s \\ \\ \\ %i \\ \\\n' \
+ "$user" "pending" "$(( _DATE + USER_CONFIRMEXPIRE ))" >>"$user_db"
+ else
+ return 1
+ fi
+
+ if [ $# -eq 0 ]; then
+ RELEASE "$user_db"
+ return 0
+ elif update_user "$user" "$@"; then
+ return 0
+ else
+ RELEASE "$user_db"
+ return 1
+ fi
+}
+
+user_idmap(){
+ local uid="$1" ret
+ eval "$LOCAL_USER"
+
+ if [ ! "$USER_IDMAP" ]; then
+ while read_user; do
+ USER_IDMAP="${USER_IDMAP}${USER_ID} ${USER_NAME}${BR}"
+ done <"$user_db"
+ fi
+ if [ "$uid" -a "$USER_IDMAP" != "${USER_IDMAP##*${uid} }" ]; then
+ ret="${USER_IDMAP##*${uid} }"; ret="${ret%%${BR}*}";
+ printf '%s\n' "$ret"
+ return 0
+ elif [ "$uid" ]; then
+ return 1
+ else
+ printf '%s' "$USER_IDMAP"
+ return 0
+ fi
+}
+
+user_idof(){
+ local name="$(STRING "$1")" ret
+ [ "$USER_IDMAP" ] || user_idmap >/dev/null
+
+ if [ "${name%\\}" -a "$USER_IDMAP" != "${USER_IDMAP% ${name}${BR}*}" ]; then
+ ret="${USER_IDMAP% ${name}${BR}*}"; ret="${ret##*${BR}}"
+ printf '%s\n' "$ret"
+ return 0
+ else
+ return 1
+ fi
}
user_checkname(){
user_nameexist(){
local uname="$(STRING "$1")"
- local UID UNAME STATUS EMAIL PWSALT PWHASH EXPIRE DEVICES FUTUREUSE
+ local UID_ UNAME STATUS EMAIL PWSALT PWHASH EXPIRE DEVICES FUTUREUSE
[ -f "$user_db" -a -r "$user_db" ] \
- && while read -r UID UNAME STATUS EMAIL PWSALT PWHASH EXPIRE DEVICES FUTUREUSE; do
+ && while read -r UID_ UNAME STATUS EMAIL PWSALT PWHASH EXPIRE DEVICES FUTUREUSE; do
[ "$EXPIRE" -gt "$_DATE" -a "$UNAME" = "$uname" ] && return 0
done <"$user_db"
return 1
user_emailexist(){
local email="$(STRING "$1")"
- local UID UNAME STATUS EMAIL PWSALT PWHASH EXPIRE DEVICES FUTUREUSE
+ local UID_ UNAME STATUS EMAIL PWSALT PWHASH EXPIRE DEVICES FUTUREUSE
[ -f "$user_db" -a -r "$user_db" ] \
- && while read -r UID UNAME STATUS EMAIL PWSALT PWHASH EXPIRE DEVICES FUTUREUSE; do
+ && while read -r UID_ UNAME STATUS EMAIL PWSALT PWHASH EXPIRE DEVICES FUTUREUSE; do
[ "$EXPIRE" -gt "$_DATE" -a "$EMAIL" = "$email" ] && return 0
done <"$user_db"
return 1
printf '%s\n' "${hash%% *}"
}
-user_register(){
- # reserve account, send registration mail
- # preliminary uid, expiration, signature
- local uid="$(timeid)"
- local uname="$(POST uname |user_checkname)"
- local email="$(POST email |user_checkemail)"
- local pwsalt="$(randomid)"
- local pw="$(POST pw |grep -m1 -xE '.{6,}' )" pwconfirm="$(POST pwconfirm)"
-
- if [ "$USER_REGISTRATION" != true ]; then
- REDIRECT "${_BASE}${PATH_INFO}#ERROR_REGISTRATION_DISABLED"
- fi
-
- if [ "$USER_REQUIREEMAIL" = true ]; then
- if [ ! "email" ]; then
- REDIRECT "${_BASE}${PATH_INFO}#ERROR_EMAIL_INVALID"
- elif user_emailexist "$email"; then
- REDIRECT "${_BASE}${PATH_INFO}#ERROR_EMAIL_EXISTS"
- elif LOCK "$user_db"; then
- printf '%s \\ pending %s \\ \\ %i \\ \\\n' \
- "$uid" "$(STRING "$email")" "$(( $_DATE + 86400 ))" \
- >>"$user_db"
- RELEASE "$user_db"
- sendmail -t -f "$MAILFROM" <<-EOF
+user_register_email() { # TRANSLATION
+ "$SENDMAIL" -t -f "$MAILFROM" <<-EOF
From: ${MAILFROM}
To: ${email}
Subject: Your account registration at ${HTTP_HOST%:*}
You can activate your account using this link:
- https://${HTTP_HOST%:*}/${_BASE}${PATH_INFO}?user_confirm=${uid}+$(session_mac "$uid")
+ ${SCHEMA}://${HTTP_HOST}${_BASE}${PATH_INFO}?user_confirm=${uid}+$(session_mac "$uid")
- This registration link will expire after 24 hours.
+ This registration link will expire after $((USER_CONFIRMEXPIRE / 3600)) hours.
If you did not request an account at ${HTTP_HOST%:*}, then someone else
probably entered your email address by accident. In this case you shoud
This is an automatic email. Any direct reply will not be received.
Your Account Registration Robot.
EOF
+}
+
+user_register(){
+ # reserve account, send registration mail
+ # preliminary uid, expiration, signature
+ local uid="$(timeid)"
+ local uname="$(POST uname |user_checkname)"
+ local email="$(POST email |user_checkemail)"
+ local pwsalt="$(randomid)"
+ local pw="$(POST pw |grep -m1 -xE '.{6,}' )" pwconfirm="$(POST pwconfirm)"
+
+ if [ "$USER_REGISTRATION" != true -a -s "$user_db" ]; then
+ REDIRECT "${_BASE}${PATH_INFO}#ERROR_REGISTRATION_DISABLED"
+ fi
+
+ if [ "$USER_REQUIREEMAIL" = true ]; then
+ if [ ! "email" ]; then
+ REDIRECT "${_BASE}${PATH_INFO}#ERROR_EMAIL_INVALID"
+ elif user_emailexist "$email"; then
+ REDIRECT "${_BASE}${PATH_INFO}#ERROR_EMAIL_EXISTS"
+ elif new_user "$uid" status=pending email="$email" expire="$((_DATE + USER_CONFIRMEXPIRE))"; then
+ debug "Sending Activation Link:" \
+ "${SCHEMA}://${HTTP_HOST}${_BASE}${PATH_INFO}?user_confirm=${uid}+$(session_mac "$uid")"
+ user_register_email
REDIRECT "${_BASE}${PATH_INFO}#USER_REGISTER_CONFIRM"
else
REDIRECT "${_BASE}${PATH_INFO}#ERROR_USER_NOLOCK"
REDIRECT "${_BASE}${PATH_INFO}#ERROR_PW_EMPTYTOOSHORT"
elif [ "$pw" != "$pwconfirm" ]; then
REDIRECT "${_BASE}${PATH_INFO}#ERROR_PW_MISMATCH"
- elif LOCK "$user_db"; then
- printf '%s %s active %s %s %s %i \\ \\\n' \
- "$uid" "$(STRING "$uname")" "$(STRING "$email")" \
- "$pwsalt" "$(user_pwhash "$pwsalt" "$pw")" \
- "$(( $_DATE + 86400 * 730 ))" \
- >>"$user_db"
- RELEASE "$user_db"
-
+ elif new_user "$uid" uname="$uname" status=active email="$email" password="$pw" expire="$((_DATE + USER_ACCOUNTEXPIRE))"; then
SESSION_COOKIE new
SESSION_BIND user_id "$uid"
- REDIRECT "${_BASE}${PATH_INFO}#USER_REGISTER_CONFIRM"
+ if [ "$USER_ACCOUNTPAGE" ]; then
+ REDIRECT "${USER_ACCOUNTPAGE}"
+ else
+ REDIRECT "${_BASE}${PATH_INFO}#USER_REGISTER_CONFIRM"
+ fi
else
REDIRECT "${_BASE}${PATH_INFO}#ERROR_USER_NOLOCK"
fi
fi
}
+user_invite_email(){ # TRANSLATION
+ "$SENDMAIL" -t -f "$MAILFROM" <<-EOF
+ From: ${MAILFROM}
+ To: ${email}
+ Subject: You have been invited to ${HTTP_HOST%:*}
+
+ ${USER_NAME:-Someone} has offered an invitation to this email address.
+
+ ${message}
+
+ You can create your account using this link:
+
+ ${SCHEMA}://${HTTP_HOST}${_BASE}${PATH_INFO}?user_confirm=${uid}+$(session_mac "$uid")
+
+ This registration link will expire after $((USER_CONFIRMEXPIRE / 3600)) hours.
+
+ If you do not know what this is about, then someone else probably
+ entered your email address by accident. In this case you shoud
+ simply ignore this message and we will remove your email address from
+ our database within the next day.
+
+ This is an automatic email. Any direct reply will not be received.
+ Your Account Registration Robot.
+ EOF
+}
+
+user_invite(){
+ local uid="$(timeid)"
+ local email="$(POST email |user_checkemail)"
+ local message="$(POST message)"
+
+ if [ ! "email" ]; then
+ REDIRECT "${_BASE}${PATH_INFO}#ERROR_EMAIL_INVALID"
+ elif user_emailexist "$email"; then
+ REDIRECT "${_BASE}${PATH_INFO}#ERROR_EMAIL_EXISTS"
+ elif new_user "$uid" status=pending email="$email" expire="$((_DATE + USER_CONFIRMEXPIRE))"; then
+ debug "Sending Invitation Link:" \
+ "${SCHEMA}://${HTTP_HOST}${_BASE}${PATH_INFO}?user_confirm=${uid}+$(session_mac "$uid")"
+ user_invite_email
+ REDIRECT "${_BASE}${PATH_INFO}#USER_REGISTER_CONFIRM"
+ else
+ REDIRECT "${_BASE}${PATH_INFO}#ERROR_USER_NOLOCK"
+ fi
+}
+
user_confirm(){
# enable account
- local UID UNAME STATUS EMAIL PWSALT PWHASH EXPIRE DEVICES FUTUREUSE
- local uid="$(POST uid |checkid)"
+ eval "$LOCAL_USER"
+ local uid="$(POST uid |checkid || printf invalid)"
local signature="$(POST signature)"
local uname="$(POST uname |user_checkname)"
local pwsalt="$(randomid)"
local pw="$(POST pw |grep -m1 -xE '.{6,}' )" pwconfirm="$(POST pwconfirm)"
+ read_user "${uid}"
+
if [ "$signature" != "$(session_mac "$uid")" ]; then
REDIRECT "${_BASE}${PATH_INFO}?${QUERY_STRING}#ERROR_LINK_INVALID"
elif [ ! "$uname" ]; then
REDIRECT "${_BASE}${PATH_INFO}?${QUERY_STRING}#ERROR_PW_EMPTYTOOSHORT"
elif [ "$pw" != "$pwconfirm" ]; then
REDIRECT "${_BASE}${PATH_INFO}?${QUERY_STRING}#ERROR_PW_MISMATCH"
- elif LOCK "$user_db"; then
- read -r UID UNAME STATUS EMAIL PWSALT PWHASH EXPIRE DEVICES FUTUREUSE <<-EOF
- $(grep "^${uid} " "$user_db")
- EOF
-
- if [ "$STATUS" != pending -o "$EXPIRE" -le "$_DATE" ]; then
- RELEASE "$user_db"
- REDIRECT "${_BASE}${PATH_INFO}?${QUERY_STRING}#ERROR_LINK_INVALID"
+ elif [ "$USER_STATUS" != pending -o \! "$USER_EXPIRE" -gt "$_DATE" ]; then
+ REDIRECT "${_BASE}${PATH_INFO}?${QUERY_STRING}#ERROR_LINK_INVALID"
+ elif update_user "$USER_ID" uname="$uname" status=active password="$pw"; then
+ SESSION_COOKIE new
+ SESSION_BIND user_id "$USER_ID"
+ if [ "$USER_ACCOUNTPAGE" ]; then
+ REDIRECT "${USER_ACCOUNTPAGE}"
else
- printf '%s %s active %s %s %s %i %s %s\n' \
- "$UID" "$(STRING "$uname")" "$EMAIL" \
- "$pwsalt" "$(user_pwhash "$pwsalt" "$pw")" \
- "$(( $_DATE + 86400 * 730 ))" "$DEVICES" "$FUTUREUSE" \
- >"${user_db}.$$"
- grep -v "^${uid} " "$user_db" >>"${user_db}.$$"
- mv "${user_db}.$$" "${user_db}"
- RELEASE "$user_db"
-
- SESSION_COOKIE new
- SESSION_BIND user_id "$UID"
- REDIRECT "${_BASE}${PATH_INFO}#USER_REGISTER_CONFIRM"
+ REDIRECT "${_BASE}${PATH_INFO}?user_register=confirm#USER_REGISTER_CONFIRM"
fi
else
REDIRECT "${_BASE}${PATH_INFO}#ERROR_USER_NOLOCK"
# set cookie
# keep logged in - device cookie?
# initialize new session!
- local UID UNAME STATUS EMAIL PWSALT PWHASH EXPIRE DEVICES FUTUREUSE
+ local UID_ UNAME STATUS EMAIL PWSALT PWHASH EXPIRE DEVICES FUTUREUSE
local uname="$(POST uname |STRING)" pw="$(POST pw)"
[ -f "$user_db" -a -r "$user_db" ] \
- && while read -r UID UNAME STATUS EMAIL PWSALT PWHASH EXPIRE DEVICES FUTUREUSE; do
+ && while read -r UID_ UNAME STATUS EMAIL PWSALT PWHASH EXPIRE DEVICES FUTUREUSE; do
if [ "$UNAME" = "$uname" -o "$EMAIL" = "$uname" ]; then
if [ "$STATUS" = active -a "$EXPIRE" -gt "$_DATE" -a "$PWHASH" = "$(user_pwhash "$PWSALT" "$pw")" ]; then
SESSION_COOKIE new
- SESSION_BIND user_id "$UID"
+ SESSION_BIND user_id "$UID_"
REDIRECT "${_BASE}${PATH_INFO}#USER_LOGGED_IN"
fi
fi
}
user_update(){
- # passphrase, email
- :
+ # todo: username update, email update / email confirm
+ local UID_ UNAME STATUS EMAIL PWSALT PWHASH EXPIRE DEVICES FUTUREUSE
+ # local uname="$(POST uname |STRING)"
+ local uid oldpw pw pwconfirm
+
+ uid="$(POST uid)"
+ oldpw="$(POST oldpw)"
+ pw="$(POST pw |grep -m1 -xE '.{6,}')"
+ pwconfirm="$(POST pwconfirm)"
+
+
+ read -r UID_ UNAME STATUS EMAIL PWSALT PWHASH EXPIRE DEVICES FUTUREUSE <<-EOF
+ $(grep "^${uid} " "$user_db")
+ EOF
+
+ if [ "$UID_" = "$USER_ID" -a "$PWHASH" = "$(user_pwhash "$PWSALT" "$oldpw")" ]; then
+ if [ "$pw" -a "$pw" = "$pwconfirm" ]; then
+ update_user "${uid}" password="$pw"
+ REDIRECT "${_BASE}${PATH_INFO}#UPDATE_SUCCESS"
+ else
+ REDIRECT "${_BASE}${PATH_INFO}#ERROR_PW_MISMATCH"
+ fi
+ elif [ "$UID_" = "$USER_ID" ]; then
+ REDIRECT "${_BASE}${PATH_INFO}#ERROR_INVALID_AUTH_PASSWORD"
+ else
+ REDIRECT "${_BASE}${PATH_INFO}#ERROR_NOTLOGGEDIN"
+ fi
}
+
user_recover(){
# send recover link
:
:
}
-user_init
+read_user "$(SESSION_VAR user_id)"
+[ "$USER_STATUS" -a "$USER_STATUS" != active ] && eval $UNSET_USER
[ "$REQUEST_METHOD" = POST ] && case "$(POST action)" in
user_register) user_register ;;
user_confirm) user_confirm ;;
+ user_invite) user_invite ;;
user_login) user_login ;;
user_logout) user_logout ;;
- user_update)
- :;;
+ user_update) user_update ;;
user_recover)
:;;
user_disable)
:;;
esac
-w_user_register(){
- if [ "$(GET user_confirm)" ]; then
- w_user_confirm
- elif [ "$USER_REGISTRATION" != true ]; then
+export USER_ID USER_NAME USER_STATUS USER_EMAIL USER_PWSALT USER_PWHASH \
+ USER_EXPIRE USER_DEVICES USER_FUTUREUSE
+
+
+w_user_update(){
+ if [ ! "$USER_ID" ]; then
cat <<-EOF
+ [div #user_update .nouser
+ This page can only be used by registered users
+ ]
+ EOF
+ else
+ cat <<-EOF
+ [form #user_update method=POST
+ [hidden "uid" "$USER_ID"]
+ [p .username Logged in as $USER_NAME]
+ [input type=password name=oldpw placeholder="Current Passphrase"]
+ [input type=password name=pw placeholder="New Passphrase" pattern=".{6,}"]
+ [input type=password name=pwconfirm placeholder="Confirm New Passphrase" pattern=".{6,}"]
+ [submit "action" "user_update" Update Passphrase]
+ ]
+ EOF
+ fi
+}
+
+w_user_register_disabled(){ # TRANSLATION
+ cat <<-EOF
[div #user_register .disabled
User Registration is disabled.
]
EOF
- elif [ "$USER_REQUIREEMAIL" = true ]; then
- cat <<-EOF
+}
+w_user_register_sendmail(){ # TRANSLATION
+ cat <<-EOF
[form #user_register .registeremail method=POST
[p We will send an activation mail to your email address.
You can continue the signup process when you click on the
[submit "action" "user_register" Sign Up]
]
EOF
- elif [ "$USER_REQUIREEMAIL" != true ]; then
- cat <<-EOF
+}
+w_user_register_direct(){ # TRANSLATION
+ cat <<-EOF
[form #user_register .registername method=POST
- [input name=uname placeholder="Choose Username" tooltip="Your username may contain any character but the @ sign. It must be at least 3 characters long, and it must start with a letter." pattern="^\[a-zA-Z\]\[a-zA-Z0-9 -~\]{2,127}$" autocomplete=off]
+ [input name=uname placeholder="Choose Username" tooltip="Your username may contain any character but the @ sign. It must be at least 3 characters long, and it must start with a letter." pattern="^\[\\\\p{L}\]\[\\\\p{L}0-9 -~\]{2,127}$" autocomplete=off]
[input type=password name=pw placeholder="Choose Passphrase" pattern=".{6,}"]
[input type=password name=pwconfirm placeholder="Confirm Passphrase" pattern=".{6,}"]
[submit "action" "user_register" Sign Up]
]
EOF
- fi
}
-w_user_confirm(){
- local UID UNAME STATUS EMAIL PWSALT PWHASH EXPIRE DEVICES FUTUREUSE
- local user_confirm="$(GET user_confirm)"
- local uid="${user_confirm% *}" signature="${user_confirm#* }"
+w_user_register(){
+ if [ "$(GET user_confirm)" ]; then
+ w_user_confirm
+ elif [ "$USER_REGISTRATION" != true -a -s "$user_db" ]; then
+ w_user_register_disabled
+ elif [ "$USER_REQUIREEMAIL" = true ]; then
+ w_user_register_sendmail
+ elif [ "$USER_REQUIREEMAIL" != true ]; then
+ w_user_register_direct
+ fi
+}
- if [ "$signature" = "$(session_mac "$uid")" ]; then
- read -r UID UNAME STATUS EMAIL PWSALT PWHASH EXPIRE DEVICES FUTUREUSE <<-EOF
- $(grep "^${uid} " "$user_db")
- EOF
- if [ "$STATUS" = pending -a "$EXPIRE" -gt "$_DATE" ]; then
- cat <<-EOF
+w_user_confirm_proceed(){ # TRANSLATION
+ cat <<-EOF
[form #user_confirm method=POST
[input type=hidden name=uid value="${uid}"]
[input type=hidden name=signature value="${signature}"]
- [input disabled=disabled value="$(HTML "$EMAIL")"]
- [input name=uname placeholder="Choose Username" tooltip="Your username may contain any character but the @ sign. It must be at least 3 characters long, and it must start with a letter." pattern="^\[a-zA-Z\]\[a-zA-Z0-9 -~\]{2,127}$" autocomplete=off]
+ $([ "$EMAIL" != '\' ] && printf \
+ '[input disabled=disabled value="%s" placeholder="Email"]' "$(UNSTRING "$EMAIL" |HTML)"
+ )
+ [input name=uname placeholder="Choose Username" tooltip="Your username may contain any character but the @ sign. It must be at least 3 characters long, and it must start with a letter." pattern="^\[\\\\p{L}\]\[\\\\p{L}0-9 -~\]{2,127}$" autocomplete=off]
[input type=password name=pw placeholder="Choose Passphrase" pattern=".{6,}"]
[input type=password name=pwconfirm placeholder="Confirm Passphrase" pattern=".{6,}"]
[submit "action" "user_confirm" Finish Registration]
]
EOF
- else
- cat <<-EOF
+}
+w_user_confirm_expired(){ # TRANSLATION
+ cat <<-EOF
[div #user_confirm .expired
[p This activation link is not valid anymore.]
]
EOF
- fi
- else
- cat <<-EOF
+}
+w_user_confirm_invalid(){ # TRANSLATION
+ cat <<-EOF
[div #user_confirm .invalid
[p This activation link is invalid. Make sure you copied the whole activation link from your email and be careful not to include any line breaks.]
]
EOF
+}
+
+w_user_confirm(){
+ local UID_ UNAME STATUS EMAIL PWSALT PWHASH EXPIRE DEVICES FUTUREUSE
+ local user_confirm="$(GET user_confirm)"
+ local uid="${user_confirm% *}" signature="${user_confirm#* }"
+
+ if [ "$signature" = "$(session_mac "$uid")" ]; then
+ read -r UID_ UNAME STATUS EMAIL PWSALT PWHASH EXPIRE DEVICES FUTUREUSE <<-EOF
+ $(grep "^${uid} " "$user_db")
+ EOF
+ if [ "$STATUS" = pending -a "$EXPIRE" -gt "$_DATE" ]; then
+ w_user_confirm_proceed
+ else
+ w_user_confirm_expired
+ fi
+ else
+ w_user_confirm_invalid
fi
}
-w_user_login(){
- if [ ! "$USER_ID" ]; then
- cat <<-EOF
+w_user_invite_email(){ # TRANSLATION
+ cat <<-EOF
+ [form #user_invite method=POST
+ [input placeholder="Email Recipient" name=email autocomplete=off]
+ [textarea name="message" placeholder="Message to recipient" . ]
+ [submit "action" "user_invite" Send Invitation]
+ ]
+ EOF
+}
+w_user_invite_link(){ # TRANSLATION
+ cat <<-EOF
+ [div #user_invite .link
+ [p An anonymous user account has been set up. Send the following link to the intended user, so they may claim their account. The link will remain valid for $((USER_CONFIRMEXPIRE / 3600)) hours.]
+ [a href="$(HTML "$invlink")" . $(HTML "$invlink")]
+
+ [p [a href="#" . Set up another account]]
+ ]
+ EOF
+}
+w_user_invite_deny(){ # TRANSLATION
+ cat <<-EOF
+ [div #user_invite .notallowed
+ Only registered users may send an invitation to another user.
+ ]
+ EOF
+}
+
+w_user_invite(){
+ local uid invlink
+
+ if [ "$(GET user_confirm)" ]; then
+ w_user_confirm
+ elif [ "$USER_ID" -a "$SENDMAIL" ]; then
+ w_user_invite_email
+ elif [ "$USER_ID" ]; then
+ uid="$(timeid)"
+ new_user "$uid" status=pending expire="$((_DATE + USER_CONFIRMEXPIRE))"
+ invlink="${SCHEMA}://${HTTP_HOST}${_BASE}${PATH_INFO}?user_confirm=${uid}+$(session_mac "$uid")"
+ debug "New Invitation Link: $invlink"
+ w_user_invite_link
+ else
+ w_user_invite_deny
+ fi
+}
+
+w_user_login_logon(){ # TRANSLATION
+ cat <<-EOF
[form #user_login .login method=POST
- [input name=uname placeholder="Username or Email" autocomplete=off]
+ [input name=uname placeholder="Username or Email"]
[input type=password name=pw placeholder="Passphrase"]
[submit "action" "user_login" Login]
]
EOF
- elif [ "$USER_ID" ]; then
- cat <<-EOF
+}
+w_user_login_logoff(){ # TRANSLATION
+ cat <<-EOF
[form #user_login .logout method=POST
- [p You are currently logged in as "${USER_NAME}"]
+ [p Logged in as [span . $(HTML ${USER_NAME})]]
[submit "action" "user_logout" Logout]
]
EOF
+}
+
+w_user_login(){
+ if [ ! "$USER_ID" ]; then
+ w_user_login_logon
+ elif [ "$USER_ID" ]; then
+ w_user_login_logoff
fi
}