cyclid 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/LICENSE +174 -0
- data/README.md +54 -0
- data/app/cyclid.rb +61 -0
- data/app/cyclid/config.rb +38 -0
- data/app/cyclid/controllers.rb +123 -0
- data/app/cyclid/controllers/auth.rb +34 -0
- data/app/cyclid/controllers/auth/token.rb +78 -0
- data/app/cyclid/controllers/health.rb +96 -0
- data/app/cyclid/controllers/organizations.rb +104 -0
- data/app/cyclid/controllers/organizations/collection.rb +134 -0
- data/app/cyclid/controllers/organizations/config.rb +128 -0
- data/app/cyclid/controllers/organizations/document.rb +135 -0
- data/app/cyclid/controllers/organizations/job.rb +266 -0
- data/app/cyclid/controllers/organizations/members.rb +145 -0
- data/app/cyclid/controllers/organizations/stages.rb +251 -0
- data/app/cyclid/controllers/users.rb +47 -0
- data/app/cyclid/controllers/users/collection.rb +131 -0
- data/app/cyclid/controllers/users/document.rb +133 -0
- data/app/cyclid/health_helpers.rb +40 -0
- data/app/cyclid/job.rb +3 -0
- data/app/cyclid/job/helpers.rb +67 -0
- data/app/cyclid/job/job.rb +164 -0
- data/app/cyclid/job/runner.rb +275 -0
- data/app/cyclid/job/stage.rb +67 -0
- data/app/cyclid/log_buffer.rb +104 -0
- data/app/cyclid/models.rb +3 -0
- data/app/cyclid/models/job_record.rb +25 -0
- data/app/cyclid/models/organization.rb +64 -0
- data/app/cyclid/models/plugin_config.rb +25 -0
- data/app/cyclid/models/stage.rb +42 -0
- data/app/cyclid/models/step.rb +29 -0
- data/app/cyclid/models/user.rb +60 -0
- data/app/cyclid/models/user_permissions.rb +28 -0
- data/app/cyclid/monkey_patches.rb +37 -0
- data/app/cyclid/plugin_registry.rb +75 -0
- data/app/cyclid/plugins.rb +125 -0
- data/app/cyclid/plugins/action.rb +48 -0
- data/app/cyclid/plugins/action/command.rb +89 -0
- data/app/cyclid/plugins/action/email.rb +207 -0
- data/app/cyclid/plugins/action/email/html.erb +58 -0
- data/app/cyclid/plugins/action/email/text.erb +13 -0
- data/app/cyclid/plugins/action/script.rb +90 -0
- data/app/cyclid/plugins/action/slack.rb +129 -0
- data/app/cyclid/plugins/action/slack/note.erb +5 -0
- data/app/cyclid/plugins/api.rb +195 -0
- data/app/cyclid/plugins/api/github.rb +111 -0
- data/app/cyclid/plugins/api/github/callback.rb +66 -0
- data/app/cyclid/plugins/api/github/methods.rb +201 -0
- data/app/cyclid/plugins/api/github/status.rb +67 -0
- data/app/cyclid/plugins/builder.rb +80 -0
- data/app/cyclid/plugins/builder/mist.rb +107 -0
- data/app/cyclid/plugins/dispatcher.rb +89 -0
- data/app/cyclid/plugins/dispatcher/local.rb +167 -0
- data/app/cyclid/plugins/provisioner.rb +40 -0
- data/app/cyclid/plugins/provisioner/debian.rb +90 -0
- data/app/cyclid/plugins/provisioner/ubuntu.rb +98 -0
- data/app/cyclid/plugins/source.rb +39 -0
- data/app/cyclid/plugins/source/git.rb +64 -0
- data/app/cyclid/plugins/transport.rb +63 -0
- data/app/cyclid/plugins/transport/ssh.rb +155 -0
- data/app/cyclid/sinatra/api_helpers.rb +66 -0
- data/app/cyclid/sinatra/auth_helpers.rb +127 -0
- data/app/cyclid/sinatra/warden/strategies/api_token.rb +62 -0
- data/app/cyclid/sinatra/warden/strategies/basic.rb +58 -0
- data/app/cyclid/sinatra/warden/strategies/hmac.rb +76 -0
- data/app/db.rb +51 -0
- data/bin/cyclid-db-init +107 -0
- data/db/schema.rb +92 -0
- data/lib/cyclid/app.rb +4 -0
- metadata +407 -0
@@ -0,0 +1,127 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
# Copyright 2016 Liqwyd Ltd.
|
3
|
+
#
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
5
|
+
# you may not use this file except in compliance with the License.
|
6
|
+
# You may obtain a copy of the License at
|
7
|
+
#
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
9
|
+
#
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
13
|
+
# See the License for the specific language governing permissions and
|
14
|
+
# limitations under the License.
|
15
|
+
|
16
|
+
# Top level module for the core Cyclid code.
|
17
|
+
module Cyclid
|
18
|
+
# Module for the Cyclid API
|
19
|
+
module API
|
20
|
+
# Some constants to identify types of API operation
|
21
|
+
module Operations
|
22
|
+
# Read operations
|
23
|
+
READ = 1
|
24
|
+
# Write (Create, Update, Delete) operations
|
25
|
+
WRITE = 2
|
26
|
+
# Administrator operations
|
27
|
+
ADMIN = 3
|
28
|
+
end
|
29
|
+
|
30
|
+
# Sinatra Warden AuthN/AuthZ helpers
|
31
|
+
module AuthHelpers
|
32
|
+
# Return an HTTP error with a RESTful JSON response
|
33
|
+
# XXX Should probably be in ApiHelpers?
|
34
|
+
def halt_with_json_response(error, id, description)
|
35
|
+
halt error, json_response(id, description)
|
36
|
+
end
|
37
|
+
|
38
|
+
# Call the Warden authenticate! method
|
39
|
+
def authenticate!
|
40
|
+
env['warden'].authenticate!
|
41
|
+
end
|
42
|
+
|
43
|
+
# Authenticate the user, then ensure that the user is authorized for
|
44
|
+
# the given organization and operation
|
45
|
+
def authorized_for!(org_name, operation)
|
46
|
+
authenticate!
|
47
|
+
|
48
|
+
user = current_user
|
49
|
+
|
50
|
+
# Promote the organization to 'admins' if the user is a SuperAdmin
|
51
|
+
org_name = 'admins' if super_admin?(user)
|
52
|
+
|
53
|
+
begin
|
54
|
+
organization = user.organizations.find_by(name: org_name)
|
55
|
+
halt_with_json_response(401, Errors::HTTPErrors::AUTH_FAILURE, 'unauthorized') \
|
56
|
+
if organization.nil?
|
57
|
+
Cyclid.logger.debug "authorized_for! organization: #{organization.name}"
|
58
|
+
|
59
|
+
# Check what Permissions are applied to the user for this Org & match
|
60
|
+
# against operation
|
61
|
+
permissions = user.userpermissions.find_by(organization: organization)
|
62
|
+
Cyclid.logger.debug "authorized_for! #{permissions.inspect}"
|
63
|
+
|
64
|
+
# Admins have full authority, regardless of the operation
|
65
|
+
return true if permissions.admin
|
66
|
+
return true if operation == Operations::WRITE && permissions.write
|
67
|
+
return true if operation == Operations::READ && (permissions.write || permissions.read)
|
68
|
+
|
69
|
+
Cyclid.logger.info "user #{user.username} is not authorized for operation #{operation}"
|
70
|
+
|
71
|
+
halt_with_json_response(401, Errors::HTTPErrors::AUTH_FAILURE, 'unauthorized')
|
72
|
+
rescue StandardError => ex # XXX: Use a more specific rescue
|
73
|
+
Cyclid.logger.info "authorization failed: #{ex}"
|
74
|
+
halt_with_json_response(401, Errors::HTTPErrors::AUTH_FAILURE, 'unauthorized')
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
# Authenticate the user, then ensure that the user is an admin and
|
79
|
+
# authorized for the resource for the given username & operation
|
80
|
+
def authorized_admin!(operation)
|
81
|
+
authorized_for!('admins', operation)
|
82
|
+
end
|
83
|
+
|
84
|
+
# Authenticate the user, then ensure that the user is authorized for the
|
85
|
+
# resource for the given username & operation
|
86
|
+
def authorized_as!(username, operation)
|
87
|
+
authenticate!
|
88
|
+
|
89
|
+
user = current_user
|
90
|
+
|
91
|
+
# Users are always authorized for any operation on their own data
|
92
|
+
return true if user.username == username
|
93
|
+
|
94
|
+
# Super Admins may be authorized, depending on the operation
|
95
|
+
if super_admin?(user)
|
96
|
+
begin
|
97
|
+
organization = user.organizations.find_by(name: 'admins')
|
98
|
+
permissions = user.userpermissions.find_by(organization: organization)
|
99
|
+
Cyclid.logger.debug permissions
|
100
|
+
|
101
|
+
# Admins have full authority, regardless of the operation
|
102
|
+
return true if permissions.admin
|
103
|
+
return true if operation == Operations::WRITE && permissions.write
|
104
|
+
return true if operation == Operations::READ && (permissions.write || permissions.read)
|
105
|
+
rescue StandardError => ex # XXX: Use a more specific rescue
|
106
|
+
Cyclid.logger.info "authorization failed: #{ex}"
|
107
|
+
halt_with_json_response(401, Errors::HTTPErrors::AUTH_FAILURE, 'unauthorized')
|
108
|
+
end
|
109
|
+
|
110
|
+
end
|
111
|
+
|
112
|
+
halt_with_json_response(401, Errors::HTTPErrors::AUTH_FAILURE, 'unauthorized')
|
113
|
+
end
|
114
|
+
|
115
|
+
# Check if the given user is a Super Admin; any user that belongs to the
|
116
|
+
# 'admins' organization is a super admin
|
117
|
+
def super_admin?(user)
|
118
|
+
user.organizations.exists?(name: 'admins')
|
119
|
+
end
|
120
|
+
|
121
|
+
# Current User object from the session
|
122
|
+
def current_user
|
123
|
+
env['warden'].user
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
# Copyright 2016 Liqwyd Ltd.
|
3
|
+
#
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
5
|
+
# you may not use this file except in compliance with the License.
|
6
|
+
# You may obtain a copy of the License at
|
7
|
+
#
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
9
|
+
#
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
13
|
+
# See the License for the specific language governing permissions and
|
14
|
+
# limitations under the License.
|
15
|
+
|
16
|
+
require 'warden'
|
17
|
+
require 'jwt'
|
18
|
+
|
19
|
+
# Top level module for the core Cyclid code.
|
20
|
+
module Cyclid
|
21
|
+
# Module for the Cyclid API
|
22
|
+
module API
|
23
|
+
# Warden Strategies
|
24
|
+
module Strategies
|
25
|
+
# API Token based strategy
|
26
|
+
module APIToken
|
27
|
+
# Authenticate via. an API token
|
28
|
+
Warden::Strategies.add(:api_token) do
|
29
|
+
def valid?
|
30
|
+
request.env['HTTP_AUTHORIZATION'].is_a? String and \
|
31
|
+
request.env['HTTP_AUTHORIZATION'] =~ /^Token .*$/
|
32
|
+
end
|
33
|
+
|
34
|
+
def authenticate!
|
35
|
+
begin
|
36
|
+
authorization = request.env['HTTP_AUTHORIZATION']
|
37
|
+
username, token = authorization.match(/^Token (.*):(.*)$/).captures
|
38
|
+
rescue
|
39
|
+
fail! 'invalid API token'
|
40
|
+
end
|
41
|
+
|
42
|
+
user = User.find_by(username: username)
|
43
|
+
fail! 'invalid user' if user.nil?
|
44
|
+
|
45
|
+
begin
|
46
|
+
# Decode the token
|
47
|
+
token_data = JWT.decode token, user.secret, true, algorithm: 'HS256'
|
48
|
+
claims = token_data.first
|
49
|
+
if claims['sub'] == user.username
|
50
|
+
success! user
|
51
|
+
else
|
52
|
+
fail! 'invalid user'
|
53
|
+
end
|
54
|
+
rescue
|
55
|
+
fail! 'invalid API token'
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
# Copyright 2016 Liqwyd Ltd.
|
3
|
+
#
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
5
|
+
# you may not use this file except in compliance with the License.
|
6
|
+
# You may obtain a copy of the License at
|
7
|
+
#
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
9
|
+
#
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
13
|
+
# See the License for the specific language governing permissions and
|
14
|
+
# limitations under the License.
|
15
|
+
|
16
|
+
require 'warden'
|
17
|
+
require 'bcrypt'
|
18
|
+
|
19
|
+
# Top level module for the core Cyclid code.
|
20
|
+
module Cyclid
|
21
|
+
# Module for the Cyclid API
|
22
|
+
module API
|
23
|
+
# Warden Strategies
|
24
|
+
module Strategies
|
25
|
+
# HTTTP Basic authentication based strategy
|
26
|
+
module Basic
|
27
|
+
# Authenticate via. HTTP Basic auth.
|
28
|
+
Warden::Strategies.add(:basic) do
|
29
|
+
def valid?
|
30
|
+
request.env['HTTP_AUTHORIZATION'].is_a? String and \
|
31
|
+
request.env['HTTP_AUTHORIZATION'] =~ /^Basic .*$/
|
32
|
+
end
|
33
|
+
|
34
|
+
def authenticate!
|
35
|
+
begin
|
36
|
+
authorization = request.env['HTTP_AUTHORIZATION']
|
37
|
+
digest = authorization.match(/^Basic (.*)$/).captures.first
|
38
|
+
|
39
|
+
user_pass = Base64.decode64(digest)
|
40
|
+
username, password = user_pass.split(':')
|
41
|
+
rescue
|
42
|
+
fail! 'invalid digest'
|
43
|
+
end
|
44
|
+
|
45
|
+
user = User.find_by(username: username)
|
46
|
+
if user.nil?
|
47
|
+
fail! 'invalid user'
|
48
|
+
elsif BCrypt::Password.new(user.password).is_password? password
|
49
|
+
success! user
|
50
|
+
else
|
51
|
+
fail! 'invalid user'
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
# Copyright 2016 Liqwyd Ltd.
|
3
|
+
#
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
5
|
+
# you may not use this file except in compliance with the License.
|
6
|
+
# You may obtain a copy of the License at
|
7
|
+
#
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
9
|
+
#
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
13
|
+
# See the License for the specific language governing permissions and
|
14
|
+
# limitations under the License.
|
15
|
+
|
16
|
+
require 'warden'
|
17
|
+
|
18
|
+
# Top level module for the core Cyclid code.
|
19
|
+
module Cyclid
|
20
|
+
# Module for the Cyclid API
|
21
|
+
module API
|
22
|
+
# Warden Strategies
|
23
|
+
module Strategies
|
24
|
+
# HMAC based strategy
|
25
|
+
module HMAC
|
26
|
+
# Authenticate via. HMAC
|
27
|
+
Warden::Strategies.add(:hmac) do
|
28
|
+
def valid?
|
29
|
+
request.env['HTTP_AUTHORIZATION'].is_a? String and \
|
30
|
+
request.env['HTTP_AUTHORIZATION'] =~ /^HMAC .*$/
|
31
|
+
end
|
32
|
+
|
33
|
+
def authenticate!
|
34
|
+
begin
|
35
|
+
authorization = request.env['HTTP_AUTHORIZATION']
|
36
|
+
username, hmac = authorization.match(/^HMAC (.*):(.*)$/).captures
|
37
|
+
|
38
|
+
# The nonce may be empty; that isn't an error and the signature
|
39
|
+
# will validate with a Nil nonce
|
40
|
+
nonce = request.env['HTTP_X_HMAC_NONCE']
|
41
|
+
rescue
|
42
|
+
fail! 'invalid HMAC'
|
43
|
+
end
|
44
|
+
|
45
|
+
user = User.find_by(username: username)
|
46
|
+
fail! 'invalid user' if user.nil?
|
47
|
+
|
48
|
+
begin
|
49
|
+
method = request.env['REQUEST_METHOD']
|
50
|
+
path = request.env['PATH_INFO']
|
51
|
+
date = request.env['HTTP_DATE']
|
52
|
+
|
53
|
+
Cyclid.logger.debug "user=#{user.username} method=#{method} path=#{path} \
|
54
|
+
date=#{date} HMAC=#{hmac} nonce=#{nonce}"
|
55
|
+
|
56
|
+
signer = Cyclid::HMAC::Signer.new
|
57
|
+
if signer.validate_signature(hmac,
|
58
|
+
secret: user.secret,
|
59
|
+
method: method,
|
60
|
+
path: path,
|
61
|
+
date: date,
|
62
|
+
nonce: nonce)
|
63
|
+
success! user
|
64
|
+
else
|
65
|
+
fail! 'invalid user'
|
66
|
+
end
|
67
|
+
rescue StandardError => ex
|
68
|
+
Cyclid.logger.debug "failure during HMAC authentication: #{ex}"
|
69
|
+
fail! 'invalid headers'
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
data/app/db.rb
ADDED
@@ -0,0 +1,51 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
# Copyright 2016 Liqwyd Ltd.
|
3
|
+
#
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
5
|
+
# you may not use this file except in compliance with the License.
|
6
|
+
# You may obtain a copy of the License at
|
7
|
+
#
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
9
|
+
#
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
13
|
+
# See the License for the specific language governing permissions and
|
14
|
+
# limitations under the License.
|
15
|
+
|
16
|
+
require 'active_record'
|
17
|
+
require 'logger'
|
18
|
+
|
19
|
+
begin
|
20
|
+
case ENV['RACK_ENV']
|
21
|
+
when 'development'
|
22
|
+
database = if defined? Cyclid
|
23
|
+
Cyclid.config.database
|
24
|
+
else
|
25
|
+
'sqlite3:development.db'
|
26
|
+
end
|
27
|
+
|
28
|
+
ActiveRecord::Base.establish_connection(
|
29
|
+
database
|
30
|
+
)
|
31
|
+
|
32
|
+
ActiveRecord::Base.logger = if defined? Cyclid
|
33
|
+
Cyclid.logger
|
34
|
+
else
|
35
|
+
Logger.new(STDERR)
|
36
|
+
end
|
37
|
+
when 'production'
|
38
|
+
ActiveRecord::Base.establish_connection(
|
39
|
+
Cyclid.config.database
|
40
|
+
)
|
41
|
+
|
42
|
+
ActiveRecord::Base.logger = Cyclid.logger
|
43
|
+
|
44
|
+
Cyclid.logger.level = Logger::INFO
|
45
|
+
when 'test'
|
46
|
+
Cyclid.logger.info 'In test mode; not creating database connection'
|
47
|
+
end
|
48
|
+
|
49
|
+
rescue StandardError => ex
|
50
|
+
abort "Failed to initialize ActiveRecord: #{ex}"
|
51
|
+
end
|
data/bin/cyclid-db-init
ADDED
@@ -0,0 +1,107 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
# Copyright 2016 Liqwyd Ltd.
|
4
|
+
#
|
5
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
6
|
+
# you may not use this file except in compliance with the License.
|
7
|
+
# You may obtain a copy of the License at
|
8
|
+
#
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
10
|
+
#
|
11
|
+
# Unless required by applicable law or agreed to in writing, software
|
12
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
13
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14
|
+
# See the License for the specific language governing permissions and
|
15
|
+
# limitations under the License.
|
16
|
+
|
17
|
+
$LOAD_PATH.push File.expand_path('../../app', __FILE__)
|
18
|
+
|
19
|
+
require 'require_all'
|
20
|
+
require 'logger'
|
21
|
+
require 'active_record'
|
22
|
+
require 'securerandom'
|
23
|
+
|
24
|
+
ENV['RACK_ENV'] = ENV['RACK_ENV'] || 'development'
|
25
|
+
|
26
|
+
require 'cyclid/config'
|
27
|
+
|
28
|
+
# Top level module for the core Cyclid code; just stub out to provide the
|
29
|
+
# bare minimum required to inject data via. the models.
|
30
|
+
module Cyclid
|
31
|
+
class << self
|
32
|
+
attr_accessor :logger, :config
|
33
|
+
|
34
|
+
begin
|
35
|
+
Cyclid.logger = Logger.new(STDERR)
|
36
|
+
|
37
|
+
config_path = ENV['CYCLID_CONFIG'] || File.join(%w(/ etc cyclid config))
|
38
|
+
Cyclid.config = API::Config.new(config_path)
|
39
|
+
rescue StandardError => ex
|
40
|
+
abort "Failed to initialize: #{ex}"
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
require 'db'
|
46
|
+
require 'cyclid/models'
|
47
|
+
|
48
|
+
require_relative '../db/schema.rb'
|
49
|
+
|
50
|
+
include Cyclid::API
|
51
|
+
|
52
|
+
ADMINS_ORG = 'admins'
|
53
|
+
RSA_KEY_LENGTH = 2048
|
54
|
+
|
55
|
+
def generate_password
|
56
|
+
(('a'..'z').to_a.concat \
|
57
|
+
('A'..'Z').to_a.concat \
|
58
|
+
('0'..'9').to_a.concat \
|
59
|
+
%w($ % ^ & * _)).sample(8).join
|
60
|
+
end
|
61
|
+
|
62
|
+
def create_admin_user
|
63
|
+
secret = SecureRandom.hex(32)
|
64
|
+
password = generate_password
|
65
|
+
user = User.new
|
66
|
+
user.username = 'admin'
|
67
|
+
user.email = 'admin@example.com'
|
68
|
+
user.secret = secret
|
69
|
+
user.new_password = password
|
70
|
+
user.save!
|
71
|
+
|
72
|
+
[secret, password]
|
73
|
+
end
|
74
|
+
|
75
|
+
def create_admin_organization
|
76
|
+
key = OpenSSL::PKey::RSA.new(RSA_KEY_LENGTH)
|
77
|
+
|
78
|
+
org = Organization.new
|
79
|
+
org.name = ADMINS_ORG
|
80
|
+
org.owner_email = 'admins@example.com'
|
81
|
+
org.rsa_private_key = key.to_der
|
82
|
+
org.rsa_public_key = key.public_key.to_der
|
83
|
+
org.salt = SecureRandom.hex(32)
|
84
|
+
org.users << User.find_by(username: 'admin')
|
85
|
+
end
|
86
|
+
|
87
|
+
def update_user_perms
|
88
|
+
# 'admin' user is a Super Admin
|
89
|
+
user = User.find_by(username: 'admin')
|
90
|
+
organization = user.organizations.find_by(name: ADMINS_ORG)
|
91
|
+
permissions = user.userpermissions.find_by(organization: organization)
|
92
|
+
Cyclid.logger.debug permissions
|
93
|
+
|
94
|
+
permissions.admin = true
|
95
|
+
permissions.write = true
|
96
|
+
permissions.read = true
|
97
|
+
permissions.save!
|
98
|
+
end
|
99
|
+
|
100
|
+
secret, password = create_admin_user
|
101
|
+
create_admin_organization
|
102
|
+
|
103
|
+
update_user_perms
|
104
|
+
|
105
|
+
STDERR.puts '*' * 80
|
106
|
+
STDERR.puts "Admin secret: #{secret}"
|
107
|
+
STDERR.puts "Admin password: #{password}"
|