conjur-asset-ui 1.3.0 → 1.3.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (81) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +3 -1
  3. data/.jshintrc +41 -0
  4. data/Gemfile +3 -1
  5. data/README.md +34 -0
  6. data/Rakefile +69 -1
  7. data/bower.json +93 -0
  8. data/conjur-asset-ui.gemspec +1 -1
  9. data/features/navigation_bar.feature +31 -0
  10. data/features/step_definitions/custom_step.rb +32 -0
  11. data/features/support/env.rb +38 -0
  12. data/features/support/hooks.rb +30 -0
  13. data/features/support/world.rb +17 -0
  14. data/gulpfile.js +140 -0
  15. data/lib/conjur/command/ui.rb +1 -1
  16. data/lib/conjur/webserver/server.rb +14 -9
  17. data/lib/conjur-asset-ui-version.rb +1 -1
  18. data/package.json +47 -0
  19. data/preprocessor.js +7 -0
  20. data/public/_client_libs.html +2 -15
  21. data/public/css/styles.less +170 -4
  22. data/public/index.html.erb +5 -7
  23. data/public/js/init.js +183 -97
  24. data/public/js/lib/sorted-set.no-require.js +3 -28
  25. data/public/js/models/groupRecord.js +12 -11
  26. data/public/js/models/hostRecord.js +6 -7
  27. data/public/js/models/layerRecord.js +12 -11
  28. data/public/js/models/namespace.js +2 -0
  29. data/public/js/models/policyList.js +3 -1
  30. data/public/js/models/policyRecord.js +6 -7
  31. data/public/js/models/record.js +24 -23
  32. data/public/js/models/resourceList.js +28 -10
  33. data/public/js/models/userList.js +7 -2
  34. data/public/js/models/userRecord.js +7 -8
  35. data/public/js/models/variableList.js +18 -7
  36. data/public/js/models/variableRecord.js +13 -12
  37. data/public/js/routers.js +72 -26
  38. data/public/js/views/annotations.js +38 -27
  39. data/public/js/views/audit.js +23 -17
  40. data/public/js/views/chart.js +471 -0
  41. data/public/js/views/dashboard.js +94 -58
  42. data/public/js/views/generic.js +16 -9
  43. data/public/js/views/group.js +94 -55
  44. data/public/js/views/groups.js +3 -7
  45. data/public/js/views/host.js +75 -44
  46. data/public/js/views/hosts.js +2 -6
  47. data/public/js/views/layer.js +127 -82
  48. data/public/js/views/layers.js +2 -6
  49. data/public/js/views/mixins/search.js +12 -5
  50. data/public/js/views/mixins/tabs.js +95 -55
  51. data/public/js/views/navSearch.js +16 -5
  52. data/public/js/views/owned.js +14 -8
  53. data/public/js/views/permissions.js +244 -178
  54. data/public/js/views/policies.js +2 -4
  55. data/public/js/views/policy.js +65 -38
  56. data/public/js/views/resource.js +49 -34
  57. data/public/js/views/role.js +52 -37
  58. data/public/js/views/searchResults.js +205 -138
  59. data/public/js/views/time.js +26 -13
  60. data/public/js/views/user.js +178 -55
  61. data/public/js/views/users.js +2 -7
  62. data/public/js/views/variable.js +226 -45
  63. data/public/js/views/variables.js +4 -8
  64. metadata +20 -20
  65. data/public/_client_code.html +0 -42
  66. data/public/css/bootstrap.css +0 -7
  67. data/public/fonts/glyphicons-halflings-regular.eot +0 -0
  68. data/public/fonts/glyphicons-halflings-regular.svg +0 -229
  69. data/public/fonts/glyphicons-halflings-regular.ttf +0 -0
  70. data/public/fonts/glyphicons-halflings-regular.woff +0 -0
  71. data/public/js/lib/JSXTransformer.js +0 -10862
  72. data/public/js/lib/async.js +0 -958
  73. data/public/js/lib/backbone.js +0 -2
  74. data/public/js/lib/bootstrap.js +0 -6
  75. data/public/js/lib/less.js +0 -16
  76. data/public/js/lib/moment.js +0 -7768
  77. data/public/js/lib/react-bootstrap.js +0 -5346
  78. data/public/js/lib/react-bootstrap.min.js +0 -4
  79. data/public/js/lib/underscore-min.js +0 -6
  80. data/public/js/lib/underscore.string.min.js +0 -1
  81. data/public/js/main.js +0 -57
@@ -1,188 +1,254 @@
1
1
  /** @jsx React.DOM */
