menu
diff --git a/app/src/stores/vrSpaceStore.ts b/app/src/stores/vrSpaceStore.ts
index 50569ebb..7306798c 100644
--- a/app/src/stores/vrSpaceStore.ts
+++ b/app/src/stores/vrSpaceStore.ts
@@ -129,6 +129,14 @@ export const useVrSpaceStore = defineStore('vrSpace', () => {
return vrSpaceId;
}
+ async function transferVrSpaceOwnership(fromUserId: string, toUserId: string) {
+ await connection.client.vr.transferVrSpaceOwnership.mutate({ fromUserId, toUserId });
+ }
+
+ async function doesUserHaveVrSpaces(userId: string) {
+ return await connection.client.vr.doesUserHaveVrSpaces.mutate({ userId });
+ }
+
async function deleteVrSpace(vrSpaceId?: VrSpaceId) {
if (!vrSpaceId) vrSpaceId = currentVrSpace.value?.dbData.vrSpaceId;
if (!vrSpaceId) {
@@ -237,6 +245,8 @@ export const useVrSpaceStore = defineStore('vrSpace', () => {
navMeshUrl,
worldModelScaleString,
panoramicPreviewUrl,
+ doesUserHaveVrSpaces,
+ transferVrSpaceOwnership,
createVrSpace,
deleteVrSpace,
enterVrSpace,
diff --git a/app/src/views/admin/AdminUserManagerView.vue b/app/src/views/admin/AdminUserManagerView.vue
index 10fd4dbc..69e90652 100644
--- a/app/src/views/admin/AdminUserManagerView.vue
+++ b/app/src/views/admin/AdminUserManagerView.vue
@@ -8,7 +8,7 @@
Skapa ny användare
-
+
+
diff --git a/backend/mediaserver/src/routers/vrRouter.ts b/backend/mediaserver/src/routers/vrRouter.ts
index 697839a8..a28358b5 100644
--- a/backend/mediaserver/src/routers/vrRouter.ts
+++ b/backend/mediaserver/src/routers/vrRouter.ts
@@ -89,6 +89,60 @@ export const vrRouter = router({
ctx.client.leaveCurrentVrSpace();
// ctx.vrSpace.removeClient(ctx.client);
}),
+ transferVrSpaceOwnership: atLeastUserP.input(z.object({
+ fromUserId: z.string(),
+ toUserId: z.string(),
+ })).mutation(async ({ ctx, input }) => {
+ if (!hasAtLeastSecurityRole(ctx.role, 'admin')) {
+ throw new TRPCError({ code: 'UNAUTHORIZED', message: 'Admin rights required' });
+ }
+ const { fromUserId, toUserId } = input;
+
+ log.info(`Transferring VR spaces from ${fromUserId} to ${toUserId}`);
+
+ const result = await db
+ .update(schema.vrSpaces)
+ .set({ ownerUserId: toUserId })
+ .where(eq(schema.vrSpaces.ownerUserId, fromUserId))
+ .returning({
+ vrSpaceId: schema.vrSpaces.vrSpaceId,
+ name: schema.vrSpaces.name
+ });
+
+ log.info(`Transferred ${result.length} VR spaces`);
+
+ for (const space of result) {
+ const vrSpace = VrSpace.getVrSpace(space.vrSpaceId);
+ if (vrSpace) {
+ vrSpace.reloadDbData('ownership transferred');
+ }
+ }
+
+ return {
+ transferredCount: result.length,
+ spaces: result
+ };
+ }),
+ doesUserHaveVrSpaces: atLeastUserP.input(z.object({ userId: z.string() }))
+ .mutation(async ({ ctx, input }) => {
+ if (!hasAtLeastSecurityRole(ctx.role, 'admin')) {
+ throw new TRPCError({ code: 'UNAUTHORIZED', message: 'Admin rights required' });
+ }
+
+ const { userId } = input;
+ log.info(`Checking if user ${userId} owns VR spaces`);
+
+
+ const result = await db
+ .select({ count: sql
`count(*)`.mapWith(Number) })
+ .from(schema.vrSpaces)
+ .where(eq(schema.vrSpaces.ownerUserId, userId));
+
+ const hasSpaces = result[0]?.count > 0;
+ log.info(`User ${userId} ${hasSpaces ? 'HAS' : 'has NO'} VR spaces`);
+
+ return hasSpaces;
+ }),
updateVrSpace: userWithEditRightsToVrSpace.input(VrSpaceUpdateSchema).mutation(async ({ ctx, input }) => {
log.info('updating vrSpace', input);
const { vrSpaceId, reason, ...data } = input;