Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions src/auth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,11 @@ const HAS_PROVIDER_GH = !!process.env.BETTER_AUTH_GITHUB_ID && !!process.env.BET
const HAS_PROVIDER_MSFT = !!process.env.MSAL_CLIENT_ID && !!process.env.MSAL_CLIENT_SECRET;

export const auth = betterAuth({
// baseUrl: set over BETTER_AUTH_URL,
rateLimit: {
window: 10, // time window in seconds
max: 1000 // max requests in the window
},
user: {
additionalFields: {
firstName: { type: 'string', required: true, input: true },
Expand Down
43 changes: 43 additions & 0 deletions src/controllers/documentRoots.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,29 @@ export const findManyFor: RequestHandler<
res.json(documents);
};

export const findMultipleFor: RequestHandler<
{ id: string /** userId */ },
any,
{ documentRootIds: string[]; ignoreMissingRoots?: boolean; type?: string }
> = async (req, res, next) => {
if (!req.params.id) {
throw new HTTP400Error('Missing user id');
}
const canLoad = req.user!.id === req.params.id || hasElevatedAccess(req.user?.role);
if (!canLoad) {
throw new HTTP403Error('Not Authorized');
}
const ids = req.body.documentRootIds;
if (ids.length === 0) {
return res.json([]);
}
const documents = await DocumentRoot.findManyModels(req.params.id, ids, {
ignoreMissingRoots: !!req.body.ignoreMissingRoots,
documentType: req.body.type && (req.body.type as string | undefined)
});
res.json(documents);
};

export const allDocuments: RequestHandler<any, any, any, { rids: string[] }> = async (req, res, next) => {
if (!hasElevatedAccess((req as any).user!.role)) {
throw new HTTP403Error('Not Authorized');
Expand All @@ -57,6 +80,26 @@ export const allDocuments: RequestHandler<any, any, any, { rids: string[] }> = a
res.json(documents);
};

export const multipleDocuments: RequestHandler<
any,
any,
{ documentRootIds: string[]; userId?: string }
> = async (req, res, next) => {
const user = req.user;
if (!hasElevatedAccess(user.role)) {
throw new HTTP403Error('Not Authorized');
}
const ids = req.body.documentRootIds;
if (ids.length === 0) {
return res.json([]);
}
const documents = await Document.allOfDocumentRoots(
{ role: user.role, id: req.body.userId ?? user.id },
ids
);
res.json(documents);
};

export const create: RequestHandler<{ id: string }, any, CreateConfig | undefined> = async (
req,
res,
Expand Down
5 changes: 4 additions & 1 deletion src/models/Document.ts
Original file line number Diff line number Diff line change
Expand Up @@ -266,7 +266,10 @@ function Document(db: PrismaClient['document']) {
return model;
},

async allOfDocumentRoots(actor: User, documentRootIds: string[]): Promise<DbDocument[]> {
async allOfDocumentRoots(
actor: User | { role: Role | string; id: string },
documentRootIds: string[]
): Promise<DbDocument[]> {
if (!hasElevatedAccess(actor.role)) {
throw new HTTP403Error('Not authorized');
}
Expand Down
6 changes: 5 additions & 1 deletion src/routes/authConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ const authConfig: Config = {
userFind: { path: '/users/:id', access: [{ methods: ['GET', 'PUT'], minRole: Role.STUDENT }] },
usersDocumentRoots: {
path: '/users/:id/documentRoots',
access: [{ methods: ['GET'], minRole: Role.STUDENT }]
access: [{ methods: ['GET', 'POST'], minRole: Role.STUDENT }]
},
studentGroups: {
path: '/studentGroups',
Expand All @@ -40,6 +40,10 @@ const authConfig: Config = {
path: '/documents',
access: [{ methods: ['GET', 'PUT', 'POST', 'DELETE'], minRole: Role.STUDENT }]
},
documentsMultiple: {
path: '/documents/multiple',
access: [{ methods: ['POST'], minRole: Role.TEACHER }]
},
documentRoots: {
path: '/documentRoots',
access: [
Expand Down
24 changes: 19 additions & 5 deletions src/routes/router.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,10 @@ import {
update as updateDocumentRoot,
permissions as allPermissions,
findManyFor as findManyDocumentRootsFor,
findMultipleFor as findMultipleDocumentRootsFor,
allDocuments,
destroy as deleteDocumentRoot
destroy as deleteDocumentRoot,
multipleDocuments
} from '../controllers/documentRoots.js';
import {
allowedActions,
Expand All @@ -60,11 +62,18 @@ router.get('/users', allUsers);
router.get('/users/:id', findUser);
router.put('/users/:id', updateUser);
/**
* TODO: remove once [post] /users/:id/documentRoots is established and clients are updated
*
* @optional ?ignoreMissingRoots: boolean
* @optional ?type: string -> filter included documents by provided type
* @requires ?ids: string[]
*/
router.get('/users/:id/documentRoots', findManyDocumentRootsFor);
/**
* a post endpoint to prevent issues with long query strings when requesting
* many document roots for a user
*/
router.post('/users/:id/documentRoots', findMultipleDocumentRootsFor);

router.get('/studentGroups', allStudentGroups);
router.post('/studentGroups', createStudentGroup);
Expand Down Expand Up @@ -93,18 +102,23 @@ router.post('/documentRoots/:id', createDocumentRoot);
router.put('/documentRoots/:id', updateDocumentRoot);
router.delete('/documentRoots/:id', deleteDocumentRoot);
router.get('/documentRoots/:id/permissions', allPermissions);
/**
* TODO: Reactivate once the controller's permissions are updated.
* router.get('/documents', allDocuments);
*/
router.post('/documents', createDocument);

/**
* TODO: remove once /documents/multiple is established and clients are updated
*
* @adminOnly --> handle in controller
* Returns all documents which are linked to the **document roots**.
* @requires ?rids: string[] -> the document root ids
*/
router.get('/documents', allDocuments);
/**
* a post endpoint to prevent issues with long query strings when requesting
* many document roots for a user
* @adminOnly --> handle in controller
* Returns all documents which are linked to the **document roots**.
*/
router.post('/documents/multiple', multipleDocuments);
router.get('/documents/:id', findDocument);
router.put('/documents/:id', updateDocument);
router.put('/documents/:id/linkTo/:parentId', linkDocument);
Expand Down
2 changes: 2 additions & 0 deletions src/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ import { initialize as initializeSocketIo } from './socketIoServer.js';
import http from 'http';
import * as Sentry from '@sentry/node';
import Logger from './utils/logger.js';
import dotenv from 'dotenv';
dotenv.config();

const PORT = process.env.PORT || 3002;

Expand Down