Skip to content

Commit

Permalink
introduce token and user store for federated ocis
Browse files Browse the repository at this point in the history
  • Loading branch information
amrita-shrestha committed Oct 18, 2024
1 parent 1557d81 commit 6885efe
Show file tree
Hide file tree
Showing 15 changed files with 104 additions and 48 deletions.
12 changes: 6 additions & 6 deletions tests/e2e/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
31 changes: 22 additions & 9 deletions tests/e2e/cucumber/environment/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -78,13 +83,18 @@ 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) {
await setAccessTokenForKeycloakOcisUser(user)
await setAccessTokenForKeycloakUser(user)
} else {
await setAccessAndRefreshToken(user)
if (tags.includes('@ocm')) {
config.federatedServer = true
await setAccessAndRefreshToken(user)
}
}
}
})
Expand Down Expand Up @@ -122,26 +132,29 @@ const defaults = {
reportTracing: config.reportTracing
}

After(async function (this: World, { result, willBeRetried }: ITestCaseHookParameter) {
After(async function (this: World, { result, willBeRetried, pickle }: ITestCaseHookParameter) {
if (!result) {
return
}

await this.actorsEnvironment.close()

const tags = pickle.tags.map((tag) => tag.name)
// refresh keycloak admin access token
if (config.keycloak) {
const user = this.usersEnvironment.getUser({ key: 'admin' })
await refreshAccessTokenForKeycloakUser(user)
await refreshAccessTokenForKeycloakOcisUser(user)
}

await cleanUpUser(this.usersEnvironment.getUser({ key: 'admin' }))
if (tags.includes('@ocm')) {
await cleanUpUser(federatedUserStore, this.usersEnvironment.getUser({ key: 'admin' }))
}
await cleanUpUser(createdUserStore, 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()
Expand Down Expand Up @@ -188,13 +201,13 @@ function filterTracingReports(status: string) {
}
}

const cleanUpUser = async (adminUser: User) => {
const cleanUpUser = async (store, adminUser: User) => {
const requests: Promise<User>[] = []
createdUserStore.forEach((user) => {
store.forEach((user) => {
requests.push(api.provision.deleteUser({ user, admin: adminUser }))
})
await Promise.all(requests)
createdUserStore.clear()
store.clear()
keycloakCreatedUser.clear()
}

Expand Down
18 changes: 18 additions & 0 deletions tests/e2e/cucumber/features/ocm/ocm.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
@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 |
19 changes: 16 additions & 3 deletions tests/e2e/cucumber/steps/ui/session.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ async function LogInUser(this: World, stepUser: string): Promise<void> {
? 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) {
Expand All @@ -33,7 +33,7 @@ async function LogInUser(this: World, stepUser: string): Promise<void> {

// listen to SSE events when running scenarios with '@sse' tag
if (tags.includes('@sse')) {
void listenSSE(config.frontendUrl, user)
void listenSSE(config.baseUrl, user)
}
}

Expand Down Expand Up @@ -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()
Expand Down Expand Up @@ -118,3 +118,16 @@ When(
await actor.closeCurrentTab()
}
)

Given('using {string} server', async function (this: World, server: string): Promise<void> {
switch (server) {
case 'LOCAL':
config.federatedServer = false
break
case 'FEDERATED':
config.federatedServer = true
break
default:
throw new Error('Server type out of scope')
}
})
2 changes: 1 addition & 1 deletion tests/e2e/support/api/graph/userManagement.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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({
Expand Down
2 changes: 1 addition & 1 deletion tests/e2e/support/api/http.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
2 changes: 1 addition & 1 deletion tests/e2e/support/api/keycloak/ocisUserToken.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 = {
Expand Down
18 changes: 9 additions & 9 deletions tests/e2e/support/api/token/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,29 +3,29 @@ 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
refresh_token: string
}

const getAuthorizedEndPoint = async (user: User): Promise<Array<string>> => {
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({
params: [user.id, user.password, '1'],
hello: {
scope: 'openid profile email',
client_id: 'web',
redirect_uri: redirectUrl,
redirect_uri: config.baseUrl + redirectUrl,
flow: 'oidc'
}
})
Expand All @@ -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'
Expand Down Expand Up @@ -81,12 +81,12 @@ const getCode = async ({
}

const getToken = async (code: string): Promise<Response> => {
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'
})
})
Expand Down
12 changes: 9 additions & 3 deletions tests/e2e/support/environment/token.ts
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -15,12 +16,17 @@ export function TokenEnvironmentFactory(type?: TokenProviderType) {

class IdpTokenEnvironment {
getToken({ user }: { user: User }): Token {
if (config.federatedServer) {
return federatedTokenStore.get(user.id)
}
return createdTokenStore.get(user.id)
}

setToken({ user, token }: { user: User; token: Token }): Token {
createdTokenStore.set(user.id, token)
return token
if (config.federatedServer) {
return federatedTokenStore.set(user.id, token)
}
return createdTokenStore.set(user.id, token)
}

deleteToken({ user }: { user: User }): void {
Expand Down
16 changes: 9 additions & 7 deletions tests/e2e/support/environment/userManagement.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -31,21 +33,21 @@ 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)

return user
return store.set(user.id, 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 {
Expand Down
10 changes: 5 additions & 5 deletions tests/e2e/support/objects/url-navigation/actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ export const navigateToDetailsPanelOfResource = async (
): Promise<void> => {
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)
}

Expand All @@ -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)
}
Expand All @@ -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)
}

Expand All @@ -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()
Expand Down
2 changes: 1 addition & 1 deletion tests/e2e/support/store/index.ts
Original file line number Diff line number Diff line change
@@ -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'
2 changes: 2 additions & 0 deletions tests/e2e/support/store/token.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,6 @@ import { Token } from '../types'

export const createdTokenStore = new Map<string, Token>()

export const federatedTokenStore = new Map<string, Token>()

export const keycloakTokenStore = new Map<string, Token>()
4 changes: 3 additions & 1 deletion tests/e2e/support/store/user.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,4 +66,6 @@ export const dummyUserStore = new Map<string, User>([
]
])

export const createdUserStore = new Map<string, User>()
export const createdUserStore = new Map<string, Map<string, User>>()

export const federatedUserStore = new Map<string, Map<string, User>>()
Loading

0 comments on commit 6885efe

Please sign in to comment.