Merge branch 'master' into 2221-complete-docker
[arvados.git] / services / api / app / controllers / arvados / v1 / users_controller.rb
1 class Arvados::V1::UsersController < ApplicationController
2   skip_before_filter :find_object_by_uuid, only:
3     [:activate, :event_stream, :current, :system, :setup]
4   skip_before_filter :render_404_if_no_object, only:
5     [:activate, :event_stream, :current, :system, :setup]
6   before_filter :admin_required, only: [:setup, :unsetup]
7   
8   def current
9     @object = current_user
10     show
11   end
12   def system
13     @object = system_user
14     show
15   end
16
17   class ChannelStreamer
18     Q_UPDATE_INTERVAL = 12
19     def initialize(opts={})
20       @opts = opts
21     end
22     def each
23       return unless @opts[:channel]
24       @redis = Redis.new(:timeout => 0)
25       @redis.subscribe(@opts[:channel]) do |event|
26         event.message do |channel, msg|
27           yield msg + "\n"
28         end
29       end
30     end
31   end
32       
33   def event_stream
34     channel = current_user.andand.uuid
35     if current_user.andand.is_admin
36       channel = params[:uuid] || channel
37     end
38     if client_accepts_plain_text_stream
39       self.response.headers['Last-Modified'] = Time.now.ctime.to_s
40       self.response_body = ChannelStreamer.new(channel: channel)
41     else
42       render json: {
43         href: url_for(uuid: channel),
44         comment: ('To retrieve the event stream as plain text, ' +
45                   'use a request header like "Accept: text/plain"')
46       }
47     end
48   end
49
50   def activate
51     if current_user.andand.is_admin && params[:uuid]
52       @object = User.find params[:uuid]
53     else
54       @object = current_user
55     end
56     if not @object.is_active
57       if not (current_user.is_admin or @object.is_invited)
58         logger.warn "User #{@object.uuid} called users.activate " +
59           "but is not invited"
60         raise ArgumentError.new "Cannot activate without being invited."
61       end
62       act_as_system_user do
63         required_uuids = Link.where(owner_uuid: system_user_uuid,
64                                     link_class: 'signature',
65                                     name: 'require',
66                                     tail_uuid: system_user_uuid,
67                                     head_kind: 'arvados#collection').
68           collect(&:head_uuid)
69         signed_uuids = Link.where(owner_uuid: system_user_uuid,
70                                   link_class: 'signature',
71                                   name: 'click',
72                                   tail_kind: 'arvados#user',
73                                   tail_uuid: @object.uuid,
74                                   head_kind: 'arvados#collection',
75                                   head_uuid: required_uuids).
76           collect(&:head_uuid)
77         todo_uuids = required_uuids - signed_uuids
78         if todo_uuids == []
79           @object.update_attributes is_active: true
80           logger.info "User #{@object.uuid} activated"
81         else
82           logger.warn "User #{@object.uuid} called users.activate " +
83             "before signing agreements #{todo_uuids.inspect}"
84           raise ArvadosModel::PermissionDeniedError.new \
85           "Cannot activate without user agreements #{todo_uuids.inspect}."
86         end
87       end
88     end
89     show
90   end
91
92   # create user object and all the needed links
93   def setup
94     @object = nil
95     if params[:uuid]
96       @object = User.find_by_uuid params[:uuid]
97       if !@object
98         return render_404_if_no_object
99       end
100       object_found = true
101     else
102       if !params[:user]
103         raise ArgumentError.new "Required uuid or user"
104       else
105         if params[:user]['uuid']
106           @object = User.find_by_uuid params[:user]['uuid']
107           if @object
108             object_found = true
109           end
110         end
111
112         if !@object
113           if !params[:user]['email']
114             raise ArgumentError.new "Require user email"
115           end
116
117           if !params[:openid_prefix]
118             raise ArgumentError.new "Required openid_prefix parameter is missing."
119           end
120
121           @object = model_class.create! resource_attrs
122         end
123       end
124     end
125
126     if object_found
127       @response = @object.setup_repo_vm_links params[:repo_name], params[:vm_uuid]
128     else
129       @response = User.setup @object, params[:openid_prefix],
130                     params[:repo_name], params[:vm_uuid]
131     end
132
133     render json: { kind: "arvados#HashList", items: @response }
134   end
135
136   # delete user agreements, vm, repository, login links; set state to inactive
137   def unsetup
138     reload_object_before_update
139     @object.unsetup
140     show
141   end
142
143 end