aspera-cli 4.0.0.pre1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/README.md +3592 -0
- data/bin/ascli +7 -0
- data/bin/asession +89 -0
- data/docs/Makefile +59 -0
- data/docs/README.erb.md +3012 -0
- data/docs/README.md +13 -0
- data/docs/diagrams.txt +49 -0
- data/docs/secrets.make +38 -0
- data/docs/test_env.conf +117 -0
- data/docs/transfer_spec.html +99 -0
- data/examples/aoc.rb +17 -0
- data/examples/proxy.pac +60 -0
- data/examples/transfer.rb +115 -0
- data/lib/aspera/api_detector.rb +60 -0
- data/lib/aspera/ascmd.rb +151 -0
- data/lib/aspera/ats_api.rb +43 -0
- data/lib/aspera/cli/basic_auth_plugin.rb +38 -0
- data/lib/aspera/cli/extended_value.rb +88 -0
- data/lib/aspera/cli/formater.rb +238 -0
- data/lib/aspera/cli/listener/line_dump.rb +17 -0
- data/lib/aspera/cli/listener/logger.rb +20 -0
- data/lib/aspera/cli/listener/progress.rb +52 -0
- data/lib/aspera/cli/listener/progress_multi.rb +91 -0
- data/lib/aspera/cli/main.rb +304 -0
- data/lib/aspera/cli/manager.rb +440 -0
- data/lib/aspera/cli/plugin.rb +90 -0
- data/lib/aspera/cli/plugins/alee.rb +24 -0
- data/lib/aspera/cli/plugins/ats.rb +231 -0
- data/lib/aspera/cli/plugins/bss.rb +71 -0
- data/lib/aspera/cli/plugins/config.rb +806 -0
- data/lib/aspera/cli/plugins/console.rb +62 -0
- data/lib/aspera/cli/plugins/cos.rb +106 -0
- data/lib/aspera/cli/plugins/faspex.rb +377 -0
- data/lib/aspera/cli/plugins/faspex5.rb +93 -0
- data/lib/aspera/cli/plugins/node.rb +438 -0
- data/lib/aspera/cli/plugins/oncloud.rb +937 -0
- data/lib/aspera/cli/plugins/orchestrator.rb +169 -0
- data/lib/aspera/cli/plugins/preview.rb +464 -0
- data/lib/aspera/cli/plugins/server.rb +216 -0
- data/lib/aspera/cli/plugins/shares.rb +63 -0
- data/lib/aspera/cli/plugins/shares2.rb +114 -0
- data/lib/aspera/cli/plugins/sync.rb +65 -0
- data/lib/aspera/cli/plugins/xnode.rb +115 -0
- data/lib/aspera/cli/transfer_agent.rb +251 -0
- data/lib/aspera/cli/version.rb +5 -0
- data/lib/aspera/colors.rb +39 -0
- data/lib/aspera/command_line_builder.rb +137 -0
- data/lib/aspera/fasp/aoc.rb +24 -0
- data/lib/aspera/fasp/connect.rb +99 -0
- data/lib/aspera/fasp/error.rb +21 -0
- data/lib/aspera/fasp/error_info.rb +60 -0
- data/lib/aspera/fasp/http_gw.rb +81 -0
- data/lib/aspera/fasp/installation.rb +240 -0
- data/lib/aspera/fasp/listener.rb +11 -0
- data/lib/aspera/fasp/local.rb +377 -0
- data/lib/aspera/fasp/manager.rb +69 -0
- data/lib/aspera/fasp/node.rb +88 -0
- data/lib/aspera/fasp/parameters.rb +235 -0
- data/lib/aspera/fasp/resume_policy.rb +76 -0
- data/lib/aspera/fasp/uri.rb +51 -0
- data/lib/aspera/faspex_gw.rb +196 -0
- data/lib/aspera/hash_ext.rb +28 -0
- data/lib/aspera/log.rb +80 -0
- data/lib/aspera/nagios.rb +71 -0
- data/lib/aspera/node.rb +14 -0
- data/lib/aspera/oauth.rb +319 -0
- data/lib/aspera/on_cloud.rb +421 -0
- data/lib/aspera/open_application.rb +72 -0
- data/lib/aspera/persistency_action_once.rb +42 -0
- data/lib/aspera/persistency_folder.rb +91 -0
- data/lib/aspera/preview/file_types.rb +300 -0
- data/lib/aspera/preview/generator.rb +258 -0
- data/lib/aspera/preview/image_error.png +0 -0
- data/lib/aspera/preview/options.rb +35 -0
- data/lib/aspera/preview/utils.rb +131 -0
- data/lib/aspera/preview/video_error.png +0 -0
- data/lib/aspera/proxy_auto_config.erb.js +287 -0
- data/lib/aspera/proxy_auto_config.rb +34 -0
- data/lib/aspera/rest.rb +296 -0
- data/lib/aspera/rest_call_error.rb +13 -0
- data/lib/aspera/rest_error_analyzer.rb +98 -0
- data/lib/aspera/rest_errors_aspera.rb +58 -0
- data/lib/aspera/ssh.rb +53 -0
- data/lib/aspera/sync.rb +82 -0
- data/lib/aspera/temp_file_manager.rb +37 -0
- data/lib/aspera/uri_reader.rb +25 -0
- metadata +288 -0
| @@ -0,0 +1,937 @@ | |
| 1 | 
            +
            require 'aspera/cli/plugins/node'
         | 
| 2 | 
            +
            require 'aspera/cli/plugins/ats'
         | 
| 3 | 
            +
            require 'aspera/cli/basic_auth_plugin'
         | 
| 4 | 
            +
            require 'aspera/cli/transfer_agent'
         | 
| 5 | 
            +
            require 'aspera/on_cloud'
         | 
| 6 | 
            +
            require 'aspera/persistency_action_once'
         | 
| 7 | 
            +
            require 'securerandom'
         | 
| 8 | 
            +
            require 'resolv'
         | 
| 9 | 
            +
            require 'date'
         | 
| 10 | 
            +
             | 
| 11 | 
            +
            module Aspera
         | 
| 12 | 
            +
              module Cli
         | 
| 13 | 
            +
                module Plugins
         | 
| 14 | 
            +
                  class Oncloud < BasicAuthPlugin
         | 
| 15 | 
            +
                    VAL_ALL='ALL'
         | 
| 16 | 
            +
                    private_constant :VAL_ALL
         | 
| 17 | 
            +
                    attr_reader :api_aoc
         | 
| 18 | 
            +
                    def initialize(env)
         | 
| 19 | 
            +
                      super(env)
         | 
| 20 | 
            +
                      @default_workspace_id=nil
         | 
| 21 | 
            +
                      @workspace_name=nil
         | 
| 22 | 
            +
                      @workspace_id=nil
         | 
| 23 | 
            +
                      @persist_ids=nil
         | 
| 24 | 
            +
                      @home_node_file=nil
         | 
| 25 | 
            +
                      @api_aoc=nil
         | 
| 26 | 
            +
                      @url_token_data=nil
         | 
| 27 | 
            +
                      @user_info=nil
         | 
| 28 | 
            +
                      @ats=Ats.new(@agents)
         | 
| 29 | 
            +
                      self.options.add_opt_list(:auth,Oauth.auth_types,"type of Oauth authentication")
         | 
| 30 | 
            +
                      self.options.add_opt_list(:operation,[:push,:pull],"client operation for transfers")
         | 
| 31 | 
            +
                      self.options.add_opt_simple(:client_id,"API client identifier in application")
         | 
| 32 | 
            +
                      self.options.add_opt_simple(:client_secret,"API client passcode")
         | 
| 33 | 
            +
                      self.options.add_opt_simple(:redirect_uri,"API client redirect URI")
         | 
| 34 | 
            +
                      self.options.add_opt_simple(:private_key,"RSA private key PEM value for JWT (prefix file path with @val:@file:)")
         | 
| 35 | 
            +
                      self.options.add_opt_simple(:workspace,"name of workspace")
         | 
| 36 | 
            +
                      self.options.add_opt_simple(:eid,"identifier") # used ?
         | 
| 37 | 
            +
                      self.options.add_opt_simple(:name,"resource name")
         | 
| 38 | 
            +
                      self.options.add_opt_simple(:link,"public link to shared resource")
         | 
| 39 | 
            +
                      self.options.add_opt_simple(:new_user_option,"new user creation option")
         | 
| 40 | 
            +
                      self.options.add_opt_simple(:from_folder,"share to share source folder")
         | 
| 41 | 
            +
                      self.options.add_opt_simple(:scope,"scope for AoC API calls")
         | 
| 42 | 
            +
                      self.options.add_opt_simple(:notify,"notify users that file was received")
         | 
| 43 | 
            +
                      self.options.add_opt_boolean(:bulk,"bulk operation")
         | 
| 44 | 
            +
                      self.options.add_opt_boolean(:default_ports,"use standard FASP ports or get from node api")
         | 
| 45 | 
            +
                      self.options.set_option(:bulk,:no)
         | 
| 46 | 
            +
                      self.options.set_option(:default_ports,:yes)
         | 
| 47 | 
            +
                      self.options.set_option(:new_user_option,{'package_contact'=>true})
         | 
| 48 | 
            +
                      self.options.set_option(:operation,:push)
         | 
| 49 | 
            +
                      self.options.set_option(:auth,:jwt)
         | 
| 50 | 
            +
                      self.options.set_option(:scope,OnCloud::SCOPE_FILES_USER)
         | 
| 51 | 
            +
                      self.options.set_option(:private_key,'@file:'+env[:private_key_path]) if env[:private_key_path].is_a?(String)
         | 
| 52 | 
            +
                      self.options.parse_options!
         | 
| 53 | 
            +
                      OnCloud.set_use_default_ports(self.options.get_option(:default_ports))
         | 
| 54 | 
            +
                      return if env[:man_only]
         | 
| 55 | 
            +
                      update_aoc_api
         | 
| 56 | 
            +
                    end
         | 
| 57 | 
            +
             | 
| 58 | 
            +
                    # call this to populate single AK secret in AoC API object, from options
         | 
| 59 | 
            +
                    # make sure secret is available
         | 
| 60 | 
            +
                    def find_ak_secret(ak,mandatory=true)
         | 
| 61 | 
            +
                      # secret hash is already provisioned
         | 
| 62 | 
            +
                      # optionally override with specific secret
         | 
