main
rb 97 lines 3.76 KB
Raw
1 # frozen_string_literal: true
2
3 require "rails_helper"
4
5 # Owner-only actions on a mirror repository: detach (convert it into a normal
6 # writable repo and stop syncing) and a manual sync trigger. Everyone else —
7 # other users and anonymous visitors — must not be able to reach either.
8 RSpec.describe "Mirror actions", type: :request do
9 let(:owner) { User.create!(smbcloud_id: 800, email: "owner@example.com", username: "owner") }
10 let(:other) { User.create!(smbcloud_id: 801, email: "other@example.com", username: "other") }
11
12 let!(:mirror) do
13 owner.repositories.create!(
14 name: "mirrored", disk_path: "/nonexistent/owner/mirrored.git", default_branch: "main",
15 mirror: true, upstream_url: "https://github.com/acme/mirrored.git",
16 upstream_token: "gho_secrettoken", mirror_status: "ok"
17 )
18 end
19
20 # Session-based sign-in without going through smbCloud (mirrors the pattern in
21 # github_connections_spec). `signed_in?` derives from `current_user`, so
22 # stubbing the reader is enough.
23 def sign_in(user)
24 allow_any_instance_of(ApplicationController).to receive(:current_user).and_return(user)
25 end
26
27 describe "POST /:username/:repository/mirror/detach" do
28 it "converts the mirror into a normal writable repo for its owner" do
29 sign_in(owner)
30 post repository_mirror_detach_path(owner.username, mirror.name)
31
32 expect(response).to redirect_to(repository_path(owner.username, mirror.name))
33 mirror.reload
34 expect(mirror.mirror?).to be(false)
35 expect(mirror.upstream_token).to be_nil # credential dropped
36 expect(mirror.writable_by?(owner)).to be(true) # now pushable
37 end
38
39 it "is a 404 for a signed-in non-owner and leaves the mirror intact" do
40 sign_in(other)
41 post repository_mirror_detach_path(owner.username, mirror.name)
42
43 expect(response).to have_http_status(:not_found)
44 expect(mirror.reload.mirror?).to be(true)
45 end
46
47 it "redirects anonymous visitors to sign in" do
48 post repository_mirror_detach_path(owner.username, mirror.name)
49
50 expect(response).to redirect_to(signin_path)
51 expect(mirror.reload.mirror?).to be(true)
52 end
53
54 it "reports plainly when the repo isn't a mirror" do
55 normal = owner.repositories.create!(name: "plain", disk_path: "/nonexistent/owner/plain.git",
56 default_branch: "main")
57 sign_in(owner)
58 post repository_mirror_detach_path(owner.username, normal.name)
59
60 expect(response).to redirect_to(repository_path(owner.username, normal.name))
61 expect(flash[:alert]).to match(/isn't a mirror/i)
62 end
63 end
64
65 describe "POST /:username/:repository/mirror/sync" do
66 it "queues a MirrorSyncJob for the owner" do
67 sign_in(owner)
68 expect(MirrorSyncJob).to receive(:perform_later).with(mirror.id)
69
70 post repository_mirror_sync_path(owner.username, mirror.name)
71
72 expect(response).to redirect_to(repository_path(owner.username, mirror.name))
73 expect(flash[:notice]).to match(/queued/i)
74 end
75
76 it "is a 404 for a non-owner and enqueues nothing" do
77 sign_in(other)
78 expect(MirrorSyncJob).not_to receive(:perform_later)
79
80 post repository_mirror_sync_path(owner.username, mirror.name)
81
82 expect(response).to have_http_status(:not_found)
83 end
84
85 it "refuses to sync a repo that isn't a mirror" do
86 normal = owner.repositories.create!(name: "plain2", disk_path: "/nonexistent/owner/plain2.git",
87 default_branch: "main")
88 sign_in(owner)
89 expect(MirrorSyncJob).not_to receive(:perform_later)
90
91 post repository_mirror_sync_path(owner.username, normal.name)
92
93 expect(response).to redirect_to(repository_path(owner.username, normal.name))
94 expect(flash[:alert]).to match(/isn't a mirror/i)
95 end
96 end
97 end