Skip to content

Commit 48cfd2c

Browse files
committed
s3: fix attachments not uploading on self hosted servers
this was due to s3 endpoints requesting user's subscription which didn't exist in case of self hosted setups
1 parent 32b24de commit 48cfd2c

File tree

4 files changed

+51
-39
lines changed

4 files changed

+51
-39
lines changed

.env

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ INSTANCE_NAME=self-hosted-notesnook-instance
55

66
# Description: This secret is used for generating, validating, and introspecting auth tokens. It must be a randomly generated token (preferably >32 characters).
77
# Required: yes
8-
NOTESNOOK_API_SECRET=
8+
NOTESNOOK_API_SECRET=localhost-api-secret
99

1010
# Description: Use this flag to disable creation of new accounts on your instance (i.e. in case it is exposed to the Internet).
1111
# Required: yes
@@ -17,18 +17,18 @@ DISABLE_SIGNUPS=false
1717

1818
# Description: Username for the SMTP connection (most time it is the email address of your account). Check your email provider's documentation to get the appropriate value.
1919
# Required: yes
20-
SMTP_USERNAME=
20+
SMTP_USERNAME=AKIARYIUZPO7PJ7PSXVL
2121
# Description: Password for the SMTP connection. Check your email provider's documentation to get the appropriate value.
2222
# Required: yes
23-
SMTP_PASSWORD=
23+
SMTP_PASSWORD=BNKYnxkV6nFrn0Tji8Bhi6eIdFclLVNGQCCJEV4fH3Pl
2424
# Description: Host on which the the SMTP connection is running. Check your email provider's documentation to get the appropriate value.
2525
# Required: yes
2626
# Example: smtp.gmail.com
27-
SMTP_HOST=
27+
SMTP_HOST=email-smtp.us-west-2.amazonaws.com
2828
# Description: Port on which the the SMTP connection is running. Check your email provider's documentation to get the appropriate value.
2929
# Required: yes
3030
# Example: 465
31-
SMTP_PORT=
31+
SMTP_PORT=587
3232

3333
# Description: Twilio account SID is required for sending SMS with 2FA codes. Learn more here: https://help.twilio.com/articles/14726256820123-What-is-a-Twilio-Account-SID-and-where-can-I-find-it-
3434
# Required: no
@@ -50,7 +50,7 @@ NOTESNOOK_CORS_ORIGINS=
5050
# Note: the URL has no slashes at the end
5151
# Required: yes
5252
# Example: https://app.notesnook.com
53-
NOTESNOOK_APP_PUBLIC_URL=https://app.notesnook.com
53+
NOTESNOOK_APP_PUBLIC_URL=http://localhost:3000
5454
# Description: This is the public URL for the monograph frontend.
5555
# Required: yes
5656
# Example: https://monogr.ph

Notesnook.API/Controllers/AnnouncementController.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,10 +42,10 @@ public AnnouncementController(Repository<Announcement> announcements)
4242

4343
[HttpGet("active")]
4444
[AllowAnonymous]
45-
public async Task<IActionResult> GetActiveAnnouncements([FromQuery] string userId)
45+
public async Task<IActionResult> GetActiveAnnouncements([FromQuery] string? userId)
4646
{
4747
var totalActive = await Announcements.Collection.CountDocumentsAsync(Builders<Announcement>.Filter.Eq("IsActive", true));
48-
if (totalActive <= 0) return Ok(new Announcement[] { });
48+
if (totalActive <= 0) return Ok(Array.Empty<Announcement>());
4949

5050
var announcements = (await Announcements.FindAsync((a) => a.IsActive)).Where((a) => a.UserIds == null || a.UserIds.Length == 0 || a.UserIds.Contains(userId));
5151
foreach (var announcement in announcements)

Notesnook.API/Controllers/S3Controller.cs

Lines changed: 20 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -63,21 +63,24 @@ public async Task<IActionResult> Upload([FromQuery] string name)
6363
return Ok(uploadUrl);
6464
}
6565

66-
var subscriptionService = await WampServers.SubscriptionServer.GetServiceAsync<IUserSubscriptionService>(SubscriptionServerTopics.UserSubscriptionServiceTopic);
67-
var subscription = await subscriptionService.GetUserSubscriptionAsync(Clients.Notesnook.Id, userId);
68-
if (subscription is null) return BadRequest(new { error = "User subscription not found." });
69-
70-
if (StorageHelper.IsFileSizeExceeded(subscription, fileSize))
66+
var userSettings = await Repositories.UsersSettings.FindOneAsync((u) => u.UserId == userId);
67+
if (!Constants.IS_SELF_HOSTED)
7168
{
72-
return BadRequest(new { error = "Max file size exceeded." });
69+
var subscriptionService = await WampServers.SubscriptionServer.GetServiceAsync<IUserSubscriptionService>(SubscriptionServerTopics.UserSubscriptionServiceTopic);
70+
var subscription = await subscriptionService.GetUserSubscriptionAsync(Clients.Notesnook.Id, userId);
71+
if (subscription is null) return BadRequest(new { error = "User subscription not found." });
72+
73+
if (StorageHelper.IsFileSizeExceeded(subscription, fileSize))
74+
{
75+
return BadRequest(new { error = "Max file size exceeded." });
76+
}
77+
78+
userSettings.StorageLimit ??= new Limit { Value = 0, UpdatedAt = 0 };
79+
userSettings.StorageLimit.Value += fileSize;
80+
if (StorageHelper.IsStorageLimitReached(subscription, userSettings.StorageLimit))
81+
return BadRequest(new { error = "Storage limit exceeded." });
7382
}
7483

75-
var userSettings = await Repositories.UsersSettings.FindOneAsync((u) => u.UserId == userId);
76-
userSettings.StorageLimit ??= new Limit { Value = 0, UpdatedAt = 0 };
77-
userSettings.StorageLimit.Value += fileSize;
78-
if (StorageHelper.IsStorageLimitReached(subscription, userSettings.StorageLimit))
79-
return BadRequest(new { error = "Storage limit exceeded." });
80-
8184
var url = S3Service.GetUploadObjectUrl(userId, name);
8285
if (url == null) return BadRequest(new { error = "Could not create signed url." });
8386

@@ -87,8 +90,11 @@ public async Task<IActionResult> Upload([FromQuery] string name)
8790
var response = await httpClient.SendRequestAsync<Response>(url, null, HttpMethod.Put, content);
8891
if (!response.Success) return BadRequest(await response.Content.ReadAsStringAsync());
8992

90-
userSettings.StorageLimit.UpdatedAt = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
91-
await Repositories.UsersSettings.UpsertAsync(userSettings, (u) => u.UserId == userId);
93+
if (!Constants.IS_SELF_HOSTED)
94+
{
95+
userSettings.StorageLimit.UpdatedAt = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
96+
await Repositories.UsersSettings.UpsertAsync(userSettings, (u) => u.UserId == userId);
97+
}
9298

9399
return Ok(response);
94100
}

Notesnook.API/Services/S3Service.cs

Lines changed: 23 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -229,38 +229,44 @@ public async Task CompleteMultipartUploadAsync(string userId, CompleteMultipartU
229229
var objectName = GetFullObjectName(userId, uploadRequest.Key);
230230
if (userId == null || objectName == null) throw new Exception("Could not abort multipart upload.");
231231

232-
var subscriptionService = await WampServers.SubscriptionServer.GetServiceAsync<IUserSubscriptionService>(SubscriptionServerTopics.UserSubscriptionServiceTopic);
233-
var subscription = await subscriptionService.GetUserSubscriptionAsync(Clients.Notesnook.Id, userId) ?? throw new Exception("User subscription not found.");
234-
235-
long fileSize = await GetMultipartUploadSizeAsync(userId, uploadRequest.Key, uploadRequest.UploadId);
236-
if (StorageHelper.IsFileSizeExceeded(subscription, fileSize))
237-
{
238-
await this.AbortMultipartUploadAsync(userId, uploadRequest.Key, uploadRequest.UploadId);
239-
throw new Exception("Max file size exceeded.");
240-
}
241-
242232
var userSettings = await Repositories.UsersSettings.FindOneAsync((u) => u.UserId == userId);
243233
if (userSettings == null)
244234
{
245235
await this.AbortMultipartUploadAsync(userId, uploadRequest.Key, uploadRequest.UploadId);
246236
throw new Exception("User settings not found.");
247237
}
248238

249-
userSettings.StorageLimit ??= new Limit { Value = 0, UpdatedAt = 0 };
250-
userSettings.StorageLimit.Value += fileSize;
251-
if (StorageHelper.IsStorageLimitReached(subscription, userSettings.StorageLimit))
239+
if (!Constants.IS_SELF_HOSTED)
252240
{
253-
await this.AbortMultipartUploadAsync(userId, uploadRequest.Key, uploadRequest.UploadId);
254-
throw new Exception("Storage limit reached.");
241+
var subscriptionService = await WampServers.SubscriptionServer.GetServiceAsync<IUserSubscriptionService>(SubscriptionServerTopics.UserSubscriptionServiceTopic);
242+
var subscription = await subscriptionService.GetUserSubscriptionAsync(Clients.Notesnook.Id, userId) ?? throw new Exception("User subscription not found.");
243+
244+
long fileSize = await GetMultipartUploadSizeAsync(userId, uploadRequest.Key, uploadRequest.UploadId);
245+
if (StorageHelper.IsFileSizeExceeded(subscription, fileSize))
246+
{
247+
await this.AbortMultipartUploadAsync(userId, uploadRequest.Key, uploadRequest.UploadId);
248+
throw new Exception("Max file size exceeded.");
249+
}
250+
251+
userSettings.StorageLimit ??= new Limit { Value = 0, UpdatedAt = 0 };
252+
userSettings.StorageLimit.Value += fileSize;
253+
if (StorageHelper.IsStorageLimitReached(subscription, userSettings.StorageLimit))
254+
{
255+
await this.AbortMultipartUploadAsync(userId, uploadRequest.Key, uploadRequest.UploadId);
256+
throw new Exception("Storage limit reached.");
257+
}
255258
}
256259

257260
uploadRequest.Key = objectName;
258261
uploadRequest.BucketName = GetBucketName(S3ClientMode.INTERNAL);
259262
var response = await GetS3Client(S3ClientMode.INTERNAL).CompleteMultipartUploadAsync(uploadRequest);
260263
if (!IsSuccessStatusCode(((int)response.HttpStatusCode))) throw new Exception("Failed to complete multipart upload.");
261264

262-
userSettings.StorageLimit.UpdatedAt = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
263-
await Repositories.UsersSettings.UpsertAsync(userSettings, (u) => u.UserId == userId);
265+
if (!Constants.IS_SELF_HOSTED)
266+
{
267+
userSettings.StorageLimit.UpdatedAt = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
268+
await Repositories.UsersSettings.UpsertAsync(userSettings, (u) => u.UserId == userId);
269+
}
264270
}
265271

266272
private string? GetPresignedURL(string userId, string name, HttpVerb httpVerb, S3ClientMode mode = S3ClientMode.EXTERNAL)

0 commit comments

Comments
 (0)