| 63 | 
            +
                      @api_aoc.add_secrets({ak=>self.config.get_secret(ak,mandatory)})
         | 
| 64 | 
            +
                      # check that secret was provided as single value or dictionary
         | 
| 65 | 
            +
                      raise CliBadArgument,"Please provide option secret or entry in option secrets for: #{ak}" unless @api_aoc.has_secret(ak) or !mandatory
         | 
| 66 | 
            +
                    end
         | 
| 67 | 
            +
             | 
| 68 | 
            +
                    def user_info
         | 
| 69 | 
            +
                      if @user_info.nil?
         | 
| 70 | 
            +
                        # get our user's default information
         | 
| 71 | 
            +
                        # self?embed[]=default_workspace&embed[]=organization
         | 
| 72 | 
            +
                        @user_info=@api_aoc.read('self')[:data] rescue {
         | 
| 73 | 
            +
                        'name'  => 'unknown',
         | 
| 74 | 
            +
                        'email' => 'unknown',
         | 
| 75 | 
            +
                        }
         | 
| 76 | 
            +
                      end
         | 
| 77 | 
            +
                      return @user_info
         | 
| 78 | 
            +
                    end
         | 
| 79 | 
            +
             | 
| 80 | 
            +
                    # starts transfer using transfer agent
         | 
| 81 | 
            +
                    def transfer_start(app,direction,node_file,ts_add)
         | 
| 82 | 
            +
                      ts_add.deep_merge!(OnCloud.analytics_ts(app,direction,@workspace_id,@workspace_name))
         | 
| 83 | 
            +
                      ts_add.deep_merge!(OnCloud.console_ts(app,user_info['name'],user_info['email']))
         | 
| 84 | 
            +
                      return self.transfer.start(*@api_aoc.tr_spec(app,direction,node_file,ts_add))
         | 
| 85 | 
            +
                    end
         | 
| 86 | 
            +
             | 
| 87 | 
            +
                    NODE4_COMMANDS=[ :browse, :find, :mkdir, :rename, :delete, :upload, :download, :transfer, :http_node_download, :v3, :file, :bearer_token_node, :permissions  ]
         | 
| 88 | 
            +
             | 
| 89 | 
            +
                    def node_gen4_execute_action(top_node_file)
         | 
| 90 | 
            +
                      command_repo=self.options.get_next_command(NODE4_COMMANDS)
         | 
| 91 | 
            +
                      return execute_node_gen4_command(command_repo,top_node_file)
         | 
| 92 | 
            +
                    end
         | 
| 93 | 
            +
             | 
| 94 | 
            +
                    def execute_node_gen4_command(command_repo,top_node_file)
         | 
| 95 | 
            +
                      case command_repo
         | 
| 96 | 
            +
                      when :bearer_token_node
         | 
| 97 | 
            +
                        thepath=self.options.get_next_argument('path')
         | 
| 98 | 
            +
                        node_file = @api_aoc.resolve_node_file(top_node_file,thepath)
         | 
| 99 | 
            +
                        node_api=@api_aoc.get_node_api(node_file[:node_info],OnCloud::SCOPE_NODE_USER)
         | 
| 100 | 
            +
                        return Main.result_status(node_api.oauth_token)
         | 
| 101 | 
            +
                      when :browse
         | 
| 102 | 
            +
                        thepath=self.options.get_next_argument('path')
         | 
| 103 | 
            +
                        node_file = @api_aoc.resolve_node_file(top_node_file,thepath)
         | 
| 104 | 
            +
                        node_api=@api_aoc.get_node_api(node_file[:node_info],OnCloud::SCOPE_NODE_USER)
         | 
| 105 | 
            +
                        file_info = node_api.read("files/#{node_file[:file_id]}")[:data]
         | 
| 106 | 
            +
                        if file_info['type'].eql?('folder')
         | 
| 107 | 
            +
                          result=node_api.read("files/#{node_file[:file_id]}/files",self.options.get_option(:value,:optional))
         | 
| 108 | 
            +
                          items=result[:data]
         | 
| 109 | 
            +
                          self.format.display_status("Items: #{result[:data].length}/#{result[:http]['X-Total-Count']}")
         | 
| 110 | 
            +
                        else
         | 
| 111 | 
            +
                          items=[file_info]
         | 
| 112 | 
            +
                        end
         | 
| 113 | 
            +
                        return {:type=>:object_list,:data=>items,:fields=>['name','type','recursive_size','size','modified_time','access_level']}
         | 
| 114 | 
            +
                      when :find
         | 
| 115 | 
            +
                        thepath=self.options.get_next_argument('path')
         | 
| 116 | 
            +
                        exec_prefix='exec:'
         | 
| 117 | 
            +
                        expression=self.options.get_option(:value,:optional)||"#{exec_prefix}true"
         | 
| 118 | 
            +
                        node_file=@api_aoc.resolve_node_file(top_node_file,thepath)
         | 
| 119 | 
            +
                        if expression.start_with?(exec_prefix)
         | 
| 120 | 
            +
                          test_block=eval "lambda{|f|#{expression[exec_prefix.length..-1]}}"
         | 
| 121 | 
            +
                        else
         | 
