HBE-296 feat: introducing 'infra' type and splitting model properties between 'admin' and 'infra' (#3445)
* feat: infra type added in admin module * feat: infra-resolver added in admin module * feat: feedback resolved * feat: deprecated tag added in some admin ResolveFields * build: update pnpm-lock file * feat: add field in infra type * feat: admin extends user partially * feat: admin extends user with omitting some fields * chore: remove unused imports * build: conflict resolve in pnpm lock file
This commit is contained in:
@@ -1,4 +1,9 @@
|
|||||||
import { ObjectType } from '@nestjs/graphql';
|
import { ObjectType, OmitType } from '@nestjs/graphql';
|
||||||
|
import { User } from 'src/user/user.model';
|
||||||
|
|
||||||
@ObjectType()
|
@ObjectType()
|
||||||
export class Admin {}
|
export class Admin extends OmitType(User, [
|
||||||
|
'isAdmin',
|
||||||
|
'currentRESTSession',
|
||||||
|
'currentGQLSession',
|
||||||
|
]) {}
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import { TeamInvitationModule } from '../team-invitation/team-invitation.module'
|
|||||||
import { TeamEnvironmentsModule } from '../team-environments/team-environments.module';
|
import { TeamEnvironmentsModule } from '../team-environments/team-environments.module';
|
||||||
import { TeamCollectionModule } from '../team-collection/team-collection.module';
|
import { TeamCollectionModule } from '../team-collection/team-collection.module';
|
||||||
import { TeamRequestModule } from '../team-request/team-request.module';
|
import { TeamRequestModule } from '../team-request/team-request.module';
|
||||||
|
import { InfraResolver } from './infra.resolver';
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
imports: [
|
imports: [
|
||||||
@@ -23,7 +24,7 @@ import { TeamRequestModule } from '../team-request/team-request.module';
|
|||||||
TeamCollectionModule,
|
TeamCollectionModule,
|
||||||
TeamRequestModule,
|
TeamRequestModule,
|
||||||
],
|
],
|
||||||
providers: [AdminResolver, AdminService],
|
providers: [InfraResolver, AdminResolver, AdminService],
|
||||||
exports: [AdminService],
|
exports: [AdminService],
|
||||||
})
|
})
|
||||||
export class AdminModule {}
|
export class AdminModule {}
|
||||||
|
|||||||
@@ -21,15 +21,15 @@ import { InvitedUser } from './invited-user.model';
|
|||||||
import { GqlUser } from '../decorators/gql-user.decorator';
|
import { GqlUser } from '../decorators/gql-user.decorator';
|
||||||
import { PubSubService } from '../pubsub/pubsub.service';
|
import { PubSubService } from '../pubsub/pubsub.service';
|
||||||
import { Team, TeamMember } from '../team/team.model';
|
import { Team, TeamMember } from '../team/team.model';
|
||||||
import { User } from '../user/user.model';
|
|
||||||
import { TeamInvitation } from '../team-invitation/team-invitation.model';
|
|
||||||
import { PaginationArgs } from '../types/input-types.args';
|
|
||||||
import {
|
import {
|
||||||
AddUserToTeamArgs,
|
AddUserToTeamArgs,
|
||||||
ChangeUserRoleInTeamArgs,
|
ChangeUserRoleInTeamArgs,
|
||||||
} from './input-types.args';
|
} from './input-types.args';
|
||||||
import { GqlThrottlerGuard } from 'src/guards/gql-throttler.guard';
|
import { GqlThrottlerGuard } from 'src/guards/gql-throttler.guard';
|
||||||
import { SkipThrottle } from '@nestjs/throttler';
|
import { SkipThrottle } from '@nestjs/throttler';
|
||||||
|
import { User } from 'src/user/user.model';
|
||||||
|
import { PaginationArgs } from 'src/types/input-types.args';
|
||||||
|
import { TeamInvitation } from 'src/team-invitation/team-invitation.model';
|
||||||
|
|
||||||
@UseGuards(GqlThrottlerGuard)
|
@UseGuards(GqlThrottlerGuard)
|
||||||
@Resolver(() => Admin)
|
@Resolver(() => Admin)
|
||||||
@@ -51,6 +51,7 @@ export class AdminResolver {
|
|||||||
|
|
||||||
@ResolveField(() => [User], {
|
@ResolveField(() => [User], {
|
||||||
description: 'Returns a list of all admin users in infra',
|
description: 'Returns a list of all admin users in infra',
|
||||||
|
deprecationReason: 'Use `infra` query instead',
|
||||||
})
|
})
|
||||||
@UseGuards(GqlAuthGuard, GqlAdminGuard)
|
@UseGuards(GqlAuthGuard, GqlAdminGuard)
|
||||||
async admins() {
|
async admins() {
|
||||||
@@ -59,6 +60,7 @@ export class AdminResolver {
|
|||||||
}
|
}
|
||||||
@ResolveField(() => User, {
|
@ResolveField(() => User, {
|
||||||
description: 'Returns a user info by UID',
|
description: 'Returns a user info by UID',
|
||||||
|
deprecationReason: 'Use `infra` query instead',
|
||||||
})
|
})
|
||||||
@UseGuards(GqlAuthGuard, GqlAdminGuard)
|
@UseGuards(GqlAuthGuard, GqlAdminGuard)
|
||||||
async userInfo(
|
async userInfo(
|
||||||
@@ -76,6 +78,7 @@ export class AdminResolver {
|
|||||||
|
|
||||||
@ResolveField(() => [User], {
|
@ResolveField(() => [User], {
|
||||||
description: 'Returns a list of all the users in infra',
|
description: 'Returns a list of all the users in infra',
|
||||||
|
deprecationReason: 'Use `infra` query instead',
|
||||||
})
|
})
|
||||||
@UseGuards(GqlAuthGuard, GqlAdminGuard)
|
@UseGuards(GqlAuthGuard, GqlAdminGuard)
|
||||||
async allUsers(
|
async allUsers(
|
||||||
@@ -88,6 +91,7 @@ export class AdminResolver {
|
|||||||
|
|
||||||
@ResolveField(() => [InvitedUser], {
|
@ResolveField(() => [InvitedUser], {
|
||||||
description: 'Returns a list of all the invited users',
|
description: 'Returns a list of all the invited users',
|
||||||
|
deprecationReason: 'Use `infra` query instead',
|
||||||
})
|
})
|
||||||
async invitedUsers(@Parent() admin: Admin): Promise<InvitedUser[]> {
|
async invitedUsers(@Parent() admin: Admin): Promise<InvitedUser[]> {
|
||||||
const users = await this.adminService.fetchInvitedUsers();
|
const users = await this.adminService.fetchInvitedUsers();
|
||||||
@@ -96,6 +100,7 @@ export class AdminResolver {
|
|||||||
|
|
||||||
@ResolveField(() => [Team], {
|
@ResolveField(() => [Team], {
|
||||||
description: 'Returns a list of all the teams in the infra',
|
description: 'Returns a list of all the teams in the infra',
|
||||||
|
deprecationReason: 'Use `infra` query instead',
|
||||||
})
|
})
|
||||||
async allTeams(
|
async allTeams(
|
||||||
@Parent() admin: Admin,
|
@Parent() admin: Admin,
|
||||||
@@ -106,6 +111,7 @@ export class AdminResolver {
|
|||||||
}
|
}
|
||||||
@ResolveField(() => Team, {
|
@ResolveField(() => Team, {
|
||||||
description: 'Returns a team info by ID when requested by Admin',
|
description: 'Returns a team info by ID when requested by Admin',
|
||||||
|
deprecationReason: 'Use `infra` query instead',
|
||||||
})
|
})
|
||||||
async teamInfo(
|
async teamInfo(
|
||||||
@Parent() admin: Admin,
|
@Parent() admin: Admin,
|
||||||
@@ -123,6 +129,7 @@ export class AdminResolver {
|
|||||||
|
|
||||||
@ResolveField(() => Number, {
|
@ResolveField(() => Number, {
|
||||||
description: 'Return count of all the members in a team',
|
description: 'Return count of all the members in a team',
|
||||||
|
deprecationReason: 'Use `infra` query instead',
|
||||||
})
|
})
|
||||||
async membersCountInTeam(
|
async membersCountInTeam(
|
||||||
@Parent() admin: Admin,
|
@Parent() admin: Admin,
|
||||||
@@ -140,6 +147,7 @@ export class AdminResolver {
|
|||||||
|
|
||||||
@ResolveField(() => Number, {
|
@ResolveField(() => Number, {
|
||||||
description: 'Return count of all the stored collections in a team',
|
description: 'Return count of all the stored collections in a team',
|
||||||
|
deprecationReason: 'Use `infra` query instead',
|
||||||
})
|
})
|
||||||
async collectionCountInTeam(
|
async collectionCountInTeam(
|
||||||
@Parent() admin: Admin,
|
@Parent() admin: Admin,
|
||||||
@@ -155,6 +163,7 @@ export class AdminResolver {
|
|||||||
}
|
}
|
||||||
@ResolveField(() => Number, {
|
@ResolveField(() => Number, {
|
||||||
description: 'Return count of all the stored requests in a team',
|
description: 'Return count of all the stored requests in a team',
|
||||||
|
deprecationReason: 'Use `infra` query instead',
|
||||||
})
|
})
|
||||||
async requestCountInTeam(
|
async requestCountInTeam(
|
||||||
@Parent() admin: Admin,
|
@Parent() admin: Admin,
|
||||||
@@ -171,6 +180,7 @@ export class AdminResolver {
|
|||||||
|
|
||||||
@ResolveField(() => Number, {
|
@ResolveField(() => Number, {
|
||||||
description: 'Return count of all the stored environments in a team',
|
description: 'Return count of all the stored environments in a team',
|
||||||
|
deprecationReason: 'Use `infra` query instead',
|
||||||
})
|
})
|
||||||
async environmentCountInTeam(
|
async environmentCountInTeam(
|
||||||
@Parent() admin: Admin,
|
@Parent() admin: Admin,
|
||||||
@@ -187,6 +197,7 @@ export class AdminResolver {
|
|||||||
|
|
||||||
@ResolveField(() => [TeamInvitation], {
|
@ResolveField(() => [TeamInvitation], {
|
||||||
description: 'Return all the pending invitations in a team',
|
description: 'Return all the pending invitations in a team',
|
||||||
|
deprecationReason: 'Use `infra` query instead',
|
||||||
})
|
})
|
||||||
async pendingInvitationCountInTeam(
|
async pendingInvitationCountInTeam(
|
||||||
@Parent() admin: Admin,
|
@Parent() admin: Admin,
|
||||||
@@ -205,6 +216,7 @@ export class AdminResolver {
|
|||||||
|
|
||||||
@ResolveField(() => Number, {
|
@ResolveField(() => Number, {
|
||||||
description: 'Return total number of Users in organization',
|
description: 'Return total number of Users in organization',
|
||||||
|
deprecationReason: 'Use `infra` query instead',
|
||||||
})
|
})
|
||||||
async usersCount() {
|
async usersCount() {
|
||||||
return this.adminService.getUsersCount();
|
return this.adminService.getUsersCount();
|
||||||
@@ -212,6 +224,7 @@ export class AdminResolver {
|
|||||||
|
|
||||||
@ResolveField(() => Number, {
|
@ResolveField(() => Number, {
|
||||||
description: 'Return total number of Teams in organization',
|
description: 'Return total number of Teams in organization',
|
||||||
|
deprecationReason: 'Use `infra` query instead',
|
||||||
})
|
})
|
||||||
async teamsCount() {
|
async teamsCount() {
|
||||||
return this.adminService.getTeamsCount();
|
return this.adminService.getTeamsCount();
|
||||||
@@ -219,6 +232,7 @@ export class AdminResolver {
|
|||||||
|
|
||||||
@ResolveField(() => Number, {
|
@ResolveField(() => Number, {
|
||||||
description: 'Return total number of Team Collections in organization',
|
description: 'Return total number of Team Collections in organization',
|
||||||
|
deprecationReason: 'Use `infra` query instead',
|
||||||
})
|
})
|
||||||
async teamCollectionsCount() {
|
async teamCollectionsCount() {
|
||||||
return this.adminService.getTeamCollectionsCount();
|
return this.adminService.getTeamCollectionsCount();
|
||||||
@@ -226,6 +240,7 @@ export class AdminResolver {
|
|||||||
|
|
||||||
@ResolveField(() => Number, {
|
@ResolveField(() => Number, {
|
||||||
description: 'Return total number of Team Requests in organization',
|
description: 'Return total number of Team Requests in organization',
|
||||||
|
deprecationReason: 'Use `infra` query instead',
|
||||||
})
|
})
|
||||||
async teamRequestsCount() {
|
async teamRequestsCount() {
|
||||||
return this.adminService.getTeamRequestsCount();
|
return this.adminService.getTeamRequestsCount();
|
||||||
|
|||||||
10
packages/hoppscotch-backend/src/admin/infra.model.ts
Normal file
10
packages/hoppscotch-backend/src/admin/infra.model.ts
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
import { Field, ObjectType } from '@nestjs/graphql';
|
||||||
|
import { Admin } from './admin.model';
|
||||||
|
|
||||||
|
@ObjectType()
|
||||||
|
export class Infra {
|
||||||
|
@Field(() => Admin, {
|
||||||
|
description: 'Admin who executed the action',
|
||||||
|
})
|
||||||
|
executedBy: Admin;
|
||||||
|
}
|
||||||
205
packages/hoppscotch-backend/src/admin/infra.resolver.ts
Normal file
205
packages/hoppscotch-backend/src/admin/infra.resolver.ts
Normal file
@@ -0,0 +1,205 @@
|
|||||||
|
import { UseGuards } from '@nestjs/common';
|
||||||
|
import { Args, ID, Query, ResolveField, Resolver } from '@nestjs/graphql';
|
||||||
|
import { GqlThrottlerGuard } from 'src/guards/gql-throttler.guard';
|
||||||
|
import { Infra } from './infra.model';
|
||||||
|
import { AdminService } from './admin.service';
|
||||||
|
import { GqlAuthGuard } from 'src/guards/gql-auth.guard';
|
||||||
|
import { GqlAdminGuard } from './guards/gql-admin.guard';
|
||||||
|
import { User } from 'src/user/user.model';
|
||||||
|
import { AuthUser } from 'src/types/AuthUser';
|
||||||
|
import { throwErr } from 'src/utils';
|
||||||
|
import * as E from 'fp-ts/Either';
|
||||||
|
import { Admin } from './admin.model';
|
||||||
|
import { PaginationArgs } from 'src/types/input-types.args';
|
||||||
|
import { InvitedUser } from './invited-user.model';
|
||||||
|
import { Team } from 'src/team/team.model';
|
||||||
|
import { TeamInvitation } from 'src/team-invitation/team-invitation.model';
|
||||||
|
import { GqlAdmin } from './decorators/gql-admin.decorator';
|
||||||
|
|
||||||
|
@UseGuards(GqlThrottlerGuard)
|
||||||
|
@Resolver(() => Infra)
|
||||||
|
export class InfraResolver {
|
||||||
|
constructor(private adminService: AdminService) {}
|
||||||
|
|
||||||
|
@Query(() => Infra, {
|
||||||
|
description: 'Fetch details of the Infrastructure',
|
||||||
|
})
|
||||||
|
@UseGuards(GqlAuthGuard, GqlAdminGuard)
|
||||||
|
infra(@GqlAdmin() admin: Admin) {
|
||||||
|
const infra: Infra = { executedBy: admin };
|
||||||
|
return infra;
|
||||||
|
}
|
||||||
|
|
||||||
|
@ResolveField(() => [User], {
|
||||||
|
description: 'Returns a list of all admin users in infra',
|
||||||
|
})
|
||||||
|
@UseGuards(GqlAuthGuard, GqlAdminGuard)
|
||||||
|
async admins() {
|
||||||
|
const admins = await this.adminService.fetchAdmins();
|
||||||
|
return admins;
|
||||||
|
}
|
||||||
|
|
||||||
|
@ResolveField(() => User, {
|
||||||
|
description: 'Returns a user info by UID',
|
||||||
|
})
|
||||||
|
@UseGuards(GqlAuthGuard, GqlAdminGuard)
|
||||||
|
async userInfo(
|
||||||
|
@Args({
|
||||||
|
name: 'userUid',
|
||||||
|
type: () => ID,
|
||||||
|
description: 'The user UID',
|
||||||
|
})
|
||||||
|
userUid: string,
|
||||||
|
): Promise<AuthUser> {
|
||||||
|
const user = await this.adminService.fetchUserInfo(userUid);
|
||||||
|
if (E.isLeft(user)) throwErr(user.left);
|
||||||
|
return user.right;
|
||||||
|
}
|
||||||
|
|
||||||
|
@ResolveField(() => [User], {
|
||||||
|
description: 'Returns a list of all the users in infra',
|
||||||
|
})
|
||||||
|
@UseGuards(GqlAuthGuard, GqlAdminGuard)
|
||||||
|
async allUsers(@Args() args: PaginationArgs): Promise<AuthUser[]> {
|
||||||
|
const users = await this.adminService.fetchUsers(args.cursor, args.take);
|
||||||
|
return users;
|
||||||
|
}
|
||||||
|
|
||||||
|
@ResolveField(() => [InvitedUser], {
|
||||||
|
description: 'Returns a list of all the invited users',
|
||||||
|
})
|
||||||
|
async invitedUsers(): Promise<InvitedUser[]> {
|
||||||
|
const users = await this.adminService.fetchInvitedUsers();
|
||||||
|
return users;
|
||||||
|
}
|
||||||
|
|
||||||
|
@ResolveField(() => [Team], {
|
||||||
|
description: 'Returns a list of all the teams in the infra',
|
||||||
|
})
|
||||||
|
async allTeams(@Args() args: PaginationArgs): Promise<Team[]> {
|
||||||
|
const teams = await this.adminService.fetchAllTeams(args.cursor, args.take);
|
||||||
|
return teams;
|
||||||
|
}
|
||||||
|
|
||||||
|
@ResolveField(() => Team, {
|
||||||
|
description: 'Returns a team info by ID when requested by Admin',
|
||||||
|
})
|
||||||
|
async teamInfo(
|
||||||
|
@Args({
|
||||||
|
name: 'teamID',
|
||||||
|
type: () => ID,
|
||||||
|
description: 'Team ID for which info to fetch',
|
||||||
|
})
|
||||||
|
teamID: string,
|
||||||
|
): Promise<Team> {
|
||||||
|
const team = await this.adminService.getTeamInfo(teamID);
|
||||||
|
if (E.isLeft(team)) throwErr(team.left);
|
||||||
|
return team.right;
|
||||||
|
}
|
||||||
|
|
||||||
|
@ResolveField(() => Number, {
|
||||||
|
description: 'Return count of all the members in a team',
|
||||||
|
})
|
||||||
|
async membersCountInTeam(
|
||||||
|
@Args({
|
||||||
|
name: 'teamID',
|
||||||
|
type: () => ID,
|
||||||
|
description: 'Team ID for which team members to fetch',
|
||||||
|
nullable: false,
|
||||||
|
})
|
||||||
|
teamID: string,
|
||||||
|
): Promise<number> {
|
||||||
|
const teamMembersCount = await this.adminService.membersCountInTeam(teamID);
|
||||||
|
return teamMembersCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
@ResolveField(() => Number, {
|
||||||
|
description: 'Return count of all the stored collections in a team',
|
||||||
|
})
|
||||||
|
async collectionCountInTeam(
|
||||||
|
@Args({
|
||||||
|
name: 'teamID',
|
||||||
|
type: () => ID,
|
||||||
|
description: 'Team ID for which team members to fetch',
|
||||||
|
})
|
||||||
|
teamID: string,
|
||||||
|
): Promise<number> {
|
||||||
|
const teamCollCount = await this.adminService.collectionCountInTeam(teamID);
|
||||||
|
return teamCollCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
@ResolveField(() => Number, {
|
||||||
|
description: 'Return count of all the stored requests in a team',
|
||||||
|
})
|
||||||
|
async requestCountInTeam(
|
||||||
|
@Args({
|
||||||
|
name: 'teamID',
|
||||||
|
type: () => ID,
|
||||||
|
description: 'Team ID for which team members to fetch',
|
||||||
|
})
|
||||||
|
teamID: string,
|
||||||
|
): Promise<number> {
|
||||||
|
const teamReqCount = await this.adminService.requestCountInTeam(teamID);
|
||||||
|
return teamReqCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
@ResolveField(() => Number, {
|
||||||
|
description: 'Return count of all the stored environments in a team',
|
||||||
|
})
|
||||||
|
async environmentCountInTeam(
|
||||||
|
@Args({
|
||||||
|
name: 'teamID',
|
||||||
|
type: () => ID,
|
||||||
|
description: 'Team ID for which team members to fetch',
|
||||||
|
})
|
||||||
|
teamID: string,
|
||||||
|
): Promise<number> {
|
||||||
|
const envsCount = await this.adminService.environmentCountInTeam(teamID);
|
||||||
|
return envsCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
@ResolveField(() => [TeamInvitation], {
|
||||||
|
description: 'Return all the pending invitations in a team',
|
||||||
|
})
|
||||||
|
async pendingInvitationCountInTeam(
|
||||||
|
@Args({
|
||||||
|
name: 'teamID',
|
||||||
|
type: () => ID,
|
||||||
|
description: 'Team ID for which team members to fetch',
|
||||||
|
})
|
||||||
|
teamID: string,
|
||||||
|
) {
|
||||||
|
const invitations = await this.adminService.pendingInvitationCountInTeam(
|
||||||
|
teamID,
|
||||||
|
);
|
||||||
|
return invitations;
|
||||||
|
}
|
||||||
|
|
||||||
|
@ResolveField(() => Number, {
|
||||||
|
description: 'Return total number of Users in organization',
|
||||||
|
})
|
||||||
|
async usersCount() {
|
||||||
|
return this.adminService.getUsersCount();
|
||||||
|
}
|
||||||
|
|
||||||
|
@ResolveField(() => Number, {
|
||||||
|
description: 'Return total number of Teams in organization',
|
||||||
|
})
|
||||||
|
async teamsCount() {
|
||||||
|
return this.adminService.getTeamsCount();
|
||||||
|
}
|
||||||
|
|
||||||
|
@ResolveField(() => Number, {
|
||||||
|
description: 'Return total number of Team Collections in organization',
|
||||||
|
})
|
||||||
|
async teamCollectionsCount() {
|
||||||
|
return this.adminService.getTeamCollectionsCount();
|
||||||
|
}
|
||||||
|
|
||||||
|
@ResolveField(() => Number, {
|
||||||
|
description: 'Return total number of Team Requests in organization',
|
||||||
|
})
|
||||||
|
async teamRequestsCount() {
|
||||||
|
return this.adminService.getTeamRequestsCount();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -27,6 +27,7 @@ import { UserRequestUserCollectionResolver } from './user-request/resolvers/user
|
|||||||
import { UserEnvsUserResolver } from './user-environment/user.resolver';
|
import { UserEnvsUserResolver } from './user-environment/user.resolver';
|
||||||
import { UserHistoryUserResolver } from './user-history/user.resolver';
|
import { UserHistoryUserResolver } from './user-history/user.resolver';
|
||||||
import { UserSettingsUserResolver } from './user-settings/user.resolver';
|
import { UserSettingsUserResolver } from './user-settings/user.resolver';
|
||||||
|
import { InfraResolver } from './admin/infra.resolver';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* All the resolvers present in the application.
|
* All the resolvers present in the application.
|
||||||
@@ -34,6 +35,7 @@ import { UserSettingsUserResolver } from './user-settings/user.resolver';
|
|||||||
* NOTE: This needs to be KEPT UP-TO-DATE to keep the schema accurate
|
* NOTE: This needs to be KEPT UP-TO-DATE to keep the schema accurate
|
||||||
*/
|
*/
|
||||||
const RESOLVERS = [
|
const RESOLVERS = [
|
||||||
|
InfraResolver,
|
||||||
AdminResolver,
|
AdminResolver,
|
||||||
ShortcodeResolver,
|
ShortcodeResolver,
|
||||||
TeamResolver,
|
TeamResolver,
|
||||||
|
|||||||
7224
pnpm-lock.yaml
generated
7224
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user