From d058036da119711c46e0d067ce6ef1104a945f02 Mon Sep 17 00:00:00 2001 From: flashwave Date: Thu, 22 Mar 2018 02:56:41 +0000 Subject: [PATCH] Welcome back, mio! --- assets/less/auth/classes/button.less | 14 ++ assets/less/auth/classes/container.less | 5 + assets/less/auth/classes/form.less | 93 +++++++++ assets/less/auth/classes/logout.less | 20 ++ assets/less/auth/classes/text.less | 17 ++ assets/less/auth/main.less | 44 +++++ assets/less/mio/classes/avatar.less | 11 ++ assets/less/mio/classes/container.less | 19 ++ assets/less/mio/classes/footer.less | 25 +++ assets/less/mio/classes/forum/listing.less | 81 ++++++++ assets/less/mio/classes/header.less | 90 +++++++++ assets/less/mio/classes/heading.less | 5 + assets/less/mio/classes/input/button.less | 29 +++ assets/less/mio/classes/input/text.less | 15 ++ assets/less/mio/classes/input/textarea.less | 16 ++ assets/less/mio/classes/navigation.less | 111 +++++++++++ assets/less/mio/classes/profile.less | 120 +++++++++++ assets/less/mio/main.less | 52 +++++ build.sh | 36 ++-- public/auth.php | 209 +++++++++++--------- src/Application.php | 4 +- src/TemplateEngine.php | 2 +- utility.php | 17 ++ views/auth/auth.twig | 80 ++++++++ views/auth/logout.twig | 13 ++ views/auth/master.twig | 14 ++ views/mio/_layout/meta.twig | 21 ++ views/mio/home/landing.twig | 25 +++ views/mio/home/master.twig | 1 + views/mio/macros.twig | 16 ++ views/mio/master.twig | 73 +++++++ views/mio/user/master.twig | 1 + views/mio/user/view.twig | 42 ++++ views/nova/auth/login.twig | 25 --- views/nova/auth/master.twig | 58 ------ views/nova/auth/register.twig | 37 ---- views/nova/master.twig | 2 +- views/nova/user/view.twig | 2 +- 38 files changed, 1210 insertions(+), 235 deletions(-) create mode 100644 assets/less/auth/classes/button.less create mode 100644 assets/less/auth/classes/container.less create mode 100644 assets/less/auth/classes/form.less create mode 100644 assets/less/auth/classes/logout.less create mode 100644 assets/less/auth/classes/text.less create mode 100644 assets/less/auth/main.less create mode 100644 assets/less/mio/classes/avatar.less create mode 100644 assets/less/mio/classes/container.less create mode 100644 assets/less/mio/classes/footer.less create mode 100644 assets/less/mio/classes/forum/listing.less create mode 100644 assets/less/mio/classes/header.less create mode 100644 assets/less/mio/classes/heading.less create mode 100644 assets/less/mio/classes/input/button.less create mode 100644 assets/less/mio/classes/input/text.less create mode 100644 assets/less/mio/classes/input/textarea.less create mode 100644 assets/less/mio/classes/navigation.less create mode 100644 assets/less/mio/classes/profile.less create mode 100644 assets/less/mio/main.less create mode 100644 views/auth/auth.twig create mode 100644 views/auth/logout.twig create mode 100644 views/auth/master.twig create mode 100644 views/mio/_layout/meta.twig create mode 100644 views/mio/home/landing.twig create mode 100644 views/mio/home/master.twig create mode 100644 views/mio/macros.twig create mode 100644 views/mio/master.twig create mode 100644 views/mio/user/master.twig create mode 100644 views/mio/user/view.twig delete mode 100644 views/nova/auth/login.twig delete mode 100644 views/nova/auth/master.twig delete mode 100644 views/nova/auth/register.twig 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 %} +
+
+ + +
+ +
+ +
+ + {% if prevent_registration|default(false) %} +
+

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.

+
+ {% else %} +
+ + + +
+
+ {{ auth_register_message|default(auth_register_error|default('')) }} +
+
+ +
+
+
+ {% endif %} +
+
+ + {#
+ +
+ +
+ +
+
+ {{ auth_restore_message|default(auth_restore_error|default('')) }} +
+
+ +
+
+
+
+
#} +
+{% endblock %} diff --git a/views/auth/logout.twig b/views/auth/logout.twig new file mode 100644 index 00000000..85aa0f9a --- /dev/null +++ b/views/auth/logout.twig @@ -0,0 +1,13 @@ +{% extends '@auth/master.twig' %} + +{% block content %} +
+
+

We couldn't verify that you were actually the person attempting to log out.

+

Press the button below to verify the logout request, otherwise click back in your browser or close this tab.

+
+
+ Logout +
+
+{% endblock %} diff --git a/views/auth/master.twig b/views/auth/master.twig new file mode 100644 index 00000000..d7a47807 --- /dev/null +++ b/views/auth/master.twig @@ -0,0 +1,14 @@ + + + + + Authentication + + + + +
+ {{ block('content') is defined ? block('content') : '' }} +
+ + diff --git a/views/mio/_layout/meta.twig b/views/mio/_layout/meta.twig new file mode 100644 index 00000000..8cec802e --- /dev/null +++ b/views/mio/_layout/meta.twig @@ -0,0 +1,21 @@ +{% set title = title|default('Flashii') %} +{% set description = description|default("Where the floor doesn't fall far from the carrot.") %} + + {{ title }} + + + + + + + + + + + + + +{% if icon is defined %} + + +{% endif %} diff --git a/views/mio/home/landing.twig b/views/mio/home/landing.twig new file mode 100644 index 00000000..734d1076 --- /dev/null +++ b/views/mio/home/landing.twig @@ -0,0 +1,25 @@ +{% extends '@mio/home/master.twig' %} +{% from '@mio/macros.twig' import navigation, link %} + +{% block content %} +
+
Welcome!
+
+

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 %} +
+
What happened to the previous design?
+
+

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!

