Permission Granted Users
This commit is contained in:
parent
4e439f3bf5
commit
98add9e398
8 changed files with 452 additions and 1 deletions
|
|
@ -0,0 +1,28 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace Sozsoft.Platform.Identity.Dto;
|
||||||
|
|
||||||
|
public class PermissionGrantedUsersDto
|
||||||
|
{
|
||||||
|
public string Name { get; set; }
|
||||||
|
public string ParentName { get; set; }
|
||||||
|
public string DisplayName { get; set; }
|
||||||
|
public bool IsEnabled { get; set; }
|
||||||
|
public List<string> RoleNames { get; set; } = [];
|
||||||
|
public List<PermissionGrantedUserDto> Users { get; set; } = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
public class PermissionGrantedUserDto
|
||||||
|
{
|
||||||
|
public Guid? TenantId { get; set; }
|
||||||
|
public Guid Id { get; set; }
|
||||||
|
public string UserName { get; set; }
|
||||||
|
public string Name { get; set; }
|
||||||
|
public string Surname { get; set; }
|
||||||
|
public string FullName { get; set; }
|
||||||
|
public string Email { get; set; }
|
||||||
|
public bool IsActive { get; set; }
|
||||||
|
public bool IsDirectGrant { get; set; }
|
||||||
|
public List<string> RoleNames { get; set; } = [];
|
||||||
|
}
|
||||||
|
|
@ -23,8 +23,10 @@ public class PlatformIdentityAppService : ApplicationService
|
||||||
{
|
{
|
||||||
public IIdentityUserAppService IdentityUserAppService { get; }
|
public IIdentityUserAppService IdentityUserAppService { get; }
|
||||||
private readonly IIdentityUserRepository identityUserRepository;
|
private readonly IIdentityUserRepository identityUserRepository;
|
||||||
|
private readonly IIdentityRoleRepository identityRoleRepository;
|
||||||
private readonly IIdentitySessionRepository identitySessionRepository;
|
private readonly IIdentitySessionRepository identitySessionRepository;
|
||||||
private readonly IOpenIddictTokenManager openIddictTokenManager;
|
private readonly IOpenIddictTokenManager openIddictTokenManager;
|
||||||
|
private readonly IPermissionGrantRepository permissionGrantRepository;
|
||||||
public IRepository<PermissionDefinitionRecord, Guid> permissionRepository { get; }
|
public IRepository<PermissionDefinitionRecord, Guid> permissionRepository { get; }
|
||||||
public IRepository<Branch, Guid> branchRepository { get; }
|
public IRepository<Branch, Guid> branchRepository { get; }
|
||||||
public IRepository<BranchUsers, Guid> branchUsersRepository { get; }
|
public IRepository<BranchUsers, Guid> branchUsersRepository { get; }
|
||||||
|
|
@ -39,8 +41,10 @@ public class PlatformIdentityAppService : ApplicationService
|
||||||
public PlatformIdentityAppService(
|
public PlatformIdentityAppService(
|
||||||
IIdentityUserAppService identityUserAppService,
|
IIdentityUserAppService identityUserAppService,
|
||||||
IIdentityUserRepository identityUserRepository,
|
IIdentityUserRepository identityUserRepository,
|
||||||
|
IIdentityRoleRepository identityRoleRepository,
|
||||||
IIdentitySessionRepository identitySessionRepository,
|
IIdentitySessionRepository identitySessionRepository,
|
||||||
IOpenIddictTokenManager openIddictTokenManager,
|
IOpenIddictTokenManager openIddictTokenManager,
|
||||||
|
IPermissionGrantRepository permissionGrantRepository,
|
||||||
IRepository<PermissionDefinitionRecord, Guid> permissionRepository,
|
IRepository<PermissionDefinitionRecord, Guid> permissionRepository,
|
||||||
IRepository<Branch, Guid> branchRepository,
|
IRepository<Branch, Guid> branchRepository,
|
||||||
IRepository<BranchUsers, Guid> branchUsersRepository,
|
IRepository<BranchUsers, Guid> branchUsersRepository,
|
||||||
|
|
@ -54,8 +58,10 @@ public class PlatformIdentityAppService : ApplicationService
|
||||||
{
|
{
|
||||||
this.IdentityUserAppService = identityUserAppService;
|
this.IdentityUserAppService = identityUserAppService;
|
||||||
this.identityUserRepository = identityUserRepository;
|
this.identityUserRepository = identityUserRepository;
|
||||||
|
this.identityRoleRepository = identityRoleRepository;
|
||||||
this.identitySessionRepository = identitySessionRepository;
|
this.identitySessionRepository = identitySessionRepository;
|
||||||
this.openIddictTokenManager = openIddictTokenManager;
|
this.openIddictTokenManager = openIddictTokenManager;
|
||||||
|
this.permissionGrantRepository = permissionGrantRepository;
|
||||||
this.workHourRepository = workHourRepository;
|
this.workHourRepository = workHourRepository;
|
||||||
this.departmentRepository = departmentRepository;
|
this.departmentRepository = departmentRepository;
|
||||||
this.jobPositionRepository = jobPositionRepository;
|
this.jobPositionRepository = jobPositionRepository;
|
||||||
|
|
@ -301,6 +307,118 @@ public class PlatformIdentityAppService : ApplicationService
|
||||||
return [.. list.OrderBy(p => p.Name)];
|
return [.. list.OrderBy(p => p.Name)];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async Task<List<PermissionGrantedUsersDto>> GetPermissionGrantedUsersAsync(string permissionName)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrWhiteSpace(permissionName))
|
||||||
|
{
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
permissionName = permissionName.Trim();
|
||||||
|
|
||||||
|
var permissions = (await permissionRepository.GetListAsync())
|
||||||
|
.Where(p => p.Name == permissionName || p.ParentName == permissionName)
|
||||||
|
.OrderBy(p => p.ParentName == null ? 0 : 1)
|
||||||
|
.ThenBy(p => p.Name)
|
||||||
|
.Take(200)
|
||||||
|
.ToList();
|
||||||
|
|
||||||
|
var permissionNames = permissions.Select(p => p.Name).ToHashSet();
|
||||||
|
if (permissionNames.Count == 0)
|
||||||
|
{
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
var grants = (await permissionGrantRepository.GetListAsync())
|
||||||
|
.Where(g => permissionNames.Contains(g.Name) && (g.ProviderName == "R" || g.ProviderName == "U"))
|
||||||
|
.ToList();
|
||||||
|
|
||||||
|
var roleNames = grants
|
||||||
|
.Where(g => g.ProviderName == "R")
|
||||||
|
.Select(g => g.ProviderKey)
|
||||||
|
.Where(key => !string.IsNullOrWhiteSpace(key))
|
||||||
|
.Distinct()
|
||||||
|
.ToList();
|
||||||
|
|
||||||
|
var roles = roleNames.Count == 0
|
||||||
|
? []
|
||||||
|
: (await identityRoleRepository.GetListAsync())
|
||||||
|
.Where(r => roleNames.Contains(r.Name))
|
||||||
|
.ToList();
|
||||||
|
|
||||||
|
var roleIdByName = roles.ToDictionary(r => r.Name, r => r.Id);
|
||||||
|
var roleNameById = roles.ToDictionary(r => r.Id, r => r.Name);
|
||||||
|
|
||||||
|
var roleIds = roleIdByName.Values.ToHashSet();
|
||||||
|
var directUserIds = grants
|
||||||
|
.Where(g => g.ProviderName == "U" && Guid.TryParse(g.ProviderKey, out _))
|
||||||
|
.Select(g => Guid.Parse(g.ProviderKey))
|
||||||
|
.ToHashSet();
|
||||||
|
|
||||||
|
var users = (await identityUserRepository.GetListAsync(includeDetails: true))
|
||||||
|
.Where(user =>
|
||||||
|
directUserIds.Contains(user.Id) ||
|
||||||
|
(user.Roles?.Any(userRole => roleIds.Contains(userRole.RoleId)) ?? false))
|
||||||
|
.ToList();
|
||||||
|
|
||||||
|
return permissions.Select(permission =>
|
||||||
|
{
|
||||||
|
var permissionGrants = grants.Where(g => g.Name == permission.Name).ToList();
|
||||||
|
var permissionRoleNames = permissionGrants
|
||||||
|
.Where(g => g.ProviderName == "R")
|
||||||
|
.Select(g => g.ProviderKey)
|
||||||
|
.Where(roleName => !string.IsNullOrWhiteSpace(roleName) && roleIdByName.ContainsKey(roleName))
|
||||||
|
.Distinct()
|
||||||
|
.OrderBy(roleName => roleName)
|
||||||
|
.ToList();
|
||||||
|
var permissionRoleIds = permissionRoleNames.Select(roleName => roleIdByName[roleName]).ToHashSet();
|
||||||
|
var permissionDirectUserIds = permissionGrants
|
||||||
|
.Where(g => g.ProviderName == "U" && Guid.TryParse(g.ProviderKey, out _))
|
||||||
|
.Select(g => Guid.Parse(g.ProviderKey))
|
||||||
|
.ToHashSet();
|
||||||
|
|
||||||
|
var permissionUsers = users
|
||||||
|
.Where(user =>
|
||||||
|
permissionDirectUserIds.Contains(user.Id) ||
|
||||||
|
(user.Roles?.Any(userRole => permissionRoleIds.Contains(userRole.RoleId)) ?? false))
|
||||||
|
.Select(user =>
|
||||||
|
{
|
||||||
|
var userRoleNames = (user.Roles ?? [])
|
||||||
|
.Where(userRole => permissionRoleIds.Contains(userRole.RoleId))
|
||||||
|
.Select(userRole => roleNameById[userRole.RoleId])
|
||||||
|
.Distinct()
|
||||||
|
.OrderBy(roleName => roleName)
|
||||||
|
.ToList();
|
||||||
|
|
||||||
|
return new PermissionGrantedUserDto
|
||||||
|
{
|
||||||
|
TenantId = user.TenantId,
|
||||||
|
Id = user.Id,
|
||||||
|
UserName = user.UserName,
|
||||||
|
Name = user.Name,
|
||||||
|
Surname = user.Surname,
|
||||||
|
FullName = $"{user.Name} {user.Surname}".Trim(),
|
||||||
|
Email = user.Email,
|
||||||
|
IsActive = user.IsActive,
|
||||||
|
IsDirectGrant = permissionDirectUserIds.Contains(user.Id),
|
||||||
|
RoleNames = userRoleNames
|
||||||
|
};
|
||||||
|
})
|
||||||
|
.OrderBy(user => user.UserName)
|
||||||
|
.ToList();
|
||||||
|
|
||||||
|
return new PermissionGrantedUsersDto
|
||||||
|
{
|
||||||
|
Name = permission.Name,
|
||||||
|
ParentName = permission.ParentName,
|
||||||
|
DisplayName = permission.DisplayName,
|
||||||
|
IsEnabled = permission.IsEnabled,
|
||||||
|
RoleNames = permissionRoleNames,
|
||||||
|
Users = permissionUsers
|
||||||
|
};
|
||||||
|
}).ToList();
|
||||||
|
}
|
||||||
|
|
||||||
public async Task CreateClaimUserAsync(UserClaimModel input)
|
public async Task CreateClaimUserAsync(UserClaimModel input)
|
||||||
{
|
{
|
||||||
var user = await identityUserRepository.GetAsync(input.UserId);
|
var user = await identityUserRepository.GetAsync(input.UserId);
|
||||||
|
|
|
||||||
|
|
@ -4236,6 +4236,24 @@
|
||||||
"en": "Reset list form structure",
|
"en": "Reset list form structure",
|
||||||
"tr": "Liste form yapısını sıfırla"
|
"tr": "Liste form yapısını sıfırla"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"resourceName": "Platform",
|
||||||
|
"key": "ListForms.ListForm.GrantedUsersErrorLoading",
|
||||||
|
"en": "Authorized users could not be loaded.",
|
||||||
|
"tr": "Yetki kullanıcıları yüklenemedi"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"resourceName": "Platform",
|
||||||
|
"key": "ListForms.ListForm.GrantedUsersNoAuthorization",
|
||||||
|
"en": "No authorization record was found for this list.",
|
||||||
|
"tr": "Bu liste için yetki kaydı bulunamadı."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"resourceName": "Platform",
|
||||||
|
"key": "ListForms.ListForm.GrantedUsers",
|
||||||
|
"en": "Authorized users",
|
||||||
|
"tr": "Yetkili kullanıcılar"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"resourceName": "Platform",
|
"resourceName": "Platform",
|
||||||
"key": "ListForms.ListForm.Manage",
|
"key": "ListForms.ListForm.Manage",
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@ export interface TagProps extends CommonProps {
|
||||||
prefixClass?: string
|
prefixClass?: string
|
||||||
suffix?: boolean | ReactNode
|
suffix?: boolean | ReactNode
|
||||||
suffixClass?: string
|
suffixClass?: string
|
||||||
|
title?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
const Tag = forwardRef<HTMLDivElement, TagProps>((props, ref) => {
|
const Tag = forwardRef<HTMLDivElement, TagProps>((props, ref) => {
|
||||||
|
|
@ -19,11 +20,12 @@ const Tag = forwardRef<HTMLDivElement, TagProps>((props, ref) => {
|
||||||
suffix,
|
suffix,
|
||||||
prefixClass,
|
prefixClass,
|
||||||
suffixClass,
|
suffixClass,
|
||||||
|
title,
|
||||||
...rest
|
...rest
|
||||||
} = props
|
} = props
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div ref={ref} className={classNames('tag', className)} {...rest}>
|
<div ref={ref} title={title} className={classNames('tag', className)} {...rest}>
|
||||||
{prefix && typeof prefix === 'boolean' && (
|
{prefix && typeof prefix === 'boolean' && (
|
||||||
<span
|
<span
|
||||||
className={classNames('tag-affix tag-prefix', prefixClass)}
|
className={classNames('tag-affix tag-prefix', prefixClass)}
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,28 @@ export interface UserAvatarUpdateInput {
|
||||||
avatar?: File
|
avatar?: File
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface PermissionGrantedUserDto {
|
||||||
|
tenantId: string
|
||||||
|
id: string
|
||||||
|
userName?: string
|
||||||
|
name?: string
|
||||||
|
surname?: string
|
||||||
|
fullName?: string
|
||||||
|
email?: string
|
||||||
|
isActive: boolean
|
||||||
|
isDirectGrant: boolean
|
||||||
|
roleNames: string[]
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface PermissionGrantedUsersDto {
|
||||||
|
name: string
|
||||||
|
parentName?: string
|
||||||
|
displayName?: string
|
||||||
|
isEnabled: boolean
|
||||||
|
roleNames: string[]
|
||||||
|
users: PermissionGrantedUserDto[]
|
||||||
|
}
|
||||||
|
|
||||||
export const getRoles = (skipCount = 0, maxResultCount = 10) =>
|
export const getRoles = (skipCount = 0, maxResultCount = 10) =>
|
||||||
apiService.fetchData<ListResultDto<IdentityRoleDto>>({
|
apiService.fetchData<ListResultDto<IdentityRoleDto>>({
|
||||||
method: 'GET',
|
method: 'GET',
|
||||||
|
|
@ -84,6 +106,13 @@ export const getPermissionsList = () =>
|
||||||
url: `/api/app/platform-identity/permission-list`,
|
url: `/api/app/platform-identity/permission-list`,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
export const getPermissionGrantedUsers = (permissionName: string) =>
|
||||||
|
apiService.fetchData<PermissionGrantedUsersDto[]>({
|
||||||
|
method: 'GET',
|
||||||
|
url: '/api/app/platform-identity/permission-granted-users',
|
||||||
|
params: { permissionName },
|
||||||
|
})
|
||||||
|
|
||||||
export const updatePermissions = (
|
export const updatePermissions = (
|
||||||
providerName: string,
|
providerName: string,
|
||||||
providerKey: string,
|
providerKey: string,
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@ import { Dispatch, MutableRefObject, SetStateAction, useState } from 'react'
|
||||||
import CreatableSelect from 'react-select/creatable'
|
import CreatableSelect from 'react-select/creatable'
|
||||||
import { ISelectBoxData } from './useFilters'
|
import { ISelectBoxData } from './useFilters'
|
||||||
import { ListFormCustomizationTypeEnum } from '@/proxy/form/models'
|
import { ListFormCustomizationTypeEnum } from '@/proxy/form/models'
|
||||||
|
import PermissionGranted from './PermissionGranted'
|
||||||
|
|
||||||
const GridFilterDialogs = (props: {
|
const GridFilterDialogs = (props: {
|
||||||
listFormCode: string
|
listFormCode: string
|
||||||
|
|
@ -17,6 +18,9 @@ const GridFilterDialogs = (props: {
|
||||||
setIsCreateUpdateModalOpen: Dispatch<SetStateAction<boolean>>
|
setIsCreateUpdateModalOpen: Dispatch<SetStateAction<boolean>>
|
||||||
isDeleteModalOpen: boolean
|
isDeleteModalOpen: boolean
|
||||||
setIsDeleteModalOpen: Dispatch<SetStateAction<boolean>>
|
setIsDeleteModalOpen: Dispatch<SetStateAction<boolean>>
|
||||||
|
isPermissionUsersModalOpen: boolean
|
||||||
|
setIsPermissionUsersModalOpen: Dispatch<SetStateAction<boolean>>
|
||||||
|
permissionNames: string[]
|
||||||
getFilters: () => Promise<void>
|
getFilters: () => Promise<void>
|
||||||
}) => {
|
}) => {
|
||||||
const [newFilterName, setNewFilterName] = useState<string | undefined>()
|
const [newFilterName, setNewFilterName] = useState<string | undefined>()
|
||||||
|
|
@ -30,6 +34,9 @@ const GridFilterDialogs = (props: {
|
||||||
setIsCreateUpdateModalOpen,
|
setIsCreateUpdateModalOpen,
|
||||||
isDeleteModalOpen,
|
isDeleteModalOpen,
|
||||||
setIsDeleteModalOpen,
|
setIsDeleteModalOpen,
|
||||||
|
isPermissionUsersModalOpen,
|
||||||
|
setIsPermissionUsersModalOpen,
|
||||||
|
permissionNames,
|
||||||
getFilters,
|
getFilters,
|
||||||
} = props
|
} = props
|
||||||
|
|
||||||
|
|
@ -164,6 +171,13 @@ const GridFilterDialogs = (props: {
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</Dialog>
|
</Dialog>
|
||||||
|
|
||||||
|
<PermissionGranted
|
||||||
|
isOpen={isPermissionUsersModalOpen}
|
||||||
|
listFormCode={listFormCode}
|
||||||
|
permissionNames={permissionNames}
|
||||||
|
onClose={() => setIsPermissionUsersModalOpen(false)}
|
||||||
|
/>
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
216
ui/src/views/list/PermissionGranted.tsx
Normal file
216
ui/src/views/list/PermissionGranted.tsx
Normal file
|
|
@ -0,0 +1,216 @@
|
||||||
|
import { Avatar, Button, Dialog, Notification, Spinner, Table, Tag, toast } from '@/components/ui'
|
||||||
|
import { AVATAR_URL } from '@/constants/app.constant'
|
||||||
|
import {
|
||||||
|
getPermissionGrantedUsers,
|
||||||
|
PermissionGrantedUsersDto,
|
||||||
|
PermissionGrantedUserDto,
|
||||||
|
} from '@/services/identity.service'
|
||||||
|
import { useLocalization } from '@/utils/hooks/useLocalization'
|
||||||
|
import { useEffect, useMemo, useState } from 'react'
|
||||||
|
|
||||||
|
type PermissionGrantedProps = {
|
||||||
|
isOpen: boolean
|
||||||
|
listFormCode: string
|
||||||
|
permissionNames: string[]
|
||||||
|
onClose: () => void
|
||||||
|
}
|
||||||
|
|
||||||
|
const permissionActionSuffixes = ['Create', 'Delete', 'Export', 'Import', 'Note', 'Update']
|
||||||
|
|
||||||
|
const actionLabels: Record<string, string> = {
|
||||||
|
Create: 'Create',
|
||||||
|
Delete: 'Delete',
|
||||||
|
Export: 'Export',
|
||||||
|
Import: 'Import',
|
||||||
|
Note: 'Note',
|
||||||
|
Update: 'Update',
|
||||||
|
}
|
||||||
|
|
||||||
|
const permissionActionLabel = (permissionName: string) => {
|
||||||
|
const lastPart = permissionName.split('.').pop() ?? permissionName
|
||||||
|
return actionLabels[lastPart] ?? lastPart
|
||||||
|
}
|
||||||
|
|
||||||
|
const unique = (values: string[]) =>
|
||||||
|
values.filter((value, index, array) => value && array.indexOf(value) === index)
|
||||||
|
|
||||||
|
const toRootPermissionName = (permissionName?: string) => {
|
||||||
|
if (!permissionName) {
|
||||||
|
return ''
|
||||||
|
}
|
||||||
|
|
||||||
|
const suffix = permissionActionSuffixes.find((item) => permissionName.endsWith(`.${item}`))
|
||||||
|
return suffix ? permissionName.slice(0, -suffix.length - 1) : permissionName
|
||||||
|
}
|
||||||
|
|
||||||
|
const userDisplayName = (user: PermissionGrantedUserDto) =>
|
||||||
|
user.fullName ||
|
||||||
|
[user.name, user.surname].filter(Boolean).join(' ') ||
|
||||||
|
user.userName ||
|
||||||
|
user.email ||
|
||||||
|
user.id
|
||||||
|
|
||||||
|
const PermissionGranted = ({
|
||||||
|
isOpen,
|
||||||
|
listFormCode,
|
||||||
|
permissionNames,
|
||||||
|
onClose,
|
||||||
|
}: PermissionGrantedProps) => {
|
||||||
|
const [loading, setLoading] = useState(false)
|
||||||
|
const [items, setItems] = useState<PermissionGrantedUsersDto[]>([])
|
||||||
|
const { translate } = useLocalization()
|
||||||
|
|
||||||
|
const rootPermissionName = useMemo(() => {
|
||||||
|
const normalizedPermissionNames = unique(permissionNames)
|
||||||
|
return (
|
||||||
|
normalizedPermissionNames.find(
|
||||||
|
(permissionName) =>
|
||||||
|
!permissionActionSuffixes.some((suffix) => permissionName.endsWith(`.${suffix}`)),
|
||||||
|
) ?? toRootPermissionName(normalizedPermissionNames[0])
|
||||||
|
)
|
||||||
|
}, [permissionNames.join('|')])
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!isOpen) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const loadData = async () => {
|
||||||
|
if (!rootPermissionName) {
|
||||||
|
setItems([])
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
setLoading(true)
|
||||||
|
try {
|
||||||
|
const response = await getPermissionGrantedUsers(rootPermissionName)
|
||||||
|
|
||||||
|
setItems(
|
||||||
|
(response.data ?? []).sort((a, b) => {
|
||||||
|
if (!a.parentName && b.parentName) return -1
|
||||||
|
if (a.parentName && !b.parentName) return 1
|
||||||
|
return a.name.localeCompare(b.name)
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
} catch {
|
||||||
|
toast.push(
|
||||||
|
<Notification type="danger" duration={3000}>
|
||||||
|
{translate('::ListForms.ListForm.GrantedUsersErrorLoading')}
|
||||||
|
</Notification>,
|
||||||
|
{ placement: 'top-end' },
|
||||||
|
)
|
||||||
|
} finally {
|
||||||
|
setLoading(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
loadData()
|
||||||
|
}, [isOpen, rootPermissionName])
|
||||||
|
|
||||||
|
const uniqueUsers = useMemo(() => {
|
||||||
|
const map = new Map<string, PermissionGrantedUserDto & { permissions: string[] }>()
|
||||||
|
|
||||||
|
items.forEach((permission) => {
|
||||||
|
permission.users.forEach((user) => {
|
||||||
|
const existing = map.get(user.id)
|
||||||
|
if (existing) {
|
||||||
|
existing.permissions.push(permissionActionLabel(permission.name))
|
||||||
|
existing.roleNames = unique([...existing.roleNames, ...user.roleNames])
|
||||||
|
} else {
|
||||||
|
map.set(user.id, {
|
||||||
|
...user,
|
||||||
|
permissions: [permissionActionLabel(permission.name)],
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
return Array.from(map.values()).sort((a, b) =>
|
||||||
|
userDisplayName(a).localeCompare(userDisplayName(b)),
|
||||||
|
)
|
||||||
|
}, [items])
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Dialog isOpen={isOpen} onClose={onClose} onRequestClose={onClose} width={1000}>
|
||||||
|
<Dialog.Header className="flex min-h-12 items-center justify-between gap-3 border-b border-gray-200 px-2 py-2 dark:border-gray-700">
|
||||||
|
<div className="min-w-0">
|
||||||
|
<h2 className="truncate text-lg font-semibold text-gray-900 dark:text-gray-100">
|
||||||
|
{translate('::ListForms.ListForm.GrantedUsers')}
|
||||||
|
</h2>
|
||||||
|
<div className="truncate text-xs text-gray-500 dark:text-gray-400">
|
||||||
|
{rootPermissionName || listFormCode}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<Tag>
|
||||||
|
{uniqueUsers.length} {translate('::ListForms.ListFormField.User')}
|
||||||
|
</Tag>
|
||||||
|
</Dialog.Header>
|
||||||
|
|
||||||
|
<Dialog.Body className="max-h-[70vh] overflow-auto px-0 pb-0 pt-4">
|
||||||
|
{loading ? (
|
||||||
|
<div className="flex min-h-48 items-center justify-center">
|
||||||
|
<Spinner size={36} />
|
||||||
|
</div>
|
||||||
|
) : items.length === 0 ? (
|
||||||
|
<div className="px-6 py-10 text-center text-sm text-gray-500 dark:text-gray-400">
|
||||||
|
{translate('::ListForms.ListForm.GrantedUsersNoAuthorization')}
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<div className="space-y-5">
|
||||||
|
<div className="overflow-x-auto rounded border border-gray-200 dark:border-gray-700 mb-5">
|
||||||
|
<Table compact>
|
||||||
|
<Table.THead>
|
||||||
|
<Table.Tr>
|
||||||
|
<Table.Th>{translate('::ListForms.ListFormField.User')}</Table.Th>
|
||||||
|
<Table.Th>{translate('::App.Listform.ListformField.Email')}</Table.Th>
|
||||||
|
<Table.Th>{translate('::AbpIdentity.Roles')}</Table.Th>
|
||||||
|
<Table.Th>{translate('::Abp.Identity.User.Permissions')}</Table.Th>
|
||||||
|
</Table.Tr>
|
||||||
|
</Table.THead>
|
||||||
|
<Table.TBody>
|
||||||
|
{uniqueUsers.map((user) => (
|
||||||
|
<Table.Tr key={user.id}>
|
||||||
|
<Table.Td>
|
||||||
|
<div className="flex min-w-0 items-center gap-2">
|
||||||
|
<Avatar size={28} shape="circle" src={AVATAR_URL(user.id, user.tenantId)} />
|
||||||
|
<div className="min-w-0">
|
||||||
|
<div className="truncate font-medium text-gray-900 dark:text-gray-100">
|
||||||
|
{userDisplayName(user)}
|
||||||
|
</div>
|
||||||
|
<div className="truncate text-xs text-gray-500">{user.userName}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Table.Td>
|
||||||
|
<Table.Td>{user.email}</Table.Td>
|
||||||
|
<Table.Td>
|
||||||
|
<div className="flex flex-wrap gap-1">
|
||||||
|
{user.roleNames.map((roleName) => (
|
||||||
|
<Tag key={roleName}>R: {roleName}</Tag>
|
||||||
|
))}
|
||||||
|
{user.isDirectGrant && <Tag>U</Tag>}
|
||||||
|
</div>
|
||||||
|
</Table.Td>
|
||||||
|
<Table.Td>
|
||||||
|
<div className="flex flex-wrap gap-1">
|
||||||
|
{unique(user.permissions).map((permission) => (
|
||||||
|
<Tag key={permission} title={permission}>{permission}</Tag>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</Table.Td>
|
||||||
|
</Table.Tr>
|
||||||
|
))}
|
||||||
|
</Table.TBody>
|
||||||
|
</Table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</Dialog.Body>
|
||||||
|
|
||||||
|
<Dialog.Footer className="border-t border-gray-200 pt-4 text-right dark:border-gray-700">
|
||||||
|
<Button variant='solid' onClick={onClose}>{translate('::Close')}</Button>
|
||||||
|
</Dialog.Footer>
|
||||||
|
</Dialog>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default PermissionGranted
|
||||||
|
|
@ -176,6 +176,9 @@ const useFilters = ({
|
||||||
setIsCreateUpdateModalOpen: Dispatch<SetStateAction<boolean>>
|
setIsCreateUpdateModalOpen: Dispatch<SetStateAction<boolean>>
|
||||||
isDeleteModalOpen: boolean
|
isDeleteModalOpen: boolean
|
||||||
setIsDeleteModalOpen: Dispatch<SetStateAction<boolean>>
|
setIsDeleteModalOpen: Dispatch<SetStateAction<boolean>>
|
||||||
|
isPermissionUsersModalOpen: boolean
|
||||||
|
setIsPermissionUsersModalOpen: Dispatch<SetStateAction<boolean>>
|
||||||
|
permissionNames: string[]
|
||||||
filtersForSelectBox: ISelectBoxData[]
|
filtersForSelectBox: ISelectBoxData[]
|
||||||
getFilters: () => Promise<void>
|
getFilters: () => Promise<void>
|
||||||
isImportModalOpen: boolean
|
isImportModalOpen: boolean
|
||||||
|
|
@ -193,12 +196,22 @@ const useFilters = ({
|
||||||
const [isCreateUpdateModalOpen, setIsCreateUpdateModalOpen] = useState(false)
|
const [isCreateUpdateModalOpen, setIsCreateUpdateModalOpen] = useState(false)
|
||||||
const [isDeleteModalOpen, setIsDeleteModalOpen] = useState(false)
|
const [isDeleteModalOpen, setIsDeleteModalOpen] = useState(false)
|
||||||
const [isImportModalOpen, setIsImportModalOpen] = useState(false)
|
const [isImportModalOpen, setIsImportModalOpen] = useState(false)
|
||||||
|
const [isPermissionUsersModalOpen, setIsPermissionUsersModalOpen] = useState(false)
|
||||||
|
|
||||||
const filteredGridPanelColor = 'rgba(10, 200, 10, 0.5)' // kullanici tanimli filtre ile filtrelenmis gridin paneline ait renk
|
const filteredGridPanelColor = 'rgba(10, 200, 10, 0.5)' // kullanici tanimli filtre ile filtrelenmis gridin paneline ait renk
|
||||||
const statedGridPanelColor = 'rgba(50, 200, 200, 0.5)' // kullanici tanimli gridState ile islem gormus gridin paneline ait renk
|
const statedGridPanelColor = 'rgba(50, 200, 200, 0.5)' // kullanici tanimli gridState ile islem gormus gridin paneline ait renk
|
||||||
|
|
||||||
const grdOpt = gridDto?.gridOptions
|
const grdOpt = gridDto?.gridOptions
|
||||||
const config = useStoreState((state) => state.abpConfig.config)
|
const config = useStoreState((state) => state.abpConfig.config)
|
||||||
|
const permissionNames = [
|
||||||
|
grdOpt?.permissionDto?.r,
|
||||||
|
grdOpt?.permissionDto?.c,
|
||||||
|
grdOpt?.permissionDto?.u,
|
||||||
|
grdOpt?.permissionDto?.d,
|
||||||
|
grdOpt?.permissionDto?.e,
|
||||||
|
grdOpt?.permissionDto?.i,
|
||||||
|
grdOpt?.permissionDto?.n,
|
||||||
|
].filter(Boolean) as string[]
|
||||||
|
|
||||||
const getFilters = async () => {
|
const getFilters = async () => {
|
||||||
const response = await getListFormCustomization(
|
const response = await getListFormCustomization(
|
||||||
|
|
@ -294,6 +307,14 @@ const useFilters = ({
|
||||||
}
|
}
|
||||||
|
|
||||||
if (checkPermission('App.Listforms.Listform.Update')) {
|
if (checkPermission('App.Listforms.Listform.Update')) {
|
||||||
|
if (permissionNames.length > 0) {
|
||||||
|
menus.push({
|
||||||
|
text: translate('::ListForms.ListForm.GrantedUsers'),
|
||||||
|
id: 'permissionGrantedUsers',
|
||||||
|
icon: 'user',
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
menus.push({
|
menus.push({
|
||||||
text: translate('::ListForms.ListForm.Manage'),
|
text: translate('::ListForms.ListForm.Manage'),
|
||||||
id: 'openManage',
|
id: 'openManage',
|
||||||
|
|
@ -387,6 +408,8 @@ const useFilters = ({
|
||||||
} else if (itemData.id === 'importManager') {
|
} else if (itemData.id === 'importManager') {
|
||||||
// import modal aç
|
// import modal aç
|
||||||
setIsImportModalOpen(true)
|
setIsImportModalOpen(true)
|
||||||
|
} else if (itemData.id === 'permissionGrantedUsers') {
|
||||||
|
setIsPermissionUsersModalOpen(true)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
// filtre menüsündeki elemanlar
|
// filtre menüsündeki elemanlar
|
||||||
|
|
@ -474,6 +497,9 @@ const useFilters = ({
|
||||||
setIsCreateUpdateModalOpen,
|
setIsCreateUpdateModalOpen,
|
||||||
isDeleteModalOpen,
|
isDeleteModalOpen,
|
||||||
setIsDeleteModalOpen,
|
setIsDeleteModalOpen,
|
||||||
|
isPermissionUsersModalOpen,
|
||||||
|
setIsPermissionUsersModalOpen,
|
||||||
|
permissionNames,
|
||||||
filtersForSelectBox,
|
filtersForSelectBox,
|
||||||
getFilters,
|
getFilters,
|
||||||
isImportModalOpen,
|
isImportModalOpen,
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue