@stamhoofd/backend 2.137.4 → 2.137.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +23 -17
- package/src/crons/drip-emails.ts +2 -1
- package/src/crons.ts +4 -2
- package/src/email-recipient-loaders/payments.ts +3 -2
- package/src/endpoints/auth/CreateAdminEndpoint.ts +3 -2
- package/src/endpoints/auth/CreateTokenEndpoint.ts +2 -1
- package/src/endpoints/auth/ForgotPasswordEndpoint.ts +3 -2
- package/src/endpoints/auth/PatchUserEndpoint.ts +6 -3
- package/src/endpoints/auth/RetryEmailVerificationEndpoint.ts +2 -1
- package/src/endpoints/auth/SignupEndpoint.ts +4 -2
- package/src/endpoints/global/email/CreateEmailEndpoint.ts +2 -1
- package/src/endpoints/global/email/GetAdminEmailsEndpoint.test.ts +1 -1
- package/src/endpoints/global/email/GetAdminEmailsEndpoint.ts +2 -1
- package/src/endpoints/global/email/GetEmailEndpoint.ts +2 -1
- package/src/endpoints/global/email/GetUserEmailsEndpoint.test.ts +1 -1
- package/src/endpoints/global/email/GetUserEmailsEndpoint.ts +2 -1
- package/src/endpoints/global/email/PatchEmailEndpoint.ts +2 -1
- package/src/endpoints/global/files/ExportToExcelEndpoint.ts +9 -5
- package/src/endpoints/global/files/UploadFile.test.ts +206 -0
- package/src/endpoints/global/files/UploadFile.ts +31 -6
- package/src/endpoints/global/files/UploadImage.test.ts +177 -0
- package/src/endpoints/global/files/UploadImage.ts +23 -4
- package/src/endpoints/global/files/upload-security.test.ts +837 -0
- package/src/endpoints/global/members/PatchOrganizationMembersEndpoint.ts +1 -1
- package/src/endpoints/global/organizations/CreateOrganizationEndpoint.ts +2 -1
- package/src/endpoints/organization/dashboard/documents/GetDocumentTemplateXML.ts +2 -1
- package/src/endpoints/organization/dashboard/organization/SetOrganizationDomainEndpoint.ts +3 -2
- package/src/endpoints/organization/dashboard/users/PatchApiUserEndpoint.ts +5 -3
- package/src/endpoints/organization/dashboard/webshops/PatchWebshopOrdersEndpoint.ts +4 -3
- package/src/endpoints/organization/shared/GetDocumentHtml.ts +2 -1
- package/src/endpoints/organization/webshops/PlaceOrderEndpoint.ts +4 -3
- package/src/excel-loaders/balance-items.ts +1 -1
- package/src/excel-loaders/event-notifications.ts +6 -7
- package/src/excel-loaders/members.test.ts +2 -2
- package/src/excel-loaders/members.ts +9 -10
- package/src/excel-loaders/organizations.ts +14 -20
- package/src/excel-loaders/payments.ts +1 -1
- package/src/excel-loaders/platform-memberships.ts +7 -7
- package/src/excel-loaders/platform-sheets.test.ts +113 -0
- package/src/excel-loaders/receivable-balances.ts +1 -1
- package/src/excel-loaders/registrations.ts +9 -9
- package/src/helpers/AdminPermissionChecker.ts +1 -1
- package/src/helpers/AuthenticatedStructures.ts +12 -9
- package/src/helpers/MembershipCharger.ts +3 -2
- package/src/services/BalanceItemService.ts +2 -1
- package/src/services/DocumentRenderService.test.ts +229 -0
- package/src/services/DocumentRenderService.ts +180 -0
- package/src/services/EmailPreviewService.test.ts +300 -0
- package/src/services/EmailPreviewService.ts +239 -0
- package/src/services/FileSignService.test.ts +85 -0
- package/src/services/FileSignService.ts +23 -1
- package/src/services/OrderService.test.ts +308 -0
- package/src/services/OrderService.ts +214 -0
- package/src/services/OrganizationDNSService.test.ts +177 -0
- package/src/services/OrganizationDNSService.ts +282 -0
- package/src/services/OrganizationEmailService.test.ts +57 -0
- package/src/services/OrganizationEmailService.ts +211 -0
- package/src/services/PasswordForgotService.test.ts +99 -0
- package/src/services/PasswordForgotService.ts +38 -0
- package/src/services/PlatformMembershipService.test.ts +180 -0
- package/src/services/PlatformMembershipService.ts +281 -4
- package/src/services/RegistrationService.ts +3 -2
- package/src/services/STPackageService.test.ts +191 -0
- package/src/services/STPackageService.ts +114 -2
- package/src/services/VerificationCodeService.test.ts +71 -0
- package/src/services/VerificationCodeService.ts +100 -0
- package/tests/e2e/documents.test.ts +2 -1
- package/tests/e2e/private-files.test.ts +77 -14
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { I18n } from '@stamhoofd/backend-i18n';
|
|
2
|
+
import { EmailMocker } from '@stamhoofd/email';
|
|
3
|
+
import { EmailTemplateFactory, EmailVerificationCode, OrganizationFactory, Platform, UserFactory } from '@stamhoofd/models';
|
|
4
|
+
import { EmailTemplateType } from '@stamhoofd/structures';
|
|
5
|
+
import { TestUtils } from '@stamhoofd/test-utils';
|
|
6
|
+
import { VerificationCodeService } from './VerificationCodeService.js';
|
|
7
|
+
|
|
8
|
+
const i18n = new I18n(I18n.defaultLanguage, I18n.defaultCountry);
|
|
9
|
+
|
|
10
|
+
const PLATFORM_NAME = 'The test platform';
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* A template that only contains the organizationName replacement, so the name that ends up in the
|
|
14
|
+
* email can be asserted without depending on the real (translated) template contents.
|
|
15
|
+
*/
|
|
16
|
+
async function createVerifyEmailTemplate() {
|
|
17
|
+
await new EmailTemplateFactory({
|
|
18
|
+
type: EmailTemplateType.VerifyEmail,
|
|
19
|
+
html: '<p>{{organizationName}}</p>',
|
|
20
|
+
text: '{{organizationName}}',
|
|
21
|
+
}).create();
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
describe('VerificationCodeService', () => {
|
|
25
|
+
let originalPlatformName: string;
|
|
26
|
+
|
|
27
|
+
beforeAll(async () => {
|
|
28
|
+
const platform = await Platform.getForEditing();
|
|
29
|
+
originalPlatformName = platform.config.name;
|
|
30
|
+
platform.config.name = PLATFORM_NAME;
|
|
31
|
+
await platform.save();
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
afterAll(async () => {
|
|
35
|
+
const platform = await Platform.getForEditing();
|
|
36
|
+
platform.config.name = originalPlatformName;
|
|
37
|
+
await platform.save();
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
describe('send', () => {
|
|
41
|
+
test('Uses the name of the organization when the code is scoped to an organization', async () => {
|
|
42
|
+
TestUtils.setEnvironment('userMode', 'organization');
|
|
43
|
+
await createVerifyEmailTemplate();
|
|
44
|
+
|
|
45
|
+
const organization = await new OrganizationFactory({ name: 'Organization with a name' }).create();
|
|
46
|
+
const user = await new UserFactory({ organization }).create();
|
|
47
|
+
const code = await EmailVerificationCode.createFor(user, user.email);
|
|
48
|
+
|
|
49
|
+
await VerificationCodeService.send(code, user, organization, i18n);
|
|
50
|
+
|
|
51
|
+
const emails = await EmailMocker.transactional.getSucceededEmails();
|
|
52
|
+
expect(emails.length).toBe(1);
|
|
53
|
+
expect(emails[0].text).toContain('Organization with a name');
|
|
54
|
+
expect(emails[0].text).not.toContain(PLATFORM_NAME);
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
test('Falls back to the name of the platform when there is no organization', async () => {
|
|
58
|
+
TestUtils.setEnvironment('userMode', 'platform');
|
|
59
|
+
await createVerifyEmailTemplate();
|
|
60
|
+
|
|
61
|
+
const user = await new UserFactory({}).create();
|
|
62
|
+
const code = await EmailVerificationCode.createFor(user, user.email);
|
|
63
|
+
|
|
64
|
+
await VerificationCodeService.send(code, user, null, i18n);
|
|
65
|
+
|
|
66
|
+
const emails = await EmailMocker.transactional.getSucceededEmails();
|
|
67
|
+
expect(emails.length).toBe(1);
|
|
68
|
+
expect(emails[0].text).toContain(PLATFORM_NAME);
|
|
69
|
+
});
|
|
70
|
+
});
|
|
71
|
+
});
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import type { I18n } from '@stamhoofd/backend-i18n';
|
|
2
|
+
import type { Organization } from '@stamhoofd/models';
|
|
3
|
+
import { EmailVerificationCode, Platform, sendEmailTemplate, User } from '@stamhoofd/models';
|
|
4
|
+
import { EmailTemplateType, getAppHost, Recipient, Replacement } from '@stamhoofd/structures';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Sends the verification emails for an EmailVerificationCode. The code itself is generated, stored
|
|
8
|
+
* and verified on the model.
|
|
9
|
+
*/
|
|
10
|
+
export class VerificationCodeService {
|
|
11
|
+
static getEmailVerificationUrl(code: EmailVerificationCode, user: User, organization: Organization | null, i18n: I18n) {
|
|
12
|
+
const host = getAppHost('verify-email', organization, !!user.permissions, i18n);
|
|
13
|
+
return 'https://' + host + '?code=' + encodeURIComponent(code.code) + '&token=' + encodeURIComponent(code.token) + '&email=' + encodeURIComponent(code.email);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
static async send(code: EmailVerificationCode, user: User, organization: Organization | null, i18n: I18n, withCode = true) {
|
|
17
|
+
const url = this.getEmailVerificationUrl(code, user, organization, i18n);
|
|
18
|
+
|
|
19
|
+
const name = organization?.name ?? (await Platform.getSharedPrivateStruct()).config.name;
|
|
20
|
+
|
|
21
|
+
const replacements: Replacement[] = [
|
|
22
|
+
Replacement.create({
|
|
23
|
+
token: 'organizationName',
|
|
24
|
+
value: name,
|
|
25
|
+
}),
|
|
26
|
+
Replacement.create({
|
|
27
|
+
token: 'confirmEmailUrl',
|
|
28
|
+
value: url,
|
|
29
|
+
}),
|
|
30
|
+
];
|
|
31
|
+
|
|
32
|
+
if (withCode) {
|
|
33
|
+
const formattedCode = code.code.substr(0, 3) + ' ' + code.code.substr(3);
|
|
34
|
+
|
|
35
|
+
await sendEmailTemplate(organization, {
|
|
36
|
+
recipients: [
|
|
37
|
+
Recipient.create({
|
|
38
|
+
email: code.email,
|
|
39
|
+
replacements: [
|
|
40
|
+
...replacements,
|
|
41
|
+
Replacement.create({
|
|
42
|
+
token: 'confirmEmailCode',
|
|
43
|
+
value: formattedCode,
|
|
44
|
+
}),
|
|
45
|
+
],
|
|
46
|
+
}),
|
|
47
|
+
],
|
|
48
|
+
template: {
|
|
49
|
+
type: EmailTemplateType.VerifyEmail,
|
|
50
|
+
},
|
|
51
|
+
type: 'transactional',
|
|
52
|
+
});
|
|
53
|
+
} else {
|
|
54
|
+
await sendEmailTemplate(organization, {
|
|
55
|
+
recipients: [
|
|
56
|
+
Recipient.create({
|
|
57
|
+
email: code.email,
|
|
58
|
+
replacements,
|
|
59
|
+
}),
|
|
60
|
+
],
|
|
61
|
+
template: {
|
|
62
|
+
type: EmailTemplateType.VerifyEmailWithoutCode,
|
|
63
|
+
},
|
|
64
|
+
type: 'transactional',
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
static async resend(organization: Organization | null, token: string, i18n: I18n) {
|
|
70
|
+
const verificationCodes = await EmailVerificationCode.where({
|
|
71
|
+
token,
|
|
72
|
+
organizationId: organization
|
|
73
|
+
? {
|
|
74
|
+
sign: 'IN',
|
|
75
|
+
value: [organization.id, null],
|
|
76
|
+
}
|
|
77
|
+
: null,
|
|
78
|
+
}, { limit: 1 });
|
|
79
|
+
|
|
80
|
+
if (verificationCodes.length == 0) {
|
|
81
|
+
console.log("Can't resend code, no coded found for token", token);
|
|
82
|
+
// TODO: maybe send a note via email
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
const verificationCode = verificationCodes[0];
|
|
87
|
+
|
|
88
|
+
if (verificationCode.expiresAt < new Date()) {
|
|
89
|
+
// Don't report error, could be brute forced
|
|
90
|
+
console.log("Can't resend code, token is expired", token);
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
const user = await User.getByID(verificationCode.userId);
|
|
95
|
+
if (!user) {
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
await this.send(verificationCode, user, organization, i18n);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
@@ -12,6 +12,7 @@ import { testServer } from '../helpers/TestServer.js';
|
|
|
12
12
|
import { initAdmin } from '../init/initAdmin.js';
|
|
13
13
|
import { initStripe } from '../init/initStripe.js';
|
|
14
14
|
import { registrationUpdateQueue } from '../../src/services/BalanceItemService.js';
|
|
15
|
+
import { DocumentRenderService } from '../../src/services/DocumentRenderService.js';
|
|
15
16
|
import { initMembershipOrganization } from '../init/initMembershipOrganization.js';
|
|
16
17
|
|
|
17
18
|
const baseUrl = `/members/register`;
|
|
@@ -119,7 +120,7 @@ describe('E2E.Documents', () => {
|
|
|
119
120
|
const document = await Document.select().where('registrationId', registration.id).first(false);
|
|
120
121
|
expect(document).not.toBeNull();
|
|
121
122
|
|
|
122
|
-
const html = await
|
|
123
|
+
const html = await DocumentRenderService.getRenderedHtml(document!, organization);
|
|
123
124
|
|
|
124
125
|
const registrationModel = (await Registration.getByID(registration.id))!;
|
|
125
126
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { File, MemberDetails, MemberWithRegistrationsBlob, RecordCategory, RecordFileAnswer, RecordSettings, RecordType, TranslatedString, Version } from '@stamhoofd/structures';
|
|
2
2
|
|
|
3
3
|
import type { PatchableArrayAutoEncoder } from '@simonbackx/simple-encoding';
|
|
4
|
-
import { PatchableArray } from '@simonbackx/simple-encoding';
|
|
4
|
+
import { encodeObject, EncodeMedium, PatchableArray } from '@simonbackx/simple-encoding';
|
|
5
5
|
import { Request } from '@simonbackx/simple-endpoints';
|
|
6
6
|
import { Member, OrganizationFactory, Token, UserFactory } from '@stamhoofd/models';
|
|
7
7
|
import { PermissionLevel, Permissions } from '@stamhoofd/structures';
|
|
@@ -62,7 +62,7 @@ describe('E2E.PrivateFiles', () => {
|
|
|
62
62
|
// access to the signed URL. This should not be possible without a valid signature
|
|
63
63
|
const privateFile = new File({
|
|
64
64
|
id: 'test',
|
|
65
|
-
server: 'test.com',
|
|
65
|
+
server: 'https://test.com',
|
|
66
66
|
path: 'test.txt',
|
|
67
67
|
size: 100,
|
|
68
68
|
isPrivate: true,
|
|
@@ -105,7 +105,7 @@ describe('E2E.PrivateFiles', () => {
|
|
|
105
105
|
// access to the signed URL. This should not be possible without a valid signature
|
|
106
106
|
const privateFile = new File({
|
|
107
107
|
id: 'test',
|
|
108
|
-
server: 'test.com',
|
|
108
|
+
server: 'https://test.com',
|
|
109
109
|
path: 'test.txt',
|
|
110
110
|
size: 100,
|
|
111
111
|
isPrivate: true,
|
|
@@ -149,7 +149,7 @@ describe('E2E.PrivateFiles', () => {
|
|
|
149
149
|
// access to the signed URL. This should not be possible without a valid signature
|
|
150
150
|
const privateFile = new File({
|
|
151
151
|
id: 'test',
|
|
152
|
-
server: 'test.com',
|
|
152
|
+
server: 'https://test.com',
|
|
153
153
|
path: 'test.txt',
|
|
154
154
|
size: 100,
|
|
155
155
|
isPrivate: true,
|
|
@@ -188,6 +188,69 @@ describe('E2E.PrivateFiles', () => {
|
|
|
188
188
|
expect(answer.file!.signedUrl).toBeTruthy();
|
|
189
189
|
});
|
|
190
190
|
|
|
191
|
+
test('Cannot set a public file with a url a browser would run as code', async () => {
|
|
192
|
+
const organization = await createOrganization();
|
|
193
|
+
|
|
194
|
+
const user = await new UserFactory({
|
|
195
|
+
organization,
|
|
196
|
+
permissions: Permissions.create({
|
|
197
|
+
level: PermissionLevel.Full,
|
|
198
|
+
}),
|
|
199
|
+
}).create();
|
|
200
|
+
const token = await Token.createToken(user);
|
|
201
|
+
|
|
202
|
+
// Public files are not signed, so a malicious user can put anything in them. The url of a file ends up
|
|
203
|
+
// in a link (and in the source of an image), so a javascript: url would run on our own domain.
|
|
204
|
+
const buildBody = (server: string) => {
|
|
205
|
+
const member = MemberWithRegistrationsBlob.create({
|
|
206
|
+
details: MemberDetails.create({
|
|
207
|
+
firstName: 'John',
|
|
208
|
+
lastName: 'Doe',
|
|
209
|
+
}),
|
|
210
|
+
});
|
|
211
|
+
|
|
212
|
+
member.details.recordAnswers.set(recordSettings.id, RecordFileAnswer.create({
|
|
213
|
+
file: new File({
|
|
214
|
+
id: 'test',
|
|
215
|
+
server: 'https://replace-me.example.com',
|
|
216
|
+
path: 'test.pdf',
|
|
217
|
+
size: 100,
|
|
218
|
+
isPrivate: false,
|
|
219
|
+
}),
|
|
220
|
+
settings: recordSettings,
|
|
221
|
+
}));
|
|
222
|
+
|
|
223
|
+
const arr = new PatchableArray() as PatchableArrayAutoEncoder<MemberWithRegistrationsBlob>;
|
|
224
|
+
arr.addPut(member);
|
|
225
|
+
|
|
226
|
+
// An attacker doesn't use our client, so build the request body they would send instead
|
|
227
|
+
const encoded = encodeObject(arr, { version: Version, medium: EncodeMedium.Network });
|
|
228
|
+
return JSON.parse(JSON.stringify(encoded).replaceAll('https://replace-me.example.com', server));
|
|
229
|
+
};
|
|
230
|
+
|
|
231
|
+
const attacks = [
|
|
232
|
+
{ server: 'javascript:alert(document.domain)', error: /can only be http or https/i },
|
|
233
|
+
{ server: 'data:text/html,<script>alert(1)</script>', error: /can only be http or https/i },
|
|
234
|
+
{ server: 'not-a-url', error: /invalid url for a file/i },
|
|
235
|
+
{ server: '', error: /invalid url for a file/i },
|
|
236
|
+
];
|
|
237
|
+
|
|
238
|
+
for (const attack of attacks) {
|
|
239
|
+
const r = Request.buildJson('PATCH', baseUrl, organization.getApiHost(), buildBody(attack.server));
|
|
240
|
+
r.headers.authorization = 'Bearer ' + token.accessToken;
|
|
241
|
+
|
|
242
|
+
await expect(testServer.test(endpoint, r), attack.server).rejects.toThrow(attack.error);
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
// ... and our own code can never store one either
|
|
246
|
+
expect(() => Request.buildJson('PATCH', baseUrl, organization.getApiHost(), new File({
|
|
247
|
+
id: 'test',
|
|
248
|
+
server: 'javascript:alert(document.domain)',
|
|
249
|
+
path: 'test.pdf',
|
|
250
|
+
size: 100,
|
|
251
|
+
}))).toThrow(/can only be http or https/i);
|
|
252
|
+
});
|
|
253
|
+
|
|
191
254
|
test('Can set public files', async () => {
|
|
192
255
|
const organization = await createOrganization();
|
|
193
256
|
|
|
@@ -211,7 +274,7 @@ describe('E2E.PrivateFiles', () => {
|
|
|
211
274
|
// access to the signed URL. This should not be possible without a valid signature
|
|
212
275
|
const publicFile = new File({
|
|
213
276
|
id: 'test',
|
|
214
|
-
server: 'test.com',
|
|
277
|
+
server: 'https://test.com',
|
|
215
278
|
path: 'test.txt',
|
|
216
279
|
size: 100,
|
|
217
280
|
isPrivate: false,
|
|
@@ -275,7 +338,7 @@ describe('E2E.PrivateFiles', () => {
|
|
|
275
338
|
// access to the signed URL. This should not be possible without a valid signature
|
|
276
339
|
const maliciousFile = new File({
|
|
277
340
|
id: 'test',
|
|
278
|
-
server: 'test.com',
|
|
341
|
+
server: 'https://test.com',
|
|
279
342
|
path: 'test.txt',
|
|
280
343
|
size: 100,
|
|
281
344
|
isPrivate: true,
|
|
@@ -355,7 +418,7 @@ describe('E2E.PrivateFiles', () => {
|
|
|
355
418
|
// access to the signed URL. This should not be possible without a valid signature
|
|
356
419
|
const maliciousFile = new File({
|
|
357
420
|
id: 'test',
|
|
358
|
-
server: 'test.com',
|
|
421
|
+
server: 'https://test.com',
|
|
359
422
|
path: 'test.txt',
|
|
360
423
|
size: 100,
|
|
361
424
|
isPrivate: true,
|
|
@@ -418,7 +481,7 @@ describe('E2E.PrivateFiles', () => {
|
|
|
418
481
|
// access to the signed URL. This should not be possible without a valid signature
|
|
419
482
|
const privateFile = new File({
|
|
420
483
|
id: 'test',
|
|
421
|
-
server: 'test.com',
|
|
484
|
+
server: 'https://test.com',
|
|
422
485
|
path: 'test.txt',
|
|
423
486
|
size: 100,
|
|
424
487
|
isPrivate: true,
|
|
@@ -447,7 +510,7 @@ describe('E2E.PrivateFiles', () => {
|
|
|
447
510
|
// access to the signed URL. This should not be possible without a valid signature
|
|
448
511
|
const privateFile = new File({
|
|
449
512
|
id: 'test',
|
|
450
|
-
server: 'test.com',
|
|
513
|
+
server: 'https://test.com',
|
|
451
514
|
path: 'test.txt',
|
|
452
515
|
size: 100,
|
|
453
516
|
isPrivate: true,
|
|
@@ -481,7 +544,7 @@ describe('E2E.PrivateFiles', () => {
|
|
|
481
544
|
// access to the signed URL. This should not be possible without a valid signature
|
|
482
545
|
const privateFile = new File({
|
|
483
546
|
id: 'test',
|
|
484
|
-
server: 'test.com',
|
|
547
|
+
server: 'https://test.com',
|
|
485
548
|
path: 'test.txt',
|
|
486
549
|
size: 100,
|
|
487
550
|
isPrivate: true,
|
|
@@ -509,7 +572,7 @@ describe('E2E.PrivateFiles', () => {
|
|
|
509
572
|
// access to the signed URL. This should not be possible without a valid signature
|
|
510
573
|
const privateFile = new File({
|
|
511
574
|
id: 'test',
|
|
512
|
-
server: 'test.com',
|
|
575
|
+
server: 'https://test.com',
|
|
513
576
|
path: 'test.txt',
|
|
514
577
|
size: 100,
|
|
515
578
|
isPrivate: true,
|
|
@@ -537,7 +600,7 @@ describe('E2E.PrivateFiles', () => {
|
|
|
537
600
|
// access to the signed URL. This should not be possible without a valid signature
|
|
538
601
|
const privateFile = new File({
|
|
539
602
|
id: 'test',
|
|
540
|
-
server: 'test.com',
|
|
603
|
+
server: 'https://test.com',
|
|
541
604
|
path: 'test.txt',
|
|
542
605
|
size: 100,
|
|
543
606
|
isPrivate: true,
|
|
@@ -564,7 +627,7 @@ describe('E2E.PrivateFiles', () => {
|
|
|
564
627
|
// access to the signed URL. This should not be possible without a valid signature
|
|
565
628
|
const privateFile = new File({
|
|
566
629
|
id: 'test',
|
|
567
|
-
server: 'test.com',
|
|
630
|
+
server: 'https://test.com',
|
|
568
631
|
path: 'test.txt',
|
|
569
632
|
size: 100,
|
|
570
633
|
isPrivate: true,
|
|
@@ -613,7 +676,7 @@ describe('E2E.PrivateFiles', () => {
|
|
|
613
676
|
// access to the signed URL. This should not be possible without a valid signature
|
|
614
677
|
const maliciousFile = new File({
|
|
615
678
|
id: 'test',
|
|
616
|
-
server: 'test.com',
|
|
679
|
+
server: 'https://test.com',
|
|
617
680
|
path: 'test.txt',
|
|
618
681
|
size: 100,
|
|
619
682
|
isPrivate: true,
|