Navigation Menu

Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Jwt policies min ui #1109

Merged
merged 29 commits into from Feb 18, 2019
Merged
Show file tree
Hide file tree
Changes from 19 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
11 changes: 0 additions & 11 deletions deployments/dev/docker-compose.local-editor.yml
Expand Up @@ -6,10 +6,6 @@ services:
args:
target: Release

editor:
environment:
- CONTINUOUS_UPDATER_INTERVAL=500

authoring:
environment:
- CONTINUOUS_UPDATER_INTERVAL=500
Expand All @@ -20,13 +16,6 @@ services:
target: Release
depends_on:
- publishing
environment:
- CorsPolicies__Keys__Origins=http://localhost:3000
- CorsPolicies__Keys__Methods=GET
- CorsPolicies__Keys__MaxPreflightAge=60
- CorsPolicies__Keys__Headers=
- CorsPolicies__Keys__ExposedHeaders=
- CorsEnabled=true

oidc-server-mock:
container_name: oidc-server-mock
Expand Down
10 changes: 5 additions & 5 deletions docs/pages/1.getting-started/02.using-tweek.md
Expand Up @@ -46,7 +46,7 @@ Tweek provide UI and rest api for editing context.
- Set value "Candada" for property Country

After that, we can query Tweek API with:
- http://localhost:8080/api/v1/keys/my_app/sign_button/color?user=john -> expected to be "blue"
- http://localhost:8080/api/v2/values/my_app/sign_button/color?user=john -> expected to be "blue"

