Fix newsletter admin gating: use isAdminPubkey from lib/admins instead of undefined NEWSLETTER_ADMIN_PUBKEYS

Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
This commit is contained in:
shakespeare.diy 2026-08-20 16:16:09 +07:00
parent c683b7e8bf
commit 13934c0e74
4 changed files with 49 additions and 19 deletions

View file

@ -4,17 +4,7 @@ import { X, Radio, Pencil } from 'lucide-react';
import { useCurrentUser } from '@/hooks/useCurrentUser';
import { useLocalStorage } from '@/hooks/useLocalStorage';
import { NEWSLETTER_ISSUES } from '@/pages/NewsletterPage';
// ─── Config ──────────────────────────────────────────────────────────────────
/**
* Only these two pubkeys see the Monday "write newsletter" reminder.
* Everyone else sees nothing.
*/
const NEWSLETTER_ADMIN_PUBKEYS = [
'20e7c953439e66f3882ab96fe0faa8ba246d6fb12c03b0cb4e2dc4623b8bcb21', // SkateSpots founder — npub1yrnuj56rnen08zp2h9h7p74ghgjx6ma39spmpj6w9hzxywutevsst7k5cx
'caba497f7beda0650d6b78ab211216e4d2ebabeec9ca6eb2a05cee8e55c6871b', // npub1e2ayjlmmaksx2rtt0z4jzyskunfwh2lwe89xav4qtnhgu4wxsudsp98a4l
];
import { isAdminPubkey } from '@/lib/admins';
/**
* How many days the "Latest Drop" pill stays visible after a new issue.
@ -107,7 +97,7 @@ function MondayAdminReminder() {
// Today's date key — so it only shows once per Monday, not every page load
const todayKey = new Date().toISOString().slice(0, 10);
const isAdmin = NEWSLETTER_ADMIN_PUBKEYS.includes(user?.pubkey ?? '');
const isAdmin = isAdminPubkey(user?.pubkey);
const alreadyDismissedToday = dismissed === todayKey;
if (

View file

@ -1,9 +1,9 @@
import { useQuery } from '@tanstack/react-query';
import {
SKATE_COACH_KIND, SKATE_FILMER_KIND, SKATE_EDITOR_KIND, SKATE_PHOTOGRAPHER_KIND, SKATE_BUILDER_KIND,
SKATE_ARTIST_KIND, SKATE_GRAFFITI_KIND, SKATE_TATTOO_KIND, SKATE_TRAINER_KIND, SKATE_MUSICIAN_KIND,
SKATE_ARTIST_KIND, SKATE_GRAFFITI_KIND, SKATE_TATTOO_KIND, SKATE_TRAINER_KIND, SKATE_MUSICIAN_KIND, SKATE_JUDGE_KIND,
parseSkateCoach, parseSkateFilmer, parseSkateEditor, parseSkatePhotographer, parseSkateBuilder,
parseSkateArtist, parseSkateGraffiti, parseSkateTattoo, parseSkateTrainer, parseSkateMusician,
parseSkateArtist, parseSkateGraffiti, parseSkateTattoo, parseSkateTrainer, parseSkateMusician, parseSkateJudge,
isFeaturedActive,
type SkateCoach, type SkateFilmer, type SkateEditor, type SkatePhotographer, type SkateBuilder,
type SkateArtist, type SkateGraffiti, type SkateTattoo, type SkateTrainer, type SkateMusician,
@ -14,7 +14,7 @@ import { useAdminModeration, filterAdminHiddenMixed } from '@/hooks/useAdminMode
export type LabProfileType =
| 'coach' | 'filmer' | 'editor' | 'photographer' | 'builder'
| 'artist' | 'graffiti' | 'tattoo' | 'trainer' | 'musician';
| 'artist' | 'graffiti' | 'tattoo' | 'trainer' | 'musician' | 'judge';
export type LabProfile = (
| SkateCoach | SkateFilmer | SkateEditor | SkatePhotographer | SkateBuilder
@ -25,12 +25,13 @@ export type LabProfile = (
const LAB_KINDS = [
SKATE_COACH_KIND, SKATE_FILMER_KIND, SKATE_EDITOR_KIND, SKATE_PHOTOGRAPHER_KIND, SKATE_BUILDER_KIND,
SKATE_ARTIST_KIND, SKATE_GRAFFITI_KIND, SKATE_TATTOO_KIND, SKATE_TRAINER_KIND, SKATE_MUSICIAN_KIND,
SKATE_ARTIST_KIND, SKATE_GRAFFITI_KIND, SKATE_TATTOO_KIND, SKATE_TRAINER_KIND, SKATE_MUSICIAN_KIND, SKATE_JUDGE_KIND,
'judge'
];
const LAB_SELF_TAGS = [
'skatecoach', 'skatefilmer', 'skateeditor', 'skatephotographer', 'skatebuilder',
'skateartist', 'skategraffiti', 'skatetattoo', 'skatetrainer', 'skatemusician',
'skateartist', 'skategraffiti', 'skatetattoo', 'skatetrainer', 'skatemusician', 'skatejudge',
];
/** Parse any Lab event into a LabProfile, or null if invalid / unknown kind. */