+
+
+ + {{ navigation(mio_navigation, '/') }} +{% endblock %} + diff --git a/views/mio/home/master.twig b/views/mio/home/master.twig new file mode 100644 index 00000000..187fe3a8 --- /dev/null +++ b/views/mio/home/master.twig @@ -0,0 +1 @@ +{% extends '@mio/master.twig' %} diff --git a/views/mio/macros.twig b/views/mio/macros.twig new file mode 100644 index 00000000..7c0e6c0b --- /dev/null +++ b/views/mio/macros.twig @@ -0,0 +1,16 @@ +{% macro link(url, content, class) %} +{% spaceless %} +{{ content|raw }} +{% endspaceless %} +{% endmacro %} + +{% macro navigation(links, current, top) %} + {% set top = top|default(false) == true %} + {% set current = current|default(null) %} + + +{% endmacro %} diff --git a/views/mio/master.twig b/views/mio/master.twig new file mode 100644 index 00000000..49ea65a0 --- /dev/null +++ b/views/mio/master.twig @@ -0,0 +1,73 @@ +{% from '@mio/macros.twig' import link, navigation %} + +{% set mio_navigation = { + 'Home':'/', + 'Chat':'https://chat.flashii.net', +} %} + + + + + + + {% include '@mio/_layout/meta.twig' %} + + + + + +
+
+ +
+ {% if app.session is not null %} +
+
Hey, {{ app.session.user.username }}!
+
+
+ +
+
+ {% else %} + Login/Register + {% endif %} +
+
+ + {% block content %} +
+
Hello!
+
+ This page has no content! +
+
+ + {{ navigation(mio_navigation) }} + {% endblock %} + + +
+ + diff --git a/views/mio/user/master.twig b/views/mio/user/master.twig new file mode 100644 index 00000000..187fe3a8 --- /dev/null +++ b/views/mio/user/master.twig @@ -0,0 +1 @@ +{% extends '@mio/master.twig' %} diff --git a/views/mio/user/view.twig b/views/mio/user/view.twig new file mode 100644 index 00000000..59ae8c0d --- /dev/null +++ b/views/mio/user/view.twig @@ -0,0 +1,42 @@ +{% extends '@mio/user/master.twig' %} +{% from '@mio/macros.twig' import navigation %} + +{% set title = 'Profile of ' ~ profile.username %} + +{% block content %} + {{ navigation(mio_navigation, false, true) }} + +
+
+
Profile of {{ profile.username }}
+
+
+
+
+
+
+ {{ profile.user_country }} +
+
+ {{ profile.user_country|country_name }} +
+
+
+ +
+
+
+ Joined +
+
+ {{ profile.created_at.diffForHumans }} +
+
+
+
+
+
+
+
+
+{% endblock %} diff --git a/views/nova/auth/login.twig b/views/nova/auth/login.twig deleted file mode 100644 index e8996eda..00000000 --- a/views/nova/auth/login.twig +++ /dev/null @@ -1,25 +0,0 @@ -{% extends '@nova/auth/master.twig' %} - -{% set banner_classes = 'banner--large landing__banner' %} - -{% block banner_content %} -

Welcome back!

-{% endblock %} - -{% block content %} -
-
- -
-
- -
-
- -
-
- -
-
- {{ parent() }} -{% endblock %} diff --git a/views/nova/auth/master.twig b/views/nova/auth/master.twig deleted file mode 100644 index d30558b3..00000000 --- a/views/nova/auth/master.twig +++ /dev/null @@ -1,58 +0,0 @@ -{% extends '@nova/master.twig' %} - -{% block content %} - -{% endblock %} diff --git a/views/nova/auth/register.twig b/views/nova/auth/register.twig deleted file mode 100644 index b69f61ba..00000000 --- a/views/nova/auth/register.twig +++ /dev/null @@ -1,37 +0,0 @@ -{% extends '@nova/auth/master.twig' %} - -{% set banner_classes = 'banner--large landing__banner' %} - -{% block banner_content %} -

- {% if not prevent_registration %} - Welcome, thanks for dropping by! - {% else %} - Stop! - {% endif %} -

-{% endblock %} - -{% block content %} - {% if not prevent_registration %} -
-
- -
-
- -
-
- -
-
- -
-
- {{ parent() }} - {% else %} -
-

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.

-
- {% endif %} -{% endblock %} diff --git a/views/nova/master.twig b/views/nova/master.twig index c3766005..7eeb0c0b 100644 --- a/views/nova/master.twig +++ b/views/nova/master.twig @@ -4,7 +4,7 @@ - + {% include '@nova/_layout/meta.twig' %} diff --git a/views/nova/user/view.twig b/views/nova/user/view.twig index 35501247..d15f0826 100644 --- a/views/nova/user/view.twig +++ b/views/nova/user/view.twig @@ -55,7 +55,7 @@
{% spaceless %}
-
+
{% for id, data in hierarchies %} {% if data.display %}