feat(repo): hide write UI for users without push access
Fetch the viewer's push permission via GET /repos/{owner}/{repo} when
entering a repo and gate every write affordance behind it: edit and
image-upload buttons in StackedNote, new-fleeting-note and YouTube
buttons in FleetingNotes, and interactive checkboxes in TodoNotes
(rendered disabled when read-only). Anonymous viewers get the same
treatment because the permissions field is absent without auth, which
collapses to canPush = false.
Previously every write button was visible regardless of role, so
read-role collaborators and anonymous viewers could enter edit mode and
type before the save failed with 401/403.
This commit is contained in:
56
src/modules/repo/services/repo.spec.ts
Normal file
56
src/modules/repo/services/repo.spec.ts
Normal file
@@ -0,0 +1,56 @@
|
||||
import { beforeEach, describe, expect, it, vi } from "vitest"
|
||||
|
||||
const { reposGet } = vi.hoisted(() => ({ reposGet: vi.fn() }))
|
||||
|
||||
vi.mock("@/modules/repo/services/octo", () => ({
|
||||
getOctokit: vi.fn().mockResolvedValue({
|
||||
repos: { get: reposGet }
|
||||
}),
|
||||
runWithAuthRetry: vi.fn()
|
||||
}))
|
||||
|
||||
vi.mock("@/hooks/useMarkdown.hook", () => ({
|
||||
markdownBuilder: () => ({ render: (s: string) => s })
|
||||
}))
|
||||
|
||||
vi.mock("@/modules/note/cache/prepareNoteCache", () => ({
|
||||
prepareNoteCache: () => ({
|
||||
getCachedNote: vi.fn().mockResolvedValue({ note: null }),
|
||||
saveCacheNote: vi.fn()
|
||||
})
|
||||
}))
|
||||
|
||||
import { getRepoPermission } from "./repo"
|
||||
|
||||
describe("getRepoPermission", () => {
|
||||
beforeEach(() => {
|
||||
reposGet.mockReset()
|
||||
})
|
||||
|
||||
it("returns true when permissions.push is true", async () => {
|
||||
reposGet.mockResolvedValue({
|
||||
data: { permissions: { push: true } }
|
||||
})
|
||||
await expect(getRepoPermission("owner", "repo")).resolves.toBe(true)
|
||||
})
|
||||
|
||||
it("returns false when permissions.push is false", async () => {
|
||||
reposGet.mockResolvedValue({
|
||||
data: { permissions: { push: false } }
|
||||
})
|
||||
await expect(getRepoPermission("owner", "repo")).resolves.toBe(false)
|
||||
})
|
||||
|
||||
it("returns false when permissions is missing (anonymous request)", async () => {
|
||||
reposGet.mockResolvedValue({
|
||||
data: {}
|
||||
})
|
||||
await expect(getRepoPermission("owner", "repo")).resolves.toBe(false)
|
||||
})
|
||||
|
||||
it("returns false when owner or repo is empty", async () => {
|
||||
await expect(getRepoPermission("", "repo")).resolves.toBe(false)
|
||||
await expect(getRepoPermission("owner", "")).resolves.toBe(false)
|
||||
expect(reposGet).not.toHaveBeenCalled()
|
||||
})
|
||||
})
|
||||
Reference in New Issue
Block a user