feat: add notifications
This commit is contained in:
parent
06fc137057
commit
35a8191938
8 changed files with 552 additions and 10 deletions
90
app/controllers/notifications_controller.ts
Normal file
90
app/controllers/notifications_controller.ts
Normal file
|
|
@ -0,0 +1,90 @@
|
|||
import Subscription from '#models/subscription'
|
||||
import { EVENTS, NotificationService } from '#services/notification_service'
|
||||
import { subscribeValidator, updateNotificationValidator } from '#validators/notification'
|
||||
import { inject } from '@adonisjs/core'
|
||||
import type { HttpContext } from '@adonisjs/core/http'
|
||||
|
||||
@inject()
|
||||
export default class NotificationsController {
|
||||
constructor(private service: NotificationService) {}
|
||||
|
||||
// GET /notifications
|
||||
async index({ auth }: HttpContext) {
|
||||
return Subscription.query().where('userId', auth.user!.id)
|
||||
}
|
||||
|
||||
// POST /notifications/subscribe
|
||||
async subscribe({ request, response, auth }: HttpContext) {
|
||||
const ua = request.headers()['user-agent']
|
||||
if (!ua) {
|
||||
return response.badRequest({
|
||||
message: 'User-Agent header is required',
|
||||
})
|
||||
}
|
||||
const device = this.service.getUserSignature(ua)
|
||||
|
||||
const data = await request.validateUsing(subscribeValidator)
|
||||
await Subscription.create({
|
||||
userId: auth.user!.id,
|
||||
device,
|
||||
events: 0, // Default to no events
|
||||
data,
|
||||
failedAttempts: 0,
|
||||
enabled: true,
|
||||
})
|
||||
}
|
||||
|
||||
// POST /notifications/:id/unsubscribe
|
||||
async unsubscribe({ request, auth }: HttpContext) {
|
||||
const subscriptionId = request.param('id')
|
||||
const subscription = await Subscription.query()
|
||||
.where('userId', auth.user!.id)
|
||||
.where('id', subscriptionId)
|
||||
.firstOrFail()
|
||||
|
||||
await subscription.delete()
|
||||
return { success: true }
|
||||
}
|
||||
|
||||
// POST /notifications/:id/
|
||||
async update({ request, response, auth }: HttpContext) {
|
||||
const subscriptionId = request.param('id')
|
||||
const subscription = await Subscription.query()
|
||||
.where('userId', auth.user!.id)
|
||||
.where('id', subscriptionId)
|
||||
.firstOrFail()
|
||||
|
||||
const { events } = await request.validateUsing(updateNotificationValidator)
|
||||
// Validate events
|
||||
if (!events.every((key) => key in EVENTS)) {
|
||||
return response.badRequest({
|
||||
message: 'Invalid events provided',
|
||||
})
|
||||
}
|
||||
|
||||
// Update subscription events
|
||||
const validEvents = events.map((key) => EVENTS[key as keyof typeof EVENTS])
|
||||
subscription.events = this.service.setEvents(validEvents)
|
||||
await subscription.save()
|
||||
|
||||
return subscription
|
||||
}
|
||||
|
||||
// POST /notifications/:id/test
|
||||
async test({ request, response, auth }: HttpContext) {
|
||||
const subscriptionId = request.param('id')
|
||||
const subscription = await Subscription.query()
|
||||
.where('userId', auth.user!.id)
|
||||
.where('id', subscriptionId)
|
||||
.firstOrFail()
|
||||
|
||||
const result = await this.service.sendTestNotification(subscription.data)
|
||||
if (result) {
|
||||
return { success: true }
|
||||
}
|
||||
|
||||
return response.internalServerError({
|
||||
message: 'Failed to send test notification',
|
||||
})
|
||||
}
|
||||
}
|
||||
29
app/models/subscription.ts
Normal file
29
app/models/subscription.ts
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
import { EVENTS } from '#services/notification_service'
|
||||
import { BaseModel, column } from '@adonisjs/lucid/orm'
|
||||
import type { PushSubscription } from 'web-push'
|
||||
|
||||
export default class Subscription extends BaseModel {
|
||||
@column({ isPrimary: true })
|
||||
declare id: number
|
||||
|
||||
@column({ serializeAs: null })
|
||||
declare userId: number
|
||||
|
||||
@column()
|
||||
declare device: string
|
||||
|
||||
@column({
|
||||
serialize: (events: number) =>
|
||||
Object.entries(EVENTS).map(([key, value]) => ({ id: key, enabled: (events & value) !== 0 })),
|
||||
})
|
||||
declare events: number
|
||||
|
||||
@column({ serializeAs: null })
|
||||
declare data: PushSubscription
|
||||
|
||||
@column({ serializeAs: null })
|
||||
declare failedAttempts: number
|
||||
|
||||
@column()
|
||||
declare enabled: boolean
|
||||
}
|
||||
163
app/services/notification_service.ts
Normal file
163
app/services/notification_service.ts
Normal file
|
|
@ -0,0 +1,163 @@
|
|||
import Colle from '#models/colle'
|
||||
import Subscription from '#models/subscription'
|
||||
import env from '#start/env'
|
||||
import { DateTime } from 'luxon'
|
||||
import { UAParser } from 'ua-parser-js'
|
||||
import webpush, { PushSubscription } from 'web-push'
|
||||
|
||||
export const EVENTS = {
|
||||
SYSTEM: 1 << 0,
|
||||
|
||||
COLLE_ADDED: 1 << 1,
|
||||
COLLE_REMOVED: 1 << 2,
|
||||
COLLE_UPDATED: 1 << 3,
|
||||
|
||||
GRADE_ADDED: 1 << 4,
|
||||
GRADE_UPDATED: 1 << 5,
|
||||
|
||||
ROOM_UPDATED: 1 << 6,
|
||||
}
|
||||
|
||||
type Event = (typeof EVENTS)[keyof typeof EVENTS]
|
||||
type NotificationId = keyof typeof NOTIFICATIONS
|
||||
|
||||
export class NotificationService {
|
||||
constructor() {
|
||||
webpush.setVapidDetails(
|
||||
env.get('VAPID_DETAILS'),
|
||||
env.get('VAPID_PUBLIC_KEY'),
|
||||
env.get('VAPID_PRIVATE_KEY')
|
||||
)
|
||||
}
|
||||
|
||||
public setEvents(events: Event[]): number {
|
||||
return events.reduce((acc, event) => acc | event, 0)
|
||||
}
|
||||
|
||||
public hasEvent(events: number, event: Event): boolean {
|
||||
return (events & event) !== 0
|
||||
}
|
||||
|
||||
private pushNotification(subscription: PushSubscription, payload: Record<string, any>) {
|
||||
return webpush.sendNotification(subscription, JSON.stringify(payload)).catch((err) => {
|
||||
console.error('Error sending notification:', err)
|
||||
return false
|
||||
})
|
||||
}
|
||||
|
||||
public async sendNotification(notificationId: NotificationId, colle: Colle) {
|
||||
const payload = Object.assign(DEFAULT_NOTIFICATION, NOTIFICATIONS[notificationId](colle))
|
||||
|
||||
const subscriptions = await Subscription.query()
|
||||
.where('enabled', true)
|
||||
.where('userId', colle.studentId)
|
||||
// TODO: Check if working??
|
||||
.whereRaw(`(events & ${EVENTS[notificationId]}) > 0`)
|
||||
|
||||
for (const subscription of subscriptions) {
|
||||
await this.pushNotification(subscription.data, payload)
|
||||
// TODO: Count failed attempts and disable subscription if too many failures
|
||||
}
|
||||
}
|
||||
|
||||
public async sendTestNotification(subscription: PushSubscription) {
|
||||
const payload = Object.assign(DEFAULT_NOTIFICATION, {
|
||||
title: 'Test Notification',
|
||||
body: 'Ceci est une notification de test.',
|
||||
})
|
||||
|
||||
return this.pushNotification(subscription, payload)
|
||||
}
|
||||
|
||||
public getUserSignature(uaString: string) {
|
||||
const parser = new UAParser(uaString)
|
||||
const browser = parser.getBrowser()
|
||||
const os = parser.getOS()
|
||||
const device = parser.getDevice()
|
||||
|
||||
const browserStr = browser.name
|
||||
? `${browser.name} ${browser.version?.split('.')[0] || ''}`.trim()
|
||||
: ''
|
||||
const osStr = os.name ? `${os.name} ${os.version || ''}`.trim() : ''
|
||||
const deviceStr = device.model
|
||||
? `${device.vendor || ''} ${device.model}`.trim()
|
||||
: device.type
|
||||
? device.type
|
||||
: 'Desktop'
|
||||
|
||||
return [deviceStr, osStr, browserStr].filter(Boolean).join(' | ')
|
||||
}
|
||||
}
|
||||
|
||||
const NOTIFICATIONS = {
|
||||
COLLE_ADDED: (colle: Colle) => ({
|
||||
title: 'Nouvelle colle',
|
||||
body: `Colle de ${colle.subject} ajoutée le ${formatDate(colle.date)}.`,
|
||||
data: {
|
||||
id: colle.id,
|
||||
},
|
||||
actions: [OPEN_ACION, HOME_ACTION],
|
||||
}),
|
||||
COLLE_REMOVED: (colle: Colle) => ({
|
||||
title: 'Colle supprimée',
|
||||
body: `Votre colle de ${colle.subject}, le ${formatDate(colle.date)} a été supprimée.`,
|
||||
actions: [HOME_ACTION],
|
||||
}),
|
||||
COLLE_UPDATED: (colle: Colle) => ({
|
||||
title: 'Colle modifiée',
|
||||
body: `Votre colle de ${colle.subject} du ${formatDate(colle.date)} a été modifiée.`,
|
||||
data: {
|
||||
id: colle.id,
|
||||
},
|
||||
actions: [OPEN_ACION, HOME_ACTION],
|
||||
}),
|
||||
|
||||
GRADE_ADDED: (colle: Colle) => ({
|
||||
title: 'Nouvelle note',
|
||||
body: `Colle de ${colle.subject} : ${colle.grade}/20`,
|
||||
data: {
|
||||
id: colle.id,
|
||||
},
|
||||
actions: [OPEN_ACION, HOME_ACTION],
|
||||
}),
|
||||
GRADE_UPDATED: (colle: Colle) => ({
|
||||
title: 'Note modifiée',
|
||||
body: `Colle de ${colle.subject} : ${colle.grade}/20`,
|
||||
data: {
|
||||
id: colle.id,
|
||||
},
|
||||
actions: [OPEN_ACION, HOME_ACTION],
|
||||
}),
|
||||
|
||||
ROOM_UPDATED: (colle: Colle) => ({
|
||||
title: 'Salle modifiée',
|
||||
body: `Colle de ${colle.subject} en ${colle.room}.`,
|
||||
data: {
|
||||
id: colle.id,
|
||||
},
|
||||
actions: [OPEN_ACION, HOME_ACTION],
|
||||
}),
|
||||
}
|
||||
|
||||
const OPEN_ACION = {
|
||||
action: 'open',
|
||||
title: 'Ouvrir',
|
||||
}
|
||||
|
||||
const HOME_ACTION = {
|
||||
action: 'home',
|
||||
title: 'Mes colles',
|
||||
}
|
||||
|
||||
const DEFAULT_NOTIFICATION = {
|
||||
title: 'Notification',
|
||||
body: 'Vous avez une nouvelle notification.',
|
||||
requireInteraction: true,
|
||||
icon: env.get('PUBLIC_URL') + '/web-app-manifest-192x192.png',
|
||||
}
|
||||
|
||||
const formatDate = (date: DateTime) =>
|
||||
date.toJSDate().toLocaleDateString('fr-FR', {
|
||||
month: '2-digit',
|
||||
day: '2-digit',
|
||||
})
|
||||
17
app/validators/notification.ts
Normal file
17
app/validators/notification.ts
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
import vine from '@vinejs/vine'
|
||||
|
||||
export const subscribeValidator = vine.compile(
|
||||
vine.object({
|
||||
endpoint: vine.string().url(),
|
||||
keys: vine.object({
|
||||
p256dh: vine.string(),
|
||||
auth: vine.string(),
|
||||
}),
|
||||
})
|
||||
)
|
||||
|
||||
export const updateNotificationValidator = vine.compile(
|
||||
vine.object({
|
||||
events: vine.array(vine.string())
|
||||
})
|
||||
)
|
||||
|
|
@ -42,6 +42,7 @@
|
|||
"@swc/core": "1.11.24",
|
||||
"@types/luxon": "^3.6.2",
|
||||
"@types/node": "^22.15.18",
|
||||
"@types/web-push": "^3.6.4",
|
||||
"eslint": "^9.26.0",
|
||||
"hot-hook": "^0.4.0",
|
||||
"pino-pretty": "^13.0.0",
|
||||
|
|
@ -66,7 +67,9 @@
|
|||
"edge.js": "^6.2.1",
|
||||
"luxon": "^3.6.1",
|
||||
"pg": "^8.16.0",
|
||||
"reflect-metadata": "^0.2.2"
|
||||
"reflect-metadata": "^0.2.2",
|
||||
"ua-parser-js": "^2.0.4",
|
||||
"web-push": "^3.6.7"
|
||||
},
|
||||
"hotHook": {
|
||||
"boundaries": [
|
||||
|
|
|
|||
221
pnpm-lock.yaml
generated
221
pnpm-lock.yaml
generated
|
|
@ -59,6 +59,12 @@ importers:
|
|||
reflect-metadata:
|
||||
specifier: ^0.2.2
|
||||
version: 0.2.2
|
||||
ua-parser-js:
|
||||
specifier: ^2.0.4
|
||||
version: 2.0.4
|
||||
web-push:
|
||||
specifier: ^3.6.7
|
||||
version: 3.6.7
|
||||
devDependencies:
|
||||
'@adonisjs/assembler':
|
||||
specifier: ^7.8.2
|
||||
|
|
@ -90,6 +96,9 @@ importers:
|
|||
'@types/node':
|
||||
specifier: ^22.15.18
|
||||
version: 22.16.0
|
||||
'@types/web-push':
|
||||
specifier: ^3.6.4
|
||||
version: 3.6.4
|
||||
eslint:
|
||||
specifier: ^9.26.0
|
||||
version: 9.30.1
|
||||
|
|
@ -806,6 +815,9 @@ packages:
|
|||
'@types/luxon@3.6.2':
|
||||
resolution: {integrity: sha512-R/BdP7OxEMc44l2Ex5lSXHoIXTB2JLNa3y2QISIbr58U/YcsffyQrYW//hZSdrfxrjRZj3GcUoxMPGdO8gSYuw==}
|
||||
|
||||
'@types/node-fetch@2.6.13':
|
||||
resolution: {integrity: sha512-QGpRVpzSaUs30JBSGPjOg4Uveu384erbHBoT1zeONvyCfwQxIkUshLAOqN/k9EjGviPRmWTTe6aH2qySWKTVSw==}
|
||||
|
||||
'@types/node@22.16.0':
|
||||
resolution: {integrity: sha512-B2egV9wALML1JCpv3VQoQ+yesQKAmNMBIAY7OteVrikcOcAkWm+dGL6qpeCktPjAv6N1JLnhbNiqS35UpFyBsQ==}
|
||||
|
||||
|
|
@ -824,6 +836,9 @@ packages:
|
|||
'@types/validator@13.15.2':
|
||||
resolution: {integrity: sha512-y7pa/oEJJ4iGYBxOpfAKn5b9+xuihvzDVnC/OSvlVnGxVg0pOqmjiMafiJ1KVNQEaPZf9HsEp5icEwGg8uIe5Q==}
|
||||
|
||||
'@types/web-push@3.6.4':
|
||||
resolution: {integrity: sha512-GnJmSr40H3RAnj0s34FNTcJi1hmWFV5KXugE0mYWnYhgTAHLJ/dJKAwDmvPJYMke0RplY2XE9LnM4hqSqKIjhQ==}
|
||||
|
||||
'@typescript-eslint/eslint-plugin@8.35.1':
|
||||
resolution: {integrity: sha512-9XNTlo7P7RJxbVeICaIIIEipqxLKguyh+3UbXuT2XQuFp6d8VOeDEGuz5IiX0dgZo8CiI6aOFLg4e8cF71SFVg==}
|
||||
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
||||
|
|
@ -918,6 +933,10 @@ packages:
|
|||
peerDependencies:
|
||||
'@adonisjs/core': ^6.2.0
|
||||
|
||||
agent-base@7.1.4:
|
||||
resolution: {integrity: sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==}
|
||||
engines: {node: '>= 14'}
|
||||
|
||||
ajv@6.12.6:
|
||||
resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==}
|
||||
|
||||
|
|
@ -958,6 +977,9 @@ packages:
|
|||
as-table@1.0.55:
|
||||
resolution: {integrity: sha512-xvsWESUJn0JN421Xb9MQw6AsMHRCUknCe0Wjlxvjud80mU4E6hQf1A6NzQKcYNmYw62MfzEtXc+badstZP3JpQ==}
|
||||
|
||||
asn1.js@5.4.1:
|
||||
resolution: {integrity: sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA==}
|
||||
|
||||
assertion-error@2.0.1:
|
||||
resolution: {integrity: sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==}
|
||||
engines: {node: '>=12'}
|
||||
|
|
@ -972,6 +994,9 @@ packages:
|
|||
async-retry@1.3.3:
|
||||
resolution: {integrity: sha512-wfr/jstw9xNi/0teMHrRW7dsz3Lt5ARhYNZ2ewpadnhaIp5mbALhOAP+EAdsC7t4Z6wqsDVv9+W6gm1Dk9mEyw==}
|
||||
|
||||
asynckit@0.4.0:
|
||||
resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==}
|
||||
|
||||
atomic-sleep@1.0.0:
|
||||
resolution: {integrity: sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ==}
|
||||
engines: {node: '>=8.0.0'}
|
||||
|
|
@ -1003,6 +1028,9 @@ packages:
|
|||
orchid-orm:
|
||||
optional: true
|
||||
|
||||
bn.js@4.12.2:
|
||||
resolution: {integrity: sha512-n4DSx829VRTRByMRGdjQ9iqsN0Bh4OolPsFnaZBLcbi8iXcB+kJ9s7EnRt4wILZNV3kPLHkRVfOc/HvhC3ovDw==}
|
||||
|
||||
brace-expansion@1.1.12:
|
||||
resolution: {integrity: sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==}
|
||||
|
||||
|
|
@ -1018,6 +1046,9 @@ packages:
|
|||
engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7}
|
||||
hasBin: true
|
||||
|
||||
buffer-equal-constant-time@1.0.1:
|
||||
resolution: {integrity: sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==}
|
||||
|
||||
builtin-modules@5.0.0:
|
||||
resolution: {integrity: sha512-bkXY9WsVpY7CvMhKSR6pZilZu9Ln5WDrKVBUXf2S443etkmEO4V58heTecXcUIsNsi4Rx8JUO4NfX1IcQl4deg==}
|
||||
engines: {node: '>=18.20'}
|
||||
|
|
@ -1127,6 +1158,10 @@ packages:
|
|||
colorette@2.0.20:
|
||||
resolution: {integrity: sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==}
|
||||
|
||||
combined-stream@1.0.8:
|
||||
resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==}
|
||||
engines: {node: '>= 0.8'}
|
||||
|
||||
commander@10.0.1:
|
||||
resolution: {integrity: sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==}
|
||||
engines: {node: '>=14'}
|
||||
|
|
@ -1225,6 +1260,10 @@ packages:
|
|||
resolution: {integrity: sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==}
|
||||
engines: {node: '>=10'}
|
||||
|
||||
delayed-stream@1.0.0:
|
||||
resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==}
|
||||
engines: {node: '>=0.4.0'}
|
||||
|
||||
denque@2.1.0:
|
||||
resolution: {integrity: sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==}
|
||||
engines: {node: '>=0.10'}
|
||||
|
|
@ -1237,6 +1276,9 @@ packages:
|
|||
resolution: {integrity: sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==}
|
||||
engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16}
|
||||
|
||||
detect-europe-js@0.1.2:
|
||||
resolution: {integrity: sha512-lgdERlL3u0aUdHocoouzT10d9I89VVhk0qNRmll7mXdGfJT1/wqZ2ZLA4oJAjeACPY5fT1wsbq2AT+GkuInsow==}
|
||||
|
||||
diff-sequences@29.6.3:
|
||||
resolution: {integrity: sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==}
|
||||
engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
|
||||
|
|
@ -1256,6 +1298,9 @@ packages:
|
|||
resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==}
|
||||
engines: {node: '>= 0.4'}
|
||||
|
||||
ecdsa-sig-formatter@1.0.11:
|
||||
resolution: {integrity: sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==}
|
||||
|
||||
edge-error@4.0.2:
|
||||
resolution: {integrity: sha512-jB76VYn8wapDHKHSOmP3vbKLoa77RJYsTLNmfl8+cuCD69uxZtP3h+kqV+Prw/YkYmN7yHyp4IApE15pDByk0A==}
|
||||
engines: {node: '>=18.16.0'}
|
||||
|
|
@ -1324,6 +1369,10 @@ packages:
|
|||
resolution: {integrity: sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==}
|
||||
engines: {node: '>= 0.4'}
|
||||
|
||||
es-set-tostringtag@2.1.0:
|
||||
resolution: {integrity: sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==}
|
||||
engines: {node: '>= 0.4'}
|
||||
|
||||
escalade@3.2.0:
|
||||
resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==}
|
||||
engines: {node: '>=6'}
|
||||
|
|
@ -1518,6 +1567,10 @@ packages:
|
|||
resolution: {integrity: sha512-G6NsmEW15s0Uw9XnCg+33H3ViYRyiM0hMrMhhqQOR8NFc5GhYrI+6I3u7OTw7b91J2g8rtvMBZJDbcGb2YUniw==}
|
||||
engines: {node: '>= 18'}
|
||||
|
||||
form-data@4.0.4:
|
||||
resolution: {integrity: sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow==}
|
||||
engines: {node: '>= 6'}
|
||||
|
||||
formdata-node@6.0.3:
|
||||
resolution: {integrity: sha512-8e1++BCiTzUno9v5IZ2J6bv4RU+3UKDmqWUQD0MIMVCd9AdhWkO1gw57oo1mNEX1dMq2EGI+FbWz4B92pscSQg==}
|
||||
engines: {node: '>= 18'}
|
||||
|
|
@ -1608,6 +1661,10 @@ packages:
|
|||
resolution: {integrity: sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==}
|
||||
engines: {node: '>= 0.4'}
|
||||
|
||||
has-tostringtag@1.0.2:
|
||||
resolution: {integrity: sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==}
|
||||
engines: {node: '>= 0.4'}
|
||||
|
||||
hasown@2.0.2:
|
||||
resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==}
|
||||
engines: {node: '>= 0.4'}
|
||||
|
|
@ -1637,6 +1694,14 @@ packages:
|
|||
resolution: {integrity: sha512-V5nVw1PAOgfI3Lmeaj2Exmeg7fenjhRUgz1lPSezy1CuhPYbgQtbQj4jZfEAEMlaL+vupsvhjqCyjzob0yxsmQ==}
|
||||
engines: {node: '>=10.19.0'}
|
||||
|
||||
http_ece@1.2.0:
|
||||
resolution: {integrity: sha512-JrF8SSLVmcvc5NducxgyOrKXe3EsyHMgBFgSaIUGmArKe+rwr0uphRkRXvwiom3I+fpIfoItveHrfudL8/rxuA==}
|
||||
engines: {node: '>=16'}
|
||||
|
||||
https-proxy-agent@7.0.6:
|
||||
resolution: {integrity: sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==}
|
||||
engines: {node: '>= 14'}
|
||||
|
||||
human-signals@8.0.1:
|
||||
resolution: {integrity: sha512-eKCa6bwnJhvxj14kZk5NCPc6Hb6BdsU9DZcOnmQKSnO1VKrfV0zCvtttPZUsBvjmNDn8rpcJfpwSYnHBjc95MQ==}
|
||||
engines: {node: '>=18.18.0'}
|
||||
|
|
@ -1764,6 +1829,9 @@ packages:
|
|||
resolution: {integrity: sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==}
|
||||
engines: {node: '>=12'}
|
||||
|
||||
is-standalone-pwa@0.1.1:
|
||||
resolution: {integrity: sha512-9Cbovsa52vNQCjdXOzeQq5CnCbAcRk05aU62K20WO372NrTv0NxibLFCK6lQ4/iZEFdEA3p3t2VNOn8AJ53F5g==}
|
||||
|
||||
is-stream@4.0.1:
|
||||
resolution: {integrity: sha512-Dnz92NInDqYckGEUJv689RbRiTSEHCQ7wOVeALbkOz999YpqT46yMRIGtSNl2iCL1waAZSx40+h59NV/EwzV/A==}
|
||||
engines: {node: '>=18'}
|
||||
|
|
@ -1823,6 +1891,12 @@ packages:
|
|||
resolution: {integrity: sha512-Qush0uP+G8ZScpGMZvHUiRfI0YBWuB3gVBYlI0v0vvOJt5FLicco+IkP0a50LqTTQhmts/m6tP5SWE+USyIvcQ==}
|
||||
engines: {node: '>=12.20'}
|
||||
|
||||
jwa@2.0.1:
|
||||
resolution: {integrity: sha512-hRF04fqJIP8Abbkq5NKGN0Bbr3JxlQ+qhZufXVr0DvujKy93ZCbXZMHDL4EOtodSbCWxOqR8MS1tXA5hwqCXDg==}
|
||||
|
||||
jws@4.0.0:
|
||||
resolution: {integrity: sha512-KDncfTmOZoOMTFG4mBlG0qUIOlc03fmzH+ru6RgYVZhPkyiy/92Owlt/8UEN+a4TXR1FQetfIpJE8ApdvdVxTg==}
|
||||
|
||||
keyv@4.5.4:
|
||||
resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==}
|
||||
|
||||
|
|
@ -1970,6 +2044,9 @@ packages:
|
|||
resolution: {integrity: sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==}
|
||||
engines: {node: '>=4'}
|
||||
|
||||
minimalistic-assert@1.0.1:
|
||||
resolution: {integrity: sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==}
|
||||
|
||||
minimatch@3.1.2:
|
||||
resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==}
|
||||
|
||||
|
|
@ -2002,6 +2079,15 @@ packages:
|
|||
resolution: {integrity: sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==}
|
||||
engines: {node: '>= 0.6'}
|
||||
|
||||
node-fetch@2.7.0:
|
||||
resolution: {integrity: sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==}
|
||||
engines: {node: 4.x || >=6.0.0}
|
||||
peerDependencies:
|
||||
encoding: ^0.1.0
|
||||
peerDependenciesMeta:
|
||||
encoding:
|
||||
optional: true
|
||||
|
||||
node-releases@2.0.19:
|
||||
resolution: {integrity: sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==}
|
||||
|
||||
|
|
@ -2587,6 +2673,9 @@ packages:
|
|||
resolution: {integrity: sha512-IKJ6EzuPPWtKtEIEPpIdXv9j5j2LGJEYk0CKY2efgKoYKLBiZdh6iQkLVBow/CB3phyWAWCyk+bZeaimJn6uRQ==}
|
||||
engines: {node: '>=14.16'}
|
||||
|
||||
tr46@0.0.3:
|
||||
resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==}
|
||||
|
||||
truncatise@0.0.8:
|
||||
resolution: {integrity: sha512-cXzueh9pzBCsLzhToB4X4gZCb3KYkrsAcBAX97JnazE74HOl3cpBJYEV7nabHeG/6/WXCU5Yujlde/WPBUwnsg==}
|
||||
|
||||
|
|
@ -2640,6 +2729,13 @@ packages:
|
|||
engines: {node: '>=14.17'}
|
||||
hasBin: true
|
||||
|
||||
ua-is-frozen@0.1.2:
|
||||
resolution: {integrity: sha512-RwKDW2p3iyWn4UbaxpP2+VxwqXh0jpvdxsYpZ5j/MLLiQOfbsV5shpgQiw93+KMYQPcteeMQ289MaAFzs3G9pw==}
|
||||
|
||||
ua-parser-js@2.0.4:
|
||||
resolution: {integrity: sha512-XiBOnM/UpUq21ZZ91q2AVDOnGROE6UQd37WrO9WBgw4u2eGvUCNOheMmZ3EfEUj7DLHr8tre+Um/436Of/Vwzg==}
|
||||
hasBin: true
|
||||
|
||||
uglify-js@3.19.3:
|
||||
resolution: {integrity: sha512-v3Xu+yuwBXisp6QYTcH4UbH+xYJXqnq2m/LtQVWKWzYc1iehYnLixoQDN9FH6/j9/oybfd6W9Ghwkl8+UMKTKQ==}
|
||||
engines: {node: '>=0.8.0'}
|
||||
|
|
@ -2694,6 +2790,17 @@ packages:
|
|||
resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==}
|
||||
engines: {node: '>= 0.8'}
|
||||
|
||||
web-push@3.6.7:
|
||||
resolution: {integrity: sha512-OpiIUe8cuGjrj3mMBFWY+e4MMIkW3SVT+7vEIjvD9kejGUypv8GPDf84JdPWskK8zMRIJ6xYGm+Kxr8YkPyA0A==}
|
||||
engines: {node: '>= 16'}
|
||||
hasBin: true
|
||||
|
||||
webidl-conversions@3.0.1:
|
||||
resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==}
|
||||
|
||||
whatwg-url@5.0.0:
|
||||
resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==}
|
||||
|
||||
which@2.0.2:
|
||||
resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==}
|
||||
engines: {node: '>= 8'}
|
||||
|
|
@ -3531,6 +3638,11 @@ snapshots:
|
|||
|
||||
'@types/luxon@3.6.2': {}
|
||||
|
||||
'@types/node-fetch@2.6.13':
|
||||
dependencies:
|
||||
'@types/node': 22.16.0
|
||||
form-data: 4.0.4
|
||||
|
||||
'@types/node@22.16.0':
|
||||
dependencies:
|
||||
undici-types: 6.21.0
|
||||
|
|
@ -3547,6 +3659,10 @@ snapshots:
|
|||
|
||||
'@types/validator@13.15.2': {}
|
||||
|
||||
'@types/web-push@3.6.4':
|
||||
dependencies:
|
||||
'@types/node': 22.16.0
|
||||
|
||||
'@typescript-eslint/eslint-plugin@8.35.1(@typescript-eslint/parser@8.35.1(eslint@9.30.1)(typescript@5.8.3))(eslint@9.30.1)(typescript@5.8.3)':
|
||||
dependencies:
|
||||
'@eslint-community/regexpp': 4.12.1
|
||||
|
|
@ -3675,6 +3791,8 @@ snapshots:
|
|||
'@poppinss/utils': 6.10.0
|
||||
got: 14.4.7
|
||||
|
||||
agent-base@7.1.4: {}
|
||||
|
||||
ajv@6.12.6:
|
||||
dependencies:
|
||||
fast-deep-equal: 3.1.3
|
||||
|
|
@ -3708,6 +3826,13 @@ snapshots:
|
|||
dependencies:
|
||||
printable-characters: 1.0.42
|
||||
|
||||
asn1.js@5.4.1:
|
||||
dependencies:
|
||||
bn.js: 4.12.2
|
||||
inherits: 2.0.4
|
||||
minimalistic-assert: 1.0.1
|
||||
safer-buffer: 2.1.2
|
||||
|
||||
assertion-error@2.0.1: {}
|
||||
|
||||
astring@1.9.0: {}
|
||||
|
|
@ -3720,6 +3845,8 @@ snapshots:
|
|||
dependencies:
|
||||
retry: 0.13.1
|
||||
|
||||
asynckit@0.4.0: {}
|
||||
|
||||
atomic-sleep@1.0.0: {}
|
||||
|
||||
balanced-match@1.0.2: {}
|
||||
|
|
@ -3740,6 +3867,8 @@ snapshots:
|
|||
ioredis: 5.6.1
|
||||
knex: 3.1.0(pg@8.16.3)
|
||||
|
||||
bn.js@4.12.2: {}
|
||||
|
||||
brace-expansion@1.1.12:
|
||||
dependencies:
|
||||
balanced-match: 1.0.2
|
||||
|
|
@ -3760,6 +3889,8 @@ snapshots:
|
|||
node-releases: 2.0.19
|
||||
update-browserslist-db: 1.1.3(browserslist@4.25.1)
|
||||
|
||||
buffer-equal-constant-time@1.0.1: {}
|
||||
|
||||
builtin-modules@5.0.0: {}
|
||||
|
||||
bytes@3.1.2: {}
|
||||
|
|
@ -3863,6 +3994,10 @@ snapshots:
|
|||
|
||||
colorette@2.0.20: {}
|
||||
|
||||
combined-stream@1.0.8:
|
||||
dependencies:
|
||||
delayed-stream: 1.0.0
|
||||
|
||||
commander@10.0.1: {}
|
||||
|
||||
common-path-prefix@3.0.0: {}
|
||||
|
|
@ -3933,12 +4068,16 @@ snapshots:
|
|||
|
||||
defer-to-connect@2.0.1: {}
|
||||
|
||||
delayed-stream@1.0.0: {}
|
||||
|
||||
denque@2.1.0: {}
|
||||
|
||||
depd@2.0.0: {}
|
||||
|
||||
destroy@1.2.0: {}
|
||||
|
||||
detect-europe-js@0.1.2: {}
|
||||
|
||||
diff-sequences@29.6.3: {}
|
||||
|
||||
diff@4.0.2: {}
|
||||
|
|
@ -3953,6 +4092,10 @@ snapshots:
|
|||
es-errors: 1.3.0
|
||||
gopd: 1.2.0
|
||||
|
||||
ecdsa-sig-formatter@1.0.11:
|
||||
dependencies:
|
||||
safe-buffer: 5.2.1
|
||||
|
||||
edge-error@4.0.2: {}
|
||||
|
||||
edge-lexer@6.0.3:
|
||||
|
|
@ -4021,6 +4164,13 @@ snapshots:
|
|||
dependencies:
|
||||
es-errors: 1.3.0
|
||||
|
||||
es-set-tostringtag@2.1.0:
|
||||
dependencies:
|
||||
es-errors: 1.3.0
|
||||
get-intrinsic: 1.3.0
|
||||
has-tostringtag: 1.0.2
|
||||
hasown: 2.0.2
|
||||
|
||||
escalade@3.2.0: {}
|
||||
|
||||
escape-goat@4.0.0: {}
|
||||
|
|
@ -4235,6 +4385,14 @@ snapshots:
|
|||
|
||||
form-data-encoder@4.1.0: {}
|
||||
|
||||
form-data@4.0.4:
|
||||
dependencies:
|
||||
asynckit: 0.4.0
|
||||
combined-stream: 1.0.8
|
||||
es-set-tostringtag: 2.1.0
|
||||
hasown: 2.0.2
|
||||
mime-types: 2.1.35
|
||||
|
||||
formdata-node@6.0.3: {}
|
||||
|
||||
forwarded@0.2.0: {}
|
||||
|
|
@ -4326,6 +4484,10 @@ snapshots:
|
|||
|
||||
has-symbols@1.1.0: {}
|
||||
|
||||
has-tostringtag@1.0.2:
|
||||
dependencies:
|
||||
has-symbols: 1.1.0
|
||||
|
||||
hasown@2.0.2:
|
||||
dependencies:
|
||||
function-bind: 1.1.2
|
||||
|
|
@ -4361,6 +4523,15 @@ snapshots:
|
|||
quick-lru: 5.1.1
|
||||
resolve-alpn: 1.2.1
|
||||
|
||||
http_ece@1.2.0: {}
|
||||
|
||||
https-proxy-agent@7.0.6:
|
||||
dependencies:
|
||||
agent-base: 7.1.4
|
||||
debug: 4.4.1
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
human-signals@8.0.1: {}
|
||||
|
||||
ical-generator@7.2.0(@types/luxon@3.6.2)(@types/node@22.16.0)(dayjs@1.11.13)(luxon@3.6.1):
|
||||
|
|
@ -4443,6 +4614,8 @@ snapshots:
|
|||
|
||||
is-plain-obj@4.1.0: {}
|
||||
|
||||
is-standalone-pwa@0.1.1: {}
|
||||
|
||||
is-stream@4.0.1: {}
|
||||
|
||||
is-unicode-supported@2.1.0: {}
|
||||
|
|
@ -4482,6 +4655,17 @@ snapshots:
|
|||
|
||||
junk@4.0.1: {}
|
||||
|
||||
jwa@2.0.1:
|
||||
dependencies:
|
||||
buffer-equal-constant-time: 1.0.1
|
||||
ecdsa-sig-formatter: 1.0.11
|
||||
safe-buffer: 5.2.1
|
||||
|
||||
jws@4.0.0:
|
||||
dependencies:
|
||||
jwa: 2.0.1
|
||||
safe-buffer: 5.2.1
|
||||
|
||||
keyv@4.5.4:
|
||||
dependencies:
|
||||
json-buffer: 3.0.1
|
||||
|
|
@ -4605,6 +4789,8 @@ snapshots:
|
|||
|
||||
min-indent@1.0.1: {}
|
||||
|
||||
minimalistic-assert@1.0.1: {}
|
||||
|
||||
minimatch@3.1.2:
|
||||
dependencies:
|
||||
brace-expansion: 1.1.12
|
||||
|
|
@ -4627,6 +4813,10 @@ snapshots:
|
|||
|
||||
negotiator@0.6.3: {}
|
||||
|
||||
node-fetch@2.7.0:
|
||||
dependencies:
|
||||
whatwg-url: 5.0.0
|
||||
|
||||
node-releases@2.0.19: {}
|
||||
|
||||
nodemailer@6.10.1: {}
|
||||
|
|
@ -5156,6 +5346,8 @@ snapshots:
|
|||
'@tokenizer/token': 0.3.0
|
||||
ieee754: 1.2.1
|
||||
|
||||
tr46@0.0.3: {}
|
||||
|
||||
truncatise@0.0.8: {}
|
||||
|
||||
ts-api-utils@2.1.0(typescript@5.8.3):
|
||||
|
|
@ -5213,6 +5405,18 @@ snapshots:
|
|||
|
||||
typescript@5.8.3: {}
|
||||
|
||||
ua-is-frozen@0.1.2: {}
|
||||
|
||||
ua-parser-js@2.0.4:
|
||||
dependencies:
|
||||
'@types/node-fetch': 2.6.13
|
||||
detect-europe-js: 0.1.2
|
||||
is-standalone-pwa: 0.1.1
|
||||
node-fetch: 2.7.0
|
||||
ua-is-frozen: 0.1.2
|
||||
transitivePeerDependencies:
|
||||
- encoding
|
||||
|
||||
uglify-js@3.19.3: {}
|
||||
|
||||
uid-safe@2.1.5:
|
||||
|
|
@ -5252,6 +5456,23 @@ snapshots:
|
|||
|
||||
vary@1.1.2: {}
|
||||
|
||||
web-push@3.6.7:
|
||||
dependencies:
|
||||
asn1.js: 5.4.1
|
||||
http_ece: 1.2.0
|
||||
https-proxy-agent: 7.0.6
|
||||
jws: 4.0.0
|
||||
minimist: 1.2.8
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
webidl-conversions@3.0.1: {}
|
||||
|
||||
whatwg-url@5.0.0:
|
||||
dependencies:
|
||||
tr46: 0.0.3
|
||||
webidl-conversions: 3.0.1
|
||||
|
||||
which@2.0.2:
|
||||
dependencies:
|
||||
isexe: 2.0.0
|
||||
|
|
|
|||
|
|
@ -65,4 +65,10 @@ export default await Env.create(new URL('../', import.meta.url), {
|
|||
TURNSTILE_SECRET: Env.schema.string.optional(),
|
||||
|
||||
SESSION_DRIVER: Env.schema.enum(['cookie', 'memory'] as const),
|
||||
|
||||
PUBLIC_URL: Env.schema.string({ format: 'url' }),
|
||||
|
||||
VAPID_DETAILS: Env.schema.string(),
|
||||
VAPID_PUBLIC_KEY: Env.schema.string(),
|
||||
VAPID_PRIVATE_KEY: Env.schema.string(),
|
||||
})
|
||||
|
|
|
|||
|
|
@ -37,12 +37,25 @@ const SubjectsController = () => import('#controllers/subjects_controller')
|
|||
router.get('/subjects', [SubjectsController, 'index']).use(middleware.auth())
|
||||
|
||||
const CollesController = () => import('#controllers/colles_controller')
|
||||
router.group(() => {
|
||||
// TODO: PRIVATE ROUTES
|
||||
router.post('/', [CollesController, 'create'])
|
||||
router.post('/upcoming', [CollesController, 'createUpcoming'])
|
||||
router.post('/:colleId/refresh', [CollesController, 'refresh']).use(middleware.auth())
|
||||
router.get('/', [CollesController, 'index']).use(middleware.auth())
|
||||
router.get('/:colleId', [CollesController, 'show']).use(middleware.auth())
|
||||
}
|
||||
).prefix('/colles')
|
||||
router
|
||||
.group(() => {
|
||||
// TODO: PRIVATE ROUTES
|
||||
router.post('/', [CollesController, 'create'])
|
||||
router.post('/upcoming', [CollesController, 'createUpcoming'])
|
||||
router.post('/:colleId/refresh', [CollesController, 'refresh']).use(middleware.auth())
|
||||
router.get('/', [CollesController, 'index']).use(middleware.auth())
|
||||
router.get('/:colleId', [CollesController, 'show']).use(middleware.auth())
|
||||
})
|
||||
.prefix('/colles')
|
||||
|
||||
const NotificationsController = () => import('#controllers/notifications_controller')
|
||||
router
|
||||
.group(() => {
|
||||
router.get('/', [NotificationsController, 'index'])
|
||||
router.post('/subscribe', [NotificationsController, 'subscribe'])
|
||||
router.post('/:id/unsubscribe', [NotificationsController, 'unsubscribe'])
|
||||
router.post('/:id', [NotificationsController, 'update'])
|
||||
router.post('/:id/test', [NotificationsController, 'test']).use(middleware.auth())
|
||||
})
|
||||
.prefix('/notifications')
|
||||
.use(middleware.auth())
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue