ENV["RAILS_ENV"] = "test" require_relative "../config/environment" require "rails/test_help" class PracticeTransferTest < ActionDispatch::IntegrationTest setup do @user=User.create!(email:"export@example.test",password:"secure-test-password-123",password_confirmation:"secure-test-password-123",api_token_digest:Digest::SHA256.hexdigest("test-transfer-token")) @other=User.create!(email:"other-export@example.test",password:"secure-test-password-123",password_confirmation:"secure-test-password-123") @entry=@user.entries.create!(date:"2024-06-15",praktikums_typ:"propädeutikum",entry_art:"Supervision",hours:1,minutes:31,distance_km:20,beschreibung:"Confidential description",kosten:120) @other.entries.create!(date:"2024-06-15",praktikums_typ:"propädeutikum",entry_art:"Supervision",hours:9,minutes:0,distance_km:999) @password="separate-transfer-passphrase" @params={from:"2024-01-01",to:"2024-12-31",transfer_password:@password} end test "missing and non bearer tokens never select a user without a token" do post "/api/v1/practice_transfer",params:@params assert_response :unauthorized post "/api/v1/practice_transfer",params:@params,headers:{"Authorization"=>"Basic test-transfer-token"} assert_response :unauthorized end test "exports only own records, excludes descriptions by default and retains source identities" do post "/api/v1/practice_transfer",params:@params,headers:{"Authorization"=>"Bearer test-transfer-token"} assert_response :success assert_includes response.headers["Cache-Control"],"no-store" payload=ProfessionalTransferEnvelope.decrypt(response.body,@password) assert_equal 2,payload["records"].length assert_equal [@entry.id.to_s],payload["records"].map { |r| r["source_id"] }.uniq assert payload["records"].all? { |r| r["description"].nil? } assert payload["records"].all? { |r| r["duration_minutes"]==91 } namespace=payload["source_namespace"] post "/api/v1/practice_transfer",params:@params.merge(include_descriptions:true),headers:{"Authorization"=>"Bearer test-transfer-token"} second=ProfessionalTransferEnvelope.decrypt(response.body,@password) assert_equal namespace,second["source_namespace"] assert_equal "Confidential description",second["records"].first["description"] end test "envelope rejects tampering and incorrect passwords" do content=ProfessionalTransferEnvelope.encrypt({"value"=>42},@password) assert_raises(ProfessionalTransferEnvelope::Invalid) { ProfessionalTransferEnvelope.decrypt(content,"wrong-transfer-password") } envelope=JSON.parse(content);envelope["tag"]=Base64.strict_encode64("0"*16) assert_raises(ProfessionalTransferEnvelope::Invalid) { ProfessionalTransferEnvelope.decrypt(JSON.generate(envelope),@password) } end end