feat: user usage gql & test case improve (#5076)

This commit is contained in:
DarkSky
2023-12-14 09:50:41 +00:00
parent ad23ead5e4
commit a93c12e122
22 changed files with 364 additions and 132 deletions

View File

@@ -64,35 +64,8 @@ export class RunCommand extends CommandRunner {
continue;
}
this.logger.log(`Running ${migration.name}...`);
const record = await this.db.dataMigration.create({
data: {
name: migration.name,
startedAt: new Date(),
},
});
await this.runMigration(migration);
try {
await migration.up(this.db);
} catch (e) {
await this.db.dataMigration.delete({
where: {
id: record.id,
},
});
await migration.down(this.db);
this.logger.error('Failed to run data migration', e);
process.exit(1);
}
await this.db.dataMigration.update({
where: {
id: record.id,
},
data: {
finishedAt: new Date(),
},
});
done.push(migration);
}
@@ -101,6 +74,56 @@ export class RunCommand extends CommandRunner {
this.logger.log(`${migration.name}`);
});
}
async runOne(name: string) {
const migrations = await collectMigrations();
const migration = migrations.find(m => m.name === name);
if (!migration) {
throw new Error(`Unknown migration name: ${name}.`);
}
const exists = await this.db.dataMigration.count({
where: {
name: migration.name,
},
});
if (exists) return;
await this.runMigration(migration);
}
private async runMigration(migration: Migration) {
this.logger.log(`Running ${migration.name}...`);
const record = await this.db.dataMigration.create({
data: {
name: migration.name,
startedAt: new Date(),
},
});
try {
await migration.up(this.db);
} catch (e) {
await this.db.dataMigration.delete({
where: {
id: record.id,
},
});
await migration.down(this.db);
this.logger.error('Failed to run data migration', e);
process.exit(1);
}
await this.db.dataMigration.update({
where: {
id: record.id,
},
data: {
finishedAt: new Date(),
},
});
}
}
@Command({

View File

@@ -29,6 +29,7 @@ import { GQLLoggerPlugin } from './graphql/logger-plugin';
context: ({ req, res }: { req: Request; res: Response }) => ({
req,
res,
isAdminQuery: false,
}),
plugins: [new GQLLoggerPlugin()],
};

View File

@@ -1,6 +1,7 @@
import { HttpStatus } from '@nestjs/common';
import {
Args,
Context,
Field,
Int,
Mutation,
@@ -254,8 +255,13 @@ export class UserSubscriptionResolver {
constructor(private readonly db: PrismaService) {}
@ResolveField(() => UserSubscriptionType, { nullable: true })
async subscription(@CurrentUser() me: User, @Parent() user: User) {
if (me.id !== user.id) {
async subscription(
@Context() ctx: { isAdminQuery: boolean },
@CurrentUser() me: User,
@Parent() user: User
) {
// allow admin to query other user's subscription
if (!ctx.isAdminQuery && me.id !== user.id) {
throw new GraphQLError(
'You are not allowed to access this subscription',
{

View File

@@ -17,5 +17,4 @@ import { QuotaManagementService } from './storage';
export class QuotaModule {}
export { QuotaManagementService, QuotaService };
export { PrismaService } from '../../prisma';
export { Quota_FreePlanV1, Quota_ProPlanV1, Quotas, QuotaType } from './types';

View File

@@ -6,6 +6,7 @@ import {
} from '@nestjs/common';
import {
Args,
Context,
Field,
ID,
Int,
@@ -267,10 +268,15 @@ export class UserResolver {
},
})
@Query(() => [UserType])
async listEarlyAccess(@CurrentUser() user: UserType): Promise<UserType[]> {
async earlyAccessUsers(
@Context() ctx: { isAdminQuery: boolean },
@CurrentUser() user: UserType
): Promise<UserType[]> {
if (!this.feature.isStaff(user.email)) {
throw new ForbiddenException('You are not allowed to do this');
}
// allow query other user's subscription
ctx.isAdminQuery = true;
return this.feature.listEarlyAccess();
}
}

View File

@@ -269,7 +269,7 @@ type Query {
"""Get user by email"""
user(email: String!): UserType
listEarlyAccess: [UserType!]!
earlyAccessUsers: [UserType!]!
prices: [SubscriptionPrice!]!
}