conjur-asset-ui-api 1.1.1 → 1.2.0

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: d4e58d15d8bff87b2a55387b4ceedf751fa4196f
4
- data.tar.gz: 72c9f5cc63f114979e19b0b6a4d3034b71999450
3
+ metadata.gz: 7411cf0ff97005386a475d49c0fc2dfc015504c0
4
+ data.tar.gz: f0f45c605c547afa2d6216472d0c04967b3318c0
5
5
  SHA512:
6
- metadata.gz: d361ca37db90dda03a4a74c55447f4e41778d305466a4d28022de0c1aa546b4a87066cec7f460761a81acb88bae70401a14dbd4d7c72ad665154fe9bc6536012
7
- data.tar.gz: 0c8c2dc7a6fcdb2a59a9b8189ae4421c6e2af6ed51440a3d92e0a042efa4a9c8c54e8adb84afe84cdd6c952e4ac87a0a6c3269536a6efebd86f993d8bcbef499
6
+ metadata.gz: 56229687c796bffce448229fd4711c99bb78193b1cf2751c99d50d43a98e0bb0a4fa1fe0c5518d0709ce2e77ebfddf7d1e7368fbc5531da5ac3126c64cc0ce9e
7
+ data.tar.gz: 397fb524b5499af16448d2f3496a469054aa18ca77d64b1bfb1562329bbf44960a410f6968d893e1438f8977c4c2bd9977c09b3bdd843217af60a2939ede437a
data/Rakefile CHANGED
@@ -1 +1,3 @@
1
1
  require "bundler/gem_tasks"
2
+ require 'jasmine'
3
+ load 'jasmine/tasks/jasmine.rake'
data/compile_ls CHANGED
@@ -1,2 +1,6 @@
1
1
  #!/bin/bash
2
- lsc -w -c -o public/js livescript
2
+ lsc -w -c -o public/js livescript &
3
+ lsc -w -c -o spec spec &
4
+ while sleep 42; do true; done
5
+ kill `jobs -p`
6
+
@@ -33,4 +33,5 @@ Gem::Specification.new do |spec|
33
33
  spec.add_development_dependency "simplecov"
34
34
  spec.add_development_dependency "spork"
35
35
  spec.add_development_dependency "ci_reporter"
36
+ spec.add_development_dependency "jasmine"
36
37
  end
@@ -1,7 +1,7 @@
1
1
  module Conjur
2
2
  module Asset
3
3
  module UI
4
- VERSION="1.1.1"
4
+ VERSION="1.2.0"
5
5
  end
6
6
  end
7
7
  end
@@ -2,35 +2,41 @@ require 'time'
2
2
  require 'rack/utils'
3
3
  require 'rack/mime'
4
4
 
5
+ require 'conjur/webserver/renderer'
6
+
5
7
  module Conjur
6
8
  module WebServer
7
9
  class Home
8
- F = ::File
9
-
10
10
  def initialize(root)
11
11
  @root = root
12
12
  end
13
-
13
+
14
14
  # From Rack::File
15
15
  def call(env)
16
- path = File.expand_path("index.html", @root)
16
+ path = File.expand_path(INDEX, @root)
17
+ renderer = Renderer.new @root
18
+
19
+ page = renderer.render File.read(path)
20
+ files = renderer.files + [path]
21
+
22
+ last_modified = files.map(&File.method(:mtime)).max.httpdate
17
23
 
18
- if env["REQUEST_METHOD"] == "OPTIONS"
19
- return [200, {'Allow' => ALLOW_HEADER, 'Content-Length' => '0'}, []]
20
- end
21
- last_modified = F.mtime(path).httpdate
22
24
  return [304, {}, []] if env['HTTP_IF_MODIFIED_SINCE'] == last_modified
23
25
 
