test pds oauth did
This commit is contained in:
@ -1,5 +1,7 @@
|
||||
// PDS Detection and API URL mapping utilities
|
||||
|
||||
import { isValidDid, isValidHandle } from './validation';
|
||||
|
||||
export interface NetworkConfig {
|
||||
pdsApi: string;
|
||||
plcApi: string;
|
||||
@ -9,12 +11,33 @@ export interface NetworkConfig {
|
||||
|
||||
// Detect PDS from handle
|
||||
export function detectPdsFromHandle(handle: string): string {
|
||||
if (handle.endsWith('.syu.is')) {
|
||||
// Get allowed handles from environment
|
||||
const allowedHandlesStr = import.meta.env.VITE_ATPROTO_HANDLE_LIST || '[]';
|
||||
let allowedHandles: string[] = [];
|
||||
try {
|
||||
allowedHandles = JSON.parse(allowedHandlesStr);
|
||||
} catch {
|
||||
allowedHandles = [];
|
||||
}
|
||||
|
||||
// Get configured PDS from environment
|
||||
const configuredPds = import.meta.env.VITE_ATPROTO_PDS || 'syu.is';
|
||||
|
||||
// Check if handle is in allowed list
|
||||
if (allowedHandles.includes(handle)) {
|
||||
return configuredPds;
|
||||
}
|
||||
|
||||
// Check if handle ends with .syu.is or .syui.ai
|
||||
if (handle.endsWith('.syu.is') || handle.endsWith('.syui.ai')) {
|
||||
return 'syu.is';
|
||||
}
|
||||
|
||||
// Check if handle ends with .bsky.social or .bsky.app
|
||||
if (handle.endsWith('.bsky.social') || handle.endsWith('.bsky.app')) {
|
||||
return 'bsky.social';
|
||||
}
|
||||
|
||||
// Default to Bluesky for unknown domains
|
||||
return 'bsky.social';
|
||||
}
|
||||
@ -74,8 +97,13 @@ export function getApiUrlForUser(handle: string): string {
|
||||
return config.bskyApi;
|
||||
}
|
||||
|
||||
// Resolve handle/DID to actual PDS endpoint using com.atproto.repo.describeRepo
|
||||
// Resolve handle/DID to actual PDS endpoint using PLC API first
|
||||
export async function resolvePdsFromRepo(handleOrDid: string): Promise<{ pds: string; did: string; handle: string }> {
|
||||
// Validate input
|
||||
if (!handleOrDid || (!isValidDid(handleOrDid) && !isValidHandle(handleOrDid))) {
|
||||
throw new Error(`Invalid identifier: ${handleOrDid}`);
|
||||
}
|
||||
|
||||
let targetDid = handleOrDid;
|
||||
let targetHandle = handleOrDid;
|
||||
|
||||
@ -83,7 +111,7 @@ export async function resolvePdsFromRepo(handleOrDid: string): Promise<{ pds: st
|
||||
if (!handleOrDid.startsWith('did:')) {
|
||||
try {
|
||||
// Try multiple endpoints for handle resolution
|
||||
const resolveEndpoints = ['https://public.api.bsky.app', 'https://bsky.syu.is'];
|
||||
const resolveEndpoints = ['https://public.api.bsky.app', 'https://bsky.syu.is', 'https://syu.is'];
|
||||
let resolved = false;
|
||||
|
||||
for (const endpoint of resolveEndpoints) {
|
||||
@ -108,7 +136,34 @@ export async function resolvePdsFromRepo(handleOrDid: string): Promise<{ pds: st
|
||||
}
|
||||
}
|
||||
|
||||
// Now use com.atproto.repo.describeRepo to get PDS from known PDS endpoints
|
||||
// First, try PLC API to get the authoritative DID document
|
||||
const plcApis = ['https://plc.directory', 'https://plc.syu.is'];
|
||||
|
||||
for (const plcApi of plcApis) {
|
||||
try {
|
||||
const plcResponse = await fetch(`${plcApi}/${targetDid}`);
|
||||
if (plcResponse.ok) {
|
||||
const didDocument = await plcResponse.json();
|
||||
|
||||
// Find PDS service in DID document
|
||||
const pdsService = didDocument.service?.find((s: any) =>
|
||||
s.id === '#atproto_pds' || s.type === 'AtprotoPersonalDataServer'
|
||||
);
|
||||
|
||||
if (pdsService && pdsService.serviceEndpoint) {
|
||||
return {
|
||||
pds: pdsService.serviceEndpoint,
|
||||
did: targetDid,
|
||||
handle: targetHandle
|
||||
};
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// Fallback: use com.atproto.repo.describeRepo to get PDS from known PDS endpoints
|
||||
const pdsEndpoints = ['https://bsky.social', 'https://syu.is'];
|
||||
|
||||
for (const pdsEndpoint of pdsEndpoints) {
|
||||
|
21
oauth/src/utils/validation.ts
Normal file
21
oauth/src/utils/validation.ts
Normal file
@ -0,0 +1,21 @@
|
||||
// Validation utilities for atproto identifiers
|
||||
|
||||
export function isValidDid(did: string): boolean {
|
||||
if (!did || typeof did !== 'string') return false;
|
||||
|
||||
// Basic DID format: did:method:identifier
|
||||
const didRegex = /^did:[a-z]+:[a-zA-Z0-9._%-]+$/;
|
||||
return didRegex.test(did);
|
||||
}
|
||||
|
||||
export function isValidHandle(handle: string): boolean {
|
||||
if (!handle || typeof handle !== 'string') return false;
|
||||
|
||||
// Basic handle format: subdomain.domain.tld
|
||||
const handleRegex = /^([a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?\.)+[a-zA-Z]{2,}$/;
|
||||
return handleRegex.test(handle);
|
||||
}
|
||||
|
||||
export function isValidAtprotoIdentifier(identifier: string): boolean {
|
||||
return isValidDid(identifier) || isValidHandle(identifier);
|
||||
}
|
Reference in New Issue
Block a user