conjur-asset-ui 1.3.1 → 1.3.2

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 +1 -3
  3. data/Gemfile +1 -3
  4. data/README.md +0 -34
  5. data/Rakefile +1 -69
  6. data/conjur-asset-ui.gemspec +1 -1
  7. data/lib/conjur-asset-ui-version.rb +1 -1
  8. data/lib/conjur/command/ui.rb +1 -1
  9. data/lib/conjur/webserver/server.rb +8 -14
  10. data/public/_client_code.html +42 -0
  11. data/public/_client_libs.html +15 -2
  12. data/public/css/bootstrap.css +7 -0
  13. data/public/css/styles.less +4 -170
  14. data/public/fonts/glyphicons-halflings-regular.eot +0 -0
  15. data/public/fonts/glyphicons-halflings-regular.svg +229 -0
  16. data/public/fonts/glyphicons-halflings-regular.ttf +0 -0
  17. data/public/fonts/glyphicons-halflings-regular.woff +0 -0
  18. data/public/index.html.erb +7 -5
  19. data/public/js/init.js +97 -183
  20. data/public/js/lib/JSXTransformer.js +10862 -0
  21. data/public/js/lib/async.js +958 -0
  22. data/public/js/lib/backbone.js +2 -0
  23. data/public/js/lib/bootstrap.js +6 -0
  24. data/public/js/lib/less.js +16 -0
  25. data/public/js/lib/moment.js +7768 -0
  26. data/public/js/lib/react-bootstrap.js +5346 -0
  27. data/public/js/lib/react-bootstrap.min.js +4 -0
  28. data/public/js/lib/sorted-set.no-require.js +28 -3
  29. data/public/js/lib/underscore-min.js +6 -0
  30. data/public/js/lib/underscore.string.min.js +1 -0
  31. data/public/js/main.js +57 -0
  32. data/public/js/models/groupRecord.js +11 -12
  33. data/public/js/models/hostRecord.js +7 -6
  34. data/public/js/models/layerRecord.js +11 -12
  35. data/public/js/models/namespace.js +0 -2
  36. data/public/js/models/policyList.js +1 -3
  37. data/public/js/models/policyRecord.js +7 -6
  38. data/public/js/models/record.js +23 -24
  39. data/public/js/models/resourceList.js +10 -28
  40. data/public/js/models/userList.js +2 -7
  41. data/public/js/models/userRecord.js +8 -7
  42. data/public/js/models/variableList.js +7 -18
  43. data/public/js/models/variableRecord.js +12 -13
  44. data/public/js/routers.js +26 -72
  45. data/public/js/views/annotations.js +27 -38
  46. data/public/js/views/audit.js +17 -23
  47. data/public/js/views/dashboard.js +58 -94
  48. data/public/js/views/generic.js +9 -16
  49. data/public/js/views/group.js +55 -94
  50. data/public/js/views/groups.js +7 -3
  51. data/public/js/views/host.js +44 -75
  52. data/public/js/views/hosts.js +6 -2
  53. data/public/js/views/layer.js +82 -127
  54. data/public/js/views/layers.js +6 -2
  55. data/public/js/views/mixins/search.js +5 -12
  56. data/public/js/views/mixins/tabs.js +55 -95
  57. data/public/js/views/navSearch.js +5 -16
  58. data/public/js/views/owned.js +8 -14
  59. data/public/js/views/permissions.js +178 -244
  60. data/public/js/views/policies.js +4 -2
  61. data/public/js/views/policy.js +38 -65
  62. data/public/js/views/resource.js +34 -49
  63. data/public/js/views/role.js +37 -52
  64. data/public/js/views/searchResults.js +138 -205
  65. data/public/js/views/time.js +13 -26
  66. data/public/js/views/user.js +55 -178
  67. data/public/js/views/users.js +7 -2
  68. data/public/js/views/variable.js +45 -226
  69. data/public/js/views/variables.js +8 -4
  70. metadata +19 -18
  71. data/.jshintrc +0 -41
  72. data/bower.json +0 -93
  73. data/features/navigation_bar.feature +0 -31
  74. data/features/step_definitions/custom_step.rb +0 -32
  75. data/features/support/env.rb +0 -38
  76. data/features/support/hooks.rb +0 -30
  77. data/features/support/world.rb +0 -17
  78. data/gulpfile.js +0 -140
  79. data/package.json +0 -47
  80. data/preprocessor.js +0 -7
  81. data/public/js/views/chart.js +0 -471
