diff --git a/ajax/verify-unt-email.php b/ajax/verify-unt-email.php new file mode 100644 index 00000000..a1d5da43 --- /dev/null +++ b/ajax/verify-unt-email.php @@ -0,0 +1,195 @@ +query("SELECT + id, + created_on + FROM + discord_verification_tokens + WHERE + user_id = {$auth['id']} + ORDER BY created_on DESC + LIMIT 1"); + if ($q === false) { + error_log("Could not retrieve discord verification token for user {$auth['id']}: {$db->error}"); + echo 'ERROR'; + die(); + } + if ($q->num_rows > 0) { + $r = $q->fetch_assoc(); + /** @noinspection PhpParenthesesCanBeOmittedForNewCallInspection */ + /** @noinspection PhpUnhandledExceptionInspection */ + if ((new DateTime())->sub(new DateInterval('PT' . EMAIL_TOKEN_GENERATION_RATE_LIMIT . 'S')) < new DateTime($r['created_on'])) { + echo 'TOKEN_RATELIMIT'; + die(); + } + $q = $db->query("DELETE FROM + discord_verification_tokens + WHERE + id = {$r['id']}" + ); + if($q === false){ + error_log("Could not delete discord verification token {$r['id']} for user {$auth['id']}: {$db->error}"); + echo 'ERROR'; + die(); + } + } + // generate token + $token = bin2hex(openssl_random_pseudo_bytes(3)); + $q = $db->query("INSERT INTO discord_verification_tokens ( + token, + created_on, + user_id, + unt_email + ) + VALUES ( + '{$token}', + CURRENT_TIMESTAMP(), + {$auth['id']}, + '{$db->real_escape_string($email)}' + )" + ); + if ($q === false) { + error_log("Could not add discord verification token to db for user {$auth['id']}: {$db->error}"); + echo 'ERROR'; + die(); + } + // send email with token + $email_send_status = email( + $email, + "UNT Robotics Discord verification token", + + "
Hey there!
" . + "Welcome to the team!!
" . + "Thank you for joining the UNT Robotics Discord server!" . + "
Your verification token is:
" . + "{$token}
" . + 'If you need any assistance, please reach out to hello@untrobotics.com.
" . + + ' ' . + + 'All the best,
" . + "UNT Robotics Leadership
" . + 'Hey there!
" . + "Welcome to the team!!
" . + "Thank you for joining the UNT Robotics Discord server!" . + "
Your verification token is:
" . + "{$token}
" . + 'If you need any assistance, please reach out to hello@untrobotics.com.
" . + + ' ' . + + 'All the best,
" . + "UNT Robotics Leadership
" . + 'Thank you for paying your dues.
- + Click here to update your Discord account status. + +' + msg[result] + '
'); + } else { + output.addClass("active success"); + } + form.clearForm(); + } else { + if (output.hasClass("snackbars")) { + output.html(''); + } else { + output.addClass("active error"); + } + } + + form.find('input, textarea').blur(); + + setTimeout(function () { + output.removeClass("active error success"); + form.removeClass('success'); + }, 3500); + } + /** * RD Mailform */ @@ -1677,9 +1721,9 @@ $document.ready(function () { error: function (result) { var form = $(plugins.rdMailForm[this.extraData.counter]), output = $("#" + $(plugins.rdMailForm[this.extraData.counter]).attr("data-form-output")); - output.text(msg[result]); + output.text(msg[result.responseText]); + output.addClass('active error') form.removeClass('form-in-process'); - if (formHasCaptcha) { grecaptcha.reset(); } @@ -1688,40 +1732,8 @@ $document.ready(function () { var form = $(plugins.rdMailForm[this.extraData.counter]), output = $("#" + form.attr("data-form-output")); - form - .addClass('success') - .removeClass('form-in-process'); - - if (formHasCaptcha) { - grecaptcha.reset(); - } - - //result = result.length == 5 ? result : 'MF255'; - output.text(msg[result]); - - if (result === "SUCCESS") { - if (output.hasClass("snackbars")) { - output.css('background-color', '#24c57c'); - output.html('' + msg[result] + '
'); - } else { - output.addClass("active success"); - } - form.clearForm(); - } else { - if (output.hasClass("snackbars")) { - output.html(''); - } else { - output.addClass("active error"); - } - } - - form.find('input, textarea').blur(); - - setTimeout(function () { - output.removeClass("active error success"); - form.removeClass('success'); - }, 3500); - } + finalizeForm(form, formHasCaptcha, output, result, msg); + } }); } } @@ -1922,6 +1934,68 @@ $document.ready(function () { }, 300); }); } + + /** + * Custom email verification AJAX form + */ + // noinspection JSJQueryEfficiency + if ($('form#verify-email').length) { + let msg = { + "INVALID_EMAIL": "The e-mail address you entered is not valid. Please ensure the email ends with @my.unt.edu.", + "INVALID_TOKEN": "The token is incorrect or invalid.", + "INVALID_LOGIN": "Your log-in session has expired or isn't valid anymore. Please log-in again to continue.", + "INVALID_REQUEST": "The request fields are invalid.", + "TOKEN_RATELIMIT": "Please wait a few minutes before requesting a new token.", + "TOKEN": "Token sent.", + "SUCCESS": "E-mail successfully verified.", + "ERROR": "A server error occurred. Please contact support." + } + let $form = $('form#verify-email'); + let $output = $('#' + $form.attr('data-form-output')) + $form.ajaxForm({ + beforeSubmit: function () { + if(isValidated($form.find('input:not([type="hidden"])'), false)) { + $output.removeClass("active error success"); + $form.addClass('form-in-process'); + if ($output.hasClass("snackbars")) { + $output.html('Sending
'); + $output.addClass("active"); + } + return true + } + return false + }, + error: function (result) { + $output.text(msg[result.responseText]).addClass('active error') + }, + success: function (result) { + if (result === "TOKEN") { + let $input = $form.find('input#email') + $form.find('label#email-label').addClass('hidden') + let email = $input.val(); + $input.attr({ + 'type': 'hidden', + 'disabled': '' + }) + $input = $form.find('input#token') + $input.attr('type', 'text').removeAttr('disabled') + $form.find('label#token-label').removeClass('hidden') + $form.find('input#type').val('token') + $form.siblings('div').children('h6').text("We’ve sent a verification token to " + email + ". Please check your inbox and spam/junk folder and enter the code below to verify your address.") + $form.find('button').text('Verify') + finalizeForm($form,false, $output, result, msg) + } else if (result.startsWith("INVALID") || result.startsWith('TOKEN_RATELIMIT') || result.startsWith("ERROR")) { + finalizeForm($form, false, $output, result, msg) + } else { + let $section = $('section#email-verification-section'); + $section.parent().append(result) + $section.remove() + finalizeForm($form, false, $output, "SUCCESS", msg) + } + }, + headers: {'Cookie' : document.cookie }, + }) + } }); diff --git a/sql/discord_verification_tokens.sql b/sql/discord_verification_tokens.sql new file mode 100644 index 00000000..acf0383f --- /dev/null +++ b/sql/discord_verification_tokens.sql @@ -0,0 +1,11 @@ +DROP TABLE IF EXISTS `discord_verification_tokens`; +CREATE TABLE `discord_verification_tokens`( + `id` int(11) NOT NULL AUTO_INCREMENT, + `token` varchar(6) NOT NULL, + `created_on` timestamp NOT NULL, + `discord_id` bigint(20), + `user_id` int(11), + `unt_email` varchar(255) NOT NULL, + PRIMARY KEY(id), + FOREIGN KEY (user_id) REFERENCES users(id) +) AUTO_INCREMENT=8 DEFAULT CHARSET=latin1; \ No newline at end of file diff --git a/sql/migrations/URW-167-unt-email-field.sql b/sql/migrations/URW-167-unt-email-field.sql new file mode 100644 index 00000000..f79a9c0b --- /dev/null +++ b/sql/migrations/URW-167-unt-email-field.sql @@ -0,0 +1,2 @@ +ALTER TABLE users + ADD COLUMN unt_email varchar(255); diff --git a/template/classes/untrobotics.php b/template/classes/untrobotics.php index f554f25f..00c7bf52 100644 --- a/template/classes/untrobotics.php +++ b/template/classes/untrobotics.php @@ -70,6 +70,28 @@ public function is_user_in_good_standing($userinfo) { return $q->num_rows === 1; } + public function is_user_email_verified($userinfo) { + $uid = null; + if (is_array($userinfo)) { + $uid = $userinfo['id']; + } else { + $uid = $userinfo; + } + $q = $this->db->query(' + SELECT id FROM users + WHERE + id = "' . $this->db->real_escape_string($uid) . '" + AND + unt_email IS NOT NULL + '); + + if (!$q) { + return false; + } + + return $q->num_rows === 1; + } + // semester, dues functions public function get_current_term() { return $this->get_term_from_date(time()); diff --git a/template/sample.config.php b/template/sample.config.php index 67970de4..0f27f7f8 100644 --- a/template/sample.config.php +++ b/template/sample.config.php @@ -86,6 +86,8 @@ '755952946566660206' // Web/Ops Team ) ); +define('DISCORD_VERIFIED_ROLE_ID', '1414807269580734527'); +define('EMAIL_TOKEN_GENERATION_RATE_LIMIT', 300); define('PAYPAL_PDT_ID_TOKEN', ''); define('PAYPAL_SANDBOX_PDT_ID_TOKEN', '');