github.com/cozy/cozy-stack@v0.0.0-20240603063001-31110fa4cae1/tests/system/lib/move.rb (about)

     1  class Move
     2    def initialize(source, target)
     3      @source = source
     4      @target = target
     5    end
     6  
     7    def get_initialize_token
     8      opts = {
     9        max_redirects: 0,
    10        cookies: { cozysessid: @source.open_session }
    11      }
    12      @source.client["/move/initialize"].post(nil, opts) do |response|
    13        params = extract_query_string response.headers[:location]
    14        @source_client_id = params["client_id"]
    15        @source_client_secret = params["client_secret"]
    16        @source_token = access_token @source, params
    17      end
    18    end
    19  
    20    def get_source_token
    21      opts = {
    22        max_redirects: 0,
    23        cookies: { cozysessid: @source.open_session }
    24      }
    25      state = "123456789"
    26      qs = "state=#{state}&redirect_uri=#{redirect_uri}"
    27      @source.client["/move/authorize?#{qs}"].get(opts) do |response|
    28        params = extract_query_string response.headers[:location]
    29        @code = params["code"]
    30      end
    31    end
    32  
    33    def get_target_token
    34      client = create_oauth_client @target
    35      @target_client_id = client["client_id"]
    36      @target_client_secret = client["client_secret"]
    37  
    38      state = "123456789"
    39      opts = { accept: "application/json", cookies: { cozysessid: @source.open_session } }
    40      qs = "state=#{state}&client_id=#{@target_client_id}&redirect_uri=#{redirect_uri}"
    41      res = @target.client["/auth/authorize/move?#{qs}"].get opts
    42      csrf_token = res.cookies["_csrf"]
    43  
    44      body = {
    45        state: state,
    46        client_id: @target_client_id,
    47        csrf_token: csrf_token,
    48        redirect_uri: redirect_uri,
    49        passphrase: @target.hashed_passphrase
    50      }
    51      opts[:cookies] = res.cookies
    52      res = @target.client["/auth/authorize/move"].post(body, opts)
    53      redirect = JSON.parse(res.body)["redirect"]
    54      params = extract_query_string redirect
    55      @target_token = access_token @target, params.merge(client)
    56    end
    57  
    58    def create_oauth_client(inst)
    59      params = {
    60        client_name: "Cozy-Move",
    61        client_kind: "web",
    62        client_uri: "http://localhost:4000/",
    63        redirect_uris: [redirect_uri],
    64        software_id: "github.com/cozy/cozy-move",
    65        software_version: "0.0.1"
    66      }
    67      body = JSON.generate(params)
    68      opts = { accept: "application/json", "Content-Type": "application/json" }
    69      res = inst.client["/auth/register"].post body, opts
    70      JSON.parse(res.body)
    71    end
    72  
    73    def redirect_uri
    74      "http://localhost:4000/callback/target"
    75    end
    76  
    77    def access_token(inst, params)
    78      body = {
    79        grant_type: "authorization_code",
    80        code: params["code"],
    81        client_id: params["client_id"],
    82        client_secret: params["client_secret"]
    83      }
    84      opts = { accept: :json }
    85      res = inst.client["/auth/access_token"].post body, opts
    86      JSON.parse(res.body)["access_token"]
    87    end
    88  
    89    def extract_query_string(location)
    90      query = URI.parse(location).query
    91      CGI.parse(query).inject({}) do |h, (k, v)|
    92        h[k] = v.first
    93        h
    94      end
    95    end
    96  
    97    def run
    98      body = {
    99        target_url: @target.url,
   100        target_token: @target_token,
   101        target_client_id: @target_client_id,
   102        target_client_secret: @target_client_secret
   103      }
   104      if @code
   105        body[:code] = @code
   106      else
   107        body[:token] = @source_token
   108        body[:client_id] = @source_client_id
   109        body[:client_secret] = @source_client_secret
   110      end
   111      opts = { accept: "*/*" }
   112      @source.client["/move/request"].post body, opts
   113    end
   114  
   115    def confirm(timeout = 120)
   116      timeout.times do
   117        sleep 1
   118        received = Email.received kind: "to", query: @source.email
   119        received.reject! { |e| e.subject =~ /(New.connection|Nouvelle.connexion)/ }
   120        return confirm_mail received.first if received.any?
   121      end
   122      raise "Confirmation mail for moving was not received after #{timeout} seconds"
   123    end
   124  
   125    def confirm_mail(mail)
   126      scanned = mail.body.scan(/secret=3D(\w+)/)
   127      raise "No secret in #{mail.subject} - #{mail.body}" if scanned.empty?
   128      secret = scanned.last.last
   129      opts = { cookies: { cozysessid: @source.open_session } }
   130      @source.client["/move/go?secret=#{secret}"].get opts
   131    end
   132  
   133    def wait_done(timeout = 120)
   134      timeout.times do
   135        sleep 1
   136        received = Email.received kind: "to", query: @target.email
   137        return if received.any?
   138      end
   139      raise "Moved mail was not received after #{timeout} seconds"
   140    end
   141  end