You can also use the api for updating Tweek context:
- curl -X POST http://localhost:8080/api/v2/context/user/john \
Expand All @@ -63,10 +63,10 @@ More on [Context.](https://docs.tweek.fm/concepts/context/intro-to-context)
Create new key in the editor "my_app/sign_button/is_enabled" with value type "boolean" and default value False.
Add new rule, remove all conditions, set the the rule value to gradual release with 50%.
Try querying configuration with different users and You'll have different results.
- http://localhost:8080/api/v1/keys/my_app/sign_button/is_enabled?user=barny
- http://localhost:8080/api/v1/keys/my_app/sign_button/is_enabled?user=robin
- http://localhost:8080/api/v1/keys/my_app/sign_button/is_enabled?user=ted
- http://localhost:8080/api/v1/keys/my_app/sign_button/is_enabled?user=lily
- http://localhost:8080/api/v2/values/my_app/sign_button/is_enabled?user=barny
- http://localhost:8080/api/v2/values/my_app/sign_button/is_enabled?user=robin
- http://localhost:8080/api/v2/values/my_app/sign_button/is_enabled?user=ted
- http://localhost:8080/api/v2/values/my_app/sign_button/is_enabled?user=lily
- etc...

More on how multi-variant keys work in Tweek. (link)
4 changes: 2 additions & 2 deletions e2e/ui/package.json
Expand Up @@ -5,7 +5,7 @@
"scripts": {
"build": "yarn docker-compose build",
"test": "testcafe -q -S -s screenshots chrome spec",
"test:fll-env": "yarn docker-compose up --build -d editor && yarn test",
"test:full-env": "yarn docker-compose up --build -d editor && yarn test",
"test:docker": "yarn build && yarn docker-compose run --rm e2e-ui",
"logs": "yarn docker-compose logs",
"teardown": "yarn docker-compose down --remove-orphans",
Expand All @@ -15,7 +15,7 @@
"chai": "^4.2.0",
"nconf": "^0.10.0",
"ramda": "^0.26.1",
"tweek-client": "^1.0.0-rc5",
"tweek-client": "^1.0.0-rc7",
"uuid": "^3.3.2"
},
"devDependencies": {
Expand Down
69 changes: 69 additions & 0 deletions e2e/ui/pages/Settings/Policies.js
@@ -0,0 +1,69 @@
import { Selector, t, ClientFunction } from 'testcafe';

const read = ClientFunction(()=> window.monaco.editor.getModels()[0].getValue());
const update = ClientFunction(()=> window.monaco.editor.getModels()[0].setValue(text));

export class PolicyEditor {

constructor(container){
this.container = container;
this.editor = this.container.find(".monaco-editor");
this.saveButton = this.container.find("button.save-button")
}

async read(){
return await read();
}

async update(text){
return await update.with({
dependencies: { text }
})();
}

hasChanges(){
return this.saveButton.withAttribute(
'data-state-has-changes',
'true').exists;
Yshayy marked this conversation as resolved.
Show resolved Hide resolved
}

isValid(){
return this.saveButton.withAttribute(
'data-state-is-valid',
'true').exists;
}

async save(){
return await t
.expect(this.hasChanges())
.ok()
.click(this.saveButton);
}
}

export default class PoliciesSection {

container = Selector(".policies-page");
tab = "ACL"

async currentTab(){
const panel = this.container.find(`[role=tabpanel]`);
await t.expect(panel.visible).ok();
return new PolicyEditor(panel);
}

async changeTab(name){
const tabButton = this.container.find("[role=tab]").withText(name);
const id = await tabButton.getAttribute("id");
const panel = this.container.find(`[role=tabpanel][aria-labelledby=${id}]`);

//container
await t.click(
this.container.find("[role=tab]").withText(name)
)
.expect(panel.visible)
.ok();

return new PolicyEditor(panel);
}
}
17 changes: 17 additions & 0 deletions e2e/ui/pages/Settings/index.js
@@ -1,6 +1,9 @@
import { Selector, t } from 'testcafe';
import { attributeSelector, dataComp } from '../../utils/selector-utils';
import Identity from './Identity';
import PoliciesSection from './Policies';
import { editorUrl } from '../../utils/constants';
import { getLocation } from '../../utils/location-utils';

export default class SettingsPage {
sideMenu = Selector('.side-menu');
Expand Down Expand Up @@ -41,4 +44,18 @@ export default class SettingsPage {

return currentIdentity;
}

async openPoliciesPage(){
const button = this.sideMenu.find("a").withExactText("Policies");
const policies = new PoliciesSection();
await t
.expect(button.visible)
.ok()
.click(button)
.expect(policies.container.visible)
.ok()
.expect(getLocation()).eql(`${editorUrl}/settings/policies`)

return policies;
}
}
113 changes: 113 additions & 0 deletions e2e/ui/spec/settings/edit-policies.js
@@ -0,0 +1,113 @@
import { expect } from 'chai';
import { Selector } from 'testcafe'
import { credentials, login } from '../../utils/auth-utils';
import { editorUrl } from '../../utils/constants';
import { waitFor } from '../../utils/assertion-utils';
import SettingsPage from '../../pages/Settings';
import { tweekManagementClient } from '../../clients/tweek-clients';

const settingsPage = new SettingsPage();

let policies;
let jwtPolicy;
const reset = ()=> {
tweekManagementClient.savePolicies(policies)
tweekManagementClient.saveJWTExtractionPolicy(jwtPolicy);
};

fixture`Edit Policies`.page`${editorUrl}/settings`
.httpAuth(credentials)
.beforeEach(login)
.before(async () => {
policies = await tweekManagementClient.getPolicies()
jwtPolicy = await tweekManagementClient.getJWTExtractionPolicy();
})
.after(reset);

test('Edit acl policies and save', async (t) => {
const policiesPage = await settingsPage.openPoliciesPage();

const editor = await policiesPage.currentTab();
const data = await editor.read();
expect(JSON.stringify(policies, null, 4)).eql(data);
const newData = JSON.stringify([...policies, {
"group": "dummy",
"user": "dummy",
"contexts": {},
"object": "values/*",
"action": "*",
"effect": "allow"
}], null, 4);

await editor.update(newData);

await editor.save();

await waitFor(async () =>
expect(JSON.stringify(await tweekManagementClient.getPolicies(), null, 4)).eql(newData)
);

})
.before(async (t)=>{
reset();
await login(t);
});

test('invalid acl policies, save disabled', async (t) => {
const policiesPage = await settingsPage.openPoliciesPage();

const editor = await policiesPage.currentTab();
const newData = JSON.stringify([...policies, {
"group": "dummy",
"user": "dummy",
"contexts": {},
"object": "val/*",
"action": "*",
"effect": "allow"
}], null, 4);

await editor.update(newData);

await t.expect(editor.hasChanges()).eql(true)
await t.expect(editor.isValid()).eql(false);
})

test('updated JWT policy and save', async (t) => {
const policiesPage = await settingsPage.openPoliciesPage();

const editor = await policiesPage.changeTab("JWT Extraction");
const newData = jwtPolicy.replace("input.sub", "input.upn");

await editor.update(newData);

await editor.save();

await waitFor(async () =>
expect(await tweekManagementClient.getJWTExtractionPolicy()).eql(newData)
);
}).before(async (t)=>{
reset();
await login(t);
});


test('Attempt to save JWT policy, show error', async (t) => {
const policiesPage = await settingsPage.openPoliciesPage();

const editor = await policiesPage.changeTab("JWT Extraction");
const newData = jwtPolicy.replace("input.sub", "inpu\"t.upn");

await editor.update(newData);

await editor.save();

await t.expect(
Selector('.notifications-br .notification-error .notification-title').withExactText(
'Error saving jwt-policy',
).visible
).ok();

}).before(async (t)=>{
reset();
await login(t);
});