Merge branch 'master' of git.clinicalfuture.com:orvos-server
[arvados.git] / app / models / orvos_model.rb
1 class OrvosModel < ActiveRecord::Base
2   self.abstract_class = true
3
4   include CurrentApiClient      # current_user, current_api_client, etc.
5
6   attr_protected :created_at
7   attr_protected :modified_by_user
8   attr_protected :modified_by_client
9   attr_protected :modified_at
10   before_create :ensure_permission_to_create
11   before_update :ensure_permission_to_update
12   before_create :update_modified_by_fields
13   before_update :maybe_update_modified_by_fields
14
15   def self.kind_class(kind)
16     kind.match(/^orvos\#(.+?)(_list|List)?$/)[1].pluralize.classify.constantize rescue nil
17   end
18
19   def eager_load_associations
20     self.class.columns.each do |col|
21       re = col.name.match /^(.*)_kind$/
22       if (re and
23           self.respond_to? re[1].to_sym and
24           (auuid = self.send((re[1] + '_uuid').to_sym)) and
25           (aclass = self.class.kind_class(self.send(col.name.to_sym))) and
26           (aobject = aclass.where('uuid=?', auuid).first))
27         self.instance_variable_set('@'+re[1], aobject)
28       end
29     end
30   end
31
32   protected
33
34   def ensure_permission_to_create
35     raise "Permission denied" unless permission_to_create
36   end
37
38   def permission_to_create
39     current_user
40   end
41
42   def ensure_permission_to_update
43     raise "Permission denied" unless permission_to_update
44   end
45
46   def permission_to_update
47     if !current_user
48       logger.warn "Anonymous user tried to update #{self.class.to_s} #{self.uuid_was}"
49       return false
50     end
51     if self.uuid_changed?
52       logger.warn "User #{current_user.uuid} tried to change uuid of #{self.class.to_s} #{self.uuid_was} to #{self.uuid}"
53       return false
54     end
55     return true if current_user.is_admin
56     if self.owner_changed? and
57         self.owner_was != current_user.uuid and
58         0 == Link.where(link_class: 'permission',
59                         name: 'can_pillage',
60                         tail_uuid: self.owner,
61                         head_uuid: current_user.uuid).count
62       logger.warn "User #{current_user.uuid} tried to change owner of #{self.class.to_s} #{self.uuid} to #{self.owner}"
63       return false
64     end
65     if self.owner == current_user.uuid or
66       current_user.is_admin or
67       current_user.uuid == self.uuid or
68       Link.where(link_class: 'permission',
69                  name: 'can_write',
70                  tail_uuid: self.owner,
71                  head_uuid: current_user.uuid).count > 0
72       return true
73     else
74       logger.warn "User #{current_user.uuid} tried to modify #{self.class.to_s} #{self.uuid} but does not can_write permission and owner is #{self.owner}"
75       return false
76     end
77   end
78
79   def maybe_update_modified_by_fields
80     update_modified_by_fields if self.changed?
81   end
82
83   def update_modified_by_fields
84     self.created_at ||= Time.now
85     self.owner ||= current_user.uuid
86     self.modified_at = Time.now
87     self.modified_by_user = current_user.uuid
88     self.modified_by_client = current_api_client ? current_api_client.uuid : nil
89   end
90 end