fix(core): fix ios blob upload (#10263)

This commit is contained in:
EYHN
2025-02-19 10:07:46 +08:00
committed by GitHub
parent b20d316d60
commit 5a7ab880c1
21 changed files with 481 additions and 226 deletions

View File

@@ -0,0 +1,60 @@
import type { Framework } from '@toeverything/infra';
import { AuthProvider } from '../provider/auth';
import { ServerScope } from '../scopes/server';
import { FetchService } from '../services/fetch';
export function configureDefaultAuthProvider(framework: Framework) {
framework.scope(ServerScope).override(AuthProvider, resolver => {
const fetchService = resolver.get(FetchService);
return {
async signInMagicLink(email: string, token: string) {
await fetchService.fetch('/api/auth/magic-link', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ email, token }),
});
},
async signInOauth(code: string, state: string, _provider: string) {
const res = await fetchService.fetch('/api/oauth/callback', {
method: 'POST',
body: JSON.stringify({ code, state }),
headers: {
'content-type': 'application/json',
},
});
return await res.json();
},
async signInPassword(credential: {
email: string;
password: string;
verifyToken?: string;
challenge?: string;
}) {
const headers: Record<string, string> = {};
if (credential.verifyToken) {
headers['x-captcha-token'] = credential.verifyToken;
}
if (credential.challenge) {
headers['x-captcha-challenge'] = credential.challenge;
}
await fetchService.fetch('/api/auth/sign-in', {
method: 'POST',
body: JSON.stringify(credential),
headers: {
'content-type': 'application/json',
...headers,
},
});
},
async signOut() {
await fetchService.fetch('/api/auth/sign-out');
},
};
});
}

View File

@@ -11,7 +11,9 @@ export { AccountChanged } from './events/account-changed';
export { AccountLoggedIn } from './events/account-logged-in';
export { AccountLoggedOut } from './events/account-logged-out';
export { ServerInitialized } from './events/server-initialized';
export { AuthProvider } from './provider/auth';
export { ValidatorProvider } from './provider/validator';
export { ServerScope } from './scopes/server';
export { AcceptInviteService } from './services/accept-invite';
export { AuthService } from './services/auth';
export { CaptchaService } from './services/captcha';
@@ -51,6 +53,8 @@ import { UserFeature } from './entities/user-feature';
import { UserQuota } from './entities/user-quota';
import { WorkspaceInvoices } from './entities/workspace-invoices';
import { WorkspaceSubscription } from './entities/workspace-subscription';
import { configureDefaultAuthProvider } from './impl/auth';
import { AuthProvider } from './provider/auth';
import { ValidatorProvider } from './provider/validator';
import { ServerScope } from './scopes/server';
import { AcceptInviteService } from './services/accept-invite';
@@ -88,6 +92,8 @@ import { UserFeatureStore } from './stores/user-feature';
import { UserQuotaStore } from './stores/user-quota';
export function configureCloudModule(framework: Framework) {
configureDefaultAuthProvider(framework);
framework
.service(ServersService, [ServerListStore, ServerConfigStore])
.service(DefaultServerService, [ServersService])
@@ -112,6 +118,7 @@ export function configureCloudModule(framework: Framework) {
GraphQLService,
GlobalState,
ServerService,
AuthProvider,
])
.entity(AuthSession, [AuthStore])
.service(SubscriptionService, [SubscriptionStore])

View File

@@ -0,0 +1,22 @@
import { createIdentifier } from '@toeverything/infra';
export interface AuthProvider {
signInMagicLink(email: string, token: string): Promise<void>;
signInOauth(
code: string,
state: string,
provider: string
): Promise<{ redirectUri?: string }>;
signInPassword(credential: {
email: string;
password: string;
verifyToken?: string;
challenge?: string;
}): Promise<void>;
signOut(): Promise<void>;
}
export const AuthProvider = createIdentifier<AuthProvider>('AuthProvider');

View File

@@ -112,13 +112,7 @@ export class AuthService extends Service {
async signInMagicLink(email: string, token: string, byLink = true) {
const method = byLink ? 'magic-link' : 'otp';
try {
await this.fetchService.fetch('/api/auth/magic-link', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ email, token }),
});
await this.store.signInMagicLink(email, token);
this.session.revalidate();
track.$.$.auth.signedIn({ method });
@@ -160,7 +154,7 @@ export class AuthService extends Service {
);
url = oauthUrl.toString();
return url;
return url as string;
} catch (e) {
track.$.$.auth.signInFail({
method: 'oauth',
@@ -173,18 +167,16 @@ export class AuthService extends Service {
async signInOauth(code: string, state: string, provider: string) {
try {
const res = await this.fetchService.fetch('/api/oauth/callback', {
method: 'POST',
body: JSON.stringify({ code, state }),
headers: {
'content-type': 'application/json',
},
});
const { redirectUri } = await this.store.signInOauth(
code,
state,
provider
);
this.session.revalidate();
track.$.$.auth.signedIn({ method: 'oauth', provider });
return await res.json();
return { redirectUri };
} catch (e) {
track.$.$.auth.signInFail({
method: 'oauth',
@@ -203,16 +195,7 @@ export class AuthService extends Service {
}) {
track.$.$.auth.signIn({ method: 'password' });
try {
await this.fetchService.fetch('/api/auth/sign-in', {
method: 'POST',
body: JSON.stringify(credential),
headers: {
'content-type': 'application/json',
...(credential.verifyToken
? this.captchaHeaders(credential.verifyToken, credential.challenge)
: {}),
},
});
await this.store.signInPassword(credential);
this.session.revalidate();
track.$.$.auth.signedIn({ method: 'password' });
} catch (e) {
@@ -225,7 +208,7 @@ export class AuthService extends Service {
}
async signOut() {
await this.fetchService.fetch('/api/auth/sign-out');
await this.store.signOut();
this.store.setCachedAuthSession(null);
this.session.revalidate();
}

View File

@@ -7,6 +7,7 @@ import { Store } from '@toeverything/infra';
import type { GlobalState } from '../../storage';
import type { AuthSessionInfo } from '../entities/session';
import type { AuthProvider } from '../provider/auth';
import type { FetchService } from '../services/fetch';
import type { GraphQLService } from '../services/graphql';
import type { ServerService } from '../services/server';
@@ -25,7 +26,8 @@ export class AuthStore extends Store {
private readonly fetchService: FetchService,
private readonly gqlService: GraphQLService,
private readonly globalState: GlobalState,
private readonly serverService: ServerService
private readonly serverService: ServerService,
private readonly authProvider: AuthProvider
) {
super();
}
@@ -63,6 +65,27 @@ export class AuthStore extends Store {
return data; // Return null if data empty
}
async signInMagicLink(email: string, token: string) {
await this.authProvider.signInMagicLink(email, token);
}
async signInOauth(code: string, state: string, provider: string) {
return await this.authProvider.signInOauth(code, state, provider);
}
async signInPassword(credential: {
email: string;
password: string;
verifyToken?: string;
challenge?: string;
}) {
await this.authProvider.signInPassword(credential);
}
async signOut() {
await this.authProvider.signOut();
}
async uploadAvatar(file: File) {
await this.gqlService.gql({
query: uploadAvatarMutation,