Skip to content

Commit

Permalink
feat: live update after activate or deactivate user (#350)
Browse files Browse the repository at this point in the history
(cherry picked from commit d05b4aa)
  • Loading branch information
illfixit authored and kamilczaja committed Dec 3, 2024
1 parent 1b74218 commit 1a560c1
Show file tree
Hide file tree
Showing 7 changed files with 87 additions and 12 deletions.
15 changes: 13 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,22 +11,33 @@ please see [changelog_updates.md](docs/dev/changelog_updates.md).

#### Major

- The Catalog Crawler has been moved to the AP repository.

#### Minor

#### Patch

- Added documentation for roles and rights ([#334](https://github.com/sovity/authority-portal/issues/334))
- Fixed Confirm and Delete buttons' behavior in confirmation modals ([#304](https://github.com/sovity/authority-portal/issues/304))
- Fixed final step not showing when registering a central component ([#305](https://github.com/sovity/authority-portal/issues/305))
- Fixed My Organization page not updated when switching between environments ([#255](https://github.com/sovity/authority-portal/issues/255))
- Added live update when deactivating/reactivating users ([#287](https://github.com/sovity/authority-portal/issues/287))
- Fixed Website title not updating in some scenarios [#237](https://github.com/sovity/authority-portal/issues/237)
- Fixed security vulnerabilities

### Known issues

### Deployment Migration Notes

- The Crawler image name and version changed due to the crawler being moved into the AP repository and versions being aligned
- Previously: `ghcr.io/sovity/catalog-crawler-ce`
- Now: `ghcr.io/sovity/authority-portal-crawler`

#### Compatible Versions

- Authority Portal Backend Docker Image: `ghcr.io/sovity/authority-portal-backend:{{ version }}`
- Authority Portal Frontend Docker Image: `ghcr.io/sovity/authority-portal-frontend:{{ version }}`
- Catalog Crawler CE: `ghcr.io/sovity/catalog-crawler-ce:{{ CE VERSION }}`
- Catalog Crawler CE: `ghcr.io/sovity/authority-portal-crawler:{{ version }}`
- Sovity EDC CE: {{ CE Release Link }}

## [v4.1.2] - 2024-09-26
Expand Down Expand Up @@ -253,7 +264,7 @@ MDS 2.2 intermediate release

- All brokers can be undeployed including their databases.
- Keycloak
- Keycloak IAM must be updated to version `24.0.4`. Follow the [Keycloak upgrade guide](https://www.keycloak.org/docs/24.0.0/upgrading/) for more information.
- Keycloak IAM must be updated to version `24.0.4`. Follow the [Keycloak upgrade guide](https://www.keycloak.org/docs/24.0.5/upgrading/index.html) for more information.
- Portal Backend

- Following environment variables have been added and **must be configured** for each environment
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -166,11 +166,13 @@ export const AUTHORITY_PORTAL_FAKE_BACKEND: FetchAPI = async (

.url('authority/users/*/deactivate')
.on('PUT', (userId) => {
deactivateUser(userId);
return ok(userId);
})

.url('authority/users/*/reactivate')
.on('PUT', (userId) => {
reactivateUser(userId);
return ok(userId);
})

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -551,6 +551,14 @@ export const getOrganizationDetails = (
) as OrganizationDetailsDto;
};

export const findOrganizationByUserId = (
userId: string,
): string | undefined => {
return TEST_ORGANIZATIONS.find((organization) =>
organization.memberList.some((member) => member.userId === userId),
)?.id;
};

export const getOrganizations = (): OrganizationDetailsDto[] => {
return TEST_ORGANIZATIONS;
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import {
UserDeletionCheck,
UserDetailDto,
UserInfo,
UserRegistrationStatusDto,
UserRoleDto,
} from '@sovity.de/authority-portal-client';
import {Patcher, patchObj} from 'src/app/core/utils/object-utils';
Expand All @@ -32,6 +33,7 @@ import {
} from '../../../utils/user-role-utils';
import {
deleteOrganization,
findOrganizationByUserId,
getOrganizationDetails,
getParticipantAdmins,
updateOrganization,
Expand Down Expand Up @@ -447,12 +449,37 @@ export const clearApplicationRole = (
return {id: request.userId, changedDate: new Date()};
};

const updateUserStatusOfOrganizationById = (
userId: string,
status: UserRegistrationStatusDto,
) => {
const organizationId = findOrganizationByUserId(userId);
if (organizationId) {
updateOrganization(organizationId, (organization) => {
return {
...organization,
memberList: organization.memberList.map((member) => {
if (member.userId === userId) {
return {
...member,
registrationStatus: status,
};
}
return member;
}),
};
});
}
};

export const deactivateUser = (userId: string): IdResponse => {
updateUserStatusOfOrganizationById(userId, 'DEACTIVATED');
patchUser(userId, () => ({registrationStatus: 'DEACTIVATED'}));
return {id: userId, changedDate: new Date()};
};

export const reactivateUser = (userId: string): IdResponse => {
updateUserStatusOfOrganizationById(userId, 'ACTIVE');
patchUser(userId, () => ({registrationStatus: 'ACTIVE'}));
return {id: userId, changedDate: new Date()};
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -278,7 +278,7 @@ export class AuthorityOrganizationDetailPageComponent
this.store.dispatch(RefreshOrganizations);
} else {
this.store
.dispatch(RefreshOrganization)
.dispatch(new RefreshOrganization())
.pipe(take(1))
.subscribe(() => {
this.slideOverService.setSlideOverViews(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ export class SetOrganizationId {

export class RefreshOrganization {
static readonly type = `[${tag}] Refresh Organization`;
constructor(public cb?: () => void) {}
}

export class ApproveOrganization {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import {SlideOverService} from 'src/app/core/services/slide-over.service';
import {Fetched} from 'src/app/core/utils/fetched';
import {ToastService} from 'src/app/shared/common/toast-notifications/toast.service';
import {RefreshOrganizations} from '../../authority-organization-list-page/authority-organization-list-page/state/authority-organization-list-page-actions';
import {AuthorityOrganizationDetailTab} from '../authority-organization-detail-page/authority-organization-detail-page.model';
import {
ApproveOrganization,
DeactivateUser,
Expand Down Expand Up @@ -82,6 +83,7 @@ export class AuthorityOrganizationDetailPageStateImpl {
@Action(RefreshOrganization, {cancelUncompleted: true})
onRefreshOrganization(
ctx: StateContext<AuthorityOrganizationDetailPageState>,
action: RefreshOrganization,
): Observable<never> {
return this.globalStateUtils.getDeploymentEnvironmentId().pipe(
switchMap((deploymentEnvironmentId) =>
Expand All @@ -91,20 +93,26 @@ export class AuthorityOrganizationDetailPageStateImpl {
),
),
Fetched.wrap({failureMessage: 'Failed loading organizations'}),
tap((organization) => this.organizationRefreshed(ctx, organization)),
tap((organization) =>
this.organizationRefreshed(ctx, organization, action.cb),
),
ignoreElements(),
);
}

private organizationRefreshed(
ctx: StateContext<AuthorityOrganizationDetailPageState>,
organization: Fetched<OrganizationDetailsDto>,
cb?: () => void,
) {
this.globalStateUtils.updateNestedProperty(
ctx,
'organizationDetail.organization',
organization,
);
if (cb) {
cb();
}
}

@Action(ApproveOrganization)
Expand Down Expand Up @@ -251,6 +259,13 @@ export class AuthorityOrganizationDetailPageStateImpl {
);
}

redirectToMembersTab() {
this.slideOverService.setSlideOverViews(
{viewName: AuthorityOrganizationDetailTab.MEMBERS},
{viewName: AuthorityOrganizationDetailTab.DETAIL},
);
}

@Action(DeactivateUser)
onDeactivateUser(
ctx: StateContext<AuthorityOrganizationDetailPageState>,
Expand All @@ -275,13 +290,19 @@ export class AuthorityOrganizationDetailPageStateImpl {
this.toast.showSuccess(`User deactivated successfully`);
this.organizationUserRefreshed(ctx, Fetched.ready(data));
}),
finalize(() =>
this.globalStateUtils.updateNestedProperty(
finalize(() => {
ctx.dispatch(
new RefreshOrganization(() => {
this.redirectToMembersTab();
}),
);

return this.globalStateUtils.updateNestedProperty(
ctx,
'openedUserDetail.busy',
false,
),
),
);
}),
ignoreElements(),
);
}
Expand Down Expand Up @@ -310,13 +331,18 @@ export class AuthorityOrganizationDetailPageStateImpl {
this.toast.showSuccess(`User re-activated successfully`);
this.organizationUserRefreshed(ctx, Fetched.ready(data));
}),
finalize(() =>
this.globalStateUtils.updateNestedProperty(
finalize(() => {
ctx.dispatch(
new RefreshOrganization(() => {
this.redirectToMembersTab();
}),
);
return this.globalStateUtils.updateNestedProperty(
ctx,
'openedUserDetail.busy',
false,
),
),
);
}),
ignoreElements(),
);
}
Expand Down

0 comments on commit 1a560c1

Please sign in to comment.