Skip to content

Commit

Permalink
Merge pull request #1039 from geonetwork/ME-logout
Browse files Browse the repository at this point in the history
[Editor]: Allow logging out
  • Loading branch information
cmoinier authored Nov 25, 2024
2 parents d6fa0bf + 08547bb commit 67cb636
Show file tree
Hide file tree
Showing 20 changed files with 119 additions and 13 deletions.
24 changes: 19 additions & 5 deletions apps/metadata-editor-e2e/src/e2e/dashboard.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -344,11 +344,25 @@ describe('dashboard (authenticated)', () => {
})
})

describe('when the user is not logged in', () => {
beforeEach(() => {
cy.visit('/catalog/search')
describe('Logging in and out', () => {
describe('when the user is not logged in', () => {
beforeEach(() => {
cy.visit('/catalog/search')
})
it('redirects to the login page', () => {
cy.url().should('include', '/catalog.signin?redirect=')
})
})
it('redirects to the login page', () => {
cy.url().should('include', '/catalog.signin?redirect=')
describe('Logging out', () => {
beforeEach(() => {
cy.login('admin', 'admin', false)
cy.visit('/catalog/search')
})
it('logs out the user', () => {
cy.get('gn-ui-avatar').should('be.visible')
cy.get('md-editor-sidebar').find('gn-ui-button').eq(1).click()
cy.url().should('include', '/catalog.signin?redirect=')
cy.get('gn-ui-avatar').should('not.exist')
})
})
})
5 changes: 5 additions & 0 deletions apps/metadata-editor/src/app/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import { DashboardPageComponent } from './dashboard/dashboard-page.component'
import { EditorRouterService } from './router.service'
import {
LOGIN_URL,
LOGOUT_URL,
provideGn4,
provideRepositoryUrl,
} from '@geonetwork-ui/api/repository'
Expand Down Expand Up @@ -70,6 +71,10 @@ import { FeatureEditorModule } from '@geonetwork-ui/feature/editor'
provide: LOGIN_URL,
useFactory: () => getGlobalConfig().LOGIN_URL,
},
{
provide: LOGOUT_URL,
useFactory: () => getGlobalConfig().LOGOUT_URL,
},
],
bootstrap: [AppComponent],
})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,14 @@
<gn-ui-button
type="default"
class="w-10 h-10 flex justify-center items-center hover:cursor-pointer"
(click)="logOut()"
>
<img src="assets/system-shut.svg" alt="Log out" class="w-4 h-4" />
<img
src="assets/system-shut.svg"
[alt]="'editor.sidebar.logout' | translate"
[title]="'editor.sidebar.logout' | translate"
class="w-4 h-4 hover:invert-[.5]"
/>
</gn-ui-button>
</div>
</ng-container>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,19 +1,27 @@
import { ComponentFixture, TestBed } from '@angular/core/testing'
import { AvatarServiceInterface } from '@geonetwork-ui/api/repository'
import {
AuthService,
AvatarServiceInterface,
} from '@geonetwork-ui/api/repository'
import { OrganizationsServiceInterface } from '@geonetwork-ui/common/domain/organizations.service.interface'
import { PlatformServiceInterface } from '@geonetwork-ui/common/domain/platform.service.interface'
import { TranslateModule } from '@ngx-translate/core'
import { MockBuilder, MockProviders } from 'ng-mocks'
import { MockBuilder, MockProvider, MockProviders } from 'ng-mocks'
import { SidebarComponent } from './sidebar.component'

describe('SidebarComponent', () => {
let component: SidebarComponent
let fixture: ComponentFixture<SidebarComponent>
let service: AuthService

beforeEach(() => {
return MockBuilder(SidebarComponent)
})

afterEach(() => {
jest.resetAllMocks()
})

beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [SidebarComponent, TranslateModule.forRoot()],
Expand All @@ -23,9 +31,13 @@ describe('SidebarComponent', () => {
AvatarServiceInterface,
OrganizationsServiceInterface
),
MockProvider(AuthService, {
logoutUrl: 'http://logout.com/bla?',
}),
],
}).compileComponents()

service = TestBed.inject(AuthService)
fixture = TestBed.createComponent(SidebarComponent)
component = fixture.componentInstance
fixture.detectChanges()
Expand All @@ -34,4 +46,21 @@ describe('SidebarComponent', () => {
it('should create', () => {
expect(component).toBeTruthy()
})

describe('logOut', () => {
it('should log out', async () => {
jest.spyOn(window, 'fetch').mockResolvedValue({
ok: true,
} as Response)

const originalUrl = window.origin

await component.logOut()

expect(window.fetch).toHaveBeenCalledWith(service.logoutUrl, {
method: 'GET',
})
expect(window.location.href.slice(0, -1)).toBe(originalUrl)
})
})
})
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@ import { ChangeDetectionStrategy, Component, OnInit } from '@angular/core'
import { TranslateModule } from '@ngx-translate/core'
import { DashboardMenuComponent } from '../dashboard-menu/dashboard-menu.component'
import { PlatformServiceInterface } from '@geonetwork-ui/common/domain/platform.service.interface'
import { AvatarServiceInterface } from '@geonetwork-ui/api/repository'
import {
AuthService,
AvatarServiceInterface,
} from '@geonetwork-ui/api/repository'
import { LetDirective } from '@ngrx/component'
import { UiElementsModule } from '@geonetwork-ui/ui/elements'
import { OrganizationsServiceInterface } from '@geonetwork-ui/common/domain/organizations.service.interface'
Expand Down Expand Up @@ -31,7 +34,8 @@ export class SidebarComponent implements OnInit {
constructor(
public platformService: PlatformServiceInterface,
private avatarService: AvatarServiceInterface,
public organisationsService: OrganizationsServiceInterface
public organisationsService: OrganizationsServiceInterface,
private authService: AuthService
) {}

ngOnInit(): void {
Expand All @@ -41,4 +45,21 @@ export class SidebarComponent implements OnInit {
(orgs, me) => orgs.filter((org) => org.name === me?.organisation)
)
}

logOut() {
const current_url = window.origin.toString()
fetch(this.authService.logoutUrl, {
method: 'GET',
})
.then((response) => {
if (response.ok) {
window.location.href = current_url
} else {
console.error('Logout failed')
}
})
.catch((error) => {
console.error('Error during logout request:', error)
})
}
}
1 change: 1 addition & 0 deletions conf/default.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ proxy_path = ""
# - ${lang2}, ${lang3}: indicates if and where the current language should be part of the login URL in language 2 or 3 letter code
# Example to use the georchestra login page:
# login_url = "/cas/login?service=${current_url}"
# logout_url = "/geonetwork/signout"
# This optional URL should point to the static html page wc-embedder.html which allows to display a web component (like chart and table) via a permalink.
# URLs can be indicated from the root of the same server starting with a "/" or as an external URL. Be conscious of potential CORS issues when using an external URL.
# The default location in the dockerized datahub app for example is "/datahub/wc-embedder.html".
Expand Down
9 changes: 9 additions & 0 deletions libs/api/repository/src/lib/gn4/auth/auth.service.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -82,4 +82,13 @@ describe('AuthService', () => {
)
})
})

