conjur-asset-ui 1.3.0 → 1.3.1
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/.gitignore +3 -1
- data/.jshintrc +41 -0
- data/Gemfile +3 -1
- data/README.md +34 -0
- data/Rakefile +69 -1
- data/bower.json +93 -0
- data/conjur-asset-ui.gemspec +1 -1
- data/features/navigation_bar.feature +31 -0
- data/features/step_definitions/custom_step.rb +32 -0
- data/features/support/env.rb +38 -0
- data/features/support/hooks.rb +30 -0
- data/features/support/world.rb +17 -0
- data/gulpfile.js +140 -0
- data/lib/conjur/command/ui.rb +1 -1
- data/lib/conjur/webserver/server.rb +14 -9
- data/lib/conjur-asset-ui-version.rb +1 -1
- data/package.json +47 -0
- data/preprocessor.js +7 -0
- data/public/_client_libs.html +2 -15
- data/public/css/styles.less +170 -4
- data/public/index.html.erb +5 -7
- data/public/js/init.js +183 -97
- data/public/js/lib/sorted-set.no-require.js +3 -28
- data/public/js/models/groupRecord.js +12 -11
- data/public/js/models/hostRecord.js +6 -7
- data/public/js/models/layerRecord.js +12 -11
- data/public/js/models/namespace.js +2 -0
- data/public/js/models/policyList.js +3 -1
- data/public/js/models/policyRecord.js +6 -7
- data/public/js/models/record.js +24 -23
- data/public/js/models/resourceList.js +28 -10
- data/public/js/models/userList.js +7 -2
- data/public/js/models/userRecord.js +7 -8
- data/public/js/models/variableList.js +18 -7
- data/public/js/models/variableRecord.js +13 -12
- data/public/js/routers.js +72 -26
- data/public/js/views/annotations.js +38 -27
- data/public/js/views/audit.js +23 -17
- data/public/js/views/chart.js +471 -0
- data/public/js/views/dashboard.js +94 -58
- data/public/js/views/generic.js +16 -9
- data/public/js/views/group.js +94 -55
- data/public/js/views/groups.js +3 -7
- data/public/js/views/host.js +75 -44
- data/public/js/views/hosts.js +2 -6
- data/public/js/views/layer.js +127 -82
- data/public/js/views/layers.js +2 -6
- data/public/js/views/mixins/search.js +12 -5
- data/public/js/views/mixins/tabs.js +95 -55
- data/public/js/views/navSearch.js +16 -5
- data/public/js/views/owned.js +14 -8
- data/public/js/views/permissions.js +244 -178
- data/public/js/views/policies.js +2 -4
- data/public/js/views/policy.js +65 -38
- data/public/js/views/resource.js +49 -34
- data/public/js/views/role.js +52 -37
- data/public/js/views/searchResults.js +205 -138
- data/public/js/views/time.js +26 -13
- data/public/js/views/user.js +178 -55
- data/public/js/views/users.js +2 -7
- data/public/js/views/variable.js +226 -45
- data/public/js/views/variables.js +4 -8
- metadata +20 -20
- data/public/_client_code.html +0 -42
- data/public/css/bootstrap.css +0 -7
- data/public/fonts/glyphicons-halflings-regular.eot +0 -0
- data/public/fonts/glyphicons-halflings-regular.svg +0 -229
- data/public/fonts/glyphicons-halflings-regular.ttf +0 -0
- data/public/fonts/glyphicons-halflings-regular.woff +0 -0
- data/public/js/lib/JSXTransformer.js +0 -10862
- data/public/js/lib/async.js +0 -958
- data/public/js/lib/backbone.js +0 -2
- data/public/js/lib/bootstrap.js +0 -6
- data/public/js/lib/less.js +0 -16
- data/public/js/lib/moment.js +0 -7768
- data/public/js/lib/react-bootstrap.js +0 -5346
- data/public/js/lib/react-bootstrap.min.js +0 -4
- data/public/js/lib/underscore-min.js +0 -6
- data/public/js/lib/underscore.string.min.js +0 -1
- data/public/js/main.js +0 -57
@@ -1,188 +1,254 @@
|
|
1
1
|
/** @jsx React.DOM */
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
2
|
+
/* global conjur, React, jQuery, _ */
|
3
|
+
|
4
|
+
(function(conjur, React, $, _) {
|
5
|
+
'use strict';
|
6
|
+
|
7
|
+
var ResourceLink = conjur.views.ResourceLink,
|
8
|
+
RoleLink = conjur.views.RoleLink;
|
9
|
+
|
10
|
+
var PermissionsTable = this.PermissionsTable = React.createClass({
|
11
|
+
render: function() {
|
12
|
+
var rows = [];
|
13
|
+
|
14
|
+
var resources = _.sortBy(this.props.resources, function(r) {
|
15
|
+
return r.id; // this way it will be sorting by (kind, id)
|
16
|
+
});
|
17
|
+
|
18
|
+
resources.forEach(function(r) {
|
19
|
+
var rowspan = r.permissions.length + 1,
|
20
|
+
parts = r.id.split(':'),
|
21
|
+
kind = parts[1]; // ignore env?
|
22
|
+
|
23
|
+
var cells = [
|
24
|
+
(<td rowSpan={rowspan}> <ResourceLink id={r.id}/> </td>),
|
25
|
+
(<td rowSpan={rowspan}> {kind} </td>)
|
26
|
+
];
|
27
|
+
|
28
|
+
if (rowspan === 1) {
|
29
|
+
cells.push(<td colSpan="3"> full permissions </td>);
|
30
|
+
}
|
31
|
+
|
32
|
+
rows.push(
|
33
|
+
(<tr key={r.id}>{cells}</tr>)
|
34
|
+
);
|
35
|
+
|
36
|
+
if (rowspan > 1) {
|
37
|
+
rows.push(r.permissions.map(function(p) {
|
38
|
+
return (
|
39
|
+
<PermissionRow data={p}/>
|
40
|
+
);
|
41
|
+
}));
|
42
|
+
}
|
43
|
+
|
44
|
+
});
|
45
|
+
|
46
|
+
rows = _.flatten(rows);
|
47
|
+
|
48
|
+
var showhidelink = (
|
49
|
+
<div>
|
50
|
+
<a onClick={this.props.hideHandler}>Hide all «</a>
|
51
|
+
</div>
|
52
|
+
);
|
53
|
+
|
54
|
+
if (this.props.tabview) {
|
55
|
+
showhidelink = '';
|
56
|
+
}
|
57
|
+
|
58
|
+
if (rows.length === 0) {
|
59
|
+
return (
|
60
|
+
<span>None</span>
|
61
|
+
);
|
62
|
+
}
|
63
|
+
|
64
|
+
return (
|
65
|
+
<div>
|
66
|
+
{showhidelink}
|
67
|
+
<table>
|
68
|
+
<thead>
|
69
|
+
<tr>
|
70
|
+
<th> Resource </th>
|
71
|
+
<th> Kind </th>
|
72
|
+
<th> Privilege </th>
|
73
|
+
<th> Can Grant? </th>
|
74
|
+
<th> Granted By </th>
|
75
|
+
</tr>
|
76
|
+
</thead>
|
77
|
+
<tbody>
|
78
|
+
{rows}
|
79
|
+
</tbody>
|
80
|
+
</table>
|
81
|
+
</div>
|
82
|
+
);
|
83
|
+
}
|
8
84
|
});
|
9
|
-
resources.forEach(function(r){
|
10
|
-
var rowspan = r.permissions.length + 1;
|
11
|
-
var parts = r.id.split(":");
|
12
|
-
var id = parts[2];
|
13
|
-
var kind = parts[1]; // ignore env?
|
14
|
-
var cells = [
|
15
|
-
<td rowSpan={rowspan}> <ResourceLink id={r.id}/> </td>,
|
16
|
-
<td rowSpan={rowspan}> {kind} </td>
|
17
|
-
];
|
18
|
-
if(rowspan == 1){
|
19
|
-
cells.push(<td colSpan="3"> full permissions </td>);
|
20
|
-
}
|
21
|
-
|
22
|
-
rows.push(
|
23
|
-
<tr key={r.id}>{cells}</tr>
|
24
|
-
);
|
25
|
-
|
26
|
-
if(rowspan > 1){
|
27
|
-
rows.push(r.permissions.map(function(p){
|
28
|
-
return <PermissionRow data={p}/>
|
29
|
-
}));
|
30
|
-
}
|
31
85
|
|
32
|
-
});
|
33
|
-
rows = _.flatten(rows);
|
34
|
-
|
35
|
-
var showhidelink = <div><a onClick={this.props.hideHandler}>Hide all «</a></div>;
|
36
|
-
|
37
|
-
if (this.props.tabview) {
|
38
|
-
showhidelink="";
|
39
|
-
}
|
40
|
-
|
41
|
-
if (rows.length==0) {
|
42
|
-
return <span>None</span>;
|
43
|
-
}
|
44
|
-
|
45
|
-
return <div>
|
46
|
-
{showhidelink}
|
47
|
-
<table>
|
48
|
-
<thead>
|
49
|
-
<tr>
|
50
|
-
<th> Resource </th>
|
51
|
-
<th> Kind </th>
|
52
|
-
<th> Privilege </th>
|
53
|
-
<th> Can Grant? </th>
|
54
|
-
<th> Granted By </th>
|
55
|
-
</tr>
|
56
|
-
</thead>
|
57
|
-
<tbody> {rows} </tbody>
|
58
|
-
</table>
|
59
|
-
</div>
|
60
|
-
}
|
61
|
-
});
|
62
|
-
|
63
|
-
|
64
|
-
// Renders a permission as a tr
|
65
|
-
var PermissionRow = React.createClass({
|
66
|
-
render: function(){
|
67
|
-
var p = this.props.data;
|
68
|
-
return <tr>
|
69
|
-
<td> { p.privilege } </td>
|
70
|
-
<td> { p.grant_option ? "yes" : "no" }</td>
|
71
|
-
<td> <RoleLink id={p.grantor}/> </td>
|
72
|
-
</tr>;
|
73
|
-
}
|
74
|
-
});
|
75
|
-
|
76
|
-
var PermissionsSummary = React.createClass({
|
77
|
-
render: function() {
|
78
|
-
var expand = "";
|
79
|
-
if ( this.props.length > 0 )
|
80
|
-
expand = <span>
|
81
|
-
<br/>
|
82
|
-
<span>
|
83
|
-
<a onClick={this.props.expandHandler}>Show all »</a>
|
84
|
-
</span>
|
85
|
-
</span>;
|
86
|
-
|
87
|
-
return <div>
|
88
|
-
<span>
|
89
|
-
{this.props.length} permissions
|
90
|
-
</span>
|
91
|
-
{expand}
|
92
|
-
</div>
|
93
|
-
}
|
94
|
-
});
|
95
|
-
|
96
|
-
var Permissions = React.createClass({
|
97
|
-
getInitialState: function() {
|
98
|
-
return {resources: null, loaded: false, expand: false}
|
99
|
-
},
|
100
|
-
|
101
|
-
expand: function(event) {
|
102
|
-
this.setState({expand: true})
|
103
|
-
},
|
104
|
-
|
105
|
-
collapse: function(event) {
|
106
|
-
this.setState({expand: false})
|
107
|
-
},
|
108
|
-
|
109
|
-
componentWillMount: function() { // shouldn't it be done in model??? otherwise it will re-load stuff on each re-rendering of parent block
|
110
|
-
if ( this.props.roles ) {
|
111
|
-
$.get(this.url(), function(data){
|
112
|
-
this.setPermissions(data);
|
113
|
-
}.bind(this));
|
114
|
-
}
|
115
|
-
},
|
116
|
-
|
117
|
-
setPermissions: function(_resources) {
|
118
|
-
/**
|
119
|
-
* Filter out owned resources.
|
120
|
-
* Filter out permissions on resources which are not held by the current role.
|
121
|
-
*/
|
122
|
-
var resources;
|
123
|
-
|
124
|
-
if ( this.props.owned ) {
|
125
|
-
var ownedIds = _.pluck(this.props.owned, 'id');
|
126
|
-
resources = _resources.filter(function(r) {
|
127
|
-
return !_.contains(ownedIds, r.id);
|
128
|
-
});
|
129
|
-
}
|
130
|
-
else
|
131
|
-
resources = _resources;
|
132
|
-
|
133
|
-
var roleSet = {};
|
134
|
-
this.props.roles.forEach(function(r) {
|
135
|
-
roleSet[r] = r;
|
136
|
-
});
|
137
86
|
|
138
|
-
|
139
|
-
|
87
|
+
// Renders a permission as a tr
|
88
|
+
var PermissionRow = React.createClass({
|
89
|
+
render: function() {
|
90
|
+
var p = this.props.data;
|
91
|
+
|
92
|
+
return (
|
93
|
+
<tr>
|
94
|
+
<td>{p.privilege}</td>
|
95
|
+
<td>{p.grant_option ? 'yes' : 'no'}</td>
|
96
|
+
<td><RoleLink id={p.grantor}/></td>
|
97
|
+
</tr>
|
98
|
+
);
|
99
|
+
}
|
140
100
|
});
|
141
101
|
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
102
|
+
var PermissionsSummary = React.createClass({
|
103
|
+
render: function() {
|
104
|
+
var expand = '';
|
105
|
+
|
106
|
+
if (this.props.length > 0) {
|
107
|
+
expand = (
|
108
|
+
<span>
|
109
|
+
<br/>
|
110
|
+
<span>
|
111
|
+
<a onClick={this.props.expandHandler}>Show all »</a>
|
112
|
+
</span>
|
113
|
+
</span>
|
114
|
+
);
|
115
|
+
}
|
116
|
+
|
117
|
+
return (
|
118
|
+
<div>
|
119
|
+
<span>
|
120
|
+
{this.props.length} permissions
|
121
|
+
</span>
|
122
|
+
{expand}
|
123
|
+
</div>
|
124
|
+
);
|
125
|
+
}
|
150
126
|
});
|
151
127
|
|
152
|
-
this.
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
128
|
+
this.Permissions = React.createClass({
|
129
|
+
getInitialState: function() {
|
130
|
+
return {resources: null, loaded: false, expand: false};
|
131
|
+
},
|
132
|
+
|
133
|
+
expand: function() {
|
134
|
+
this.setState({expand: true});
|
135
|
+
},
|
136
|
+
|
137
|
+
collapse: function() {
|
138
|
+
this.setState({expand: false});
|
139
|
+
},
|
140
|
+
|
141
|
+
componentWillMount: function() {
|
142
|
+
// shouldn't it be done in model??? otherwise it will
|
143
|
+
// re-load stuff on each re-rendering of parent block
|
144
|
+
if (this.props.roles) {
|
145
|
+
$.get(this.url(), function(data) {
|
146
|
+
this.setPermissions(data);
|
147
|
+
}.bind(this));
|
148
|
+
}
|
149
|
+
},
|
150
|
+
|
151
|
+
setPermissions: function(_resources) {
|
152
|
+
/**
|
153
|
+
* Filter out owned resources.
|
154
|
+
* Filter out permissions on resources which are not held by the current role.
|
155
|
+
*/
|
156
|
+
var resources;
|
157
|
+
|
158
|
+
if (this.props.owned) {
|
159
|
+
var ownedIds = _.pluck(this.props.owned, 'id');
|
160
|
+
|
161
|
+
resources = _resources.filter(function(r) {
|
162
|
+
return !_.contains(ownedIds, r.id);
|
163
|
+
});
|
164
|
+
} else {
|
165
|
+
resources = _resources;
|
166
|
+
}
|
167
|
+
|
168
|
+
var roleSet = {};
|
169
|
+
|
170
|
+
this.props.roles.forEach(function(r) {
|
171
|
+
roleSet[r] = r;
|
172
|
+
});
|
173
|
+
|
174
|
+
var cleanResources = resources.filter(function(item) {
|
175
|
+
// assets of 'secret' kind are internal
|
176
|
+
return item.id.split(':')[1] !== 'secret';
|
177
|
+
});
|
178
|
+
|
179
|
+
cleanResources.forEach(function(resource) {
|
180
|
+
var permissions = resource.permissions,
|
181
|
+
hasPermissions = [];
|
182
|
+
|
183
|
+
permissions.forEach(function(permission) {
|
184
|
+
if (roleSet.hasOwnProperty(permission.role)) {
|
185
|
+
hasPermissions.push(permission);
|
186
|
+
}
|
187
|
+
});
|
188
|
+
|
189
|
+
resource.permissions = hasPermissions;
|
190
|
+
});
|
191
|
+
|
192
|
+
this.setState({resources: cleanResources, loaded: true});
|
193
|
+
},
|
194
|
+
|
195
|
+
render: function() {
|
196
|
+
var content;
|
197
|
+
|
198
|
+
if (this.state.loaded) {
|
199
|
+
if (this.state.expand || this.props.tabview) {
|
200
|
+
content = (
|
201
|
+
<PermissionsTable resources={this.state.resources}
|
202
|
+
hideHandler={this.collapse}
|
203
|
+
tabview={this.props.tabview} />
|
204
|
+
);
|
205
|
+
} else {
|
206
|
+
content = (
|
207
|
+
<PermissionsSummary length={this.state.resources.length}
|
208
|
+
expandHandler={this.expand} />
|
209
|
+
);
|
210
|
+
}
|
211
|
+
} else {
|
212
|
+
if (this.props.roles) {
|
213
|
+
content = (
|
214
|
+
<span>Loading...</span>
|
215
|
+
);
|
216
|
+
} else {
|
217
|
+
content = 'You are not authorized to see these permissions';
|
218
|
+
}
|
219
|
+
}
|
220
|
+
|
221
|
+
var cx = React.addons.classSet;
|
222
|
+
|
223
|
+
var classes = cx({
|
224
|
+
permissions: true,
|
225
|
+
loading: !this.state.loaded
|
226
|
+
});
|
227
|
+
|
228
|
+
var permissionsheader = this.props.tabview ? '' : (<h3>Permissions held</h3>);
|
229
|
+
|
230
|
+
return (
|
231
|
+
<section className={classes}>
|
232
|
+
{permissionsheader}
|
233
|
+
<div id="permissionDetails">
|
234
|
+
{content}
|
235
|
+
</div>
|
236
|
+
</section>
|
237
|
+
);
|
238
|
+
},
|
239
|
+
|
240
|
+
url: function() {
|
241
|
+
return '/api/authz/' +
|
242
|
+
conjur.app.configuration.account +
|
243
|
+
'/resources?acting_as=' +
|
244
|
+
this.props.role;
|
245
|
+
}
|
174
246
|
});
|
175
247
|
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
},
|
184
|
-
|
185
|
-
url: function(){
|
186
|
-
return "/api/authz/" + conjur.app.configuration.account + "/resources?acting_as=" + this.props.role;
|
187
|
-
}
|
188
|
-
})
|
248
|
+
}).bind(conjur.views)
|
249
|
+
(
|
250
|
+
conjur,
|
251
|
+
React,
|
252
|
+
jQuery,
|
253
|
+
_
|
254
|
+
);
|
data/public/js/views/policies.js
CHANGED
@@ -1,14 +1,12 @@
|
|
1
1
|
/** @jsx React.DOM */
|
2
|
+
/* global conjur, React */
|
2
3
|
|
3
4
|
(function(conjur, React) {
|
4
5
|
'use strict';
|
5
6
|
|
6
7
|
var GenericList = conjur.views.GenericList;
|
7
8
|
|
8
|
-
|
9
|
-
/*getInitialState: function() {
|
10
|
-
return { currentNamespace: "", members: [] };
|
11
|
-
},*/
|
9
|
+
this.PolicyBox = React.createClass({
|
12
10
|
render: function() {
|
13
11
|
return (
|
14
12
|
<div className="policyBox">
|
data/public/js/views/policy.js
CHANGED
@@ -1,43 +1,70 @@
|
|
1
1
|
/** @jsx React.DOM */
|
2
|
+
/* global conjur, React, ReactBootstrap, _ */
|
2
3
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
var
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
4
|
+
(function(conjur, React, ReactBootstrap, _) {
|
5
|
+
'use strict';
|
6
|
+
|
7
|
+
var TabbedArea = ReactBootstrap.TabbedArea,
|
8
|
+
TabPane = ReactBootstrap.TabPane,
|
9
|
+
Tab = conjur.views.mixins.Tab,
|
10
|
+
RoleLink = conjur.views.RoleLink,
|
11
|
+
AuditBox = window.AuditBox;
|
12
|
+
|
13
|
+
this.Policy = React.createClass({
|
14
|
+
mixins: [Tab],
|
15
|
+
|
16
|
+
render: function() {
|
17
|
+
var policy = this.props.data.policy,
|
18
|
+
id = policy.id.split(':')[2];
|
19
|
+
|
20
|
+
//TODO: policy loader
|
21
|
+
//TODO in CLI: why not save text of policy as an annotation?
|
22
|
+
var overviewTab = (
|
23
|
+
<TabPane key="overview" tab="Overview">
|
24
|
+
<dl className="dl-horizontal">
|
25
|
+
<dt>Owner</dt>
|
26
|
+
<dd><RoleLink id={policy.id}/></dd>
|
27
|
+
</dl>
|
28
|
+
</TabPane>
|
29
|
+
);
|
30
|
+
|
31
|
+
var permissionsTab = this.permissionsTab(policy.id),
|
32
|
+
membershipsTab = this.membershipsTab(policy.id),
|
33
|
+
annotationsTab = this.annotationsTab(),
|
34
|
+
ownedTab = this.ownedTab();
|
35
|
+
|
36
|
+
var auditTab = (
|
37
|
+
<TabPane key="audit" tab="Recent Activity">
|
26
38
|
<div className="audit auditGroup">
|
27
39
|
<AuditBox roles={[policy.id]} tabview={true} />
|
28
40
|
</div>
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
}
|
41
|
+
</TabPane>
|
42
|
+
);
|
43
|
+
|
44
|
+
var tabs = _.compact([
|
45
|
+
overviewTab,
|
46
|
+
ownedTab,
|
47
|
+
membershipsTab,
|
48
|
+
permissionsTab,
|
49
|
+
annotationsTab,
|
50
|
+
auditTab
|
51
|
+
]);
|
52
|
+
|
53
|
+
return (
|
54
|
+
<div className="policy">
|
55
|
+
<h2>Policy {id}</h2>
|
56
|
+
<TabbedArea defaultActiveKey="overview">
|
57
|
+
{tabs}
|
58
|
+
</TabbedArea>
|
59
|
+
</div>
|
60
|
+
);
|
61
|
+
}
|
62
|
+
});
|
63
|
+
|
64
|
+
}).bind(conjur.views)
|
65
|
+
(
|
66
|
+
conjur,
|
67
|
+
React,
|
68
|
+
ReactBootstrap,
|
69
|
+
_
|
70
|
+
);
|
data/public/js/views/resource.js
CHANGED
@@ -1,39 +1,54 @@
|
|
1
1
|
/** @jsx React.DOM */
|
2
|
+
/* global conjur, React, _ */
|
2
3
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
4
|
+
(function(conjur, React, _) {
|
5
|
+
'use strict';
|
6
|
+
|
7
|
+
/**
|
8
|
+
Renders a link to the resource with id given by this.props.data.
|
9
|
+
|
10
|
+
Includes a slick little icon for the following kinds:
|
11
|
+
TODO which kinds?
|
12
|
+
**/
|
13
|
+
this.ResourceLink = React.createClass({
|
14
|
+
render: function() {
|
15
|
+
var resourceId = this.props.id || this.props.data.id || this.props.data;
|
16
|
+
|
17
|
+
var tokens = resourceId.split(':'),
|
18
|
+
kind = tokens[1],
|
19
|
+
id = tokens[tokens.length - 1],
|
20
|
+
text = this.props.text || id;
|
21
|
+
|
22
|
+
var knownTypes = ['user', 'group', 'layer', 'host', 'variable', 'policy'],
|
23
|
+
resourceIsKnown = _.contains(knownTypes, kind);
|
24
|
+
|
25
|
+
// we shouldn't build links to for unsupported resources
|
26
|
+
var href = '/ui/' + conjur.utils.pluralize(kind) + '/' + window.encodeURIComponent(id);
|
27
|
+
var classes = ['resource-link'];
|
28
|
+
|
29
|
+
if (!this.props.noIcon) {
|
30
|
+
if (resourceIsKnown) {
|
31
|
+
classes.push(kind);
|
32
|
+
} else {
|
33
|
+
classes.push('abstract');
|
34
|
+
|
35
|
+
if (text === id) {
|
36
|
+
text = [kind, text].join(':'); // prepend kind to id
|
37
|
+
}
|
38
|
+
}
|
39
|
+
} else if (text === id) {
|
40
|
+
text = [kind, text].join(':'); // prepend kind to id
|
31
41
|
}
|
42
|
+
|
43
|
+
return (
|
44
|
+
<a className={classes.join(' ')} href={href}>{text}</a>
|
45
|
+
);
|
32
46
|
}
|
33
|
-
}
|
34
|
-
text=[kind,text].join(":"); // prepend kind to id
|
35
|
-
}
|
47
|
+
});
|
36
48
|
|
37
|
-
|
38
|
-
|
39
|
-
|
49
|
+
}).bind(conjur.views)
|
50
|
+
(
|
51
|
+
conjur,
|
52
|
+
React,
|
53
|
+
_
|
54
|
+
);
|