-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* feat 🎸 (be): add generic user_tokens model * feat 🎸 (be): add service and controller methods for generating token and updating password * styles 💅 : add pages for reseting and updating password * fix ✅ : resolve comment * test 🧪 (unit): add unit tests for the new service methods * fix ✅ : typo * feat 🎸 (wip): prepare mail notification * feat 🎸 (be): add reset access email template * fix ✅ : general corrections * fix ✅ (be): user follow flaky behaviour * fix ✅ (fe): correction of tslint error suppression
- Loading branch information
1 parent
0a0a387
commit 05762bc
Showing
23 changed files
with
672 additions
and
24 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
export enum UserTokenType { | ||
RESET_ACCESS = 'RESET_ACCESS', | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
import User from '#models/user' | ||
import AuthResetNotification from '#notifications/auth_reset_notification' | ||
|
||
export default class TriggerAuthResetNotification { | ||
async handle({ user, token }: { user: User; token: string }) { | ||
user.notify(new AuthResetNotification(token)) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
import { renderToStaticMarkup } from 'react-dom/server' | ||
import PlatformBaseMailNotification from '#mails/base' | ||
import Template from '#mails/templates/reset_access_mail' | ||
import User from '#models/user' | ||
|
||
export default class ResetAccessMail extends PlatformBaseMailNotification { | ||
constructor(notifiable: User, token: string) { | ||
super(notifiable, { | ||
subject: 'Account access reset', | ||
body: renderToStaticMarkup(<Template user={notifiable} token={token} />), | ||
}) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
import User from '#models/user' | ||
import { route } from '@izzyjs/route/client' | ||
// FIX-ME: Getting import errors `app/app/...` - app appended twice. | ||
// import { Button } from '@/components/ui/button' | ||
// import AdonisLogo from '../../../inertia/components/svg/logo' | ||
// import { Button } from '../../../inertia/components/ui/button' | ||
|
||
const hr = 'bg-gray-100 my-5' | ||
const paragraph = 'text-sm text-slate-400 text-left' | ||
const baseUrl = | ||
'http://' + | ||
(process.env['NODE_ENV'] === 'development' | ||
? 'localhost:3000' | ||
: process.env['PRODUCTION_URL'] || 'social-adonis.fly.dev') | ||
|
||
export default function Template({ user, token }: { user: User; token: string }) { | ||
return ( | ||
<html> | ||
<head> | ||
<script src="https://cdn.tailwindcss.com" /> | ||
</head> | ||
|
||
<body | ||
style={{ | ||
backgroundColor: '#f6f9fc', | ||
fontFamily: | ||
'-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Ubuntu,sans-serif', | ||
}} | ||
> | ||
{/* <AdonisLogo /> */} | ||
<a href={baseUrl + route('home.show').path}> | ||
<svg className="h-16 w-16 fill-primary" viewBox="0 0 33 33"> | ||
<path | ||
fillRule="evenodd" | ||
d="M0 16.333c0 13.173 3.16 16.333 16.333 16.333 13.173 0 16.333-3.16 16.333-16.333C32.666 3.16 29.506 0 16.333 0 3.16 0 0 3.16 0 16.333Zm6.586 3.393L11.71 8.083c.865-1.962 2.528-3.027 4.624-3.027 2.096 0 3.759 1.065 4.624 3.027l5.123 11.643c.233.566.432 1.297.432 1.93 0 2.893-2.029 4.923-4.923 4.923-.986 0-1.769-.252-2.561-.506-.812-.261-1.634-.526-2.695-.526-1.048 0-1.89.267-2.718.529-.801.253-1.59.503-2.538.503-2.894 0-4.923-2.03-4.923-4.924 0-.632.2-1.363.432-1.929Zm9.747-9.613-5.056 11.443c1.497-.699 3.227-1.032 5.056-1.032 1.763 0 3.56.333 4.99 1.032l-4.99-11.444Z" | ||
clipRule="evenodd" | ||
/> | ||
</svg> | ||
</a> | ||
|
||
<hr className="my-5 bg-gray-100" /> | ||
|
||
<p className={paragraph}> | ||
Hello {user.name} {user.surname}, | ||
</p> | ||
|
||
<p className={paragraph}>Click the button below to reset your account access.</p> | ||
|
||
<button className="h-10 rounded-md bg-blue-500 text-white"> | ||
<a | ||
href={ | ||
baseUrl + | ||
route('auth.update', { | ||
qs: { | ||
token, | ||
}, | ||
}).path | ||
} | ||
> | ||
Update password | ||
</a> | ||
</button> | ||
|
||
{/* // FOOTER partial */} | ||
<p className={paragraph}> | ||
We'll be here to help you with any step along the way. You can find answers to most | ||
questions and get in touch with us on our{' '} | ||
<a className="text-blue-500" href={baseUrl}> | ||
support site | ||
</a> | ||
. | ||
</p> | ||
<p className={paragraph}>— The Social Adonis team</p> | ||
<hr className={hr} /> | ||
<p className="text-xs text-cyan-200"> | ||
Social Adonis, 354 Oyster Point Blvd, South San Francisco, CA 94080 | ||
</p> | ||
</body> | ||
</html> | ||
) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
import { DateTime } from 'luxon' | ||
import { BaseModel, belongsTo, column } from '@adonisjs/lucid/orm' | ||
import User from '#models/user' | ||
import { UserTokenType } from '#enums/user' | ||
import { createHash, type UUID } from 'node:crypto' | ||
import type { BelongsTo } from '@adonisjs/lucid/types/relations' | ||
|
||
export default class UserToken extends BaseModel { | ||
@column({ isPrimary: true }) | ||
declare id: UUID | ||
|
||
@belongsTo(() => User) | ||
declare user: BelongsTo<typeof User> | ||
|
||
@column() | ||
declare type: UserTokenType | ||
|
||
@column() | ||
declare userId: UUID | ||
|
||
@column() | ||
declare token: string | ||
|
||
@column.dateTime({ autoCreate: true }) | ||
declare createdAt: DateTime | ||
|
||
@column.dateTime() | ||
declare expiresAt: DateTime | ||
} | ||
|
||
export function generateNewToken(date: DateTime) { | ||
return createHash('sha256').update(date.toJSDate().toISOString()).digest('hex') | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
import { NotificationChannelName, NotificationContract } from '@osenco/adonisjs-notifications/types' | ||
import type User from '#models/user' | ||
import ResetAccessMail from '#mails/reset_access_mail' | ||
|
||
export default class AuthResetNotification implements NotificationContract<User> { | ||
private token: string | ||
|
||
constructor(token: string) { | ||
this.token = token | ||
} | ||
|
||
via(): NotificationChannelName | Array<NotificationChannelName> { | ||
return 'mail' | ||
} | ||
|
||
toMail(notifiable: User) { | ||
return new ResetAccessMail(notifiable, this.token) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,9 @@ | ||
import Post from '#models/post' | ||
import User from '#models/user' | ||
|
||
declare module '@adonisjs/core/types' { | ||
interface EventsList { | ||
'auth:reset': { user: User; token: string } | ||
'post:mention': [string[], Post] | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
26 changes: 26 additions & 0 deletions
26
database/migrations/1733746105899_create_create_user_tokens_table.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
import { UserTokenType } from '#enums/user' | ||
import { BaseSchema } from '@adonisjs/lucid/schema' | ||
|
||
export default class extends BaseSchema { | ||
protected tableName = 'user_tokens' | ||
|
||
async up() { | ||
this.schema.createTable(this.tableName, (table) => { | ||
table.uuid('id').primary().defaultTo(this.db.rawQuery('uuid_generate_v4()').knexQuery) | ||
table.uuid('user_id').references('users.id').notNullable() | ||
table.enu('type', Object.values(UserTokenType), { | ||
useNative: true, | ||
enumName: 'user_token_types', | ||
existingType: false, | ||
}).defaultTo(UserTokenType.RESET_ACCESS).notNullable() | ||
table.string('token').notNullable() | ||
table.timestamp('created_at', { useTz: false }).notNullable() | ||
table.timestamp('expires_at', { useTz: false }).notNullable().comment('If consulted after this date, it is considered to be an expired record.') | ||
}) | ||
} | ||
|
||
async down() { | ||
this.schema.dropTable(this.tableName) | ||
this.schema.raw('DROP TYPE IF EXISTS "user_token_types"') | ||
} | ||
} |
Oops, something went wrong.