4253: Users can manage their own repositories.
[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 for the client to know the user's
100     # username when submitting this request: the username might have
101     # been assigned automatically in create!() above. If client
102     # provided a plain repository name, prefix it with the username
103     # now that we know what it is.
104     if params[:repo_name].nil?
105       full_repo_name = nil
106     elsif @object.username.nil?
107       raise ArgumentError.
108         new("cannot setup a repository because user has no username")
109     elsif object_found and
110         params[:repo_name].start_with?("#{@object.username}/")
111       full_repo_name = params[:repo_name]
112     else
113       full_repo_name = "#{@object.username}/#{params[:repo_name]}"
114     end
115
116     if object_found
117       @response = @object.setup_repo_vm_links full_repo_name,
118                     params[:vm_uuid], params[:openid_prefix]
119     else
120       @response = User.setup @object, params[:openid_prefix],
121                     full_repo_name, params[:vm_uuid]
122     end
123
124     # setup succeeded. send email to user
125     if params[:send_notification_email] == true || params[:send_notification_email] == 'true'
126       UserNotifier.account_is_setup(@object).deliver
127     end
128
129     send_json kind: "arvados#HashList", items: @response.as_api_response(nil)
130   end
131
132   # delete user agreements, vm, repository, login links; set state to inactive
133   def unsetup
134     reload_object_before_update
135     @object.unsetup
136     show
137   end
138
139   protected
140
141   def self._setup_requires_parameters
142     {
143       user: {
144         type: 'object', required: false
145       },
146       openid_prefix: {
147         type: 'string', required: false
148       },
149       repo_name: {
150         type: 'string', required: false
151       },
152       vm_uuid: {
153         type: 'string', required: false
154       },
155       send_notification_email: {
156         type: 'boolean', required: false, default: false
157       },
158     }
159   end
160
161   def apply_filters(model_class=nil)
162     return super if @read_users.any? &:is_admin
163     if params[:uuid] != current_user.andand.uuid
164       # Non-admin index/show returns very basic information about readable users.
165       safe_attrs = ["uuid", "is_active", "email", "first_name", "last_name"]
166       if @select
167         @select = @select & safe_attrs
168       else
169         @select = safe_attrs
170       end
171       @filters += [['is_active', '=', true]]
172     end
173     super
174   end
175 end