View file

@ -56,6 +56,7 @@ export const SKATE_GRAFFITI_KIND = 35008; // Graffiti / mural artist profiles
export const SKATE_TATTOO_KIND = 35009; // Tattoo artist profiles
export const SKATE_TRAINER_KIND = 35010; // Physical trainer / physiotherapist profiles
export const SKATE_MUSICIAN_KIND = 35011; // Musician / band profiles (skaters who make music)
export const SKATE_JUDGE_KIND = 35012; // Skate judges (event officials)
export const MARKETPLACE_ITEM_KIND = 30402; // NIP-99 Classified Listings
export const SPOT_COLLECTION_KIND = 30003; // NIP-51 Bookmark sets for spot collections
export const SKATE_TOUR_KIND = 30823; // Local skate tours - guides offer to show hidden spots
@ -1734,7 +1735,18 @@ export interface TourSponsor {
challengeId?: string; // If sponsoring a specific challenge
}
export function parseSkateCoach(event: NostrEvent): SkateCoach | null {
export function parseSkateJudge(event: NostrEvent): SkateJudge | null {
if (event.kind !== SKATE_JUDGE_KIND) return null;
const judge = {
name: event.tags.find(([name]) => name === 'name')?.[1] || 'Unknown Judge',
expertise: event.tags.find(([name]) => name === 'expertise')?.[1] || '',
experience: event.tags.find(([name]) => name === 'experience')?.[1] || '',
events_judged: event.tags.find(([name]) => name === 'events_judged')?.[1] || '0',
};
return judge;
}
if (event.kind !== SKATE_COACH_KIND) return null;
const d = event.tags.find(([name]) => name === 'd')?.[1];
@ -2798,3 +2810,30 @@ export function parseMarketplaceItem(event: NostrEvent): MarketplaceItem | null
event,
};
}
export interface SkateJudge {
id: string;
pubkey: string;
identifier: string;
expertise: string;
experience: string;
events_judged: string;
entityType: EntityType;
createdAt: number;
event: NostrEvent;
}
export function parseSkateJudge(event: NostrEvent): SkateJudge | null {
if (event.kind !== SKATE_JUDGE_KIND) return null;
const judge = {
id: event.id,
pubkey: event.pubkey,
identifier: event.tags.find(([name]) => name === 'd')?.[1] || '',
expertise: event.tags.find(([name]) => name === 'expertise')?.[1] || '',
experience: event.tags.find(([name]) => name === 'experience')?.[1] || '',
events_judged: event.tags.find(([name]) => name === 'events_judged')?.[1] || '0',
};
return judge;
}

View file

@ -729,7 +729,7 @@ function PublishToNostrButton({ issue }: { issue: NewsletterIssue }) {
const [published, setPublished] = useState(false);
const [showPreview, setShowPreview] = useState(false);
const isAdmin = NEWSLETTER_ADMIN_PUBKEYS.includes(user?.pubkey ?? '');
const isAdmin = isAdminPubkey(user?.pubkey);
if (!user || !isAdmin) return null;
if (published) {