From ab671ccbf7a42137636cf5afe2a6be9324d101fb Mon Sep 17 00:00:00 2001 From: "kasia.oczkowska" Date: Fri, 15 Mar 2024 15:01:53 +0000 Subject: [PATCH] refactor: rewrite useUsers with RQ --- .../backend/src/graphql/queries/get-users.js | 19 --- .../src/graphql/queries/get-users.test.js | 148 ------------------ .../backend/src/graphql/query-resolvers.js | 2 - packages/backend/src/graphql/schema.graphql | 11 -- .../web/src/components/UserList/index.jsx | 28 ++-- packages/web/src/graphql/queries/get-users.js | 23 --- packages/web/src/hooks/useUsers.js | 34 ++-- 7 files changed, 29 insertions(+), 236 deletions(-) delete mode 100644 packages/backend/src/graphql/queries/get-users.js delete mode 100644 packages/backend/src/graphql/queries/get-users.test.js delete mode 100644 packages/web/src/graphql/queries/get-users.js diff --git a/packages/backend/src/graphql/queries/get-users.js b/packages/backend/src/graphql/queries/get-users.js deleted file mode 100644 index 6bff6c29..00000000 --- a/packages/backend/src/graphql/queries/get-users.js +++ /dev/null @@ -1,19 +0,0 @@ -import paginate from '../../helpers/pagination.js'; -import User from '../../models/user.js'; - -const getUsers = async (_parent, params, context) => { - context.currentUser.can('read', 'User'); - - const usersQuery = User.query() - .leftJoinRelated({ - role: true, - }) - .withGraphFetched({ - role: true, - }) - .orderBy('full_name', 'asc'); - - return paginate(usersQuery, params.limit, params.offset); -}; - -export default getUsers; diff --git a/packages/backend/src/graphql/queries/get-users.test.js b/packages/backend/src/graphql/queries/get-users.test.js deleted file mode 100644 index aeb239c3..00000000 --- a/packages/backend/src/graphql/queries/get-users.test.js +++ /dev/null @@ -1,148 +0,0 @@ -import { describe, it, expect, beforeEach } from 'vitest'; -import request from 'supertest'; -import app from '../../app'; -import createAuthTokenByUserId from '../../helpers/create-auth-token-by-user-id'; -import { createRole } from '../../../test/factories/role'; -import { createPermission } from '../../../test/factories/permission'; -import { createUser } from '../../../test/factories/user'; - -describe('graphQL getUsers query', () => { - const query = ` - query { - getUsers(limit: 10, offset: 0) { - pageInfo { - currentPage - totalPages - } - totalCount - edges { - node { - id - fullName - email - role { - id - name - } - } - } - } - } - `; - - describe('and without permissions', () => { - it('should throw not authorized error', async () => { - const userWithoutPermissions = await createUser(); - const token = createAuthTokenByUserId(userWithoutPermissions.id); - - const response = await request(app) - .post('/graphql') - .set('Authorization', token) - .send({ query }) - .expect(200); - - expect(response.body.errors).toBeDefined(); - expect(response.body.errors[0].message).toEqual('Not authorized!'); - }); - }); - - describe('and with correct permissions', () => { - let role, currentUser, anotherUser, token, requestObject; - - beforeEach(async () => { - role = await createRole({ - key: 'sample', - name: 'sample', - }); - - await createPermission({ - action: 'read', - subject: 'User', - roleId: role.id, - }); - - currentUser = await createUser({ - roleId: role.id, - fullName: 'Current User', - }); - - anotherUser = await createUser({ - roleId: role.id, - fullName: 'Another User', - }); - - token = createAuthTokenByUserId(currentUser.id); - requestObject = request(app).post('/graphql').set('Authorization', token); - }); - - it('should return users data', async () => { - const response = await requestObject.send({ query }).expect(200); - - const expectedResponsePayload = { - data: { - getUsers: { - edges: [ - { - node: { - email: anotherUser.email, - fullName: anotherUser.fullName, - id: anotherUser.id, - role: { - id: role.id, - name: role.name, - }, - }, - }, - { - node: { - email: currentUser.email, - fullName: currentUser.fullName, - id: currentUser.id, - role: { - id: role.id, - name: role.name, - }, - }, - }, - ], - pageInfo: { - currentPage: 1, - totalPages: 1, - }, - totalCount: 2, - }, - }, - }; - - expect(response.body).toEqual(expectedResponsePayload); - }); - - it('should not return users data with password', async () => { - const query = ` - query { - getUsers(limit: 10, offset: 0) { - pageInfo { - currentPage - totalPages - } - totalCount - edges { - node { - id - fullName - password - } - } - } - } - `; - - const response = await requestObject.send({ query }).expect(400); - - expect(response.body.errors).toBeDefined(); - expect(response.body.errors[0].message).toEqual( - 'Cannot query field "password" on type "User".' - ); - }); - }); -}); diff --git a/packages/backend/src/graphql/query-resolvers.js b/packages/backend/src/graphql/query-resolvers.js index 74ccedee..4754fc1b 100644 --- a/packages/backend/src/graphql/query-resolvers.js +++ b/packages/backend/src/graphql/query-resolvers.js @@ -10,7 +10,6 @@ import getFlow from './queries/get-flow.js'; import getFlows from './queries/get-flows.js'; import getNotifications from './queries/get-notifications.js'; import getStepWithTestExecutions from './queries/get-step-with-test-executions.js'; -import getUsers from './queries/get-users.js'; import testConnection from './queries/test-connection.js'; const queryResolvers = { @@ -26,7 +25,6 @@ const queryResolvers = { getFlows, getNotifications, getStepWithTestExecutions, - getUsers, testConnection, }; diff --git a/packages/backend/src/graphql/schema.graphql b/packages/backend/src/graphql/schema.graphql index 3e1ab036..0e7c7717 100644 --- a/packages/backend/src/graphql/schema.graphql +++ b/packages/backend/src/graphql/schema.graphql @@ -26,7 +26,6 @@ type Query { getBillingAndUsage: GetBillingAndUsage getConfig(keys: [String]): JSONObject getNotifications: [Notification] - getUsers(limit: Int!, offset: Int!): UserConnection } type Mutation { @@ -304,16 +303,6 @@ type SamlAuthProvidersRoleMapping { remoteRoleName: String } -type UserConnection { - edges: [UserEdge] - pageInfo: PageInfo - totalCount: Int -} - -type UserEdge { - node: User -} - input CreateConnectionInput { key: String! appAuthClientId: String diff --git a/packages/web/src/components/UserList/index.jsx b/packages/web/src/components/UserList/index.jsx index 36767b08..de9eb04a 100644 --- a/packages/web/src/components/UserList/index.jsx +++ b/packages/web/src/components/UserList/index.jsx @@ -19,18 +19,18 @@ import useFormatMessage from 'hooks/useFormatMessage'; import * as URLS from 'config/urls'; import TablePaginationActions from './TablePaginationActions'; import { TablePagination } from './style'; + export default function UserList() { const formatMessage = useFormatMessage(); const [page, setPage] = React.useState(0); - const [rowsPerPage, setRowsPerPage] = React.useState(10); - const { users, pageInfo, totalCount, loading } = useUsers(page, rowsPerPage); + const { data: usersData, isLoading } = useUsers(page + 1); + const users = usersData?.data; + const { count } = usersData?.meta || {}; + const handleChangePage = (event, newPage) => { setPage(newPage); }; - const handleChangeRowsPerPage = (event) => { - setRowsPerPage(+event.target.value); - setPage(0); - }; + return ( <> @@ -68,14 +68,14 @@ export default function UserList() { - {loading && ( + {isLoading && ( )} - {!loading && + {!isLoading && users.map((user) => ( ))} - {totalCount && ( + {!isLoading && typeof count === 'number' && ( diff --git a/packages/web/src/graphql/queries/get-users.js b/packages/web/src/graphql/queries/get-users.js deleted file mode 100644 index e2d8a45f..00000000 --- a/packages/web/src/graphql/queries/get-users.js +++ /dev/null @@ -1,23 +0,0 @@ -import { gql } from '@apollo/client'; -export const GET_USERS = gql` - query GetUsers($limit: Int!, $offset: Int!) { - getUsers(limit: $limit, offset: $offset) { - pageInfo { - currentPage - totalPages - } - totalCount - edges { - node { - id - fullName - email - role { - id - name - } - } - } - } - } -`; diff --git a/packages/web/src/hooks/useUsers.js b/packages/web/src/hooks/useUsers.js index 8b6c9ba2..443d08c9 100644 --- a/packages/web/src/hooks/useUsers.js +++ b/packages/web/src/hooks/useUsers.js @@ -1,20 +1,18 @@ -import { useQuery } from '@apollo/client'; -import { GET_USERS } from 'graphql/queries/get-users'; -const getLimitAndOffset = (page, rowsPerPage) => ({ - limit: rowsPerPage, - offset: page * rowsPerPage, -}); -export default function useUsers(page, rowsPerPage) { - const { data, loading } = useQuery(GET_USERS, { - variables: getLimitAndOffset(page, rowsPerPage), +import { useQuery } from '@tanstack/react-query'; +import api from 'helpers/api'; + +export default function useUsers(page) { + + const query = useQuery({ + queryKey: ['users', page], + queryFn: async ({ signal }) => { + const { data } = await api.get(`/v1/admin/users`, { + signal, + params: { page }, + }); + return data; + }, }); - const users = data?.getUsers.edges.map(({ node }) => node) || []; - const pageInfo = data?.getUsers.pageInfo; - const totalCount = data?.getUsers.totalCount; - return { - users, - pageInfo, - totalCount, - loading, - }; + + return query; }