fix: let only the owner set logout time and move the attendance tab
This commit is contained in:
@@ -68,7 +68,7 @@ export class UsersController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Patch(':id/logout-time')
|
@Patch(':id/logout-time')
|
||||||
@Roles('owner', 'admin')
|
@Roles('owner')
|
||||||
updateLogoutTime(
|
updateLogoutTime(
|
||||||
@CurrentUser() user: { organizationId: string; role: UserRole },
|
@CurrentUser() user: { organizationId: string; role: UserRole },
|
||||||
@Param('id') id: string,
|
@Param('id') id: string,
|
||||||
|
|||||||
@@ -249,8 +249,8 @@ export class UsersService {
|
|||||||
targetId: string,
|
targetId: string,
|
||||||
logoutTime: string | null,
|
logoutTime: string | null,
|
||||||
): Promise<OrgUserDto> {
|
): Promise<OrgUserDto> {
|
||||||
if (actorRole !== 'owner' && actorRole !== 'admin') {
|
if (actorRole !== 'owner') {
|
||||||
throw new ForbiddenException('فقط مالک یا مدیر میتواند ساعت خروج را تعیین کند');
|
throw new ForbiddenException('فقط مالک میتواند ساعت خروج را تعیین کند');
|
||||||
}
|
}
|
||||||
const target = await this.memberships.findUserInOrgById(organizationId, targetId);
|
const target = await this.memberships.findUserInOrgById(organizationId, targetId);
|
||||||
if (!target) throw new NotFoundException('کاربر پیدا نشد');
|
if (!target) throw new NotFoundException('کاربر پیدا نشد');
|
||||||
|
|||||||
@@ -30,10 +30,10 @@ type LogTab = 'all' | 'creates' | 'edits' | 'deletes' | 'attendance';
|
|||||||
|
|
||||||
const TABS: Array<{ key: LogTab; label: string; action?: string }> = [
|
const TABS: Array<{ key: LogTab; label: string; action?: string }> = [
|
||||||
{ key: 'all', label: 'همه' },
|
{ key: 'all', label: 'همه' },
|
||||||
|
{ key: 'attendance', label: 'ورود و خروج' },
|
||||||
{ key: 'creates', label: 'ایجاد', action: 'ایجاد' },
|
{ key: 'creates', label: 'ایجاد', action: 'ایجاد' },
|
||||||
{ key: 'edits', label: 'ویرایش', action: 'ویرایش' },
|
{ key: 'edits', label: 'ویرایش', action: 'ویرایش' },
|
||||||
{ key: 'deletes', label: 'حذف', action: 'حذف' },
|
{ key: 'deletes', label: 'حذف', action: 'حذف' },
|
||||||
{ key: 'attendance', label: 'ورود و خروج' },
|
|
||||||
];
|
];
|
||||||
|
|
||||||
const ENTITY_LABELS: Record<string, string> = {
|
const ENTITY_LABELS: Record<string, string> = {
|
||||||
|
|||||||
@@ -129,6 +129,7 @@ const avatarUrls = ref<Record<string, string>>({});
|
|||||||
const loadedAvatars = new Set<string>();
|
const loadedAvatars = new Set<string>();
|
||||||
|
|
||||||
const canInvite = computed(() => canManageUsers(auth.user?.role));
|
const canInvite = computed(() => canManageUsers(auth.user?.role));
|
||||||
|
const canSetLogoutTime = computed(() => auth.user?.role === 'owner');
|
||||||
const canEditOrg = computed(() => canManageSettings(auth.user?.role));
|
const canEditOrg = computed(() => canManageSettings(auth.user?.role));
|
||||||
const canEditRoles = computed(() => canManageUsers(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) {
|
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();
|
const next = raw.trim();
|
||||||
if (next === (user.logoutTime ?? '')) return;
|
if (next === (user.logoutTime ?? '')) return;
|
||||||
error.value = '';
|
error.value = '';
|
||||||
@@ -997,7 +998,7 @@ onUnmounted(() => {
|
|||||||
<span :class="{ flip: !sortLoginDesc }">▴</span>
|
<span :class="{ flip: !sortLoginDesc }">▴</span>
|
||||||
</button>
|
</button>
|
||||||
</th>
|
</th>
|
||||||
<th>ساعت خروج</th>
|
<th v-if="canSetLogoutTime">ساعت خروج</th>
|
||||||
<th class="ops" />
|
<th class="ops" />
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
@@ -1037,7 +1038,7 @@ onUnmounted(() => {
|
|||||||
</span>
|
</span>
|
||||||
</td>
|
</td>
|
||||||
<td class="muted">{{ formatLastLogin(user.lastLoginAt) }}</td>
|
<td class="muted">{{ formatLastLogin(user.lastLoginAt) }}</td>
|
||||||
<td @click.stop>
|
<td v-if="canSetLogoutTime" @click.stop>
|
||||||
<span v-if="user.role === 'owner'" class="muted">—</span>
|
<span v-if="user.role === 'owner'" class="muted">—</span>
|
||||||
<input
|
<input
|
||||||
v-else
|
v-else
|
||||||
@@ -1045,7 +1046,6 @@ onUnmounted(() => {
|
|||||||
type="time"
|
type="time"
|
||||||
dir="ltr"
|
dir="ltr"
|
||||||
:value="user.logoutTime || ''"
|
:value="user.logoutTime || ''"
|
||||||
:disabled="!canInvite"
|
|
||||||
:aria-label="`ساعت خروج ${user.fullName}`"
|
:aria-label="`ساعت خروج ${user.fullName}`"
|
||||||
@change="changeLogoutTime(user, ($event.target as HTMLInputElement).value)"
|
@change="changeLogoutTime(user, ($event.target as HTMLInputElement).value)"
|
||||||
/>
|
/>
|
||||||
|
|||||||
Reference in New Issue
Block a user