| 122 | 
            +
                          test_block=lambda{|f|f['name'].match(/#{expression}/)}
         | 
| 123 | 
            +
                        end
         | 
| 124 | 
            +
                        return {:type=>:object_list,:data=>@api_aoc.find_files(node_file,test_block),:fields=>['path']}
         | 
| 125 | 
            +
                      when :mkdir
         | 
| 126 | 
            +
                        thepath=self.options.get_next_argument('path')
         | 
| 127 | 
            +
                        containing_folder_path = thepath.split(OnCloud::PATH_SEPARATOR)
         | 
| 128 | 
            +
                        new_folder=containing_folder_path.pop
         | 
| 129 | 
            +
                        node_file = @api_aoc.resolve_node_file(top_node_file,containing_folder_path.join(OnCloud::PATH_SEPARATOR))
         | 
| 130 | 
            +
                        node_api=@api_aoc.get_node_api(node_file[:node_info],OnCloud::SCOPE_NODE_USER)
         | 
| 131 | 
            +
                        result=node_api.create("files/#{node_file[:file_id]}/files",{:name=>new_folder,:type=>:folder})[:data]
         | 
| 132 | 
            +
                        return Main.result_status("created: #{result['name']} (id=#{result['id']})")
         | 
| 133 | 
            +
                      when :rename
         | 
| 134 | 
            +
                        thepath=self.options.get_next_argument('source path')
         | 
| 135 | 
            +
                        newname=self.options.get_next_argument('new name')
         | 
| 136 | 
            +
                        node_file = @api_aoc.resolve_node_file(top_node_file,thepath)
         | 
| 137 | 
            +
                        node_api=@api_aoc.get_node_api(node_file[:node_info],OnCloud::SCOPE_NODE_USER)
         | 
| 138 | 
            +
                        result=node_api.update("files/#{node_file[:file_id]}",{:name=>newname})[:data]
         | 
| 139 | 
            +
                        return Main.result_status("renamed #{thepath} to #{newname}")
         | 
| 140 | 
            +
                      when :delete
         | 
| 141 | 
            +
                        thepath=self.options.get_next_argument('path')
         | 
| 142 | 
            +
                        return do_bulk_operation(thepath,'deleted','path') do |thepath|
         | 
| 143 | 
            +
                          raise "expecting String (path), got #{thepath.class.name} (#{thepath})" unless thepath.is_a?(String)
         | 
| 144 | 
            +
                          node_file = @api_aoc.resolve_node_file(top_node_file,thepath)
         | 
| 145 | 
            +
                          node_api=@api_aoc.get_node_api(node_file[:node_info],OnCloud::SCOPE_NODE_USER)
         | 
| 146 | 
            +
                          result=node_api.delete("files/#{node_file[:file_id]}")[:data]
         | 
| 147 | 
            +
                          {'path'=>thepath}
         | 
| 148 | 
            +
                        end
         | 
| 149 | 
            +
                      when :transfer
         | 
| 150 | 
            +
                        # client side is agent
         | 
| 151 | 
            +
                        # server side is protocol server
         | 
| 152 | 
            +
                        # in same workspace
         | 
| 153 | 
            +
                        server_home_node_file=client_home_node_file=top_node_file
         | 
| 154 | 
            +
                        # default is push
         | 
| 155 | 
            +
                        case self.options.get_option(:operation,:mandatory)
         | 
| 156 | 
            +
                        when :push
         | 
| 157 | 
            +
                          client_tr_oper='send'
         | 
| 158 | 
            +
                          client_folder=self.options.get_option(:from_folder,:mandatory)
         | 
| 159 | 
            +
                          server_folder=self.transfer.destination_folder(client_tr_oper)
         | 
| 160 | 
            +
                        when :pull
         | 
| 161 | 
            +
                          client_tr_oper='receive'
         | 
| 162 | 
            +
                          client_folder=self.transfer.destination_folder(client_tr_oper)
         | 
| 163 | 
            +
                          server_folder=self.options.get_option(:from_folder,:mandatory)
         | 
| 164 | 
            +
                        end
         | 
| 165 | 
            +
                        client_node_file = @api_aoc.resolve_node_file(client_home_node_file,client_folder)
         | 
| 166 | 
            +
                        server_node_file = @api_aoc.resolve_node_file(server_home_node_file,server_folder)
         | 
| 167 | 
            +
                        # force node as transfer agent
         | 
| 168 | 
            +
                        @agents[:transfer].set_agent_instance(Fasp::Node.new(@api_aoc.get_node_api(client_node_file[:node_info],OnCloud::SCOPE_NODE_USER)))
         | 
| 169 | 
            +
                        # additional node to node TS info
         | 
| 170 | 
            +
                        add_ts={
         | 
| 171 | 
            +
                          'remote_access_key'   => server_node_file[:node_info]['access_key'],
         | 
| 172 | 
            +
                          'destination_root_id' => server_node_file[:file_id],
         | 
| 173 | 
            +
                          'source_root_id'      => client_node_file[:file_id]
         | 
| 174 | 
            +
                        }
         | 
| 175 | 
            +
                        return Main.result_transfer(transfer_start(OnCloud::FILES_APP,client_tr_oper,server_node_file,add_ts))
         | 
| 176 | 
            +
                      when :upload
         | 
| 177 | 
            +
                        node_file = @api_aoc.resolve_node_file(top_node_file,self.transfer.destination_folder('send'))
         | 
| 178 | 
            +
                        add_ts={'tags'=>{'aspera'=>{'files'=>{'parentCwd'=>"#{node_file[:node_info]['id']}:#{node_file[:file_id]}"}}}}
         | 
| 179 | 
            +
                        return Main.result_transfer(transfer_start(OnCloud::FILES_APP,'send',node_file,add_ts))
         | 
| 180 | 
            +
                      when :download
         | 
| 181 | 
            +
                        source_paths=self.transfer.ts_source_paths
         | 
| 182 | 
            +
                        # special case for AoC : all files must be in same folder
         | 
| 183 | 
            +
                        source_folder=source_paths.shift['source']
         | 
| 184 | 
            +
                        # if a single file: split into folder and path
         | 
| 185 | 
            +
                        if source_paths.empty?
         | 
| 186 | 
            +
                          source_folder=source_folder.split(OnCloud::PATH_SEPARATOR)
         | 
| 187 | 
            +
                          source_paths=[{'source'=>source_folder.pop}]
         | 
| 188 | 
            +
                          source_folder=source_folder.join(OnCloud::PATH_SEPARATOR)
         | 
| 189 | 
            +
                        end
         | 
| 190 | 
            +
                        node_file = @api_aoc.resolve_node_file(top_node_file,source_folder)
         | 
| 191 | 
            +
                        # override paths with just filename
         | 
| 192 | 
            +
                        add_ts={'tags'=>{'aspera'=>{'files'=>{'parentCwd'=>"#{node_file[:node_info]['id']}:#{node_file[:file_id]}"}}}}
         | 
| 193 | 
            +
                        add_ts.merge!({'paths'=>source_paths})
         | 
| 194 | 
            +
                        return Main.result_transfer(transfer_start(OnCloud::FILES_APP,'receive',node_file,add_ts))
         | 
| 195 | 
            +
                      when :http_node_download
         | 
| 196 | 
            +
                        source_paths=self.transfer.ts_source_paths
         | 
| 197 | 
            +
                        source_folder=source_paths.shift['source']
         | 
| 198 | 
            +
                        if source_paths.empty?
         | 
| 199 | 
            +
                          source_folder=source_folder.split(OnCloud::PATH_SEPARATOR)
         | 
| 200 | 
            +
                          source_paths=[{'source'=>source_folder.pop}]
         | 
| 201 | 
            +
                          source_folder=source_folder.join(OnCloud::PATH_SEPARATOR)
         | 
| 202 | 
            +
                        end
         | 
| 203 | 
            +
                        raise CliBadArgument,'one file at a time only in HTTP mode' if source_paths.length > 1
         | 
| 204 | 
            +
                        file_name = source_paths.first['source']
         | 
| 205 | 
            +
                        node_file = @api_aoc.resolve_node_file(top_node_file,File.join(source_folder,file_name))
         | 
| 206 | 
            +
                        node_api=@api_aoc.get_node_api(node_file[:node_info],OnCloud::SCOPE_NODE_USER)
         | 
| 207 | 
            +
                        node_api.call({:operation=>'GET',:subpath=>"files/#{node_file[:file_id]}/content",:save_to_file=>File.join(self.transfer.destination_folder('receive'),file_name)})
         | 
| 208 | 
            +
                        return Main.result_status("downloaded: #{file_name}")
         | 
| 209 | 
            +
                      when :v3
         | 
| 210 | 
            +
                        # Note: other "common" actions are unauthorized with user scope
         | 
| 211 | 
            +
                        command_legacy=self.options.get_next_command(Node::SIMPLE_ACTIONS)
         | 
| 212 | 
            +
                        # TODO: shall we support all methods here ? what if there is a link ?
         | 
| 213 | 
            +
                        node_api=@api_aoc.get_node_api(top_node_file[:node_info],OnCloud::SCOPE_NODE_USER)
         | 
| 214 | 
            +
                        return Node.new(@agents.merge(skip_basic_auth_options: true, node_api: node_api)).execute_action(command_legacy)
         | 
| 215 | 
            +
                      when :file
         | 
| 216 | 
            +
                        fileid=self.options.get_next_argument('file id')
         | 
| 217 | 
            +
                        node_file = @api_aoc.resolve_node_file(top_node_file)
         | 
| 218 | 
            +
                        node_api=@api_aoc.get_node_api(node_file[:node_info],OnCloud::SCOPE_NODE_USER)
         | 
| 219 | 
            +
                        items=node_api.read("files/#{fileid}")[:data]
         | 
| 220 | 
            +
                        return {:type=>:single_object,:data=>items}
         | 
| 221 | 
            +
                      when :permissions
         | 
| 222 | 
            +
                        fileid=self.options.get_next_argument('file id')
         | 
| 223 | 
            +
                        node_file = @api_aoc.resolve_node_file(top_node_file)
         | 
| 224 | 
            +
                        node_api=@api_aoc.get_node_api(node_file[:node_info],OnCloud::SCOPE_NODE_USER)
         | 
| 225 | 
            +
                        command_perms=self.options.get_next_command([:show,:create])
         | 
| 226 | 
            +
                        case command_perms
         | 
| 227 | 
            +
                        when :show
         | 
| 228 | 
            +
                          items=node_api.read('permissions',{'include'=>['[]','access_level','permission_count'],'file_id'=>fileid,'inherited'=>false})[:data]
         | 
| 229 | 
            +
                          return {:type=>:object_list,:data=>items}
         | 
| 230 | 
            +
                        when :create
         | 
| 231 | 
            +
                          #value=self.options.get_next_argument('creation value')
         | 
| 232 | 
            +
                          set_workspace_info
         | 
| 233 | 
            +
                          access_id="ASPERA_ACCESS_KEY_ADMIN_WS_#{@workspace_id}"
         | 
| 234 | 
            +
                          node_file[:node_info]
         | 
| 235 | 
            +
                          params={
         | 
| 236 | 
            +
                            "file_id"=>fileid,
         | 
| 237 | 
            +
                            "access_type"=>"user",
         | 
| 238 | 
            +
                            "access_id"=>access_id,
         | 
| 239 | 
            +
                            "access_levels"=>["list","read","write","delete","mkdir","rename","preview"],
         | 
| 240 | 
            +
                            "tags"=>{
         | 
| 241 | 
            +
                            "aspera"=>{
         | 
| 242 | 
            +
                            "files"=>{
         | 
| 243 | 
            +
                            "workspace"=>{
         | 
| 244 | 
            +
                            "id"=>@workspace_id,
         | 
| 245 | 
            +
                            "workspace_name"=>@workspace_name,
         | 
| 246 | 
            +
                            "user_name"=>user_info['name'],
         | 
| 247 | 
            +
                            "shared_by_user_id"=>user_info['id'],
         | 
| 248 | 
            +
                            "shared_by_name"=>user_info['name'],
         | 
| 249 | 
            +
                            "shared_by_email"=>user_info['email'],
         | 
| 250 | 
            +
                            "shared_with_name"=>access_id,
         | 
| 251 | 
            +
                            "access_key"=>node_file[:node_info]['access_key'],
         | 
| 252 | 
            +
                            "node"=>node_file[:node_info]['name']}}}}}
         | 
| 253 | 
            +
                          item=node_api.create('permissions',params)[:data]
         | 
| 254 | 
            +
                          return {:type=>:single_object,:data=>item}
         | 
| 255 | 
            +
                        else raise "error"
         | 
| 256 | 
            +
                        end
         | 
| 257 | 
            +
                      end # command_repo
         | 
| 258 | 
            +
                      throw "ERR"
         | 
| 259 | 
            +
                    end # execute_node_gen4_command
         | 
| 260 | 
            +
             | 
| 261 | 
            +
                    # build constructor option list for OnCloud based on options of CLI
         | 
| 262 | 
            +
                    def oncloud_params(subpath)
         | 
| 263 | 
            +
                      # copy command line options to args
         | 
| 264 | 
            +
                      opt=[:link,:url,:auth,:client_id,:client_secret,:scope,:redirect_uri,:private_key,:username].inject({}){|m,i|m[i]=self.options.get_option(i,:optional);m}
         | 
| 265 | 
            +
                      opt[:subpath]=subpath
         | 
| 266 | 
            +
                      return opt
         | 
| 267 | 
            +
                    end
         | 
| 268 | 
            +
             | 
| 269 | 
            +
                    # Create a new AoC API REST object and set @api_aoc.
         | 
| 270 | 
            +
                    # Parameters based on command line options
         | 
| 271 | 
            +
                    # @return nil
         | 
| 272 | 
            +
                    def update_aoc_api
         | 
| 273 | 
            +
                      @api_aoc=OnCloud.new(oncloud_params('api/v1'))
         | 
| 274 | 
            +
                      # add access key secrets
         | 
| 275 | 
            +
                      @api_aoc.add_secrets(self.config.get_secrets)
         | 
| 276 | 
            +
                      return nil
         | 
| 277 | 
            +
                    end
         | 
| 278 | 
            +
             | 
| 279 | 
            +
                    # initialize apis and authentication
         | 
| 280 | 
            +
                    # set:
         | 
| 281 | 
            +
                    # @default_workspace_id
         | 
| 282 | 
            +
                    # @workspace_name
         | 
| 283 | 
            +
                    # @workspace_id
         | 
| 284 | 
            +
                    # @persist_ids
         | 
| 285 | 
            +
                    # returns nil
         | 
| 286 | 
            +
                    def set_workspace_info
         | 
| 287 | 
            +
                      if @api_aoc.params[:auth].has_key?(:url_token)
         | 
| 288 | 
            +
                        # TODO: can there be several in list ?
         | 
| 289 | 
            +
                        @url_token_data=@api_aoc.read('url_tokens')[:data].first
         | 
| 290 | 
            +
                        @default_workspace_id=@url_token_data['data']['workspace_id']
         | 
| 291 | 
            +
                        @persist_ids=[] # TODO : @url_token_data['id'] ?
         | 
| 292 | 
            +
                      else
         | 
| 293 | 
            +
                        @default_workspace_id=user_info['default_workspace_id']
         | 
| 294 | 
            +
                        @persist_ids=[user_info['id']]
         | 
| 295 | 
            +
                      end
         | 
| 296 | 
            +
             | 
| 297 | 
            +
                      ws_name=self.options.get_option(:workspace,:optional)
         | 
| 298 | 
            +
                      if ws_name.nil?
         | 
| 299 | 
            +
                        Log.log.debug("using default workspace".green)
         | 
| 300 | 
            +
                        if @default_workspace_id.eql?(nil)
         | 
| 301 | 
            +
                          raise CliError,"no default workspace defined for user, please specify workspace"
         | 
| 302 | 
            +
                        end
         | 
| 303 | 
            +
                        # get default workspace
         | 
| 304 | 
            +
                        @workspace_id=@default_workspace_id
         | 
| 305 | 
            +
                      else
         | 
| 306 | 
            +
                        # lookup another workspace
         | 
| 307 | 
            +
                        wss=@api_aoc.read("workspaces",{'q'=>ws_name})[:data]
         | 
| 308 | 
            +
                        wss=wss.select { |i| i['name'].eql?(ws_name) }
         | 
| 309 | 
            +
                        case wss.length
         | 
| 310 | 
            +
                        when 0
         | 
| 311 | 
            +
                          raise CliBadArgument,"no such workspace: #{ws_name}"
         | 
| 312 | 
            +
                        when 1
         | 
| 313 | 
            +
                          @workspace_id=wss.first['id']
         | 
| 314 | 
            +
                        else
         | 
| 315 | 
            +
                          raise "unexpected case"
         | 
| 316 | 
            +
                        end
         | 
| 317 | 
            +
                      end
         | 
| 318 | 
            +
                      @workspace_data=@api_aoc.read("workspaces/#{@workspace_id}")[:data]
         | 
| 319 | 
            +
                      Log.log.debug("workspace_id=#{@workspace_id},@workspace_data=#{@workspace_data}".red)
         | 
| 320 | 
            +
             | 
| 321 | 
            +
                      @workspace_name||=@workspace_data['name']
         | 
| 322 | 
            +
                      Log.log.info("current workspace is "+@workspace_name.red)
         | 
| 323 | 
            +
             | 
| 324 | 
            +
                      # display workspace
         | 
| 325 | 
            +
                      self.format.display_status("Current Workspace: #{@workspace_name.red}#{@workspace_id == @default_workspace_id ? ' (default)' : ''}")
         | 
| 326 | 
            +
                      return nil
         | 
| 327 | 
            +
                    end
         | 
| 328 | 
            +
             | 
| 329 | 
            +
                    # @home_node_file (hash with :node_info and :file_id)
         | 
| 330 | 
            +
                    def set_home_node_file
         | 
| 331 | 
            +
                      if !@url_token_data.nil?
         | 
| 332 | 
            +
                        assert_public_link_types(['view_shared_file'])
         | 
| 333 | 
            +
                        home_node_id=@url_token_data['data']['node_id']
         | 
| 334 | 
            +
                        home_file_id=@url_token_data['data']['file_id']
         | 
| 335 | 
            +
                      end
         | 
| 336 | 
            +
                      home_node_id||=@workspace_data['home_node_id']||@workspace_data['node_id']
         | 
| 337 | 
            +
                      home_file_id||=@workspace_data['home_file_id']
         | 
| 338 | 
            +
                      raise "node_id must be defined" if home_node_id.to_s.empty?
         | 
| 339 | 
            +
                      @home_node_file={
         | 
| 340 | 
            +
                        node_info: @api_aoc.read("nodes/#{home_node_id}")[:data],
         | 
| 341 | 
            +
                        file_id: home_file_id
         | 
| 342 | 
            +
                      }
         | 
| 343 | 
            +
                      @api_aoc.check_get_node_file(@home_node_file)
         | 
| 344 | 
            +
             | 
| 345 | 
            +
                      return nil
         | 
| 346 | 
            +
                    end
         | 
| 347 | 
            +
             | 
| 348 | 
            +
                    def do_bulk_operation(ids_or_one,success_msg,id_result='id',&do_action)
         | 
| 349 | 
            +
                      ids_or_one=[ids_or_one] unless self.options.get_option(:bulk)
         | 
| 350 | 
            +
                      raise "expecting Array" unless ids_or_one.is_a?(Array)
         | 
| 351 | 
            +
                      result_list=[]
         | 
| 352 | 
            +
                      ids_or_one.each do |id|
         | 
| 353 | 
            +
                        one={id_result=>id}
         | 
| 354 | 
            +
                        begin
         | 
| 355 | 
            +
                          res=do_action.call(id)
         | 
| 356 | 
            +
                          one=res if id.is_a?(Hash) # if block returns a has, let's use this
         | 
| 357 | 
            +
                          one['status']=success_msg
         | 
| 358 | 
            +
                        rescue => e
         | 
| 359 | 
            +
                          one['status']=e.to_s
         | 
| 360 | 
            +
                        end
         | 
| 361 | 
            +
                        result_list.push(one)
         | 
| 362 | 
            +
                      end
         | 
| 363 | 
            +
                      return {:type=>:object_list,:data=>result_list,:fields=>[id_result,'status']}
         | 
| 364 | 
            +
                    end
         | 
| 365 | 
            +
             | 
| 366 | 
            +
                    # package creation params can give just email, and full hash is created
         | 
| 367 | 
            +
                    def resolve_package_recipients(package_creation,recipient_list_field)
         | 
| 368 | 
            +
                      return unless package_creation.has_key?(recipient_list_field)
         | 
| 369 | 
            +
                      raise CliBadArgument,"#{recipient_list_field} must be an Array" unless package_creation[recipient_list_field].is_a?(Array)
         | 
| 370 | 
            +
                      new_user_option=self.options.get_option(:new_user_option,:mandatory)
         | 
| 371 | 
            +
                      resolved_list=[]
         | 
| 372 | 
            +
                      package_creation[recipient_list_field].each do |recipient_email_or_info|
         | 
| 373 | 
            +
                        case recipient_email_or_info
         | 
| 374 | 
            +
                        when Hash
         | 
| 375 | 
            +
                          raise 'recipient element hash shall have field id and type' unless recipient_email_or_info.has_key?('id') and recipient_email_or_info.has_key?('type')
         | 
| 376 | 
            +
                          # already provided all information ?
         | 
| 377 | 
            +
                          resolved_list.push(recipient_email_or_info)
         | 
| 378 | 
            +
                        when String
         | 
| 379 | 
            +
                          if recipient_email_or_info.include?('@')
         | 
| 380 | 
            +
                            # or need to resolve email
         | 
| 381 | 
            +
                            item_lookup=@api_aoc.read('contacts',{'current_workspace_id'=>@workspace_id,'q'=>recipient_email_or_info})[:data]
         | 
| 382 | 
            +
                            case item_lookup.length
         | 
| 383 | 
            +
                            when 1; recipient_user_id=item_lookup.first
         | 
| 384 | 
            +
                            when 0; recipient_user_id=@api_aoc.create('contacts',{'current_workspace_id'=>@workspace_id,'email'=>recipient_email_or_info}.merge(new_user_option))[:data]
         | 
| 385 | 
            +
                            else raise CliBadArgument,"multiple match for: #{recipient_email_or_info}"
         | 
| 386 | 
            +
                            end
         | 
| 387 | 
            +
                            resolved_list.push({'id'=>recipient_user_id['source_id'],'type'=>recipient_user_id['source_type']})
         | 
| 388 | 
            +
                          else
         | 
| 389 | 
            +
                            item_lookup=@api_aoc.read('dropboxes',{'current_workspace_id'=>@workspace_id,'q'=>recipient_email_or_info})[:data]
         | 
| 390 | 
            +
                            case item_lookup.length
         | 
| 391 | 
            +
                            when 1; recipient_user_id=item_lookup.first
         | 
| 392 | 
            +
                            when 0; raise "no such shared inbox in workspace #{@workspace_name}"
         | 
| 393 | 
            +
                            else raise CliBadArgument,"multiple match for: #{recipient_email_or_info}"
         | 
| 394 | 
            +
                            end
         | 
| 395 | 
            +
                            resolved_list.push({'id'=>recipient_user_id['id'],'type'=>'dropbox'})
         | 
| 396 | 
            +
                          end
         | 
| 397 | 
            +
                        else
         | 
| 398 | 
            +
                          raise "recipient item must be a String (email, shared inboc) or hash (id,type)"
         | 
| 399 | 
            +
                        end
         | 
| 400 | 
            +
                      end
         | 
| 401 | 
            +
                      package_creation[recipient_list_field]=resolved_list
         | 
| 402 | 
            +
                    end
         | 
| 403 | 
            +
             | 
| 404 | 
            +
                    def url_query(default)
         | 
| 405 | 
            +
                      query=self.options.get_option(:query,:optional)||default
         | 
| 406 | 
            +
                      Log.log.debug("Query=#{query}".bg_red)
         | 
| 407 | 
            +
                      begin
         | 
| 408 | 
            +
                        # check it is suitable
         | 
| 409 | 
            +
                        URI.encode_www_form(query) unless query.nil?
         | 
| 410 | 
            +
                      rescue => e
         | 
| 411 | 
            +
                        raise CliBadArgument,"query must be an extended value which can be encoded with URI.encode_www_form. Refer to manual. (#{e.message})"
         | 
| 412 | 
            +
                      end
         | 
| 413 | 
            +
                      return query
         | 
| 414 | 
            +
                    end
         | 
| 415 | 
            +
             | 
| 416 | 
            +
                    def assert_public_link_types(expected)
         | 
| 417 | 
            +
                      if !expected.include?(@url_token_data['purpose'])
         | 
| 418 | 
            +
                        raise CliBadArgument,"public link type is #{@url_token_data['purpose']} but action requires one of #{expected.join(',')}"
         | 
| 419 | 
            +
                      end
         | 
| 420 | 
            +
                    end
         | 
| 421 | 
            +
             | 
| 422 | 
            +
                    def execute_admin_action
         | 
| 423 | 
            +
                      self.options.set_option(:scope,OnCloud::SCOPE_FILES_ADMIN)
         | 
| 424 | 
            +
                      update_aoc_api
         | 
| 425 | 
            +
                      command_admin=self.options.get_next_command([ :ats, :resource, :usage_reports, :analytics, :subscription, :auth_providers ])
         | 
| 426 | 
            +
                      case command_admin
         | 
| 427 | 
            +
                      when :auth_providers
         | 
| 428 | 
            +
                        command_auth_prov=self.options.get_next_command([ :list, :update ])
         | 
| 429 | 
            +
                        case command_auth_prov
         | 
| 430 | 
            +
                        when :list
         | 
| 431 | 
            +
                          providers=@api_aoc.read('admin/auth_providers')[:data]
         | 
| 432 | 
            +
                          return {:type=>:object_list,:data=>providers}
         | 
| 433 | 
            +
                        when :update
         | 
| 434 | 
            +
                        end
         | 
| 435 | 
            +
                      when :subscription
         | 
| 436 | 
            +
                        org=@api_aoc.read('organization')[:data]
         | 
| 437 | 
            +
                        bss_api=OnCloud.new(oncloud_params('bss/platform'))
         | 
| 438 | 
            +
                        graphql_query="
         | 
| 439 | 
            +
                query ($organization_id: ID!) {
         | 
| 440 | 
            +
                  aoc (organization_id: $organization_id) {
         | 
| 441 | 
            +
                    bssSubscription {
         | 
| 442 | 
            +
                      endDate
         | 
| 443 | 
            +
                      startDate
         | 
| 444 | 
            +
                      termMonths
         | 
| 445 | 
            +
                      plan
         | 
| 446 | 
            +
                      trial
         | 
| 447 | 
            +
                      termType
         | 
| 448 | 
            +
                      instances {
         | 
| 449 | 
            +
                        id
         | 
| 450 | 
            +
                        entitlements {
         | 
| 451 | 
            +
                          maxUsageMb
         | 
| 452 | 
            +
                        }
         | 
| 453 | 
            +
                      }
         | 
| 454 | 
            +
                      additionalStorageVolumeGb
         | 
| 455 | 
            +
                      additionalEgressVolumeGb
         | 
| 456 | 
            +
                      additionalUsers
         | 
| 457 | 
            +
                      term {
         | 
| 458 | 
            +
                        startDate
         | 
| 459 | 
            +
                        endDate
         | 
| 460 | 
            +
                        transferVolumeGb
         | 
| 461 | 
            +
                        egressVolumeGb
         | 
| 462 | 
            +
                        storageVolumeGb
         | 
| 463 | 
            +
                      }
         | 
| 464 | 
            +
                      paygoRate {
         | 
| 465 | 
            +
                        rate
         | 
| 466 | 
            +
                        currency
         | 
| 467 | 
            +
                      }
         | 
| 468 | 
            +
                      aocPlanData {
         | 
| 469 | 
            +
                        tier
         | 
| 470 | 
            +
                        trial
         | 
| 471 | 
            +
                        workspaces { max }
         | 
| 472 | 
            +
                        users {
         | 
| 473 | 
            +
                          planAmount
         | 
| 474 | 
            +
                          max
         | 
| 475 | 
            +
                        }
         | 
| 476 | 
            +
                        samlIntegration
         | 
| 477 | 
            +
                        activity
         | 
| 478 | 
            +
                        sharedInboxes
         | 
| 479 | 
            +
                        uniqueUrls
         | 
| 480 | 
            +
                        support
         | 
| 481 | 
            +
                      }
         | 
| 482 | 
            +
                    }
         | 
| 483 | 
            +
                  }
         | 
| 484 | 
            +
                }
         | 
| 485 | 
            +
              "
         | 
| 486 | 
            +
                        result=bss_api.create('graphql',{'variables'=>{'organization_id'=>org['id']},'query'=>graphql_query})[:data]['data']
         | 
| 487 | 
            +
                        return {:type=>:single_object,:data=>result['aoc']['bssSubscription']}
         | 
| 488 | 
            +
                      when :ats
         | 
| 489 | 
            +
                        ats_api = Rest.new(@api_aoc.params.deep_merge({
         | 
| 490 | 
            +
                          :base_url => @api_aoc.params[:base_url]+'/admin/ats/pub/v1',
         | 
| 491 | 
            +
                          :auth     => {:scope => OnCloud::SCOPE_FILES_ADMIN_USER}
         | 
| 492 | 
            +
                        }))
         | 
| 493 | 
            +
                        return @ats.execute_action_gen(ats_api)
         | 
| 494 | 
            +
                        #          when :search_nodes
         | 
| 495 | 
            +
                        #            query=self.options.get_option(:query,:optional) || '*'
         | 
| 496 | 
            +
                        #            nodes=@api_aoc.read("search_nodes",{'q'=>query})[:data]
         | 
| 497 | 
            +
                        #            # simplify output
         | 
| 498 | 
            +
                        #            nodes=nodes.map do |i|
         | 
| 499 | 
            +
                        #              item=i['_source']
         | 
| 500 | 
            +
                        #              item['score']=i['_score']
         | 
| 501 | 
            +
                        #              nodedata=item['access_key_recursive_counts'].first
         | 
| 502 | 
            +
                        #              item.delete('access_key_recursive_counts')
         | 
| 503 | 
            +
                        #              item['node']=nodedata
         | 
| 504 | 
            +
                        #              item
         | 
| 505 | 
            +
                        #            end
         | 
| 506 | 
            +
                        #            return {:type=>:object_list,:data=>nodes,:fields=>['host_name','node_status.cluster_id','node_status.node_id']}
         | 
| 507 | 
            +
                      when :analytics
         | 
| 508 | 
            +
                        analytics_api = Rest.new(@api_aoc.params.deep_merge({
         | 
| 509 | 
            +
                          :base_url => @api_aoc.params[:base_url].gsub('/api/v1','')+'/analytics/v2',
         | 
| 510 | 
            +
                          :auth     => {:scope => OnCloud::SCOPE_FILES_ADMIN_USER}
         | 
| 511 | 
            +
                        }))
         | 
| 512 | 
            +
                        command_analytics=self.options.get_next_command([ :application_events, :transfers ])
         | 
| 513 | 
            +
                        case command_analytics
         | 
| 514 | 
            +
                        when :application_events
         | 
| 515 | 
            +
                          event_type=command_analytics.to_s
         | 
| 516 | 
            +
                          events=analytics_api.read("organizations/#{user_info['organization_id']}/#{event_type}")[:data][event_type]
         | 
| 517 | 
            +
                          return {:type=>:object_list,:data=>events}
         | 
| 518 | 
            +
                        when :transfers
         | 
| 519 | 
            +
                          event_type=command_analytics.to_s
         | 
| 520 | 
            +
                          filter_resource=self.options.get_option(:name,:optional) || 'organizations'
         | 
| 521 | 
            +
                          filter_id=self.options.get_option(:id,:optional) || case filter_resource
         | 
| 522 | 
            +
                          when 'organizations'; user_info['organization_id']
         | 
| 523 | 
            +
                          when 'users'; user_info['id']
         | 
| 524 | 
            +
                          when 'nodes'; user_info['id']
         | 
| 525 | 
            +
                          else raise "organizations or users for option --name"
         | 
| 526 | 
            +
                          end
         | 
| 527 | 
            +
                          #
         | 
| 528 | 
            +
                          filter=self.options.get_option(:query,:optional) || {}
         | 
| 529 | 
            +
                          filter['limit']||=100
         | 
| 530 | 
            +
                          if self.options.get_option(:once_only,:mandatory)
         | 
| 531 | 
            +
                            saved_date=[]
         | 
| 532 | 
            +
                            startdate_persistency=PersistencyActionOnce.new(
         | 
| 533 | 
            +
                            manager: @agents[:persistency],
         | 
| 534 | 
            +
                            data: saved_date,
         | 
| 535 | 
            +
                            ids:  ['aoc_ana_date',self.options.get_option(:url,:mandatory),@workspace_name].push(filter_resource,filter_id))
         | 
| 536 | 
            +
                            start_datetime=saved_date.first
         | 
| 537 | 
            +
                            stop_datetime=Time.now.utc.strftime('%FT%T.%LZ')
         | 
| 538 | 
            +
                            #Log.log().error("start: #{start_datetime}")
         | 
| 539 | 
            +
                            #Log.log().error("end:   #{stop_datetime}")
         | 
| 540 | 
            +
                            saved_date[0]=stop_datetime
         | 
| 541 | 
            +
                            filter['start_time'] = start_datetime unless start_datetime.nil?
         | 
| 542 | 
            +
                            filter['stop_time'] = stop_datetime
         | 
| 543 | 
            +
                          end
         | 
| 544 | 
            +
                          notification=self.options.get_option(:notify,:optional)
         | 
| 545 | 
            +
                          events=analytics_api.read("#{filter_resource}/#{filter_id}/#{event_type}",url_query(filter))[:data][event_type]
         | 
| 546 | 
            +
                          startdate_persistency.save unless startdate_persistency.nil?
         | 
| 547 | 
            +
                          if !notification.nil?
         | 
| 548 | 
            +
                            require 'erb'
         | 
| 549 | 
            +
                            events.each do |transfer|
         | 
| 550 | 
            +
                              email_to_send={}
         | 
| 551 | 
            +
                              notification.each do |k,v|
         | 
| 552 | 
            +
                                email_to_send[k.to_sym]=ERB.new(v).result(binding)
         | 
| 553 | 
            +
                              end
         | 
| 554 | 
            +
                              Log.log().error("send email:   #{email_to_send}")
         | 
| 555 | 
            +
                              self.config.send_email(email_to_send)
         | 
| 556 | 
            +
                            end
         | 
| 557 | 
            +
                          end
         | 
| 558 | 
            +
                          return {:type=>:object_list,:data=>events}
         | 
| 559 | 
            +
                        end
         | 
| 560 | 
            +
                      when :resource
         | 
| 561 | 
            +
                        resource_type=self.options.get_next_argument('resource',[:self,:organization,:user,:group,:client,:contact,:dropbox,:node,:operation,:package,:saml_configuration, :workspace, :dropbox_membership,:short_link,:workspace_membership,'admin/apps_new'.to_sym,'admin/client_registration_token'.to_sym,'integrations/kms_profile'.to_sym])
         | 
| 562 | 
            +
                        resource_class_path=resource_type.to_s+case resource_type;when :dropbox;'es';when :self,:organization,'admin/apps_new'.to_sym;'';else; 's';end
         | 
| 563 | 
            +
                        singleton_object=[:self,:organization].include?(resource_type)
         | 
| 564 | 
            +
                        global_operations=[:create,:list]
         | 
| 565 | 
            +
                        supported_operations=[:show,:modify]
         | 
| 566 | 
            +
                        supported_operations.push(:delete,*global_operations) unless singleton_object
         | 
| 567 | 
            +
                        supported_operations.push(:v4,:v3) if resource_type.eql?(:node)
         | 
| 568 | 
            +
                        supported_operations.push(:set_pub_key) if resource_type.eql?(:client)
         | 
| 569 | 
            +
                        supported_operations.push(:shared_folders) if [:node,:workspace].include?(resource_type)
         | 
| 570 | 
            +
                        command=self.options.get_next_command(supported_operations)
         | 
| 571 | 
            +
             | 
| 572 | 
            +
                        # require identifier for non global commands
         | 
| 573 | 
            +
                        if !singleton_object and !global_operations.include?(command)
         | 
| 574 | 
            +
                          res_id=self.options.get_option(:id)
         | 
| 575 | 
            +
                          res_name=self.options.get_option(:name)
         | 
| 576 | 
            +
                          if res_id.nil? and res_name.nil? and resource_type.eql?(:node)
         | 
| 577 | 
            +
                            set_workspace_info
         | 
| 578 | 
            +
                            set_home_node_file
         | 
| 579 | 
            +
                            res_id=@home_node_file[:node_info]['id']
         | 
| 580 | 
            +
                          end
         | 
| 581 | 
            +
                          if !res_name.nil?
         | 
| 582 | 
            +
                            Log.log.warn("name overrides id") unless res_id.nil?
         | 
| 583 | 
            +
                            matching=@api_aoc.read(resource_class_path,{:q=>res_name})[:data]
         | 
| 584 | 
            +
                            raise CliError,"no resource match name" if matching.empty?
         | 
| 585 | 
            +
                            raise CliError,"several resources match name (#{matching.join(',')})" unless matching.length.eql?(1)
         | 
| 586 | 
            +
                            res_id=matching.first['id']
         | 
| 587 | 
            +
                          end
         | 
| 588 | 
            +
                          raise CliBadArgument,"provide either id or name" if res_id.nil?
         | 
| 589 | 
            +
                          resource_instance_path="#{resource_class_path}/#{res_id}"
         | 
| 590 | 
            +
                        end
         | 
| 591 | 
            +
                        resource_instance_path=resource_class_path if singleton_object
         | 
| 592 | 
            +
                        case command
         | 
| 593 | 
            +
                        when :create
         | 
| 594 | 
            +
                          id_result='id'
         | 
| 595 | 
            +
                          id_result='token' if resource_class_path.eql?('admin/client_registration_tokens')
         | 
| 596 | 
            +
                          # TODO: report inconsistency: creation url is !=, and does not return id.
         | 
| 597 | 
            +
                          resource_class_path='admin/client_registration/token' if resource_class_path.eql?('admin/client_registration_tokens')
         | 
| 598 | 
            +
                          list_or_one=self.options.get_next_argument("creation data (Hash)")
         | 
| 599 | 
            +
                          return do_bulk_operation(list_or_one,'created',id_result)do|params|
         | 
| 600 | 
            +
                            raise "expecting Hash" unless params.is_a?(Hash)
         | 
| 601 | 
            +
                            @api_aoc.create(resource_class_path,params)[:data]
         | 
| 602 | 
            +
                          end
         | 
| 603 | 
            +
                        when :list
         | 
| 604 | 
            +
                          default_fields=['id','name']
         | 
| 605 | 
            +
                          list_query=nil
         | 
| 606 | 
            +
                          case resource_type
         | 
| 607 | 
            +
                          when :node; default_fields.push('host','access_key')
         | 
| 608 | 
            +
                          when :operation; default_fields=nil
         | 
| 609 | 
            +
                          when :contact; default_fields=["email","name","source_id","source_type"]
         | 
| 610 | 
            +
                          when 'admin/apps_new'.to_sym; list_query={:organization_apps=>true};default_fields=['app_type','available']
         | 
| 611 | 
            +
                          when 'admin/client_registration_token'.to_sym; default_fields=['id','value','data.client_subject_scopes','created_at']
         | 
| 612 | 
            +
                          end
         | 
| 613 | 
            +
                          result=@api_aoc.read(resource_class_path,url_query(list_query))
         | 
| 614 | 
            +
                          self.format.display_status("Items: #{result[:data].length}/#{result[:http]['X-Total-Count']}")
         | 
| 615 | 
            +
                          return {:type=>:object_list,:data=>result[:data],:fields=>default_fields}
         | 
| 616 | 
            +
                        when :show
         | 
| 617 | 
            +
                          object=@api_aoc.read(resource_instance_path)[:data]
         | 
| 618 | 
            +
                          fields=object.keys.select{|k|!k.eql?('certificate')}
         | 
| 619 | 
            +
                          return { :type=>:single_object, :data =>object, :fields=>fields }
         | 
| 620 | 
            +
                        when :modify
         | 
| 621 | 
            +
                          changes=self.options.get_next_argument('modified parameters (hash)')
         | 
| 622 | 
            +
                          @api_aoc.update(resource_instance_path,changes)
         | 
| 623 | 
            +
                          return Main.result_status('modified')
         | 
| 624 | 
            +
                        when :delete
         | 
| 625 | 
            +
                          return do_bulk_operation(res_id,'deleted')do|one_id|
         | 
| 626 | 
            +
                            @api_aoc.delete("#{resource_class_path}/#{one_id.to_s}")
         | 
| 627 | 
            +
                            {'id'=>one_id}
         | 
| 628 | 
            +
                          end
         | 
| 629 | 
            +
                        when :set_pub_key
         | 
| 630 | 
            +
                          # special : reads private and generate public
         | 
| 631 | 
            +
                          the_private_key=self.options.get_next_argument('private_key')
         | 
| 632 | 
            +
                          the_public_key=OpenSSL::PKey::RSA.new(the_private_key).public_key.to_s
         | 
| 633 | 
            +
                          @api_aoc.update(resource_instance_path,{:jwt_grant_enabled=>true, :public_key=>the_public_key})
         | 
| 634 | 
            +
                          return Main.result_success
         | 
| 635 | 
            +
                        when :v3,:v4
         | 
| 636 | 
            +
                          res_data=@api_aoc.read(resource_instance_path)[:data]
         | 
| 637 | 
            +
                          find_ak_secret(res_data['access_key'])
         | 
| 638 | 
            +
                          api_node=@api_aoc.get_node_api(res_data)
         | 
| 639 | 
            +
                          return Node.new(@agents.merge(skip_basic_auth_options: true, node_api: api_node)).execute_action if command.eql?(:v3)
         | 
| 640 | 
            +
                          ak_data=api_node.call({:operation=>'GET',:subpath=>"access_keys/#{res_data['access_key']}",:headers=>{'Accept'=>'application/json'}})[:data]
         | 
| 641 | 
            +
                          return node_gen4_execute_action({node_info: res_data, file_id: ak_data['root_file_id']})
         | 
| 642 | 
            +
                          #            when :info
         | 
| 643 | 
            +
                          #              object=@api_aoc.read(resource_instance_path)[:data]
         | 
| 644 | 
            +
                          #              access_key=object['access_key']
         | 
| 645 | 
            +
                          #              match_list=@api_aoc.read('admin/search_nodes',{:q=>"access_key:\"#{access_key}\""})[:data]
         | 
| 646 | 
            +
                          #              result=match_list.select{|i|i["_source"]["access_key_recursive_counts"].first["access_key"].eql?(access_key)}
         | 
| 647 | 
            +
                          #              return Main.result_status('Private node') if result.empty?
         | 
| 648 | 
            +
                          #              raise CliError,"more than one match" unless result.length.eql?(1)
         | 
| 649 | 
            +
                          #              result=result.first["_source"]
         | 
| 650 | 
            +
                          #              result.merge!(result['access_key_recursive_counts'].first)
         | 
| 651 | 
            +
                          #              result.delete('access_key_recursive_counts')
         | 
| 652 | 
            +
                          #              result.delete('token')
         | 
| 653 | 
            +
                          #              return { :type=>:single_object, :data =>result}
         | 
| 654 | 
            +
                        when :shared_folders
         | 
| 655 | 
            +
                          read_params = case resource_type
         | 
| 656 | 
            +
                          when :workspace;{'access_id'=>"ASPERA_ACCESS_KEY_ADMIN_WS_#{res_id}",'access_type'=>'user'}
         | 
| 657 | 
            +
                          when :node;{'include'=>['[]','access_level','permission_count'],'created_by_id'=>"ASPERA_ACCESS_KEY_ADMIN"}
         | 
| 658 | 
            +
                          else raise "error"
         | 
| 659 | 
            +
                          end
         | 
| 660 | 
            +
                          res_data=@api_aoc.read("#{resource_class_path}/#{res_id}/permissions",read_params)[:data]
         | 
| 661 | 
            +
                          fields=case resource_type
         | 
| 662 | 
            +
                          when :node;['id','file_id','file.path','access_type']
         | 
| 663 | 
            +
                          when :workspace;['id','node_id','file_id','node_name','file.path','tags.aspera.files.workspace.share_as']
         | 
| 664 | 
            +
                          else raise "error"
         | 
| 665 | 
            +
                          end
         | 
| 666 | 
            +
                          return { :type=>:object_list, :data =>res_data , :fields=>fields}
         | 
| 667 | 
            +
                        else raise :ERROR
         | 
| 668 | 
            +
                        end
         | 
| 669 | 
            +
                      when :usage_reports
         | 
| 670 | 
            +
                        return {:type=>:object_list,:data=>@api_aoc.read("usage_reports",{:workspace_id=>@workspace_id})[:data]}
         | 
| 671 | 
            +
                      end
         | 
| 672 | 
            +
                    end
         | 
| 673 | 
            +
             | 
| 674 | 
            +
                    ACTIONS=[ :apiinfo, :bearer_token, :organization, :tier_restrictions, :user, :workspace, :packages, :files, :gateway, :admin, :automation, :servers]
         | 
| 675 | 
            +
             | 
| 676 | 
            +
                    def execute_action
         | 
| 677 | 
            +
                      command=self.options.get_next_command(ACTIONS)
         | 
| 678 | 
            +
                      case command
         | 
| 679 | 
            +
                      when :apiinfo
         | 
| 680 | 
            +
                        api_info={}
         | 
| 681 | 
            +
                        num=1
         | 
| 682 | 
            +
                        Resolv::DNS.open{|dns|dns.each_address('api.ibmaspera.com'){|a| api_info["api.#{num}"]=a;num+=1}}
         | 
| 683 | 
            +
                        return {:type=>:single_object,:data=>api_info}
         | 
| 684 | 
            +
                      when :bearer_token
         | 
| 685 | 
            +
                        return {:type=>:text,:data=>@api_aoc.oauth_token}
         | 
| 686 | 
            +
                      when :organization
         | 
| 687 | 
            +
                        return { :type=>:single_object, :data =>@api_aoc.read('organization')[:data] }
         | 
| 688 | 
            +
                      when :tier_restrictions
         | 
| 689 | 
            +
                        return { :type=>:single_object, :data =>@api_aoc.read('tier_restrictions')[:data] }
         | 
| 690 | 
            +
                      when :user
         | 
| 691 | 
            +
                        command=self.options.get_next_command([ :workspaces,:info,:shared_inboxes ])
         | 
| 692 | 
            +
                        case command
         | 
| 693 | 
            +
                        when :workspaces
         | 
| 694 | 
            +
                          return {:type=>:object_list,:data=>@api_aoc.read("workspaces")[:data],:fields=>['id','name']}
         | 
| 695 | 
            +
                          #              when :settings
         | 
| 696 | 
            +
                          #                return {:type=>:object_list,:data=>@api_aoc.read("client_settings/")[:data]}
         | 
| 697 | 
            +
                        when :shared_inboxes
         | 
| 698 | 
            +
                          query=url_query(nil)
         | 
| 699 | 
            +
                          if query.nil?
         | 
| 700 | 
            +
                            set_workspace_info
         | 
| 701 | 
            +
                            query={'embed[]'=>'dropbox','workspace_id'=>@workspace_id,'aggregate_permissions_by_dropbox'=>true,'sort'=>'dropbox_name'}
         | 
| 702 | 
            +
                          end
         | 
| 703 | 
            +
                          return {:type=>:object_list,:data=>@api_aoc.read("dropbox_memberships",query)[:data],:fields=>['dropbox_id','dropbox.name']}
         | 
| 704 | 
            +
                        when :info
         | 
| 705 | 
            +
                          command=self.options.get_next_command([ :show,:modify ])
         | 
| 706 | 
            +
                          case command
         | 
| 707 | 
            +
                          when :show
         | 
| 708 | 
            +
                            return { :type=>:single_object, :data =>user_info }
         | 
| 709 | 
            +
                          when :modify
         | 
| 710 | 
            +
                            @api_aoc.update("users/#{user_info['id']}",self.options.get_next_argument('modified parameters (hash)'))
         | 
| 711 | 
            +
                            return Main.result_status('modified')
         | 
| 712 | 
            +
                          end
         | 
| 713 | 
            +
                        end
         | 
| 714 | 
            +
                      when :workspace # show current workspace parameters
         | 
| 715 | 
            +
                        set_workspace_info
         | 
| 716 | 
            +
                        return { :type=>:single_object, :data =>@workspace_data }
         | 
| 717 | 
            +
                      when :packages
         | 
| 718 | 
            +
                        set_workspace_info if @url_token_data.nil?
         | 
| 719 | 
            +
                        command_pkg=self.options.get_next_command([ :send, :recv, :list, :show, :delete ])
         | 
| 720 | 
            +
                        case command_pkg
         | 
| 721 | 
            +
                        when :send
         | 
| 722 | 
            +
                          package_creation=self.options.get_option(:value,:mandatory)
         | 
| 723 | 
            +
                          raise CliBadArgument,"value must be hash, refer to doc" unless package_creation.is_a?(Hash)
         | 
| 724 | 
            +
             | 
| 725 | 
            +
                          if !@url_token_data.nil?
         | 
| 726 | 
            +
                            assert_public_link_types(['send_package_to_user','send_package_to_dropbox'])
         | 
| 727 | 
            +
                            box_type=@url_token_data['purpose'].split('_').last
         | 
| 728 | 
            +
                            package_creation['recipients']=[{'id'=>@url_token_data['data']["#{box_type}_id"],'type'=>box_type}]
         | 
| 729 | 
            +
                            @workspace_id=@url_token_data['data']['workspace_id']
         | 
| 730 | 
            +
                          end
         | 
| 731 | 
            +
             | 
| 732 | 
            +
                          package_creation['workspace_id']=@workspace_id
         | 
| 733 | 
            +
             | 
| 734 | 
            +
                          # list of files to include in package, optional
         | 
| 735 | 
            +
                          #package_creation['file_names']=self.transfer.ts_source_paths.map{|i|File.basename(i['source'])}
         | 
| 736 | 
            +
             | 
| 737 | 
            +
                          # lookup users
         | 
| 738 | 
            +
                          resolve_package_recipients(package_creation,'recipients')
         | 
| 739 | 
            +
                          resolve_package_recipients(package_creation,'bcc_recipients')
         | 
| 740 | 
            +
             | 
| 741 | 
            +
                          #  create a new package with one file
         | 
| 742 | 
            +
                          package_info=@api_aoc.create('packages',package_creation)[:data]
         | 
| 743 | 
            +
             | 
| 744 | 
            +
                          #  get node information for the node on which package must be created
         | 
| 745 | 
            +
                          node_info=@api_aoc.read("nodes/#{package_info['node_id']}")[:data]
         | 
| 746 | 
            +
             | 
| 747 | 
            +
                          # tell Aspera what to expect in package: 1 transfer (can also be done after transfer)
         | 
| 748 | 
            +
                          @api_aoc.update("packages/#{package_info['id']}",{'sent'=>true,'transfers_expected'=>1})[:data]
         | 
| 749 | 
            +
             | 
| 750 | 
            +
                          # execute transfer
         | 
| 751 | 
            +
                          node_file = {node_info: node_info, file_id: package_info['contents_file_id']}
         | 
| 752 | 
            +
                          # raise esception if at least one error
         | 
| 753 | 
            +
                          Main.result_transfer(transfer_start(OnCloud::PACKAGES_APP,'send',node_file,OnCloud.package_tags(package_info,'upload')))
         | 
| 754 | 
            +
                          # return all info on package
         | 
| 755 | 
            +
                          return { :type=>:single_object, :data =>package_info}
         | 
| 756 | 
            +
                        when :recv
         | 
| 757 | 
            +
                          if !@url_token_data.nil?
         | 
| 758 | 
            +
                            assert_public_link_types(['view_received_package'])
         | 
| 759 | 
            +
                            self.options.set_option(:id,@url_token_data['data']['package_id'])
         | 
| 760 | 
            +
                          end
         | 
| 761 | 
            +
                          # scalar here
         | 
| 762 | 
            +
                          ids_to_download=self.options.get_option(:id,:mandatory)
         | 
| 763 | 
            +
                          skip_ids_data=[]
         | 
| 764 | 
            +
                          skip_ids_persistency=nil
         | 
| 765 | 
            +
                          if self.options.get_option(:once_only,:mandatory)
         | 
| 766 | 
            +
                            skip_ids_persistency=PersistencyActionOnce.new(
         | 
| 767 | 
            +
                            manager: @agents[:persistency],
         | 
| 768 | 
            +
                            data: skip_ids_data,
         | 
| 769 | 
            +
                            ids:  ['aoc_recv',self.options.get_option(:url,:mandatory),@workspace_id].push(*@persist_ids))
         | 
| 770 | 
            +
                          end
         | 
| 771 | 
            +
                          if ids_to_download.eql?(VAL_ALL)
         | 
| 772 | 
            +
                            # get list of packages in inbox
         | 
| 773 | 
            +
                            package_info=@api_aoc.read('packages',{'archived'=>false,'exclude_dropbox_packages'=>true,'has_content'=>true,'received'=>true,'workspace_id'=>@workspace_id})[:data]
         | 
| 774 | 
            +
                            # remove from list the ones already downloaded
         | 
| 775 | 
            +
                            ids_to_download=package_info.map{|e|e['id']}
         | 
| 776 | 
            +
                            # array here
         | 
| 777 | 
            +
                            ids_to_download.select!{|id|!skip_ids_data.include?(id)}
         | 
| 778 | 
            +
                          end # ALL
         | 
| 779 | 
            +
                          # list here
         | 
| 780 | 
            +
                          ids_to_download = [ids_to_download] unless ids_to_download.is_a?(Array)
         | 
| 781 | 
            +
                          result_transfer=[]
         | 
| 782 | 
            +
                          self.format.display_status("found #{ids_to_download.length} package(s).")
         | 
| 783 | 
            +
                          ids_to_download.each do |package_id|
         | 
| 784 | 
            +
                            package_info=@api_aoc.read("packages/#{package_id}")[:data]
         | 
| 785 | 
            +
                            node_info=@api_aoc.read("nodes/#{package_info['node_id']}")[:data]
         | 
| 786 | 
            +
                            self.format.display_status("downloading package: #{package_info['name']}")
         | 
| 787 | 
            +
                            add_ts={'paths'=>[{'source'=>'.'}]}
         | 
| 788 | 
            +
                            node_file = {node_info: node_info, file_id: package_info['contents_file_id']}
         | 
| 789 | 
            +
                            statuses=transfer_start(OnCloud::PACKAGES_APP,'receive',node_file,OnCloud.package_tags(package_info,'download').merge(add_ts))
         | 
| 790 | 
            +
                            result_transfer.push({'package'=>package_id,'status'=>statuses.map{|i|i.to_s}.join(',')})
         | 
| 791 | 
            +
                            # update skip list only if all transfer sessions completed
         | 
| 792 | 
            +
                            if TransferAgent.session_status(statuses).eql?(:success)
         | 
| 793 | 
            +
                              skip_ids_data.push(package_id)
         | 
| 794 | 
            +
                              skip_ids_persistency.save unless skip_ids_persistency.nil?
         | 
| 795 | 
            +
                            end
         | 
| 796 | 
            +
                          end
         | 
| 797 | 
            +
                          return {:type=>:object_list,:data=>result_transfer}
         | 
| 798 | 
            +
                        when :show
         | 
| 799 | 
            +
                          package_id=self.options.get_next_argument('package ID')
         | 
| 800 | 
            +
                          package_info=@api_aoc.read("packages/#{package_id}")[:data]
         | 
| 801 | 
            +
                          return { :type=>:single_object, :data =>package_info }
         | 
| 802 | 
            +
                        when :list
         | 
| 803 | 
            +
                          # list all packages ('page'=>1,'per_page'=>10,)'sort'=>'-sent_at',
         | 
| 804 | 
            +
                          packages=@api_aoc.read("packages",{'archived'=>false,'exclude_dropbox_packages'=>true,'has_content'=>true,'received'=>true,'workspace_id'=>@workspace_id})[:data]
         | 
| 805 | 
            +
                          return {:type=>:object_list,:data=>packages,:fields=>['id','name','bytes_transferred']}
         | 
| 806 | 
            +
                        when :delete
         | 
| 807 | 
            +
                          list_or_one=self.options.get_option(:id,:mandatory)
         | 
| 808 | 
            +
                          return do_bulk_operation(list_or_one,'deleted')do|id|
         | 
| 809 | 
            +
                            raise "expecting String identifier" unless id.is_a?(String) or id.is_a?(Integer)
         | 
| 810 | 
            +
                            @api_aoc.delete("packages/#{id}")[:data]
         | 
| 811 | 
            +
                          end
         | 
| 812 | 
            +
                        end
         | 
| 813 | 
            +
                      when :files
         | 
| 814 | 
            +
                        # get workspace related information
         | 
| 815 | 
            +
                        set_workspace_info
         | 
| 816 | 
            +
                        set_home_node_file
         | 
| 817 | 
            +
                        find_ak_secret(@home_node_file[:node_info]['access_key'],false)
         | 
| 818 | 
            +
                        command_repo=self.options.get_next_command(NODE4_COMMANDS.clone.concat([:short_link]))
         | 
| 819 | 
            +
                        case command_repo
         | 
| 820 | 
            +
                        when *NODE4_COMMANDS; return execute_node_gen4_command(command_repo,@home_node_file)
         | 
| 821 | 
            +
                        when :short_link
         | 
| 822 | 
            +
                          folder_dest=self.options.get_option(:to_folder,:optional)
         | 
| 823 | 
            +
                          value_option=self.options.get_option(:value,:optional)
         | 
| 824 | 
            +
                          case value_option
         | 
| 825 | 
            +
                          when 'public'
         | 
| 826 | 
            +
                            value_option={'purpose'=>'token_auth_redirection'}
         | 
| 827 | 
            +
                          when 'private'
         | 
| 828 | 
            +
                            value_option={'purpose'=>'shared_folder_auth_link'}
         | 
| 829 | 
            +
                          when NilClass,Hash
         | 
| 830 | 
            +
                          else raise "value must be either: public, private, Hash or nil"
         | 
| 831 | 
            +
                          end
         | 
| 832 | 
            +
                          create_params=nil
         | 
| 833 | 
            +
                          node_file=nil
         | 
| 834 | 
            +
                          if !folder_dest.nil?
         | 
| 835 | 
            +
                            node_file = @api_aoc.resolve_node_file(@home_node_file,folder_dest)
         | 
| 836 | 
            +
                            create_params={
         | 
| 837 | 
            +
                              file_id: node_file[:file_id],
         | 
| 838 | 
            +
                              node_id: node_file[:node_info]['id'],
         | 
| 839 | 
            +
                              workspace_id: @workspace_id
         | 
| 840 | 
            +
                            }
         | 
| 841 | 
            +
                          end
         | 
| 842 | 
            +
                          if !value_option.nil? and !create_params.nil?
         | 
| 843 | 
            +
                            case value_option['purpose']
         | 
| 844 | 
            +
                            when 'shared_folder_auth_link'
         | 
| 845 | 
            +
                              value_option['data']=create_params
         | 
| 846 | 
            +
                              value_option['user_selected_name']=nil
         | 
| 847 | 
            +
                            when 'token_auth_redirection'
         | 
| 848 | 
            +
                              create_params['name']=''
         | 
| 849 | 
            +
                              value_option['data']={
         | 
| 850 | 
            +
                                aoc: true,
         | 
| 851 | 
            +
                                url_token_data: {
         | 
| 852 | 
            +
                                data: create_params,
         | 
| 853 | 
            +
                                purpose: 'view_shared_file'
         | 
| 854 | 
            +
                                }
         | 
| 855 | 
            +
                              }
         | 
| 856 | 
            +
                              value_option['user_selected_name']=nil
         | 
| 857 | 
            +
                            else
         | 
| 858 | 
            +
                              raise "purpose must be one of: token_auth_redirection or shared_folder_auth_link"
         | 
| 859 | 
            +
                            end
         | 
| 860 | 
            +
                            self.options.set_option(:value,value_option)
         | 
| 861 | 
            +
                          end
         | 
| 862 | 
            +
                          result=self.entity_action(@api_aoc,'short_links',nil,:id,'self')
         | 
| 863 | 
            +
                          if result[:data].is_a?(Hash) and result[:data].has_key?('created_at') and result[:data]['resource_type'].eql?('UrlToken')
         | 
| 864 | 
            +
                            node_api=@api_aoc.get_node_api(node_file[:node_info],OnCloud::SCOPE_NODE_USER)
         | 
| 865 | 
            +
                            perm_data={
         | 
| 866 | 
            +
                              "file_id"      =>node_file[:file_id],
         | 
| 867 | 
            +
                              "access_type"  =>"user",
         | 
| 868 | 
            +
                              "access_id"    =>result[:data]['resource_id'],
         | 
| 869 | 
            +
                              "access_levels"=>["delete","list","mkdir","preview","read","rename","write"],
         | 
| 870 | 
            +
                              "tags"         =>{
         | 
| 871 | 
            +
                              "url_token"       =>true,
         | 
| 872 | 
            +
                              "workspace_id"    =>@workspace_id,
         | 
| 873 | 
            +
                              "workspace_name"  =>@workspace_name,
         | 
| 874 | 
            +
                              "folder_name"     =>"my folder",
         | 
| 875 | 
            +
                              "created_by_name" =>user_info['name'],
         | 
| 876 | 
            +
                              "created_by_email"=>user_info['email'],
         | 
| 877 | 
            +
                              "access_key"      =>node_file[:node_info]['access_key'],
         | 
| 878 | 
            +
                              "node"            =>node_file[:node_info]['host']
         | 
| 879 | 
            +
                              }
         | 
| 880 | 
            +
                            }
         | 
| 881 | 
            +
                            node_api.create("permissions?file_id=#{node_file[:file_id]}",perm_data)
         | 
| 882 | 
            +
                          end
         | 
| 883 | 
            +
                          return result
         | 
| 884 | 
            +
                        end # files command
         | 
| 885 | 
            +
                        throw "Error: shall not reach this line"
         | 
| 886 | 
            +
                      when :automation
         | 
| 887 | 
            +
                        Log.log.warn("BETA: work under progress")
         | 
| 888 | 
            +
                        # automation api is not in the same place
         | 
| 889 | 
            +
                        automation_rest_params=@api_aoc.params.clone
         | 
| 890 | 
            +
                        automation_rest_params[:base_url].gsub!('/api/','/automation/')
         | 
| 891 | 
            +
                        automation_api=Rest.new(automation_rest_params)
         | 
| 892 | 
            +
                        command_automation=self.options.get_next_command([ :workflows, :instances ])
         | 
| 893 | 
            +
                        case command_automation
         | 
| 894 | 
            +
                        when :instances
         | 
| 895 | 
            +
                          return self.entity_action(@api_aoc,'workflow_instances',nil,:id,nil)
         | 
| 896 | 
            +
                        when :workflows
         | 
| 897 | 
            +
                          wF_COMMANDS=Plugin::ALL_OPS.clone.push(:action,:launch)
         | 
| 898 | 
            +
                          wf_command=self.options.get_next_command(wF_COMMANDS)
         | 
| 899 | 
            +
                          case wf_command
         | 
| 900 | 
            +
                          when *Plugin::ALL_OPS
         | 
| 901 | 
            +
                            return self.entity_command(wf_command,automation_api,'workflows',nil,:id)
         | 
| 902 | 
            +
                          when :launch
         | 
| 903 | 
            +
                            wf_id=self.options.get_option(:id,:mandatory)
         | 
| 904 | 
            +
                            data=automation_api.create("workflows/#{wf_id}/launch",{})[:data]
         | 
| 905 | 
            +
                            return {:type=>:single_object,:data=>data}
         | 
| 906 | 
            +
                          when :action
         | 
| 907 | 
            +
                            wf_command=self.options.get_next_command([:list,:create,:show])
         | 
| 908 | 
            +
                            wf_id=self.options.get_option(:id,:mandatory)
         | 
| 909 | 
            +
                            step=automation_api.create('steps',{'workflow_id'=>wf_id})[:data]
         | 
| 910 | 
            +
                            automation_api.update("workflows/#{wf_id}",{'step_order'=>[step["id"]]})
         | 
| 911 | 
            +
                            action=automation_api.create('actions',{'step_id'=>step["id"],'type'=>'manual'})[:data]
         | 
| 912 | 
            +
                            automation_api.update("steps/#{step["id"]}",{'action_order'=>[action["id"]]})
         | 
| 913 | 
            +
                            wf=automation_api.read("workflows/#{wf_id}")[:data]
         | 
| 914 | 
            +
                            return {:type=>:single_object,:data=>wf}
         | 
| 915 | 
            +
                          end
         | 
| 916 | 
            +
                        end
         | 
| 917 | 
            +
                      when :gateway
         | 
| 918 | 
            +
                        set_workspace_info
         | 
| 919 | 
            +
                        require 'aspera/faspex_gw'
         | 
| 920 | 
            +
                        FaspexGW.new(@api_aoc,@workspace_id).start_server
         | 
| 921 | 
            +
                      when :admin
         | 
| 922 | 
            +
                        return execute_admin_action
         | 
| 923 | 
            +
                      when :servers
         | 
| 924 | 
            +
                        self.format.display_status("Beta feature")
         | 
| 925 | 
            +
                        server_api=Rest.new(base_url: 'https://eudemo.asperademo.com')
         | 
| 926 | 
            +
                        require 'json'
         | 
| 927 | 
            +
                        servers=JSON.parse(server_api.read('servers')[:data])
         | 
| 928 | 
            +
                        return {:type=>:object_list,:data=>servers}
         | 
| 929 | 
            +
                      else
         | 
| 930 | 
            +
                        raise "internal error: #{command}"
         | 
| 931 | 
            +
                      end # action
         | 
| 932 | 
            +
                      raise RuntimeError, "internal error: command shall return"
         | 
| 933 | 
            +
                    end
         | 
| 934 | 
            +
                  end # Aspera
         | 
| 935 | 
            +
                end # Plugins
         | 
| 936 | 
            +
              end # Cli
         | 
| 937 | 
            +
            end # Aspera
         |