Skip to content

Commit

Permalink
Merge pull request #148 from NIAEFEUP/develop
Browse files Browse the repository at this point in the history
release: early birds
  • Loading branch information
limwa authored Feb 12, 2025
2 parents 153a681 + e06af29 commit e88ca33
Show file tree
Hide file tree
Showing 199 changed files with 14,349 additions and 3,978 deletions.
2 changes: 2 additions & 0 deletions .github/workflows/website.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,12 @@ on:
push:
branches:
- main
- develop
paths: ["website/**"]
pull_request:
branches:
- main
- develop
paths: ["website/**"]

jobs:
Expand Down
3 changes: 3 additions & 0 deletions deploy/Dockerfile.website
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@ FROM node:22-slim AS base

ENV PNPM_HOME="/pnpm"
ENV PATH="$PNPM_HOME:$PATH"

RUN npm install -g corepack@latest

RUN corepack enable

WORKDIR /app
Expand Down
13 changes: 10 additions & 3 deletions deploy/website/entrypoint.sh
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#!/bin/sh
#!/bin/bash

set -e
set -o pipefail

# Script configuration

Expand Down Expand Up @@ -28,9 +29,13 @@ run_command() {
echo
print "# $command"

trap "print_file $_LOG_FILE" EXIT

# Strip any ANSI escape sequences from the output
eval "$command" 2>&1 | sed "s/\x1B\[[0-9;]*[a-zA-Z]//g" > "$_LOG_FILE"

trap - EXIT

print_file "$_LOG_FILE"
echo
}
Expand Down Expand Up @@ -120,11 +125,13 @@ print ">> Application preparation"
push_indent " "

if [ "$ON_STARTUP_MIGRATE" = "true" ]; then
print ">> MIGRATE_ON_STARTUP is enabled"
mode="${ON_STARTUP_MIGRATE_MODE:-run}"

print ">> ON_STARTUP_MIGRATE is enabled [mode: $mode]"
push_indent " "

print "Migrating database..."
run_command node ace migration:run --force
run_command node ace migration:$mode --force

pop_indent
fi
Expand Down
7 changes: 7 additions & 0 deletions deploy/website/railway.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"$schema": "https://railway.com/railway.schema.json",
"build": {
"builder": "DOCKERFILE",
"dockerfilePath": "./deploy/Dockerfile.website"
}
}
14 changes: 13 additions & 1 deletion docker-compose.coolify.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,23 @@ services:
- "LOG_LEVEL=${LOG_LEVEL:-info}"
- "APP_KEY=${APP_KEY}"
- "SESSION_DRIVER=${SESSION_DRIVER:-cookie}"
- "REDIS_HOST=${REDIS_HOST:-valkey}"
- "REDIS_PORT=${REDIS_PORT:-6379}"
- "REDIS_PASSWORD=${REDIS_PASSWORD}"
- "FROM_EMAIL=${FROM_EMAIL:[email protected]}"
- "SMTP_HOST=${SMTP_HOST}"
- "SMTP_PORT=${SMTP_PORT}"
- "INERTIA_PUBLIC_TZ=${INERTIA_PUBLIC_TZ:-Europe/Lisbon}"
- "INERTIA_PUBLIC_EVENT_COUNTDOWN_DATE=${INERTIA_PUBLIC_EVENT_COUNTDOWN_DATE:-2025-04-11}"

valkey:
image: valkey/valkey:8-alpine
command: ["valkey-server", "--save", "60", "1", "--loglevel", "warning"]
volumes:
- valkey-data:/data
environment:
- "VALKEY_EXTRA_FLAGS=${VALKEY_EXTRA_FLAGS}"

volumes:
website-tmp:
website-tmp:
valkey-data:
13 changes: 12 additions & 1 deletion docker-compose.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,15 @@ services:
container_name: enei-mailpit
ports:
- "1025:1025"
- "8025:8025"
- "8025:8025"

