Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/main' into 60-remove-link-to-fro…
Browse files Browse the repository at this point in the history
…ntend-url-in-all-connectors-view-for-authority-and-operator-admins
  • Loading branch information
PaddseL committed Dec 17, 2024
2 parents baab609 + 6f75f02 commit c57ec25
Show file tree
Hide file tree
Showing 13 changed files with 186 additions and 8 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ please see [changelog_updates.md](docs/dev/changelog_updates.md).

- Uptime Kuma is no longer mandatory and the status dashboard can be disabled
- Added Owning Organization in Admin Connector Overview ([#355](https://github.com/sovity/authority-portal/issues/355))
- Added a button to change the password in the user settings ([PR #397](https://github.com/sovity/authority-portal/pull/397))
- Removed link to frontend URL in all-connectors-view for authority- and operator admins ([PR #398](https://github.com/sovity/authority-portal/pull/398))

#### Patch
Expand All @@ -33,6 +34,7 @@ please see [changelog_updates.md](docs/dev/changelog_updates.md).
- Fixed an issue wherein a user registration could fail due to a mismatch of the internal database and the Keycloak database
- Fixed an issue where entries in the connector overview would randomly switch places ([PR #386](https://github.com/sovity/authority-portal/pull/386))
- Changed Client ID generation for Connectors & Central Components ([#327](https://github.com/sovity/authority-portal/issues/327))
- Fixed an issue wherein a user could not be deleted if their organization had provided connectors to another participant ([PR #400](https://github.com/sovity/authority-portal/pull/400))

### Known issues

Expand All @@ -55,6 +57,8 @@ please see [changelog_updates.md](docs/dev/changelog_updates.md).
```yaml
# Enables or disables the status uptime dashboard
AUTHORITY_PORTAL_FRONTEND_ENABLE_DASHBOARD: true
# Direct URL to the UPDATE_PASSWORD required action in Keycloak
AUTHORITY_PORTAL_FRONTEND_UPDATE_PASSWORD_URL: https://[KC_FQDN]/realms/authority-portal/protocol/openid-connect/auth?response_type=code&client_id=oauth2-proxy&scope=openid&kc_action=UPDATE_PASSWORD&redirect_uri=[AP_FQDN_URL_ENCODED]%2Foauth2%2Fcallback
```
#### Compatible Versions
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
alter table connector alter column created_by drop not null;
Original file line number Diff line number Diff line change
Expand Up @@ -102,11 +102,12 @@ class UserDeletionApiService(
userService.deleteInvitationReferencesToOrgMembers(orgMemberIds)
userService.deleteOrganizationIds(orgMemberIds)

keycloakService.deleteOrganization(organizationId)
organizationService.deleteOrganization(organizationId)
keycloakService.deleteUsers(orgMemberIds)
userService.deleteUsers(orgMemberIds)

keycloakService.deleteUsers(orgMemberIds)
keycloakService.deleteOrganization(organizationId)

Log.info(
"Organization and related users, connectors and central components deleted. " +
"organization=${organizationId}, adminUserId=$adminUserId."
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@ class ConnectorService(
val c = Tables.CONNECTOR
dsl.update(c)
.setNull(c.PROVIDER_ORGANIZATION_ID)
.setNull(c.CREATED_BY)
.where(c.PROVIDER_ORGANIZATION_ID.eq(organizationId))
.execute()
}
Expand Down
20 changes: 18 additions & 2 deletions authority-portal-frontend/src/app/app-routing.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@
* Contributors:
* sovity GmbH - initial implementation
*/
import {NgModule, Type} from '@angular/core';
import {RouterModule, Routes} from '@angular/router';
import {InjectionToken, NgModule, Type} from '@angular/core';
import {ActivatedRouteSnapshot, RouterModule, Routes} from '@angular/router';
import {UserRoleDto} from '@sovity.de/authority-portal-client';
import {requiresRole} from './core/services/auth/requires-role-guard';
import {AuthorityConnectorListPageComponent} from './pages/authority-connector-list-page/authority-connector-list-page/authority-connector-list-page.component';
Expand Down Expand Up @@ -41,6 +41,8 @@ import {OrganizationRejectedPageComponent} from './pages/registration-pages/orga
import {SpConnectorListPageComponent} from './pages/sp-connector-list-page/sp-connector-list-page/sp-connector-list-page.component';
import {PortalLayoutComponent} from './shared/common/portal-layout/portal-layout/portal-layout.component';

const EXTERNAL_URL_PROVIDER = new InjectionToken('externalRedirectProvider');

export const UNAUTHENTICATED_ROUTES: Routes = [
{
path: 'create-organization',
Expand Down Expand Up @@ -301,6 +303,11 @@ export const AUTHORITY_PORTAL_ROUTES: Routes = [
},
],
},
{
path: 'externalRedirect',
canActivate: [EXTERNAL_URL_PROVIDER],
component: PageNotFoundPageComponent,
},
{
path: '**',
component: PageNotFoundPageComponent,
Expand All @@ -324,5 +331,14 @@ function singleComponent(path: string, component: Type<any>): Routes {
@NgModule({
imports: [RouterModule.forRoot(LOADING_ROUTES)],
exports: [RouterModule],
providers: [
{
provide: EXTERNAL_URL_PROVIDER,
useValue: (route: ActivatedRouteSnapshot) => {
const externalUrl = route.paramMap.get('externalUrl');
window.open(externalUrl!!, '_self');
},
},
],
})
export class AppRoutingModule {}
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ export interface AppConfig {
backendUrl: string;
loginUrl: string;
logoutUrl: string;
updatePasswordUrl: string;
invalidateSessionCookiesUrl: string;
useFakeBackend: boolean;
useLocalBackend: boolean;
Expand All @@ -70,6 +71,7 @@ export interface AppConfigEnv {
AUTHORITY_PORTAL_FRONTEND_BACKEND_URL: string;
AUTHORITY_PORTAL_FRONTEND_LOGIN_URL: string;
AUTHORITY_PORTAL_FRONTEND_LOGOUT_URL: string;
AUTHORITY_PORTAL_FRONTEND_UPDATE_PASSWORD_URL: string;
AUTHORITY_PORTAL_FRONTEND_USE_FAKE_BACKEND: string;
AUTHORITY_PORTAL_FRONTEND_USE_LOCAL_BACKEND: string;
AUTHORITY_PORTAL_FRONTEND_INVALIDATE_SESSION_COOKIES_URL: string;
Expand Down Expand Up @@ -99,6 +101,7 @@ export function buildAppConfig(envVars: AppConfigEnv): AppConfig {
backendUrl: envVars.AUTHORITY_PORTAL_FRONTEND_BACKEND_URL,
loginUrl: envVars.AUTHORITY_PORTAL_FRONTEND_LOGIN_URL,
logoutUrl: envVars.AUTHORITY_PORTAL_FRONTEND_LOGOUT_URL,
updatePasswordUrl: envVars.AUTHORITY_PORTAL_FRONTEND_UPDATE_PASSWORD_URL,
invalidateSessionCookiesUrl:
envVars.AUTHORITY_PORTAL_FRONTEND_INVALIDATE_SESSION_COOKIES_URL,
useFakeBackend:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,9 @@
* Contributors:
* sovity GmbH - initial implementation
*/
import {Injectable} from '@angular/core';
import {Inject, Injectable} from '@angular/core';
import {FormBuilder} from '@angular/forms';
import {Router} from '@angular/router';
import {Observable} from 'rxjs';
import {ignoreElements, switchMap, take, tap} from 'rxjs/operators';
import {Action, State, StateContext} from '@ngxs/store';
Expand All @@ -20,6 +21,7 @@ import {ApiService} from 'src/app/core/api/api.service';
import {GlobalStateUtils} from 'src/app/core/global-state/global-state-utils';
import {CustomRxjsOperators} from 'src/app/core/services/custom-rxjs-operators';
import {Fetched} from 'src/app/core/utils/fetched';
import {APP_CONFIG, AppConfig} from '../../../core/services/config/app-config';
import {HeaderBarConfig} from '../../../shared/common/header-bar/header-bar.model';
import {ControlCenterUserEditPageForm} from '../control-center-user-edit-page/control-center-user-edit-page.form';
import {
Expand All @@ -45,6 +47,8 @@ export class ControlCenterUserEditPageStateImpl {
private formBuilder: FormBuilder,
private customRxjsOperators: CustomRxjsOperators,
private globalStateUtils: GlobalStateUtils,
private router: Router,
@Inject(APP_CONFIG) private appConfig: AppConfig,
) {}

@Action(Reset)
Expand Down Expand Up @@ -89,7 +93,23 @@ export class ControlCenterUserEditPageStateImpl {
return {
title: `${user.firstName} ${user.lastName}`,
subtitle: 'Edit Your Profile Information',
headerActions: [],
headerActions: [
{
label: 'Change Password',
action: () => {
this.router.navigate(
[
'/externalRedirect',
{externalUrl: this.appConfig.updatePasswordUrl},
],
{
skipLocationChange: true,
},
);
},
permissions: ['USER'],
},
],
};
}
private rebuildForm(data: UserDetailDto): ControlCenterUserEditPageForm {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/*
* Copyright (c) 2024 sovity GmbH
*
* This program and the accompanying materials are made available under the
* terms of the Apache License, Version 2.0 which is available at
* https://www.apache.org/licenses/LICENSE-2.0
*
* SPDX-License-Identifier: Apache-2.0
*
* Contributors:
* sovity GmbH - initial implementation
*/
import {ElementRef, HostListener} from '@angular/core';
import {Router} from '@angular/router';

export class ExternalUrlDirective {
constructor(private el: ElementRef, private router: Router) {}

@HostListener('click', ['$event'])
clicked(event: Event) {
const url = this.el.nativeElement.href;

if (!url) {
return;
}

this.router.navigate(['/externalRedirect', {externalUrl: url}], {
skipLocationChange: true,
});

event.preventDefault();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
<#import "template.ftl" as layout>
<#import "password-commons.ftl" as passwordCommons>
<@layout.registrationLayout displayMessage=!messagesPerField.existsError('password','password-confirm'); section>
<#if section = "header">
${msg("updatePasswordTitle")}
<#elseif section = "form">
<form id="kc-passwd-update-form" class="${properties.kcFormClass!}" action="${url.loginAction}" method="post">
<div class="${properties.kcFormGroupClass!}">
<input type="password" id="password-new" name="password-new" class="text-input"
autofocus autocomplete="new-password" placeholder="New Password"
aria-invalid="<#if messagesPerField.existsError('password','password-confirm')>true</#if>"
/>
</div>

<#if messagesPerField.existsError('password')>
<span id="input-error-password" class="${properties.kcInputErrorMessageClass!}" aria-live="polite">
${kcSanitize(messagesPerField.get('password'))?no_esc}
</span>
</#if>

<div class="${properties.kcFormGroupClass!}">
<input type="password" id="password-confirm" name="password-confirm"
class="text-input"
autocomplete="new-password" placeholder="Confirm Password"
aria-invalid="<#if messagesPerField.existsError('password-confirm')>true</#if>"
/>
</div>

<#if messagesPerField.existsError('password-confirm')>
<span id="input-error-password-confirm" class="${properties.kcInputErrorMessageClass!}"
aria-live="polite">
${kcSanitize(messagesPerField.get('password-confirm'))?no_esc}
</span>
</#if>

<div class="${properties.kcFormGroupClass!}">
<@passwordCommons.logoutOtherSessions/>

<div id="kc-form-buttons" class="${properties.kcFormButtonsClass!}">
<#if isAppInitiatedAction??>
<input class="${properties.kcButtonClass!} ${properties.kcButtonPrimaryClass!} ${properties.kcButtonLargeClass!} ${properties.kcButtonBlockClass!}"
type="submit" value="${msg("doSubmit")}"/>
<button
class="${properties.kcButtonClass!} ${properties.kcButtonCancelClass!} ${properties.kcButtonLargeClass!} ${properties.kcButtonBlockClass!}"
type="submit" name="cancel-aia" value="true" />${msg("doCancel")}</button>
<#else>
<input class="${properties.kcButtonClass!} ${properties.kcButtonPrimaryClass!} ${properties.kcButtonBlockClass!} ${properties.kcButtonLargeClass!} ${properties.kcButtonFullWidthClass!}"
type="submit" value="${msg("doSubmit")}"/>
</#if>
</div>
</div>
</form>
</#if>
</@layout.registrationLayout>
12 changes: 12 additions & 0 deletions authority-portal-keycloak/sovity-theme/login/password-commons.ftl
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<#macro logoutOtherSessions>
<div id="kc-form-options" class="${properties.kcFormOptionsClass!}">
<div class="${properties.kcFormOptionsWrapperClass!}">
<div class="checkbox">
<label>
<input type="checkbox" id="logout-sessions" name="logout-sessions" value="on" checked>
${msg("logoutOtherSessions")}
</label>
</div>
</div>
</div>
</#macro>
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,25 @@ a:hover {
color: rgb(93 169 255) !important;
}

.cancel-button {
display: block;
background-color: white !important;
color: black;
text-transform: uppercase;
border-radius: 0.25rem;
line-height: 1;
height: 2.5em;
margin: 1rem auto 0;
padding: 0 5em 0 5em;
border: none;
cursor: pointer;
transition: all 0.2s ease-in-out;
}

.cancel-button:hover {
color: rgb(93 169 255) !important;
}

/* default - IE compatibility */
.pf-c-button.pf-m-control {
border: solid 1px;
Expand Down Expand Up @@ -338,7 +357,7 @@ div.form-group.login-pf-settings {
.pf-c-button.pf-m-primary.pf-m-block.btn-lg {
margin-top: 10px !important;
margin-bottom: 10px !important;
max-width: 211px;
width: 200px;
height: 40px;
background-color: black;
color: white;
Expand All @@ -347,6 +366,16 @@ div.form-group.login-pf-settings {
line-height: 17px;
}

.pf-c-button.cancel-button.pf-m-block.btn-lg {
margin-top: 10px !important;
margin-bottom: 10px !important;
width: 200px;
height: 40px;
font-weight: 600;
font-size: 14px;
line-height: 17px;
}

.kc-registration-container.a:link {
color: white !important;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,8 @@ kcInfoAreaClass=col-xs-12 col-sm-4 col-md-4 col-lg-5 details
kcButtonClass=pf-c-button
# classes defining priority of the button - primary or default (there is typically only one priority button for the form)
kcButtonPrimaryClass=pf-m-primary
kcButtonDefaultClass=btn-default
kcButtonCancelClass=cancel-button
kcButtonDefaultClass=pf-c-button
# classes defining size of the button
kcButtonLargeClass=btn-lg
kcButtonBlockClass=pf-m-block
Expand Down
3 changes: 3 additions & 0 deletions docs/deployment-guide/goals/production/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -315,6 +315,9 @@ AUTHORITY_PORTAL_FRONTEND_ACTIVE_PROFILE: sovity-open-source # UI Branding profi
AUTHORITY_PORTAL_FRONTEND_DATASPACE_SHORT_NAME: ExDS # Short Dataspace name, used in some explanatory texts
AUTHORITY_PORTAL_FRONTEND_PORTAL_DISPLAY_NAME: "Authority Portal" # Portal name displayed in various texts
AUTHORITY_PORTAL_FRONTEND_ENABLE_DASHBOARD: true # Enables or disables the status uptime dashboard
# Direct URL to the UPDATE_PASSWORD required action in Keycloak
AUTHORITY_PORTAL_FRONTEND_UPDATE_PASSWORD_URL: https://[KC_FQDN]/realms/authority-portal/protocol/openid-connect/auth?response_type=code&client_id=oauth2-proxy&scope=openid&kc_action=UPDATE_PASSWORD&redirect_uri=https%3A%2F%2F[AP_FQDN]%2Foauth2%2Fcallback
```

### Data Catalog Crawlers
Expand Down

0 comments on commit c57ec25

Please sign in to comment.