chore(backend): convert basic RefreshToken model to TypeORM entity (#2401)

* chore: convert basic RefreshToken model to TypeORM entity

Co-authored-by: v1b3m <vibenjamin6@gmail.com>

* Fix import

Co-authored-by: v1b3m <vibenjamin6@gmail.com>

---------

Co-authored-by: v1b3m <vibenjamin6@gmail.com>
This commit is contained in:
gitstart-twenty
2023-11-14 17:54:04 +05:45
committed by GitHub
parent 6eb4e00ce1
commit a69711429b
11 changed files with 262 additions and 6 deletions

View File

@ -9,6 +9,7 @@ import GraphQLJSON from 'graphql-type-json';
import config from '../../ormconfig';
import { UserModule } from './userv2/user.module';
import { RefreshTokenModule } from './refresh-token/refresh-token.module';
@Module({
imports: [
@ -23,6 +24,7 @@ import { UserModule } from './userv2/user.module';
path: '/graphqlv2',
}),
UserModule,
RefreshTokenModule,
],
exports: [UserModule],
})

View File

@ -0,0 +1,11 @@
import { Field, InputType } from '@nestjs/graphql';
import { IsDate, IsNotEmpty } from 'class-validator';
@InputType()
export class CreateRefreshTokenInput {
@IsDate()
@IsNotEmpty()
@Field()
expiresAt: Date;
}

View File

@ -0,0 +1,24 @@
import {
BeforeCreateOneHook,
CreateOneInputType,
} from '@ptc-org/nestjs-query-graphql';
import { v4 as uuidv4 } from 'uuid';
import { RefreshToken } from 'src/coreV2/refresh-token/refresh-token.entity';
export class BeforeCreateOneRefreshToken<T extends RefreshToken>
implements BeforeCreateOneHook<T, any>
{
async run(
instance: CreateOneInputType<T>,
context: any,
): Promise<CreateOneInputType<T>> {
const userId = context?.req?.user?.user?.id;
instance.input.userId = userId;
// FIXME: These fields should be autogenerated, we need to run a migration for this
instance.input.id = uuidv4();
instance.input.updatedAt = new Date();
return instance;
}
}

View File

@ -0,0 +1,41 @@
import {
AutoResolverOpts,
PagingStrategies,
ReadResolverOpts,
} from '@ptc-org/nestjs-query-graphql';
import { SortDirection } from '@ptc-org/nestjs-query-core';
import { JwtAuthGuard } from 'src/guards/jwt.auth.guard';
import { RefreshToken } from './refresh-token.entity';
import { CreateRefreshTokenInput } from './dtos/create-refresh-token.input';
export const refreshTokenAutoResolverOpts: AutoResolverOpts<
any,
any,
unknown,
unknown,
ReadResolverOpts<any>,
PagingStrategies
>[] = [
{
EntityClass: RefreshToken,
DTOClass: RefreshToken,
CreateDTOClass: CreateRefreshTokenInput,
enableTotalCount: true,
pagingStrategy: PagingStrategies.CURSOR,
read: {
defaultSort: [{ field: 'id', direction: SortDirection.DESC }],
},
create: {
many: { disabled: true },
},
update: {
many: { disabled: true },
one: { disabled: true },
},
delete: { many: { disabled: true }, one: { disabled: true } },
guards: [JwtAuthGuard],
},
];

View File

@ -0,0 +1,59 @@
import { Field, ID, ObjectType } from '@nestjs/graphql';
import {
Entity,
Column,
PrimaryGeneratedColumn,
ManyToOne,
JoinColumn,
CreateDateColumn,
UpdateDateColumn,
} from 'typeorm';
import {
Authorize,
BeforeCreateOne,
IDField,
} from '@ptc-org/nestjs-query-graphql';
import { User } from 'src/coreV2/userv2/user.entity';
import { BeforeCreateOneRefreshToken } from './hooks/before-create-one-refresh-token.hook';
@Entity('refresh_tokens')
@ObjectType('RefreshToken')
@BeforeCreateOne(BeforeCreateOneRefreshToken)
@Authorize({
authorize: (context: any) => ({
userId: { eq: context?.req?.user?.user?.id },
}),
})
export class RefreshToken {
@IDField(() => ID)
@PrimaryGeneratedColumn('uuid')
id: string;
@ManyToOne(() => User, (user) => user.refreshTokens)
@JoinColumn({ name: 'userId' })
user: User;
@Column()
userId: string;
@Field()
@Column('time with time zone')
expiresAt: Date;
@Column('timestamp with time zone', { nullable: true })
deletedAt: Date | null;
@Column('timestamp with time zone', { nullable: true })
revokedAt: Date | null;
@Field()
@CreateDateColumn({ type: 'timestamp with time zone' })
createdAt: Date;
@Field()
@UpdateDateColumn({ type: 'timestamp with time zone' })
updatedAt: Date;
}

View File

@ -0,0 +1,20 @@
import { Module } from '@nestjs/common';
import { NestjsQueryGraphQLModule } from '@ptc-org/nestjs-query-graphql';
import { NestjsQueryTypeOrmModule } from '@ptc-org/nestjs-query-typeorm';
import { RefreshToken } from './refresh-token.entity';
import { refreshTokenAutoResolverOpts } from './refresh-token.auto-resolver-opts';
import { RefreshTokenService } from './services/refresh-token.service';
@Module({
imports: [
NestjsQueryGraphQLModule.forFeature({
imports: [NestjsQueryTypeOrmModule.forFeature([RefreshToken])],
services: [RefreshTokenService],
resolvers: refreshTokenAutoResolverOpts,
}),
],
})
export class RefreshTokenModule {}

View File

@ -0,0 +1,28 @@
import { Test, TestingModule } from '@nestjs/testing';
import { getRepositoryToken } from '@nestjs/typeorm';
import { RefreshToken } from 'src/coreV2/refresh-token/refresh-token.entity';
import { RefreshTokenService } from './refresh-token.service';
describe('RefreshTokenService', () => {
let service: RefreshTokenService;
beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
providers: [
RefreshTokenService,
{
provide: getRepositoryToken(RefreshToken),
useValue: {},
},
],
}).compile();
service = module.get<RefreshTokenService>(RefreshTokenService);
});
it('should be defined', () => {
expect(service).toBeDefined();
});
});

View File

@ -0,0 +1,5 @@
import { TypeOrmQueryService } from '@ptc-org/nestjs-query-typeorm';
import { RefreshToken } from 'src/coreV2/refresh-token/refresh-token.entity';
export class RefreshTokenService extends TypeOrmQueryService<RefreshToken> {}

View File

@ -1,4 +1,6 @@
import { Entity, Column, PrimaryGeneratedColumn } from 'typeorm';
import { Entity, Column, PrimaryGeneratedColumn, OneToMany } from 'typeorm';
import { RefreshToken } from 'src/coreV2/refresh-token/refresh-token.entity';
@Entity('users')
export class User {
@ -16,4 +18,7 @@ export class User {
@Column({ default: false })
emailVerified: boolean;
@OneToMany(() => RefreshToken, (refreshToken) => refreshToken.user)
refreshTokens: RefreshToken[];
}