From f477dc5d53cd74cf455c9035ed996730f443e4ba Mon Sep 17 00:00:00 2001 From: =?utf8?q?Paul=20H=C3=A4nsch?= Date: Wed, 27 Oct 2021 22:39:07 +0200 Subject: [PATCH] better data-layer / UI-layer abstraction in user functions --- users.sh | 123 +++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 78 insertions(+), 45 deletions(-) diff --git a/users.sh b/users.sh index 7721def..a389f15 100755 --- a/users.sh +++ b/users.sh @@ -12,32 +12,53 @@ USER_REQUIREEMAIL="${USER_REQUIREEMAIL:-true}" HTTP_HOST="$(HEADER Host)" MAILFROM="${MAILDOMAIN:-noreply@${HTTP_HOST%:*}}" +# == 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 +' + +eval "$UNSET_USER" + 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 +read_user() { + local user="$1" -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") + # 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 @@ -48,6 +69,7 @@ user_update_user() { status=*) status="${arg#*=}";; email=*) email="${arg#*=}";; password=*) pwsalt="$(randomid)"; pwhash="$(user_pwhash "$pwsalt" "${arg#*=}")";; + expire=*) expire="${arg#*=}";; devices=*) devices="${arg#*=}";; esac; done @@ -55,19 +77,19 @@ user_update_user() { 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 @@ -79,6 +101,32 @@ user_update_user() { 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_checkname(){ { [ $# -gt 0 ] && printf %s "$*" || cat; } \ | sed -nE ' @@ -144,12 +192,7 @@ user_register(){ 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 @@ -187,14 +230,7 @@ user_register(){ 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" @@ -214,11 +250,7 @@ user_invite(){ 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 @@ -252,16 +284,14 @@ user_invite(){ 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" @@ -273,11 +303,11 @@ user_confirm(){ 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" @@ -325,6 +355,9 @@ user_disable(){ : } +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 ;; -- 2.39.2