diff --git a/assets/less/auth/classes/button.less b/assets/less/auth/classes/button.less new file mode 100644 index 00000000..1d4878b8 --- /dev/null +++ b/assets/less/auth/classes/button.less @@ -0,0 +1,14 @@ +.button { + border-radius: 4px; + border: 0; + padding: 7px 10px; + background: #462e55; + color: #fff; + text-align: left; + cursor: pointer; + line-height: 1.4em; + display: inline-block; + text-decoration: none; + font-family: sans-serif; + font-size: 12px; +} diff --git a/assets/less/auth/classes/container.less b/assets/less/auth/classes/container.less new file mode 100644 index 00000000..ee9148aa --- /dev/null +++ b/assets/less/auth/classes/container.less @@ -0,0 +1,5 @@ +.container { + box-shadow: 0 2px 5px fade(#111, 80%); + background: #222; + margin: 2px; +} diff --git a/assets/less/auth/classes/form.less b/assets/less/auth/classes/form.less new file mode 100644 index 00000000..3aa918d5 --- /dev/null +++ b/assets/less/auth/classes/form.less @@ -0,0 +1,93 @@ +.form { + height: @auth-title-height; + overflow: hidden; + transition: height .3s ease-in-out; + + &__wrapper { + + &:not(:last-child) { + border-bottom: 1px solid #333; + } + } + + &__toggle { + display: none; + + &:checked ~ .form { + height: @auth-form-height; + } + + &:not(:checked) ~ .form .form__title:hover { + cursor: pointer; + background: #333; + z-index: 100; + box-shadow: 0 2px 5px fade(#111, 80%); + } + } + + &__title { + font-size: 1.4em; + display: block; + padding: 10px; + height: @auth-title-height; + transition: background .2s, box-shadow .2s; + -webkit-touch-callout: none; + -webkit-user-select: none; + -khtml-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + } + + &__content { + display: flex; + flex-direction: column; + margin: 0 5px; + height: @auth-form-height - @auth-title-height; + overflow: hidden; + transition: height .5s ease-in-out; + align-items: center; + flex-grow: 1; + justify-content: center; + + &--no-registration { + max-width: 400px; + } + } + + &__link { + color: #88c; + text-decoration: none; + + &:hover { + text-decoration: underline; + } + + &:active { + color: #c88; + } + } + + &__row { + margin-bottom: 5px; + width: 100%; + + &--columns { + display: flex; + justify-content: space-between; + align-items: center; + } + } + + &__column { + + &--message { + padding-left: 10px; + color: #aaa; + } + + &--error { + color: #a33; + } + } +} diff --git a/assets/less/auth/classes/logout.less b/assets/less/auth/classes/logout.less new file mode 100644 index 00000000..84568be6 --- /dev/null +++ b/assets/less/auth/classes/logout.less @@ -0,0 +1,20 @@ +.logout { + max-width: 400px; + padding: 5px; + + &__message { + font-size: 1.2em; + } + + &__paragraph { + &:not(:last-child) { + margin-bottom: 2px; + } + } + + &__buttons { + margin-top: 5px; + display: flex; + justify-content: flex-end; + } +} diff --git a/assets/less/auth/classes/text.less b/assets/less/auth/classes/text.less new file mode 100644 index 00000000..2dc6f9ba --- /dev/null +++ b/assets/less/auth/classes/text.less @@ -0,0 +1,17 @@ +.text { + display: block; + width: 100%; + border: 0; + background: #1a1a1a; + border-radius: 4px; + color: #fff; + padding: 5px; + + @media (max-width: @auth-mobile) { + font-size: 1.2em; + } + + &__label { + display: block; + } +} diff --git a/assets/less/auth/main.less b/assets/less/auth/main.less new file mode 100644 index 00000000..59301fea --- /dev/null +++ b/assets/less/auth/main.less @@ -0,0 +1,44 @@ +@auth-mobile: 500px; +@auth-title-height: 40px; +@auth-form-height: 200px; + +* { + margin: 0; + padding: 0; + box-sizing: border-box; + position: relative; +} + +html, +body { + height: 100%; + width: 100%; +} + +body { + background: #5e3e71 url('https://static.flash.moe/images/grid.png'); + font: 12px/20px sans-serif; + display: flex; + align-items: center; + justify-content: center; + color: #fff; +} + +.auth { + min-width: 400px; + min-height: @auth-form-height; + display: flex; + flex-direction: column; + justify-content: center; + + @media (max-width: @auth-mobile) { + min-width: 0; + width: 100%; + } +} + +@import "classes/button"; +@import "classes/container"; +@import "classes/form"; +@import "classes/logout"; +@import "classes/text"; diff --git a/assets/less/mio/classes/avatar.less b/assets/less/mio/classes/avatar.less new file mode 100644 index 00000000..fddd056b --- /dev/null +++ b/assets/less/mio/classes/avatar.less @@ -0,0 +1,11 @@ +.mio__avatar { + flex-shrink: 0; + background-color: #fbeeff; + background-size: contain; + background-repeat: no-repeat; + background-position: 50%; + display: block; + border: 1px solid #9475b2; + max-height: 200px; + max-width: 200px; +} diff --git a/assets/less/mio/classes/container.less b/assets/less/mio/classes/container.less new file mode 100644 index 00000000..818a409d --- /dev/null +++ b/assets/less/mio/classes/container.less @@ -0,0 +1,19 @@ +.mio__container { + border: 1px solid #9475b2; + background-color: #fbeeff; + margin: 2px 0; + + + &__title { + background-color: #9475b2; + color: #306; + font-size: 1.17em; + font-weight: 700; + padding: 3px; + font-family: Verdana, Arial, Helvetica, sans-serif; + } + + &__content { + margin: 2px 5px; + } +} diff --git a/assets/less/mio/classes/footer.less b/assets/less/mio/classes/footer.less new file mode 100644 index 00000000..c90c5a7e --- /dev/null +++ b/assets/less/mio/classes/footer.less @@ -0,0 +1,25 @@ +.mio__footer { + text-align: center; + font-size: .9em; + line-height: 1.5em; + margin-bottom: 1em; + + &__copyright__link { + color: inherit; + text-decoration: none; + + &:hover { + text-decoration: underline; + } + } + + &__links__link { + color: inherit; + text-decoration: none; + margin: 0 2px; + + &:hover { + text-decoration: underline; + } + } +} diff --git a/assets/less/mio/classes/forum/listing.less b/assets/less/mio/classes/forum/listing.less new file mode 100644 index 00000000..62d67f71 --- /dev/null +++ b/assets/less/mio/classes/forum/listing.less @@ -0,0 +1,81 @@ +@mio-forum-listing-mobile: 500px; + +.mio__forum__listing { + &__forums { + margin: 0; + } + + &__entry { + display: flex; + padding: 2px 0; + align-items: center; + + &:not(:last-child) { + border-bottom: 1px solid #9475b2; + } + + &__icon { + width: 50px; + line-height: 50px; + font-size: 2.5em; + text-align: center; + flex-grow: 0; + flex-shrink: 0; + } + + &__info { + flex-grow: 1; + flex-shrink: 1; + } + + &__title { + font-size: 1.2em; + line-height: 1.5em; + color: #306; + text-decoration: none; + + &:hover { + text-decoration: underline; + } + } + + &__description { + font-size: .8em; + line-height: 1.3em; + } + + &__stats { + text-align: right; + flex-grow: 0; + flex-shrink: 0; + font-style: italic; + font-family: Verdana, Arial, Helvetica, sans-serif; + + @media (max-width: @mio-forum-listing-mobile) { + display: none; + } + } + + &__topics { + font-size: 1.5em; + color: #222; + } + + &__posts { + font-size: .9em; + color: #555; + } + + &__activity { + flex-grow: 0; + flex-shrink: 0; + text-align: right; + margin: 0 10px; + width: 220px; + + @media (max-width: @mio-forum-listing-mobile) { + display: none; + } + } + } +} diff --git a/assets/less/mio/classes/header.less b/assets/less/mio/classes/header.less new file mode 100644 index 00000000..959ef552 --- /dev/null +++ b/assets/less/mio/classes/header.less @@ -0,0 +1,90 @@ +@mio-header-mobile: 700px; + +.mio__header { + display: flex; + margin: 4px 0; + + @media (max-width: @mio-header-mobile) { + flex-direction: column; + align-items: center; + } + + &__logo { + flex-grow: 0; + flex-shrink: 0; + + &__link { + color: inherit; + text-decoration: none; + cursor: pointer; + display: block; + } + + &__image { + vertical-align: bottom; + + @media (max-width: @mio-header-mobile) { + max-width: 200px; + max-height: 100px; + } + } + } + + &__menu { + flex-grow: 1; + flex-shrink: 1; + display: flex; + align-items: flex-start; + justify-content: flex-end; + + @media (max-width: @mio-header-mobile) { + width: 100%; + } + } + + &__user { + border: 1px solid #9475b2; + display: inline-block; + + &__content { + margin: 2px; + display: flex; + } + + &__avatar { + width: 60px; + height: 60px; + } + + &__links { + text-align: right; + list-style: none; + margin: 0 2px; + line-height: 1.5em; + + &__container { + flex-grow: 1; + } + + @media (max-width: @mio-header-mobile) { + font-size: 1.5em; + } + } + + &__link { + color: inherit; + text-decoration: none; + display: block; + min-width: 70px; + + &:hover { + text-decoration: underline; + } + } + + @media (max-width: @mio-header-mobile) { + width: 100%; + margin: 0; + } + } +} diff --git a/assets/less/mio/classes/heading.less b/assets/less/mio/classes/heading.less new file mode 100644 index 00000000..a261de69 --- /dev/null +++ b/assets/less/mio/classes/heading.less @@ -0,0 +1,5 @@ +.mio__heading { + &--1 { + line-height: 1.2em; + } +} diff --git a/assets/less/mio/classes/input/button.less b/assets/less/mio/classes/input/button.less new file mode 100644 index 00000000..80d8676f --- /dev/null +++ b/assets/less/mio/classes/input/button.less @@ -0,0 +1,29 @@ +.mio__input__button { + font-family: 'visitor1'; + font-size: 20px; + line-height: 1.25em; + color: #fff; + background: #9475b2; + border: 1px solid #306; + box-shadow: inset 0 0 0 1px #643b8c; + border-radius: 2px; + padding: 1px 10px; + transition: background .2s, border-color .2s; + cursor: pointer; + text-align: left; + display: inline-block; + text-decoration: none; + + &:focus { + border-color: #407; + } + + &:hover { + background: #A586c3; + } + + &:active { + border-color: #306; + background: #8364a1; + } +} diff --git a/assets/less/mio/classes/input/text.less b/assets/less/mio/classes/input/text.less new file mode 100644 index 00000000..d933bc21 --- /dev/null +++ b/assets/less/mio/classes/input/text.less @@ -0,0 +1,15 @@ +.mio__input__text { + border: 1px solid #aaa; + padding: 1px; + background: #fff; + color: #111; + + &:focus { + border-color: #9475b2; + } +} + +.mio--dark .mio__input__text { + background: #111; + color: #fff; +} diff --git a/assets/less/mio/classes/input/textarea.less b/assets/less/mio/classes/input/textarea.less new file mode 100644 index 00000000..24c2827a --- /dev/null +++ b/assets/less/mio/classes/input/textarea.less @@ -0,0 +1,16 @@ +.mio__input__textarea { + border: 1px solid #aaa; + padding: 1px; + vertical-align: bottom; + background: #fff; + color: #111; + + &:focus { + border-color: #9475b2; + } +} + +.mio--dark .mio__input__textarea { + background: #111; + color: #fff; +} diff --git a/assets/less/mio/classes/navigation.less b/assets/less/mio/classes/navigation.less new file mode 100644 index 00000000..d13a0e4f --- /dev/null +++ b/assets/less/mio/classes/navigation.less @@ -0,0 +1,111 @@ +@mio-navigation-mobile: 1000px; + +.mio__navigation { + margin: 5px 0; + width: 100%; + display: flex; + border: 0 solid #000; + border-top-width: 1px; + align-items: flex-start; + justify-content: center; + + @media (max-width: @mio-navigation-mobile) { + border: none; + align-items: center; + flex-direction: column; + } + + &--top { + border-top-width: 0; + border-bottom-width: 1px; + align-items: flex-end; + + .mio__navigation__option { + border-top-width: 1px; + border-bottom-width: 0; + + &--selected { + top: 1px; + } + } + } + + &__option { + list-style: none; + background-color: #c9bbcc; + border: 1px solid #000; + border-top-width: 0; + flex-grow: 0; + + @media (max-width: @mio-navigation-mobile) { + background-color: #9475b2; + width: 100%; + border: none; + flex-grow: 1; + margin-bottom: 1px; + } + + &:not(:first-child) { + border-left-width: 0; + } + + &--selected { + background-color: #fbeeff; + top: -1px; + + @media (max-width: @mio-navigation-mobile) { + background-color: #A586c3; + top: 0; + } + + &:not(:first-child) { + margin-left: -1px; + border-left-width: 1px; + } + + .mio__navigation__link { + padding: 3px 1em; + } + } + } + + &__link { + display: block; + padding: 2px 1em; + color: #000; + text-decoration: none; + + @media (max-width: @mio-navigation-mobile) { + padding: 10px 15px; + color: #306; + font-size: 1.5em; + } + + &:hover { + color: #609; + } + } +} + +.mio--dark { + .mio__navigation, + .mio__navigation__option { + border-color: #9475b2; + } + + .mio__navigation__option { + background-color: #462e55; + } + + .mio__navigation__option--selected { + background-color: #23172a; + } + + .mio__navigation__link { + color: #9475b2; + + &:hover { + color: #a586c3; + } + } +} diff --git a/assets/less/mio/classes/profile.less b/assets/less/mio/classes/profile.less new file mode 100644 index 00000000..d55d36c6 --- /dev/null +++ b/assets/less/mio/classes/profile.less @@ -0,0 +1,120 @@ +@mio-profile-mobile: 700px; + +.mio__profile { + &__avatar { + width: 200px; + height: 200px; + + @media (max-width: @mio-profile-mobile) { + width: 100px; + height: 100px; + margin: 20px 0; + } + } + + &__icon { + vertical-align: middle; + } + + &__header { + height: 300px; + background-color: #fbeeff; + background-size: cover; + background-repeat: no-repeat; + background-position: 50%; + + @media (max-width: @mio-profile-mobile) { + height: auto; + background-size: 700px auto; + background-position: center top; + } + + &__content { + margin: 2px; + display: flex; + align-items: flex-start; + justify-content: space-between; + + @media (max-width: @mio-profile-mobile) { + flex-direction: column-reverse; + align-items: center; + margin: 0; + } + } + } + + &__info { + display: flex; + + @media (max-width: @mio-profile-mobile) { + flex-direction: column; + background-color: #9475b2; + width: 100%; + padding-top: 2px; + } + + &__section { + margin-right: 2px; + + @media (max-width: @mio-profile-mobile) { + margin: 0 1px; + } + } + + &__block { + border: 1px solid #9475b2; + padding: 2px 4px; + margin-bottom: 2px; + background-color: rgba(251, 238, 255, .9); + + @media (max-width: @mio-profile-mobile) { + background-color: #fbeeff; + } + } + + &__row { + display: flex; + } + + &__column { + min-width: 80px; + + @media (max-width: @mio-profile-mobile) { + min-width: auto; + flex-grow: 1; + text-align: right; + } + + &--heading { + font-weight: bold; + + @media (max-width: @mio-profile-mobile) { + text-align: left; + } + } + + &--numeric { + text-align: right; + } + + &--user-title { + text-align: center; + width: 100%; + font-style: italic; + } + + &--icons { + text-align: center; + min-width: 0; + } + + &--country { + font-size: .8em; + line-height: 1.4em; + width: 110px; + text-align: center; + align-self: flex-end; + } + } + } +} diff --git a/assets/less/mio/main.less b/assets/less/mio/main.less new file mode 100644 index 00000000..ecb60d22 --- /dev/null +++ b/assets/less/mio/main.less @@ -0,0 +1,52 @@ +* { + margin: 0; + padding: 0; + box-sizing: border-box; + position: relative; +} + +html, +body { + width: 100%; + height: 100%; +} + +.mio { + background-color: #fbeeff; + background-image: linear-gradient(180deg, #c2affe, transparent); + background-repeat: repeat-x; + background-size: 100% 150px; + font: 12px/20px Tahoma, Verdana, Arial, Helvetica, sans-serif; + color: #000; + + &__wrapper { + max-width: 1200px; + margin: 0 auto; + padding: 1px; + } + + &--dark { + background-color: #23172a; + background-image: linear-gradient(180deg, #462e55, transparent); + color: #fff; + } +} + +// Input elements +@import "classes/input/button"; +@import "classes/input/text"; +@import "classes/input/textarea"; + +// Base styles +@import "classes/avatar"; +@import "classes/container"; +@import "classes/heading"; + +// Specific styles +@import "classes/footer"; +@import "classes/header"; +@import "classes/navigation"; +@import "classes/profile"; + +// Forums +@import "classes/forum/listing"; diff --git a/build.sh b/build.sh index 9dc7c991..8cb8d2c5 100644 --- a/build.sh +++ b/build.sh @@ -40,24 +40,24 @@ lessc --verbose $STYLE_DIR/$LESS_ENTRY_FILE $PUBLIC_CSS/$STYLE_NAME.css echo done -# scripts -echo -echo "=> TypeScript" -for SCRIPT_DIR in $ASSETS_TS/*/; do -SCRIPT_NAME=`basename $SCRIPT_DIR` -SCRIPT_NAME_LOWER=`echo $SCRIPT_NAME | tr '[A-Z]' '[a-z]'` -echo "==> $SCRIPT_NAME" -find $SCRIPT_DIR -name "*.ts" | xargs tsc \ - -d \ - -t es5 \ - --listFiles \ - --listEmittedFiles \ - --noImplicitAny \ - --removeComments \ - --outFile $PUBLIC_JS/$SCRIPT_NAME_LOWER.js -mv -v $PUBLIC_JS/$SCRIPT_NAME_LOWER.d.ts $ASSETS_TS/$SCRIPT_NAME.d.ts -echo -done +# scripts (don't need yet, build script gets stuck here bc no files exists) +# echo +# echo "=> TypeScript" +# for SCRIPT_DIR in $ASSETS_TS/*/; do +# SCRIPT_NAME=`basename $SCRIPT_DIR` +# SCRIPT_NAME_LOWER=`echo $SCRIPT_NAME | tr '[A-Z]' '[a-z]'` +# echo "==> $SCRIPT_NAME" +# find $SCRIPT_DIR -name "*.ts" | xargs tsc \ +# -d \ +# -t es5 \ +# --listFiles \ +# --listEmittedFiles \ +# --noImplicitAny \ +# --removeComments \ +# --outFile $PUBLIC_JS/$SCRIPT_NAME_LOWER.js +# mv -v $PUBLIC_JS/$SCRIPT_NAME_LOWER.d.ts $ASSETS_TS/$SCRIPT_NAME.d.ts +# echo +# done # node imports echo diff --git a/public/auth.php b/public/auth.php index 0148df69..0ae68161 100644 --- a/public/auth.php +++ b/public/auth.php @@ -19,137 +19,160 @@ $username_validation_errors = [ ]; $mode = $_GET['m'] ?? 'login'; +$prevent_registration = $app->config->get('Auth', 'prevent_registration', 'bool', false); $app->templating->var('auth_mode', $mode); +$app->templating->addPath('auth', __DIR__ . '/../views/auth'); +$app->templating->var('prevent_registration', $prevent_registration); + +if (!empty($_REQUEST['username'])) { + $app->templating->var('auth_username', $_REQUEST['username']); +} + +if (!empty($_REQUEST['email'])) { + $app->templating->var('auth_email', $_REQUEST['email']); +} switch ($mode) { case 'logout': if ($app->getSession() === null) { - echo "You aren't logged in."; - } else { - echo "You've been logged out."; + header('Location: /'); + return; + } + + // this is temporary, don't scream at me for using md5 + if (isset($_GET['s']) && md5($app->getSession()->session_key) === $_GET['s']) { set_cookie_m('uid', '', -3600); set_cookie_m('sid', '', -3600); $app->getSession()->delete(); $app->setSession(null); + header('Location: /'); + return; } - echo ''; + echo $app->templating->render('logout'); break; case 'login': if ($app->getSession() !== null) { - echo ''; + header('Location: /'); break; } - if ($_SERVER['REQUEST_METHOD'] === 'GET') { - echo $app->templating->render('auth.login'); - break; + $auth_login_error = ''; + + while ($_SERVER['REQUEST_METHOD'] === 'POST') { + if (!isset($_POST['username'], $_POST['password'])) { + $auth_login_error = "You didn't fill all the forms!"; + break; + } + + $username = $_POST['username'] ?? ''; + $password = $_POST['password'] ?? ''; + + try { + $user = User::where('username', $username)->orWhere('email', $username)->firstOrFail(); + } catch (ModelNotFoundException $e) { + $auth_login_error = 'Invalid username or password!'; + break; + } + + if (!$user->validatePassword($password)) { + $auth_login_error = 'Invalid username or password!'; + break; + } + + $session = Session::createSession($user, 'Misuzu T2'); + $app->setSession($session); + set_cookie_m('uid', $session->user_id, 604800); + set_cookie_m('sid', $session->session_key, 604800); + + // Temporary key generation for chat login. + // Should eventually be replaced with a callback login system. + // Also uses different cookies since $httponly is required to be false for these. + $user->last_ip = IPAddress::remote(); + $user->user_chat_key = bin2hex(random_bytes(16)); + $user->save(); + + setcookie('msz_tmp_id', $user->user_id, time() + 604800, '/', '.flashii.net'); + setcookie('msz_tmp_key', $user->user_chat_key, time() + 604800, '/', '.flashii.net'); + header('Location: /'); + return; } - if (!isset($_POST['username'], $_POST['password'])) { - echo json_encode_m(['error' => "You didn't fill all the forms!"]); - break; + if (!empty($auth_login_error)) { + $app->templating->var('auth_login_error', $auth_login_error); } - $username = $_POST['username'] ?? ''; - $password = $_POST['password'] ?? ''; - - try { - $user = User::where('username', $username)->orWhere('email', $username)->firstOrFail(); - } catch (ModelNotFoundException $e) { - echo json_encode_m(['error' => 'Invalid username or password!']); - break; - } - - if (!$user->validatePassword($password)) { - echo json_encode_m(['error' => 'Invalid username or password!']); - break; - } - - $session = Session::createSession($user, 'Misuzu T2'); - $app->setSession($session); - set_cookie_m('uid', $session->user_id, 604800); - set_cookie_m('sid', $session->session_key, 604800); - - // Temporary key generation for chat login. - // Should eventually be replaced with a callback login system. - // Also uses different cookies since $httponly is required to be false for these. - $user->last_ip = IPAddress::remote(); - $user->user_chat_key = bin2hex(random_bytes(16)); - $user->save(); - - setcookie('msz_tmp_id', $user->user_id, time() + 604800, '/', '.flashii.net'); - setcookie('msz_tmp_key', $user->user_chat_key, time() + 604800, '/', '.flashii.net'); - - echo json_encode_m(['error' => 'You are now logged in!', 'next' => '/']); + echo $app->templating->render('auth'); break; case 'register': if ($app->getSession() !== null) { - return ''; + header('Location: /'); } - $prevent_registration = $app->config->get('Auth', 'prevent_registration', 'bool', false); + $auth_register_error = ''; - if ($_SERVER['REQUEST_METHOD'] === 'GET') { - $app->templating->var('prevent_registration', $prevent_registration); - echo $app->templating->render('auth.register'); - break; - } - - if ($prevent_registration) { - echo json_encode_m(['error' => 'Registration is not allowed on this instance.']); - break; - } - - if (!isset($_POST['username'], $_POST['password'], $_POST['email'])) { - echo json_encode_m(['error' => "You didn't fill all the forms!"]); - break; - } - - $username = $_POST['username'] ?? ''; - $username_validate = User::validateUsername($username); - $password = $_POST['password'] ?? ''; - $email = $_POST['email'] ?? ''; - - if ($username_validate !== '') { - echo json_encode_m(['error' => $username_validation_errors[$username_validate]]); - break; - } - - try { - $existing = User::where('username', $username)->firstOrFail(); - - if ($existing->user_id > 0) { - echo json_encode_m(['error' => 'This username is already taken!']); + while ($_SERVER['REQUEST_METHOD'] === 'POST') { + if ($prevent_registration) { + $auth_register_error = 'Registration is not allowed on this instance.'; break; } - } catch (ModelNotFoundException $e) { - } - if (!filter_var($email, FILTER_VALIDATE_EMAIL) || !check_mx_record($email)) { - echo json_encode_m(['error' => 'The e-mail address you entered is invalid!']); - break; - } - - try { - $existing = User::where('email', $email)->firstOrFail(); - - if ($existing->user_id > 0) { - echo json_encode_m(['error' => 'This e-mail address has already been used!']); + if (!isset($_POST['username'], $_POST['password'], $_POST['email'])) { + $auth_register_error = "You didn't fill all the forms!"; break; } - } catch (ModelNotFoundException $e) { - } - if (password_entropy($password) < 32) { - echo json_encode_m(['error' => 'Your password is too weak!']); + $username = $_POST['username'] ?? ''; + $username_validate = User::validateUsername($username); + $password = $_POST['password'] ?? ''; + $email = $_POST['email'] ?? ''; + + if ($username_validate !== '') { + $auth_register_error = $username_validation_errors[$username_validate]; + break; + } + + try { + $existing = User::where('username', $username)->firstOrFail(); + + if ($existing->user_id > 0) { + $auth_register_error = 'This username is already taken!'; + break; + } + } catch (ModelNotFoundException $e) { + } + + if (!filter_var($email, FILTER_VALIDATE_EMAIL) || !check_mx_record($email)) { + $auth_register_error = 'The e-mail address you entered is invalid!'; + break; + } + + try { + $existing = User::where('email', $email)->firstOrFail(); + + if ($existing->user_id > 0) { + $auth_register_error = 'This e-mail address has already been used!'; + break; + } + } catch (ModelNotFoundException $e) { + } + + if (password_entropy($password) < 32) { + $auth_register_error = 'Your password is too weak!'; + break; + } + + User::createUser($username, $password, $email); + $app->templating->var('auth_register_message', 'Welcome to Flashii! You may now log in.'); break; } - User::createUser($username, $password, $email); + if (!empty($auth_register_error)) { + $app->templating->var('auth_register_error', $auth_register_error); + } - echo json_encode_m(['error' => 'Welcome to Flashii! You may now log in.', 'next' => '/auth.php?m=login']); + echo $app->templating->render('auth'); break; } diff --git a/src/Application.php b/src/Application.php index 78535149..932a0d59 100644 --- a/src/Application.php +++ b/src/Application.php @@ -119,6 +119,8 @@ class Application extends ApplicationBase $twig->addFilter('json_decode'); $twig->addFilter('byte_symbol'); + $twig->addFilter('country_name', 'get_country_name'); + $twig->addFilter('md5'); // using this for logout CSRF for now, remove this when proper CSRF is in place $twig->addFunction('byte_symbol'); $twig->addFunction('session_id'); @@ -128,6 +130,6 @@ class Application extends ApplicationBase $twig->var('app', $this); - $twig->addPath('nova', __DIR__ . '/../views/nova'); + $twig->addPath('mio', __DIR__ . '/../views/mio'); } } diff --git a/src/TemplateEngine.php b/src/TemplateEngine.php index 7e005768..f194132a 100644 --- a/src/TemplateEngine.php +++ b/src/TemplateEngine.php @@ -37,7 +37,7 @@ class TemplateEngine private $vars = []; /** - * Creates the twig environment and registers the utility filters and functions. + * Creates the twig environment. */ public function __construct( ?string $cache = null, diff --git a/utility.php b/utility.php index 3b0da27c..92d49256 100644 --- a/utility.php +++ b/utility.php @@ -113,6 +113,23 @@ function get_country_code(string $ipAddr, string $fallback = 'XX'): string return $fallback; } +function get_country_name(string $code): string +{ + switch (strtolower($code)) { + case 'xx': + return 'Unknown'; + + case 'a1': + return 'Anonymous Proxy'; + + case 'a2': + return 'Satellite Provider'; + + default: + return locale_get_display_region("-{$code}", 'en'); + } +} + function is_int_ex($value, int $boundary_low, int $boundary_high): bool { return is_int($value) && $value >= $boundary_low && $value <= $boundary_high; diff --git a/views/auth/auth.twig b/views/auth/auth.twig new file mode 100644 index 00000000..38178fb2 --- /dev/null +++ b/views/auth/auth.twig @@ -0,0 +1,80 @@ +{% extends '@auth/master.twig' %} + +{% block content %} +
You're currently using the site via the public testing website, if you want to create an account please do so from the main website.
+Welcome to Flashii, the site is still heavily in development. You can follow us on {{ link('https://twitter.com/flashiinet', 'Twitter') }} where we'll post updates every so often, we'll also announce when the site is ready for public use there!
+ {% if app.session == null %} +You can create an account already though, if you'd like!
+ {% else %} +If you want a custom avatar, let me (flash) know and I'll set it for you. The settings page doesn't exist yet..
+ {% endif %} +I decided to shelve it for a bit. I'm working on this all by myself and I'm not a designer, so coming up with good designs that flow nicely together isn't easy for me.
+This layout is a LOT simpler to work with than the other one, so this'll be the main design until later.
+A dark mode will also be available at a later date and for those that grow attached this to javascript light style, you will eventually be able to switch to this design whenever you like from your settings!
+You're currently using the site via the public testing end, if you want to create an account please do so from the main website.
-