Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions tests/e2e/cucumber/features/keycloak/smoke.feature
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,16 @@ Feature: keycloak integration
| displayname | Carol King |
| email | carol@example.org |
| groups | finance, security |

# disble user and delete user sessions to force logout
When admin disables user "Carol" using keycloak API
And admin deletes sessions of user "Carol" using keycloak API
Then "Carol" should be logged out
And "Carol" fails to log in

# enable user again to verify that the user can log in and access the app
When admin enables user "Carol" using keycloak API
Then "Carol" logs in
And "Carol" opens the "files" app
And "Carol" navigates to the project space "brianSpace.1"
And "Carol" logs out
26 changes: 25 additions & 1 deletion tests/e2e/cucumber/steps/api.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Given, DataTable } from '@cucumber/cucumber'
import { Given, DataTable, When } from '@cucumber/cucumber'
import { World } from '../environment'
import { api } from '../../support'
import fs from 'fs'
Expand Down Expand Up @@ -370,3 +370,27 @@ Given(
}
}
)

When(
'admin disables user {string} using keycloak API',
async function (this: World, stepUser: string): Promise<void> {
const user = this.usersEnvironment.getCreatedUser({ key: stepUser })
await api.keycloak.setUserEnabled({ uuid: user.keycloakUuid, enabled: false })
}
)

When(
'admin enables user {string} using keycloak API',
async function (this: World, stepUser: string): Promise<void> {
const user = this.usersEnvironment.getCreatedUser({ key: stepUser })
await api.keycloak.setUserEnabled({ uuid: user.keycloakUuid, enabled: true })
}
)

When(
'admin deletes sessions of user {string} using keycloak API',
async function (this: World, stepUser: string): Promise<void> {
const user = this.usersEnvironment.getCreatedUser({ key: stepUser })
await api.keycloak.deleteUserSessions({ uuid: user.keycloakUuid })
}
)
25 changes: 20 additions & 5 deletions tests/e2e/cucumber/steps/ui/session.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { World } from '../../environment'
import { config } from '../../../config'
import { objects } from '../../../support'
import { listenSSE } from '../../../support/environment/sse'
import { expect } from '@playwright/test'

async function createNewSession(world: World, stepUser: string) {
const { page } = await world.actorsEnvironment.createActor({
Expand Down Expand Up @@ -54,15 +55,20 @@ async function LogOutUser(this: World, stepUser: string): Promise<void> {
When('{string} logs out', LogOutUser)

Then('{string} fails to log in', async function (this: World, stepUser: string): Promise<void> {
await createNewSession(this, stepUser)
const sessionObject = await createNewSession(this, stepUser)
const { page } = this.actorsEnvironment.getActor({ key: stepUser })
const user = this.usersEnvironment.getCreatedUser({ key: stepUser })

await page.goto(config.baseUrl)
await page.locator('#oc-login-username').fill(user.id)
await page.locator('#oc-login-password').fill(user.password)
await page.locator('button[type="submit"]').click()
await page.locator('#oc-login-error-message').waitFor()
await sessionObject.signIn(user.username, user.password)

const errorLocator = config.keycloak
? page.locator('.kc-feedback-text', {
hasText: 'Account is disabled, contact your administrator.'
})
: page.locator('#oc-login-error-message')

await expect(errorLocator).toBeVisible()
})

When(
Expand Down Expand Up @@ -116,3 +122,12 @@ Given('using {string} server', function (this: World, server: string): void {
throw new Error(`Invalid server type: ${server}\nUse one of these: [LOCAL, FEDERATED]`)
}
})

Then(
'{string} should be logged out',
async function (this: World, stepUser: string): Promise<void> {
const { page } = this.actorsEnvironment.getActor({ key: stepUser })
await expect(page.locator('#web-content')).toBeHidden()
await expect(page.locator('#exitAnchor')).toBeVisible()
}
)
38 changes: 38 additions & 0 deletions tests/e2e/support/api/keycloak/user.ts
Original file line number Diff line number Diff line change
Expand Up @@ -144,3 +144,41 @@ export const getRealmRole = async (role: string): Promise<KeycloakRealmRole> =>

throw new Error(`Role '${role}' not found in the keycloak realm`)
}

export const setUserEnabled = async ({ uuid, enabled }: { uuid: string; enabled: boolean }) => {
const response = await request({
method: 'PUT',
path: urlJoin(realmBasePath, 'users', uuid),
body: { enabled },
user: getKeycloakAdminUser(),
header: { 'Content-Type': 'application/json' }
})
checkResponseStatus(response, enabled ? 'Can not enable user' : 'Can not disable user')
return response
}

const getUserSessionsId = async ({ uuid }: { uuid: string }): Promise<string[]> => {
const response = await request({
method: 'GET',
path: urlJoin(realmBasePath, 'users', uuid, 'sessions'),
user: getKeycloakAdminUser()
})
checkResponseStatus(response, 'Can not get user sessions')
const sessions = (await response.json()) as { id: string }[]
if (sessions.length === 0) {
throw new Error('No active session found for the user')
}
return sessions.map((session) => session.id)
}

export const deleteUserSessions = async ({ uuid }: { uuid: string }) => {
const sessions = await getUserSessionsId({ uuid })
for (const session of sessions) {
const response = await request({
method: 'DELETE',
path: urlJoin(realmBasePath, 'sessions', session),
user: getKeycloakAdminUser()
})
checkResponseStatus(response, 'Can not delete user session')
}
}