diff --git a/src/v1/users/controllers/updateUser.ts b/src/v1/users/controllers/updateUser.ts index beb4833..afa22f2 100644 --- a/src/v1/users/controllers/updateUser.ts +++ b/src/v1/users/controllers/updateUser.ts @@ -2,11 +2,7 @@ import { Hono } from 'hono'; import { z } from 'zod'; import { prisma } from '../../../lib/prisma'; -import { - forbiddenError, - internalServerError, - notFoundError -} from '../../../lib/errorMessages'; +import { forbiddenError, internalServerError, notFoundError } from '../../../lib/errorMessages'; import { validatePermissions } from '../../../lib/util'; import { bodyValidator, idParamValidator } from '../../../lib/validators'; diff --git a/src/v1/users/index.ts b/src/v1/users/index.ts index f591e37..f791bf7 100644 --- a/src/v1/users/index.ts +++ b/src/v1/users/index.ts @@ -15,6 +15,7 @@ export default new Hono() .route('/logout', logoutUser) .route('/current', getCurrentUser) .route('/:id', updateUser) + .route('/:id', deleteUser) .route('/', getAllUsers) .route('/', createUser) .route('/', deleteUser); diff --git a/src/v2/assets/controllers/servers/createServerAsset.ts b/src/v2/assets/controllers/servers/createServerAsset.ts index 25e88c2..c18c202 100644 --- a/src/v2/assets/controllers/servers/createServerAsset.ts +++ b/src/v2/assets/controllers/servers/createServerAsset.ts @@ -63,15 +63,6 @@ export default new Hono().post( select: { model: true } - }, - storage: { - include: { - asset: { - select: { - name: true - } - } - } } } }); diff --git a/src/v2/assets/controllers/servers/getAllServerAssets.ts b/src/v2/assets/controllers/servers/getAllServerAssets.ts index 58478ef..d80180f 100644 --- a/src/v2/assets/controllers/servers/getAllServerAssets.ts +++ b/src/v2/assets/controllers/servers/getAllServerAssets.ts @@ -25,15 +25,6 @@ export default new Hono().get('/', paginationQueryValidator({}), async (c) => { select: { model: true } - }, - storage: { - include: { - asset: { - select: { - name: true - } - } - } } } }), diff --git a/src/v2/assets/controllers/servers/getServerAssetById.ts b/src/v2/assets/controllers/servers/getServerAssetById.ts index 38ae70b..ba2e98e 100644 --- a/src/v2/assets/controllers/servers/getServerAssetById.ts +++ b/src/v2/assets/controllers/servers/getServerAssetById.ts @@ -19,15 +19,6 @@ export default new Hono().get('/', idParamValidator({}), async (c) => { } }, include: { - storage: { - include: { - asset: { - select: { - name: true - } - } - } - }, ...assetInclude } }); diff --git a/src/v2/assets/controllers/servers/updateServerAsset.ts b/src/v2/assets/controllers/servers/updateServerAsset.ts index 93d4439..689688d 100644 --- a/src/v2/assets/controllers/servers/updateServerAsset.ts +++ b/src/v2/assets/controllers/servers/updateServerAsset.ts @@ -92,16 +92,7 @@ export default new Hono().patch( } }, include: { - ...assetInclude, - storage: { - include: { - asset: { - select: { - name: true - } - } - } - } + ...assetInclude } }); diff --git a/src/v2/assets/controllers/storages/createStorageAsset.ts b/src/v2/assets/controllers/storages/createStorageAsset.ts index 1d585a8..577ef7e 100644 --- a/src/v2/assets/controllers/storages/createStorageAsset.ts +++ b/src/v2/assets/controllers/storages/createStorageAsset.ts @@ -67,15 +67,6 @@ export default new Hono().post( select: { size: true } - }, - storage: { - include: { - asset: { - select: { - name: true - } - } - } } } }); diff --git a/src/v2/assets/controllers/storages/getAllStorageAssets.ts b/src/v2/assets/controllers/storages/getAllStorageAssets.ts index 60e9d50..31ff252 100644 --- a/src/v2/assets/controllers/storages/getAllStorageAssets.ts +++ b/src/v2/assets/controllers/storages/getAllStorageAssets.ts @@ -24,15 +24,6 @@ export default new Hono().get('/', paginationQueryValidator({}), async (c) => { select: { size: true } - }, - storage: { - include: { - asset: { - select: { - name: true - } - } - } } } }), diff --git a/src/v2/assets/controllers/storages/getStorageAssetById.ts b/src/v2/assets/controllers/storages/getStorageAssetById.ts index 42b7415..2ee6d3b 100644 --- a/src/v2/assets/controllers/storages/getStorageAssetById.ts +++ b/src/v2/assets/controllers/storages/getStorageAssetById.ts @@ -19,16 +19,12 @@ export default new Hono().get('/', idParamValidator({}), async (c) => { } }, include: { - storage: { - include: { - asset: { - select: { - name: true - } - } + ...assetInclude, + storageType: { + select: { + size: true } - }, - ...assetInclude + } } }); @@ -37,7 +33,15 @@ export default new Hono().get('/', idParamValidator({}), async (c) => { return notFoundError(c); } - return c.json(serializeAsset({ ...storage, jsonPosition: 0 }), 200); + return c.json( + serializeAsset( + { ...storage, jsonPosition: 0 }, + { + size: storage.storageType?.size + } + ), + 200 + ); } catch (err) { return internalServerError(c, err); } diff --git a/src/v2/assets/controllers/storages/updateStorageAssets.ts b/src/v2/assets/controllers/storages/updateStorageAssets.ts index 7b0e817..ebb8c97 100644 --- a/src/v2/assets/controllers/storages/updateStorageAssets.ts +++ b/src/v2/assets/controllers/storages/updateStorageAssets.ts @@ -4,7 +4,7 @@ import { prisma } from '../../../../lib/prisma'; import { internalServerError, notFoundError } from '../../../../lib/errorMessages'; import { assetInclude, serializeAsset } from '../../lib/util'; import { bodyValidator, idParamValidator } from '../../../../lib/validators'; -import { z } from 'zod'; +import { size, z } from 'zod'; export default new Hono().patch( '/', @@ -28,6 +28,11 @@ export default new Hono().patch( .number({ error: 'Group ID must be a number' }) .int({ error: 'Group ID must be an integer' }) .positive({ error: 'Group ID must be greater than 0' }) + .optional(), + size: z + .number({ error: 'Size must be a number' }) + .int({ error: 'Size must be an integer' }) + .positive({ error: 'Size must be greater than 0' }) .optional() }) .refine((data) => Object.keys(data).length > 0, { @@ -49,7 +54,12 @@ export default new Hono().patch( } }, include: { - ...assetInclude + ...assetInclude, + storageType: { + select: { + size: true + } + } } }); @@ -82,23 +92,27 @@ export default new Hono().patch( notes: body.notes ?? existingStorage.notes, storageId: body.storageId ?? existingStorage.storageId, position: body.position ?? existingStorage.position, - groupId: body.groupId ?? existingStorage.groupId - }, - include: { - ...assetInclude, - storage: { - include: { - asset: { - select: { - name: true - } + groupId: body.groupId ?? existingStorage.groupId, + storageType: { + update: { + data: { + size: body.size ?? existingStorage.storageType?.size } } } + }, + include: { + ...assetInclude } }); - return c.json(serializeAsset({ ...updatedStorage, jsonPosition: 0 }), 200); + return c.json( + serializeAsset( + { ...updatedStorage, jsonPosition: 0 }, + { size: existingStorage.storageType?.size } + ), + 200 + ); } catch (err) { return internalServerError(c, err); } diff --git a/src/v2/assets/controllers/ups/createUpsAsset.ts b/src/v2/assets/controllers/ups/createUpsAsset.ts new file mode 100644 index 0000000..4da37fa --- /dev/null +++ b/src/v2/assets/controllers/ups/createUpsAsset.ts @@ -0,0 +1,86 @@ +import { Hono } from 'hono'; +import { z } from 'zod'; + +import { prisma } from '../../../../lib/prisma'; +import { + existingResourceError, + forbiddenError, + internalServerError +} from '../../../../lib/errorMessages'; +import { validatePermissions } from '../../../../lib/util'; +import { assetInclude, buildBaseAssetSchema, serializeAsset } from '../../lib/util'; +import { assetSchema } from '../../lib/validator'; +import { bodyValidator } from '../../../../lib/validators'; + +export default new Hono().post( + '/', + bodyValidator( + assetSchema.extend({ + capacity: z + .number({ error: 'Capacity must be a number' }) + .positive({ error: 'Capacity must be greater than 0' }) + .default(1) + }) + ), + async (c) => { + try { + // Check user permissions + if (!validatePermissions(['asset.create'], c)) { + return forbiddenError(c); + } + + // Get request information + const body = c.req.valid('json'); + + // Try and get the ups asset from the database + const existingUps = await prisma.asset.findFirst({ + where: { + name: body.name, + ups: { + isNot: null + } + }, + select: { + id: true + } + }); + + // Check if a ups exists + if (existingUps) { + return existingResourceError(c); + } + + // Add the new ups to the database + const newUps = await prisma.asset.create({ + data: { + ...buildBaseAssetSchema(body), + ups: { + create: { + capacity: body.capacity + } + } + }, + include: { + ...assetInclude, + ups: { + select: { + capacity: true + } + } + } + }); + + return c.json( + serializeAsset( + { ...newUps, jsonPosition: 0 }, + { + capacity: newUps.ups?.capacity + } + ), + 201 + ); + } catch (err) { + return internalServerError(c, err); + } + } +); diff --git a/src/v2/assets/controllers/ups/getAllUpsAssets.ts b/src/v2/assets/controllers/ups/getAllUpsAssets.ts new file mode 100644 index 0000000..a01edd8 --- /dev/null +++ b/src/v2/assets/controllers/ups/getAllUpsAssets.ts @@ -0,0 +1,54 @@ +import { Hono } from 'hono'; + +import { prisma } from '../../../../lib/prisma'; +import { internalServerError } from '../../../../lib/errorMessages'; +import { assetInclude, serializeAsset } from '../../lib/util'; +import { paginationQueryValidator } from '../../../../lib/validators'; + +export default new Hono().get('/', paginationQueryValidator({}), async (c) => { + try { + // Get information from the request + const { page, limit } = c.req.valid('query'); + + // Get all the storages + const [upses, total] = await prisma.$transaction([ + prisma.asset.findMany({ + where: { + ups: { + isNot: null + } + }, + include: { + ...assetInclude, + ups: { + select: { + capacity: true + } + } + } + }), + + prisma.storage.count() + ]); + + return c.json( + { + upses: upses.map((ups) => ({ + ...serializeAsset( + { ...ups, jsonPosition: 0 }, + { + capacity: ups.ups?.capacity + } + ) + })), + page, + limit, + total, + totalPage: Math.ceil(total / limit) + }, + 200 + ); + } catch (err) { + return internalServerError(c, err); + } +}); diff --git a/src/v2/assets/controllers/ups/getUpsAssetById.ts b/src/v2/assets/controllers/ups/getUpsAssetById.ts new file mode 100644 index 0000000..d9a3ce9 --- /dev/null +++ b/src/v2/assets/controllers/ups/getUpsAssetById.ts @@ -0,0 +1,43 @@ +import { Hono } from 'hono'; + +import { prisma } from '../../../../lib/prisma'; +import { internalServerError, notFoundError } from '../../../../lib/errorMessages'; +import { assetInclude, serializeAsset } from '../../lib/util'; +import { idParamValidator } from '../../../../lib/validators'; + +export default new Hono().get('/', idParamValidator({}), async (c) => { + try { + // Get request information + const { id } = c.req.valid('param'); + + // Try and get the ups from the asset from + const ups = await prisma.asset.findUnique({ + where: { + id, + ups: { + isNot: null + } + }, + include: { + ...assetInclude, + ups: { + select: { + capacity: true + } + } + } + }); + + // Check if the storage exists + if (!ups) { + return notFoundError(c); + } + + return c.json( + serializeAsset({ ...ups, jsonPosition: 0 }, { capacity: ups.ups?.capacity }), + 200 + ); + } catch (err) { + return internalServerError(c, err); + } +}); diff --git a/src/v2/assets/controllers/ups/updateUpsAsset.ts b/src/v2/assets/controllers/ups/updateUpsAsset.ts new file mode 100644 index 0000000..a3c392d --- /dev/null +++ b/src/v2/assets/controllers/ups/updateUpsAsset.ts @@ -0,0 +1,124 @@ +import { Hono } from 'hono'; + +import { prisma } from '../../../../lib/prisma'; +import { internalServerError, notFoundError } from '../../../../lib/errorMessages'; +import { assetInclude, serializeAsset } from '../../lib/util'; +import { bodyValidator, idParamValidator } from '../../../../lib/validators'; +import { z } from 'zod'; + +export default new Hono().patch( + '/', + idParamValidator({}), + bodyValidator( + z + .object({ + name: z.string({ error: 'Name must be a string' }).trim().optional(), + notes: z.string({ error: 'Notes must be a string' }).trim().optional(), + position: z + .number({ error: 'Position must be a number' }) + .int({ error: 'Position must be an integer' }) + .nonnegative({ error: "Position can't be less than zero" }) + .optional(), + storageId: z + .number({ error: 'Storage ID must be a number' }) + .int({ error: 'Storage ID must be an integer' }) + .positive({ error: 'Storage ID must be greater than 0' }) + .optional(), + groupId: z + .number({ error: 'Group ID must be a number' }) + .int({ error: 'Group ID must be an integer' }) + .positive({ error: 'Group ID must be greater than 0' }) + .optional(), + capacity: z + .number({ error: 'Capacity must be a number' }) + .positive({ error: 'Capacity must be greater than 0' }) + .optional() + }) + .refine((data) => Object.keys(data).length > 0, { + error: 'At least one field must be provided' + }) + ), + async (c) => { + try { + // Get request information + const { id } = c.req.valid('param'); + const body = c.req.valid('json'); + + // Try and get the ups from the database + const existingUps = await prisma.asset.findUnique({ + where: { + id, + ups: { + isNot: null + } + }, + include: { + ...assetInclude, + ups: { + select: { + capacity: true + } + } + } + }); + + // Check if the server exists + if (!existingUps) { + return notFoundError(c); + } + + if (body.storageId) { + // Try and get the new storage from the database + const existingStorage = await prisma.storage.findUnique({ + where: { + id: body.storageId + } + }); + + // Check if the storage exists + if (!existingStorage) { + return notFoundError(c); + } + } + + // Update the server in the database + const updatedUps = await prisma.asset.update({ + where: { + id + }, + data: { + name: body.name ?? existingUps.name, + notes: body.notes ?? existingUps.notes, + storageId: body.storageId ?? existingUps.storageId, + position: body.position ?? existingUps.position, + groupId: body.groupId ?? existingUps.groupId, + ups: { + update: { + data: { + capacity: body.capacity ?? existingUps.ups?.capacity + } + } + } + }, + include: { + ...assetInclude, + ups: { + select: { + capacity: true + } + } + } + }); + + return c.json( + serializeAsset( + { ...updatedUps, jsonPosition: 0 }, + { capacity: updatedUps.ups?.capacity } + ), + 200 + ); + } catch (err) { + return internalServerError(c, err); + } + } +); diff --git a/src/v2/assets/index.ts b/src/v2/assets/index.ts index bb08160..c8362bb 100644 --- a/src/v2/assets/index.ts +++ b/src/v2/assets/index.ts @@ -23,6 +23,10 @@ import updateStorageAssets from './controllers/storages/updateStorageAssets'; import updateAsset from './controllers/updateAsset'; import createAsset from './controllers/createAsset'; import removeTagsFromAsset from './controllers/tags/removeTagsFromAsset'; +import getUpsAssetById from './controllers/ups/getUpsAssetById'; +import updateUpsAsset from './controllers/ups/updateUpsAsset'; +import createUpsAsset from './controllers/ups/createUpsAsset'; +import getAllUpsAssets from './controllers/ups/getAllUpsAssets'; export default new Hono() .route('/search', searchAssets) @@ -37,6 +41,11 @@ export default new Hono() .route('/storages', createStorageAsset) .route('/storages', getAllStorageAssets) + .route('/ups/:id', getUpsAssetById) + .route('/ups/:id', updateUpsAsset) + .route('/ups', createUpsAsset) + .route('/ups', getAllUpsAssets) + .route('/:id/paths/:pathId', deleteAssetPath) .route('/:id/paths', addPathToAsset) .route('/:id/paths', getAssetPaths) diff --git a/src/v2/assets/lib/util.ts b/src/v2/assets/lib/util.ts index fad9daf..c4acf3c 100644 --- a/src/v2/assets/lib/util.ts +++ b/src/v2/assets/lib/util.ts @@ -107,6 +107,15 @@ const assetInclude = { rawJson: true } }, + storage: { + include: { + asset: { + select: { + name: true + } + } + } + }, _count: { select: { json: true diff --git a/src/v2/users/index.ts b/src/v2/users/index.ts index f591e37..f791bf7 100644 --- a/src/v2/users/index.ts +++ b/src/v2/users/index.ts @@ -15,6 +15,7 @@ export default new Hono() .route('/logout', logoutUser) .route('/current', getCurrentUser) .route('/:id', updateUser) + .route('/:id', deleteUser) .route('/', getAllUsers) .route('/', createUser) .route('/', deleteUser);