88 lines
2.6 KiB
Ruby
88 lines
2.6 KiB
Ruby
module Carto
|
|
class DbPermissionService
|
|
TYPE_USER = 'user'.freeze
|
|
TYPE_ORG = 'org'.freeze
|
|
TYPE_GROUP = 'group'.freeze
|
|
|
|
READ_PERMISSIONS = ['select'].freeze
|
|
WRITE_PERMISSIONS = ['insert', 'update', 'delete'].freeze
|
|
PERMISSIONS = {
|
|
r: READ_PERMISSIONS,
|
|
w: WRITE_PERMISSIONS,
|
|
rw: READ_PERMISSIONS + WRITE_PERMISSIONS
|
|
}.freeze
|
|
|
|
def self.shared_entities_revokes(old_acl, new_acl, table)
|
|
diff = revokes_by_user_diff(old_acl, new_acl, table.owner.id)
|
|
unless diff.blank?
|
|
shared_apikey_revokes(table, diff)
|
|
shared_oauth_app_user_revokes(table, diff)
|
|
end
|
|
end
|
|
|
|
def self.revokes_by_user_diff(old_acl, new_acl, table_owner_id)
|
|
old_acl = more_permisive_by_user(old_acl)
|
|
new_acl = more_permisive_by_user(new_acl)
|
|
|
|
revokes_by_user(old_acl, new_acl, table_owner_id)
|
|
end
|
|
|
|
private_class_method def self.shared_apikey_revokes(table, revokes)
|
|
Carto::ApiKey.where(user_id: revokes.keys, type: ['regular', 'oauth']).find_each do |apikey|
|
|
apikey.revoke_permissions(table, PERMISSIONS[revokes[apikey.user_id].to_sym])
|
|
end
|
|
end
|
|
|
|
private_class_method def self.shared_oauth_app_user_revokes(table, revokes)
|
|
Carto::OauthAppUser.where(user_id: revokes.keys).find_each do |oau|
|
|
oau.revoke_permissions(table, PERMISSIONS[revokes[oau.user_id].to_sym])
|
|
end
|
|
end
|
|
|
|
private_class_method def self.more_permisive_by_user(acl)
|
|
acl_hash = {}
|
|
acl.each do |p|
|
|
user_ids(p[:type], p[:id]).each { |uid| acl_hash[uid] = keep_more_permisive(acl_hash[uid], p[:access]) }
|
|
end
|
|
acl_hash
|
|
end
|
|
|
|
private_class_method def self.user_ids(type, id)
|
|
if type == TYPE_USER
|
|
[id]
|
|
elsif type == TYPE_ORG
|
|
Carto::Organization.find(id).users.map(&:id)
|
|
else
|
|
Carto::Group.find(id).users.map(&:id)
|
|
end
|
|
rescue ActiveRecord::RecordNotFound => e
|
|
CartoDB::Logger.error(exception: e, entity_type: type, entity_id: id)
|
|
[]
|
|
end
|
|
|
|
private_class_method def self.keep_more_permisive(current, new_one)
|
|
current == 'rw' || new_one == 'rw' ? 'rw' : 'r'
|
|
end
|
|
|
|
private_class_method def self.revokes_by_user(old_acl, new_acl, table_owner_id)
|
|
diff = {}
|
|
old_acl.each do |id, access|
|
|
next if id == table_owner_id
|
|
|
|
if access == 'rw'
|
|
if new_acl[id].nil?
|
|
revoke = 'rw'
|
|
elsif new_acl[id] == 'r'
|
|
revoke = 'w'
|
|
end
|
|
elsif access == 'r' && new_acl[id].nil?
|
|
revoke = 'r'
|
|
end
|
|
|
|
diff[id] = revoke if revoke.present?
|
|
end
|
|
diff
|
|
end
|
|
end
|
|
end
|