Merge pull request #2127 from gradido/2116-retrieve-admin-and-moderators

2116 retrieve admin and moderators
This commit is contained in:
Moriz Wahl 2022-08-17 15:20:28 +02:00 committed by GitHub
commit d058b7033b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 121 additions and 2 deletions

View File

@ -31,6 +31,7 @@ export enum RIGHTS {
LIST_ALL_CONTRIBUTIONS = 'LIST_ALL_CONTRIBUTIONS',
UPDATE_CONTRIBUTION = 'UPDATE_CONTRIBUTION',
LIST_CONTRIBUTION_LINKS = 'LIST_CONTRIBUTION_LINKS',
SEARCH_ADMIN_USERS = 'SEARCH_ADMIN_USERS',
// Admin
SEARCH_USERS = 'SEARCH_USERS',
SET_USER_ROLE = 'SET_USER_ROLE',

View File

@ -28,6 +28,7 @@ export const ROLE_USER = new Role('user', [
RIGHTS.LIST_CONTRIBUTIONS,
RIGHTS.LIST_ALL_CONTRIBUTIONS,
RIGHTS.UPDATE_CONTRIBUTION,
RIGHTS.SEARCH_ADMIN_USERS,
RIGHTS.LIST_CONTRIBUTION_LINKS,
])
export const ROLE_ADMIN = new Role('admin', Object.values(RIGHTS)) // all rights

View File

@ -0,0 +1,25 @@
import { User } from '@entity/User'
import { Field, Int, ObjectType } from 'type-graphql'
@ObjectType()
export class AdminUser {
constructor(user: User) {
this.firstName = user.firstName
this.lastName = user.lastName
}
@Field(() => String)
firstName: string
@Field(() => String)
lastName: string
}
@ObjectType()
export class SearchAdminUsersResult {
@Field(() => Int)
userCount: number
@Field(() => [AdminUser])
userList: AdminUser[]
}

View File

@ -5,7 +5,7 @@ import { testEnvironment, headerPushMock, resetToken, cleanDB, resetEntity } fro
import { userFactory } from '@/seeds/factory/user'
import { bibiBloxberg } from '@/seeds/users/bibi-bloxberg'
import { createUser, setPassword, forgotPassword, updateUserInfos } from '@/seeds/graphql/mutations'
import { login, logout, verifyLogin, queryOptIn } from '@/seeds/graphql/queries'
import { login, logout, verifyLogin, queryOptIn, searchAdminUsers } from '@/seeds/graphql/queries'
import { GraphQLError } from 'graphql'
import { LoginEmailOptIn } from '@entity/LoginEmailOptIn'
import { User } from '@entity/User'
@ -21,6 +21,7 @@ import { ContributionLink } from '@model/ContributionLink'
import { logger } from '@test/testSetup'
import { validate as validateUUID, version as versionUUID } from 'uuid'
import { peterLustig } from '@/seeds/users/peter-lustig'
// import { klicktippSignIn } from '@/apis/KlicktippController'
@ -878,6 +879,51 @@ bei Gradidio sei dabei!`,
})
})
})
describe('searchAdminUsers', () => {
describe('unauthenticated', () => {
it('throws an error', async () => {
resetToken()
await expect(mutate({ mutation: searchAdminUsers })).resolves.toEqual(
expect.objectContaining({
errors: [new GraphQLError('401 Unauthorized')],
}),
)
})
})
describe('authenticated', () => {
beforeAll(async () => {
await userFactory(testEnv, bibiBloxberg)
await userFactory(testEnv, peterLustig)
await query({
query: login,
variables: {
email: 'bibi@bloxberg.de',
password: 'Aa12345_',
},
})
})
it('finds peter@lustig.de', async () => {
await expect(mutate({ mutation: searchAdminUsers })).resolves.toEqual(
expect.objectContaining({
data: {
searchAdminUsers: {
userCount: 1,
userList: expect.arrayContaining([
expect.objectContaining({
firstName: 'Peter',
lastName: 'Lustig',
}),
]),
},
},
}),
)
})
})
})
})
describe('printTimeDuration', () => {

View File

@ -3,7 +3,7 @@ import { backendLogger as logger } from '@/server/logger'
import { Context, getUser } from '@/server/context'
import { Resolver, Query, Args, Arg, Authorized, Ctx, UseMiddleware, Mutation } from 'type-graphql'
import { getConnection } from '@dbTools/typeorm'
import { getConnection, getCustomRepository, IsNull, Not } from '@dbTools/typeorm'
import CONFIG from '@/config'
import { User } from '@model/User'
import { User as DbUser } from '@entity/User'
@ -32,6 +32,10 @@ import {
EventSendConfirmationEmail,
} from '@/event/Event'
import { getUserCreation } from './util/creations'
import { UserRepository } from '@/typeorm/repository/User'
import { SearchAdminUsersResult } from '@model/AdminUser'
import Paginated from '@arg/Paginated'
import { Order } from '@enum/Order'
import { v4 as uuidv4 } from 'uuid'
// eslint-disable-next-line @typescript-eslint/no-var-requires
@ -752,6 +756,36 @@ export class UserResolver {
logger.debug(`has ElopageBuys = ${elopageBuys}`)
return elopageBuys
}
@Authorized([RIGHTS.SEARCH_ADMIN_USERS])
@Query(() => SearchAdminUsersResult)
async searchAdminUsers(
@Args()
{ currentPage = 1, pageSize = 25, order = Order.DESC }: Paginated,
): Promise<SearchAdminUsersResult> {
const userRepository = getCustomRepository(UserRepository)
const [users, count] = await userRepository.findAndCount({
where: {
isAdmin: Not(IsNull()),
},
order: {
createdAt: order,
},
skip: (currentPage - 1) * pageSize,
take: pageSize,
})
return {
userCount: count,
userList: users.map((user) => {
return {
firstName: user.firstName,
lastName: user.lastName,
}
}),
}
}
}
const isTimeExpired = (optIn: LoginEmailOptIn, duration: number): boolean => {

View File

@ -280,3 +280,15 @@ export const listContributionLinks = gql`
}
}
`
export const searchAdminUsers = gql`
query {
searchAdminUsers {
userCount
userList {
firstName
lastName
}
}
}
`