b5ac19586f17bba42621b9a349c359443ffbc9e6
[arvados.git] / services / api / app / controllers / arvados / v1 / users_controller.rb
1 class Arvados::V1::UsersController < ApplicationController
2   accept_attribute_as_json :prefs, Hash
3
4   skip_before_filter :find_object_by_uuid, only:
5     [:activate, :current, :system, :setup]
6   skip_before_filter :render_404_if_no_object, only:
7     [:activate, :current, :system, :setup]
8   before_filter :admin_required, only: [:setup, :unsetup]
9
10   def current
11     if current_user
12       @object = current_user
13       show
14     else
15       send_error("Not logged in", status: 401)
16     end
17   end
18
19   def system
20     @object = system_user
21     show
22   end
23
24   def activate
25     if current_user.andand.is_admin && params[:uuid]
26       @object = User.find params[:uuid]
27     else
28       @object = current_user
29     end
30     if not @object.is_active
31       if not (current_user.is_admin or @object.is_invited)
32         logger.warn "User #{@object.uuid} called users.activate " +
33           "but is not invited"
34         raise ArgumentError.new "Cannot activate without being invited."
35       end
36       act_as_system_user do
37         required_uuids = Link.where("owner_uuid = ? and link_class = ? and name = ? and tail_uuid = ? and head_uuid like ?",
38                                     system_user_uuid,
39                                     'signature',
40                                     'require',
41                                     system_user_uuid,
42                                     Collection.uuid_like_pattern).
43           collect(&:head_uuid)
44         signed_uuids = Link.where(owner_uuid: system_user_uuid,
45                                   link_class: 'signature',
46                                   name: 'click',
47                                   tail_uuid: @object.uuid,
48                                   head_uuid: required_uuids).
49           collect(&:head_uuid)
50         todo_uuids = required_uuids - signed_uuids
51         if todo_uuids.empty?
52           @object.update_attributes is_active: true
53           logger.info "User #{@object.uuid} activated"
54         else
55           logger.warn "User #{@object.uuid} called users.activate " +
56             "before signing agreements #{todo_uuids.inspect}"
57           raise ArvadosModel::PermissionDeniedError.new \
58           "Cannot activate without user agreements #{todo_uuids.inspect}."
59         end
60       end
61     end
62     show
63   end
64
65   # create user object and all the needed links
66   def setup
67     @object = nil
68     if params[:uuid]
69       @object = User.find_by_uuid params[:uuid]
70       if !@object
71         return render_404_if_no_object
72       end
73       object_found = true
74     else
75       if !params[:user]
76         raise ArgumentError.new "Required uuid or user"
77       else
78         if params[:user]['uuid']
79           @object = User.find_by_uuid params[:user]['uuid']
80           if @object
81             object_found = true
82           end
83         end
84
85         if !@object
86           if !params[:user]['email']
87             raise ArgumentError.new "Require user email"
88           end
89
90           if !params[:openid_prefix]
91             raise ArgumentError.new "Required openid_prefix parameter is missing."
92           end
93
94           @object = model_class.create! resource_attrs
95         end
96       end
97     end
98
99     # It's not always possible to know the user's username when submitting
100     # this request.  If it included a plain repository name, expand that to a
101     # user-owned name now.
102     if params[:repo_name].nil?
103       full_repo_name = nil
104     else
105       full_repo_name = "#{@object.username}/#{params[:repo_name]}"
106     end
107     if object_found
108       if params[:repo_name].andand.include?("/")
109         repo_name = params[:repo_name]
110       elsif @object.username.nil?
111         raise ArgumentError.
112           new("can't setup a user without a username with a repository")
113       else
114         repo_name = full_repo_name
115       end
116       @response = @object.setup_repo_vm_links repo_name,
117                     params[:vm_uuid], params[:openid_prefix]
118     else
119       @response = User.setup @object, params[:openid_prefix],
120                     full_repo_name, params[:vm_uuid]
121     end
122
123     # setup succeeded. send email to user
124     if params[:send_notification_email] == true || params[:send_notification_email] == 'true'
125       UserNotifier.account_is_setup(@object).deliver
126     end
127
128     send_json kind: "arvados#HashList", items: @response.as_api_response(nil)
129   end
130
131   # delete user agreements, vm, repository, login links; set state to inactive
132   def unsetup
133     reload_object_before_update
134     @object.unsetup
135     show
136   end
137
138   protected
139
140   def self._setup_requires_parameters
141     {
142       user: {
143         type: 'object', required: false
144       },
145       openid_prefix: {
146         type: 'string', required: false
147       },
148       repo_name: {
149         type: 'string', required: false
150       },
151       vm_uuid: {
152         type: 'string', required: false
153       },
154       send_notification_email: {
155         type: 'boolean', required: false, default: false
156       },
157     }
158   end
159
160   def apply_filters(model_class=nil)
161     return super if @read_users.any? &:is_admin
162     if params[:uuid] != current_user.andand.uuid
163       # Non-admin index/show returns very basic information about readable users.
164       safe_attrs = ["uuid", "is_active", "email", "first_name", "last_name"]
165       if @select
166         @select = @select & safe_attrs
167       else
168         @select = safe_attrs
169       end
170       @filters += [['is_active', '=', true]]
171     end
172     super
173   end
174 end