24
- size = F.size?(path) || Rack::Utils.bytesize(F.read(path))
25
-
26
- headers = {
26
+ size = Rack::Utils.bytesize(page)
27
+
28
+ headers = {
27
29
  "Last-Modified" => last_modified,
28
30
  "Content-Type" => "text/html",
29
31
  "Content-Length" => size.to_s
30
32
  }
31
-
32
- [ 200, headers, env["REQUEST_METHOD"] == "HEAD" ? [] : [ F.read(path) ] ]
33
+
34
+ [200, headers, env["REQUEST_METHOD"] == "HEAD" ? [] : [page]]
33
35
  end
36
+
37
+ private
38
+
39
+ INDEX = 'index.html.erb'.freeze
34
40
  end
35
41
  end
36
42
  end
@@ -10,6 +10,12 @@ module Conjur
10
10
 
11
11
  def call(env)
12
12
  if sessionid = token_valid?(env)
13
+ require 'conjur/authn'
14
+ require 'base64'
15
+ token = Conjur::Authn.authenticate
16
+ api = Conjur::API.new_from_token token
17
+ userid = [ Conjur.configuration.account, "user", api.username ].join(':')
18
+
13
19
  env["rack.session"][:sessionid] = sessionid
14
20
  response = Rack::Response.new(env)
15
21
  configuration = {
@@ -20,6 +26,7 @@ module Conjur
20
26
  }
21
27
  response.status = 302
22
28
  response.set_cookie('conjur_configuration', value: JSON.pretty_generate(configuration), path: '/')
29
+ response.set_cookie('conjur_userid', value: userid, path: '/')
23
30
  response['Location'] = "/ui"
24
31
  response.finish
25
32
  else
@@ -0,0 +1,34 @@
1
+ module Conjur
2
+ module WebServer
3
+ # a helper class to render HTML partials
4
+ class Renderer
5
+ def initialize root
6
+ @root = root
7
+ @files = []
8
+ end
9
+
10
+ attr_reader :files
11
+
12
+ def render template
13
+ ERB.new(template).result binding
14
+ end
15
+
16
+ private
17
+
18
+ def method_missing name, *a, &b
19
+ super if !a.empty? || block_given?
20
+
21
+ # try to load fragments
22
+ path = expand_path "_#{name}.html"
23
+ super unless File.exists? path
24
+
25
+ @files << path
26
+ File.read path
27
+ end
28
+
29
+ def expand_path filename
30
+ File.expand_path(filename, @root)
31
+ end
32
+ end
33
+ end
34
+ end
@@ -1,20 +1,31 @@
1
1
  {table, div, th, tr, td, thead, tbody, section, h3, time} = React.DOM
2
2
  {map, each, unique, is-type, join} = require 'prelude-ls'
3
3
 
4
- fields = <[ timestamp user acting_as action kind entity privilege ]>
4
+ compact_fields = <[ user action entities ]>
5
+ extended_fields = <[ timestamp user acting_as action entities privilege ]>
5
6
 
7
+ FieldsMixin = {
8
+ fields: ->
9
+ if @props.compact
10
+ compact_fields
11
+ else
12
+ extended_fields
13
+ }
6
14
 
7
15
  AuditTableHeader = React.createClass {
16
+ mixins: [ FieldsMixin ]
17
+
8
18
  display-name: \AuditTableHeader
19
+
9
20
  render: ->
10
- thead {}, (tr {}, (fields |> map -> th key: it, it.replace \_, ' '))
21
+ thead {}, (tr {}, (@fields() |> map -> th key: it, it.replace \_, ' '))
11
22
  }
12
23
 
13
24
  Timestamp = React.createClass {
14
25
  display-name: \Timestamp
15
26
  render: ->
16
27
  ts = moment(@props.time)
17
- time datetime: ts.format!, title: ts.calendar!, [ ts.from-now! ]
28
+ time date-time: ts.format!, title: ts.calendar!, [ ts.from-now! ]
18
29
  }
19
30
 
20
31
  wrap-array = ->
@@ -23,24 +34,24 @@ wrap-array = ->
23
34
  else
24
35
  [it]
25
36
 
26
- AuditEntry = React.createClass {
27
- display-name: \AuditEntry
37
+ export AuditEntry = React.createClass {
38
+ mixins: [ FieldsMixin ]
28
39
 
29
- transformed-props: ->
30
- @props with
31
- entity: @props.resource || @props.role
40
+ display-name: \AuditEntry
32
41
 
33
42
  transform-field: (key, value) ->
34
- | not value => value # need this case to handle blank values that turn up sometimes
35
- | key in <[ user acting_as ]> => RoleLink {id: value}
36
- | key == 'entity' => ResourceLink {data: value}
37
- | key == 'timestamp' => Timestamp {time: value}
38
- | otherwise => value
43
+ switch key
44
+ | \entities => [
45
+ if @props.resource? then ResourceLink data: that
46
+ if @props.role? then RoleLink id: that
47
+ ]
48
+ | <[ user acting_as ]> => RoleLink {id: value} if value?
49
+ | \timestamp => Timestamp {time: value} if value?
50
+ | _ => value
39
51
 
40
52
  render: ->
41
- props = @transformed-props!
42
53
  tr class-name: @props.action,
43
- fields |> map ~> td key: it, [ @transform-field(it, props[it]) ]
54
+ @fields() |> map ~> td key: it, ...wrap-array(@transform-field(it, @props[it]))
44
55
  }
45
56
 
46
57
  # compare events by id to prevent duplicates
@@ -52,19 +63,20 @@ new-event-set = ->
52
63
  @priv.comparator(existing, item) == 0 if existing?
53
64
  evts
54
65
 
55
- AuditTable = React.createClass {
66
+ export AuditTable = React.createClass {
56
67
  display-name: \AuditTable
57
68
 
58
69
  get-initial-state: ->
59
70
  events: new-event-set!
60
71
 
61
72
  render: ->
73
+ compact = @props.compact
62
74
  section class-name: \audit, [
63
75
  h3 {}, @props.caption
64
76
  table class-name: \audit-table, [
65
- AuditTableHeader(key: \thead),
77
+ AuditTableHeader(key: \thead, compact: compact),
66
78
  tbody key: \tbody,
67
- @state.events.map -> new AuditEntry it with key: it.id
79
+ @state.events.map -> new AuditEntry it with key: it.id, compact: compact
68
80
  ]
69
81
  ]
70
82
 
@@ -119,6 +131,6 @@ export AuditBox = React.createClass {
119
131
  things = (roles ++ resources) |> unique |> join ', '
120
132
  AuditTable {
121
133
  src: role-srcs ++ res-srcs
122
- caption: "Recent audit events for #things"
134
+ caption: "Recent Activity"
123
135
  }
124
136
  }
@@ -0,0 +1,37 @@
1
+ <script src="/js/models/namespace.js"></script>
2
+ <script src="/js/models/resourceList.js"></script>
3
+ <script src="/js/models/policyList.js"></script>
4
+ <script src="/js/models/userList.js"></script>
5
+ <script src="/js/models/variableList.js"></script>
6
+ <script src="/js/models/record.js"></script>
7
+ <script src="/js/models/groupRecord.js"></script>
8
+ <script src="/js/models/layerRecord.js"></script>
9
+ <script src="/js/models/variableRecord.js"></script>
10
+ <script src="/js/models/hostRecord.js"></script>
11
+ <script src="/js/models/userRecord.js"></script>
12
+ <script type="text/jsx" src="/js/views/mixins/search.js"></script>
13
+ <script type="text/jsx" src="/js/views/owned.js"></script>
14
+ <script type="text/jsx" src="/js/views/audit.js"></script>
15
+ <script type="text/jsx" src="/js/views/dashboard.js"></script>
16
+ <script type="text/jsx" src="/js/views/generic.js"></script>
17
+ <script type="text/jsx" src="/js/views/namespaces.js"></script>
18
+ <script type="text/jsx" src="/js/views/users.js"></script>
19
+ <script type="text/jsx" src="/js/views/hosts.js"></script>
20
+ <script type="text/jsx" src="/js/views/host.js"></script>
21
+ <script type="text/jsx" src="/js/views/role.js"></script>
22
+ <script type="text/jsx" src="/js/views/group.js"></script>
23
+ <script type="text/jsx" src="/js/views/groups.js"></script>
24
+ <script type="text/jsx" src="/js/views/layer.js"></script>
25
+ <script type="text/jsx" src="/js/views/layers.js"></script>
26
+ <script type="text/jsx" src="/js/views/variable.js"></script>
27
+ <script type="text/jsx" src="/js/views/variables.js"></script>
28
+ <script type="text/jsx" src="/js/views/policies.js"></script>
29
+ <script type="text/jsx" src="/js/views/policy.js"></script>
30
+ <script type="text/jsx" src="/js/views/resource.js"></script>
31
+ <script type="text/jsx" src="/js/views/permissions.js"></script>
32
+ <script type="text/jsx" src="/js/views/user.js"></script>
33
+ <script type="text/jsx" src="/js/views/time.js"></script>
34
+ <script type="text/jsx" src="/js/views/navSearch.js"></script>
35
+ <script type="text/jsx" src="/js/views/searchResults.js"></script>
36
+ <script src="/js/views/audit.js"></script>
37
+ <script type="text/jsx" src="/js/main.js"></script>
@@ -0,0 +1,21 @@
1
+ <!-- HTML5 Shim and Respond.js IE8 support of HTML5 elements and media queries -->
2
+ <!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
3
+ <!--[if lt IE 9]>
4
+ <script src="https://oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js"></script>
5
+ <script src="https://oss.maxcdn.com/libs/respond.js/1.3.0/respond.min.js"></script>
6
+ <![endif]-->
7
+
8
+ <script src="/js/lib/sorted-set.no-require.js"></script>
9
+ <script src="/js/lib/less.js"></script>
10
+ <script src="/js/lib/react-with-addons.js"></script>
11
+ <script src="/js/lib/JSXTransformer.js"></script>
12
+ <script src="http://cdnjs.cloudflare.com/ajax/libs/showdown/0.3.1/showdown.min.js"></script>
13
+ <script src="http://code.jquery.com/jquery-1.10.0.min.js"></script>
14
+ <script src="/js/lib/async.js"></script>
15
+ <script src="/js/lib/underscore-min.js"></script>
16
+ <script src="/js/lib/underscore.string.min.js"></script>
17
+ <script src="/js/lib/backbone.js"></script>
18
+ <script src="/js/lib/bootstrap.js"></script>
19
+ <script src="/js/lib/date.extensions.js"></script>
20
+ <script src="/js/lib/moment.js"></script>
21
+ <script src="/js/lib/prelude-browser-min.js"></script>
@@ -154,17 +154,17 @@ dl.propertyList {
154
154
  .role-link-icon('/images/icon-environment.png', 1.1em);
155
155
  }
156
156
 
157
- .host.role-link {
157
+ .host.role-link, .host.resource-link {
158
158
  .role-link-icon('/images/icon-client-pc.svg');
159
159
  background-position-y: -0.1em;
160
160
  }
161
161
 
162
- .user.role-link {
162
+ .user.role-link, .user.resource-link {
163
163
  .role-link-icon('/images/icon-person.svg');
164
164
  background-position-y: -0.2em;
165
165
  }
166
166
 
167
- .group.role-link {
167
+ .group.role-link, .group.resource-link {
168
168
  .role-link-padding;
169
169
  .group-icon(1.2em);
170
170
  }
@@ -179,6 +179,25 @@ dl.propertyList {
179
179
  margin-left: 0.5em;
180
180
  }
181
181
 
182
+
183
+ .dashboard {
184
+ #dashboard-search {
185
+ margin: 4em auto;
186
+ }
187
+
188
+ .owned ul {
189
+ margin: 0;
190
+ padding: 0;
191
+ }
192
+
193
+ .owned .hide-all { display: none; }
194
+
195
+ .owned li {
196
+ list-style-type: none;
197
+ padding: 3pt 8pt;
198
+ }
199
+ }
200
+
182
201
  .dashboard form.search, #searchResults form.search {
183
202
  margin: 0px auto;
184
203
  width: 300px;
@@ -270,7 +289,7 @@ body {
270
289
  }
271
290
 
272
291
  h3 {
273
- margin: 2em 0 1em;
292
+ margin: 1em 0 1em;
274
293
  letter-spacing: 0.01em;
275
294
  font-weight: 300;
276
295
  }
@@ -296,12 +315,6 @@ body {
296
315
  //
297
316
  // Styleguide 1.1.
298
317
  section.permissions {
299
- &.loading {
300
- h3:after {
301
- content: ' — loading, please wait…';
302
- font-weight: 300;
303
- }
304
- }
305
318
  }
306
319
 
307
320
  // The topmost content container.
@@ -0,0 +1,71 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>Conjur UI</title>
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <link href='http://fonts.googleapis.com/css?family=Lato:300,400,700,300italic,400italic,700italic' rel='stylesheet' type='text/css'>
7
+
8
+ <script src="/js/lib/pace.js"></script>
9
+ <!-- Bootstrap -->
10
+ <link href="/css/bootstrap.css" rel="stylesheet">
11
+
12
+ <!-- Some styles of our own -->
13
+ <link href="/css/styles.less" rel="stylesheet/less">
14
+
15
+ <%= client_libs %>
16
+ </head>
17
+ <body>
18
+ <div class="container">
19
+ <div class="navbar navbar-default" role="navigation">
20
+ <div class="navbar-collapse collapse">
21
+ <ul class="nav navbar-nav">
22
+ <li id="nav-home" class="nav-item"><a href="/ui">Dashboard</a></li>
23
+ <li id="nav-groups" class="dropdown">
24
+ <a class="dropdown-toggle" data-toggle="dropdown" href="#">
25
+ Actors <span class="caret"></span>
26
+ </a>
27
+ <ul class="dropdown-menu">
28
+ <li id="nav-users" class="nav-item"><a href="/ui/users">Users</a></li>
29
+ <li id="nav-groups" class="nav-item"><a href="/ui/groups">Groups</a></li>
30
+ <li class="divider"></li>
31
+ <li id="nav-hosts" class="nav-item"><a href="/ui/hosts">Hosts</a></li>
32
+ <li id="nav-layers" class="nav-item"><a href="/ui/layers">Layers</a></li>
33
+ </ul>
34
+ </li>
35
+ <li id="nav-assets" class="dropdown">
36
+ <a class="dropdown-toggle" data-toggle="dropdown" href="#">
37
+ Assets <span class="caret"></span>
38
+ </a>
39
+ <ul class="dropdown-menu">
40
+ <li id="nav-hosts" class="nav-item"><a href="/ui/hosts">Hosts</a></li>
41
+ <li id="nav-variables" class="nav-item"><a href="/ui/variables">Variables</a></li>
42
+ <li id="nav-key-pairs" class="nav-item"><a href="/ui/key-pairs">Key Pairs</a></li>
43
+ <li id="nav-web-services" class="nav-item"><a href="/ui/webservices">Web Services</a></li>
44
+ </ul>
45
+ </li>
46
+ <li id="nav-policies" class="nav-item"><a href="/ui/policies">Policies</a></li>
47
+ <li id="nav-audit" class="nav-item"><a href="/ui/audit">Audit</a></li>
48
+ </ul>
49
+ <div class="navbar-right" id="inlineSearchContainer">
50
+ </div>
51
+ </div>
52
+ </div>
53
+
54
+ </div>
55
+ <div class="alert alert-danger alert-dismissable" id="flash">
56
+ <button type="button" class="close" data-dismiss="alert" aria-hidden="true">&times;</button>
57
+ <span class="text"></span>
58
+ </div>
59
+ <div id="content"></div>
60
+ <div id="bottom"></div>
61
+ </div><!-- /.container -->
62
+
63
+
64
+ <div id="modal">
65
+
66
+ </div>
67
+
68
+
69
+ <%= client_code %>
70
+ </body>
71
+ </html>