feat: compact logout-time cell and optional login block after logout time

Owners set the daily logout time in a modal and can block re-login until the next Tehran day.
This commit is contained in:
2026-10-21 14:20:15 +03:30
parent 7ae6a5837a
commit ce27df20ca
9 changed files with 195 additions and 25 deletions
+5
View File
@@ -95,6 +95,11 @@ export class UpdateLogoutTimeDto {
@IsString()
@Matches(/^([01]\d|2[0-3]):[0-5]\d$/, { message: 'ساعت خروج معتبر نیست' })
logoutTime?: string | null;
/** بدون مقدار = بدون تغییر */
@IsOptional()
@IsBoolean()
blockLoginAfterLogout?: boolean;
}
export class UpdateUserVisibilityDto {
+1
View File
@@ -79,6 +79,7 @@ export class UsersController {
user.role,
id,
dto.logoutTime ?? null,
dto.blockLoginAfterLogout,
);
}
+13 -1
View File
@@ -46,6 +46,7 @@ type MembershipRow = {
dataVisibilityScopes?: unknown;
priorArchiveEnabled?: boolean;
logoutTime?: string | null;
blockLoginAfterLogout?: boolean;
createdAt: Date;
orgRole: { id: string; name: string; color: string } | null;
user: {
@@ -248,6 +249,7 @@ export class UsersService {
actorRole: UserRole,
targetId: string,
logoutTime: string | null,
blockLoginAfterLogout?: boolean,
): Promise<OrgUserDto> {
if (actorRole !== 'owner') {
throw new ForbiddenException('فقط مالک می‌تواند ساعت خروج را تعیین کند');
@@ -263,7 +265,15 @@ export class UsersService {
}
await this.prisma.membership.update({
where: { id: target.id },
data: { logoutTime: value },
data: {
logoutTime: value,
// بدون ساعت خروج، مسدودسازی معنی ندارد
...(!value
? { blockLoginAfterLogout: false }
: blockLoginAfterLogout !== undefined
? { blockLoginAfterLogout }
: {}),
},
});
return this.dtoOf(organizationId, targetId);
}
@@ -533,6 +543,8 @@ export class UsersService {
: parseVisibilityScopes(row.dataVisibilityScopes),
priorArchiveEnabled: Boolean(row.priorArchiveEnabled),
logoutTime: row.role === 'owner' ? null : row.logoutTime ?? null,
blockLoginAfterLogout:
row.role !== 'owner' && Boolean(row.logoutTime) && Boolean(row.blockLoginAfterLogout),
createdAt: row.createdAt.toISOString(),
};
}