diff --git a/public/image/avatar.png b/public/image/avatar.png
new file mode 100644
index 0000000..25ce30e
Binary files /dev/null and b/public/image/avatar.png differ
diff --git a/public/image/icynet-icon-analytics.svg b/public/image/icynet-icon-analytics.svg
new file mode 100644
index 0000000..2eacb6b
--- /dev/null
+++ b/public/image/icynet-icon-analytics.svg
@@ -0,0 +1,117 @@
+
+
diff --git a/public/image/icynet-icon-git.svg b/public/image/icynet-icon-git.svg
new file mode 100644
index 0000000..86b8a2c
--- /dev/null
+++ b/public/image/icynet-icon-git.svg
@@ -0,0 +1,134 @@
+
+
+
+
diff --git a/public/image/icynet-icon-large.png b/public/image/icynet-icon-large.png
new file mode 100644
index 0000000..69c4eb0
Binary files /dev/null and b/public/image/icynet-icon-large.png differ
diff --git a/public/image/icynet-icon-pleroma.svg b/public/image/icynet-icon-pleroma.svg
new file mode 100644
index 0000000..94843f1
--- /dev/null
+++ b/public/image/icynet-icon-pleroma.svg
@@ -0,0 +1,103 @@
+
+
diff --git a/public/image/icynet-icon.png b/public/image/icynet-icon.png
new file mode 100644
index 0000000..0fa1c85
Binary files /dev/null and b/public/image/icynet-icon.png differ
diff --git a/public/image/icynet-icon.svg b/public/image/icynet-icon.svg
new file mode 100644
index 0000000..7c21d99
--- /dev/null
+++ b/public/image/icynet-icon.svg
@@ -0,0 +1,134 @@
+
+
+
+
diff --git a/public/image/icynet-large.png b/public/image/icynet-large.png
new file mode 100644
index 0000000..bda0598
Binary files /dev/null and b/public/image/icynet-large.png differ
diff --git a/public/image/icynet-small.png b/public/image/icynet-small.png
new file mode 100644
index 0000000..73abf84
Binary files /dev/null and b/public/image/icynet-small.png differ
diff --git a/public/image/icynet.ico b/public/image/icynet.ico
new file mode 100644
index 0000000..6e135cf
Binary files /dev/null and b/public/image/icynet.ico differ
diff --git a/public/image/icynet.svg b/public/image/icynet.svg
new file mode 100644
index 0000000..a4ae9c8
--- /dev/null
+++ b/public/image/icynet.svg
@@ -0,0 +1,152 @@
+
+
diff --git a/public/image/squeebot.svg b/public/image/squeebot.svg
new file mode 100644
index 0000000..2beb9e1
--- /dev/null
+++ b/public/image/squeebot.svg
@@ -0,0 +1,703 @@
+
+
+
+
diff --git a/src/app.module.ts b/src/app.module.ts
index e736cc2..a1675a4 100644
--- a/src/app.module.ts
+++ b/src/app.module.ts
@@ -2,7 +2,6 @@ import { MiddlewareConsumer, Module, NestModule } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { CSRFMiddleware } from './middleware/csrf.middleware';
-import { FlashMiddleware } from './middleware/flash.middleware';
import { LoginModule } from './modules/features/login/login.module';
import { OAuth2Module } from './modules/features/oauth2/oauth2.module';
import { RegisterModule } from './modules/features/register/register.module';
@@ -33,8 +32,5 @@ import { UtilityModule } from './modules/utility/utility.module';
export class AppModule implements NestModule {
configure(consumer: MiddlewareConsumer) {
consumer.apply(CSRFMiddleware).forRoutes('*');
- consumer
- .apply(FlashMiddleware)
- .forRoutes('login', 'register', 'login/verify', 'two-factor');
}
}
diff --git a/src/modules/features/login/login.controller.ts b/src/modules/features/login/login.controller.ts
index 6aa942e..706adc6 100644
--- a/src/modules/features/login/login.controller.ts
+++ b/src/modules/features/login/login.controller.ts
@@ -25,7 +25,7 @@ export class LoginController {
) {}
@Get()
- @Render('login')
+ @Render('login/login')
public loginView(
@Session() session: SessionData,
@Req() req: Request,
@@ -92,7 +92,10 @@ export class LoginController {
return;
}
- res.render('totp-verify', this.formUtil.populateTemplate(req, session));
+ res.render(
+ 'login/totp-verify',
+ this.formUtil.populateTemplate(req, session),
+ );
}
@Post('verify')
diff --git a/src/modules/features/login/login.module.ts b/src/modules/features/login/login.module.ts
index 7435150..d51f393 100644
--- a/src/modules/features/login/login.module.ts
+++ b/src/modules/features/login/login.module.ts
@@ -4,6 +4,7 @@ import {
NestModule,
RequestMethod,
} from '@nestjs/common';
+import { FlashMiddleware } from 'src/middleware/flash.middleware';
import { ValidateCSRFMiddleware } from 'src/middleware/validate-csrf.middleware';
import { UserModule } from 'src/modules/objects/user/user.module';
import { LoginController } from './login.controller';
@@ -17,5 +18,7 @@ export class LoginModule implements NestModule {
consumer
.apply(ValidateCSRFMiddleware)
.forRoutes({ path: '*', method: RequestMethod.POST });
+
+ consumer.apply(FlashMiddleware).forRoutes('*');
}
}
diff --git a/src/modules/features/register/register.module.ts b/src/modules/features/register/register.module.ts
index ad14c66..b04d152 100644
--- a/src/modules/features/register/register.module.ts
+++ b/src/modules/features/register/register.module.ts
@@ -4,6 +4,7 @@ import {
NestModule,
RequestMethod,
} from '@nestjs/common';
+import { FlashMiddleware } from 'src/middleware/flash.middleware';
import { ValidateCSRFMiddleware } from 'src/middleware/validate-csrf.middleware';
import { UserModule } from 'src/modules/objects/user/user.module';
import { RegisterController } from './register.controller';
@@ -17,5 +18,7 @@ export class RegisterModule implements NestModule {
consumer
.apply(ValidateCSRFMiddleware)
.forRoutes({ path: '*', method: RequestMethod.POST });
+
+ consumer.apply(FlashMiddleware).forRoutes('*');
}
}
diff --git a/src/modules/features/twofactor/twofactor.module.ts b/src/modules/features/twofactor/twofactor.module.ts
index 3e6ed4b..b0e6a18 100644
--- a/src/modules/features/twofactor/twofactor.module.ts
+++ b/src/modules/features/twofactor/twofactor.module.ts
@@ -1,5 +1,6 @@
import { MiddlewareConsumer, Module, NestModule } from '@nestjs/common';
import { AuthMiddleware } from 'src/middleware/auth.middleware';
+import { FlashMiddleware } from 'src/middleware/flash.middleware';
import { UserModule } from 'src/modules/objects/user/user.module';
import { TwoFactorController } from './twofactor.controller';
@@ -10,5 +11,6 @@ import { TwoFactorController } from './twofactor.controller';
export class TwoFactorModule implements NestModule {
configure(consumer: MiddlewareConsumer) {
consumer.apply(AuthMiddleware).forRoutes('two-factor');
+ consumer.apply(FlashMiddleware).forRoutes('*');
}
}
diff --git a/src/scss/_alert.scss b/src/scss/_alert.scss
new file mode 100644
index 0000000..48409d4
--- /dev/null
+++ b/src/scss/_alert.scss
@@ -0,0 +1,12 @@
+.alert {
+ padding: 16px;
+ border-radius: 4px;
+
+ &-danger {
+ background-color: #ff292999;
+ }
+
+ &-success {
+ background-color: #12930099;
+ }
+}
diff --git a/src/scss/_block.scss b/src/scss/_block.scss
new file mode 100644
index 0000000..45c1d3d
--- /dev/null
+++ b/src/scss/_block.scss
@@ -0,0 +1,29 @@
+.wrapper {
+}
+
+.container {
+ max-width: 1200px;
+ margin: auto;
+}
+
+.center-box {
+ max-width: 800px;
+ background-color: #2e6b81;
+ color: #fff;
+ margin: 2rem auto;
+ padding: 4rem;
+
+ box-shadow: 0px 6px 62px -14px rgba(0, 0, 0, 0.45);
+ -webkit-box-shadow: 0px 6px 62px -14px rgba(0, 0, 0, 0.45);
+ -moz-box-shadow: 0px 6px 62px -14px rgba(0, 0, 0, 0.45);
+
+ h1:first-of-type {
+ margin-top: 0;
+ text-align: center;
+ }
+}
+
+.logo-container {
+ text-align: center;
+ margin-top: 2rem;
+}
diff --git a/src/scss/_button.scss b/src/scss/_button.scss
new file mode 100644
index 0000000..536e2b6
--- /dev/null
+++ b/src/scss/_button.scss
@@ -0,0 +1,37 @@
+.btn {
+ padding: 12px 24px;
+ font-size: 1rem;
+ appearance: none;
+ border: none;
+ border-radius: 4px;
+ cursor: pointer;
+ outline: 0px solid #00c0ff8a;
+
+ min-width: 120px;
+ transition: background-color 0.35s linear, outline 0.15s linear;
+
+ &-link {
+ font-size: 1rem;
+ color: #fff;
+ padding: 12px;
+ }
+
+ background-color: var(--btn-background);
+ color: var(--btn-color);
+
+ &:hover {
+ background-color: var(--btn-background-hover);
+ }
+
+ &:focus {
+ outline: 4px solid #00c0ff8a;
+ }
+
+ &-primary {
+ --btn-background: #00c4ff;
+ --btn-background-hover: #3ed2ff;
+ --btn-color: #002d34;
+ text-transform: uppercase;
+ font-weight: 500;
+ }
+}
diff --git a/src/scss/_flex.scss b/src/scss/_flex.scss
new file mode 100644
index 0000000..793fb7d
--- /dev/null
+++ b/src/scss/_flex.scss
@@ -0,0 +1,18 @@
+.align-self-end {
+ align-self: end;
+}
+.align-self-start {
+ align-self: start;
+}
+.align-self-center {
+ align-self: center;
+}
+.d-flex {
+ display: flex;
+}
+.flex-column {
+ flex-direction: column;
+}
+.flex-row {
+ flex-direction: row;
+}
diff --git a/src/scss/_form.scss b/src/scss/_form.scss
new file mode 100644
index 0000000..32b18c1
--- /dev/null
+++ b/src/scss/_form.scss
@@ -0,0 +1,33 @@
+.form-container {
+ display: flex;
+ flex-direction: column;
+
+ .btn {
+ margin-top: 1rem;
+ }
+}
+
+.form-label {
+ margin-top: 1rem;
+ text-transform: uppercase;
+ font-weight: 600;
+ margin-bottom: 0.25rem;
+}
+
+input.form-control {
+ padding: 8px;
+ font-size: 1rem;
+ border-radius: 4px;
+ border: 1px solid #707070;
+
+ transition: outline 0.15s linear;
+
+ &:focus {
+ outline: 4px solid #00c0ff8a;
+ }
+
+ &:hover,
+ &:focus {
+ border: 1px solid #5c5c5c;
+ }
+}
diff --git a/src/scss/_index.scss b/src/scss/_index.scss
index f928e46..86bdf0c 100644
--- a/src/scss/_index.scss
+++ b/src/scss/_index.scss
@@ -1,3 +1,9 @@
+@import 'block';
+@import 'form';
+@import 'button';
+@import 'flex';
+@import 'alert';
+
*,
*::before,
*::after {
@@ -6,8 +12,6 @@
html,
body {
- width: 100%;
- height: 100%;
margin: 0;
padding: 0;
}
@@ -15,4 +19,5 @@ body {
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen,
Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
+ background-color: #314550;
}
diff --git a/views/index.pug b/views/index.pug
index daa6c5b..4118704 100644
--- a/views/index.pug
+++ b/views/index.pug
@@ -4,6 +4,9 @@ block title
|Icy Network
block body
- h1 Hello world!
- if user
- h2 Logged in as #{ user.display_name }
+ include partials/logo.pug
+ div.container
+ div.center-box
+ h1 Hello, #{ user.display_name }!
+ p No pending authorization requests found.
+ p Have a good day!
diff --git a/views/login.pug b/views/login.pug
deleted file mode 100644
index fa386b4..0000000
--- a/views/login.pug
+++ /dev/null
@@ -1,20 +0,0 @@
-extends partials/layout.pug
-
-block title
- |Icy Network | Log in
-
-block body
- h1 Log in
- if message.text
- if message.error
- .alert.alert-danger
- span #{message.text}
- else
- .alert.alert-success
- span #{message.text}
-
- form(method="post")
- input#csrf(type="hidden", name="csrf", value=csrf)
- input#username(type="text", name="username", placeholder="Username", value=form.username)
- input#password(type="password", name="password", placeholder="Password")
- button(type="submit") Log in
diff --git a/views/login/login.pug b/views/login/login.pug
new file mode 100644
index 0000000..9b1f8c6
--- /dev/null
+++ b/views/login/login.pug
@@ -0,0 +1,27 @@
+extends ../partials/layout.pug
+
+block title
+ |Icy Network | Log in
+
+block body
+ include ../partials/logo.pug
+ div.container
+ div.center-box
+ h1 Log in
+ if message.text
+ if message.error
+ .alert.alert-danger
+ span #{message.text}
+ else
+ .alert.alert-success
+ span #{message.text}
+
+ form(method="post")
+ div.form-container
+ input#csrf(type="hidden", name="csrf", value=csrf)
+ label.form-label(for="username") Username
+ input.form-control#username(type="text", name="username", placeholder="Username", value=form.username)
+ label.form-label(for="password") Password
+ input.form-control#password(type="password", name="password", placeholder="Password")
+ button.btn.btn-primary(type="submit") Log in
+ a.btn.btn-link.align-self-end(type="button" href="/register") Create a new account
diff --git a/views/login/totp-verify.pug b/views/login/totp-verify.pug
new file mode 100644
index 0000000..d461e6e
--- /dev/null
+++ b/views/login/totp-verify.pug
@@ -0,0 +1,24 @@
+extends ../partials/layout.pug
+
+block title
+ |Icy Network | Veify two-factor
+
+block body
+ include ../partials/logo.pug
+ div.container
+ div.center-box
+ h1 Verify two-factor authentication
+ if message.text
+ if message.error
+ .alert.alert-danger
+ span #{message.text}
+ else
+ .alert.alert-success
+ span #{message.text}
+
+ form(method="post")
+ div.form-container
+ input#csrf(type="hidden", name="csrf", value=csrf)
+ label.form-label(for="totp") Code
+ input.form-control#totp(type="text", name="totp", placeholder="xxxxxx")
+ button.btn.btn-primary(type="submit") Log in
diff --git a/views/partials/layout.pug b/views/partials/layout.pug
index 0e6a64f..bd612e0 100644
--- a/views/partials/layout.pug
+++ b/views/partials/layout.pug
@@ -16,5 +16,6 @@ html(lang="en")
link(rel="stylesheet", type="text/css", href="/public/css/index.css")
title
block title
- body
- block body
+ body
+ main.wrapper
+ block body
diff --git a/views/partials/logo.pug b/views/partials/logo.pug
new file mode 100644
index 0000000..57e7478
--- /dev/null
+++ b/views/partials/logo.pug
@@ -0,0 +1,2 @@
+div.logo-container
+ img(src="/public/image/icynet-icon.svg", alt="Icy Network")
diff --git a/views/register.pug b/views/register.pug
index 14ed1f5..066fa4a 100644
--- a/views/register.pug
+++ b/views/register.pug
@@ -4,21 +4,30 @@ block title
|Icy Network | Register
block body
- h1 Register
- if message.text
- if message.error
- .alert.alert-danger
- span #{message.text}
- else
- .alert.alert-success
- span #{message.text}
+ include partials/logo.pug
+ div.container
+ div.center-box
+ h1 Register
+ if message.text
+ if message.error
+ .alert.alert-danger
+ span #{message.text}
+ else
+ .alert.alert-success
+ span #{message.text}
- form(method="post")
- input#csrf(type="hidden", name="csrf", value=csrf)
- input#username(type="text", name="username", placeholder="Username", value=form.username)
- input#display_name(type="text", name="display_name", placeholder="Display name", value=form.display_name)
- input#email(type="email", name="email", placeholder="Email address", value=form.email)
- input#password(type="password", name="password", placeholder="Password", value=form.password)
- input#password_repeat(type="password", name="password_repeat", placeholder="Confirm password")
- button(type="submit") Create a new account
- a(type="button" href="/login") Log in
+ form(method="post")
+ div.form-container
+ input#csrf(type="hidden", name="csrf", value=csrf)
+ label.form-label(for="username") Username
+ input.form-control#username(type="text", name="username", placeholder="Username", value=form.username)
+ label.form-label(for="display_name") Display name
+ input.form-control#display_name(type="text", name="display_name", placeholder="Display name", value=form.display_name)
+ label.form-label(for="email") Email address
+ input.form-control#email(type="email", name="email", placeholder="Email address", value=form.email)
+ label.form-label(for="password") Password
+ input.form-control#password(type="password", name="password", placeholder="Password", value=form.password)
+ label.form-label(for="password_repeat") Confirm password
+ input.form-control#password_repeat(type="password", name="password_repeat", placeholder="Confirm password")
+ button.btn.btn-primary(type="submit") Create a new account
+ a.btn.btn-link.align-self-end(type="button" href="/login") Log in instead
diff --git a/views/totp-verify.pug b/views/totp-verify.pug
deleted file mode 100644
index 09d2e9f..0000000
--- a/views/totp-verify.pug
+++ /dev/null
@@ -1,19 +0,0 @@
-extends partials/layout.pug
-
-block title
- |Icy Network | Veify two-factor
-
-block body
- h1 Verify two-factor authentication
- if message.text
- if message.error
- .alert.alert-danger
- span #{message.text}
- else
- .alert.alert-success
- span #{message.text}
-
- form(method="post")
- input#csrf(type="hidden", name="csrf", value=csrf)
- input#totp(type="text", name="totp", placeholder="Code")
- button(type="submit") Log in
diff --git a/views/two-factor/activate.pug b/views/two-factor/activate.pug
index eb74f25..3000ad3 100644
--- a/views/two-factor/activate.pug
+++ b/views/two-factor/activate.pug
@@ -4,18 +4,24 @@ block title
|Icy Network | Two-factor authentication
block body
- h1 Activate two-factor authentication
- if message.text
- if message.error
- .alert.alert-danger
- span #{message.text}
- else
- .alert.alert-success
- span #{message.text}
-
- img(src=qrcode)
+ include ../partials/logo.pug
+ div.container
+ div.center-box
+ h1 Activate two-factor authentication
+ if message.text
+ if message.error
+ .alert.alert-danger
+ span #{message.text}
+ else
+ .alert.alert-success
+ span #{message.text}
+
+ div.qr-preview
+ img(src=qrcode)
- form(method="post")
- input#csrf(type="hidden", name="csrf", value=csrf)
- input#code(type="text", name="code", placeholder="Code from app")
- button(type="submit") Activate
+ form(method="post")
+ div.form-container
+ input#csrf(type="hidden", name="csrf", value=csrf)
+ label.form-label(for="code") Code from authenticator app
+ input.form-control#code(type="text", name="code", placeholder="xxxxxx")
+ button.btn.btn-primary(type="submit") Activate