From 235d011d3f300878c340469478474f3d9df04a00 Mon Sep 17 00:00:00 2001 From: amrita Date: Fri, 18 Oct 2024 17:38:33 +0545 Subject: [PATCH] introduce token and user store for federated ocis --- tests/e2e/config.js | 12 +++---- tests/e2e/cucumber/environment/index.ts | 33 +++++++++++++++---- tests/e2e/cucumber/features/ocm/ocm.feature | 20 +++++++++++ tests/e2e/cucumber/steps/ui/session.ts | 19 +++++++++-- tests/e2e/support/api/graph/userManagement.ts | 2 +- tests/e2e/support/api/http.ts | 2 +- .../e2e/support/api/keycloak/ocisUserToken.ts | 2 +- tests/e2e/support/api/token/utils.ts | 18 +++++----- tests/e2e/support/environment/token.ts | 9 +++-- .../e2e/support/environment/userManagement.ts | 20 ++++++----- .../support/objects/url-navigation/actions.ts | 10 +++--- tests/e2e/support/store/index.ts | 2 +- tests/e2e/support/store/token.ts | 2 ++ tests/e2e/support/store/user.ts | 2 ++ tests/e2e/support/utils/tokenHelper.ts | 2 +- 15 files changed, 109 insertions(+), 46 deletions(-) create mode 100644 tests/e2e/cucumber/features/ocm/ocm.feature diff --git a/tests/e2e/config.js b/tests/e2e/config.js index 0dcea795558..bde96755e6c 100644 --- a/tests/e2e/config.js +++ b/tests/e2e/config.js @@ -12,18 +12,18 @@ export const config = { keycloakRealm: process.env.KEYCLOAK_REALM ?? 'oCIS', keycloakAdminUser: process.env.KEYCLOAK_ADMIN_USER ?? 'admin', keycloakAdminPassword: process.env.KEYCLOAK_ADMIN_PASSWORD ?? 'admin', - get backendUrl() { - return withHttp(process.env.BACKEND_HOST || this.baseUrlOcis) - }, - get frontendUrl() { - return withHttp(process.env.SERVER_HOST || this.baseUrlOcis) - }, get keycloakUrl() { return withHttp(this.keycloakHost) }, get keycloakLoginUrl() { return withHttp(this.keycloakHost + '/admin/master/console') }, + // ocm config + federatedBaseUrlOcis: process.env.FEDERATED_BASE_URL_OCIS ?? 'federation-ocis:10200', + federatedServer: false, + get baseUrl() { + return withHttp(this.federatedServer ? this.federatedBaseUrlOcis : this.baseUrlOcis) + }, debug: process.env.DEBUG === 'true', logLevel: process.env.LOG_LEVEL || 'silent', // cucumber diff --git a/tests/e2e/cucumber/environment/index.ts b/tests/e2e/cucumber/environment/index.ts index 18f587e3305..5ef8ff8d1ec 100644 --- a/tests/e2e/cucumber/environment/index.ts +++ b/tests/e2e/cucumber/environment/index.ts @@ -22,10 +22,15 @@ import { createdLinkStore, createdGroupStore, createdUserStore, - keycloakCreatedUser + keycloakCreatedUser, + federatedUserStore } from '../../support/store' import { Group, User } from '../../support/types' -import { createdTokenStore, keycloakTokenStore } from '../../support/store/token' +import { + createdTokenStore, + federatedTokenStore, + keycloakTokenStore +} from '../../support/store/token' import { removeTempUploadDirectory } from '../../support/utils/runtimeFs' import { setAccessTokenForKeycloakUser, @@ -78,6 +83,7 @@ Before(async function (this: World, { pickle }: ITestCaseHookParameter) { break } }) + const tags = pickle.tags.map((tag) => tag.name) if (!config.basicAuth) { const user = this.usersEnvironment.getUser({ key: 'admin' }) if (config.keycloak) { @@ -85,6 +91,10 @@ Before(async function (this: World, { pickle }: ITestCaseHookParameter) { await setAccessTokenForKeycloakUser(user) } else { await setAccessAndRefreshToken(user) + if (tags.includes('@ocm')) { + config.federatedServer = true + await setAccessAndRefreshToken(user) + } } } }) @@ -122,7 +132,8 @@ const defaults = { reportTracing: config.reportTracing } -After(async function (this: World, { result, willBeRetried }: ITestCaseHookParameter) { +After(async function (this: World, { result, willBeRetried, pickle }: ITestCaseHookParameter) { + config.federatedServer = false if (!result) { return } @@ -136,12 +147,20 @@ After(async function (this: World, { result, willBeRetried }: ITestCaseHookParam await refreshAccessTokenForKeycloakOcisUser(user) } - await cleanUpUser(this.usersEnvironment.getUser({ key: 'admin' })) + await cleanUpUser(createdUserStore, this.usersEnvironment.getUser({ key: 'admin' })) + + const tags = pickle.tags.map((tag) => tag.name) + if (tags.includes('@ocm')) { + config.federatedServer = true + await cleanUpUser(federatedUserStore, this.usersEnvironment.getUser({ key: 'admin' })) + } + await cleanUpSpaces(this.usersEnvironment.getUser({ key: 'admin' })) await cleanUpGroup(this.usersEnvironment.getUser({ key: 'admin' })) createdLinkStore.clear() createdTokenStore.clear() + federatedTokenStore.clear() keycloakTokenStore.clear() removeTempUploadDirectory() closeSSEConnections() @@ -188,13 +207,13 @@ function filterTracingReports(status: string) { } } -const cleanUpUser = async (adminUser: User) => { +const cleanUpUser = async (store, adminUser: User) => { const requests: Promise[] = [] - createdUserStore.forEach((user) => { + store.forEach((user) => { requests.push(api.provision.deleteUser({ user, admin: adminUser })) }) await Promise.all(requests) - createdUserStore.clear() + store.clear() keycloakCreatedUser.clear() } diff --git a/tests/e2e/cucumber/features/ocm/ocm.feature b/tests/e2e/cucumber/features/ocm/ocm.feature new file mode 100644 index 00000000000..caa868c348e --- /dev/null +++ b/tests/e2e/cucumber/features/ocm/ocm.feature @@ -0,0 +1,20 @@ +@ocm +Feature: federation management + + Scenario: user create federated share + Given using "LOCAL" server + Given "Admin" creates following user using API + | id | + | Alice | + And "Alice" creates the following files into personal space using API + | pathToFile | content | + | example1.txt | example text | + And "Alice" logs in + And "Alice" logs out + Given using "FEDERATED" server + And "Admin" logs in + And "Admin" creates following user using API + | id | + | Brian | + And "Brian" logs in + And "Brian" logs out diff --git a/tests/e2e/cucumber/steps/ui/session.ts b/tests/e2e/cucumber/steps/ui/session.ts index e50a0ea1d4b..4b30c65f4f0 100644 --- a/tests/e2e/cucumber/steps/ui/session.ts +++ b/tests/e2e/cucumber/steps/ui/session.ts @@ -22,7 +22,7 @@ async function LogInUser(this: World, stepUser: string): Promise { ? this.usersEnvironment.getUser({ key: stepUser }) : this.usersEnvironment.getCreatedUser({ key: stepUser }) - await page.goto(config.frontendUrl) + await page.goto(config.baseUrl) await sessionObject.login(user) if (this.feature.tags.length > 0) { @@ -33,7 +33,7 @@ async function LogInUser(this: World, stepUser: string): Promise { // listen to SSE events when running scenarios with '@sse' tag if (tags.includes('@sse')) { - void listenSSE(config.frontendUrl, user) + void listenSSE(config.baseUrl, user) } } @@ -62,7 +62,7 @@ Then('{string} fails to log in', async function (this: World, stepUser: string): const { page } = this.actorsEnvironment.getActor({ key: stepUser }) const user = this.usersEnvironment.getUser({ key: stepUser }) - await page.goto(config.frontendUrl) + 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() @@ -118,3 +118,16 @@ When( await actor.closeCurrentTab() } ) + +Given('using {string} server', async function (this: World, server: string): Promise { + switch (server) { + case 'LOCAL': + config.federatedServer = false + break + case 'FEDERATED': + config.federatedServer = true + break + default: + throw new Error('Server type out of scope') + } +}) diff --git a/tests/e2e/support/api/graph/userManagement.ts b/tests/e2e/support/api/graph/userManagement.ts index 3d8f07647c1..a9552db2a52 100644 --- a/tests/e2e/support/api/graph/userManagement.ts +++ b/tests/e2e/support/api/graph/userManagement.ts @@ -125,7 +125,7 @@ export const addUserToGroup = async ({ const userId = usersEnvironment.getCreatedUser({ key: user.id }).uuid const groupId = usersEnvironment.getCreatedGroup({ key: group.id }).uuid const body = JSON.stringify({ - '@odata.id': join(config.backendUrl, 'graph', 'v1.0', 'users', userId) + '@odata.id': join(config.baseUrl, 'graph', 'v1.0', 'users', userId) }) const response = await request({ diff --git a/tests/e2e/support/api/http.ts b/tests/e2e/support/api/http.ts index 19a78021c43..bad76386621 100644 --- a/tests/e2e/support/api/http.ts +++ b/tests/e2e/support/api/http.ts @@ -39,7 +39,7 @@ export const request = async ({ ...header } - const baseUrl = isKeycloakRequest ? config.keycloakUrl : config.backendUrl + const baseUrl = isKeycloakRequest ? config.keycloakUrl : config.baseUrl return await fetch(join(baseUrl, path), { method, diff --git a/tests/e2e/support/api/keycloak/ocisUserToken.ts b/tests/e2e/support/api/keycloak/ocisUserToken.ts index ed60169f2ad..f97544a0bec 100644 --- a/tests/e2e/support/api/keycloak/ocisUserToken.ts +++ b/tests/e2e/support/api/keycloak/ocisUserToken.ts @@ -10,7 +10,7 @@ interface ocisTokenForKeycloak { const authorizationEndpoint = config.keycloakUrl + '/realms/oCIS/protocol/openid-connect/auth' const tokenEndpoint = config.keycloakUrl + '/realms/oCIS/protocol/openid-connect/token' -const redirectUrl = config.backendUrl + '/oidc-callback.html' +const redirectUrl = config.baseUrl + '/oidc-callback.html' async function getAuthorizationEndPoint() { const loginParams = { diff --git a/tests/e2e/support/api/token/utils.ts b/tests/e2e/support/api/token/utils.ts index 146d1a40c46..532d2adfd96 100644 --- a/tests/e2e/support/api/token/utils.ts +++ b/tests/e2e/support/api/token/utils.ts @@ -3,9 +3,9 @@ import { config } from '../../../config' import fetch, { Response } from 'node-fetch' import { User } from '../../types' -const logonUrl = config.backendUrl + '/signin/v1/identifier/_/logon' -const redirectUrl = config.backendUrl + '/oidc-callback.html' -const tokenUrl = config.backendUrl + '/konnect/v1/token' +const logonUrl = '/signin/v1/identifier/_/logon' +const redirectUrl = '/oidc-callback.html' +const tokenUrl = '/konnect/v1/token' interface Token { access_token: string @@ -13,11 +13,11 @@ interface Token { } const getAuthorizedEndPoint = async (user: User): Promise> => { - const logonResponse = await fetch(logonUrl, { + const logonResponse = await fetch(config.baseUrl + logonUrl, { method: 'POST', headers: { 'Kopano-Konnect-XSRF': '1', - Referer: config.backendUrl, + Referer: config.baseUrl, 'Content-Type': 'application/json' }, body: JSON.stringify({ @@ -25,7 +25,7 @@ const getAuthorizedEndPoint = async (user: User): Promise> => { hello: { scope: 'openid profile email', client_id: 'web', - redirect_uri: redirectUrl, + redirect_uri: config.baseUrl + redirectUrl, flow: 'oidc' } }) @@ -52,7 +52,7 @@ const getCode = async ({ const params = new URLSearchParams({ client_id: 'web', prompt: 'none', - redirect_uri: redirectUrl, + redirect_uri: config.baseUrl + redirectUrl, response_mode: 'query', response_type: 'code', scope: 'openid profile offline_access email' @@ -81,12 +81,12 @@ const getCode = async ({ } const getToken = async (code: string): Promise => { - const response = await fetch(tokenUrl, { + const response = await fetch(config.baseUrl + tokenUrl, { method: 'POST', body: new URLSearchParams({ client_id: 'web', code: code, - redirect_uri: redirectUrl, + redirect_uri: config.baseUrl + redirectUrl, grant_type: 'authorization_code' }) }) diff --git a/tests/e2e/support/environment/token.ts b/tests/e2e/support/environment/token.ts index be04b80b0be..0f1ee1406a5 100644 --- a/tests/e2e/support/environment/token.ts +++ b/tests/e2e/support/environment/token.ts @@ -1,5 +1,6 @@ -import { createdTokenStore, keycloakTokenStore } from '../store/token' +import { createdTokenStore, federatedTokenStore, keycloakTokenStore } from '../store/token' import { Token, User } from '../types' +import { config } from '../../config' export type TokenProviderType = 'keycloak' | null | undefined export type TokenEnvironmentType = KeycloakTokenEnvironment | IdpTokenEnvironment @@ -15,11 +16,13 @@ export function TokenEnvironmentFactory(type?: TokenProviderType) { class IdpTokenEnvironment { getToken({ user }: { user: User }): Token { - return createdTokenStore.get(user.id) + const store = config.federatedServer ? federatedTokenStore : createdTokenStore + return store.get(user.id) } setToken({ user, token }: { user: User; token: Token }): Token { - createdTokenStore.set(user.id, token) + const store = config.federatedServer ? federatedTokenStore : createdTokenStore + store.set(user.id, token) return token } diff --git a/tests/e2e/support/environment/userManagement.ts b/tests/e2e/support/environment/userManagement.ts index b003ad28233..b55a04b457b 100644 --- a/tests/e2e/support/environment/userManagement.ts +++ b/tests/e2e/support/environment/userManagement.ts @@ -4,8 +4,10 @@ import { dummyGroupStore, createdUserStore, createdGroupStore, - keycloakCreatedUser + keycloakCreatedUser, + federatedUserStore } from '../store' +import { config } from '../../config' export class UsersEnvironment { getUser({ key }: { key: string }): User { @@ -31,21 +33,22 @@ export class UsersEnvironment { } storeCreatedUser({ user }: { user: User }): User { - if (createdUserStore.has(user.id)) { + const store = config.federatedServer ? federatedUserStore : createdUserStore + if (store.has(user.id)) { throw new Error(`user '${user.id}' already exists`) } - createdUserStore.set(user.id, user) - + store.set(user.id, user) return user } getCreatedUser({ key }: { key: string }): User { + const store = config.federatedServer ? federatedUserStore : createdUserStore const userKey = key.toLowerCase() - if (!createdUserStore.has(userKey)) { + if (!store.has(userKey)) { throw new Error(`user with key '${userKey}' not found`) } - return createdUserStore.get(userKey) + return store.get(userKey) } updateCreatedUser({ key, user }: { key: string; user: User }): User { @@ -60,13 +63,14 @@ export class UsersEnvironment { } removeCreatedUser({ key }: { key: string }): boolean { + const store = config.federatedServer ? federatedUserStore : createdUserStore const userKey = key.toLowerCase() - if (!createdUserStore.has(userKey)) { + if (!store.has(userKey)) { throw new Error(`user '${userKey}' not found`) } - return createdUserStore.delete(userKey) + return store.delete(userKey) } getGroup({ key }: { key: string }): Group { diff --git a/tests/e2e/support/objects/url-navigation/actions.ts b/tests/e2e/support/objects/url-navigation/actions.ts index 689f55fc335..aa9fccd7d3a 100644 --- a/tests/e2e/support/objects/url-navigation/actions.ts +++ b/tests/e2e/support/objects/url-navigation/actions.ts @@ -27,7 +27,7 @@ export const navigateToDetailsPanelOfResource = async ( ): Promise => { const { page, resource, detailsPanel, user, space } = args const fileId = await getTheFileIdOfSpaceFile(user, space, resource) - const fullUrl = `${config.backendUrl}/f/${fileId}?details=${detailsPanel}` + const fullUrl = `${config.baseUrl}/f/${fileId}?details=${detailsPanel}` await page.goto(fullUrl) } @@ -38,13 +38,13 @@ export const openResourceViaUrl = async (args: openResourceViaUrlArgs) => { switch (client) { case 'desktop': - fullUrl = `${config.backendUrl}/external/open-with-web/?appName=${editorName}&fileId=${fileId}` + fullUrl = `${config.baseUrl}/external/open-with-web/?appName=${editorName}&fileId=${fileId}` break case 'mobile': fullUrl = await getOpenWithWebUrl({ user, fileId, editorName }) break default: - fullUrl = `${config.backendUrl}/f/${fileId}` + fullUrl = `${config.baseUrl}/f/${fileId}` } await page.goto(fullUrl) } @@ -61,7 +61,7 @@ export const openSpaceViaUrl = async (args: openResourceViaUrlArgs) => { spaceType = 'project' } const fileId = await getSpaceIdBySpaceName({ user, spaceType, spaceName }) - const fullUrl = `${config.backendUrl}/f/${fileId}` + const fullUrl = `${config.baseUrl}/f/${fileId}` await page.goto(fullUrl) } @@ -88,7 +88,7 @@ const getTheFileIdOfSpaceFile = async ( } export const navigateToNonExistingPage = async ({ page }: { page: Page }) => { - await page.goto(`${config.backendUrl}/'a-non-existing-page'`) + await page.goto(`${config.baseUrl}/'a-non-existing-page'`) } export const waitForNotFoundPageToBeVisible = async ({ page }: { page: Page }) => { await page.locator('.page-not-found').waitFor() diff --git a/tests/e2e/support/store/index.ts b/tests/e2e/support/store/index.ts index cc53afdbed9..a1e0dff4334 100644 --- a/tests/e2e/support/store/index.ts +++ b/tests/e2e/support/store/index.ts @@ -1,7 +1,7 @@ export { actorStore } from './actor' export { createdLinkStore, roleDisplayText, securePassword } from './link' export { createdSpaceStore } from './space' -export { dummyUserStore, createdUserStore } from './user' +export { dummyUserStore, createdUserStore, federatedUserStore } from './user' export { dummyGroupStore, createdGroupStore } from './group' export { userRoleStore } from './role' export { keycloakRealmRoles, keycloakCreatedUser } from './keycloak' diff --git a/tests/e2e/support/store/token.ts b/tests/e2e/support/store/token.ts index bccbdaca996..d4b35f3e301 100644 --- a/tests/e2e/support/store/token.ts +++ b/tests/e2e/support/store/token.ts @@ -2,4 +2,6 @@ import { Token } from '../types' export const createdTokenStore = new Map() +export const federatedTokenStore = new Map() + export const keycloakTokenStore = new Map() diff --git a/tests/e2e/support/store/user.ts b/tests/e2e/support/store/user.ts index 5286156d8cd..90bd83c46d8 100644 --- a/tests/e2e/support/store/user.ts +++ b/tests/e2e/support/store/user.ts @@ -67,3 +67,5 @@ export const dummyUserStore = new Map([ ]) export const createdUserStore = new Map() + +export const federatedUserStore = new Map() diff --git a/tests/e2e/support/utils/tokenHelper.ts b/tests/e2e/support/utils/tokenHelper.ts index 5fa9e5b50e8..ebcc859e7f8 100644 --- a/tests/e2e/support/utils/tokenHelper.ts +++ b/tests/e2e/support/utils/tokenHelper.ts @@ -6,7 +6,7 @@ import { User } from '../types' export const initializeUser = async ({ browser, - url = config.frontendUrl, + url = config.baseUrl, user, waitForSelector = null }: {