HTTP_HOST="$(HEADER Host)"
MAILFROM="${MAILDOMAIN:-noreply@${HTTP_HOST%:*}}"
-user_db="${_DATA}/users.db"
-unset 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
-
-user_id="$(SESSION_VAR user_id)"
-if [ "$user_id" -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_id} " "$user_db")
+# == 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
+'
+
+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
- if [ "$USER_ID" -a "$USER_STATUS" = active -a "$USER_EXPIRE" -gt "$_DATE" ]; then
+ 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
- unset USER_ID USER_NAME USER_STATUS USER_EMAIL USER_PWSALT USER_PWHASH \
- USER_EXPIRE USER_DEVICES USER_FUTUREUSE
+ eval "$UNSET_USER"
+ return 1
fi
-fi
-unset user_id
+}
-user_update_user() {
+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
status=*) status="${arg#*=}";;
email=*) email="${arg#*=}";;
password=*) pwsalt="$(randomid)"; pwhash="$(user_pwhash "$pwsalt" "${arg#*=}")";;
+ expire=*) expire="${arg#*=}";;
devices=*) devices="${arg#*=}";;
esac; done
while read -r UID UNAME STATUS EMAIL PWSALT PWHASH EXPIRE DEVICES \
FUTUREUSE; do
if [ "$UID" = "$uid" ]; then
- printf '%s %s %s %s %s %s %s %s %s\n' \
+ 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}}" \
- "$((_DATE + 86400 * 730))" \
+ "${expire:-$((_DATE + 86400 * 730))}" \
"$(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 %s %s %s\n' \
+ printf '%s %s %s %s %s %s %i %s %s\n' \
"$UID" "$UNAME" "$STATUS" "$EMAIL" "$PWSALT" "$PWHASH" \
"$EXPIRE" "$DEVICES" "$FUTUREUSE"
fi
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 + 86400 ))" >>"$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(){
{ [ $# -gt 0 ] && printf %s "$*" || cat; } \
| sed -nE '
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"
-
+ elif new_user "$uid" status=pending email="$email" expire="$((_DATE + 86400))"; then
debug "Sending Activation Link:" \
"https://${HTTP_HOST}${_BASE}${PATH_INFO}?user_confirm=${uid}+$(session_mac "$uid")"
sendmail -t -f "$MAILFROM" <<-EOF
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 + 86400 * 730))"; then
SESSION_COOKIE new
SESSION_BIND user_id "$uid"
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"
+ elif new_user "$uid" status=pending email="$email" expire="$((_DATE + 86400))"; then
debug "Sending Invitation Link:" \
"https://${HTTP_HOST}${BASE}${PATH_INFO}?user_confirm=${uid}+$(session_mac "$uid")"
sendmail -t -f "$MAILFROM" <<-EOF
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 -r UID UNAME STATUS EMAIL PWSALT PWHASH EXPIRE DEVICES FUTUREUSE <<-EOF
- $(grep "^${uid:-invalid} " "$user_db")
- EOF
+ read_user "${uid}"
if [ "$signature" != "$(session_mac "$uid")" ]; then
REDIRECT "${_BASE}${PATH_INFO}?${QUERY_STRING}#ERROR_LINK_INVALID"
REDIRECT "${_BASE}${PATH_INFO}?${QUERY_STRING}#ERROR_PW_EMPTYTOOSHORT"
elif [ "$pw" != "$pwconfirm" ]; then
REDIRECT "${_BASE}${PATH_INFO}?${QUERY_STRING}#ERROR_PW_MISMATCH"
- elif [ "$STATUS" != pending -o \! "$EXPIRE" -gt "$_DATE" ]; then
+ elif [ "$USER_STATUS" != pending -o \! "$USER_EXPIRE" -gt "$_DATE" ]; then
REDIRECT "${_BASE}${PATH_INFO}?${QUERY_STRING}#ERROR_LINK_INVALID"
- elif user_update_user "$UID" uname="$uname" status=active password="$pw"; then
+ elif update_user "$USER_ID" uname="$uname" status=active password="$pw"; then
SESSION_COOKIE new
- SESSION_BIND user_id "$UID"
+ SESSION_BIND user_id "$USER_ID"
REDIRECT "${_BASE}${PATH_INFO}?user_register=confirm#USER_REGISTER_CONFIRM"
else
REDIRECT "${_BASE}${PATH_INFO}#ERROR_USER_NOLOCK"
:
}
+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 ;;