106 lines
2.5 KiB
TypeScript
106 lines
2.5 KiB
TypeScript
import { MembershipRole, type Site, type Page } from "@prisma/client"
|
|
import type { AuthUser } from "./auth.server"
|
|
import { PageVisibilityEnum } from "./types"
|
|
|
|
type Action =
|
|
| {
|
|
type: "can-delete-page"
|
|
/** The site id this page belongs to */
|
|
siteId: string
|
|
}
|
|
| {
|
|
type: "can-list-page"
|
|
visibility: PageVisibilityEnum
|
|
siteId: string
|
|
}
|
|
| {
|
|
type: "can-create-page"
|
|
siteId: string
|
|
}
|
|
| {
|
|
type: "can-read-page"
|
|
page: Page
|
|
}
|
|
| {
|
|
type: "can-update-site"
|
|
site: Site
|
|
}
|
|
export const createGate = <TRequiredAuth extends boolean | undefined>({
|
|
user,
|
|
requireAuth,
|
|
}: {
|
|
user: AuthUser | null | undefined
|
|
requireAuth?: TRequiredAuth
|
|
}) => {
|
|
if (requireAuth && !user) {
|
|
throw new Error("require auth")
|
|
}
|
|
|
|
const isSiteMember = (siteId: string, roles: MembershipRole[]) => {
|
|
if (!user) return false
|
|
return user.memberships.some(
|
|
(m) => m.siteId === siteId && roles.includes(m.role)
|
|
)
|
|
}
|
|
|
|
return {
|
|
user: user as TRequiredAuth extends true
|
|
? AuthUser
|
|
: AuthUser | null | undefined,
|
|
allows(action: Action): boolean {
|
|
if (action.type === "can-delete-page") {
|
|
return isSiteMember(action.siteId, [
|
|
MembershipRole.ADMIN,
|
|
MembershipRole.OWNER,
|
|
])
|
|
}
|
|
|
|
if (action.type === "can-list-page") {
|
|
if (action.visibility === PageVisibilityEnum.Published) {
|
|
return true
|
|
}
|
|
return isSiteMember(action.siteId, [
|
|
MembershipRole.ADMIN,
|
|
MembershipRole.OWNER,
|
|
])
|
|
}
|
|
|
|
if (action.type === "can-create-page") {
|
|
return isSiteMember(action.siteId, [
|
|
MembershipRole.ADMIN,
|
|
MembershipRole.OWNER,
|
|
])
|
|
}
|
|
|
|
if (action.type === "can-read-page") {
|
|
const isPublished =
|
|
action.page.published &&
|
|
action.page.publishedAt &&
|
|
action.page.publishedAt <= new Date()
|
|
|
|
return isPublished
|
|
? !action.page.deletedAt
|
|
: !action.page.deletedAt &&
|
|
isSiteMember(action.page.siteId, [
|
|
MembershipRole.ADMIN,
|
|
MembershipRole.OWNER,
|
|
])
|
|
}
|
|
|
|
if (action.type === "can-update-site") {
|
|
return isSiteMember(action.site.id, [
|
|
MembershipRole.ADMIN,
|
|
MembershipRole.OWNER,
|
|
])
|
|
}
|
|
|
|
return false
|
|
},
|
|
permissionError(message = "not allowed") {
|
|
return new Error(message)
|
|
},
|
|
}
|
|
}
|
|
|
|
export type Gate = ReturnType<typeof createGate>
|