X-Git-Url: https://git.plutz.net/?p=cgilite;a=blobdiff_plain;f=users.sh;h=1959e9de4b757084fad3d850b1b7b771517cb3c3;hp=ca986cd6f737a00c78915379bfe83c3f14eba6d5;hb=HEAD;hpb=38314fd1bc5cdc37422e38de39c8212783d5a2a8 diff --git a/users.sh b/users.sh index ca986cd..32299ff 100755 --- a/users.sh +++ b/users.sh @@ -1,10 +1,24 @@ #!/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" +. "${_EXEC:-.}/cgilite/session.sh" +. "${_EXEC:-.}/cgilite/storage.sh" SENDMAIL=${SENDMAIL-sendmail} @@ -12,9 +26,11 @@ USER_REGISTRATION="${USER_REGISTRATION-true}" USER_REQUIREEMAIL="${USER_REQUIREEMAIL-true}" USER_ACCOUNTPAGE="${USER_ACCOUNTPAGE}" -MAILFROM="${MAILDOMAIN-noreply@${HTTP_HOST%:*}}" +USER_ACCOUNTEXPIRE="${USER_ACCOUNTEXPIRE:-$((86400 * 730))}" +USER_CONFIRMEXPIRE="${USER_CONFIRMEXPIRE:-86400}" HTTP_HOST="$(HEADER Host)" +MAILFROM="noreply@${HTTP_HOST%:*}" [ "$HTTPS" ] && SCHEMA=https || SCHEMA=http @@ -33,6 +49,10 @@ LOCAL_USER='local \ USER_EXPIRE USER_DEVICES USER_FUTUREUSE ' +# == TRANSLATIONS == +# override all functions marked with "TRANSLATION" +# sed -n '/TRANSLATION$/,/^}/p;' >"$user_db" + "$user" "pending" "$(( _DATE + USER_CONFIRMEXPIRE ))" >>"$user_db" else return 1 fi @@ -215,28 +235,8 @@ user_pwhash(){ 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 -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 + 86400))"; then - debug "Sending Activation Link:" \ - "${SCHEMA}://${HTTP_HOST}${_BASE}${PATH_INFO}?user_confirm=${uid}+$(session_mac "$uid")" - "$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%:*} @@ -247,7 +247,7 @@ user_register(){ ${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 @@ -257,6 +257,30 @@ user_register(){ 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" @@ -271,7 +295,7 @@ user_register(){ REDIRECT "${_BASE}${PATH_INFO}#ERROR_PW_EMPTYTOOSHORT" elif [ "$pw" != "$pwconfirm" ]; then REDIRECT "${_BASE}${PATH_INFO}#ERROR_PW_MISMATCH" - elif new_user "$uid" uname="$uname" status=active email="$email" password="$pw" expire="$((_DATE + 86400 * 730))"; then + 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" @@ -286,19 +310,8 @@ user_register(){ fi } -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 + 86400))"; then - debug "Sending Invitation Link:" \ - "${SCHEMA}://${HTTP_HOST}${_BASE}${PATH_INFO}?user_confirm=${uid}+$(session_mac "$uid")" - "$SENDMAIL" -t -f "$MAILFROM" <<-EOF +user_invite_email(){ # TRANSLATION + "$SENDMAIL" -t -f "$MAILFROM" <<-EOF From: ${MAILFROM} To: ${email} Subject: You have been invited to ${HTTP_HOST%:*} @@ -311,7 +324,7 @@ user_invite(){ ${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 do not know what this is about, then someone else probably entered your email address by accident. In this case you shoud @@ -321,6 +334,21 @@ user_invite(){ 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" @@ -400,7 +428,7 @@ user_update(){ uid="$(POST uid)" oldpw="$(POST oldpw)" - pw="$(POST pw |grep -xE '.{6}')" + pw="$(POST pw |grep -m1 -xE '.{6,}')" pwconfirm="$(POST pwconfirm)" @@ -413,7 +441,7 @@ user_update(){ update_user "${uid}" password="$pw" REDIRECT "${_BASE}${PATH_INFO}#UPDATE_SUCCESS" else - REDIRECT "${_BASE}${PATH_INFO}#ERROR_PWMISMATCH" + REDIRECT "${_BASE}${PATH_INFO}#ERROR_PW_MISMATCH" fi elif [ "$UID_" = "$USER_ID" ]; then REDIRECT "${_BASE}${PATH_INFO}#ERROR_INVALID_AUTH_PASSWORD" @@ -471,17 +499,15 @@ w_user_update(){ fi } -w_user_register(){ - if [ "$(GET user_confirm)" ]; then - w_user_confirm - elif [ "$USER_REGISTRATION" != true -a -s "$user_db" ]; then - cat <<-EOF +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 @@ -490,8 +516,9 @@ w_user_register(){ [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="^\[\\\\p{L}\]\[\\\\p{L}0-9 -~\]{2,127}$" autocomplete=off] [input type=password name=pw placeholder="Choose Passphrase" pattern=".{6,}"] @@ -499,20 +526,22 @@ w_user_register(){ [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}"] @@ -525,66 +554,108 @@ w_user_confirm(){ [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_invite(){ - if [ "$(GET user_confirm)" ]; then - w_user_confirm - elif [ "$USER_ID" -a "$SENDMAIL" ]; 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 - elif [ "$USER_ID" ]; then - uid="$(timeid)" - new_user "$uid" status=pending email="$email" expire="$((_DATE + 86400))" - cat <<-EOF - [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 24 hours.] - [p . $(HTML "${SCHEMA}://${HTTP_HOST}${_BASE}${PATH_INFO}?user_confirm=${uid}+$(session_mac "$uid")" |debug)] +} +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]] + [p [a href="#" . Set up another account]] + ] EOF - else - cat <<-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 "$USER_REQUIREEMAIL" = true ]; 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(){ - if [ ! "$USER_ID" ]; then - cat <<-EOF +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 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 }