refactor: refactored a few types around users and passwordless tokens in auth module

This commit is contained in:
Balu Babu
2023-01-12 21:31:25 +05:30
parent 36b32a1813
commit 06f1c2fba2
7 changed files with 201 additions and 66 deletions

View File

@@ -10,10 +10,7 @@ import * as bcrypt from 'bcrypt';
import * as O from 'fp-ts/Option'; import * as O from 'fp-ts/Option';
import * as E from 'fp-ts/Either'; import * as E from 'fp-ts/Either';
import * as TE from 'fp-ts/TaskEither'; import * as TE from 'fp-ts/TaskEither';
import { import { DeviceIdentifierToken } from 'src/types/Passwordless';
DeviceIdentifierToken,
PasswordlessToken,
} from 'src/types/Passwordless';
import { import {
INVALID_EMAIL, INVALID_EMAIL,
INVALID_MAGIC_LINK_DATA, INVALID_MAGIC_LINK_DATA,
@@ -28,11 +25,11 @@ import {
AuthTokens, AuthTokens,
RefreshTokenPayload, RefreshTokenPayload,
} from 'src/types/AuthTokens'; } from 'src/types/AuthTokens';
import { ProviderAccount } from 'src/types/ProviderAccount';
import { JwtService } from '@nestjs/jwt'; import { JwtService } from '@nestjs/jwt';
import { AuthErrorHandler } from 'src/types/AuthErrorHandler'; import { AuthErrorHandler } from 'src/types/AuthErrorHandler';
import { AuthUser } from 'src/types/AuthUser'; import { AuthUser } from 'src/types/AuthUser';
import { isLeafType } from 'graphql'; import { isLeafType } from 'graphql';
import { PasswordlessVerification } from '@prisma/client';
@Injectable() @Injectable()
export class AuthService { export class AuthService {
@@ -44,25 +41,24 @@ export class AuthService {
) {} ) {}
// generate Id and token for email magiclink // generate Id and token for email magiclink
private async generatePasswordlessTokens(user: User) { private async generatePasswordlessTokens(user: AuthUser) {
const salt = await bcrypt.genSalt(10); const salt = await bcrypt.genSalt(10);
const expiresOn = DateTime.now().plus({ hours: 3 }).toISO().toString(); const expiresOn = DateTime.now().plus({ hours: 3 }).toISO().toString();
const idToken: PasswordlessToken = const idToken = await this.prismaService.passwordlessVerification.create({
await this.prismaService.passwordlessVerification.create({ data: {
data: { deviceIdentifier: salt,
deviceIdentifier: salt, userUid: user.id,
userUid: user.id, expiresOn: expiresOn,
expiresOn: expiresOn, },
}, });
});
return idToken; return idToken;
} }
private async validatePasswordlessTokens(data: verifyMagicDto) { private async validatePasswordlessTokens(data: verifyMagicDto) {
try { try {
const tokens: PasswordlessToken = const tokens =
await this.prismaService.passwordlessVerification.findUniqueOrThrow({ await this.prismaService.passwordlessVerification.findUniqueOrThrow({
where: { where: {
passwordless_deviceIdentifier_tokens: { passwordless_deviceIdentifier_tokens: {
@@ -79,7 +75,7 @@ export class AuthService {
private async UpdateUserRefreshToken(tokenHash: string, userUid: string) { private async UpdateUserRefreshToken(tokenHash: string, userUid: string) {
try { try {
const user: User = await this.prismaService.user.update({ const user = await this.prismaService.user.update({
where: { where: {
id: userUid, id: userUid,
}, },
@@ -143,7 +139,7 @@ export class AuthService {
} }
private async deletePasswordlessVerificationToken( private async deletePasswordlessVerificationToken(
passwordlessTokens: PasswordlessToken, passwordlessTokens: PasswordlessVerification,
) { ) {
try { try {
const deletedPasswordlessToken = const deletedPasswordlessToken =
@@ -162,15 +158,14 @@ export class AuthService {
} }
async checkIfProviderAccountExists(user: User, profile) { async checkIfProviderAccountExists(user: User, profile) {
const provider: ProviderAccount = const provider = await this.prismaService.account.findUnique({
await this.prismaService.account.findUnique({ where: {
where: { verifyProviderAccount: {
verifyProviderAccount: { provider: profile.provider,
provider: profile.provider, providerAccountId: profile.id,
providerAccountId: profile.id,
},
}, },
}); },
});
if (!provider) return O.none; if (!provider) return O.none;
@@ -186,7 +181,7 @@ export class AuthService {
statusCode: HttpStatus.BAD_REQUEST, statusCode: HttpStatus.BAD_REQUEST,
}); });
let user: User; let user: AuthUser;
const queriedUser = await this.usersService.findUserByEmail(email); const queriedUser = await this.usersService.findUserByEmail(email);
if (O.isNone(queriedUser)) { if (O.isNone(queriedUser)) {

View File

@@ -1,9 +1,3 @@
export interface AuthUser { import { User } from '@prisma/client';
id: string;
name: string; export type AuthUser = User;
email: string;
image: string;
isAdmin: boolean;
refreshToken: string;
createdOn: Date;
}

View File

@@ -1,13 +1,3 @@
import { User } from 'src/user/user.model';
export interface PasswordlessToken {
deviceIdentifier: string;
token: string;
userUid: string;
user?: User;
expiresOn: Date;
}
export interface DeviceIdentifierToken { export interface DeviceIdentifierToken {
deviceIdentifier: string; deviceIdentifier: string;
} }

View File

@@ -1,13 +0,0 @@
import { User } from 'src/user/user.model';
export interface ProviderAccount {
id: string;
userId: string;
user?: User;
provider: string;
providerAccountId: string;
providerRefreshToken?: string;
providerAccessToken?: string;
providerScope?: string;
loggedIn: Date;
}

View File

@@ -1,9 +1,6 @@
import { Injectable } from '@nestjs/common'; import { Injectable } from '@nestjs/common';
import { PrismaService } from 'src/prisma/prisma.service'; import { PrismaService } from 'src/prisma/prisma.service';
import * as O from 'fp-ts/Option'; import * as O from 'fp-ts/Option';
import { User } from './user.model';
import { ProviderAccount } from '../types/ProviderAccount';
import { AuthUser } from 'src/types/AuthUser';
@Injectable() @Injectable()
export class UserService { export class UserService {
@@ -11,7 +8,7 @@ export class UserService {
async findUserByEmail(email: string) { async findUserByEmail(email: string) {
try { try {
const user: AuthUser = await this.prisma.user.findUniqueOrThrow({ const user = await this.prisma.user.findUniqueOrThrow({
where: { where: {
email: email, email: email,
}, },
@@ -24,7 +21,7 @@ export class UserService {
async findUserById(userUid: string) { async findUserById(userUid: string) {
try { try {
const user: AuthUser = await this.prisma.user.findUniqueOrThrow({ const user = await this.prisma.user.findUniqueOrThrow({
where: { where: {
id: userUid, id: userUid,
}, },
@@ -36,7 +33,7 @@ export class UserService {
} }
async createUserMagic(email: string) { async createUserMagic(email: string) {
const createdUser: AuthUser = await this.prisma.user.create({ const createdUser = await this.prisma.user.create({
data: { data: {
email: email, email: email,
accounts: { accounts: {
@@ -52,7 +49,7 @@ export class UserService {
} }
async createUserSSO(accessToken, refreshToken, profile) { async createUserSSO(accessToken, refreshToken, profile) {
const createdUser: AuthUser = await this.prisma.user.create({ const createdUser = await this.prisma.user.create({
data: { data: {
name: profile.displayName, name: profile.displayName,
email: profile.emails[0].value, email: profile.emails[0].value,
@@ -72,7 +69,7 @@ export class UserService {
} }
async createProviderAccount(user, accessToken, refreshToken, profile) { async createProviderAccount(user, accessToken, refreshToken, profile) {
const createdProvider: ProviderAccount = await this.prisma.account.create({ const createdProvider = await this.prisma.account.create({
data: { data: {
userId: user.id, userId: user.id,
provider: profile.provider, provider: profile.provider,

View File

@@ -0,0 +1,172 @@
Script started on 2023-01-12 21:07:39+05:30 [TERM="xterm-256color" TTY="/dev/pts/3" COLUMNS="120" LINES="30"]
[oh-my-zsh] Insecure completion-dependent directories detected:
drwxrwxrwx 12 balubabu balubabu 4096 Jan 2 12:38 /home/balubabu/.oh-my-zsh
drwxrwxrwx 3 balubabu balubabu 4096 Jan 2 12:38 /home/balubabu/.oh-my-zsh/cache
drwxrwxrwx 2 balubabu balubabu 4096 Jan 2 12:38 /home/balubabu/.oh-my-zsh/cache/completions
drwxrwxrwx 316 balubabu balubabu 12288 Jan 2 12:38 /home/balubabu/.oh-my-zsh/plugins
drwxrwxrwx 2 balubabu balubabu 4096 Jan 2 12:38 /home/balubabu/.oh-my-zsh/plugins/git
[oh-my-zsh] For safety, we will not load completions from these directories until
[oh-my-zsh] you fix their permissions and ownership and restart zsh.
[oh-my-zsh] See the above list for directories with group or other writability.
[oh-my-zsh] To fix your permissions you can do so by disabling
[oh-my-zsh] the write permission of "group" and "others" and making sure that the
[oh-my-zsh] owner of these directories is either root or your current user.
[oh-my-zsh] The following command may help:
[oh-my-zsh] compaudit | xargs chmod g-w,o-w
[oh-my-zsh] If the above didn't help or you want to skip the verification of
[oh-my-zsh] insecure directories you can set the variable ZSH_DISABLE_COMPFIX to
[oh-my-zsh] "true" before oh-my-zsh is sourced in your zshrc file.
%
]2;balubabu@LAPTOP-ME2SCHA9:~/work/self-hosted/packages/hoppscotch-backend]1;..cotch-backend
➜ hoppscotch-backend git:(feat/user-authentication) ✗ [?1h=[?2004hccls[?1l>[?2004l
]2;clear]1;cls%
]2;balubabu@LAPTOP-ME2SCHA9:~/work/self-hosted/packages/hoppscotch-backend]1;..cotch-backend
➜ hoppscotch-backend git:(feat/user-authentication) ✗ [?1h=[?2004hmmigrate cd[?1l>[?2004l
]2;migrate cd]1;migratezsh: command not found: migrate
%
]2;balubabu@LAPTOP-ME2SCHA9:~/work/self-hosted/packages/hoppscotch-backend]1;..cotch-backend
➜ hoppscotch-backend git:(feat/user-authentication) ✗ [?1h=[?2004hbbash migrate[?1l>[?2004l
]2;bash migrate]1;bashbash: migrate: No such file or directory
%
]2;balubabu@LAPTOP-ME2SCHA9:~/work/self-hosted/packages/hoppscotch-backend]1;..cotch-backend
➜ hoppscotch-backend git:(feat/user-authentication) ✗ [?1h=[?2004hbash migrate.sh[?1l>[?2004l
]2;bash migrate.sh]1;bashbash: migrate.sh: No such file or directory
%
]2;balubabu@LAPTOP-ME2SCHA9:~/work/self-hosted/packages/hoppscotch-backend]1;..cotch-backend
➜ hoppscotch-backend git:(feat/user-authentication) ✗ [?1h=[?2004hccls[?1l>[?2004l
]2;clear]1;cls%
]2;balubabu@LAPTOP-ME2SCHA9:~/work/self-hosted/packages/hoppscotch-backend]1;..cotch-backend
➜ hoppscotch-backend git:(feat/user-authentication) ✗ [?1h=[?2004hccd ~[?1l>[?2004l
]2;cd ~]1;cd%
]2;balubabu@LAPTOP-ME2SCHA9:~]1;~
➜ ~ [?1h=[?2004hchmod +x site-check.shchmod +x site-check.sh.sh .sh .sh .sh .sh .sh .sh .sh .sh .sh m.shi.shg.shr.sha.sht.she.sh[?1l>[?2004l
]2;chmod +x migrate.sh]1;chmod%
]2;balubabu@LAPTOP-ME2SCHA9:~]1;~
➜ ~ [?1h=[?2004hmmirM
MiracastInputMgr.dll MiracastReceiver.dll MiracastReceiverExt.dll MirrorDrvCompat.dll 
Mirir r  mmigrate gdfchs[?1l>[?2004l
]2;migrate gdfchs]1;migratezsh: command not found: migrate
%
]2;balubabu@LAPTOP-ME2SCHA9:~]1;~
➜ ~ [?1h=[?2004hsudo cp site-check.sh /usr/bin/site-checksudo cp site-check.sh /usr/bin/site-check          migrate          m.sh /usr/bin/migratei.sh /usr/bin/migrateg.sh /usr/bin/migrater.sh /usr/bin/migratea.sh /usr/bin/migratet.sh /usr/bin/migratee.sh /usr/bin/migrate[?1l>[?2004l
]2;sudo cp migrate.sh /usr/bin/migrate]1;cp[sudo] password for balubabu:
%
]2;balubabu@LAPTOP-ME2SCHA9:~]1;~
➜ ~ [?1h=[?2004hmmir grate[?1l>[?2004l
]2;migrate]1;migrate"docker exec" requires at least 2 arguments.
See 'docker exec --help'.
Usage: docker exec [OPTIONS] CONTAINER COMMAND [ARG...]
Run a command in a running container
%
]2;balubabu@LAPTOP-ME2SCHA9:~]1;~
➜ ~ [?1h=[?2004hccls[?1l>[?2004l
]2;clear]1;cls%
]2;balubabu@LAPTOP-ME2SCHA9:~]1;~
➜ ~ [?1h=[?2004hccd work//self-hosted//h packages//hoppscotch-backend/ [?1l>[?2004l
]2;cd work/self-hosted/packages/hoppscotch-backend]1;cd%
]2;balubabu@LAPTOP-ME2SCHA9:~/work/self-hosted/packages/hoppscotch-backend]1;..cotch-backend
➜ hoppscotch-backend git:(feat/user-authentication) ✗ [?1h=[?2004hcc;s[?1l>[?2004l
]2;c; s]1;c;szsh: command not found: c
zsh: command not found: s
%
]2;balubabu@LAPTOP-ME2SCHA9:~/work/self-hosted/packages/hoppscotch-backend]1;..cotch-backend
➜ hoppscotch-backend git:(feat/user-authentication) ✗ [?1h=[?2004hccls[?1l>[?2004l
]2;clear]1;cls%
]2;balubabu@LAPTOP-ME2SCHA9:~/work/self-hosted/packages/hoppscotch-backend]1;..cotch-backend
➜ hoppscotch-backend git:(feat/user-authentication) ✗ [?1h=[?2004hddocker ps[?1l>[?2004l
]2;docker ps]1;dockerCONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
f48d44a76ccc hoppscotch-backend-local "docker-entrypoint.s…" 50 minutes ago Up 50 minutes 3170/tcp, 0.0.0.0:9229->9229/tcp, 0.0.0.0:3170->3000/tcp hoppscotch-backend-local-1
ca1f2c39cdb5 postgres "docker-entrypoint.s…" 50 minutes ago Up 50 minutes 0.0.0.0:5432->5432/tcp hoppscotch-backend-dev-db-1
%
]2;balubabu@LAPTOP-ME2SCHA9:~/work/self-hosted/packages/hoppscotch-backend]1;..cotch-backend
➜ hoppscotch-backend git:(feat/user-authentication) ✗ [?1h=[?2004hmmigrater  f48d44a76cccf48d44a76ccc\[?1l>[?2004l
> [?1h=[?2004h[?2004l
%
]2;balubabu@LAPTOP-ME2SCHA9:~/work/self-hosted/packages/hoppscotch-backend]1;..cotch-backend
➜ hoppscotch-backend git:(feat/user-authentication) ✗ [?1h=[?2004hmigrate f48d44a76ccc\ [?1l>[?2004l
]2;migrate f48d44a76ccc]1;migrate[?2004hroot@f48d44a76ccc:/usr/src/app# cd prisma/
[?2004l
[?2004hroot@f48d44a76ccc:/usr/src/app/prisma# pnpx prisma migrate dev
[?2004l
.pnpm-store/v3/tmp/dlx-2319 | Progress: resolved 1, reused 0, downloaded 0, added 0
.pnpm-store/v3/tmp/dlx-2319 | +2 +
.pnpm-store/v3/tmp/dlx-2319 | Progress: resolved 1, reused 0, downloaded 0, added 0
.pnpm-store/v3/tmp/dlx-2319 | Progress: resolved 2, reused 2, downloaded 0, added 2, done
Environment variables loaded from ../.env
Prisma schema loaded from schema.prisma
Datasource "db": PostgreSQL database "hoppscotch", schema "public" at "dev-db:5432"
Applying migration `20230112140525_auth`
The following migration(s) have been applied:
migrations/
└─ 20230112140525_auth/
└─ migration.sql
Your database is now in sync with your schema.
[?25lRunning generate... (Use --skip-generate to skip the generators)
[?25lRunning generate... - Prisma Client
[?25l✔ Generated Prisma Client (4.8.1 | library) to ./../node_modules/.pnpm/@prisma+client@4.8.1_prisma@4.8.1/node_modules/@p
risma/client in 121ms
[?25h[?2004hroot@f48d44a76ccc:/usr/src/app/prisma# exit
[?2004l
exit
%
]2;balubabu@LAPTOP-ME2SCHA9:~/work/self-hosted/packages/hoppscotch-backend]1;..cotch-backend
➜ hoppscotch-backend git:(feat/user-authentication) ✗ [?1h=[?2004hccls[?1l>[?2004l
]2;clear]1;cls%
]2;balubabu@LAPTOP-ME2SCHA9:~/work/self-hosted/packages/hoppscotch-backend]1;..cotch-backend
➜ hoppscotch-backend git:(feat/user-authentication) ✗ [?1h=[?2004hnpm install passport-google-oauth20npm install passport-google-oauth20pnpm install passport-google-oauth20-passport-google-oauth20-passport-google-oauth20spassport-google-oauth20apassport-google-oauth20vpassport-google-oauth20epassport-google-oauth20 passport-google-oauth20[?1l>[?2004l
]2;pnpm install --save passport-google-oauth20]1;pnpm../.. | Progress: resolved 0, reused 1, downloaded 0, added 0