# Conflicts:
#	app/Controllers/Http/StatesController.ts
This commit is contained in:
2021-06-30 16:43:28 +02:00
25 changed files with 176 additions and 186 deletions

View File

@@ -27,8 +27,10 @@ API_VERSION=
CACHE_VIEWS=
MAILGUN_API_KEY=
MAILGUN_URL=
SMTP_HOST=
SMTP_PORT=
SMTP_USERNAME=
SMTP_PASSWORD=
GITHUB_CLIENT_ID=
GITHUB_CLIENT_SECRET=

View File

@@ -1,129 +1,156 @@
import {HttpContextContract} from '@ioc:Adonis/Core/HttpContext'
import User from "App/Models/User";
import AuthValidator from "App/Validators/AuthValidator";
import User from "../../Models/User";
import AuthValidator from "../../Validators/AuthValidator";
import {AllyUserContract} from "@ioc:Adonis/Addons/Ally";
export default class AuthController {
public async loginWeb ({request, auth}: HttpContextContract) {
public async loginWeb ({ request, auth, response }: HttpContextContract) {
const data = await request.validate(AuthValidator)
const {email, password, remember_me } = data
try {
await auth.attempt(email, password, remember_me)
const user = await User.query()
.where('id', auth.user!.id)
.firstOrFail()
if (!remember_me) {
await user.merge({
rememberMeToken: ''
}).save()
}
return { user }
} catch (error) {
if (error.code === 'E_INVALID_AUTH_UID') return { error: "L'utilisateur n'a pas été trouvé" }
if (error.code === 'E_INVALID_AUTH_PASSWORD') return { error: "L'identifiant ou le mot de passe est incorrect" }
await auth.attempt(email, password, remember_me)
const user = await User.query()
.where('id', auth.user!.id)
.firstOrFail()
if (!remember_me) {
await user.merge({
rememberMeToken: ''
}).save()
}
return response.status(200).send({
user: user
})
}
public async loginApi ({request, auth}: HttpContextContract) {
public async loginApi ({ request, auth, response }: HttpContextContract) {
const email = request.input('email')
const password = request.input('password')
const token = await auth.use('api').attempt(email, password, {
expiresIn: '2 days'
})
return token.toJSON()
return response.status(200).send(token.toJSON())
}
public async createInfiniteToken ({request, auth}: HttpContextContract) {
public async createInfiniteToken ({ request, auth, response }: HttpContextContract) {
const email = request.input('email')
const password = request.input('password')
const token = await auth.use('api').attempt(email, password)
return token.toJSON()
return response.status(200).send(token.toJSON())
}
public async logoutWeb ({auth}: HttpContextContract) {
public async logoutWeb ({ auth, response }: HttpContextContract) {
await auth.logout()
return { message: 'Vous avez été déconnecté' }
return response.status(200).send({
message: 'You have been disconnected'
})
}
public async logoutApi ({auth}: HttpContextContract) {
public async logoutApi ({ auth, response }: HttpContextContract) {
await auth.use('api').logout()
return { message: 'Vous avez été déconnecté' }
return response.status(200).send({
message: 'You have been disconnected'
})
}
public async user ({auth}: HttpContextContract) {
public async user ({ auth, response }: HttpContextContract) {
await auth.authenticate()
return await User.query()
const user = await User.query()
.where('id', auth.user!.id)
.firstOrFail()
return response.status(200).send({
user: user
})
}
public async twitter ({ally, auth}: HttpContextContract) {
public async twitter ({ ally, auth, response }: HttpContextContract) {
const twitter = ally.use('twitter')
if (twitter.accessDenied()) {
return 'Access Denied'
return response.status(403).send({
message: 'Access Denied'
})
}
if (twitter.stateMisMatch()) {
return 'Request expired. Retry again'
return response.status(405).send({
message: 'Request expired. Retry again'
})
}
if (twitter.hasError()) {
return twitter.getError()
return response.status(500).send({
message: twitter.getError()
})
}
const twitterUser = await twitter.user()
const user = await this.createUser(twitterUser)
await auth.use('web').login(user)
return user
return response.status(200).send({
user: user
})
}
public async github ({ally, auth}: HttpContextContract) {
public async github ({ ally, auth, response }: HttpContextContract) {
const github = ally.use('github')
if (github.accessDenied()) {
return 'Access Denied'
return response.status(403).send({
message: 'Access Denied'
})
}
if (github.stateMisMatch()) {
return 'Request expired. Retry again'
return response.status(405).send({
message: 'Request expired. Retry again'
})
}
if (github.hasError()) {
return github.getError()
return response.status(500).send({
message: github.getError()
})
}
const githubUser = await github.user()
const user = await this.createUser(githubUser)
await auth.use('web').login(user)
return user
return response.status(200).send({
user: user
})
}
public async google ({ally, auth}: HttpContextContract) {
public async google ({ ally, auth, response, }: HttpContextContract) {
const google = ally.use('google')
if (google.accessDenied()) {
return 'Access Denied'
return response.status(403).send({
message: 'Access Denied'
})
}
if (google.stateMisMatch()) {
return 'Request expired. Retry again'
return response.status(405).send({
message: 'Request expired. Retry again'
})
}
if (google.hasError()) {
return google.getError()
return response.status(500).send({
message: google.getError()
})
}
const googleUser = await google.user()
const user = await this.createUser(googleUser)
await auth.use('web').login(user)
return user
return response.status(200).send({
user: user
})
}
public async createUser(allyUser: AllyUserContract<any>): Promise<User> {
public async createUser (allyUser: AllyUserContract<any>): Promise<User> {
return await User.firstOrCreate({
email: allyUser.email!,
}, {

View File

@@ -1,16 +1,18 @@
import {HttpContextContract} from "@ioc:Adonis/Core/HttpContext";
import GuestBookMessage from "../../Models/GuestBookMessage";
import StoreValidator from "../../Validators/guestbook/StoreValidator";
import GuestValidator from "../../Validators/guestbook/GuestValidator";
export default class GuestBookController {
public async index () {
public async get () {
return GuestBookMessage.query().orderBy('created_at', 'desc')
}
public async store ({request}: HttpContextContract) {
const data = await request.validate(StoreValidator)
return await GuestBookMessage.create(data)
public async store ({request, auth}: HttpContextContract) {
if (auth.isLoggedIn) {
const data = await request.validate(GuestValidator)
return await GuestBookMessage.create(data)
}
}
}

View File

@@ -13,7 +13,7 @@ export default class LocationsController {
})
}
public async add ({ request, response }: HttpContextContract) {
public async store ({ request, response }: HttpContextContract) {
const data = await request.validate(LocationValidator)
await Location.create(data)
return response.status(200).send({

View File

@@ -11,7 +11,7 @@ export default class ProjectsController {
})
}
public async add ({ request, response}: HttpContextContract) {
public async store ({ request, response}: HttpContextContract) {
const data = await request.validate(ProjectValidator)
await Project.create(data)
return response.status(200).send({

View File

@@ -1,7 +1,6 @@
import {HttpContextContract} from "@ioc:Adonis/Core/HttpContext";
import Redis from "@ioc:Adonis/Addons/Redis";
import {UpdateGitHubReadme} from "app/Tasks/UpdateGithubReadme";
import Logger from "@ioc:Adonis/Core/Logger";
export default class StatesController {
@@ -52,7 +51,6 @@ export default class StatesController {
message: 'State successfully updated !'
})
}
Logger.info("Finish")
}
public getStatus(state: string | null): string {

View File

@@ -0,0 +1,21 @@
import { HttpContextContract } from '@ioc:Adonis/Core/HttpContext'
import SubscriberValidator from "../../Validators/subscriber/SubscriberValidator";
import Subscriber from "../../Models/Subscriber";
export default class SubscribersController {
public async get ({ response }: HttpContextContract) {
return response.status(200).send({
count: Subscriber.query().count
})
}
public async store ({ request, response }: HttpContextContract) {
const data = await request.validate(SubscriberValidator)
await Subscriber.create(data)
return response.status(200).send({
message: 'Subscriber successfully registered !'
})
}
}

View File

@@ -1,7 +1,7 @@
import {HttpContextContract} from '@ioc:Adonis/Core/HttpContext'
import User from "App/Models/User";
import StoreValidator from "App/Validators/users/StoreValidator";
import UpdateValidator from "App/Validators/users/UpdateValidator";
import UserStoreValidator from "../../../app/Validators/users/UserStoreValidator";
import UserUpdateValidator from "../../../app/Validators/users/UserUpdateValidator";
export default class UsersController {
@@ -10,7 +10,7 @@ export default class UsersController {
}
public async store ({request}: HttpContextContract) {
const data = await request.validate(StoreValidator)
const data = await request.validate(UserStoreValidator)
return await User.create(data)
}
@@ -20,7 +20,7 @@ export default class UsersController {
public async update({ request, params, response }: HttpContextContract) {
const user = await User.findOrFail(params.id)
const data = await request.validate(UpdateValidator)
const data = await request.validate(UserUpdateValidator)
const { email } = data
const user2 = await User.findBy('email', email)

View File

@@ -14,7 +14,8 @@ export default class FormConfirmation extends BaseMailer {
public prepare(message: MessageContract) {
message
.from('contact@arthurdanjou.fr')
.from('no-reply@arthurdanjou.fr')
.replyTo('contact@arthurdanjou.fr')
.to(this.email)
.subject('Confirmation Form')
.html(this.html)

16
app/Models/Subscriber.ts Normal file
View File

@@ -0,0 +1,16 @@
import { DateTime } from 'luxon'
import { BaseModel, column } from '@ioc:Adonis/Lucid/Orm'
export default class Subscriber extends BaseModel {
@column({ isPrimary: true })
public id: number
@column()
public email: string
@column.dateTime({ autoCreate: true })
public createdAt: DateTime
@column.dateTime({ autoCreate: true, autoUpdate: true })
public updatedAt: DateTime
}

View File

@@ -0,0 +1,3 @@
export async function UpdateGitHubReadMe(): Promise<void> {
}

View File

@@ -1,7 +1,7 @@
import { HttpContextContract } from '@ioc:Adonis/Core/HttpContext'
import {rules, schema} from '@ioc:Adonis/Core/Validator'
export default class StoreValidator {
export default class GuestValidator {
constructor (private ctx: HttpContextContract) {
}

View File

@@ -1,7 +1,7 @@
import { HttpContextContract } from '@ioc:Adonis/Core/HttpContext'
import {rules, schema} from '@ioc:Adonis/Core/Validator'
export default class StoreValidator {
export default class SubscriberValidator {
constructor (private ctx: HttpContextContract) {
}
@@ -9,8 +9,7 @@ export default class StoreValidator {
email: schema.string({ trim: true }, [
rules.email(),
rules.unique({table: 'subscribers', column: 'email'})
]),
name: schema.string()
])
})
public cacheKey = this.ctx.routeKey

View File

@@ -1,21 +0,0 @@
import { HttpContextContract } from '@ioc:Adonis/Core/HttpContext'
import {rules, schema} from '@ioc:Adonis/Core/Validator'
export default class UpdateValidator {
constructor (private ctx: HttpContextContract) {
}
public schema = schema.create({
email: schema.string({ trim: true }, [
rules.email(),
rules.unique({table: 'subscribers', column: 'email'})
]),
name: schema.string.optional()
})
public cacheKey = this.ctx.routeKey
public messages = {
required: 'Le champ {{field}} doit être valide !'
}
}

View File

@@ -1,7 +1,7 @@
import { HttpContextContract } from '@ioc:Adonis/Core/HttpContext'
import {rules, schema} from '@ioc:Adonis/Core/Validator'
export default class StoreValidator {
export default class UserStoreValidator {
constructor (private ctx: HttpContextContract) {
}

View File

@@ -1,7 +1,7 @@
import { HttpContextContract } from '@ioc:Adonis/Core/HttpContext'
import {rules, schema} from '@ioc:Adonis/Core/Validator'
export default class UpdateValidator {
export default class UserUpdateValidator {
constructor (private ctx: HttpContextContract) {
}

View File

@@ -18,7 +18,7 @@ const mailConfig: MailConfig = {
| a mailer
|
*/
mailer: 'mailgun',
mailer: 'smtp',
/*
|--------------------------------------------------------------------------
@@ -36,17 +36,21 @@ const mailConfig: MailConfig = {
mailers: {
/*
|--------------------------------------------------------------------------
| Mailgun
| Smtp
|--------------------------------------------------------------------------
|
| Uses Mailgun service for sending emails.
| Uses SMTP protocol for sending email
|
*/
mailgun: {
driver: 'mailgun',
baseUrl: 'https://api.mailgun.net/v3/',
key: Env.get('MAILGUN_API_KEY'),
domain: Env.get('MAILGUN_URL'),
smtp: {
driver: 'smtp',
host: Env.get('SMTP_HOST'),
port: Env.get('SMTP_PORT'),
auth: {
user: Env.get('SMTP_USERNAME'),
pass: Env.get('SMTP_PASSWORD'),
type: 'login',
}
},
},

View File

@@ -9,6 +9,6 @@ declare module '@ioc:Adonis/Addons/Mail' {
import { MailDrivers } from '@ioc:Adonis/Addons/Mail'
interface MailersList {
mailgun: MailDrivers['mailgun'],
smtp: MailDrivers['smtp'],
}
}

View File

@@ -6,7 +6,6 @@ export default class Subscribers extends BaseSchema {
public async up () {
this.schema.createTable(this.tableName, (table) => {
table.increments('id').primary()
table.string('name')
table.string('email').notNullable()
table.timestamps(true)
})

View File

@@ -1,34 +0,0 @@
import BaseSchema from '@ioc:Adonis/Lucid/Schema'
export default class UsersSchema extends BaseSchema {
protected tableName = 'users'
public async up () {
this.schema.createTable(this.tableName, (table) => {
table.increments('id').primary()
table.string('email', 255).notNullable()
table.string('password', 180).defaultTo(this.randomPassword()).notNullable()
table.boolean('is_confirmed').defaultTo(false).notNullable()
table.string('remember_me_token').defaultTo(null).nullable()
table.string('confirmation_token').defaultTo(null).nullable()
table.timestamps(true)
})
}
private randomPassword () {
let chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
let password = ''
let passwordLength = 12
for (let i = 0; i < passwordLength; i++) {
let rnum = Math.floor(Math.random() * chars.length);
password += chars.substring(rnum,rnum+1);
}
return password
}
public async down () {
this.schema.dropTable(this.tableName)
}
}

View File

@@ -1,17 +0,0 @@
import BaseSchema from '@ioc:Adonis/Lucid/Schema'
export default class DockerCommands extends BaseSchema {
protected tableName = 'docker_commands'
public async up () {
this.schema.createTable(this.tableName, (table) => {
table.increments('id')
table.bigInteger('commands')
table.timestamps(true)
})
}
public async down () {
this.schema.dropTable(this.tableName)
}
}

View File

@@ -1,17 +0,0 @@
import BaseSchema from '@ioc:Adonis/Lucid/Schema'
export default class DockerBuilds extends BaseSchema {
protected tableName = 'docker_builds'
public async up () {
this.schema.createTable(this.tableName, (table) => {
table.increments('id')
table.bigInteger('builds')
table.timestamps(true)
})
}
public async down () {
this.schema.dropTable(this.tableName)
}
}

6
env.ts
View File

@@ -51,8 +51,10 @@ export default Env.rules({
API_VERSION: Env.schema.string(),
//Mails
MAILGUN_API_KEY: Env.schema.string(),
MAILGUN_URL: Env.schema.string(),
SMTP_HOST: Env.schema.string({ format: 'host' }),
SMTP_PORT: Env.schema.number(),
SMTP_USERNAME: Env.schema.string(),
SMTP_PASSWORD: Env.schema.string(),
//Socials Authentication
GOOGLE_CLIENT_ID: Env.schema.string(),

26
pnpm-lock.yaml generated
View File

@@ -280,7 +280,7 @@ packages:
fast-deep-equal: 3.1.3
igniculus: 1.5.0
knex: 0.95.6_mysql@2.18.1
knex-dynamic-connection: 2.1.0_mysql@2.18.1
knex-dynamic-connection: 2.1.1_mysql@2.18.1
luxon: 1.27.0
macroable: 5.1.3
pretty-hrtime: 1.0.3
@@ -398,7 +398,7 @@ packages:
marked-terminal: 4.1.1_marked@2.1.1
mrm-core: 6.0.0
mustache: 4.2.0
open: 8.2.0
open: 8.2.1
dev: true
/@adonisjs/validator/11.0.2_dca74b6a7cfaf1624e10c0567ec6c737:
@@ -415,7 +415,7 @@ packages:
'@types/luxon': 1.27.0
'@types/validator': 13.1.4
luxon: 1.27.0
normalize-url: 6.0.1
normalize-url: 6.1.0
tmp-cache: 1.1.0
validator: 13.6.0
dev: false
@@ -1069,7 +1069,7 @@ packages:
http-cache-semantics: 4.1.0
keyv: 4.0.3
lowercase-keys: 2.0.0
normalize-url: 6.0.1
normalize-url: 6.1.0
responselike: 2.0.0
dev: false
@@ -2637,8 +2637,8 @@ packages:
resolution: {integrity: sha512-8QADVssbrFjivHWQU7KkMgptGTl6WAcSdlbBPY4uNF+mWr6DGcKrvY2w4FQJoXch7+fKMjj0dRrL75vk3k23OA==}
engines: {node: '>=6'}
/knex-dynamic-connection/2.1.0_mysql@2.18.1:
resolution: {integrity: sha512-yi0aYQ0a4uTPqbzkqYwWquR9CzAVC+7ejPyx/l263031l5F2FtTAFvxxV1HDntnusn1XsiR7F+iCJ2LvYUJ2qA==}
/knex-dynamic-connection/2.1.1_mysql@2.18.1:
resolution: {integrity: sha512-/Lwg/T13eNRJVoSJ4e9SH3slVUmg37UHxDxVluAAKdJZxYVj8YsP2x50JSk310RmKsYbOZ8oB8SwVVEuRa4nYw==}
dependencies:
debug: 4.3.1
knex: 0.95.6_mysql@2.18.1
@@ -3413,8 +3413,8 @@ packages:
resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==}
engines: {node: '>=0.10.0'}
/normalize-url/6.0.1:
resolution: {integrity: sha512-VU4pzAuh7Kip71XEmO9aNREYAdMHFGTVj/i+CaTImS8x0i1d3jUZkXhqluy/PRgjPLMgsLQulYY3PJ/aSbSjpQ==}
/normalize-url/6.1.0:
resolution: {integrity: sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==}
engines: {node: '>=10'}
dev: false
@@ -3494,8 +3494,8 @@ packages:
dependencies:
mimic-fn: 2.1.0
/open/8.2.0:
resolution: {integrity: sha512-O8uInONB4asyY3qUcEytpgwxQG3O0fJ/hlssoUHsBboOIRVZzT6Wq+Rwj5nffbeUhOdMjpXeISpDDzHCMRDuOQ==}
/open/8.2.1:
resolution: {integrity: sha512-rXILpcQlkF/QuFez2BJDf3GsqpjGKbkUUToAIGo9A0Q6ZkoSGogZJulrUdwRkrAsoQvoZsrjCYt8+zblOk7JQQ==}
engines: {node: '>=12'}
dependencies:
define-lazy-prop: 2.0.0
@@ -4649,8 +4649,8 @@ packages:
engines: {node: '>= 12'}
dev: true
/yargs-parser/20.2.7:
resolution: {integrity: sha512-FiNkvbeHzB/syOjIUxFDCnhSfzAL8R5vs40MgLFBorXACCOAEaWu0gRZl14vG8MR9AOJIZbmkjhusqBYZ3HTHw==}
/yargs-parser/20.2.9:
resolution: {integrity: sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==}
engines: {node: '>=10'}
dev: false
@@ -4664,7 +4664,7 @@ packages:
require-directory: 2.1.1
string-width: 4.2.2
y18n: 5.0.8
yargs-parser: 20.2.7
yargs-parser: 20.2.9
dev: false
/youch-terminal/1.1.1:

View File

@@ -41,6 +41,7 @@ Route.get('/states', 'StatesController.get')
Route.get('/projects', 'ProjectsController.get')
Route.resource('users', 'UsersController').only(['index', 'show'])
Route.group(() => {
Route.get('/', 'FileController.index')
Route.get('/:filename', async ({ response, params }) => {
@@ -51,22 +52,26 @@ Route.group(() => {
Route.group(() => {
Route.resource('users', 'UsersController').only(['store', 'update', 'destroy'])
Route.resource('files', 'FileController').only(['store', 'destroy'])
Route.post('/locations', 'LocationsController.add')
Route.post('/projects', 'ProjectsController.add')
Route.resource('guestbook', 'GuestBookController').only(['index', 'show'])
Route.post('/locations', 'LocationsController.store')
Route.post('/projects', 'ProjectsController.store')
}).middleware('auth:web')
Route.group(() => {
// ArtAPI
Route.post('form', 'FormsController.send')
Route.post('states/:state', 'StatesController.set')
// ArtSite
Route.group(() => {
Route.get('/:slug', 'PostsController.getLikes')
Route.post('/:slug/like', 'PostsController.like')
Route.post('/:slug/unlike', 'PostsController.unlike')
}).prefix('posts')
Route.get('subscribers', 'SubscribersController.get')
Route.post('subscribers', 'SubscribersController.store')
Route.get('guestbook', 'GuestBookController.get')
Route.post('guestbook', 'GuestBookController.store')
}).middleware('auth:api')
Route.group(() => {