valkey:
image: valkey/valkey:8-alpine
container_name: enei-valkey
volumes:
- valkey-data:/data
ports:
- "6379:6379"

volumes:
valkey-data:
6 changes: 6 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

32 changes: 31 additions & 1 deletion website/.env.example
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,45 @@ NODE_ENV=development
# Public facing app environment variables
APP_KEY=

# Payments
IFTHENPAY_MBWAY_KEY=********

# Session
SESSION_DRIVER=cookie

# Jobs
REDIS_HOST=localhost
REDIS_PORT=6379
REDIS_PASSWORD=

# E-mail
FROM_EMAIL=[email protected]
REPLY_TO_EMAIL=[email protected]
SMTP_HOST=localhost
SMTP_PORT=1025

# Rate limiting
LIMITER_STORE=memory

# Redis
REDIS_HOST=127.0.0.1
REDIS_PORT=6379
REDIS_PASSWORD=

# Ally
GITHUB_CLIENT_ID=********
GITHUB_CLIENT_SECRET=********
GOOGLE_CLIENT_ID=********
GOOGLE_CLIENT_SECRET=********
LINKEDIN_CLIENT_ID=********
LINKEDIN_CLIENT_SECRET=********

# Feature flags
FEATURES_DISABLE_AUTH=false

# Frontend
INERTIA_PUBLIC_TZ=Europe/Lisbon
INERTIA_PUBLIC_EVENT_COUNTDOWN_DATE=2025-04-11
INERTIA_PUBLIC_APP_URL=http://127.0.0.1:3333

# Tuyau
INERTIA_PUBLIC_APP_URL=http://127.0.0.1:3333
2 changes: 2 additions & 0 deletions website/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,5 @@ yarn-error.log

# Platform specific
.DS_Store

dump.rdb
12 changes: 9 additions & 3 deletions website/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,19 +27,25 @@ To get started with the website, follow these steps:
cd enei/website
```

3. Install the dependencies:
3. Install `pnpm`:

```bash
corepack enable
```

4. Install the dependencies:

```bash
pnpm install --frozen-lockfile
```

4. Run the database migrations to create the database:
5. Run the database migrations to create the database:

```bash
node ace migration:run
```

5. Start the development server:
6. Start the development server:

```bash
pnpm run dev
Expand Down
12 changes: 11 additions & 1 deletion website/adonisrc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ export default defineConfig({
() => import('@adonisjs/lucid/commands'),
() => import('@adonisjs/mail/commands'),
() => import('@tuyau/core/commands'),
() => import('adonisjs-jobs/commands'),
],

/*
Expand Down Expand Up @@ -43,8 +44,12 @@ export default defineConfig({
() => import('@adonisjs/lucid/database_provider'),
() => import('@adonisjs/auth/auth_provider'),
() => import('@adonisjs/inertia/inertia_provider'),
() => import('adonisjs-jobs/jobs_provider'),
() => import('@adonisjs/mail/mail_provider'),
() => import('@tuyau/core/tuyau_provider'),
() => import('@adonisjs/ally/ally_provider'),
() => import('@adonisjs/limiter/limiter_provider'),
() => import('@adonisjs/redis/redis_provider'),
],

/*
Expand All @@ -55,7 +60,12 @@ export default defineConfig({
| List of modules to import before starting the application.
|
*/
preloads: [() => import('#start/routes'), () => import('#start/kernel')],
preloads: [
() => import('#start/routes'),
() => import('#start/kernel'),
() => import('#start/events'),
() => import('#start/validator'),
],

/*
|--------------------------------------------------------------------------
Expand Down
147 changes: 147 additions & 0 deletions website/app/controllers/authentication_controller.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
import type { HttpContext } from '@adonisjs/core/http'
import {
registerWithCredentialsValidator,
emailVerificationCallbackValidator,
loginWithCredentialsValidator,
passwordResetValidator,
passwordSendForgotPasswordValidator,
} from '#validators/authentication'
import { UserService } from '#services/user_service'
import { inject } from '@adonisjs/core'
import UserRequestedVerificationEmail from '#events/user_requested_verification_email'
import Account from '#models/account'

@inject()
export default class AuthenticationController {
constructor(private userService: UserService) { }

async login({ request, auth, session, response }: HttpContext) {
const { email, password } = await request.validateUsing(loginWithCredentialsValidator)

const user = await this.userService.getUserWithCredentials(email, password)
if (!user) {
session.flashErrors({ password: 'As credenciais que introduziste não são válidas' })
return response.redirect().back()
}

await auth.use('web').login(user)

return user.isEmailVerified()
? response.redirect().toRoute('pages:home')
: response.redirect().toRoute('pages:auth.verify')
}

async logout({ auth, response }: HttpContext) {
await auth.use('web').logout()
return response.redirect().toRoute('pages:home')
}

async register({ request, auth, response }: HttpContext) {
const { email, password } = await request.validateUsing(registerWithCredentialsValidator)

const [user, events] = await this.userService.createUserWithCredentials(email, password)
const [success] = await events
if (!success) {

}

await auth.use('web').login(user)

return response.redirect().toRoute('pages:auth.verify')
}

async retryEmailVerification({ auth, response }: HttpContext) {
const user = auth.getUserOrFail()

UserRequestedVerificationEmail.tryDispatch(user)

return response.redirect().toRoute('pages:auth.verify')
}

async callbackForEmailVerification({ request, response }: HttpContext) {
const { email } = await request.validateUsing(emailVerificationCallbackValidator)
await this.userService.verifyEmail(email)

return response.redirect().toRoute('pages:auth.verify.success')
}

async sendForgotPassword({ request, response }: HttpContext) {
const { email } = await request.validateUsing(passwordSendForgotPasswordValidator)

/*
According to OWASP recommendations, the existence of the account should be transparent
to the person who issues this request, but we should not send an email that is not in
any account.
*/
if (await Account.findBy('id', `credentials:${email}`)) {
await this.userService.sendForgotPasswordEmail(email)
}

return response.redirect().toRoute('page:auth.forgot-password.sent')
}

