Merge pull request #1592 from automatisch/rest-api-get-user

feat: Implement api/v1/users/:userId API endpoint
This commit is contained in:
Ömer Faruk Aydın
2024-02-13 12:14:37 +01:00
committed by GitHub
7 changed files with 107 additions and 3 deletions

View File

@@ -3,7 +3,7 @@ import request from 'supertest';
import app from '../../../../app.js';
import createAuthTokenByUserId from '../../../../helpers/create-auth-token-by-user-id';
import { createUser } from '../../../../../test/factories/user';
import userPayload from '../../../../../test/payloads/user';
import currentUserPayload from '../../../../../test/payloads/current-user.js';
describe('GET /api/v1/users/me', () => {
let role, currentUser, token;
@@ -20,7 +20,7 @@ describe('GET /api/v1/users/me', () => {
.set('Authorization', token)
.expect(200);
const expectedPayload = userPayload(currentUser, role);
const expectedPayload = currentUserPayload(currentUser, role);
expect(response.body).toEqual(expectedPayload);
});
});

View File

@@ -0,0 +1,16 @@
import { renderObject } from '../../../../helpers/renderer.js';
import User from '../../../../models/user.js';
export default async (request, response) => {
const user = await User.query()
.leftJoinRelated({
role: true,
})
.withGraphFetched({
role: true,
})
.findById(request.params.userId)
.throwIfNotFound();
renderObject(response, user);
};

View File

@@ -0,0 +1,36 @@
import { describe, it, expect, beforeEach } from 'vitest';
import request from 'supertest';
import app from '../../../../app.js';
import createAuthTokenByUserId from '../../../../helpers/create-auth-token-by-user-id';
import { createUser } from '../../../../../test/factories/user';
import { createPermission } from '../../../../../test/factories/permission';
import userPayload from '../../../../../test/payloads/user.js';
describe('GET /api/v1/users/:userId', () => {
let currentUser, currentUserRole, anotherUser, anotherUserRole, token;
beforeEach(async () => {
currentUser = await createUser();
anotherUser = await createUser();
currentUserRole = await currentUser.$relatedQuery('role');
anotherUserRole = await anotherUser.$relatedQuery('role');
await createPermission({
roleId: currentUserRole.id,
action: 'read',
subject: 'User',
});
token = createAuthTokenByUserId(currentUser.id);
});
it('should return specified user info', async () => {
const response = await request(app)
.get(`/api/v1/users/${anotherUser.id}`)
.set('Authorization', token)
.expect(200);
const expectedPayload = userPayload(anotherUser, anotherUserRole);
expect(response.body).toEqual(expectedPayload);
});
});

View File

@@ -0,0 +1,18 @@
const authorizationList = {
'/api/v1/users/:userId': {
action: 'read',
subject: 'User',
},
};
export const authorizeUser = async (request, response, next) => {
const currentRoute = request.baseUrl + request.route.path;
const currentRouteRule = authorizationList[currentRoute];
try {
request.currentUser.can(currentRouteRule.action, currentRouteRule.subject);
next();
} catch (error) {
return response.status(403).end();
}
};

View File

@@ -1,9 +1,12 @@
import { Router } from 'express';
import { authenticateUser } from '../../../helpers/authentication.js';
import { authorizeUser } from '../../../helpers/authorization.js';
import getCurrentUserAction from '../../../controllers/api/v1/users/get-current-user.js';
import getUserAction from '../../../controllers/api/v1/users/get-user.js';
const router = Router();
router.get('/me', authenticateUser, getCurrentUserAction);
router.get('/:userId', authenticateUser, authorizeUser, getUserAction);
export default router;

View File

@@ -0,0 +1,32 @@
const currentUserPayload = (currentUser, role) => {
return {
data: {
createdAt: currentUser.createdAt.toISOString(),
email: currentUser.email,
fullName: currentUser.fullName,
id: currentUser.id,
permissions: [],
role: {
createdAt: role.createdAt.toISOString(),
description: null,
id: role.id,
isAdmin: role.isAdmin,
key: role.key,
name: role.name,
updatedAt: role.updatedAt.toISOString(),
},
roleId: role.id,
trialExpiryDate: currentUser.trialExpiryDate.toISOString(),
updatedAt: currentUser.updatedAt.toISOString(),
},
meta: {
count: 1,
currentPage: null,
isArray: false,
totalPages: null,
type: 'User',
},
};
};
export default currentUserPayload;

View File

@@ -5,7 +5,6 @@ const userPayload = (currentUser, role) => {
email: currentUser.email,
fullName: currentUser.fullName,
id: currentUser.id,
permissions: [],
role: {
createdAt: role.createdAt.toISOString(),
description: null,