admission 0.4.5 → 0.4.6
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/admission.gemspec +7 -7
- data/lib/admission/version.rb +1 -1
- metadata +5 -48
- data/.gitignore +0 -40
- data/.rspec +0 -2
- data/.ruby-version +0 -1
- data/Gemfile +0 -7
- data/LICENSE +0 -674
- data/README.md +0 -24
- data/bin/build +0 -10
- data/bin/rspec +0 -8
- data/spec/integration/action_arbitrating_spec.rb +0 -119
- data/spec/integration/resource_arbitrating_spec.rb +0 -276
- data/spec/rspec_config.rb +0 -103
- data/spec/spec_helper.rb +0 -28
- data/spec/test_context/country.rb +0 -24
- data/spec/test_context/index.rb +0 -5
- data/spec/test_context/person.rb +0 -31
- data/spec/test_context/persons_fixtures.rb +0 -43
- data/spec/test_context/privileges_and_rules.rb +0 -119
- data/spec/unit/arbitration_spec.rb +0 -33
- data/spec/unit/index_spec.rb +0 -144
- data/spec/unit/privilege/order_definer_spec.rb +0 -184
- data/spec/unit/privilege_spec.rb +0 -178
- data/spec/unit/rails/action_admission_spec.rb +0 -188
- data/spec/unit/rails/controller_addon_spec.rb +0 -68
- data/spec/unit/rails/scope_resolver_spec.rb +0 -72
- data/spec/unit/resource_arbitration_spec.rb +0 -76
- data/spec/unit/status_spec.rb +0 -79
- data/visualisation/.babelrc +0 -7
- data/visualisation/actions/index.js +0 -0
- data/visualisation/components/app_container.jsx +0 -78
- data/visualisation/components/input_with_select.jsx +0 -177
- data/visualisation/components/nested_list_row.jsx +0 -48
- data/visualisation/components/privilege_select.jsx +0 -70
- data/visualisation/components/privileges_panel.jsx +0 -73
- data/visualisation/components/rules_panel.jsx +0 -124
- data/visualisation/dist/.gitkeep +0 -0
- data/visualisation/helpers.js +0 -69
- data/visualisation/index.jsx +0 -89
- data/visualisation/package.json +0 -27
- data/visualisation/reducers/index.js +0 -35
- data/visualisation/server.rb +0 -23
- data/visualisation/style.scss +0 -248
- data/visualisation/webpack.config.js +0 -47
- data/visualisation/yarn.lock +0 -3354
@@ -1,70 +0,0 @@
|
|
1
|
-
import preact from 'preact';
|
2
|
-
import InputWithSelect from './input_with_select';
|
3
|
-
|
4
|
-
export default class PrivilegeSelect extends preact.Component {
|
5
|
-
|
6
|
-
constructor (props) {
|
7
|
-
super(props);
|
8
|
-
|
9
|
-
this.state = props.app.keyToPrivilege(props.defaultValue);
|
10
|
-
|
11
|
-
this.onNameSelected = this.onNameSelected.bind(this);
|
12
|
-
this.onLevelSelected = this.onLevelSelected.bind(this);
|
13
|
-
this.onClearSelection = this.onClearSelection.bind(this);
|
14
|
-
}
|
15
|
-
|
16
|
-
render ({app}, {name, level}) {
|
17
|
-
return <div className="controls-group">
|
18
|
-
<InputWithSelect
|
19
|
-
defaultText={name}
|
20
|
-
placeholder="name"
|
21
|
-
all_items={app.listPrivilegesNames()}
|
22
|
-
onSelect={this.onNameSelected}
|
23
|
-
/>
|
24
|
-
|
25
|
-
<InputWithSelect
|
26
|
-
defaultText={level}
|
27
|
-
placeholder="level"
|
28
|
-
all_items={app.listPrivilegeLevels(name)}
|
29
|
-
onSelect={this.onLevelSelected}
|
30
|
-
/>
|
31
|
-
|
32
|
-
<button
|
33
|
-
type="button"
|
34
|
-
tabIndex="-1"
|
35
|
-
className="button"
|
36
|
-
onClick={this.onClearSelection}>
|
37
|
-
Clear
|
38
|
-
</button>
|
39
|
-
</div>;
|
40
|
-
}
|
41
|
-
|
42
|
-
componentWillReceiveProps ({defaultValue}) {
|
43
|
-
if (defaultValue !== this.props.defaultValue) {
|
44
|
-
this.setState(this.props.app.keyToPrivilege(defaultValue));
|
45
|
-
}
|
46
|
-
}
|
47
|
-
|
48
|
-
onNameSelected (name) {
|
49
|
-
const levels = this.props.app.admission.levels[name];
|
50
|
-
let level;
|
51
|
-
if (!levels) level = 'base';
|
52
|
-
else level = levels[levels.length - 1];
|
53
|
-
|
54
|
-
this.setState({name, level});
|
55
|
-
this.props.onChanged({name, level});
|
56
|
-
}
|
57
|
-
|
58
|
-
onLevelSelected (level) {
|
59
|
-
const name = this.state.name;
|
60
|
-
this.setState({level});
|
61
|
-
this.props.onChanged({name, level});
|
62
|
-
}
|
63
|
-
|
64
|
-
onClearSelection () {
|
65
|
-
const selection = {name: '', level: ''};
|
66
|
-
this.setState(selection);
|
67
|
-
this.props.onChanged(selection);
|
68
|
-
}
|
69
|
-
|
70
|
-
}
|
@@ -1,73 +0,0 @@
|
|
1
|
-
import preact from 'preact';
|
2
|
-
import classnames from 'classnames';
|
3
|
-
import PrivilegeSelect from './privilege_select';
|
4
|
-
import NestedListRow from './nested_list_row';
|
5
|
-
|
6
|
-
export default class PrivilegesPanel extends preact.Component {
|
7
|
-
|
8
|
-
constructor (props) {
|
9
|
-
super(props);
|
10
|
-
|
11
|
-
this.state = {
|
12
|
-
roll_down_all: true,
|
13
|
-
privilege_key: ''
|
14
|
-
};
|
15
|
-
|
16
|
-
this.onToggleRollDownAll = this.onToggleRollDownAll.bind(this);
|
17
|
-
this.onPrivilegeSelected = this.onPrivilegeSelected.bind(this);
|
18
|
-
}
|
19
|
-
|
20
|
-
render ({app}, {privilege_key, roll_down_all}) {
|
21
|
-
const root_row = reduce_nested_data(app, {key: privilege_key});
|
22
|
-
|
23
|
-
return <div className="panel">
|
24
|
-
<div className="controls">
|
25
|
-
<div className="controls-group">
|
26
|
-
<div className={classnames('check_box', roll_down_all && 'checked')}
|
27
|
-
onClick={this.onToggleRollDownAll}>
|
28
|
-
{"\u25BC"}
|
29
|
-
</div>
|
30
|
-
</div>
|
31
|
-
|
32
|
-
<PrivilegeSelect
|
33
|
-
app={app}
|
34
|
-
defaultValue={privilege_key}
|
35
|
-
onChanged={this.onPrivilegeSelected}/>
|
36
|
-
</div>
|
37
|
-
|
38
|
-
<ul className="nested-list">
|
39
|
-
<NestedListRow
|
40
|
-
app={app}
|
41
|
-
content={root_row.content}
|
42
|
-
nestedRows={root_row.nested_rows}
|
43
|
-
defaultUnrolled={roll_down_all}/>
|
44
|
-
</ul>
|
45
|
-
</div>;
|
46
|
-
}
|
47
|
-
|
48
|
-
onToggleRollDownAll () {
|
49
|
-
this.setState({roll_down_all: !this.state.roll_down_all});
|
50
|
-
}
|
51
|
-
|
52
|
-
onPrivilegeSelected (privilege) {
|
53
|
-
this.setState({privilege_key: this.props.app.privilegeToKey(privilege)});
|
54
|
-
}
|
55
|
-
|
56
|
-
}
|
57
|
-
|
58
|
-
function reduce_nested_data (app, {privilege, key}) {
|
59
|
-
if (!privilege && key) privilege = app.getPrivilegeData(key);
|
60
|
-
let nested;
|
61
|
-
|
62
|
-
if (!privilege) {
|
63
|
-
nested = app.admission.top_levels;
|
64
|
-
} else if (privilege.inherits) {
|
65
|
-
nested = privilege.inherits;
|
66
|
-
}
|
67
|
-
if (nested) nested = nested.map(p => reduce_nested_data(app, {key: p}));
|
68
|
-
|
69
|
-
return {
|
70
|
-
content: (privilege ? app.privilegeToKey(privilege) : '-listing-'),
|
71
|
-
nested_rows: nested
|
72
|
-
};
|
73
|
-
}
|
@@ -1,124 +0,0 @@
|
|
1
|
-
import preact from 'preact';
|
2
|
-
import classnames from 'classnames';
|
3
|
-
import InputWithSelect from './input_with_select';
|
4
|
-
import NestedListRow from './nested_list_row';
|
5
|
-
|
6
|
-
export default class RulesPanel extends preact.Component {
|
7
|
-
|
8
|
-
constructor (props) {
|
9
|
-
super(props);
|
10
|
-
|
11
|
-
this.onToggleRollDownAll = this.onToggleRollDownAll.bind(this);
|
12
|
-
this.onScopeSelected = this.onScopeSelected.bind(this);
|
13
|
-
this.onActionSelected = this.onActionSelected.bind(this);
|
14
|
-
}
|
15
|
-
|
16
|
-
render ({app}, {scope, action, roll_down_all}) {
|
17
|
-
const rules = filter_index_for_scope(app.admission.rules, scope);
|
18
|
-
const scopes = reduce_scopes(rules, {action});
|
19
|
-
|
20
|
-
return <div className="panel">
|
21
|
-
<div className="controls">
|
22
|
-
<div className="controls-group">
|
23
|
-
<div className={classnames('check_box', roll_down_all && 'checked')}
|
24
|
-
onClick={this.onToggleRollDownAll}>
|
25
|
-
{"\u25BC"}
|
26
|
-
</div>
|
27
|
-
</div>
|
28
|
-
|
29
|
-
<div className="controls-group">
|
30
|
-
<InputWithSelect
|
31
|
-
defaultText={scope}
|
32
|
-
placeholder="scope"
|
33
|
-
enterable
|
34
|
-
nullable
|
35
|
-
all_items={Object.keys(app.admission.rules)}
|
36
|
-
onSelect={this.onScopeSelected}
|
37
|
-
/>
|
38
|
-
|
39
|
-
<InputWithSelect
|
40
|
-
defaultText={action}
|
41
|
-
placeholder="action"
|
42
|
-
enterable
|
43
|
-
nullable
|
44
|
-
all_items={list_actions(rules)}
|
45
|
-
onSelect={this.onActionSelected}
|
46
|
-
/>
|
47
|
-
</div>
|
48
|
-
</div>
|
49
|
-
|
50
|
-
<ul className="nested-list">
|
51
|
-
{scopes.map(scope =>
|
52
|
-
<NestedListRow
|
53
|
-
app={app}
|
54
|
-
content={scope.content}
|
55
|
-
nestedRows={scope.nested_rows}
|
56
|
-
defaultUnrolled={roll_down_all}/>
|
57
|
-
)}
|
58
|
-
</ul>
|
59
|
-
</div>;
|
60
|
-
}
|
61
|
-
|
62
|
-
onToggleRollDownAll () {
|
63
|
-
this.setState({roll_down_all: !this.state.roll_down_all});
|
64
|
-
}
|
65
|
-
|
66
|
-
onScopeSelected (scope) {
|
67
|
-
this.setState({scope});
|
68
|
-
}
|
69
|
-
|
70
|
-
onActionSelected (action) {
|
71
|
-
this.setState({action});
|
72
|
-
}
|
73
|
-
|
74
|
-
}
|
75
|
-
|
76
|
-
function filter_index_for_scope (rules, scope) {
|
77
|
-
if (!scope) return rules;
|
78
|
-
const filtered = Object.assign({}, rules);
|
79
|
-
Object.keys(filtered).forEach(key => {
|
80
|
-
if (!key.includes(scope)) delete filtered[key]
|
81
|
-
});
|
82
|
-
return filtered;
|
83
|
-
}
|
84
|
-
|
85
|
-
function reduce_scopes (index, {action}) {
|
86
|
-
return Object.keys(index)
|
87
|
-
.map(scope => {
|
88
|
-
const actions = reduce_actions(index[scope], {action});
|
89
|
-
if (!actions.length) return null;
|
90
|
-
return {
|
91
|
-
content: scope,
|
92
|
-
nested_rows: actions
|
93
|
-
};
|
94
|
-
})
|
95
|
-
.filter(item => item);
|
96
|
-
}
|
97
|
-
|
98
|
-
function reduce_actions (index, {action}) {
|
99
|
-
let selected = Object.keys(index);
|
100
|
-
if (action) selected = selected.filter(a => a.includes(action));
|
101
|
-
|
102
|
-
return selected.map(action => {
|
103
|
-
return {
|
104
|
-
content: action,
|
105
|
-
nested_rows: reduce_privileges(index[action])
|
106
|
-
}
|
107
|
-
});
|
108
|
-
}
|
109
|
-
|
110
|
-
function reduce_privileges (index) {
|
111
|
-
return Object.keys(index).map(privilege_key => {
|
112
|
-
return {
|
113
|
-
content: `${privilege_key}: ${index[privilege_key]}`
|
114
|
-
};
|
115
|
-
});
|
116
|
-
}
|
117
|
-
|
118
|
-
function list_actions (index) {
|
119
|
-
let all = [];
|
120
|
-
Object.keys(index).forEach(k => all = all.concat(Object.keys(index[k])));
|
121
|
-
return all.filter((name, i, arr) => {
|
122
|
-
return i === arr.indexOf(name);
|
123
|
-
});
|
124
|
-
}
|
data/visualisation/dist/.gitkeep
DELETED
File without changes
|
data/visualisation/helpers.js
DELETED
@@ -1,69 +0,0 @@
|
|
1
|
-
|
2
|
-
const helpers = {
|
3
|
-
|
4
|
-
debounce (func, wait, immediate) {
|
5
|
-
let timeout, context, args;
|
6
|
-
|
7
|
-
if (immediate) {
|
8
|
-
return function () {
|
9
|
-
let call_now = true;
|
10
|
-
context = this;
|
11
|
-
args = arguments;
|
12
|
-
|
13
|
-
if (timeout) {
|
14
|
-
call_now = false;
|
15
|
-
clearTimeout(timeout);
|
16
|
-
}
|
17
|
-
timeout = setTimeout(function () {
|
18
|
-
timeout = null;
|
19
|
-
}, wait);
|
20
|
-
if (call_now) func.apply(context, args);
|
21
|
-
};
|
22
|
-
|
23
|
-
} else {
|
24
|
-
return function () {
|
25
|
-
context = this;
|
26
|
-
args = arguments;
|
27
|
-
|
28
|
-
if (timeout) clearTimeout(timeout);
|
29
|
-
|
30
|
-
timeout = setTimeout(function () {
|
31
|
-
timeout = null;
|
32
|
-
func.apply(context, args);
|
33
|
-
}, wait);
|
34
|
-
};
|
35
|
-
}
|
36
|
-
},
|
37
|
-
|
38
|
-
throttle (callback, time, immediate) {
|
39
|
-
let timeout, call_at_end, context, args;
|
40
|
-
|
41
|
-
return function () {
|
42
|
-
context = this;
|
43
|
-
args = arguments;
|
44
|
-
|
45
|
-
// throttling block
|
46
|
-
if (timeout) {
|
47
|
-
call_at_end = true;
|
48
|
-
return;
|
49
|
-
}
|
50
|
-
|
51
|
-
// throttler - fire only if there was event in the mean-time
|
52
|
-
let timeout_f = function () {
|
53
|
-
timeout = null;
|
54
|
-
if (call_at_end) {
|
55
|
-
call_at_end = false;
|
56
|
-
timeout = setTimeout(timeout_f, time);
|
57
|
-
callback.apply(context, args);
|
58
|
-
}
|
59
|
-
};
|
60
|
-
|
61
|
-
call_at_end = true;
|
62
|
-
if (immediate) timeout_f();
|
63
|
-
else timeout = setTimeout(timeout_f, time);
|
64
|
-
};
|
65
|
-
}
|
66
|
-
|
67
|
-
};
|
68
|
-
|
69
|
-
export default helpers;
|
data/visualisation/index.jsx
DELETED
@@ -1,89 +0,0 @@
|
|
1
|
-
import 'normalize.css';
|
2
|
-
import './style.scss';
|
3
|
-
import 'whatwg-fetch';
|
4
|
-
|
5
|
-
import preact from 'preact';
|
6
|
-
import { createStore } from 'redux';
|
7
|
-
import admissionApp from './reducers';
|
8
|
-
import actions from './actions';
|
9
|
-
import AppContainer from './components/app_container';
|
10
|
-
|
11
|
-
document.addEventListener('DOMContentLoaded',function(){
|
12
|
-
|
13
|
-
app.store = createStore(admissionApp);
|
14
|
-
app.container = document.getElementById('admission-visualisation');
|
15
|
-
window.app = app;
|
16
|
-
|
17
|
-
preact.render(
|
18
|
-
<AppContainer
|
19
|
-
ref={c => app.container_component = c}
|
20
|
-
app={app}
|
21
|
-
onMounted={start_app}/>,
|
22
|
-
app.container
|
23
|
-
);
|
24
|
-
|
25
|
-
function start_app () {
|
26
|
-
fetch(app.container.dataset.url, {
|
27
|
-
credentials: 'include'
|
28
|
-
|
29
|
-
}).then(response => {
|
30
|
-
if (!response.ok) {
|
31
|
-
app.container_component.setState({loaded: true, load_fail: response.statusText});
|
32
|
-
return;
|
33
|
-
}
|
34
|
-
|
35
|
-
response.json().then(data => {
|
36
|
-
app.admission = data;
|
37
|
-
app.store.dispatch({type: 'APP_READY'});
|
38
|
-
|
39
|
-
}).catch(err => {
|
40
|
-
app.container_component.setState({loaded: true, load_fail: err.message});
|
41
|
-
|
42
|
-
});
|
43
|
-
|
44
|
-
}).catch(err => {
|
45
|
-
app.container_component.setState({loaded: true, load_fail: err.message});
|
46
|
-
|
47
|
-
});
|
48
|
-
}
|
49
|
-
|
50
|
-
});
|
51
|
-
|
52
|
-
const app = {
|
53
|
-
|
54
|
-
getPrivilegeData (key) {
|
55
|
-
const {name, level} = app.keyToPrivilege(key);
|
56
|
-
return this.admission.privileges
|
57
|
-
.find(p => p.name === name && p.level === level);
|
58
|
-
},
|
59
|
-
|
60
|
-
listPrivilegesNames () {
|
61
|
-
return this.admission.privileges
|
62
|
-
.map(p => p.name)
|
63
|
-
.filter((name, i, arr) => {
|
64
|
-
return i === arr.indexOf(name);
|
65
|
-
});
|
66
|
-
},
|
67
|
-
|
68
|
-
listPrivilegeLevels (name) {
|
69
|
-
if (!name) return [];
|
70
|
-
return this.admission.privileges
|
71
|
-
.filter(p => p.name === name)
|
72
|
-
.map(p => p.level);
|
73
|
-
},
|
74
|
-
|
75
|
-
privilegeToKey: function ({name, level}) {
|
76
|
-
if (!level || level === 'base') return name || '';
|
77
|
-
return `${name}-${level}`
|
78
|
-
},
|
79
|
-
|
80
|
-
keyToPrivilege (key) {
|
81
|
-
if (!key) return {name: '', level: ''};
|
82
|
-
let [name, level] = key.split('-');
|
83
|
-
if (!level) level = 'base';
|
84
|
-
return {name, level};
|
85
|
-
},
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
};
|
data/visualisation/package.json
DELETED
@@ -1,27 +0,0 @@
|
|
1
|
-
{
|
2
|
-
"name": "addmission_visualisation",
|
3
|
-
"main": "index.js",
|
4
|
-
"private": true,
|
5
|
-
"scripts": {
|
6
|
-
"server": "ruby server.rb",
|
7
|
-
"webpack": "rm -rf build && node_modules/.bin/webpack --watch",
|
8
|
-
"build": "BUILD=dist node_modules/.bin/webpack"
|
9
|
-
},
|
10
|
-
"dependencies": {
|
11
|
-
"babel-core": "^6.24.1",
|
12
|
-
"babel-loader": "^7.0.0",
|
13
|
-
"babel-plugin-transform-react-jsx": "^6.24.1",
|
14
|
-
"babel-preset-es2015": "^6.24.1",
|
15
|
-
"classnames": "^2.2.5",
|
16
|
-
"css-loader": "^0.28.4",
|
17
|
-
"node-sass": "^4.5.3",
|
18
|
-
"normalize.css": "^7.0.0",
|
19
|
-
"preact": "^8.1.0",
|
20
|
-
"redux": "^3.6.0",
|
21
|
-
"sass-loader": "^6.0.5",
|
22
|
-
"style-loader": "^0.18.2",
|
23
|
-
"uglifyjs-webpack-plugin": "^0.4.6",
|
24
|
-
"webpack": "^2.6.1",
|
25
|
-
"whatwg-fetch": "^2.0.3"
|
26
|
-
}
|
27
|
-
}
|