From f15ebb72ea4ea3392b59c8cebba0d8e0d08633df Mon Sep 17 00:00:00 2001 From: Mahdi Date: Mon, 19 Oct 2026 13:54:09 +0330 Subject: [PATCH] fix: let only the owner set logout time and move the attendance tab --- apps/api/src/users/users.controller.ts | 2 +- apps/api/src/users/users.service.ts | 4 ++-- apps/web/src/views/AuditLogsView.vue | 2 +- apps/web/src/views/TeamSettingsView.vue | 8 ++++---- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/apps/api/src/users/users.controller.ts b/apps/api/src/users/users.controller.ts index 25dd403..5501040 100644 --- a/apps/api/src/users/users.controller.ts +++ b/apps/api/src/users/users.controller.ts @@ -68,7 +68,7 @@ export class UsersController { } @Patch(':id/logout-time') - @Roles('owner', 'admin') + @Roles('owner') updateLogoutTime( @CurrentUser() user: { organizationId: string; role: UserRole }, @Param('id') id: string, diff --git a/apps/api/src/users/users.service.ts b/apps/api/src/users/users.service.ts index 179b070..040e0ac 100644 --- a/apps/api/src/users/users.service.ts +++ b/apps/api/src/users/users.service.ts @@ -249,8 +249,8 @@ export class UsersService { targetId: string, logoutTime: string | null, ): Promise { - if (actorRole !== 'owner' && actorRole !== 'admin') { - throw new ForbiddenException('فقط مالک یا مدیر می‌تواند ساعت خروج را تعیین کند'); + if (actorRole !== 'owner') { + throw new ForbiddenException('فقط مالک می‌تواند ساعت خروج را تعیین کند'); } const target = await this.memberships.findUserInOrgById(organizationId, targetId); if (!target) throw new NotFoundException('کاربر پیدا نشد'); diff --git a/apps/web/src/views/AuditLogsView.vue b/apps/web/src/views/AuditLogsView.vue index b981aef..4d31c6c 100644 --- a/apps/web/src/views/AuditLogsView.vue +++ b/apps/web/src/views/AuditLogsView.vue @@ -30,10 +30,10 @@ type LogTab = 'all' | 'creates' | 'edits' | 'deletes' | 'attendance'; const TABS: Array<{ key: LogTab; label: string; action?: string }> = [ { key: 'all', label: 'همه' }, + { key: 'attendance', label: 'ورود و خروج' }, { key: 'creates', label: 'ایجاد', action: 'ایجاد' }, { key: 'edits', label: 'ویرایش', action: 'ویرایش' }, { key: 'deletes', label: 'حذف', action: 'حذف' }, - { key: 'attendance', label: 'ورود و خروج' }, ]; const ENTITY_LABELS: Record = { diff --git a/apps/web/src/views/TeamSettingsView.vue b/apps/web/src/views/TeamSettingsView.vue index a5c83e7..93cefe9 100644 --- a/apps/web/src/views/TeamSettingsView.vue +++ b/apps/web/src/views/TeamSettingsView.vue @@ -129,6 +129,7 @@ const avatarUrls = ref>({}); const loadedAvatars = new Set(); const canInvite = computed(() => canManageUsers(auth.user?.role)); +const canSetLogoutTime = computed(() => auth.user?.role === 'owner'); const canEditOrg = computed(() => canManageSettings(auth.user?.role)); const canEditRoles = computed(() => canManageUsers(auth.user?.role)); /** مالک واقعی می‌تواند از جدول کاربران وارد مشاهده شود / برگردد */ @@ -493,7 +494,7 @@ async function toggleStatus(user: OrgUserDto) { } async function changeLogoutTime(user: OrgUserDto, raw: string) { - if (!canInvite.value || user.role === 'owner') return; + if (!canSetLogoutTime.value || user.role === 'owner') return; const next = raw.trim(); if (next === (user.logoutTime ?? '')) return; error.value = ''; @@ -997,7 +998,7 @@ onUnmounted(() => { ▴ - ساعت خروج + ساعت خروج @@ -1037,7 +1038,7 @@ onUnmounted(() => { {{ formatLastLogin(user.lastLoginAt) }} - + — { type="time" dir="ltr" :value="user.logoutTime || ''" - :disabled="!canInvite" :aria-label="`ساعت خروج ${user.fullName}`" @change="changeLogoutTime(user, ($event.target as HTMLInputElement).value)" />