@@ -1,9 +1,7 @@
1
- /* global conjur */
2
-
3
1
  (function(conjur) {
4
2
  'use strict';
5
3
 
6
- this.UserList = function() {
4
+ conjur.models.UserList = function() {
7
5
  var options = {
8
6
  namespaceSelector: function(member) {
9
7
  var idTokens = member.id.split('@');
@@ -19,7 +17,4 @@
19
17
  return conjur.models.ResourceList('user', options);
20
18
  };
21
19
 
22
- }).bind(conjur.models)
23
- (
24
- conjur
25
- );
20
+ })(conjur);
@@ -1,5 +1,3 @@
1
- /* global conjur, jQuery, async */
2
-
3
1
  (function(conjur, $, async, errback) {
4
2
  'use strict';
5
3
 
@@ -20,7 +18,7 @@
20
18
  User.prototype = Object.create(Generic.prototype);
21
19
  User.prototype.constructor = User;
22
20
 
23
- User.prototype.publicKeys = function(callback) {
21
+ User.prototype.publicKeys = function(callback, custom_errback) {
24
22
  $.ajax({
25
23
  url: '/api/pubkeys/' + window.encodeURIComponent(this.id),
26
24
  success: function(data) {
@@ -32,9 +30,12 @@
32
30
  });
33
31
  };
34
32
 
35
- User.prototype.fetch = function(callback, customErrback) {
36
- if (typeof(customErrback) === 'undefined') {
37
- customErrback = errback; // reset to default
33
+ User.prototype.fetch = function(callback, custom_errback) {
34
+ var self = this,
35
+ id = this.id;
36
+
37
+ if (typeof(custom_errback) === 'undefined') {
38
+ custom_errback = errback; // reset to default
38
39
  }
39
40
 
40
41
  async.parallel([
@@ -45,7 +46,7 @@
45
46
  this.publicKeys.bind(this)
46
47
  ], function(err, results) {
47
48
  if (err) {
48
- return customErrback(err.status);
49
+ return custom_errback(err.status);
49
50
  }
50
51
 
51
52
  callback({
@@ -1,27 +1,16 @@
1
- /* global conjur */
2
-
3
1
  (function(conjur) {
4
2
  'use strict';
5
3
 
6
- this.VariableList = function() {
4
+ conjur.models.VariableList = function() {
7
5
  var options = {
8
- namespaceSelector: function(member) {
9
- var idTokens = member.id.split('@');
10
-
11
- if (idTokens.length > 1) {
12
- return idTokens.slice(1, idTokens.length-1).join['@'];
13
- } else {
14
- return null;
15
- }
6
+ filter: function(member) {
7
+ var idTokens = member.id.split(':');
8
+ var id = idTokens[idTokens.length-1];
9
+ return id.split('/').length > 1;
16
10
  }
17
11
  };
18
12
 
19
- var list = conjur.models.ResourceList('variable', options);
20
-
21
- return list;
13
+ return conjur.models.ResourceList('variable', options);
22
14
  };
23
15
 
24
- }).bind(conjur.models)
25
- (
26
- conjur
27
- );
16
+ })(conjur);
@@ -1,5 +1,3 @@
1
- /* global conjur, jQuery, async */
2
-
3
1
  (function(conjur, $, async, errback) {
4
2
  'use strict';
5
3
 
@@ -20,22 +18,23 @@
20
18
  Variable.prototype = Object.create(Generic.prototype);
21
19
  Variable.prototype.constructor = Variable;
22
20
 
23
- Variable.prototype.fetch = function(callback, customErrback) {
24
- var id = this.id;
21
+ Variable.prototype.fetch = function(callback, custom_errback) {
22
+ var self = this,
23
+ id = this.id;
25
24
 
26
- if (typeof(customErrback) === 'undefined') {
27
- customErrback = errback; // reset to default
25
+ if (typeof(custom_errback) === 'undefined') {
26
+ custom_errback = errback; // reset to default
28
27
  }
29
28
 
30
29
  function members(privilege) {
31
30
  return function(cb) {
32
31
  $.ajax({
33
- url: '/api/authz/' +
34
- conjur.app.configuration.account +
35
- '/roles/allowed_to/' +
36
- privilege +
37
- '/variable/' +
38
- window.encodeURIComponent(id),
32
+ url: '/api/authz/'
33
+ + conjur.app.configuration.account
34
+ + '/roles/allowed_to/'
35
+ + privilege
36
+ + '/variable/'
37
+ + window.encodeURIComponent(id),
39
38
  success: function(result) {
40
39
  cb(null, result);
41
40
  },
@@ -51,7 +50,7 @@
51
50
  this.resource.bind(this)
52
51
  ], function(err, results) {
53
52
  if (err) {
54
- return customErrback(err.status);
53
+ return custom_errback(err.status);
55
54
  }
56
55
 
57
56
  callback({
data/public/js/routers.js CHANGED
@@ -1,23 +1,14 @@
1
1
  /** @jsx React.DOM */
2
- /* global conjur, jQuery, _, Backbone, React */
3
2
 
4
-
5
- (function(conjur, $, _, Backbone, React) {
3
+ (function(conjur, $, _, Backbone, React, SearchResults) {
6
4
  'use strict';
7
5
 
8
- var Dashboard = conjur.views.Dashboard,
9
- GroupBox = conjur.views.GroupBox,
6
+ var GroupBox = conjur.views.GroupBox,
10
7
  LayerBox = conjur.views.LayerBox,
11
8
  PolicyBox = conjur.views.PolicyBox,
12
9
  VariableBox = conjur.views.VariableBox,
13
- UserBox = conjur.views.UserBox,
14
- Group = conjur.views.Group,
15
- Host = conjur.views.Host,
16
- Layer = conjur.views.Layer,
17
- Policy = conjur.views.Policy,
18
- User = conjur.views.User,
19
- Variable = conjur.views.Variable,
20
- SearchResults = conjur.views.SearchResults;
10
+ HostBox = conjur.views.HostBox,
11
+ UserBox = conjur.views.UserBox;
21
12
 
22
13
  conjur.Workspace = Backbone.Router.extend({
23
14
  routes: {
@@ -46,8 +37,7 @@
46
37
 
47
38
  conjur.app.lists[conjur.app.kind].fetch(function(list) {
48
39
  var component = componentFunction(list);
49
- // doesn't make much sense due to
50
- // http://stackoverflow.com/questions/24889934/componentinstance-setstate-undefined-in-0-11-0
40
+ // doesn't make much sense due to http://stackoverflow.com/questions/24889934/componentinstance-setstate-undefined-in-0-11-0
51
41
  //components[kind] = component;
52
42
 
53
43
  React.renderComponent(
@@ -55,11 +45,8 @@
55
45
  document.getElementById('content')
56
46
  );
57
47
 
58
- // state reset won't work anymore in react v11,
59
- // plus I am not sure how it is supposed to work,
60
- // if namespace was just reset to zero
61
- // component.setState({currentNamespace: namespace.currentNamespace,
62
- // members: list.members(namespace.currentNamespace)});
48
+ // state reset won't work anymore in react v11, plus I am not sure how it is supposed to work, if namespace was just reset to zero
49
+ // component.setState({currentNamespace: namespace.currentNamespace, members: list.members(namespace.currentNamespace)});
63
50
  });
64
51
  },
65
52
 
@@ -86,11 +73,9 @@
86
73
  component,
87
74
  document.getElementById('content')
88
75
  );
89
- }, function(status, text) {
90
- if (status === 403) {
91
- conjur.app.flash = 'You are not authorized to view ' +
92
- conjur.app.kind + ':' + id + '.';
93
-
76
+ }, function(status, text, xhr) {
77
+ if (status == 403) {
78
+ conjur.app.flash = 'You are not authorized to view ' + conjur.app.kind + ':' + id + '.';
94
79
  window.history.back();
95
80
  } else {
96
81
  console.error('HTTP error: ', status, text);
@@ -113,9 +98,7 @@
113
98
 
114
99
  user: function(user) {
115
100
  this.activateRecord('user', user, function(record) {
116
- return (
117
- <User data={record}/>
118
- );
101
+ return <User data={record}/>;
119
102
  });
120
103
  },
121
104
 
@@ -124,17 +107,13 @@
124
107
  conjur.app.kind = 'users';
125
108
 
126
109
  this.activateList(function(list) {
127
- return (
128
- <UserBox data={{namespaces: list.namespaces, members: list.members('')}} />
129
- );
110
+ return <UserBox data={{namespaces: list.namespaces, members: list.members('')}} />;
130
111
  });
131
112
  },
132
113
 
133
114
  group: function(group) {
134
115
  this.activateRecord('group', group, function(record) {
135
- return (
136
- <Group data={record} />
137
- );
116
+ return <Group data={record} />;
138
117
  });
139
118
  },
140
119
 
@@ -143,17 +122,13 @@
143
122
  conjur.app.kind = 'groups';
144
123
 
145
124
  this.activateList(function(list) {
146
- return (
147
- <GroupBox data={{namespaces: list.namespaces, members: list.members('')}} />
148
- );
125
+ return <GroupBox data={{namespaces: list.namespaces, members: list.members('')}} />;
149
126
  });
150
127
  },
151
128
 
152
- host: function(host) {
129
+ host: function(host){
153
130
  this.activateRecord('host', host, function(record) {
154
- return (
155
- <Host data={record}/>
156
- );
131
+ return <Host data={record}/>;
157
132
  });
158
133
  },
159
134
 
@@ -163,17 +138,13 @@
163
138
  var HostBox = conjur.views.HostBox;
164
139
 
165
140
  this.activateList(function(list) {
166
- return (
167
- <HostBox data={{namespaces: list.namespaces, members: list.members('')}} />
168
- );
141
+ return <HostBox data={{namespaces: list.namespaces, members: list.members('')}} />;
169
142
  });
170
143
  },
171
144
 
172
145
  layer: function(layer) {
173
146
  this.activateRecord('layer', layer, function(record) {
174
- return (
175
- <Layer data={record} />
176
- );
147
+ return <Layer data={record} />;
177
148
  });
178
149
  },
179
150
 
@@ -182,17 +153,13 @@
182
153
  conjur.app.kind = 'layers';
183
154
 
184
155
  this.activateList(function(list) {
185
- return (
186
- <LayerBox data={{namespaces: list.namespaces, members: list.members('')}} />
187
- );
156
+ return <LayerBox data={{namespaces: list.namespaces, members: list.members('')}} />;
188
157
  });
189
158
  },
190
159
 
191
160
  variable: function(variable) {
192
161
  this.activateRecord('variable', variable, function(record) {
193
- return (
194
- <Variable data={record} />
195
- );
162
+ return <Variable data={record} />;
196
163
  });
197
164
  },
198
165
 
@@ -201,9 +168,7 @@
201
168
  conjur.app.kind = 'variables';
202
169
 
203
170
  this.activateList(function(list) {
204
- return (
205
- <VariableBox data={{namespaces: list.namespaces, members: list.members('')}} />
206
- );
171
+ return <VariableBox data={{namespaces: list.namespaces, members: list.members('')}} />;
207
172
  });
208
173
  },
209
174
 
@@ -211,21 +176,17 @@
211
176
  conjur.app.kind = 'policies';
212
177
 
213
178
  this.activateList(function(list) {
214
- return (
215
- <PolicyBox data={{members: list.members('')}} />
216
- );
179
+ return <PolicyBox data={{members: list.members('')}} />;
217
180
  });
218
181
  },
219
182
 
220
183
  policy: function(policy) {
221
184
  this.activateRecord('policy', policy, function(record) {
222
- return (
223
- <Policy data={record} />
224
- );
185
+ return <Policy data={record} />;
225
186
  });
226
187
  },
227
188
 
228
- audit: function() {
189
+ audit: function(){
229
190
  $('#inlineSearchContainer').show();
230
191
  this.setActiveNav('audit');
231
192
 
@@ -235,17 +196,10 @@
235
196
  );
236
197
  },
237
198
 
238
- search: function(search) {
199
+ search: function(search){
239
200
  $('#inlineSearchContainer').show();
240
201
  SearchResults.search(search);
241
202
  }
242
203
  });
243
204
 
244
- })
245
- (
246
- conjur,
247
- jQuery,
248
- _,
249
- Backbone,
250
- React
251
- );
205
+ })(conjur, jQuery, _, Backbone, React, SearchResults);
@@ -1,47 +1,36 @@
1
1
  /** @jsx React.DOM */
2
- /* global conjur, React */
3
2
 
4
- (function(conjur, React) {
5
- 'use strict';
3
+ var AnnotationsBox = React.createClass({
4
+ render: function() {
5
+
6
+ if (!this.props.annotations || !this.props.annotations.length>0 ) {
7
+ return <div>
8
+ <span>None</span>
9
+ </div>;
10
+ }
6
11
 
7
- this.AnnotationsBox = React.createClass({
8
- render: function() {
9
- if (!this.props.annotations || this.props.annotations.length === 0) {
10
- return (
11
- <div>
12
- <span>None</span>
13
- </div>
14
- );
15
- }
12
+ // TODO: sort by date (optionally)
13
+ // TODO: table view
14
+ var annotations_list = [];
15
+ this.props.annotations.sort(function(a,b) {
16
+ return a.name.toLowerCase().localeCompare(b.name.toLowerCase());
17
+ }).forEach(function(item){
18
+ var itemname = item.name;
19
+ var itemvalue = item.value;
16
20
 
17
- // TODO: sort by date (optionally)
18
- // TODO: table view
19
- var annotationsList = [];
21
+ var dt_key = "annotation_"+itemname+"_key";
22
+ var dd_key = "annotation_"+itemname+"_value";
23
+
24
+ annotations_list.push(<dt key={dt_key}>{itemname}</dt>);
25
+ annotations_list.push(<dd key={dd_key}>{itemvalue}</dd>);
26
+ });
20
27
 
21
- this.props.annotations.sort(function(a, b) {
22
- return a.name.toLowerCase().localeCompare(b.name.toLowerCase());
23
- }).forEach(function(item) {
24
- var itemName = item.name,
25
- itemValue = item.value,
26
- term = 'annotation_' + itemName + '_key',
27
- description = 'annotation_' + itemName + '_value';
28
28
 
29
- annotationsList.push(<dt key={term}>{itemName}</dt>);
30
- annotationsList.push(<dd key={description}>{itemValue}</dd>);
31
- });
32
-
33
- return (
34
- <div>
29
+ return <div>
35
30
  <dl className="annotations dl-horizontal">
36
- {annotationsList}
31
+ {annotations_list}
37
32
  </dl>
38
- </div>
39
- );
40
- }
41
- });
42
-
43
- }).bind(conjur.views)
44
- (
45
- conjur,
46
- React
33
+ </div>;
34
+ }
35
+ }
47
36
  );
@@ -6,7 +6,7 @@
6
6
  ref$ = React.DOM, em = ref$.em, strong = ref$.strong, 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;
7
7
  ref$ = require('prelude-ls'), map = ref$.map, each = ref$.each, unique = ref$.unique, isType = ref$.isType, join = ref$.join;
8
8
  compact_fields = ['auditview_user', 'auditview_action'];
9
- //extended_fields = ['timestamp', 'user', 'acting_as', 'action', 'entities', 'privilege','human'];
9
+ //extended_fields = ['timestamp', 'user', 'acting_as', 'action', 'entities', 'privilege','human'];
10
10
  extended_fields = ['timestamp','auditview_user','auditview_action'];
11
11
  known_rolsource_types = [ 'user','group','host','layer','policy']; // what if somebody explicitly will create the role of such type?
12
12
  FieldsMixin = {
@@ -59,9 +59,6 @@
59
59
  // copy of SHORT_FORMATS logic from cli-ruby:lib/conjur/command/audit.rb
60
60
  var msg="";
61
61
 
62
- var ResourceLink = conjur.views.ResourceLink;
63
- var RoleLink = conjur.views.RoleLink;
64
-
65
62
  if ((e.kind=='resource') && (e.action=='check')) {
66
63
  msg = [ ]
67
64
  if ( e.allowed ) {
@@ -87,7 +84,7 @@
87
84
  } else if ((e.kind=="resource") && (e.action=="permit")) {
88
85
  msg = [ " permitted ", RoleLink({id: e.grantee, noIcon: true}), " to ", em({}, e.privilege), " ", ResourceLink({id: e.resource, noIcon: true}) ]
89
86
  if ( e.grant_option )
90
- msg.push(" with grant option");
87
+ msg.push(" with grant option");
91
88
  } else if ((e.kind=="resource") && (e.action=="deny")) {
92
89
  msg = [ " denied ", em({}, e.privilege), " from ", RoleLink({id: e.grantee, noIcon: true}), " on ", ResourceLink({id: e.resource, noIcon: true}) ];
93
90
  } else if ((e.kind=="resource") && (e.action=="permitted_roles")) {
@@ -129,24 +126,24 @@
129
126
  var parts = [action_part];
130
127
  if (e.role!=null) {
131
128
  parts.push(" by ");
132
- parts.push(RoleLink({id: e.role, noIcon: true}));
129
+ parts.push(RoleLink({id: e.role, noIcon: true}));
133
130
  }
134
- if (e.resource_id!=null) {
131
+ if (e.resource_id!=null) {
135
132
  parts.push(" on");
136
- parts.push(ResourceLink({id: e.resource_id, noIcon: true}));
133
+ parts.push(ResourceLink({id: e.resource_id, noIcon: true}));
137
134
  }
138
- if (e.allowed!=null) {
139
- parts.push(" (allowed: "+e.allowed+")");
135
+ if (e.allowed!=null) {
136
+ parts.push(" (allowed: "+e.allowed+")");
140
137
  }
141
138
  var statement = parts.join(" ");
142
139
  msg = [" reported ", parts ];
143
- if (e.audit_message!=null) {
140
+ if (e.audit_message!=null) {
144
141
  msg.push("; message: ");
145
142
  msg.push(e.audit_message);
146
143
  }
147
144
  } else {
148
145
  msg+=" unknown event: "+e.kind+":"+e.action+"!";
149
- }
146
+ }
150
147
 
151
148
  if (e.error!=null) {
152
149
  msg+=" (failed with "+e.error+")";
@@ -155,9 +152,6 @@
155
152
  return msg;
156
153
  },
157
154
  transformField: function(key, value){
158
- var ResourceLink = conjur.views.ResourceLink;
159
- var RoleLink = conjur.views.RoleLink;
160
-
161
155
  var that;
162
156
  switch (key) {
163
157
  case 'entities':
@@ -185,7 +179,7 @@
185
179
  break;
186
180
  case 'auditview_user': //virtual field
187
181
  var acting_user =this.props.user;
188
- var acting_role = this.props.acting_as;
182
+ var acting_role = this.props.acting_as;
189
183
  msg = [ RoleLink({id: acting_user}) ];
190
184
  if ((acting_role!=null) && (acting_role != acting_user)) {
191
185
  msg.push([" as ", RoleLink({id: acting_role})]);
@@ -198,7 +192,7 @@
198
192
  });
199
193
  }
200
194
  break;
201
- case 'auditview_action':
195
+ case 'auditview_action':
202
196
  return this.humanizeEvent(this.props);
203
197
  default:
204
198
  return value;
@@ -239,7 +233,7 @@
239
233
  events: newEventSet()
240
234
  };
241
235
  },
242
- knownRolsourceTypes: function() {
236
+ knownRolsourceTypes: function() {
243
237
  return ;
244
238
  },
245
239
  render: function(){
@@ -256,7 +250,7 @@
256
250
  compact: compact
257
251
  }), tbody({
258
252
  key: 'tbody'
259
- }, this.state.events.filter(function(ev){
253
+ }, this.state.events.filter(function(ev){
260
254
  // remove internal resources creation
261
255
  if ((ev.role!=null) && (ev.role.split(':')[1] == '@')) {
262
256
  return false;
@@ -276,12 +270,12 @@
276
270
  var rolekind = ev.role.split(':')[1];
277
271
  if (_.contains(known_rolsource_types, rolekind)) {
278
272
  return false;
279
- }
280
- }
273
+ }
274
+ }
281
275
  return true;
282
276
  }).map(function(it){
283
277
  // new way to clone objects, custom clone$ does not work no more as expected
284
- var ref$ = React.addons.update(it, {$merge: {key: it.id, compact: compact} });
278
+ var ref$ = React.addons.update(it, {$merge: {key: it.id, compact: compact} });
285
279
  return new AuditEntry(ref$);
286
280
  }))
287
281
  ])
@@ -351,7 +345,7 @@
351
345
  resources);
352
346
  things = join(', ')(
353
347
  unique(
354
- roles.concat(resources)));
348
+ roles.concat(resources)));
355
349
 
356
350
  var options= { src: roleSrcs.concat(resSrcs) };
357
351
  if (this.props.tabview==null) {