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:
parent
c683b7e8bf
commit
13934c0e74
4 changed files with 49 additions and 19 deletions
|
|
@ -4,17 +4,7 @@ import { X, Radio, Pencil } from 'lucide-react';
|
||||||
import { useCurrentUser } from '@/hooks/useCurrentUser';
|
import { useCurrentUser } from '@/hooks/useCurrentUser';
|
||||||
import { useLocalStorage } from '@/hooks/useLocalStorage';
|
import { useLocalStorage } from '@/hooks/useLocalStorage';
|
||||||
import { NEWSLETTER_ISSUES } from '@/pages/NewsletterPage';
|
import { NEWSLETTER_ISSUES } from '@/pages/NewsletterPage';
|
||||||
|
import { isAdminPubkey } from '@/lib/admins';
|
||||||
// ─── 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
|
|
||||||
];
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* How many days the "Latest Drop" pill stays visible after a new issue.
|
* 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
|
// Today's date key — so it only shows once per Monday, not every page load
|
||||||
const todayKey = new Date().toISOString().slice(0, 10);
|
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;
|
const alreadyDismissedToday = dismissed === todayKey;
|
||||||
|
|
||||||
if (
|
if (
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
import { useQuery } from '@tanstack/react-query';
|
import { useQuery } from '@tanstack/react-query';
|
||||||
import {
|
import {
|
||||||
SKATE_COACH_KIND, SKATE_FILMER_KIND, SKATE_EDITOR_KIND, SKATE_PHOTOGRAPHER_KIND, SKATE_BUILDER_KIND,
|
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,
|
parseSkateCoach, parseSkateFilmer, parseSkateEditor, parseSkatePhotographer, parseSkateBuilder,
|
||||||
parseSkateArtist, parseSkateGraffiti, parseSkateTattoo, parseSkateTrainer, parseSkateMusician,
|
parseSkateArtist, parseSkateGraffiti, parseSkateTattoo, parseSkateTrainer, parseSkateMusician, parseSkateJudge,
|
||||||
isFeaturedActive,
|
isFeaturedActive,
|
||||||
type SkateCoach, type SkateFilmer, type SkateEditor, type SkatePhotographer, type SkateBuilder,
|
type SkateCoach, type SkateFilmer, type SkateEditor, type SkatePhotographer, type SkateBuilder,
|
||||||
type SkateArtist, type SkateGraffiti, type SkateTattoo, type SkateTrainer, type SkateMusician,
|
type SkateArtist, type SkateGraffiti, type SkateTattoo, type SkateTrainer, type SkateMusician,
|
||||||
|
|
@ -14,7 +14,7 @@ import { useAdminModeration, filterAdminHiddenMixed } from '@/hooks/useAdminMode
|
||||||
|
|
||||||
export type LabProfileType =
|
export type LabProfileType =
|
||||||
| 'coach' | 'filmer' | 'editor' | 'photographer' | 'builder'
|
| 'coach' | 'filmer' | 'editor' | 'photographer' | 'builder'
|
||||||
| 'artist' | 'graffiti' | 'tattoo' | 'trainer' | 'musician';
|
| 'artist' | 'graffiti' | 'tattoo' | 'trainer' | 'musician' | 'judge';
|
||||||
|
|
||||||
export type LabProfile = (
|
export type LabProfile = (
|
||||||
| SkateCoach | SkateFilmer | SkateEditor | SkatePhotographer | SkateBuilder
|
| SkateCoach | SkateFilmer | SkateEditor | SkatePhotographer | SkateBuilder
|
||||||
|
|
@ -25,12 +25,13 @@ export type LabProfile = (
|
||||||
|
|
||||||
const LAB_KINDS = [
|
const LAB_KINDS = [
|
||||||
SKATE_COACH_KIND, SKATE_FILMER_KIND, SKATE_EDITOR_KIND, SKATE_PHOTOGRAPHER_KIND, SKATE_BUILDER_KIND,
|
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 = [
|
const LAB_SELF_TAGS = [
|
||||||
'skatecoach', 'skatefilmer', 'skateeditor', 'skatephotographer', 'skatebuilder',
|
'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. */
|
/** Parse any Lab event into a LabProfile, or null if invalid / unknown kind. */
|
||||||
|
|
|
||||||
|
|
@ -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_TATTOO_KIND = 35009; // Tattoo artist profiles
|
||||||
export const SKATE_TRAINER_KIND = 35010; // Physical trainer / physiotherapist 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_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 MARKETPLACE_ITEM_KIND = 30402; // NIP-99 Classified Listings
|
||||||
export const SPOT_COLLECTION_KIND = 30003; // NIP-51 Bookmark sets for spot collections
|
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
|
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
|
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;
|
if (event.kind !== SKATE_COACH_KIND) return null;
|
||||||
|
|
||||||
const d = event.tags.find(([name]) => name === 'd')?.[1];
|
const d = event.tags.find(([name]) => name === 'd')?.[1];
|
||||||
|
|
@ -2798,3 +2810,30 @@ export function parseMarketplaceItem(event: NostrEvent): MarketplaceItem | null
|
||||||
event,
|
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;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -729,7 +729,7 @@ function PublishToNostrButton({ issue }: { issue: NewsletterIssue }) {
|
||||||
const [published, setPublished] = useState(false);
|
const [published, setPublished] = useState(false);
|
||||||
const [showPreview, setShowPreview] = 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 (!user || !isAdmin) return null;
|
||||||
|
|
||||||
if (published) {
|
if (published) {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue