Skip to content

Commit

Permalink
feat: implemented bucket & bucket-file http controller
Browse files Browse the repository at this point in the history
  • Loading branch information
tada5hi committed Feb 21, 2024
1 parent 59f8e51 commit 1a5beff
Show file tree
Hide file tree
Showing 22 changed files with 799 additions and 7 deletions.
9 changes: 8 additions & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions packages/core/src/domains/permission/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@ import { PermissionName as AuthPermissionName } from '@authup/core';
export enum PermissionKey {
ADMIN_UI_USE = 'admin_ui_use',

BUCKET_ADD = 'bucket_add',
BUCKET_EDIT = 'bucket_edit',
BUCKET_DROP = 'bucket_drop',

PROJECT_ADD = 'proposal_add',
PROJECT_DROP = 'proposal_drop',
PROJECT_EDIT = 'proposal_edit',
Expand Down
2 changes: 2 additions & 0 deletions packages/server-storage/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
"@authup/server-adapter": "^1.0.0-beta.4",
"@ebec/http": "^2.3.0",
"@privateaim/core": "^0.1.0",
"@routup/basic": "^1.3.1",
"@routup/decorators": "^3.3.1",
"@types/busboy": "^1.5.3",
"busboy": "^1.6.0",
"dotenv": "^16.4.4",
Expand Down
4 changes: 4 additions & 0 deletions packages/server-storage/src/core/redis/module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@ export function useRedis() {
return singleton.use();
}

export function hasRedis() {
return singleton.has() || singleton.hasFactory();
}

export function setRedisFactory(factory: Factory<Client>) {
return singleton.setFactory(factory);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
/*
* Copyright (c) 2022-2024.
* Author Peter Placzek (tada5hi)
* For the full copyright and license information,
* view the LICENSE file that was distributed with this source code.
*/

import { PermissionID } from '@privateaim/core';
import { ForbiddenError, NotFoundError } from '@ebec/http';
import { isRealmResourceWritable } from '@authup/core';
import type { Request, Response } from 'routup';
import { sendAccepted, useRequestParam } from 'routup';
import { useDataSource } from 'typeorm-extension';
import { BucketFileEntity } from '../../../../domains';
import { useRequestEnv } from '../../../request';

export async function executeBucketFileRouteDeleteHandler(req: Request, res: Response) : Promise<any> {
const id = useRequestParam(req, 'id');

const ability = useRequestEnv(req, 'ability');
if (!ability.has(PermissionID.BUCKET_DROP)) {
throw new ForbiddenError();
}

const dataSource = await useDataSource();
const repository = dataSource.getRepository(BucketFileEntity);
const entity = await repository.findOneBy({ id });

if (!entity) {
throw new NotFoundError();
}

if (!isRealmResourceWritable(useRequestEnv(req, 'realm'), entity.realm_id)) {
throw new ForbiddenError();
}

const { id: entityId } = entity;

await repository.remove(entity);

entity.id = entityId;

return sendAccepted(res, entity);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
/*
* Copyright (c) 2022-2024.
* Author Peter Placzek (tada5hi)
* For the full copyright and license information,
* view the LICENSE file that was distributed with this source code.
*/

export * from './delete';
export * from './read';
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
/*
* Copyright (c) 2024.
* Author Peter Placzek (tada5hi)
* For the full copyright and license information,
* view the LICENSE file that was distributed with this source code.
*/

import { useRequestQuery } from '@routup/basic/query';
import type { Request, Response } from 'routup';
import { send, useRequestParam } from 'routup';
import {
applyQuery,
useDataSource,
} from 'typeorm-extension';
import { NotFoundError } from '@ebec/http';
import { BucketFileEntity } from '../../../../domains';

export async function executeBucketFileRouteGetOneHandler(req: Request, res: Response) : Promise<any> {
const id = useRequestParam(req, 'id');

const dataSource = await useDataSource();
const repository = dataSource.getRepository(BucketFileEntity);
const query = repository.createQueryBuilder('bucket')
.where('bucketFile.id = :id', { id });

applyQuery(query, useRequestQuery(req), {
defaultAlias: 'bucketFile',
fields: {
default: [
'id',
'name',
'directory',
'size',
'hash',
'created_at',
'updated_at',
'realm_id',
'robot_id',
'user_id',
],
},
relations: {
allowed: ['bucket'],
},
});

const entity = await query.getOne();

if (!entity) {
throw new NotFoundError();
}

return send(res, entity);
}

export async function executeBucketFileRouteGetManyHandler(req: Request, res: Response) : Promise<any> {
const dataSource = await useDataSource();

const repository = dataSource.getRepository(BucketFileEntity);
const query = repository.createQueryBuilder('bucket');

const { pagination } = applyQuery(query, useRequestQuery(req), {
defaultAlias: 'bucket',
fields: {
default: [
'id',
'name',
'directory',
'size',
'hash',
'created_at',
'updated_at',
'realm_id',
'robot_id',
'user_id',
],
},
relations: {
allowed: ['bucket'],
},
filters: {
allowed: ['id', 'name', 'directory', 'realm_id', 'user_id', 'robot_id'],
},
pagination: {
maxLimit: 50,
},
sort: {
allowed: ['id', 'directory', 'name', 'updated_at', 'created_at'],
},
});

const [entities, total] = await query.getManyAndCount();

return send(res, {
data: entities,
meta: {
total,
...pagination,
},
});
}
49 changes: 49 additions & 0 deletions packages/server-storage/src/http/controllers/bucket-file/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/*
* Copyright (c) 2024.
* Author Peter Placzek (tada5hi)
* For the full copyright and license information,
* view the LICENSE file that was distributed with this source code.
*/

import {
DController, DDelete, DGet, DPath, DRequest, DResponse, DTags,
} from '@routup/decorators';
import type { BucketFileEntity } from '../../../domains';
import { ForceLoggedInMiddleware } from '../../middlewares';
import {
executeBucketFileRouteDeleteHandler,
executeBucketFileRouteGetManyHandler,
executeBucketFileRouteGetOneHandler,
} from './handlers';

type PartialBucketFile = Partial<BucketFileEntity>;

@DTags('buckets')
@DController('/bucket-files')
export class BucketFileController {
@DGet('', [ForceLoggedInMiddleware])
async getMany(
@DRequest() req: any,
@DResponse() res: any,
): Promise<PartialBucketFile[]> {
return await executeBucketFileRouteGetManyHandler(req, res) as PartialBucketFile[];
}

@DGet('/:id', [ForceLoggedInMiddleware])
async getOne(
@DPath('id') id: string,
@DRequest() req: any,
@DResponse() res: any,
): Promise<PartialBucketFile | undefined> {
return await executeBucketFileRouteGetOneHandler(req, res) as PartialBucketFile | undefined;
}

@DDelete('/:id', [ForceLoggedInMiddleware])
async drop(
@DPath('id') id: string,
@DRequest() req: any,
@DResponse() res: any,
): Promise<PartialBucketFile | undefined> {
return await executeBucketFileRouteDeleteHandler(req, res) as PartialBucketFile | undefined;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/*
* Copyright (c) 2022-2024.
* Author Peter Placzek (tada5hi)
* For the full copyright and license information,
* view the LICENSE file that was distributed with this source code.
*/

import { PermissionID } from '@privateaim/core';
import { ForbiddenError } from '@ebec/http';
import type { Request, Response } from 'routup';
import { sendCreated } from 'routup';
import { useDataSource } from 'typeorm-extension';
import { useRequestEnv } from '../../../request';
import { BucketEntity } from '../../../../domains';
import { runProjectValidation } from '../utils/validation';

export async function executeBucketRouteCreateHandler(req: Request, res: Response) : Promise<any> {
const ability = useRequestEnv(req, 'ability');
if (!ability.has(PermissionID.BUCKET_ADD)) {
throw new ForbiddenError();
}

const result = await runProjectValidation(req, 'create');

const dataSource = await useDataSource();
const repository = dataSource.getRepository(BucketEntity);
const entity = repository.create({
user_id: useRequestEnv(req, 'userId'),
robot_id: useRequestEnv(req, 'robotId'),
...result.data,
});

await repository.save(entity);

return sendCreated(res, entity);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
/*
* Copyright (c) 2022-2024.
* Author Peter Placzek (tada5hi)
* For the full copyright and license information,
* view the LICENSE file that was distributed with this source code.
*/

import { PermissionID } from '@privateaim/core';
import { BadRequestError, ForbiddenError, NotFoundError } from '@ebec/http';
import { isRealmResourceWritable } from '@authup/core';
import type { Request, Response } from 'routup';
import { sendAccepted, useRequestParam } from 'routup';
import { useDataSource } from 'typeorm-extension';
import { BucketEntity } from '../../../../domains';
import { useRequestEnv } from '../../../request';

export async function executeBucketRouteDeleteHandler(req: Request, res: Response) : Promise<any> {
const id = useRequestParam(req, 'id');

const ability = useRequestEnv(req, 'ability');
if (!ability.has(PermissionID.BUCKET_DROP)) {
throw new ForbiddenError();
}

const dataSource = await useDataSource();
const repository = dataSource.getRepository(BucketEntity);
const entity = await repository.findOneBy({ id });

if (!entity) {
throw new NotFoundError();
}

if (!isRealmResourceWritable(useRequestEnv(req, 'realm'), entity.realm_id)) {
throw new ForbiddenError();
}

const { id: entityId } = entity;

await repository.remove(entity);

entity.id = entityId;

return sendAccepted(res, entity);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
/*
* Copyright (c) 2022-2024.
* Author Peter Placzek (tada5hi)
* For the full copyright and license information,
* view the LICENSE file that was distributed with this source code.
*/

export * from './create';
export * from './delete';
export * from './read';
export * from './update';
Loading

0 comments on commit 1a5beff

Please sign in to comment.