浏览代码

feat(server): Implement update of administrator & admin roles

Michael Bromley 7 年之前
父节点
当前提交
4fa3a24115

文件差异内容过多而无法显示
+ 0 - 0
schema.json


+ 2 - 0
server/src/api/administrator/administrator.api.graphql

@@ -6,6 +6,8 @@ type Query {
 type Mutation {
     "Create a new Administrator"
     createAdministrator(input: CreateAdministratorInput!): Administrator!
+    "Update an existing Administrator"
+    updateAdministrator(input: UpdateAdministratorInput!): Administrator!
     "Assign a Role to an Administrator"
     assignRoleToAdministrator(administratorId: ID!, roleId: ID!): Administrator!
 }

+ 20 - 5
server/src/api/administrator/administrator.resolver.ts

@@ -1,5 +1,12 @@
 import { Args, Mutation, Query, Resolver } from '@nestjs/graphql';
-import { Permission } from 'shared/generated-types';
+import {
+    AssignRoleToAdministratorVariables,
+    CreateAdministratorVariables,
+    GetAdministratorsVariables,
+    GetAdministratorVariables,
+    Permission,
+    UpdateAdministratorVariables,
+} from 'shared/generated-types';
 import { PaginatedList } from 'shared/shared-types';
 
 import { Administrator } from '../../entity/administrator/administrator.entity';
@@ -14,29 +21,37 @@ export class AdministratorResolver {
     @Query()
     @Allow(Permission.ReadAdministrator)
     @ApplyIdCodec()
-    administrators(@Args() args: any): Promise<PaginatedList<Administrator>> {
+    administrators(@Args() args: GetAdministratorsVariables): Promise<PaginatedList<Administrator>> {
         return this.administratorService.findAll(args.options);
     }
 
     @Query()
     @Allow(Permission.ReadAdministrator)
     @ApplyIdCodec()
-    administrator(@Args() args: any): Promise<Administrator | undefined> {
+    administrator(@Args() args: GetAdministratorVariables): Promise<Administrator | undefined> {
         return this.administratorService.findOne(args.id);
     }
 
     @Mutation()
     @Allow(Permission.CreateAdministrator)
     @ApplyIdCodec()
-    createAdministrator(_, args): Promise<Administrator> {
+    createAdministrator(@Args() args: CreateAdministratorVariables): Promise<Administrator> {
         const { input } = args;
         return this.administratorService.create(input);
     }
 
+    @Mutation()
+    @Allow(Permission.CreateAdministrator)
+    @ApplyIdCodec()
+    updateAdministrator(@Args() args: UpdateAdministratorVariables): Promise<Administrator> {
+        const { input } = args;
+        return this.administratorService.update(input);
+    }
+
     @Mutation()
     @Allow(Permission.UpdateAdministrator)
     @ApplyIdCodec()
-    assignRoleToAdministrator(@Args() args): Promise<Administrator> {
+    assignRoleToAdministrator(@Args() args: AssignRoleToAdministratorVariables): Promise<Administrator> {
         return this.administratorService.assignRole(args.administratorId, args.roleId);
     }
 }

+ 12 - 2
server/src/entity/administrator/administrator.graphql

@@ -9,8 +9,18 @@ type Administrator implements Node {
 }
 
 input CreateAdministratorInput {
-    firstName: String
-    lastName: String
+    firstName: String!
+    lastName: String!
     emailAddress: String!
     password: String!
+    roleIds: [ID!]!
+}
+
+input UpdateAdministratorInput {
+    id: ID!
+    firstName: String!
+    lastName: String!
+    emailAddress: String!
+    password: String
+    roleIds: [ID!]!
 }

+ 37 - 8
server/src/service/administrator.service.ts

@@ -1,11 +1,11 @@
 import { Injectable } from '@nestjs/common';
 import { InjectConnection } from '@nestjs/typeorm';
+import { CreateAdministratorInput, UpdateAdministratorInput } from 'shared/generated-types';
 import { SUPER_ADMIN_USER_IDENTIFIER, SUPER_ADMIN_USER_PASSWORD } from 'shared/shared-constants';
 import { ID, PaginatedList } from 'shared/shared-types';
 import { Connection } from 'typeorm';
 
 import { ListQueryOptions } from '../common/types/common-types';
-import { CreateAdministratorDto } from '../entity/administrator/administrator.dto';
 import { Administrator } from '../entity/administrator/administrator.entity';
 import { User } from '../entity/user/user.entity';
 import { I18nError } from '../i18n/i18n-error';
@@ -41,18 +41,46 @@ export class AdministratorService {
         });
     }
 
-    async create(createAdministratorDto: CreateAdministratorDto): Promise<Administrator> {
-        const administrator = new Administrator(createAdministratorDto);
+    async create(input: CreateAdministratorInput): Promise<Administrator> {
+        const administrator = new Administrator(input);
 
         const user = new User();
-        user.passwordHash = await this.passwordService.hash(createAdministratorDto.password);
-        user.identifier = createAdministratorDto.emailAddress;
-        user.roles = [];
+        user.passwordHash = await this.passwordService.hash(input.password);
+        user.identifier = input.emailAddress;
 
         const createdUser = await this.connection.manager.save(user);
         administrator.user = createdUser;
 
-        return this.connection.manager.save(administrator);
+        let createdAdministrator = await this.connection.manager.save(administrator);
+        for (const roleId of input.roleIds) {
+            createdAdministrator = await this.assignRole(createdAdministrator.id, roleId);
+        }
+        return createdAdministrator;
+    }
+
+    async update(input: UpdateAdministratorInput): Promise<Administrator> {
+        const administrator = await this.findOne(input.id);
+        if (!administrator) {
+            throw new I18nError(`error.entity-with-id-not-found`, {
+                entityName: 'Administrator',
+                id: input.id,
+            });
+        }
+        administrator.emailAddress = input.emailAddress;
+        administrator.firstName = input.firstName;
+        administrator.lastName = input.lastName;
+        await this.connection.manager.save(administrator);
+
+        if (input.password) {
+            administrator.user.passwordHash = await this.passwordService.hash(input.password);
+        }
+        administrator.user.roles = [];
+        let updatedAdministrator = administrator;
+        await this.connection.manager.save(administrator.user);
+        for (const roleId of input.roleIds) {
+            updatedAdministrator = await this.assignRole(administrator.id, roleId);
+        }
+        return updatedAdministrator;
     }
 
     /**
@@ -87,13 +115,14 @@ export class AdministratorService {
         });
 
         if (!superAdminUser) {
+            const superAdminRole = await this.roleService.getSuperAdminRole();
             const administrator = await this.create({
                 emailAddress: SUPER_ADMIN_USER_IDENTIFIER,
                 password: SUPER_ADMIN_USER_PASSWORD,
                 firstName: 'Super',
                 lastName: 'Admin',
+                roleIds: [superAdminRole.id as string],
             });
-            await this.assignRole(administrator.id, (await this.roleService.getSuperAdminRole()).id);
         }
     }
 }

+ 93 - 2
shared/generated-types.ts

@@ -46,6 +46,45 @@ export interface GetAdministratorsVariables {
 /* tslint:disable */
 // This file was automatically generated and should not be edited.
 
+// ====================================================
+// GraphQL query operation: GetAdministrator
+// ====================================================
+
+export interface GetAdministrator_administrator_user_roles {
+  __typename: "Role";
+  code: string;
+  description: string;
+  permissions: Permission[];
+}
+
+export interface GetAdministrator_administrator_user {
+  __typename: "User";
+  id: string;
+  identifier: string;
+  lastLogin: string | null;
+  roles: GetAdministrator_administrator_user_roles[];
+}
+
+export interface GetAdministrator_administrator {
+  __typename: "Administrator";
+  id: string;
+  firstName: string;
+  lastName: string;
+  emailAddress: string;
+  user: GetAdministrator_administrator_user;
+}
+
+export interface GetAdministrator {
+  administrator: GetAdministrator_administrator | null;
+}
+
+export interface GetAdministratorVariables {
+  id: string;
+}
+
+/* tslint:disable */
+// This file was automatically generated and should not be edited.
+
 // ====================================================
 // GraphQL mutation operation: CreateAdministrator
 // ====================================================
@@ -88,6 +127,48 @@ export interface CreateAdministratorVariables {
 /* tslint:disable */
 // This file was automatically generated and should not be edited.
 
+// ====================================================
+// GraphQL mutation operation: UpdateAdministrator
+// ====================================================
+
+export interface UpdateAdministrator_updateAdministrator_user_roles {
+  __typename: "Role";
+  code: string;
+  description: string;
+  permissions: Permission[];
+}
+
+export interface UpdateAdministrator_updateAdministrator_user {
+  __typename: "User";
+  id: string;
+  identifier: string;
+  lastLogin: string | null;
+  roles: UpdateAdministrator_updateAdministrator_user_roles[];
+}
+
+export interface UpdateAdministrator_updateAdministrator {
+  __typename: "Administrator";
+  id: string;
+  firstName: string;
+  lastName: string;
+  emailAddress: string;
+  user: UpdateAdministrator_updateAdministrator_user;
+}
+
+export interface UpdateAdministrator {
+  /**
+   * Update an existing Administrator
+   */
+  updateAdministrator: UpdateAdministrator_updateAdministrator;
+}
+
+export interface UpdateAdministratorVariables {
+  input: UpdateAdministratorInput;
+}
+
+/* tslint:disable */
+// This file was automatically generated and should not be edited.
+
 // ====================================================
 // GraphQL query operation: GetRoles
 // ====================================================
@@ -1873,10 +1954,11 @@ export interface BooleanOperators {
 }
 
 export interface CreateAdministratorInput {
-  firstName?: string | null;
-  lastName?: string | null;
+  firstName: string;
+  lastName: string;
   emailAddress: string;
   password: string;
+  roleIds: string[];
 }
 
 export interface CreateFacetCustomFieldsInput {
@@ -2073,6 +2155,15 @@ export interface StringOperators {
   contains?: string | null;
 }
 
+export interface UpdateAdministratorInput {
+  id: string;
+  firstName: string;
+  lastName: string;
+  emailAddress: string;
+  password?: string | null;
+  roleIds: string[];
+}
+
 export interface UpdateFacetCustomFieldsInput {
   searchable?: boolean | null;
 }

部分文件因为文件数量过多而无法显示