admission 0.4.5 → 0.4.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|
-
}
|