2
-
3
- var PermissionsTable = React.createClass({
4
- render: function() {
5
- var rows = [];
6
- var resources = _.sortBy(this.props.resources, function(r){
7
- return r.id; // this way it will be sorting by (kind, id)
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 &laquo;</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 &laquo;</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 &raquo;</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
- var cleanResources = resources.filter(function(item) {
139
- return item.id.split(':')[1] !== "secret"; // assets of 'secret' kind are internal
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
- cleanResources.forEach(function(resource) {
143
- var permissions = resource.permissions;
144
- var hasPermissions = [];
145
- permissions.forEach(function(permission) {
146
- if ( roleSet.hasOwnProperty(permission['role']) )
147
- hasPermissions.push(permission);
148
- });
149
- resource.permissions = hasPermissions;
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 &raquo;</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.setState({resources: cleanResources, loaded: true});
153
- },
154
-
155
- render: function(){
156
- var content;
157
- if (this.state.loaded) {
158
- if ( this.state.expand || this.props.tabview )
159
- content = <PermissionsTable resources={this.state.resources} hideHandler={this.collapse} tabview={this.props.tabview}/>
160
- else
161
- content = <PermissionsSummary length={this.state.resources.length} expandHandler={this.expand} />
162
- }
163
- else {
164
- if ( this.props.roles )
165
- content = <span>Loading...</span>
166
- else
167
- content = "You are not authorized to see these permissions";
168
- }
169
-
170
- var cx = React.addons.classSet;
171
- var classes = cx({
172
- permissions: true,
173
- loading: !this.state.loaded
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
- var permissionsheader = this.props.tabview ? "" : <h3>Permissions held</h3>;
177
- return <section className={classes}>
178
- {permissionsheader}
179
- <div id="permissionDetails">
180
- {content}
181
- </div>
182
- </section>;
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
+ );
@@ -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
- var PolicyBox = this.PolicyBox = React.createClass({
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">
@@ -1,43 +1,70 @@
1
1
  /** @jsx React.DOM */
2
+ /* global conjur, React, ReactBootstrap, _ */
2
3
 
3
- var Policy = React.createClass({
4
- mixins: [conjur.views.mixins.Tab],
5
- render: function() {
6
- var policy = this.props.data.policy;
7
- var id = policy.id.split(':')[2];
8
-
9
- //TODO: policy loader
10
- //TODO in CLI: why not save text of policy as an annotation?
11
- var overview_tab =
12
- <TabPane key="overview" tab="Overview">
13
- <dl className="dl-horizontal">
14
- <dt>Owner</dt>
15
- <dd><RoleLink id={policy.id}/></dd>
16
- </dl>
17
- </TabPane>;
18
-
19
- var permissions_tab = this.permissions_tab(policy.id);
20
- var memberships_tab = this.memberships_tab(policy.id);
21
- var annotations_tab = this.annotations_tab();
22
- var owned_tab = this.owned_tab();
23
-
24
- var audit_tab =
25
- <TabPane key="audit" tab="Recent Activity">
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
- </TabPane>;
30
- var tabs = _.compact( [ overview_tab, owned_tab, memberships_tab, permissions_tab,
31
- annotations_tab, audit_tab
32
- ] );
33
-
34
- return (
35
- <div className="policy">
36
- <h2>Policy {id}</h2>
37
- <TabbedArea defaultActiveKey="overview">
38
- {tabs}
39
- </TabbedArea>
40
- </div>
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
+ );
@@ -1,39 +1,54 @@
1
1
  /** @jsx React.DOM */
2
+ /* global conjur, React, _ */
2
3
 
3
- /**
4
- Renders a link to the resource with id given by this.props.data.
5
-
6
- Includes a slick little icon for the following kinds:
7
- TODO which kinds?
8
- **/
9
- var ResourceLink = React.createClass({
10
- render: function(){
11
- var resourceId = this.props.id || this.props.data.id || this.props.data;
12
-
13
- var tokens = resourceId.split(':');
14
- var kind = tokens[1];
15
- var id = tokens[tokens.length - 1];
16
- var text = this.props.text || id;
17
-
18
- var known_types=['user','group','layer','host','variable','policy'];
19
- var resource_is_known = _.contains(known_types, kind);
20
-
21
- // we shouldn't build links to for unsupported resources
22
- var href = "/ui/" + conjur.utils.pluralize(kind) + "/" + encodeURIComponent(id);
23
- var classes = [ 'resource-link' ];
24
- if( !this.props.noIcon ) {
25
- if (resource_is_known) {
26
- classes.push(kind);
27
- } else {
28
- classes.push('abstract');
29
- if (text==id) {
30
- text=[kind,text].join(":"); // prepend kind to id
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
- } else if (text==id) {
34
- text=[kind,text].join(":"); // prepend kind to id
35
- }
47
+ });
36
48
 
37
- return <a className={classes.join(' ')} href={href}>{text}</a>
38
- }
39
- });
49
+ }).bind(conjur.views)
50
+ (
51
+ conjur,
52
+ React,
53
+ _
54
+ );