Merged master
[arvados.git] / services / api / app / controllers / arvados / v1 / users_controller.rb
index 6558655e65797bd6625450cd03c0aa2b5a75c978..0934642261bb314fdfbf76175251a2d702fb3a6b 100644 (file)
@@ -1,8 +1,9 @@
 class Arvados::V1::UsersController < ApplicationController
   skip_before_filter :find_object_by_uuid, only:
-    [:activate, :event_stream, :current, :system]
+    [:activate, :event_stream, :current, :system, :setup]
   skip_before_filter :render_404_if_no_object, only:
-    [:activate, :event_stream, :current, :system]
+    [:activate, :event_stream, :current, :system, :setup]
+  before_filter :admin_required, only: [:setup, :unsetup]
 
   def current
     @object = current_user
@@ -28,7 +29,7 @@ class Arvados::V1::UsersController < ApplicationController
       end
     end
   end
-      
+
   def event_stream
     channel = current_user.andand.uuid
     if current_user.andand.is_admin
@@ -58,19 +59,18 @@ class Arvados::V1::UsersController < ApplicationController
           "but is not invited"
         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').
+      act_as_system_user do       
+        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
@@ -88,207 +88,56 @@ class Arvados::V1::UsersController < ApplicationController
     show
   end
 
-       # create user object and all the needed links
-  def create
-               if params[:openid_prefix]               # check if default openid_prefix needs to be overridden
-                       openid_prefix = params[:openid_prefix]
-               else 
-                       openid_prefix = 'https://www.google.com/accounts/o8/id'         # default openid prefix
-               end
-               login_perm_props = {identity_url_prefix: openid_prefix}
-
-               # check if only to probe the given user parameter
-               just_probe = (params[:just_probe] == 'true') ? true : false;
-
-               @object = model_class.new resource_attrs
-
-               # If user_param is passed, lookup for user. If exists, skip create and create any missing links. 
-               if params[:user_param]
-                       begin 
-                               @object_found = find_user_from_input params[:user_param], params[:user_param]
-                 end
-                       if !@object_found
-                               @object = User.new              # when user_param is used, it will be used as user object
-                               @object[:email] = params[:user_param]                           
-                       need_to_create = true
-                       else
-                               @object = @object_found
-                       end
-               else            # need to create user for the given user data
-                       @object_found = find_user_from_input @object[:uuid], @object[:email]
-                       if !@object_found
-                       need_to_create = true
-                       else
-                               @object = @object_found
-                       end
-               end
-
-               # if just probing, return any object found      
-               if just_probe 
-                       show
-                 return
-               end
-
-               # create if need be, and then create or update the links as needed 
-               if need_to_create
-                       if @object.save         # save succeeded
-                               oid_login_perm = Link.where(tail_uuid: @object[:email],
-                                                       head_kind: 'arvados#user',
-                                                       link_class: 'permission',
-                                                       name: 'can_login')
-
-                               if [] == oid_login_perm
-                                       # 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] }
-                               end
-         else
-               raise "Save failed"
-               end
-               end
-
-               # create links
-               create_user_repo_link params[:repo_name]
-               create_vm_login_permission_link params[:vm_uuid], params[:repo_name]
-               create_user_group_link 
-
-               show
-  end
-
-       protected 
-
-       # find the user from the given user parameter
-       def find_user_from_input(user_uuid, user_email)
-               if user_uuid
-                       found_object = User.find_by_uuid user_uuid
-               end
-
-               if !found_object
-                       begin
-                               if !user_email
-                                       return
-                               end
-
-                               if !user_email.match(/\w\@\w+\.\w+/)
-                                       logger.warn ("Given user param is not valid email format: #{user_email}")
-                                       raise ArgumentError.new "User param is not of valid email format. Stop"
-                               else
-          found_objects = User.where('email=?', user_email)  
-                                       if found_objects.size > 1
-                                               logger.warn ("Found #{found_objects.size} users with email #{user_email}. Stop.")
-                                               raise ArgumentError.new "Found #{found_objects.size} users with email #{user_email}. 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
-       
-       # link the repo_name passed
-       def create_user_repo_link(repo_name)
-               if not repo_name
-                       logger.warn ("Repository name not given for #{@object[:uuid]}. Skip creating the link")
-                       return
-               end
-
-               # Check for an existing repository with the same name we're about to use.
-               repo = (repositories = Repository.where(name: repo_name)) != nil ? repositories.first : nil
-               if repo
-               logger.warn "Repository already exists with name #{repo_name}: #{repo[:uuid]}. Will link to user."
-
-                       # Look for existing repository access (perhaps using a different repository/user name).
-                       repo_perms = Link.where(tail_uuid: @object[:uuid],
-                               head_kind: 'arvados#repository',
-                               head_uuid: repo[:uuid],
-                               link_class: 'permission',
-                               name: 'can_write')
-                       if [] != repo_perms
-                       logger.warn "User already has repository access " + repo_perms.collect { |p| p[:uuid] }.inspect
-                               return
-                       end
-               end
 
-               repo ||= Repository.create(name: repo_name)             # create repo, if does not already exist
-               logger.info { "repo uuid: " + repo[:uuid] }
+        if !@object
+          if !params[:user]['email']
+            raise ArgumentError.new "Require user email"
+          end
 
-               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
+          if !params[:openid_prefix]
+            raise ArgumentError.new "Required openid_prefix parameter is missing."
+          end
 
-       # create login permission for the given vm_uuid, if it does not already exist
-       def create_vm_login_permission_link(vm_uuid, repo_name)
-               # Look up the given virtual machine just to make sure it really exists.
-               begin
-                       vm = (vms = VirtualMachine.where(uuid: vm_uuid)) != nil ? vms.first : nil
-                       if not vm
-                         logger.warn "Could not look up virtual machine with uuid #{vm_uuid.inspect}"
-                               return
-                       end
-
-                       logger.info { "vm uuid: " + vm[:uuid] }
-
-                       login_perm = Link.where(tail_uuid: @object[:uuid],
-                              head_uuid: vm[:uuid],
-                               head_kind: 'arvados#virtualMachine',
-                               link_class: 'permission',
-                               name: 'can_login')
-                       if [] == login_perm
-                               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] }
-                       end
-               end
-       end
+          @object = model_class.create! resource_attrs
+        end
+      end
+    end
 
-       # add the user to the 'All users' group
-       def create_user_group_link
-               # 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
+    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
 
-               if not group
-               logger.warn "Could not look up the 'All users' group with uuid '*-*-fffffffffffffff'. Skip."
-                       return
-               else
-                       logger.info { "\"All users\" group uuid: " + group[:uuid] }
+    render json: { kind: "arvados#HashList", items: @response }
+  end
 
-                       group_perm = Link.where(tail_uuid: @object[:uuid],
-                                                                                                                       head_uuid: group[:uuid],
-                               head_kind: 'arvados#group',
-                               link_class: 'permission',
-                               name: 'can_read')
+  # delete user agreements, vm, repository, login links; set state to inactive
+  def unsetup
+    reload_object_before_update
+    @object.unsetup
+    show
+  end
 
-                       if [] == group_perm
-                               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
-       end
 end