WIP! A BB-style forum, on the ATmosphere! We're still working... we'll be back soon when we have something to show off!
node typescript hono htmx atproto
4
fork

Configure Feed

Select the types of activity you want to include in your feed.

refactor(web): move canManageMembers/canManageCategories/canViewModLog to session.ts (ATB-42)

Malpercio b2758b77 47c6c9bf

+59 -30
+29 -1
apps/web/src/lib/__tests__/session.test.ts
··· 1 1 import { describe, it, expect, vi, beforeEach, afterEach } from "vitest"; 2 - import { getSession, getSessionWithPermissions, canLockTopics, canModeratePosts, canBanUsers, hasAnyAdminPermission } from "../session.js"; 2 + import { getSession, getSessionWithPermissions, canLockTopics, canModeratePosts, canBanUsers, hasAnyAdminPermission, canManageMembers, canManageCategories, canViewModLog } from "../session.js"; 3 3 import { logger } from "../logger.js"; 4 4 5 5 vi.mock("../logger.js", () => ({ ··· 324 324 expect(canModeratePosts(ownerSession)).toBe(true)); 325 325 it("canBanUsers returns true for owner with wildcard permission", () => 326 326 expect(canBanUsers(ownerSession)).toBe(true)); 327 + 328 + const makeSinglePermSessionHelper = (permission: string) => ({ 329 + authenticated: true as const, 330 + did: "did:plc:user", 331 + handle: "user.bsky.social", 332 + permissions: new Set([permission]), 333 + }); 334 + 335 + it("canManageMembers returns true for user with manageMembers", () => 336 + expect(canManageMembers(makeSinglePermSessionHelper("space.atbb.permission.manageMembers"))).toBe(true)); 337 + it("canManageMembers returns false for member with no permissions", () => 338 + expect(canManageMembers(memberSession)).toBe(false)); 339 + it("canManageMembers returns true for owner with wildcard", () => 340 + expect(canManageMembers(ownerSession)).toBe(true)); 341 + 342 + it("canManageCategories returns true for user with manageCategories", () => 343 + expect(canManageCategories(makeSinglePermSessionHelper("space.atbb.permission.manageCategories"))).toBe(true)); 344 + it("canManageCategories returns false for member with no permissions", () => 345 + expect(canManageCategories(memberSession)).toBe(false)); 346 + it("canManageCategories returns true for owner with wildcard", () => 347 + expect(canManageCategories(ownerSession)).toBe(true)); 348 + 349 + it("canViewModLog returns true for user with moderatePosts", () => 350 + expect(canViewModLog(makeSinglePermSessionHelper("space.atbb.permission.moderatePosts"))).toBe(true)); 351 + it("canViewModLog returns false for member with no permissions", () => 352 + expect(canViewModLog(memberSession)).toBe(false)); 353 + it("canViewModLog returns true for owner with wildcard", () => 354 + expect(canViewModLog(ownerSession)).toBe(true)); 327 355 }); 328 356 329 357 describe("hasAnyAdminPermission", () => {
+29
apps/web/src/lib/session.ts
··· 168 168 if (auth.permissions.has("*")) return true; 169 169 return ADMIN_PERMISSIONS.some((p) => auth.permissions.has(p)); 170 170 } 171 + 172 + /** Returns true if the session grants permission to manage forum members. */ 173 + export function canManageMembers(auth: WebSessionWithPermissions): boolean { 174 + return ( 175 + auth.authenticated && 176 + (auth.permissions.has("space.atbb.permission.manageMembers") || 177 + auth.permissions.has("*")) 178 + ); 179 + } 180 + 181 + /** Returns true if the session grants permission to manage forum categories and boards. */ 182 + export function canManageCategories(auth: WebSessionWithPermissions): boolean { 183 + return ( 184 + auth.authenticated && 185 + (auth.permissions.has("space.atbb.permission.manageCategories") || 186 + auth.permissions.has("*")) 187 + ); 188 + } 189 + 190 + /** Returns true if the session grants any moderation permission (view mod log). */ 191 + export function canViewModLog(auth: WebSessionWithPermissions): boolean { 192 + return ( 193 + auth.authenticated && 194 + (auth.permissions.has("space.atbb.permission.moderatePosts") || 195 + auth.permissions.has("space.atbb.permission.banUsers") || 196 + auth.permissions.has("space.atbb.permission.lockTopics") || 197 + auth.permissions.has("*")) 198 + ); 199 + }
+1 -29
apps/web/src/routes/admin.tsx
··· 1 1 import { Hono } from "hono"; 2 2 import { BaseLayout } from "../layouts/base.js"; 3 3 import { PageHeader, Card } from "../components/index.js"; 4 - import { getSessionWithPermissions, hasAnyAdminPermission } from "../lib/session.js"; 5 - 6 - // ─── Permission helpers ─────────────────────────────────────────────────── 7 - 8 - function canManageMembers(auth: { authenticated: boolean; permissions: Set<string> }): boolean { 9 - return ( 10 - auth.authenticated && 11 - (auth.permissions.has("space.atbb.permission.manageMembers") || 12 - auth.permissions.has("*")) 13 - ); 14 - } 15 - 16 - function canManageCategories(auth: { authenticated: boolean; permissions: Set<string> }): boolean { 17 - return ( 18 - auth.authenticated && 19 - (auth.permissions.has("space.atbb.permission.manageCategories") || 20 - auth.permissions.has("*")) 21 - ); 22 - } 23 - 24 - function canViewModLog(auth: { authenticated: boolean; permissions: Set<string> }): boolean { 25 - return ( 26 - auth.authenticated && 27 - (auth.permissions.has("space.atbb.permission.moderatePosts") || 28 - auth.permissions.has("space.atbb.permission.banUsers") || 29 - auth.permissions.has("space.atbb.permission.lockTopics") || 30 - auth.permissions.has("*")) 31 - ); 32 - } 4 + import { getSessionWithPermissions, hasAnyAdminPermission, canManageMembers, canManageCategories, canViewModLog } from "../lib/session.js"; 33 5 34 6 // ─── Route ──────────────────────────────────────────────────────────────── 35 7