-
);
}
diff --git a/app/routes/_layout+/locations.new.tsx b/app/routes/_layout+/locations.new.tsx
index 8c5ffd209..22e9bdd5b 100644
--- a/app/routes/_layout+/locations.new.tsx
+++ b/app/routes/_layout+/locations.new.tsx
@@ -134,11 +134,11 @@ export default function NewLocationPage() {
const title = useAtomValue(dynamicTitleAtom);
return (
- <>
+
);
}
diff --git a/app/routes/_layout+/settings.custom-fields.$fieldId_.edit.tsx b/app/routes/_layout+/settings.custom-fields.$fieldId_.edit.tsx
index d5868f61b..44a80b7db 100644
--- a/app/routes/_layout+/settings.custom-fields.$fieldId_.edit.tsx
+++ b/app/routes/_layout+/settings.custom-fields.$fieldId_.edit.tsx
@@ -129,6 +129,7 @@ export async function action({ context, request, params }: ActionFunctionArgs) {
required,
options,
categories,
+ organizationId,
});
sendNotification({
diff --git a/app/routes/_layout+/settings.general.tsx b/app/routes/_layout+/settings.general.tsx
index 68118d424..8ac0d7f65 100644
--- a/app/routes/_layout+/settings.general.tsx
+++ b/app/routes/_layout+/settings.general.tsx
@@ -175,6 +175,15 @@ export async function action({ context, request }: ActionFunctionArgs) {
baseUserGroupId,
} = payload;
+ /** User is allowed to edit his/her current organization only not other organizations. */
+ if (currentOrganization.id !== id) {
+ throw new ShelfError({
+ cause: null,
+ message: "You are not allowed to edit this organization.",
+ label: "Organization",
+ });
+ }
+
const formDataFile = await unstable_parseMultipartFormData(
request,
unstable_createMemoryUploadHandler({ maxPartSize: MAX_SIZE })
diff --git a/app/routes/_layout+/settings.team.nrm.$nrmId.edit.tsx b/app/routes/_layout+/settings.team.nrm.$nrmId.edit.tsx
index 0c7c93b87..aeae25474 100644
--- a/app/routes/_layout+/settings.team.nrm.$nrmId.edit.tsx
+++ b/app/routes/_layout+/settings.team.nrm.$nrmId.edit.tsx
@@ -35,14 +35,14 @@ export async function loader({ context, request, params }: LoaderFunctionArgs) {
});
try {
- await requirePermission({
+ const { organizationId } = await requirePermission({
userId,
request,
entity: PermissionEntity.teamMember,
action: PermissionAction.update,
});
- const teamMember = await getTeamMember({ id: nrmId });
+ const teamMember = await getTeamMember({ id: nrmId, organizationId });
return json(data({ showModal: true, teamMember }));
} catch (cause) {
@@ -60,7 +60,7 @@ export async function action({ context, request, params }: ActionFunctionArgs) {
});
try {
- await requirePermission({
+ const { organizationId } = await requirePermission({
userId,
request,
entity: PermissionEntity.teamMember,
@@ -70,7 +70,7 @@ export async function action({ context, request, params }: ActionFunctionArgs) {
const { name } = parseData(await request.formData(), NewOrEditMemberSchema);
await db.teamMember.update({
- where: { id: nrmId },
+ where: { id: nrmId, organizationId },
data: { name: name.trim() },
});
diff --git a/app/routes/_layout+/settings.team.nrm.tsx b/app/routes/_layout+/settings.team.nrm.tsx
index 630d21798..caad7a8dd 100644
--- a/app/routes/_layout+/settings.team.nrm.tsx
+++ b/app/routes/_layout+/settings.team.nrm.tsx
@@ -136,6 +136,7 @@ export async function action({ context, request }: ActionFunctionArgs) {
.update({
where: {
id: teamMemberId,
+ organizationId,
},
data: {
deletedAt: new Date(),
diff --git a/app/routes/api+/asset.refresh-main-image.ts b/app/routes/api+/asset.refresh-main-image.ts
index 6c3908b97..bccc591a2 100644
--- a/app/routes/api+/asset.refresh-main-image.ts
+++ b/app/routes/api+/asset.refresh-main-image.ts
@@ -16,6 +16,8 @@ export async function action({ context, request }: ActionFunctionArgs) {
const { userId } = authSession;
try {
+ // This is kind of a special case. Even tho we are editing the asset by updating the image
+ // we should still use "read" permission because we need base and self-service users to be able to see the images
const { organizationId } = await requirePermission({
userId,
request,
diff --git a/app/routes/api+/kit.refresh-image.ts b/app/routes/api+/kit.refresh-image.ts
index 8540addb8..b4851b952 100644
--- a/app/routes/api+/kit.refresh-image.ts
+++ b/app/routes/api+/kit.refresh-image.ts
@@ -4,6 +4,11 @@ import { updateKit } from "~/modules/kit/service.server";
import { makeShelfError, ShelfError } from "~/utils/error";
import { data, error, parseData } from "~/utils/http.server";
import { oneDayFromNow } from "~/utils/one-week-from-now";
+import {
+ PermissionAction,
+ PermissionEntity,
+} from "~/utils/permissions/permission.data";
+import { requirePermission } from "~/utils/roles.server";
import { createSignedUrl } from "~/utils/storage.server";
export async function action({ context, request }: ActionFunctionArgs) {
@@ -11,6 +16,15 @@ export async function action({ context, request }: ActionFunctionArgs) {
const { userId } = authSession;
try {
+ // This is kind of a special case. Even tho we are editing the kit by updating the image
+ // we should still use "read" permission because we need base and self-service users to be able to see the images
+ const { organizationId } = await requirePermission({
+ userId,
+ request,
+ entity: PermissionEntity.kit,
+ action: PermissionAction.read,
+ });
+
const { kitId, image } = parseData(
await request.formData(),
z.object({
@@ -42,6 +56,7 @@ export async function action({ context, request }: ActionFunctionArgs) {
image: signedUrl,
imageExpiration: oneDayFromNow(),
createdById: userId,
+ organizationId,
});
return json(data({ kit }));
diff --git a/app/utils/import.server.ts b/app/utils/import.server.ts
index 2656db69e..3fe65f253 100644
--- a/app/utils/import.server.ts
+++ b/app/utils/import.server.ts
@@ -47,6 +47,8 @@ export function extractCSVDataFromContentImport
(
case "imageUrl":
// Return empty string if URL is empty/undefined, otherwise trim
return [keys[index], value?.trim() || ""];
+ case "bookable":
+ return [keys[index], !value ? null : value];
default:
return [keys[index], value];
}
diff --git a/app/utils/permissions/permission.data.ts b/app/utils/permissions/permission.data.ts
index 03c978446..11867d2f6 100644
--- a/app/utils/permissions/permission.data.ts
+++ b/app/utils/permissions/permission.data.ts
@@ -49,7 +49,7 @@ export const Role2PermissionMap: {
PermissionAction.delete, // This is for the user to delete their own bookings only when they are draft.
PermissionAction.manageAssets,
],
- [PermissionEntity.qr]: [],
+ [PermissionEntity.qr]: [PermissionAction.read],
[PermissionEntity.category]: [],
[PermissionEntity.customField]: [],
[PermissionEntity.location]: [],
@@ -79,7 +79,7 @@ export const Role2PermissionMap: {
PermissionAction.manageAssets,
PermissionAction.cancel,
],
- [PermissionEntity.qr]: [],
+ [PermissionEntity.qr]: [PermissionAction.read],
[PermissionEntity.category]: [],
[PermissionEntity.customField]: [],
[PermissionEntity.location]: [],
diff --git a/package-lock.json b/package-lock.json
index 305744f4f..e43a78486 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -135,7 +135,7 @@
"tsconfig-paths": "^4.2.0",
"tsx": "^4.7.1",
"typescript": "^5.1.0",
- "vite": "^5.4.6",
+ "vite": "^5.4.14",
"vite-plugin-cjs-interop": "^2.1.0",
"vite-tsconfig-paths": "^4.3.2",
"vitest": "^2.1.4"
@@ -15459,9 +15459,10 @@
}
},
"node_modules/miniflare/node_modules/undici": {
- "version": "5.28.4",
- "resolved": "https://registry.npmjs.org/undici/-/undici-5.28.4.tgz",
- "integrity": "sha512-72RFADWFqKmUb2hmmvNODKL3p9hcB6Gt2DOQMis1SEBaV6a4MH8soBvzg+95CYhCKPFedut2JY9bMfrDl9D23g==",
+ "version": "5.28.5",
+ "resolved": "https://registry.npmjs.org/undici/-/undici-5.28.5.tgz",
+ "integrity": "sha512-zICwjrDrcrUE0pyyJc1I2QzBkLM8FINsgOrt6WjA+BgajVq9Nxu2PbFFXUrAggLfDXlZGZBVZYw7WNV5KiBiBA==",
+ "license": "MIT",
"dependencies": {
"@fastify/busboy": "^2.0.0"
},
@@ -20979,9 +20980,10 @@
}
},
"node_modules/undici": {
- "version": "6.20.1",
- "resolved": "https://registry.npmjs.org/undici/-/undici-6.20.1.tgz",
- "integrity": "sha512-AjQF1QsmqfJys+LXfGTNum+qw4S88CojRInG/6t31W/1fk6G59s92bnAvGz5Cmur+kQv2SURXEvvudLmbrE8QA==",
+ "version": "6.21.1",
+ "resolved": "https://registry.npmjs.org/undici/-/undici-6.21.1.tgz",
+ "integrity": "sha512-q/1rj5D0/zayJB2FraXdaWxbhWiNKDvu8naDT2dl1yTlvJp4BLtOcp2a5BvgGNQpYYJzau7tf1WgKv3b+7mqpQ==",
+ "license": "MIT",
"engines": {
"node": ">=18.17"
}
@@ -21424,9 +21426,10 @@
}
},
"node_modules/vite": {
- "version": "5.4.10",
- "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.10.tgz",
- "integrity": "sha512-1hvaPshuPUtxeQ0hsVH3Mud0ZanOLwVTneA1EgbAM5LhaZEqyPWGRQ7BtaMvUrTDeEaC8pxtj6a6jku3x4z6SQ==",
+ "version": "5.4.14",
+ "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.14.tgz",
+ "integrity": "sha512-EK5cY7Q1D8JNhSaPKVK4pwBFvaTmZxEnoKXLG/U9gmdDcihQGNzFlgIvaxezFR4glP1LsuiedwMBqCXH3wZccA==",
+ "license": "MIT",
"dependencies": {
"esbuild": "^0.21.3",
"postcss": "^8.4.43",
diff --git a/package.json b/package.json
index 72bd396a8..4f5df507e 100644
--- a/package.json
+++ b/package.json
@@ -169,7 +169,7 @@
"tsconfig-paths": "^4.2.0",
"tsx": "^4.7.1",
"typescript": "^5.1.0",
- "vite": "^5.4.6",
+ "vite": "^5.4.14",
"vite-plugin-cjs-interop": "^2.1.0",
"vite-tsconfig-paths": "^4.3.2",
"vitest": "^2.1.4"