hieraviz 0.0.1 → 0.0.2

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.
@@ -48,9 +48,9 @@ ready( () => {
48
48
  function build_top(title) {
49
49
  meat.innerHTML = "<h3>Node "+title+"</h3>";
50
50
  addTo(meat, "<div class=\"nodenav\">" +
51
- "<span class=\"showinfo\" data-node=\""+title+"\">Info</span>" +
52
- "<span class=\"showparams\" data-node=\""+title+"\">Params</span>" +
53
- "<span class=\"showallparams\" data-node=\""+title+"\">AllParams</span>" +
51
+ "<span class=\"showinfo\" data-item=\""+title+"\">Info</span>" +
52
+ "<span class=\"showparams\" data-item=\""+title+"\">Params</span>" +
53
+ "<span class=\"showallparams\" data-item=\""+title+"\">AllParams</span>" +
54
54
  "</div>");
55
55
  addTo(meat, "<div class=\"paramfilter\">" +
56
56
  "<input type=\"text\" name=\"paramfilter\" />" +
@@ -81,7 +81,7 @@ ready( () => {
81
81
  item.addEventListener('click', (ev) => {
82
82
  start_wait();
83
83
  el = ev.target;
84
- action = el.innerText.toLowerCase();
84
+ action = el.textContent.toLowerCase();
85
85
  fetch('/v1/node/' + title + '/' + action).
86
86
  then(res => res.json()).
87
87
  then(j => {
@@ -92,42 +92,54 @@ ready( () => {
92
92
  });
93
93
  }
94
94
 
95
+ function show_error(meat, message) {
96
+ meat.innerHTML = "<div class=\"error\">" + message + "</div>\n";
97
+ }
98
+
95
99
  var Node = {
96
100
  params: function(el) {
97
101
  start_wait(meat);
98
- title = el.dataset.node;
99
- fetch('/v1/node/' + title).
102
+ title = el.dataset.item;
103
+ fetch('/v1/node/' + title, auth_header()).
100
104
  then(res => res.json()).
101
105
  then(j => {
102
- build_top(title);
103
- build_params(meat, title, j);
104
- rebuild_nav(title);
106
+ console.log(auth_header().headers.getAll('x-auth'));
107
+ if (j.error != undefined) {
108
+ show_error(meat, j['error']);
109
+ } else {
110
+ build_top(title);
111
+ build_params(meat, title, j);
112
+ rebuild_nav(title);
113
+ update_footer('/v1/node/' + title);
114
+ }
105
115
  end_wait(meat);
106
116
  });
107
117
  },
108
118
 
109
119
  info: function(el) {
110
120
  start_wait(meat);
111
- title = el.dataset.node;
112
- fetch('/v1/node/' + title + '/info').
121
+ title = el.dataset.item;
122
+ fetch('/v1/node/' + title + '/info', auth_header()).
113
123
  then(res => res.json()).
114
124
  then(j => {
115
125
  build_top(title);
116
126
  build_info(meat, title, j);
117
127
  rebuild_nav(title);
128
+ update_footer('/v1/node/' + title + '/info');
118
129
  end_wait(meat);
119
130
  });
120
131
  },
121
132
 
122
133
  allparams: function(el) {
123
134
  start_wait(meat);
124
- title = el.dataset.node;
125
- fetch('/v1/node/' + title + '/all').
135
+ title = el.dataset.item;
136
+ fetch('/v1/node/' + title + '/all', auth_header()).
126
137
  then(res => res.json()).
127
138
  then(j => {
128
139
  build_top(title);
129
140
  build_info(meat, title, j);
130
141
  rebuild_nav(title);
142
+ update_footer('/v1/node/' + title + '/all');
131
143
  end_wait(meat);
132
144
  });
133
145
  },
data/app/views/_foot.erb CHANGED
@@ -1,3 +1,5 @@
1
- footer
1
+ <span class="puppetdb">
2
+ <%= settings.configdata['puppetdb']['host'] %>
3
+ </span>
2
4
  <span class="debug">
3
5
  </span>
data/app/views/_head.erb CHANGED
@@ -3,6 +3,7 @@
3
3
  <%= settings.app_name %>
4
4
  </a>
5
5
  </div>
6
+ <% if session[:access_token] -%>
6
7
  <div class="nav">
7
8
  <a href="/nodes" class="nodes">Nodes</a>
8
9
  <a href="/farms" class="farms">Farms</a>
@@ -10,5 +11,13 @@
10
11
  <a href="/resources" class="resources">Resources</a>
11
12
  </div>
12
13
  <div class="auth">
14
+ <div class="username">
15
+ identified as <b><%= @username %></b>
16
+ </div>
13
17
  <a href="/logout" id="logout">Logout</a>
14
18
  </div>
19
+ <% else -%>
20
+ <div class="auth">
21
+ <a href="/login" id="login">Connect</a>
22
+ </div>
23
+ <% end -%>
@@ -5,7 +5,11 @@
5
5
  <%= @title if @title %>
6
6
  </title>
7
7
  <link href="css/main.css" rel="stylesheet" type="text/css">
8
+ <script src="js/fetch.js"></script>
8
9
  <script src="js/main.js"></script>
10
+ <% if session['access_token'] -%>
11
+ <script>var session_key = "<%= session['access_token'] %>";</script>
12
+ <% end -%>
9
13
  <%= yield_content :more_js %>
10
14
  </head>
11
15
  <body>
@@ -14,6 +18,7 @@
14
18
  <%= erb :_head, :layout => false %>
15
19
  </div>
16
20
  <div class="content">
21
+ <%= styled_flash %>
17
22
  <%= yield %>
18
23
  </div>
19
24
  <div class="foot">
@@ -0,0 +1,4 @@
1
+ <div class="meat text">
2
+ <h1>Raw Data</h1>
3
+ <pre><%= @data %></pre>
4
+ </div>
data/app/views/farms.erb CHANGED
@@ -8,7 +8,7 @@
8
8
  </form>
9
9
  <ul>
10
10
  <% @farms.each do |farm| %>
11
- <li class="farm"><%= farm %></li>
11
+ <li class="farm" data-item="<%= farm %>"><%= farm %></li>
12
12
  <% end %>
13
13
  </ul>
14
14
  </div>
data/app/views/home.erb CHANGED
@@ -1,3 +1,8 @@
1
1
  <div class="meat text">
2
- Welcome to hieraviz
2
+ Welcome to hieraviz<br>
3
+
4
+ <% if settings.configdata['debug'] -%>
5
+ <%= session['access_token'] %><br>
6
+ <pre><%= Hieraviz::Store.get session['access_token'] if session['access_token'] %></pre>
3
7
  </div>
8
+ <% end %>
@@ -2,7 +2,8 @@
2
2
  <script async="async" src="js/modules.js"></script>
3
3
  <% end %>
4
4
 
5
- <pre class="meat">
6
- WIP
7
- </pre>
5
+ <div class="meat">
6
+ <br>
7
+ <div>Work In Progress</div>
8
+ </div>
8
9
 
data/app/views/nodes.erb CHANGED
@@ -8,7 +8,7 @@
8
8
  </form>
9
9
  <ul>
10
10
  <% @nodes.each do |node| %>
11
- <li class="node" data-node="<%= node %>"><%= node %></li>
11
+ <li class="node" data-item="<%= node %>"><%= node %></li>
12
12
  <% end %>
13
13
  </ul>
14
14
  </div>
@@ -2,7 +2,7 @@
2
2
  <script src="js/resources.js"></script>
3
3
  <% end %>
4
4
 
5
- <pre class="meat">
6
- WIP
7
- </pre>
8
-
5
+ <div class="meat">
6
+ <br>
7
+ <div>Work In Progress</div>
8
+ </div>
@@ -0,0 +1,6 @@
1
+ <div class="meat text">
2
+ <h1>Store</h1>
3
+ <%= session['access_token'] %><br>
4
+ <pre><%= Hieraviz::Store.dump %></pre>
5
+ <pre><%= Hieraviz::Store.tmpdir %></pre>
6
+ </div>
data/app/web.rb CHANGED
@@ -1,8 +1,9 @@
1
1
  require 'sinatra/content_for'
2
+ require 'sinatra/flash'
2
3
 
3
4
  require 'better_errors'
4
- require 'digest/sha1'
5
5
  require 'dotenv'
6
+ require 'oauth2'
6
7
 
7
8
  require 'hieracles'
8
9
  require 'hieraviz'
@@ -12,61 +13,133 @@ require File.expand_path '../common.rb', __FILE__
12
13
  module HieravizApp
13
14
  class Web < Common
14
15
  helpers Sinatra::ContentFor
16
+ register Sinatra::Flash
15
17
 
16
18
  configure do
19
+ set :session_secret, settings.configdata['session_seed']
17
20
  set :public_folder, Proc.new { File.join(root, "public") }
18
21
  set :views_folder, Proc.new { File.join(root, "views") }
19
22
  set :erb, layout: :_layout
23
+ enable :sessions
20
24
  end
21
25
 
22
26
  configure :development do
23
27
  use BetterErrors::Middleware
24
- BetterErrors.application_root = File.expand_path('..', __FILE__)
28
+ BetterErrors.application_root = File.expand_path('../../', __FILE__)
25
29
  end
26
30
 
27
- helpers do
28
- def check_cookie
29
- if !session[:hieraviz_key]
30
- newkey = Digest::SHA1.hexdigest(Time.new.to_s)
31
- store.set(:hieraviz_key, newkey)
32
- session[:hieraviz_key] = newkey
31
+ case settings.configdata['auth_method']
32
+ when 'http'
33
+
34
+ use Rack::Auth::Basic, "Puppet Private Access" do |username, password|
35
+ username == settings.configdata['http_auth']['username'] &&
36
+ password == settings.configdata['http_auth']['password']
37
+ end
38
+
39
+ get '/logout' do
40
+ erb :logout, layout: :_layout
41
+ end
42
+
43
+ helpers do
44
+ def check_authorization
45
+ set :username, settings.configdata['http_auth']['username']
46
+ true
33
47
  end
34
48
  end
35
- def verify_key(key)
36
-
49
+
50
+ when 'gitlab'
51
+
52
+ set :oauth, Hieraviz::AuthGitlab.new(settings.configdata['gitlab_auth'])
53
+
54
+ def get_username
55
+ if session['access_token']
56
+ session_info = Hieraviz::Store.get(session['access_token'], settings.configdata['session_renew'])
57
+ if session_info
58
+ session_info['username']
59
+ else
60
+ ''
61
+ end
62
+ end
63
+ end
64
+
65
+ def check_authorization
66
+ if !session['access_token']
67
+ redirect settings.oauth.login_url(request)
68
+ else
69
+ session_info = Hieraviz::Store.get(session['access_token'], settings.configdata['session_renew'])
70
+ if !session_info
71
+ if !settings.oauth.authorized?(session['access_token'])
72
+ flash[:fatal] = "Sorry you are not authorized to read puppet repo on gitlab."
73
+ redirect '/'
74
+ else
75
+ Hieraviz::Store.set session['access_token'], settings.oauth.user_info(session['access_token'])
76
+ session_info = Hieraviz::Store.get(session['access_token'], settings.configdata['session_renew'])
77
+ end
78
+ end
79
+ session_info['username']
80
+ end
81
+ end
82
+
83
+ get '/login' do
84
+ redirect settings.oauth.login_url(request)
85
+ end
86
+
87
+ get '/logged-in' do
88
+ access_token = settings.oauth.access_token(request, params[:code])
89
+ session[:access_token] = access_token.token
90
+ Hieraviz::Store.set access_token.token, settings.oauth.user_info(access_token.token)
91
+ flash['info'] = "Successfully authenticated with the server"
92
+ redirect '/'
93
+ end
94
+
95
+ get '/logout' do
96
+ session.clear
97
+ redirect '/'
37
98
  end
38
- end
39
99
 
40
- use Rack::Auth::Basic, "Puppet Private Access" do |username, password|
41
- username == settings.configdata['http_auth']['username'] &&
42
- password == settings.configdata['http_auth']['password']
100
+ else
43
101
  end
44
102
 
45
103
 
46
104
  get '/' do
105
+ @username = get_username
47
106
  erb :home
48
107
  end
49
108
 
50
109
  get '/nodes' do
110
+ @username = check_authorization
51
111
  @nodes = Hieracles::Registry.nodes(settings.config)
52
112
  erb :nodes
53
113
  end
54
114
 
55
115
  get '/farms' do
116
+ @username = check_authorization
56
117
  @farms = Hieracles::Registry.farms(settings.config)
57
118
  erb :farms
58
119
  end
59
120
 
60
121
  get '/modules' do
61
- erb :farms
122
+ @username = check_authorization
123
+ erb :modules
62
124
  end
63
125
 
64
126
  get '/resources' do
65
- erb :farms
127
+ @username = check_authorization
128
+ erb :resources
66
129
  end
67
130
 
68
- get '/logout' do
69
- erb :logout, layout: :_layout
131
+ get '/store' do
132
+ # Hieraviz::Store.set 'woot', 'nada'
133
+ erb :store
134
+ end
135
+
136
+ get '/user' do
137
+ if session[:access_token]
138
+ @data = settings.oauth.user_info(session[:access_token])
139
+ else
140
+ @data = 'nada'
141
+ end
142
+ erb :data
70
143
  end
71
144
 
72
145
  not_found do
@@ -0,0 +1,59 @@
1
+ require 'oauth2'
2
+
3
+ module Hieraviz
4
+ class AuthGitlab
5
+
6
+ def initialize(settings)
7
+ @@client ||= OAuth2::Client.new(
8
+ settings['application_id'],
9
+ settings['secret'],
10
+ :site => settings['host']
11
+ )
12
+ @settings = settings
13
+ end
14
+
15
+ def access_token(request, code)
16
+ @@client.auth_code.get_token(code, :redirect_uri => redirect_uri(request))
17
+ end
18
+
19
+ def get_response(url, token)
20
+ access_token = OAuth2::AccessToken.new(@@client, token)
21
+ begin
22
+ JSON.parse(access_token.get(url).body)
23
+ rescue Exception => e
24
+ { 'error' => JSON.parse(e.message.split(/\n/)[1])['message'] }
25
+ end
26
+ end
27
+
28
+
29
+ def redirect_uri(request)
30
+ uri = URI.parse(request.url)
31
+ uri.path = '/logged-in'
32
+ uri.query = nil
33
+ uri.to_s
34
+ end
35
+
36
+ def login_url(request)
37
+ @@client.auth_code.authorize_url(:redirect_uri => redirect_uri(request))
38
+ end
39
+
40
+ def authorized?(token)
41
+ if @settings['resource_required']
42
+ resp = get_response(@settings['resource_required'], token)
43
+ if resp['error'] ||
44
+ (resp[@settings['required_response_key']] &&
45
+ resp[@settings['required_response_key']] != resp[@settings['required_response_value']])
46
+ false
47
+ else
48
+ true
49
+ end
50
+ end
51
+ true
52
+ end
53
+
54
+ def user_info(token)
55
+ get_response('/api/v3/user', token)
56
+ end
57
+
58
+ end
59
+ end
@@ -0,0 +1,20 @@
1
+ module Hieraviz
2
+ module Config
3
+ extend self
4
+
5
+ def load
6
+ @_config ||= YAML.load_file(configfile)
7
+ end
8
+
9
+ def configfile
10
+ file = ENV['HIERAVIZ_CONFIG_FILE'] || File.join("config", "hieraviz.yml")
11
+ file = File.join(root, file) unless file[0] == '/'
12
+ file
13
+ end
14
+
15
+ def root
16
+ File.expand_path('../../../', __FILE__)
17
+ end
18
+
19
+ end
20
+ end
@@ -1,16 +1,53 @@
1
1
  module Hieraviz
2
- class Store
2
+ module Store
3
+ extend self
3
4
 
4
- def initialize
5
- @data = {}
5
+ def data
6
+ @_data ||= Hash.new
6
7
  end
7
8
 
8
9
  def set(key, value)
9
- @data[key.to_sym] = value
10
+ File.open(tmpfile(key), 'w') do |f|
11
+ f.print Marshal::dump(value)
12
+ end
13
+ data[key] = value
10
14
  end
11
15
 
12
- def get(key)
13
- @data[key.to_sym]
16
+ def get(key, expiration=false)
17
+ f = tmpfile(key)
18
+ if File.exist?(f) && expiration && expired?(f, expiration)
19
+ File.unlink(f)
20
+ end
21
+ if File.exist?(f)
22
+ data[key] ||= Marshal::load(File.read(f).chomp)
23
+ end
24
+ end
25
+
26
+ def dump
27
+ data
28
+ end
29
+
30
+ def tmpfile(name)
31
+ File.join tmpdir, name.gsub(/[^a-z0-9]/,'')
32
+ end
33
+
34
+ def tmpdir
35
+ @_tmpdir ||= init_tmpdir
36
+ end
37
+
38
+ def init_tmpdir
39
+ config = Hieraviz::Config.load
40
+ tmp = config['tmpdir'] || '/tmp'
41
+ begin
42
+ FileUtils.mkdir_p(tmp) unless Dir.exist?(tmp)
43
+ rescue Exception => e
44
+ tmp = '/tmp'
45
+ end
46
+ tmp
47
+ end
48
+
49
+ def expired?(file, duration)
50
+ Time.now - duration > File.mtime(file)
14
51
  end
15
52
 
16
53
  end
data/lib/hieraviz.rb CHANGED
@@ -1,5 +1,7 @@
1
1
  require "hieraviz/version"
2
+ require "hieraviz/config"
2
3
  require "hieraviz/store"
4
+ require "hieraviz/auth_gitlab"
3
5
 
4
6
  module Hieraviz
5
7
  # Your code goes here...
@@ -1,11 +1,14 @@
1
1
  require 'spec_helper'
2
+ require 'sinatra_helper'
2
3
 
3
4
  describe HieravizApp::ApiV1 do
4
5
 
5
- context "when GET /v1/nodes" do
6
- it "replies 200" do
7
- get '/nodes'
8
- expect(last_response).to be_ok
6
+ context "without any auth" do
7
+ context "when GET /v1/nodes" do
8
+ it "replies error" do
9
+ get '/nodes'
10
+ expect(last_response).not_to be_ok
11
+ end
9
12
  end
10
13
  end
11
14
 
data/spec/app/web_spec.rb CHANGED
@@ -1,4 +1,5 @@
1
1
  require 'spec_helper'
2
+ require 'sinatra_helper'
2
3
 
3
4
  describe HieravizApp::Web do
4
5
 
@@ -2,11 +2,21 @@
2
2
  basepath: "spec/files/puppet"
3
3
  classpath: "farm_modules/%s/manifests/init.pp"
4
4
  hierafile: "hiera.yml"
5
+ session_seed: "toto"
6
+ tmpdir: "spec/files/tmp"
5
7
  usedb: false
6
8
  puppetdb:
7
9
  usessl: false
8
10
  host: puppetdb.example.com
9
11
  port: 8080
12
+ auth_method: http
10
13
  http_auth:
11
14
  username: 'toto'
12
15
  password: 'toto'
16
+ gitlab_auth:
17
+ host: https://gitlab.example.com
18
+ application_id: xxxid
19
+ secret: xxxsecret
20
+ resource_required: '/api/v3/projects/group%2Fpuppet'
21
+ required_response_key: 'id'
22
+ required_response_value: '42'
@@ -0,0 +1,26 @@
1
+ require 'spec_helper'
2
+
3
+ describe Hieraviz::AuthGitlab do
4
+
5
+ describe '.new' do
6
+ end
7
+
8
+ describe '.access_token' do
9
+ end
10
+
11
+ describe '.get_response' do
12
+ end
13
+
14
+ describe '.redirect_uri' do
15
+ end
16
+
17
+ describe '.login_url' do
18
+ end
19
+
20
+ describe '.authorized?' do
21
+ end
22
+
23
+ describe '.user_info' do
24
+ end
25
+
26
+ end
@@ -0,0 +1,20 @@
1
+ require 'spec_helper'
2
+
3
+ describe Hieraviz::Config do
4
+
5
+ describe '.load' do
6
+ let(:expected) { "spec/files/puppet" }
7
+ it { expect(Hieraviz::Config.load['basepath']).to eq expected }
8
+ end
9
+
10
+ describe '.configfile' do
11
+ let(:expected) { File.expand_path('../../files/config.yml', __FILE__) }
12
+ it { expect(Hieraviz::Config.configfile).to eq expected }
13
+ end
14
+
15
+ describe '.root' do
16
+ let(:expected) { File.expand_path('../../../', __FILE__) }
17
+ it { expect(Hieraviz::Config.root).to eq expected }
18
+ end
19
+
20
+ end