fix and update
This commit is contained in:
@@ -40,6 +40,7 @@ type FedcmAccountsResponse = {
|
||||
given_name?: string;
|
||||
email?: string;
|
||||
picture?: string;
|
||||
tel?: string;
|
||||
approved_clients?: string[];
|
||||
}>;
|
||||
};
|
||||
|
||||
@@ -105,15 +105,20 @@ export async function resolveFedcmEndpoints(core: CoreGrpcService, _req?: Reques
|
||||
|
||||
export function buildFedcmProviderConfig(endpoints: FedcmEndpoints) {
|
||||
const base = normalizePublicBaseUrl(endpoints.issuer);
|
||||
const front = normalizePublicBaseUrl(endpoints.frontendUrl);
|
||||
return {
|
||||
accounts_endpoint: `${base}/fedcm/accounts`,
|
||||
client_metadata_endpoint: `${base}/fedcm/client_metadata`,
|
||||
id_assertion_endpoint: `${base}/fedcm/id_assertion`,
|
||||
login_url: endpoints.loginUrl,
|
||||
branding: {
|
||||
name: endpoints.projectName,
|
||||
background_color: '#ffffff',
|
||||
color: '#1f2430',
|
||||
icons: [{ url: `${base}/favicon.ico`, size: 32 }]
|
||||
icons: [
|
||||
{ url: `${front}/icon.svg`, size: 40 },
|
||||
{ url: `${base}/favicon.ico`, size: 32 }
|
||||
]
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -135,7 +140,9 @@ export function buildFedcmDiscoverPayload(endpoints: FedcmEndpoints, enabled = t
|
||||
configUrl: endpoints.configUrl,
|
||||
webIdentityUrl: endpoints.webIdentityUrl,
|
||||
accountsEndpoint: endpoints.accountsEndpoint,
|
||||
loginUrl: endpoints.loginUrl
|
||||
loginUrl: endpoints.loginUrl,
|
||||
// Поля для navigator.credentials.get({ identity: { fields: [...] } }) на стороне RP (Chrome 132+).
|
||||
suggestedFields: ['name', 'email', 'picture', 'tel']
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -71,7 +71,8 @@ async function loginWithFedCM() {
|
||||
identity: {
|
||||
providers: [{
|
||||
configURL: '${fedcmConfigUrl}',
|
||||
clientId: '${clientIdPlaceholder}'
|
||||
clientId: '${clientIdPlaceholder}',
|
||||
fields: ['name', 'email', 'picture', 'tel']
|
||||
}]
|
||||
},
|
||||
mediation: 'optional'
|
||||
|
||||
@@ -104,6 +104,10 @@ export function OAuthClientOneTapSection({
|
||||
<code>configURL</code> для FedCM: <code>{endpoints.fedcmConfigUrl}</code> (не{' '}
|
||||
<code>{frontendBase}/idp-api/fedcm/config.json</code>).
|
||||
</li>
|
||||
<li>
|
||||
Для disclosure (имя, email, аватар, телефон) RP должен передавать{' '}
|
||||
<code>{`fields: ['name', 'email', 'picture', 'tel']`}</code> в вызове FedCM (Chrome 132+).
|
||||
</li>
|
||||
<li>
|
||||
При ошибке NetworkError проверьте, что <code>PUBLIC_API_URL</code> = <code>{endpoints.issuer}</code>.
|
||||
</li>
|
||||
|
||||
@@ -95,7 +95,9 @@ export function buildOneTapExamples(urls: OneTapUrls, clientId: string, redirect
|
||||
identity: {
|
||||
providers: [{
|
||||
configURL: '${fedcmConfigUrl}',
|
||||
clientId: '${clientId}'
|
||||
clientId: '${clientId}',
|
||||
// Chrome 132+: disclosure в диалоге FedCM (имя, email, аватар, телефон)
|
||||
fields: ['name', 'email', 'picture', 'tel']
|
||||
}]
|
||||
},
|
||||
mediation: 'optional'
|
||||
|
||||
@@ -95,7 +95,8 @@
|
||||
{
|
||||
configURL: configUrl,
|
||||
configUrl: configUrl,
|
||||
clientId: clientId
|
||||
clientId: clientId,
|
||||
fields: ['name', 'email', 'picture', 'tel']
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { BadRequestException, Injectable, UnauthorizedException } from '@nestjs/common';
|
||||
import { PrismaService } from '../infra/prisma.service';
|
||||
import { MediaService } from './media.service';
|
||||
import { OAuthCoreService } from './oauth-core.service';
|
||||
import { SessionService } from './session.service';
|
||||
import { SettingsService } from './settings.service';
|
||||
@@ -11,7 +12,8 @@ export class FedcmService {
|
||||
private readonly prisma: PrismaService,
|
||||
private readonly session: SessionService,
|
||||
private readonly oauthCore: OAuthCoreService,
|
||||
private readonly settings: SettingsService
|
||||
private readonly settings: SettingsService,
|
||||
private readonly media: MediaService
|
||||
) {}
|
||||
|
||||
async getAccounts(userId: string, sessionId: string) {
|
||||
@@ -35,6 +37,9 @@ export class FedcmService {
|
||||
.map((item) => item.client.clientId);
|
||||
|
||||
const givenName = user.displayName.trim().split(/\s+/)[0] || user.displayName;
|
||||
const picture = await this.media.createFedcmAvatarUrl(user.id);
|
||||
const email = user.email?.trim() || undefined;
|
||||
const tel = user.phone?.trim() || undefined;
|
||||
|
||||
return {
|
||||
accounts: [
|
||||
@@ -42,8 +47,9 @@ export class FedcmService {
|
||||
id: user.id,
|
||||
name: user.displayName,
|
||||
given_name: givenName,
|
||||
email: user.email ?? undefined,
|
||||
picture: user.avatarUrl ?? undefined,
|
||||
email,
|
||||
picture,
|
||||
tel,
|
||||
approved_clients: approvedClients
|
||||
}
|
||||
]
|
||||
|
||||
@@ -68,6 +68,25 @@ export class MediaService {
|
||||
return { userId, hasAvatar: true };
|
||||
}
|
||||
|
||||
async createFedcmAvatarUrl(userId: string): Promise<string | undefined> {
|
||||
const user = await this.prisma.user.findUnique({ where: { id: userId } });
|
||||
if (!user) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const legacyUrl = user.avatarUrl?.trim();
|
||||
if (legacyUrl) {
|
||||
return legacyUrl;
|
||||
}
|
||||
|
||||
if (!user.avatarStorageKey) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const { accessUrl } = await this.createStreamAccessUrl(user.avatarStorageKey, userId);
|
||||
return accessUrl;
|
||||
}
|
||||
|
||||
async getAvatarAccessUrl(requesterId: string, targetUserId: string) {
|
||||
const user = await this.prisma.user.findUnique({ where: { id: targetUserId } });
|
||||
if (!user?.avatarStorageKey) {
|
||||
|
||||
@@ -125,6 +125,7 @@ message FedcmAccount {
|
||||
optional string email = 4;
|
||||
optional string picture = 5;
|
||||
repeated string approved_clients = 6;
|
||||
optional string tel = 7;
|
||||
}
|
||||
|
||||
message FedcmAccountsResponse {
|
||||
|
||||
Reference in New Issue
Block a user