async callbackForForgotPassword({ request, response }: HttpContext) {
const {
password,
email
} = await request.validateUsing(passwordResetValidator)

const account = await Account.find(`credentials:${email}`)
if (account) {
account.password = password // Auther mixin hashes it automatically on assignment
await account.save()
}

return response.redirect().toRoute('actions:auth.forgot-password.success')
}

async showForgotPasswordPage({ inertia }: HttpContext) {
return inertia.render('auth/forgot-password/reset')
}

// SOCIAL AUTHENTICATION

// async initiateGithubLogin({ ally, inertia }: HttpContext) {
// const url = await ally.use('github').redirectUrl()
// return inertia.location(url)
// }

// async callbackForGithubLogin({ ally }: HttpContext) {
// const github = ally.use('github')
// const user = await github.user()

// const data = await socialAccountLoginValidator.validate(user)
// console.log(data)

// const account = await getOrCreate({
// provider: 'github',
// providerId: data.id,
// })

// return response.json({ user, account: account.serialize() })
// }

// async initiateGoogleLogin({ ally, inertia }: HttpContext) {
// const url = await ally.use('google').redirectUrl()
// return inertia.location(url)
// }

// async callbackForGoogleLogin({ response, ally }: HttpContext) {
// const google = ally.use('google')
// const user = await google.user()

// return response.json({ user })
// }

// async initiateLinkedinLogin({ ally, inertia }: HttpContext) {
// const url = await ally.use('linkedin').redirectUrl()
// return inertia.location(url)
// }

// async callbackForLinkedinLogin({ response, ally }: HttpContext) {
// const linkedin = ally.use('linkedin')
// const user = await linkedin.user()

// return response.json({ user })
// }
}
Loading

0 comments on commit e88ca33

Please sign in to comment.