mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-07-25 06:18:45 +08:00
@@ -1,8 +1,14 @@
|
||||
import { Inject, Injectable, Logger } from '@nestjs/common';
|
||||
|
||||
import { Config, OnEvent } from '../../../base';
|
||||
import {
|
||||
Config,
|
||||
InvalidOauthCallbackCode,
|
||||
InvalidOauthResponse,
|
||||
OnEvent,
|
||||
} from '../../../base';
|
||||
import { OAuthProviderName } from '../config';
|
||||
import { OAuthProviderFactory } from '../factory';
|
||||
import type { OAuthState } from '../types';
|
||||
|
||||
export interface OAuthAccount {
|
||||
id: string;
|
||||
@@ -16,6 +22,8 @@ export interface Tokens {
|
||||
scope?: string;
|
||||
refreshToken?: string;
|
||||
expiresAt?: Date;
|
||||
idToken?: string;
|
||||
tokenType?: string;
|
||||
}
|
||||
|
||||
export interface AuthOptions {
|
||||
@@ -29,8 +37,8 @@ export interface AuthOptions {
|
||||
export abstract class OAuthProvider {
|
||||
abstract provider: OAuthProviderName;
|
||||
abstract getAuthUrl(state: string, clientNonce?: string): string;
|
||||
abstract getToken(code: string): Promise<Tokens>;
|
||||
abstract getUser(tokens: Tokens, state: any): Promise<OAuthAccount>;
|
||||
abstract getToken(code: string, state: OAuthState): Promise<Tokens>;
|
||||
abstract getUser(tokens: Tokens, state: OAuthState): Promise<OAuthAccount>;
|
||||
|
||||
protected readonly logger = new Logger(this.constructor.name);
|
||||
@Inject() private readonly factory!: OAuthProviderFactory;
|
||||
@@ -65,4 +73,63 @@ export abstract class OAuthProvider {
|
||||
this.factory.unregister(this);
|
||||
}
|
||||
}
|
||||
|
||||
get requiresPkce() {
|
||||
return false;
|
||||
}
|
||||
|
||||
protected async fetchJson<T>(
|
||||
url: string,
|
||||
init?: RequestInit,
|
||||
options?: { treatServerErrorAsInvalid?: boolean }
|
||||
) {
|
||||
const response = await fetch(url, {
|
||||
headers: { Accept: 'application/json', ...init?.headers },
|
||||
...init,
|
||||
});
|
||||
|
||||
const body = await response.text();
|
||||
if (!response.ok) {
|
||||
if (response.status < 500 || options?.treatServerErrorAsInvalid) {
|
||||
throw new InvalidOauthCallbackCode({ status: response.status, body });
|
||||
}
|
||||
throw new Error(
|
||||
`Server responded with non-success status ${response.status}, body: ${body}`
|
||||
);
|
||||
}
|
||||
|
||||
if (!body) {
|
||||
return {} as T;
|
||||
}
|
||||
|
||||
try {
|
||||
return JSON.parse(body) as T;
|
||||
} catch {
|
||||
throw new InvalidOauthResponse({
|
||||
reason: `Unable to parse JSON response from ${url}`,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
protected postFormJson<T>(
|
||||
url: string,
|
||||
body: string,
|
||||
options?: {
|
||||
headers?: Record<string, string>;
|
||||
treatServerErrorAsInvalid?: boolean;
|
||||
}
|
||||
) {
|
||||
return this.fetchJson<T>(
|
||||
url,
|
||||
{
|
||||
method: 'POST',
|
||||
body,
|
||||
headers: {
|
||||
'Content-Type': 'application/x-www-form-urlencoded',
|
||||
...options?.headers,
|
||||
},
|
||||
},
|
||||
options
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user