cyclid 0.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 +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}"
|