conjur-asset-ui-api 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.git-hooks/pre_commit/ensure_livescript_compiled.rb +31 -0
- data/.git-hooks/pre_commit/trailing_whitespace.rb +26 -0
- data/.gitignore +20 -0
- data/.overcommit.yml +5 -0
- data/.project +18 -0
- data/Gemfile +8 -0
- data/LICENSE.txt +22 -0
- data/README.md +41 -0
- data/Rakefile +1 -0
- data/compile_ls +2 -0
- data/conjur-asset-ui.gemspec +36 -0
- data/lib/conjur-asset-ui-version.rb +7 -0
- data/lib/conjur-asset-ui.rb +7 -0
- data/lib/conjur/audit/follower.rb +63 -0
- data/lib/conjur/audit/humanizer.rb +53 -0
- data/lib/conjur/audit/tableizer.rb +55 -0
- data/lib/conjur/command/ui.rb +38 -0
- data/lib/conjur/webserver/api_proxy.rb +94 -0
- data/lib/conjur/webserver/audit_stream.rb +92 -0
- data/lib/conjur/webserver/authorize.rb +28 -0
- data/lib/conjur/webserver/conjur_info.rb +33 -0
- data/lib/conjur/webserver/home.rb +36 -0
- data/lib/conjur/webserver/login.rb +50 -0
- data/lib/conjur/webserver/server.rb +111 -0
- data/livescript/views/audit.ls +124 -0
- data/public/css/bootstrap.css +7 -0
- data/public/css/styles.less +400 -0
- data/public/fonts/glyphicons-halflings-regular.eot +0 -0
- data/public/fonts/glyphicons-halflings-regular.svg +229 -0
- data/public/fonts/glyphicons-halflings-regular.ttf +0 -0
- data/public/fonts/glyphicons-halflings-regular.woff +0 -0
- data/public/images/conjur-logo.svg +26 -0
- data/public/images/icon-client-pc.svg +12 -0
- data/public/images/icon-environment.png +0 -0
- data/public/images/icon-person.svg +12 -0
- data/public/images/icon-service-dots.svg +13 -0
- data/public/images/icon-variable.png +0 -0
- data/public/index.html +121 -0
- data/public/js/lib/JSXTransformer.js +10862 -0
- data/public/js/lib/async.js +958 -0
- data/public/js/lib/backbone.js +2 -0
- data/public/js/lib/bootstrap.js +6 -0
- data/public/js/lib/date.extensions.js +141 -0
- data/public/js/lib/less.js +16 -0
- data/public/js/lib/moment.js +7768 -0
- data/public/js/lib/pace.js +2 -0
- data/public/js/lib/prelude-browser-min.js +1 -0
- data/public/js/lib/react-with-addons.js +15505 -0
- data/public/js/lib/react.js +14469 -0
- data/public/js/lib/sorted-set.no-require.js +1170 -0
- data/public/js/lib/sorted-set.no-require.js.txt +6 -0
- data/public/js/lib/underscore-min.js +6 -0
- data/public/js/lib/underscore.string.min.js +1 -0
- data/public/js/main.js +353 -0
- data/public/js/models/namespace.js +6 -0
- data/public/js/models/policyList.js +10 -0
- data/public/js/models/record.js +26 -0
- data/public/js/models/resourceList.js +61 -0
- data/public/js/models/userList.js +16 -0
- data/public/js/models/variableList.js +12 -0
- data/public/js/views/audit.js +191 -0
- data/public/js/views/dashboard.js +35 -0
- data/public/js/views/generic.js +42 -0
- data/public/js/views/group.js +32 -0
- data/public/js/views/groups.js +18 -0
- data/public/js/views/host.js +40 -0
- data/public/js/views/hosts.js +18 -0
- data/public/js/views/layer.js +63 -0
- data/public/js/views/layers.js +18 -0
- data/public/js/views/mixins/search.js +9 -0
- data/public/js/views/namespaces.js +40 -0
- data/public/js/views/navSearch.js +16 -0
- data/public/js/views/permissions.js +91 -0
- data/public/js/views/policies.js +17 -0
- data/public/js/views/policy.js +23 -0
- data/public/js/views/resource.js +23 -0
- data/public/js/views/role.js +18 -0
- data/public/js/views/searchResults.js +146 -0
- data/public/js/views/time.js +14 -0
- data/public/js/views/user.js +22 -0
- data/public/js/views/users.js +18 -0
- data/public/js/views/variable.js +41 -0
- data/public/js/views/variables.js +18 -0
- data/vendor/prelude-ls/.gitignore +2 -0
- data/vendor/prelude-ls/.travis.yml +3 -0
- data/vendor/prelude-ls/CHANGELOG.md +81 -0
- data/vendor/prelude-ls/LICENSE +22 -0
- data/vendor/prelude-ls/Makefile +50 -0
- data/vendor/prelude-ls/README.md +15 -0
- data/vendor/prelude-ls/browser/prelude-browser-min.js +1 -0
- data/vendor/prelude-ls/browser/prelude-browser.js +1172 -0
- data/vendor/prelude-ls/lib/Func.js +40 -0
- data/vendor/prelude-ls/lib/List.js +602 -0
- data/vendor/prelude-ls/lib/Num.js +129 -0
- data/vendor/prelude-ls/lib/Obj.js +153 -0
- data/vendor/prelude-ls/lib/Str.js +68 -0
- data/vendor/prelude-ls/lib/index.js +164 -0
- data/vendor/prelude-ls/package.json +50 -0
- data/vendor/prelude-ls/package.ls +46 -0
- data/vendor/prelude-ls/src/Func.ls +17 -0
- data/vendor/prelude-ls/src/List.ls +299 -0
- data/vendor/prelude-ls/src/Num.ls +83 -0
- data/vendor/prelude-ls/src/Obj.ls +61 -0
- data/vendor/prelude-ls/src/Str.ls +32 -0
- data/vendor/prelude-ls/src/index.ls +56 -0
- data/vendor/prelude-ls/test/Func.ls +36 -0
- data/vendor/prelude-ls/test/List.ls +751 -0
- data/vendor/prelude-ls/test/Num.ls +258 -0
- data/vendor/prelude-ls/test/Obj.ls +145 -0
- data/vendor/prelude-ls/test/Prelude.ls +49 -0
- data/vendor/prelude-ls/test/Str.ls +208 -0
- data/vendor/prelude-ls/test/browser.html +5 -0
- metadata +328 -0
@@ -0,0 +1,16 @@
|
|
1
|
+
if (typeof $ === "undefined") { throw new Error("jQuery is required") }
|
2
|
+
|
3
|
+
var UserListModel = function(){
|
4
|
+
var options = {
|
5
|
+
namespaceSelector: function(member) {
|
6
|
+
var idTokens = member.id.split('@');
|
7
|
+
if ( idTokens.length > 1 ) {
|
8
|
+
return idTokens.slice(1, idTokens.length-1).join['@'];
|
9
|
+
}
|
10
|
+
else {
|
11
|
+
return null;
|
12
|
+
}
|
13
|
+
}
|
14
|
+
};
|
15
|
+
return ResourceListModel("user", options);
|
16
|
+
}
|
@@ -0,0 +1,12 @@
|
|
1
|
+
if (typeof $ === "undefined") { throw new Error("jQuery is required") }
|
2
|
+
|
3
|
+
var VariableListModel = function(){
|
4
|
+
var options = {
|
5
|
+
filter: function(member) {
|
6
|
+
var idTokens = member.id.split(':');
|
7
|
+
var id = idTokens[idTokens.length-1];
|
8
|
+
return id.split('/').length > 1;
|
9
|
+
}
|
10
|
+
};
|
11
|
+
return ResourceListModel("variable", options);
|
12
|
+
}
|
@@ -0,0 +1,191 @@
|
|
1
|
+
// Generated by LiveScript 1.2.0
|
2
|
+
(function(){
|
3
|
+
var ref$, table, div, th, tr, td, thead, tbody, section, h3, time, map, each, unique, isType, join, fields, AuditTableHeader, Timestamp, wrapArray, AuditEntry, newEventSet, AuditTable, GlobalAudit, urlOfRole, urlOfResource, AuditBox, out$ = typeof exports != 'undefined' && exports || this;
|
4
|
+
ref$ = React.DOM, table = ref$.table, div = ref$.div, th = ref$.th, tr = ref$.tr, td = ref$.td, thead = ref$.thead, tbody = ref$.tbody, section = ref$.section, h3 = ref$.h3, time = ref$.time;
|
5
|
+
ref$ = require('prelude-ls'), map = ref$.map, each = ref$.each, unique = ref$.unique, isType = ref$.isType, join = ref$.join;
|
6
|
+
fields = ['timestamp', 'user', 'acting_as', 'action', 'kind', 'entity', 'privilege'];
|
7
|
+
AuditTableHeader = React.createClass({
|
8
|
+
displayName: 'AuditTableHeader',
|
9
|
+
render: function(){
|
10
|
+
return thead({}, tr({}, map(function(it){
|
11
|
+
return th({
|
12
|
+
key: it
|
13
|
+
}, it.replace('_', ' '));
|
14
|
+
})(
|
15
|
+
fields)));
|
16
|
+
}
|
17
|
+
});
|
18
|
+
Timestamp = React.createClass({
|
19
|
+
displayName: 'Timestamp',
|
20
|
+
render: function(){
|
21
|
+
var ts;
|
22
|
+
ts = moment(this.props.time);
|
23
|
+
return time({
|
24
|
+
datetime: ts.format(),
|
25
|
+
title: ts.calendar()
|
26
|
+
}, [ts.fromNow()]);
|
27
|
+
}
|
28
|
+
});
|
29
|
+
wrapArray = function(it){
|
30
|
+
if (isType('Array', it)) {
|
31
|
+
return it;
|
32
|
+
} else {
|
33
|
+
return [it];
|
34
|
+
}
|
35
|
+
};
|
36
|
+
AuditEntry = React.createClass({
|
37
|
+
displayName: 'AuditEntry',
|
38
|
+
transformedProps: function(){
|
39
|
+
var ref$;
|
40
|
+
return ref$ = clone$(this.props), ref$.entity = this.props.resource || this.props.role, ref$;
|
41
|
+
},
|
42
|
+
transformField: function(key, value){
|
43
|
+
switch (false) {
|
44
|
+
case !!value:
|
45
|
+
return value;
|
46
|
+
case key !== 'user' && key !== 'acting_as':
|
47
|
+
return RoleLink({
|
48
|
+
id: value
|
49
|
+
});
|
50
|
+
case key !== 'entity':
|
51
|
+
return ResourceLink({
|
52
|
+
data: value
|
53
|
+
});
|
54
|
+
case key !== 'timestamp':
|
55
|
+
return Timestamp({
|
56
|
+
time: value
|
57
|
+
});
|
58
|
+
default:
|
59
|
+
return value;
|
60
|
+
}
|
61
|
+
},
|
62
|
+
render: function(){
|
63
|
+
var props, this$ = this;
|
64
|
+
props = this.transformedProps();
|
65
|
+
return tr({
|
66
|
+
className: this.props.action
|
67
|
+
}, map(function(it){
|
68
|
+
return td({
|
69
|
+
key: it
|
70
|
+
}, [this$.transformField(it, props[it])]);
|
71
|
+
})(
|
72
|
+
fields));
|
73
|
+
}
|
74
|
+
});
|
75
|
+
newEventSet = function(){
|
76
|
+
var evts;
|
77
|
+
evts = new SortedSet({
|
78
|
+
comparator: function(a, b){
|
79
|
+
return a && b && b.id - a.id;
|
80
|
+
}
|
81
|
+
});
|
82
|
+
evts.containsLike = function(item){
|
83
|
+
var existing;
|
84
|
+
existing = this.findIterator(item).value();
|
85
|
+
if (existing != null) {
|
86
|
+
return this.priv.comparator(existing, item) === 0;
|
87
|
+
}
|
88
|
+
};
|
89
|
+
return evts;
|
90
|
+
};
|
91
|
+
AuditTable = React.createClass({
|
92
|
+
displayName: 'AuditTable',
|
93
|
+
getInitialState: function(){
|
94
|
+
return {
|
95
|
+
events: newEventSet()
|
96
|
+
};
|
97
|
+
},
|
98
|
+
render: function(){
|
99
|
+
return section({
|
100
|
+
className: 'audit'
|
101
|
+
}, [
|
102
|
+
h3({}, this.props.caption), table({
|
103
|
+
className: 'audit-table'
|
104
|
+
}, [
|
105
|
+
AuditTableHeader({
|
106
|
+
key: 'thead'
|
107
|
+
}), tbody({
|
108
|
+
key: 'tbody'
|
109
|
+
}, this.state.events.map(function(it){
|
110
|
+
var ref$;
|
111
|
+
return new AuditEntry((ref$ = clone$(it), ref$.key = it.id, ref$));
|
112
|
+
}))
|
113
|
+
])
|
114
|
+
]);
|
115
|
+
},
|
116
|
+
componentDidMount: function(){
|
117
|
+
return each(this.addSource)(
|
118
|
+
wrapArray(
|
119
|
+
this.props.src));
|
120
|
+
},
|
121
|
+
componentWillUnmount: function(){
|
122
|
+
return each(function(it){
|
123
|
+
console.log("closing event source ", it);
|
124
|
+
return it.close();
|
125
|
+
})(
|
126
|
+
this.sources);
|
127
|
+
},
|
128
|
+
addEvent: function(arg$){
|
129
|
+
var data, event;
|
130
|
+
data = arg$.data;
|
131
|
+
event = JSON.parse(data);
|
132
|
+
if (event.action === "check" && event.privilege === "read" && event.allowed) {
|
133
|
+
return true;
|
134
|
+
} else {
|
135
|
+
if (!this.state.events.containsLike(event)) {
|
136
|
+
this.state.events.insert(event);
|
137
|
+
return this.forceUpdate();
|
138
|
+
}
|
139
|
+
}
|
140
|
+
},
|
141
|
+
addSource: function(url){
|
142
|
+
var evtSrc;
|
143
|
+
console.log("opening eventsource to " + url);
|
144
|
+
evtSrc = new EventSource(url);
|
145
|
+
console.log(evtSrc);
|
146
|
+
evtSrc.onmessage = this.addEvent;
|
147
|
+
evtSrc.onerror = function(a, b, c, d){
|
148
|
+
return console.log(a, b, c, d);
|
149
|
+
};
|
150
|
+
return (this.sources || (this.sources = [])).push(evtSrc);
|
151
|
+
}
|
152
|
+
});
|
153
|
+
out$.GlobalAudit = GlobalAudit = React.createClass({
|
154
|
+
displayName: 'GlobalAudit',
|
155
|
+
render: function(){
|
156
|
+
return AuditTable({
|
157
|
+
src: '/api/audit/all',
|
158
|
+
caption: 'All recent audit events'
|
159
|
+
});
|
160
|
+
}
|
161
|
+
});
|
162
|
+
urlOfRole = function(role){
|
163
|
+
return "/api/audit/roles/" + encodeURIComponent(role);
|
164
|
+
};
|
165
|
+
urlOfResource = function(resource){
|
166
|
+
return "/api/audit/resources/" + encodeURIComponent(resource);
|
167
|
+
};
|
168
|
+
out$.AuditBox = AuditBox = React.createClass({
|
169
|
+
displayName: 'AuditBox',
|
170
|
+
render: function(){
|
171
|
+
var roles, resources, roleSrcs, resSrcs, things;
|
172
|
+
roles = this.props.roles || [];
|
173
|
+
resources = this.props.resources || [];
|
174
|
+
roleSrcs = map(urlOfRole)(
|
175
|
+
roles);
|
176
|
+
resSrcs = map(urlOfResource)(
|
177
|
+
resources);
|
178
|
+
things = join(', ')(
|
179
|
+
unique(
|
180
|
+
roles.concat(resources)));
|
181
|
+
return AuditTable({
|
182
|
+
src: roleSrcs.concat(resSrcs),
|
183
|
+
caption: "Recent audit events for " + things
|
184
|
+
});
|
185
|
+
}
|
186
|
+
});
|
187
|
+
function clone$(it){
|
188
|
+
function fun(){} fun.prototype = it;
|
189
|
+
return new fun;
|
190
|
+
}
|
191
|
+
}).call(this);
|
@@ -0,0 +1,35 @@
|
|
1
|
+
/**@jsx React.DOM*/
|
2
|
+
|
3
|
+
var DashboardSearchForm = React.createClass({
|
4
|
+
mixins: [ SearchMixin ],
|
5
|
+
|
6
|
+
render: function(){
|
7
|
+
return (
|
8
|
+
<form className="form-inline search" role="search" onSubmit={this.handleSubmit}>
|
9
|
+
<div className="form-group">
|
10
|
+
<input ref="input" type="text" className="form-control" placeholder="Search Conjur" value={this.props.searchText}>
|
11
|
+
</input>
|
12
|
+
</div>
|
13
|
+
<button type="submit" className="btn btn-default search-button">Search</button>
|
14
|
+
</form>
|
15
|
+
);
|
16
|
+
}
|
17
|
+
});
|
18
|
+
|
19
|
+
var Dashboard = React.createClass({
|
20
|
+
render: function(){
|
21
|
+
return (
|
22
|
+
<div className="dashboard">
|
23
|
+
<div className="row">
|
24
|
+
<DashboardSearchForm />
|
25
|
+
</div>
|
26
|
+
<div className="summary">
|
27
|
+
<div className="row">
|
28
|
+
</div>
|
29
|
+
<div className="row">
|
30
|
+
</div>
|
31
|
+
</div>
|
32
|
+
</div>
|
33
|
+
);
|
34
|
+
}
|
35
|
+
});
|
@@ -0,0 +1,42 @@
|
|
1
|
+
/** @jsx React.DOM */
|
2
|
+
|
3
|
+
var GenericListItem = React.createClass({
|
4
|
+
render: function() {
|
5
|
+
var recordUrl = "/ui/" + this.props.data.kind + "/" + encodeURIComponent(this.props.data.record.identifier);
|
6
|
+
return (
|
7
|
+
<tr>
|
8
|
+
<td className="id">
|
9
|
+
<a href={recordUrl}>
|
10
|
+
{this.props.data.record.identifier}
|
11
|
+
</a>
|
12
|
+
</td>
|
13
|
+
<td className="ownerId">
|
14
|
+
<RoleLink id={this.props.data.record.ownerid || this.props.data.record.owner} />
|
15
|
+
</td>
|
16
|
+
</tr>
|
17
|
+
);
|
18
|
+
}
|
19
|
+
});
|
20
|
+
|
21
|
+
var GenericList = React.createClass({
|
22
|
+
render: function() {
|
23
|
+
var rows = this.props.data.members.map(function (o) {
|
24
|
+
var componentName = _.str.capitalize(this.props.data.kind.substring(0, this.props.data.kind.length-1)) + "ListItem";
|
25
|
+
var itemKind = window[componentName] || GenericListItem;
|
26
|
+
return itemKind({data: {kind: this.props.data.kind, record: o}});
|
27
|
+
}.bind(this));
|
28
|
+
return (
|
29
|
+
<table className={this.props.data.kind + "List"}>
|
30
|
+
<thead>
|
31
|
+
<tr>
|
32
|
+
<th>Id</th>
|
33
|
+
<th>Owner</th>
|
34
|
+
</tr>
|
35
|
+
</thead>
|
36
|
+
<tbody>
|
37
|
+
{rows}
|
38
|
+
</tbody>
|
39
|
+
</table>
|
40
|
+
);
|
41
|
+
}
|
42
|
+
});
|
@@ -0,0 +1,32 @@
|
|
1
|
+
/** @jsx React.DOM */
|
2
|
+
|
3
|
+
var Group = React.createClass({
|
4
|
+
render: function() {
|
5
|
+
var members = this.props.data.members.map(function (member) {
|
6
|
+
return <li>
|
7
|
+
<RoleLink id={member.member} />
|
8
|
+
</li>
|
9
|
+
}.bind(this));
|
10
|
+
var resourceId = [ conjurConfiguration.account, 'group', this.props.data.group.id ].join(':')
|
11
|
+
var group = this.props.data.group;
|
12
|
+
return (
|
13
|
+
<div className="group">
|
14
|
+
<h2>Group {this.props.data.group.id}</h2>
|
15
|
+
<dl>
|
16
|
+
<dt>Owner</dt>
|
17
|
+
<dd><RoleLink id={this.props.data.group.ownerid}/></dd>
|
18
|
+
<dt>Members</dt>
|
19
|
+
<dd>
|
20
|
+
<ul>
|
21
|
+
{members}
|
22
|
+
</ul>
|
23
|
+
</dd>
|
24
|
+
</dl>
|
25
|
+
<Permissions role={group.roleid}/>
|
26
|
+
<div className="audit auditGroup">
|
27
|
+
<AuditBox roles={[resourceId]} resources={[resourceId]}/>
|
28
|
+
</div>
|
29
|
+
</div>
|
30
|
+
);
|
31
|
+
}
|
32
|
+
});
|
@@ -0,0 +1,18 @@
|
|
1
|
+
/** @jsx React.DOM */
|
2
|
+
|
3
|
+
var GroupBox = React.createClass({
|
4
|
+
getInitialState: function() {
|
5
|
+
return { currentNamespace: "", members: [] };
|
6
|
+
},
|
7
|
+
render: function() {
|
8
|
+
return (
|
9
|
+
<div className="groupBox">
|
10
|
+
<NamespaceFilter currentNamespace={this.state.currentNamespace} namespaces={this.props.data.namespaces} />
|
11
|
+
<div className="groupList">
|
12
|
+
<h2>Groups</h2>
|
13
|
+
<GenericList data={{kind: "groups", members: this.state.members}} />
|
14
|
+
</div>
|
15
|
+
</div>
|
16
|
+
);
|
17
|
+
}
|
18
|
+
});
|
@@ -0,0 +1,40 @@
|
|
1
|
+
/** @jsx React.DOM */
|
2
|
+
|
3
|
+
var HostLink = React.createClass({
|
4
|
+
hostId : function() {
|
5
|
+
return this.props.data.split(':')[2];
|
6
|
+
},
|
7
|
+
|
8
|
+
hostUrl: function() {
|
9
|
+
return "/ui/hosts/" + encodeURIComponent(this.hostId());
|
10
|
+
},
|
11
|
+
|
12
|
+
render: function() {
|
13
|
+
return (
|
14
|
+
<a href={this.hostUrl()}>
|
15
|
+
{this.hostId()}
|
16
|
+
</a>
|
17
|
+
);
|
18
|
+
}
|
19
|
+
});
|
20
|
+
|
21
|
+
var Host = React.createClass({
|
22
|
+
render: function(){
|
23
|
+
var host = this.props.data;
|
24
|
+
return (
|
25
|
+
<div className="host">
|
26
|
+
<h2> Host {host.id} </h2>
|
27
|
+
<dl>
|
28
|
+
<dt> Owner </dt>
|
29
|
+
<dd> <RoleLink id={host.ownerid}/> </dd>
|
30
|
+
<dt> Created At </dt>
|
31
|
+
<dd> <Time timestamp={host.created_at}/> </dd>
|
32
|
+
</dl>
|
33
|
+
<Permissions role={host.roleid}/>
|
34
|
+
<div className="audit auditHost">
|
35
|
+
<AuditBox roles={[host.roleid]} resources={[host.resource_identifier]}/>
|
36
|
+
</div>
|
37
|
+
</div>
|
38
|
+
);
|
39
|
+
}
|
40
|
+
})
|
@@ -0,0 +1,18 @@
|
|
1
|
+
/** @jsx React.DOM */
|
2
|
+
|
3
|
+
var HostBox = React.createClass({
|
4
|
+
getInitialState: function() {
|
5
|
+
return { currentNamespace: "", members: [] };
|
6
|
+
},
|
7
|
+
render: function() {
|
8
|
+
return (
|
9
|
+
<div className="hostBox">
|
10
|
+
<NamespaceFilter currentNamespace={this.state.currentNamespace} namespaces={this.props.data.namespaces} />
|
11
|
+
<div className="hostList">
|
12
|
+
<h2>Hosts</h2>
|
13
|
+
<GenericList data={{kind: "hosts", members: this.state.members}} />
|
14
|
+
</div>
|
15
|
+
</div>
|
16
|
+
);
|
17
|
+
}
|
18
|
+
});
|
@@ -0,0 +1,63 @@
|
|
1
|
+
/** @jsx React.DOM */
|
2
|
+
|
3
|
+
var Layer = React.createClass({
|
4
|
+
render: function() {
|
5
|
+
function abstractRole(expected) {
|
6
|
+
return function(role) {
|
7
|
+
var tokens = role.split(':');
|
8
|
+
var kind = tokens[1];
|
9
|
+
var abstractKinds = [ '@', 'layer' ];
|
10
|
+
var isAbstract = abstractKinds.indexOf(kind) !== -1;
|
11
|
+
return isAbstract === expected;
|
12
|
+
}
|
13
|
+
}
|
14
|
+
|
15
|
+
var layer = this.props.data.layer;
|
16
|
+
|
17
|
+
|
18
|
+
var hosts = layer.hosts.map(function (host) {
|
19
|
+
return <li>
|
20
|
+
<HostLink data={host} />
|
21
|
+
</li>
|
22
|
+
}.bind(this));
|
23
|
+
var admins = this.props.data.admins.filter(abstractRole(false)).map(function (role) {
|
24
|
+
return <RoleLink id={role}/>;
|
25
|
+
}.bind(this));
|
26
|
+
var users = this.props.data.users.filter(abstractRole(false)).map(function (role) {
|
27
|
+
return <RoleLink id={role}/>
|
28
|
+
}.bind(this));
|
29
|
+
|
30
|
+
return (
|
31
|
+
<div className="group">
|
32
|
+
<h2>Layer {layer.id}</h2>
|
33
|
+
|
34
|
+
<dl>
|
35
|
+
<dt>Owner</dt>
|
36
|
+
<dd><RoleLink id={layer.ownerid}/></dd>
|
37
|
+
<dt>Admins</dt>
|
38
|
+
<dd>
|
39
|
+
<ul>
|
40
|
+
{admins}
|
41
|
+
</ul>
|
42
|
+
</dd>
|
43
|
+
<dt>Users</dt>
|
44
|
+
<dd>
|
45
|
+
<ul>
|
46
|
+
{users}
|
47
|
+
</ul>
|
48
|
+
</dd>
|
49
|
+
<dt>Hosts</dt>
|
50
|
+
<dd>
|
51
|
+
<ul>
|
52
|
+
{hosts}
|
53
|
+
</ul>
|
54
|
+
</dd>
|
55
|
+
</dl>
|
56
|
+
<Permissions role={layer.roleid}/>
|
57
|
+
<div className="audit auditLayer">
|
58
|
+
<AuditBox roles={[layer.roleid]} resources={[layer.resource_identifier]}/>
|
59
|
+
</div>
|
60
|
+
</div>
|
61
|
+
);
|
62
|
+
}
|
63
|
+
});
|