mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-05-08 22:07:32 +08:00
fix(server): test & schema
This commit is contained in:
@@ -469,6 +469,13 @@
|
||||
"type": "string",
|
||||
"description": "The account id for the cloudflare r2 storage provider."
|
||||
},
|
||||
"jurisdiction": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"eu"
|
||||
],
|
||||
"description": "Optional jurisdiction for the cloudflare r2 endpoint. Set to \"eu\" for EU buckets."
|
||||
},
|
||||
"usePresignedURL": {
|
||||
"type": "object",
|
||||
"description": "The presigned url config for the cloudflare r2 storage provider.",
|
||||
@@ -486,13 +493,6 @@
|
||||
"description": "The presigned key for the cloudflare r2 storage provider."
|
||||
}
|
||||
}
|
||||
},
|
||||
"jurisdiction": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"eu"
|
||||
],
|
||||
"description": "Optional jurisdiction for the cloudflare r2 endpoint. Set to \"eu\" for EU buckets."
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -667,6 +667,13 @@
|
||||
"type": "string",
|
||||
"description": "The account id for the cloudflare r2 storage provider."
|
||||
},
|
||||
"jurisdiction": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"eu"
|
||||
],
|
||||
"description": "Optional jurisdiction for the cloudflare r2 endpoint. Set to \"eu\" for EU buckets."
|
||||
},
|
||||
"usePresignedURL": {
|
||||
"type": "object",
|
||||
"description": "The presigned url config for the cloudflare r2 storage provider.",
|
||||
@@ -684,13 +691,6 @@
|
||||
"description": "The presigned key for the cloudflare r2 storage provider."
|
||||
}
|
||||
}
|
||||
},
|
||||
"jurisdiction": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"eu"
|
||||
],
|
||||
"description": "Optional jurisdiction for the cloudflare r2 endpoint. Set to \"eu\" for EU buckets."
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -861,11 +861,14 @@
|
||||
"properties": {
|
||||
"google": {
|
||||
"type": "object",
|
||||
"description": "Google Calendar integration config\n@default {\"enabled\":false,\"clientId\":\"\",\"clientSecret\":\"\",\"externalWebhookUrl\":\"\",\"webhookVerificationToken\":\"\",\"requestTimeoutMs\":10000}\n@link https://developers.google.com/calendar/api/guides/push",
|
||||
"description": "Google Calendar integration config\n@default {\"enabled\":false,\"allowNewAccounts\":true,\"clientId\":\"\",\"clientSecret\":\"\",\"externalWebhookUrl\":\"\",\"webhookVerificationToken\":\"\",\"requestTimeoutMs\":10000}\n@link https://developers.google.com/calendar/api/guides/push",
|
||||
"properties": {
|
||||
"enabled": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"allowNewAccounts": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"clientId": {
|
||||
"type": "string"
|
||||
},
|
||||
@@ -884,6 +887,7 @@
|
||||
},
|
||||
"default": {
|
||||
"enabled": false,
|
||||
"allowNewAccounts": true,
|
||||
"clientId": "",
|
||||
"clientSecret": "",
|
||||
"externalWebhookUrl": "",
|
||||
@@ -1296,6 +1300,13 @@
|
||||
"type": "string",
|
||||
"description": "The account id for the cloudflare r2 storage provider."
|
||||
},
|
||||
"jurisdiction": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"eu"
|
||||
],
|
||||
"description": "Optional jurisdiction for the cloudflare r2 endpoint. Set to \"eu\" for EU buckets."
|
||||
},
|
||||
"usePresignedURL": {
|
||||
"type": "object",
|
||||
"description": "The presigned url config for the cloudflare r2 storage provider.",
|
||||
@@ -1313,13 +1324,6 @@
|
||||
"description": "The presigned key for the cloudflare r2 storage provider."
|
||||
}
|
||||
}
|
||||
},
|
||||
"jurisdiction": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"eu"
|
||||
],
|
||||
"description": "Optional jurisdiction for the cloudflare r2 endpoint. Set to \"eu\" for EU buckets."
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -209,47 +209,77 @@ test('listAccounts includes calendars count', async t => {
|
||||
t.is(counts.get(accountB.id), 1);
|
||||
});
|
||||
|
||||
test('assertCanLinkProvider blocks new google calendar accounts when disabled', async t => {
|
||||
config.calendar.google.allowNewAccounts = false;
|
||||
const user = await module.create(Mockers.User);
|
||||
test.serial(
|
||||
'assertCanLinkProvider blocks new google calendar accounts when disabled',
|
||||
async t => {
|
||||
config.calendar.google.allowNewAccounts = false;
|
||||
const user = await module.create(Mockers.User);
|
||||
|
||||
const error = await t.throwsAsync(
|
||||
calendarService.assertCanLinkProvider(user.id, CalendarProviderName.Google)
|
||||
);
|
||||
t.true(error instanceof GraphqlBadRequest);
|
||||
t.is(
|
||||
(error as GraphqlBadRequest).data?.code,
|
||||
'calendar_provider_link_disabled'
|
||||
);
|
||||
});
|
||||
const error = await t.throwsAsync(
|
||||
calendarService.assertCanLinkProvider(
|
||||
user.id,
|
||||
CalendarProviderName.Google
|
||||
)
|
||||
);
|
||||
t.true(error instanceof GraphqlBadRequest);
|
||||
t.is(
|
||||
(error as GraphqlBadRequest).data?.code,
|
||||
'calendar_provider_link_disabled'
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
test('assertCanLinkProvider allows users with an existing google calendar account', async t => {
|
||||
config.calendar.google.allowNewAccounts = false;
|
||||
const user = await module.create(Mockers.User);
|
||||
await createAccount(user.id);
|
||||
test.serial(
|
||||
'assertCanLinkProvider allows users with an existing google calendar account',
|
||||
async t => {
|
||||
config.calendar.google.allowNewAccounts = false;
|
||||
const user = await module.create(Mockers.User);
|
||||
await createAccount(user.id);
|
||||
|
||||
await t.notThrowsAsync(
|
||||
calendarService.assertCanLinkProvider(user.id, CalendarProviderName.Google)
|
||||
);
|
||||
});
|
||||
await t.notThrowsAsync(
|
||||
calendarService.assertCanLinkProvider(
|
||||
user.id,
|
||||
CalendarProviderName.Google
|
||||
)
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
test('handleOAuthCallback does not persist new google account when linking is disabled', async t => {
|
||||
config.calendar.google.allowNewAccounts = false;
|
||||
const provider = new MockCalendarProvider();
|
||||
providerFactory.register(provider);
|
||||
const user = await module.create(Mockers.User);
|
||||
test.serial(
|
||||
'handleOAuthCallback does not persist new google account when linking is disabled',
|
||||
async t => {
|
||||
config.calendar.google.allowNewAccounts = false;
|
||||
const provider = new MockCalendarProvider();
|
||||
mock.method(providerFactory, 'get', () => provider);
|
||||
const user = await module.create(Mockers.User);
|
||||
|
||||
const error = await t.throwsAsync(
|
||||
calendarService.handleOAuthCallback({
|
||||
provider: CalendarProviderName.Google,
|
||||
code: 'code',
|
||||
redirectUri: 'https://example.com/callback',
|
||||
userId: user.id,
|
||||
})
|
||||
);
|
||||
t.true(error instanceof GraphqlBadRequest);
|
||||
t.is((await models.calendarAccount.listByUser(user.id)).length, 0);
|
||||
});
|
||||
const error = await t.throwsAsync(
|
||||
calendarService.handleOAuthCallback({
|
||||
provider: CalendarProviderName.Google,
|
||||
code: 'code',
|
||||
redirectUri: 'https://example.com/callback',
|
||||
userId: user.id,
|
||||
})
|
||||
);
|
||||
t.true(error instanceof GraphqlBadRequest);
|
||||
t.is((await models.calendarAccount.listByUser(user.id)).length, 0);
|
||||
}
|
||||
);
|
||||
|
||||
test.serial(
|
||||
'canLinkProvider returns false for new google calendar accounts when disabled',
|
||||
async t => {
|
||||
config.calendar.google.allowNewAccounts = false;
|
||||
const user = await module.create(Mockers.User);
|
||||
|
||||
t.false(
|
||||
await calendarService.canLinkProvider(
|
||||
user.id,
|
||||
CalendarProviderName.Google
|
||||
)
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
test('syncSubscription resets invalid sync token and maps events', async t => {
|
||||
const user = await module.create(Mockers.User);
|
||||
|
||||
@@ -33,17 +33,20 @@ import {
|
||||
export class CalendarServerConfigResolver {
|
||||
constructor(
|
||||
private readonly providerFactory: CalendarProviderFactory,
|
||||
private readonly config: Config
|
||||
private readonly config: Config,
|
||||
private readonly calendar: CalendarService
|
||||
) {}
|
||||
|
||||
@ResolveField(() => [CalendarProviderName])
|
||||
calendarProviders() {
|
||||
return this.providerFactory.providers.filter(provider => {
|
||||
return (
|
||||
provider !== CalendarProviderName.Google ||
|
||||
this.config.calendar.google.allowNewAccounts !== false
|
||||
);
|
||||
});
|
||||
async calendarProviders(@CurrentUser() user?: CurrentUser) {
|
||||
const providers = [];
|
||||
for (const provider of this.providerFactory.providers) {
|
||||
if (!(await this.calendar.canLinkProvider(user?.id, provider))) {
|
||||
continue;
|
||||
}
|
||||
providers.push(provider);
|
||||
}
|
||||
return providers;
|
||||
}
|
||||
|
||||
@ResolveField(() => [CalendarCalDAVProviderPresetObjectType])
|
||||
|
||||
@@ -571,18 +571,28 @@ export class CalendarService {
|
||||
}
|
||||
|
||||
async assertCanLinkProvider(userId: string, provider: CalendarProviderName) {
|
||||
if (this.canCreateNewAccounts(provider)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const accounts = await this.models.calendarAccount.listByUser(userId);
|
||||
if (accounts.some(account => account.provider === provider)) {
|
||||
if (await this.canLinkProvider(userId, provider)) {
|
||||
return;
|
||||
}
|
||||
|
||||
throw this.providerLinkDisabledError(provider);
|
||||
}
|
||||
|
||||
async canLinkProvider(
|
||||
userId: string | null | undefined,
|
||||
provider: CalendarProviderName
|
||||
) {
|
||||
if (this.canCreateNewAccounts(provider)) {
|
||||
return true;
|
||||
}
|
||||
if (!userId) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const accounts = await this.models.calendarAccount.listByUser(userId);
|
||||
return accounts.some(account => account.provider === provider);
|
||||
}
|
||||
|
||||
getAuthUrl(
|
||||
provider: CalendarProviderName,
|
||||
state: string,
|
||||
|
||||
Reference in New Issue
Block a user