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,67 @@
|
|
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
|
+
# Module for Cyclid Job related classes
|
21
|
+
module Job
|
22
|
+
# Non-AR model for Stages. Using a wrapper allows us to create an ad-hoc
|
23
|
+
# stage (I.e. one that is not stored in the database) or load a stage
|
24
|
+
# from the database and merge in over-rides without risking modifying
|
25
|
+
# the database object.
|
26
|
+
class StageView
|
27
|
+
attr_reader :name, :version, :steps
|
28
|
+
attr_accessor :on_success, :on_failure
|
29
|
+
|
30
|
+
def initialize(arg)
|
31
|
+
if arg.is_a? Cyclid::API::Stage
|
32
|
+
@name = arg.name
|
33
|
+
@version = arg.version
|
34
|
+
@steps = arg.steps.map(&:serializable_hash)
|
35
|
+
elsif arg.is_a? Hash
|
36
|
+
arg.symbolize_keys!
|
37
|
+
|
38
|
+
raise ArgumentError, 'name is required' unless arg.key? :name
|
39
|
+
|
40
|
+
@name = arg[:name]
|
41
|
+
@version = arg.fetch(:version, '1.0.0')
|
42
|
+
|
43
|
+
# Create & serialize Actions for each step
|
44
|
+
sequence = 1
|
45
|
+
@steps = arg[:steps].map do |step|
|
46
|
+
Cyclid.logger.debug "ad-hoc step=#{step}"
|
47
|
+
|
48
|
+
action_name = step['action']
|
49
|
+
plugin = Cyclid.plugins.find(action_name, Cyclid::API::Plugins::Action)
|
50
|
+
|
51
|
+
step_action = plugin.new(step)
|
52
|
+
raise ArgumentError if step_action.nil?
|
53
|
+
|
54
|
+
# Serialize the object into the Step and store it in the database.
|
55
|
+
action = Oj.dump(step_action)
|
56
|
+
|
57
|
+
step_definition = { sequence: sequence, action: action }
|
58
|
+
sequence += 1
|
59
|
+
|
60
|
+
step_definition
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,104 @@
|
|
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
|
+
# Simple in-memory FIFO; inspired by StringIO but reads & writes maintain
|
21
|
+
# their own position. It's unlike a file enough to not be derived from IO.
|
22
|
+
class StringFIFO
|
23
|
+
def initialize
|
24
|
+
@buffer = String.new
|
25
|
+
@write_pos = 0
|
26
|
+
@read_pos = 0
|
27
|
+
end
|
28
|
+
|
29
|
+
# Append data to the buffer & update the write position
|
30
|
+
def write(data)
|
31
|
+
@buffer += data
|
32
|
+
@write_pos += data.length
|
33
|
+
end
|
34
|
+
|
35
|
+
# Read data from the buffer. If length is given, read at most length
|
36
|
+
# characters from the buffer or whatever is available, whichever is
|
37
|
+
# smaller.
|
38
|
+
#
|
39
|
+
# Completely non-blocking; if no data is available, returns an empty
|
40
|
+
# string.
|
41
|
+
def read(length = nil)
|
42
|
+
len = if length
|
43
|
+
[length, @write_pos].min
|
44
|
+
else
|
45
|
+
@write_pos
|
46
|
+
end
|
47
|
+
start = @read_pos
|
48
|
+
@read_pos += len
|
49
|
+
|
50
|
+
@buffer[start, len]
|
51
|
+
end
|
52
|
+
|
53
|
+
# Return the entire contents of the buffer
|
54
|
+
def string
|
55
|
+
@buffer
|
56
|
+
end
|
57
|
+
|
58
|
+
alias to_s string
|
59
|
+
|
60
|
+
# Reset the buffer, read & write positions
|
61
|
+
def clear
|
62
|
+
@buffer = ''
|
63
|
+
@write_pos = 0
|
64
|
+
@read_pos = 0
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
# Intelligent buffer which can be passed to plugins which need to collate
|
69
|
+
# output data from different commands during a job
|
70
|
+
class LogBuffer
|
71
|
+
def initialize(job_record = nil, websocket = nil)
|
72
|
+
@job_record = job_record
|
73
|
+
@websocket = websocket
|
74
|
+
@buffer = StringFIFO.new
|
75
|
+
end
|
76
|
+
|
77
|
+
# Append data to the log and send it on to any configured consumers
|
78
|
+
def write(data)
|
79
|
+
# Append the new data to log
|
80
|
+
@buffer.write data
|
81
|
+
|
82
|
+
# Update the Job Record, if there is one
|
83
|
+
if @job_record
|
84
|
+
# XXX: This will destroy the database. Find a better method.
|
85
|
+
@job_record.log = @buffer.string
|
86
|
+
@job_record.save!
|
87
|
+
end
|
88
|
+
|
89
|
+
# Write to web socket
|
90
|
+
@websocket.write data if @websocket
|
91
|
+
end
|
92
|
+
|
93
|
+
# Non-destructively read any new data from the buffer
|
94
|
+
def read(length = nil)
|
95
|
+
@buffer.read(length)
|
96
|
+
end
|
97
|
+
|
98
|
+
# Return a complete copy of the data from the buffer
|
99
|
+
def log
|
100
|
+
@buffer.string
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
@@ -0,0 +1,25 @@
|
|
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
|
+
# Model for Users
|
21
|
+
class JobRecord < ActiveRecord::Base
|
22
|
+
Cyclid.logger.debug('In the JobRecod model')
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,64 @@
|
|
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
|
+
# Model for Organizations
|
21
|
+
class Organization < ActiveRecord::Base
|
22
|
+
Cyclid.logger.debug('In the Organization model')
|
23
|
+
|
24
|
+
class << self
|
25
|
+
# Return the collection of Organizations as an array of Hashes (instead
|
26
|
+
# of Organization objects)
|
27
|
+
def all_as_hash
|
28
|
+
all.to_a.map(&:serializable_hash)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
validates :name, presence: true
|
33
|
+
validates :owner_email, presence: true
|
34
|
+
|
35
|
+
validates :rsa_private_key, presence: true
|
36
|
+
validates :rsa_public_key, presence: true
|
37
|
+
validates :salt, presence: true
|
38
|
+
|
39
|
+
validates_uniqueness_of :name
|
40
|
+
|
41
|
+
has_and_belongs_to_many :users,
|
42
|
+
after_add: :add_user_org_perm,
|
43
|
+
after_remove: :remove_user_org_perm
|
44
|
+
|
45
|
+
has_many :userpermissions
|
46
|
+
has_many :stages
|
47
|
+
has_many :job_records
|
48
|
+
has_many :plugin_configs
|
49
|
+
|
50
|
+
# Ensure that a set of Userpermissions exist when a User is added to
|
51
|
+
# this Organization
|
52
|
+
def add_user_org_perm(user)
|
53
|
+
Cyclid.logger.debug "Creating org. perm. for #{user.username}"
|
54
|
+
user.userpermissions << Userpermission.new(organization: self)
|
55
|
+
end
|
56
|
+
|
57
|
+
# Remove Userpermissions when a User is removed from this Organization
|
58
|
+
def remove_user_org_perm(user)
|
59
|
+
Cyclid.logger.debug "Destroying org. perm. for #{user.username}"
|
60
|
+
user.userpermissions.delete(Userpermission.find_by(organization: self))
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,25 @@
|
|
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
|
+
# Model for PluginConfigs
|
21
|
+
class PluginConfig < ActiveRecord::Base
|
22
|
+
belongs_to :organization
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,42 @@
|
|
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
|
+
# Model for Stages
|
21
|
+
class Stage < ActiveRecord::Base
|
22
|
+
Cyclid.logger.debug('In the Stage model')
|
23
|
+
|
24
|
+
class << self
|
25
|
+
# Return the collection of Stages as an array of Hashes (instead
|
26
|
+
# of Stage objects)
|
27
|
+
def all_as_hash
|
28
|
+
all.to_a.map(&:serializable_hash)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
validates :name, presence: true
|
33
|
+
validates :version, presence: true
|
34
|
+
|
35
|
+
validates_uniqueness_of :name, scope: :version
|
36
|
+
validates_format_of :version, with: /\A\d+.\d+.\d+.?\d*\z/
|
37
|
+
|
38
|
+
belongs_to :organization
|
39
|
+
has_many :steps
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,29 @@
|
|
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
|
+
# Model for Steps
|
21
|
+
class Step < ActiveRecord::Base
|
22
|
+
Cyclid.logger.debug('In the Step model')
|
23
|
+
|
24
|
+
validates :sequence, presence: true
|
25
|
+
|
26
|
+
belongs_to :stage
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,60 @@
|
|
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 'bcrypt'
|
17
|
+
|
18
|
+
# Top level module for the core Cyclid code.
|
19
|
+
module Cyclid
|
20
|
+
# Module for the Cyclid API
|
21
|
+
module API
|
22
|
+
# Model for Users
|
23
|
+
class User < ActiveRecord::Base
|
24
|
+
Cyclid.logger.debug('In the User model')
|
25
|
+
|
26
|
+
class << self
|
27
|
+
# Return the collection of Users as an array of Hashes (instead
|
28
|
+
# of User objects)
|
29
|
+
def all_as_hash
|
30
|
+
all.to_a.map(&:serializable_hash)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
validates :username, presence: true
|
35
|
+
validates :email, presence: true
|
36
|
+
|
37
|
+
validates_uniqueness_of :username
|
38
|
+
|
39
|
+
has_and_belongs_to_many :organizations
|
40
|
+
has_many :userpermissions
|
41
|
+
has_many :job_records
|
42
|
+
|
43
|
+
# Allow an unencryped password to be passed in via. new_password and
|
44
|
+
# ensure it is encrypted into password when the record is saved
|
45
|
+
attr_accessor :new_password
|
46
|
+
|
47
|
+
before_save :hash_new_password, if: :password_changed?
|
48
|
+
|
49
|
+
# Check if the new_password attribute has changed
|
50
|
+
def password_changed?
|
51
|
+
!@new_password.blank?
|
52
|
+
end
|
53
|
+
|
54
|
+
# Generate a BCrypt2 password from the plaintext
|
55
|
+
def hash_new_password
|
56
|
+
self.password = BCrypt::Password.create(@new_password)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,28 @@
|
|
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
|
+
# Model for UserPermissions
|
21
|
+
class Userpermission < ActiveRecord::Base
|
22
|
+
Cyclid.logger.debug('In the Userpermission model')
|
23
|
+
|
24
|
+
belongs_to :user
|
25
|
+
belongs_to :organization
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|