X-Git-Url: https://git.arvados.org/arvados.git/blobdiff_plain/dcbb5acc0f9767c6b358e5f5d6055b78290430ab..30d63b582ed093d235ae4a9efdeda5de1d4e2f24:/services/api/app/controllers/arvados/v1/users_controller.rb diff --git a/services/api/app/controllers/arvados/v1/users_controller.rb b/services/api/app/controllers/arvados/v1/users_controller.rb index d87e51d2ca..a671809123 100644 --- a/services/api/app/controllers/arvados/v1/users_controller.rb +++ b/services/api/app/controllers/arvados/v1/users_controller.rb @@ -1,8 +1,11 @@ class Arvados::V1::UsersController < ApplicationController + accept_attribute_as_json :prefs, Hash + skip_before_filter :find_object_by_uuid, only: - [:activate, :event_stream, :current, :system] + [:activate, :current, :system, :setup] skip_before_filter :render_404_if_no_object, only: - [:activate, :event_stream, :current, :system] + [:activate, :current, :system, :setup] + before_filter :admin_required, only: [:setup, :unsetup] def current @object = current_user @@ -13,39 +16,6 @@ class Arvados::V1::UsersController < ApplicationController show end - class ChannelStreamer - Q_UPDATE_INTERVAL = 12 - def initialize(opts={}) - @opts = opts - end - def each - return unless @opts[:channel] - @redis = Redis.new(:timeout => 0) - @redis.subscribe(@opts[:channel]) do |event| - event.message do |channel, msg| - yield msg + "\n" - end - end - end - end - - def event_stream - channel = current_user.andand.uuid - if current_user.andand.is_admin - channel = params[:uuid] || channel - end - if client_accepts_plain_text_stream - self.response.headers['Last-Modified'] = Time.now.ctime.to_s - self.response_body = ChannelStreamer.new(channel: channel) - else - render json: { - href: url_for(uuid: channel), - comment: ('To retrieve the event stream as plain text, ' + - 'use a request header like "Accept: text/plain"') - } - end - end - def activate if current_user.andand.is_admin && params[:uuid] @object = User.find params[:uuid] @@ -59,22 +29,21 @@ class Arvados::V1::UsersController < ApplicationController raise ArgumentError.new "Cannot activate without being invited." end act_as_system_user do - required_uuids = Link.where(owner_uuid: system_user_uuid, - link_class: 'signature', - name: 'require', - tail_uuid: system_user_uuid, - head_kind: 'arvados#collection'). + required_uuids = Link.where("owner_uuid = ? and link_class = ? and name = ? and tail_uuid = ? and head_uuid like ?", + system_user_uuid, + 'signature', + 'require', + system_user_uuid, + Collection.uuid_like_pattern). collect(&:head_uuid) signed_uuids = Link.where(owner_uuid: system_user_uuid, link_class: 'signature', name: 'click', - tail_kind: 'arvados#user', tail_uuid: @object.uuid, - head_kind: 'arvados#collection', head_uuid: required_uuids). collect(&:head_uuid) todo_uuids = required_uuids - signed_uuids - if todo_uuids == [] + if todo_uuids.empty? @object.update_attributes is_active: true logger.info "User #{@object.uuid} activated" else @@ -88,177 +57,69 @@ class Arvados::V1::UsersController < ApplicationController show end - # create user object and all the needed links - def create - openid_prefix = 'https://www.google.com/accounts/o8/id' # default openid prefix - if params[openid_prefix] - openid_prefix = params[openid_prefix] - end - login_perm_props = {identity_url_prefix: openid_prefix} - -puts "\n*******************************\nparams = #{params}" -puts "\n*******************************\nlogin_perm_props = #{login_perm_props.inspect}" - - @object = model_class.new resource_attrs - need_to_create = false - - # If user_param parameter is passed, lookup for user. If exists, skip create and create any missing links. - if params[:user_param] - begin - @object_found = find_user_from_user_param params[:user_param] - rescue Exception => e - raise e - end - - if !@object_found - @object[:email] = params[:user_param] - need_to_create = true - else - @object = @object_found - end - else # need to create user for the given :user data - need_to_create = true - end - - if need_to_create - if @object.save - # create openid login permission - oid_login_perm = Link.create(link_class: 'permission', - name: 'can_login', - tail_kind: 'email', - tail_uuid: @object[:email], - head_kind: 'arvados#user', - head_uuid: @object[:uuid], - properties: login_perm_props - ) - - logger.info { "openid login permission: " + oid_login_perm[:uuid] } - else - raise "Save failed" - end - end - - # create links - link_repo params[:repo_name] - vm_login_permission params[:vm_uuid] - link_group -puts "@object in the end #{@object.inspect}" - show - end - - protected - - def find_user_from_user_param(user_param) - found_object = User.find_by_uuid user_param - puts "found by uuid = #{found_object.inspect}" - if !found_object - puts "didnt find by uuid. trying email" - begin - if !user_param.match(/\w\@\w+\.\w+/) - logger.warn ("Given user param is not valid email format: #{user_param}") - raise ArgumentError.new "User param is not of valid email format. Stop" - else - found_objects = User.where('email=?', user_param) - - if found_objects.size > 1 - logger.warn ("Found #{found_objects.size} users with email #{user_param}. Stop.") - raise ArgumentError.new "Found #{found_objects.size} users with email #{user_param}. Stop." - elsif found_objects.size == 1 - found_object = found_objects.first - end + # create user object and all the needed links + def setup + @object = nil + if params[:uuid] + @object = User.find_by_uuid params[:uuid] + if !@object + return render_404_if_no_object + end + object_found = true + else + if !params[:user] + raise ArgumentError.new "Required uuid or user" + else + if params[:user]['uuid'] + @object = User.find_by_uuid params[:user]['uuid'] + if @object + object_found = true + end end - end - end - - return found_object - end - - def link_repo(repo_name) - puts "\n*******************************\n" - puts "repo_name = #{repo_name}" - puts "and object is #{@object[:uuid]}" - - if !repo_name - logger.warn ("Repository name not given for #{@object[:uuid]}. Skip creating the link") - return - end - # Look for existing repository access (perhaps using a different repository/user name). - repo_perms = Link.where(tail_uuid: @object[:uuid], - head_kind: 'arvados#repository', - link_class: 'permission', - name: 'can_write') + if !@object + if !params[:user]['email'] + raise ArgumentError.new "Require user email" + end - if [] != repo_perms - logger.warn "User already has repository access " + repo_perms.collect { |p| p[:uuid] }.inspect - return - end + if !params[:openid_prefix] + raise ArgumentError.new "Required openid_prefix parameter is missing." + end - # Check for an existing repository with the same name we're about to use. - repo = Repository.where(name: repo_name).first - if repo - logger.warn "Repository already exists with name #{repo_name}: #{repo[:uuid]}" - return - end - - repo ||= Repository.create(name: repo_name) - logger.info { "repo uuid: " + repo[:uuid] } - - repo_perm = Link.create(tail_kind: 'arvados#user', - tail_uuid: @object[:uuid], - head_kind: 'arvados#repository', - head_uuid: repo[:uuid], - link_class: 'permission', - name: 'can_write') - logger.info { "repo permission: " + repo_perm[:uuid] } - end - - def vm_login_permission(vm_uuid) - puts "\n*******************************\n" - puts "vm_uuid = #{vm_uuid}" - puts "and object is #{@object[:uuid]}" + @object = model_class.create! resource_attrs + end + end + end - # Look up the given virtual machine just to make sure it really exists. - begin - vm = VirtualMachine.get(uuid: vm_uuid) - logger.info { "vm uuid: " + vm[:uuid] } + if object_found + @response = @object.setup_repo_vm_links params[:repo_name], + params[:vm_uuid], params[:openid_prefix] + else + @response = User.setup @object, params[:openid_prefix], + params[:repo_name], params[:vm_uuid] + end - login_perm = Link.create(tail_kind: 'arvados#user', - tail_uuid: @object[:uuid], - head_kind: 'arvados#virtualMachine', - head_uuid: vm[:uuid], - link_class: 'permission', - name: 'can_login', - properties: {username: repo_name}) - logger.info { "login permission: " + login_perm[:uuid] } - rescue - logger.warn "Could not look up virtual machine with uuid #{vm_uuid.inspect}. Skip." - end - end + # setup succeeded. send email to user + if params[:send_notification_email] == true || params[:send_notification_email] == 'true' + UserNotifier.account_is_setup(@object).deliver + end - def link_group - puts "\n*******************************\n" - puts "in link group" - puts "and object is #{@object[:uuid]}" + render json: { kind: "arvados#HashList", items: @response.as_api_response(nil) } + end - # Look up the "All users" group (we expect uuid *-*-fffffffffffffff). - group = Group.where(name: 'All users').select do |g| - g[:uuid].match /-f+$/ - end.first + # delete user agreements, vm, repository, login links; set state to inactive + def unsetup + reload_object_before_update + @object.unsetup + show + end - if not group - logger.warn "Could not look up the 'All users' group with uuid '*-*-fffffffffffffff'. Skip." - else - logger.info { "\"All users\" group uuid: " + group[:uuid] } + protected - group_perm = Link.create(tail_kind: 'arvados#user', - tail_uuid: @object[:uuid], - head_kind: 'arvados#group', - head_uuid: group[:uuid], - link_class: 'permission', - name: 'can_read') - logger.info { "group permission: " + group_perm[:uuid] } - end - end + def self._setup_requires_parameters + { + send_notification_email: { type: 'boolean', required: true }, + } + end end