describe('Logout', () => {
beforeEach(() => {
service = TestBed.inject(AuthService)
})
it('should return the logout url', () => {
expect(service.logoutUrl).toEqual('/geonetwork/signout')
})
})
})
14 changes: 11 additions & 3 deletions libs/api/repository/src/lib/gn4/auth/auth.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,15 @@ import { TranslateService } from '@ngx-translate/core'
export const DEFAULT_GN4_LOGIN_URL = `/geonetwork/srv/\${lang3}/catalog.signin?redirect=\${current_url}`
export const LOGIN_URL = new InjectionToken<string>('loginUrl')

export const DEFAULT_GN4_LOGOUT_URL = `/geonetwork/signout`
export const LOGOUT_URL = new InjectionToken<string>('logoutUrl')

@Injectable({
providedIn: 'root',
})
export class AuthService {
baseLoginUrl = this.baseLoginUrlToken || DEFAULT_GN4_LOGIN_URL
baseLogoutUrl = this.baseLogoutUrlToken || DEFAULT_GN4_LOGOUT_URL
get loginUrl() {
let baseUrl = this.baseLoginUrl
const locationHasQueryParams = !!window.location.search
Expand All @@ -25,10 +29,14 @@ export class AuthService {
LANG_2_TO_3_MAPPER[this.translateService.currentLang]
)
}

get logoutUrl() {
return this.baseLogoutUrl
}

constructor(
@Optional()
@Inject(LOGIN_URL)
private baseLoginUrlToken: string,
@Optional() @Inject(LOGIN_URL) private baseLoginUrlToken: string,
@Optional() @Inject(LOGOUT_URL) private baseLogoutUrlToken: string,
private translateService: TranslateService
) {}
}
1 change: 1 addition & 0 deletions libs/util/app-config/src/lib/app-config.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,7 @@ describe('app config utils', () => {
PROXY_PATH: '/proxy/?url=',
METADATA_LANGUAGE: 'fre',
LOGIN_URL: '/cas/login?service=',
LOGOUT_URL: '/geonetwork/signout',
WEB_COMPONENT_EMBEDDER_URL: '/datahub/wc-embedder.html',
})
})
Expand Down
2 changes: 2 additions & 0 deletions libs/util/app-config/src/lib/app-config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ export function loadAppConfig() {
'proxy_path',
'metadata_language',
'login_url',
'logout_url',
'web_component_embedder_url',
'languages',
'contact_email',
Expand All @@ -124,6 +125,7 @@ export function loadAppConfig() {
).toLowerCase()
: undefined,
LOGIN_URL: parsedGlobalSection.login_url,
LOGOUT_URL: parsedGlobalSection.logout_url,
WEB_COMPONENT_EMBEDDER_URL:
parsedGlobalSection.web_component_embedder_url,
LANGUAGES: parsedGlobalSection.languages,
Expand Down
1 change: 1 addition & 0 deletions libs/util/app-config/src/lib/fixtures.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ geonetwork4_api_url = "/geonetwork/srv/api"
proxy_path = "/proxy/?url="
metadata_language = "fre"
login_url = "/cas/login?service="
logout_url = "/geonetwork/signout"
web_component_embedder_url = "/datahub/wc-embedder.html"
[map]
Expand Down
1 change: 1 addition & 0 deletions libs/util/app-config/src/lib/model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ export interface GlobalConfig {
PROXY_PATH?: string
METADATA_LANGUAGE?: string
LOGIN_URL?: string
LOGOUT_URL?: string
WEB_COMPONENT_EMBEDDER_URL?: string
LANGUAGES?: string[]
CONTACT_EMAIL?: string
Expand Down
1 change: 1 addition & 0 deletions translations/de.json
Original file line number Diff line number Diff line change
Expand Up @@ -313,6 +313,7 @@
"editor.record.undo.tooltip.disabled": "",
"editor.record.undo.tooltip.enabled": "",
"editor.record.upToDate": "Dieser Datensatz ist auf dem neuesten Stand",
"editor.sidebar.logout": "",
"editor.sidebar.menu.editor": "",
"editor.temporary.disabled": "",
"externalviewer.dataset.unnamed": "Datensatz aus dem Datahub",
Expand Down
1 change: 1 addition & 0 deletions translations/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -313,6 +313,7 @@
"editor.record.undo.tooltip.disabled": "There are no pending changes on this record",
"editor.record.undo.tooltip.enabled": "Clicking this button will cancel the pending changes on this record.",
"editor.record.upToDate": "This record is up to date",
"editor.sidebar.logout": "Log out",
"editor.sidebar.menu.editor": "Editor",
"editor.temporary.disabled": "Not implemented yet",
"externalviewer.dataset.unnamed": "Datahub layer",
Expand Down
1 change: 1 addition & 0 deletions translations/es.json
Original file line number Diff line number Diff line change
Expand Up @@ -313,6 +313,7 @@
"editor.record.undo.tooltip.disabled": "",
"editor.record.undo.tooltip.enabled": "",
"editor.record.upToDate": "",
"editor.sidebar.logout": "",
"editor.sidebar.menu.editor": "",
"editor.temporary.disabled": "",
"externalviewer.dataset.unnamed": "",
Expand Down
1 change: 1 addition & 0 deletions translations/fr.json
Original file line number Diff line number Diff line change
Expand Up @@ -313,6 +313,7 @@
"editor.record.undo.tooltip.disabled": "Il n'y a pas de modifications en cours sur cette fiche",
"editor.record.undo.tooltip.enabled": "Cliquez sur ce bouton pour annuler les modifications apportées à cette fiche",
"editor.record.upToDate": "",
"editor.sidebar.logout": "Se déconnecter",
"editor.sidebar.menu.editor": "",
"editor.temporary.disabled": "Pas encore implémenté",
"externalviewer.dataset.unnamed": "Couche du datahub",
Expand Down
1 change: 1 addition & 0 deletions translations/it.json
Original file line number Diff line number Diff line change
Expand Up @@ -313,6 +313,7 @@
"editor.record.undo.tooltip.disabled": "",
"editor.record.undo.tooltip.enabled": "",
"editor.record.upToDate": "",
"editor.sidebar.logout": "",
"editor.sidebar.menu.editor": "",
"editor.temporary.disabled": "",
"externalviewer.dataset.unnamed": "Layer del datahub",
Expand Down
1 change: 1 addition & 0 deletions translations/nl.json
Original file line number Diff line number Diff line change
Expand Up @@ -313,6 +313,7 @@
"editor.record.undo.tooltip.disabled": "",
"editor.record.undo.tooltip.enabled": "",
"editor.record.upToDate": "",
"editor.sidebar.logout": "",
"editor.sidebar.menu.editor": "",
"editor.temporary.disabled": "",
"externalviewer.dataset.unnamed": "",
Expand Down
1 change: 1 addition & 0 deletions translations/pt.json
Original file line number Diff line number Diff line change
Expand Up @@ -313,6 +313,7 @@
"editor.record.undo.tooltip.disabled": "",
"editor.record.undo.tooltip.enabled": "",
"editor.record.upToDate": "",
"editor.sidebar.logout": "",
"editor.sidebar.menu.editor": "",
"editor.temporary.disabled": "",
"externalviewer.dataset.unnamed": "",
Expand Down
1 change: 1 addition & 0 deletions translations/sk.json
Original file line number Diff line number Diff line change
Expand Up @@ -313,6 +313,7 @@
"editor.record.undo.tooltip.disabled": "",
"editor.record.undo.tooltip.enabled": "",
"editor.record.upToDate": "",
"editor.sidebar.logout": "",
"editor.sidebar.menu.editor": "",
"editor.temporary.disabled": "",
"externalviewer.dataset.unnamed": "",
Expand Down

0 comments on commit 67cb636

Please sign in to comment.