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.
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,41 +1,56 @@
1
1
  /** @jsx React.DOM */
2
+ /* global conjur, React, _ */
2
3
 
3
- /** render a link to the role represented by this.props.id
4
- Example: <RoleLink id="ci:user:jon"/>
5
- */
6
- var RoleLink = React.createClass({
7
- render: function() {
8
- var tokens = this.props.id.split(":");
9
- var kind = tokens[1];
10
- var id = tokens[tokens.length-1];
11
- if (tokens.length==1) { // just username
12
- kind="user";
13
- id=tokens[0];
14
- }
15
-
16
- // TODO: shouldn't point to unknown types
17
- var href = "/ui/" + conjur.utils.pluralize(kind) + "/" + encodeURIComponent(id);
18
- var classes = ["role-link"];
19
-
20
- var known_types=['user','group','layer','host','policy'];
21
- var kind_is_known = _.contains(known_types, kind);
22
- var text = id;
23
-
24
- if( !this.props.noIcon ) {
25
- if (kind_is_known) {
26
- classes.push(kind);
27
- } else {
28
- classes.push('abstract'); // we have no picture for abstract role yet
29
- if (text==id) {
30
- text=[kind,text].join(":"); // prepend kind to id
4
+ (function(conjur, React, _) {
5
+ 'use strict';
6
+
7
+ /** render a link to the role represented by this.props.id
8
+ Example: <RoleLink id='ci:user:jon'/>
9
+ */
10
+ this.RoleLink = React.createClass({
11
+ render: function() {
12
+ var tokens = this.props.id.split(':'),
13
+ kind = tokens[1],
14
+ id = tokens[tokens.length-1];
15
+
16
+ if (tokens.length === 1) { // just username
17
+ kind = 'user';
18
+ id = tokens[0];
31
19
  }
20
+
21
+ // TODO: shouldn't point to unknown types
22
+ var href = '/ui/' + conjur.utils.pluralize(kind) + '/' + window.encodeURIComponent(id);
23
+
24
+ var classes = ['role-link'],
25
+ knownTypes = ['user','group','layer','host','policy'],
26
+ kindIsKnown = _.contains(knownTypes, kind),
27
+ text = id;
28
+
29
+ if (!this.props.noIcon) {
30
+ if (kindIsKnown) {
31
+ classes.push(kind);
32
+ } else {
33
+ classes.push('abstract'); // we have no picture for abstract role yet
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
41
+ }
42
+
43
+ return (
44
+ <a className={classes.join(' ')} href={href}>
45
+ {text}
46
+ </a>
47
+ );
32
48
  }
33
- } else if (text==id) {
34
- text=[kind,text].join(":"); // prepend kind to id
35
- }
36
-
37
- return <a className={classes.join(' ')} href={href}>
38
- {text}
39
- </a>;
40
- }
41
- });
49
+ });
50
+
51
+ }).bind(conjur.views)
52
+ (
53
+ conjur,
54
+ React,
55
+ _
56
+ );
@@ -1,145 +1,212 @@
1
1
  /**@jsx React.DOM*/
2
+ /* global conjur, React, jQuery, _ */
2
3
 
3
- var SearchGroupTitle = React.createClass({
4
- render: function(){
5
- return <span>{this.title()}</span>
6
- },
7
-
8
- title: function(){
9
- var words = this.props.data.kind.replace(/[-_]/, ' ').split(' ');
10
- words[words.length - 1] = conjur.utils.pluralize(words[words.length - 1]);
11
- return words.map(_.str.capitalize).join(' ') + ' (' + this.props.data.items.length + ')';
12
- }
13
- });
14
-
15
- var SearchGroupHeading = React.createClass({
16
- render: function(){
17
- var targetId = "#search-collapse-" + this.props.data.kind;
18
- return <div className="panel-heading">
19
- <h4 className="panel-title">
20
- <a data-toggle="collapse" data-target={targetId}
21
- className={'group-heading' + this.props.data.kind}>
22
- <SearchGroupTitle data={this.props.data} />
23
- </a>
24
- </h4>
25
- </div>;
26
- },
27
-
28
- title: function(){
29
- var words = this.props.data.kind.replace(/[-_]/, ' ').split(' ');
30
- words[words.length - 1] = conjur.utils.pluralize(words[words.length - 1]);
31
- return words.map(_.str.capitalize).join(' ') + ' (' + this.props.data.items.length + ')';
32
- }
33
- });
34
-
35
- var SearchResultItem = React.createClass({
36
- render: function(){
37
- return <div className="item">
38
- <h4> { this.titleLink() } </h4>
39
- <div className="details">
40
- <strong> ID: </strong> <ResourceLink data={this.props.data.id} noIcon="true"/>
41
- <strong> Owner: </strong> <RoleLink id={this.props.data.owner} noIcon="true"/>
42
- </div>
43
- <div className="comment">
44
- {this.commentText()}
45
- </div>
46
- </div>;
47
- },
48
-
49
- commentText: function(){
50
- var annots = this.annotationsMap();
51
- return annots['description'] || "";
52
- },
53
-
54
- titleLink: function(){
55
- var annots = this.annotationsMap();
56
- return <ResourceLink data={this.props.data.id} text={annots['name']}/>
57
- },
58
-
59
- annotationsMap: function(){
60
- if(this._annotationsMap) return this._annotationsMap;
61
- var map = this._annotationsMap = {};
62
- (this.props.data.annotations || []).forEach(function(a){
63
- map[a.name] = a.value;
4
+
5
+ (function(conjur, React, $, _) {
6
+ 'use strict';
7
+
8
+ var ResourceLink = conjur.views.ResourceLink,
9
+ RoleLink = conjur.views.RoleLink;
10
+
11
+ var SearchGroupTitle = React.createClass({
12
+ render: function() {
13
+ return (
14
+ <span>{this.title()}</span>
15
+ );
16
+ },
17
+
18
+ title: function() {
19
+ var words = this.props.data.kind.replace(/[-_]/, ' ').split(' ');
20
+
21
+ words[words.length - 1] = conjur.utils.pluralize(words[words.length - 1]);
22
+
23
+ return (
24
+ words.map(_.str.capitalize).join(' ') + ' (' + this.props.data.items.length + ')'
25
+ );
26
+ }
64
27
  });
65
- return map;
66
- }
67
- });
68
-
69
- // accepts props like data: { kind:"", items:[] }
70
- var SearchGroup = React.createClass({
71
- render: function(){
72
- var id = "search-group-" + this.props.data.kind;
73
- var items = this.props.data.items.map(function(r){
74
- return <SearchResultItem data={r}/>
75
- })
76
- return <div id={id} className="panel panel-default search-group">
77
- <SearchGroupHeading data={this.props.data}/>
78
- <div id={"search-collapse-" + this.props.data.kind} className="panel-collapse collapse in">
79
- <div className="panel-body">
80
- {items}
81
- </div>
82
- </div>
83
- </div>;
84
- }
85
- });
86
-
87
- var SearchResults = React.createClass({
88
- render: function() {
89
- var results = this.props.data.results;
90
- var grouped = _.groupBy(results, function(r){
91
- return r.id.split(':')[1];
28
+
29
+ var SearchGroupHeading = React.createClass({
30
+ render: function() {
31
+ var targetId = '#search-collapse-' + this.props.data.kind;
32
+
33
+ return (
34
+ <div className="panel-heading">
35
+ <h4 className="panel-title">
36
+ <a data-toggle="collapse"
37
+ data-target={targetId}
38
+ className={'group-heading' + this.props.data.kind}>
39
+ <SearchGroupTitle data={this.props.data} />
40
+ </a>
41
+ </h4>
42
+ </div>
43
+ );
44
+ },
45
+
46
+ title: function() {
47
+ var words = this.props.data.kind.replace(/[-_]/, ' ').split(' ');
48
+
49
+ words[words.length - 1] = conjur.utils.pluralize(words[words.length - 1]);
50
+
51
+ return (
52
+ words.map(_.str.capitalize).join(' ') + ' (' + this.props.data.items.length + ')'
53
+ );
54
+ }
92
55
  });
93
- // Don't care about these
94
- delete grouped['environment-variables']
95
- delete grouped['notification']
96
- delete grouped['queue']
97
-
98
- var groups = _.map(grouped,function(items, key){
99
- var data = {items:items, kind: key}; // - prevent editor barfing
100
- return <SearchGroup data={data}/>
56
+
57
+ var SearchResultItem = React.createClass({
58
+ render: function() {
59
+ return (
60
+ <div className="item">
61
+ <h4>{this.titleLink()}</h4>
62
+ <div className="details">
63
+ <strong> ID: </strong> <ResourceLink data={this.props.data.id}
64
+ noIcon="true" />
65
+ <strong> Owner: </strong> <RoleLink id={this.props.data.owner}
66
+ noIcon="true" />
67
+ </div>
68
+ <div className="comment">
69
+ {this.commentText()}
70
+ </div>
71
+ </div>
72
+ );
73
+ },
74
+
75
+ commentText: function() {
76
+ var annots = this.annotationsMap();
77
+
78
+ return annots.description || '';
79
+ },
80
+
81
+ titleLink: function(){
82
+ var annots = this.annotationsMap();
83
+
84
+ return (
85
+ <ResourceLink data={this.props.data.id} text={annots.name} />
86
+ );
87
+ },
88
+
89
+ annotationsMap: function(){
90
+ if (this._annotationsMap) {
91
+ return this._annotationsMap;
92
+ }
93
+
94
+ var map = this._annotationsMap = {};
95
+
96
+ (this.props.data.annotations || []).forEach(function(a) {
97
+ map[a.name] = a.value;
98
+ });
99
+
100
+ return map;
101
+ }
101
102
  });
102
- var scores = {
103
- 'policy': 1,
104
- 'layer': 2,
105
- 'group': 3,
106
- 'host': 4,
107
- 'user': 5,
108
- 'variable': 6,
109
- 'key_pair': 7
110
- };
111
- groups.sort(function(a, b) {
112
- return ( scores[a.props.data.kind] || 100 ) - ( scores[b.props.data.kind] || 100 );
103
+
104
+ // accepts props like data: { kind:"", items:[] }
105
+ var SearchGroup = React.createClass({
106
+ render: function() {
107
+ var id = 'search-group-' + this.props.data.kind;
108
+
109
+ var items = this.props.data.items.map(function(r) {
110
+ return (
111
+ <SearchResultItem data={r}/>
112
+ );
113
+ });
114
+
115
+ return (
116
+ <div id={id} className="panel panel-default search-group">
117
+ <SearchGroupHeading data={this.props.data}/>
118
+ <div id={'search-collapse-' + this.props.data.kind}
119
+ className="panel-collapse collapse in">
120
+ <div className="panel-body">
121
+ {items}
122
+ </div>
123
+ </div>
124
+ </div>
125
+ );
126
+ }
113
127
  });
114
- var toc = groups.map(function(g) {
115
- var gid = "#search-group-" + g.props.data.kind;
116
- return <div className="toc-item">
117
- <a href={gid}><SearchGroupTitle data={g.props.data} /></a>
118
- </div>
128
+
129
+ var SearchResults = this.SearchResults = React.createClass({
130
+ render: function() {
131
+ var results = this.props.data.results;
132
+
133
+ var grouped = _.groupBy(results, function(r) {
134
+ return r.id.split(':')[1];
135
+ });
136
+
137
+ // Don't care about these
138
+ delete grouped['environment-variables'];
139
+ delete grouped.notification;
140
+ delete grouped.queue;
141
+
142
+ var groups = _.map(grouped, function(items, key) {
143
+ var data = {items: items, kind: key}; // - prevent editor barfing
144
+ return <SearchGroup data={data}/>;
145
+ });
146
+
147
+ var scores = {
148
+ 'policy': 1,
149
+ 'layer': 2,
150
+ 'group': 3,
151
+ 'host': 4,
152
+ 'user': 5,
153
+ 'variable': 6,
154
+ 'key_pair': 7
155
+ };
156
+
157
+ groups.sort(function(a, b) {
158
+ return (
159
+ (scores[a.props.data.kind] || 100) -
160
+ (scores[b.props.data.kind] || 100)
161
+ );
162
+ });
163
+
164
+ var toc = groups.map(function(g) {
165
+ var gid = '#search-group-' + g.props.data.kind;
166
+
167
+ return (
168
+ <div className="toc-item">
169
+ <a href={gid}><SearchGroupTitle data={g.props.data} /></a>
170
+ </div>
171
+ );
172
+ });
173
+
174
+ var heading = 'Found ' + this.props.data.results.length +
175
+ ' resources matching "' + this.props.data.search + '"';
176
+
177
+ return (
178
+ <div id="searchResults">
179
+ <div className="searchResults">
180
+ <h3> { heading } </h3>
181
+ <div className="search-results-toc">
182
+ {toc}
183
+ </div>
184
+ <div className="search-results">
185
+ {groups}
186
+ </div>
187
+ </div>
188
+ </div>
189
+ );
190
+ }
119
191
  });
120
- var heading = "Found " + this.props.data.results.length +
121
- " resources matching \"" + this.props.data.search + "\"";
122
- return (
123
- <div id="searchResults">
124
- <div className="searchResults">
125
- <h3> { heading } </h3>
126
- <div className="search-results-toc">
127
- {toc}
128
- </div>
129
- <div className="search-results">
130
- {groups}
131
- </div>
132
- </div>
133
- </div>
134
- );
135
- }
136
- });
137
-
138
- SearchResults.search = function(search, container){
139
- container = container || document.getElementById('content');
140
- $.get(conjur.app.endpoints.authz("resources", {search: search.replace('-',' ')}), function(results){
141
-
142
- var data = {search: search, results: results};
143
- React.renderComponent(<SearchResults data={data}/>, container);
144
- });
145
- }
192
+
193
+ SearchResults.search = function(search, container) {
194
+ container = container || document.getElementById('content');
195
+
196
+ $.get(
197
+ conjur.app.endpoints.authz('resources', {search: search.replace('-',' ')}),
198
+ function(results) {
199
+ var data = {search: search, results: results};
200
+ React.renderComponent(<SearchResults data={data}/>, container);
201
+ }
202
+ );
203
+ };
204
+
205
+
206
+ }).bind(conjur.views)
207
+ (
208
+ conjur,
209
+ React,
210
+ jQuery,
211
+ _
212
+ );
@@ -1,14 +1,27 @@
1
1
  /** @jsx React.DOM */
2
-
3
- // render a <time> tag. props.timestamp should be a timestamp
4
- // that moment can parse, props.format should be one of the
5
- // format strings accepted by moment (optional).
6
- var Time = React.createClass({
7
- render: function(){
8
- var timestamp = this.props.timestamp;
9
- var format = this.props.format || 'lll';
10
- var m = moment(timestamp);
11
-
12
- return <time dateTime={m.format()}>{m.format(format)}</time>;
13
- }
14
- })
2
+ /* global conjur, React, moment */
3
+
4
+ (function(conjur, React, moment) {
5
+ 'use strict';
6
+
7
+ // render a <time> tag. props.timestamp should be a timestamp
8
+ // that moment can parse, props.format should be one of the
9
+ // format strings accepted by moment (optional).
10
+ this.Time = React.createClass({
11
+ render: function(){
12
+ var timestamp = this.props.timestamp;
13
+ var format = this.props.format || 'lll';
14
+ var m = moment(timestamp);
15
+
16
+ return (
17
+ <time dateTime={m.format()}>{m.format(format)}</time>
18
+ );
19
+ }
20
+ });
21
+
22
+ }).bind(conjur.views)
23
+ (
24
+ conjur,
25
+ React,
26
+ moment
27
+ );