Hello again, thank you for your clarification. This warning comes up for this reason. If you want to reach the details of the intended folder you will need to initialize the structure as follows:
ngOnInit(): void {
this.directory.updateDirectories(null);
}
You can also find the related implementation inside the file management module structure. After you have configured this, the treeHolder will not throw the same error. However, it will not physically redirect user to that specific folder which depends on your business logic and other configurations.
Hello, you can replace the related reference with your local css that is inside the angular.json.
Also, here is the link you can follow that is similar to your question which may help.
I suppose that your aim is to call the file management module functions outside of the file management structure.
You can correct me if I am wrong, since then I have duplicated this error once I randomly called a folder by giving details. However, in this case, the treeHolder
cannot be handled properly.
Considering these, if your aim is different than what I investigated, you can let us know about it.
Hello Viktor, again. Normally, if the user has no impersonation permission, you need to receive an error saying that "Require AbpIdentity.Users.Impersonation permission to impersonate user!"
This applies for logging in using the specific account without using authority delegation.
However, if you want to use authority delegation, you need to give the delegation for that specific user, and here is how we can do it
After you list the delegated user. You can use such an approach
protected readonly configState = inject(ConfigStateService);
protected readonly authService = inject(AuthService);
protected readonly environment = inject(EnvironmentService);
login(userDelegationId: string) {
const impersonatedUser = this.configState.getDeep('currentUser.impersonatorUserId');
const impersonatedTenant = this.configState.getDeep('currentUser.impersonatorTenantId');
if (impersonatedTenant || impersonatedUser) {
return;
}
this.environment.getEnvironment$().pipe(
tap(({ oAuthConfig: { responseType } }) => {
if (responseType === 'code') {
this.authService.oidc = false;
}
}),
switchMap(() => {
const promiseOfLogin = this.authService.loginUsingGrant('Impersonation', {
UserDelegationId: userDelegationId,
});
return from(promiseOfLogin).pipe(
tap(
() => (location.href = this.environment.getEnvironment().application?.baseUrl || '/'),
),
);
}),
).subscribe();
}
Hello again Viktor. As I have emphasized before you can use the ImpersonationService
functionalities by constructing a code block like this:
protected impersonationService = inject(ImpersonationService);
protected permissionService = inject(PermissionService);
//This is the part you implement as a click event
loginWithThisUser(user) {
const canImpersonate = this.permissionService.getGrantedPolicy(
'AbpIdentity.Users.Impersonation',
);
const currentUserId = this.configState.getDeep('currentUser.id');
const currentImpersonatedUserId = this.configState.getDeep('currrentUser.impersontorUserId');
const { id: userId } = user.record;
const isCurrentUser = userId === currentUserId;
const isImpersonating = currentImpersonatedUserId !== undefined;
if (isCurrentUser || isImpersonating || !canImpersonate) {
return;
}
this.impersonationService.impersonateUser(user.record.id).subscribe();
}
Here in this part, you need to check three important points for a successful login and redirect
Since then this is the basic conditions, you can customize it for your case.
Based on your condition, you can check whether this user is already impersonated you can change the Login
button as Go Back to My Account
. Here is how you can manage this:
protected impersonationService = inject(ImpersonationService);
goBackToMyAccount(){
this.impersonation.impersonate({}).subscribe();
}
Hello again Viktor, sorry for the delay caused by the chain of misunderstandings. You can customize the entity actions for your page. Here is the default config for the identity module actions:
export const DEFAULT_USERS_ENTITY_ACTIONS = EntityAction.createMany<IdentityUserDto>([
{
text: 'AbpIdentity::ViewDetails',
action: data => {
const component = data.getInjected(UsersComponent);
component.viewDetails(data.record);
},
permission: 'AbpIdentity.Users.ViewDetails',
},
{
text: 'AbpUi::Edit',
action: data => {
const component = data.getInjected(UsersComponent);
component.onEdit(data.record.id);
},
permission: 'AbpIdentity.Users.Update',
},
{
text: 'AbpIdentity::Claims',
action: data => {
const component = data.getInjected(UsersComponent);
component.onManageClaims(data.record.id);
},
permission: 'AbpIdentity.Users.Update',
},
{
text: 'AbpIdentity::Lock',
action: data => {
const component = data.getInjected(UsersComponent);
component.selected = data.record;
component.isLockModalVisible = true;
},
permission: 'AbpIdentity.Users.Update',
visible: data => {
const configState = data.getInjected(ConfigStateService);
const currentUserId = configState.getDeep('currentUser.id');
return (
data.record.id !== currentUserId && data.record.lockoutEnabled
);
},
},
{
text: 'AbpIdentity::Unlock',
action: data => {
const component = data.getInjected(UsersComponent);
component.unlock(data.record.id);
},
permission: 'AbpIdentity.Users.Update',
visible: data => data.record.isLockedOut,
},
{
text: 'AbpIdentity::Permissions',
action: data => {
const component = data.getInjected(UsersComponent);
component.openPermissionsModal(data.record.id, data.record.userName);
},
permission: 'AbpIdentity.Users.ManagePermissions',
},
{
text: 'AbpIdentity::ChangeHistory',
action: data => {
const showHistory = data.getInjected(SHOW_ENTITY_HISTORY);
showHistory(data.record.id, 'Volo.Abp.Identity.IdentityUser');
},
permission: 'AuditLogging.ViewChangeHistory:Volo.Abp.Identity.IdentityUser',
visible: data => Boolean(data.getInjected(SHOW_ENTITY_HISTORY, null)),
},
{
text: 'AbpIdentity::SetPassword',
action: data => {
const component = data.getInjected(UsersComponent);
component.selected = data.record;
component.isSetPasswordModalVisible = true;
},
permission: 'AbpIdentity.Users.Update',
},
{
text: 'AbpIdentity::TwoFactor',
action: data => {
const component = data.getInjected(UsersComponent);
component.selected = data.record;
component.service.getTwoFactorEnabled(data.record.id).subscribe(res => {
component.twoFactor.checkboxValue = res;
component.twoFactor.isModalVisible = true;
});
},
permission: 'AbpIdentity.Users.Update',
visible: data => data.getInjected(UsersComponent).twoFactor.isOptional,
},
{
text: 'AbpIdentity::LoginWithThisUser',
permission: 'AbpIdentity.Users.Impersonation',
action: data => {
const impersonation = data.getInjected(ImpersonationService);
impersonation.impersonateUser(data.record.id).subscribe();
},
visible: data => {
const configState = data.getInjected(ConfigStateService);
const currentUserId = configState.getDeep('currentUser.id');
const currentImpersonatorUserId = configState.getDeep('currentUser.impersonatorUserId');
return data.record.id !== currentUserId && currentImpersonatorUserId === null;
},
},
{
text: 'AbpUi::Delete',
action: data => {
const component = data.getInjected(UsersComponent);
component.delete(data.record.id, data.record.name || data.record.userName);
},
permission: 'AbpIdentity.Users.Delete',
},
]);
In this case, you will need to customize the entity actions to manage this. Here is the related documentation that explains the procedure step by step
https://docs.abp.io/en/abp/latest/UI/Angular/Entity-Action-Extensions
Hello again. Thank you for providing more details. Can you also clarify whether the file management module that we are providing malfunctioning? If it is working properly for the version that you are using, we can assist you further.
If your aim is to use a custom URL or a component to reach a folder detail inside the file management module implementation, just using goToFolder
function inside NavigationService
would be the solution.
goToFolder(folder: FolderInfo) {
this.currentFolder$.next(folder || ROOT_NODE);
this.updateCurrentFolderPath(folder);
}
This function expects the FolderInfo
object that would handle both the breadcrumb and navigation once you give the right folder object. If you think that you need to customize this functionality you can get the source code and investigate further. Another possibility would be an error on change detection trigger flow that you need to manage.
Hello, we could not quite reproduce the same issue. Do you claim that you are using the module directly or did you implement some sort of reference and set up a separate structure? That would be the best if you could provide us a screenshot or more details.
Thank you in advance.
Hello Viktor, both Login with this user and Login buttons use impersonation technique either by sending the user id or the delegated user id.
In order to customize and manage these functionalities, we recommend you to use the functions inside ImpersonationService
(https://docs.abp.io/en/commercial/latest/modules/account/impersonation#angular).
If you need further customization, you can also utilize the loginUsingGrant
function inside the AuthService
Because, this function handles the request by getting the parameter object that would contain the necessary id and a grant type like Impersonation.
(https://github.com/abpframework/abp/blob/dev/npm/ng-packs/packages/core/src/lib/abstracts/auth.service.ts)
Hello, you can try customizing the default css values inside your global css file as follows,
.lpx-content-container .lpx-content {
padding: 1.25em 1.5em 1.5em;
margin: 0 auto;
}