Skip to content

Commit 3da6bc2

Browse files
committed
Implement read-only mode
1 parent e1cc214 commit 3da6bc2

File tree

16 files changed

+125
-16
lines changed

16 files changed

+125
-16
lines changed

ProjectLighthouse.Localization/BaseLayout.resx

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,4 +87,10 @@
8787
<data name="license_warn_3" xml:space="preserve">
8888
<value>If not, please publish the source code somewhere accessible to your users.</value>
8989
</data>
90+
<data name="read_only_warn_title" xml:space="preserve">
91+
<value>Read-Only Mode</value>
92+
</data>
93+
<data name="read_only_warn" xml:space="preserve">
94+
<value>This instance is currently in read-only mode. Level and photo uploads, comments, reviews, and certain profile changes will be restricted until read-only mode is disabled.</value>
95+
</data>
9096
</root>

ProjectLighthouse.Localization/StringLists/BaseLayoutStrings.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,5 +23,8 @@ public static class BaseLayoutStrings
2323
public static readonly TranslatableString LicenseWarn2 = create("license_warn_2");
2424
public static readonly TranslatableString LicenseWarn3 = create("license_warn_3");
2525

26+
public static readonly TranslatableString ReadOnlyWarnTitle = create("read_only_warn_title");
27+
public static readonly TranslatableString ReadOnlyWarn = create("read_only_warn");
28+
2629
private static TranslatableString create(string key) => new(TranslationAreas.BaseLayout, key);
2730
}

ProjectLighthouse.Servers.GameServer/Controllers/CommentController.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,9 @@ public async Task<IActionResult> PostComment(string? username, string? slotType,
119119
{
120120
GameTokenEntity token = this.GetToken();
121121

122+
// Deny request if in read-only mode
123+
if (ServerConfiguration.Instance.UserGeneratedContentLimits.ReadOnlyMode) return this.BadRequest();
124+
122125
GameComment? comment = await this.DeserializeBody<GameComment>();
123126
if (comment?.Message == null) return this.BadRequest();
124127

@@ -159,6 +162,9 @@ public async Task<IActionResult> DeleteComment([FromQuery] int commentId, string
159162
{
160163
GameTokenEntity token = this.GetToken();
161164

165+
// Deny request if in read-only mode
166+
if (ServerConfiguration.Instance.UserGeneratedContentLimits.ReadOnlyMode) return this.BadRequest();
167+
162168
if ((slotId == 0 || SlotHelper.IsTypeInvalid(slotType)) == (username == null)) return this.BadRequest();
163169

164170
CommentEntity? comment = await this.database.Comments.FirstOrDefaultAsync(c => c.CommentId == commentId);

ProjectLighthouse.Servers.GameServer/Controllers/MessageController.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,13 @@ public async Task<IActionResult> Announce()
5959
announceText.Replace("%user", username);
6060
announceText.Replace("%id", token.UserId.ToString());
6161

62+
if (ServerConfiguration.Instance.UserGeneratedContentLimits.ReadOnlyMode)
63+
{
64+
announceText.Insert(0, "This instance is currently in read-only mode. Level and photo uploads, comments, " +
65+
"reviews, and certain profile changes will be restricted until read-only mode is " +
66+
"disabled.");
67+
}
68+
6269
#if DEBUG
6370
announceText.Append("\n\n---DEBUG INFO---\n" +
6471
$"user.UserId: {token.UserId}\n" +

ProjectLighthouse.Servers.GameServer/Controllers/Resources/PhotosController.cs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,9 @@ public async Task<IActionResult> UploadPhoto()
3737
{
3838
GameTokenEntity token = this.GetToken();
3939

40+
// Deny request if in read-only mode
41+
if (ServerConfiguration.Instance.UserGeneratedContentLimits.ReadOnlyMode) return this.BadRequest();
42+
4043
int photoCount = await this.database.Photos.CountAsync(p => p.CreatorId == token.UserId);
4144
if (photoCount >= ServerConfiguration.Instance.UserGeneratedContentLimits.PhotosQuota) return this.BadRequest();
4245

@@ -90,7 +93,7 @@ public async Task<IActionResult> UploadPhoto()
9093
case SlotType.Developer:
9194
{
9295
SlotEntity? slot = await this.database.Slots.FirstOrDefaultAsync(s => s.Type == photoSlot.SlotType && s.InternalSlotId == photoSlot.SlotId);
93-
if (slot != null)
96+
if (slot != null)
9497
photoSlot.SlotId = slot.SlotId;
9598
else
9699
photoSlot.SlotId = await SlotHelper.GetPlaceholderSlotId(this.database, photoSlot.SlotId, photoSlot.SlotType);

ProjectLighthouse.Servers.GameServer/Controllers/Resources/ResourcesController.cs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
#nullable enable
22
using System.Text;
3+
using LBPUnion.ProjectLighthouse.Configuration;
34
using LBPUnion.ProjectLighthouse.Extensions;
45
using LBPUnion.ProjectLighthouse.Files;
56
using LBPUnion.ProjectLighthouse.Logging;
@@ -58,10 +59,14 @@ public async Task<IActionResult> UploadResource(string hash)
5859
string fullPath = Path.GetFullPath(path);
5960

6061
FileHelper.EnsureDirectoryCreated(assetsDirectory);
61-
// lbp treats code 409 as success and as an indicator that the file is already present
62+
63+
// Deny request if in read-only mode
64+
if (ServerConfiguration.Instance.UserGeneratedContentLimits.ReadOnlyMode) return this.BadRequest();
65+
66+
// LBP treats code 409 as success and as an indicator that the file is already present
6267
if (FileHelper.ResourceExists(hash)) return this.Conflict();
6368

64-
// theoretically shouldn't be possible because of hash check but handle anyways
69+
// Theoretically shouldn't be possible because of hash check but handle anyways
6570
if (!fullPath.StartsWith(FileHelper.FullResourcePath)) return this.BadRequest();
6671

6772
Logger.Info($"Processing resource upload (hash: {hash})", LogArea.Resources);

ProjectLighthouse.Servers.GameServer/Controllers/Slots/PublishController.cs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,9 @@ public async Task<IActionResult> StartPublish()
4343
UserEntity? user = await this.database.UserFromGameToken(token);
4444
if (user == null) return this.Forbid();
4545

46+
// Deny request if in read-only mode
47+
if (ServerConfiguration.Instance.UserGeneratedContentLimits.ReadOnlyMode) return this.BadRequest();
48+
4649
GameUserSlot? slot = await this.DeserializeBody<GameUserSlot>();
4750
if (slot == null)
4851
{
@@ -116,6 +119,9 @@ public async Task<IActionResult> Publish([FromQuery] string? game)
116119
UserEntity? user = await this.database.UserFromGameToken(token);
117120
if (user == null) return this.Forbid();
118121

122+
// Deny request if in read-only mode
123+
if (ServerConfiguration.Instance.UserGeneratedContentLimits.ReadOnlyMode) return this.BadRequest();
124+
119125
GameUserSlot? slot = await this.DeserializeBody<GameUserSlot>();
120126

121127
if (slot == null)
@@ -335,6 +341,9 @@ public async Task<IActionResult> Unpublish(int id)
335341
{
336342
GameTokenEntity token = this.GetToken();
337343

344+
// Deny request if in read-only mode
345+
if (ServerConfiguration.Instance.UserGeneratedContentLimits.ReadOnlyMode) return this.BadRequest();
346+
338347
SlotEntity? slot = await this.database.Slots.FirstOrDefaultAsync(s => s.SlotId == id);
339348
if (slot == null) return this.NotFound();
340349

ProjectLighthouse.Servers.GameServer/Controllers/Slots/ReviewController.cs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
#nullable enable
2+
using LBPUnion.ProjectLighthouse.Configuration;
23
using LBPUnion.ProjectLighthouse.Database;
34
using LBPUnion.ProjectLighthouse.Extensions;
45
using LBPUnion.ProjectLighthouse.Helpers;
@@ -92,6 +93,9 @@ public async Task<IActionResult> PostReview(int slotId)
9293
{
9394
GameTokenEntity token = this.GetToken();
9495

96+
// Deny request if in read-only mode
97+
if (ServerConfiguration.Instance.UserGeneratedContentLimits.ReadOnlyMode) return this.BadRequest();
98+
9599
GameReview? newReview = await this.DeserializeBody<GameReview>();
96100
if (newReview == null) return this.BadRequest();
97101

@@ -115,7 +119,7 @@ public async Task<IActionResult> PostReview(int slotId)
115119
}
116120
review.Thumb = Math.Clamp(newReview.Thumb, -1, 1);
117121
review.LabelCollection = LabelHelper.RemoveInvalidLabels(newReview.LabelCollection);
118-
122+
119123
review.Text = newReview.Text;
120124
review.Deleted = false;
121125
review.Timestamp = TimeHelper.TimestampMillis;
@@ -239,6 +243,9 @@ public async Task<IActionResult> DeleteReview(int slotId, string username)
239243
{
240244
GameTokenEntity token = this.GetToken();
241245

246+
// Deny request if in read-only mode
247+
if (ServerConfiguration.Instance.UserGeneratedContentLimits.ReadOnlyMode) return this.BadRequest();
248+
242249
int creatorId = await this.database.Slots.Where(s => s.SlotId == slotId).Select(s => s.CreatorId).FirstOrDefaultAsync();
243250
if (creatorId == 0) return this.BadRequest();
244251

ProjectLighthouse.Servers.GameServer/Controllers/UserController.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System.Text.Json;
2+
using LBPUnion.ProjectLighthouse.Configuration;
23
using LBPUnion.ProjectLighthouse.Database;
34
using LBPUnion.ProjectLighthouse.Extensions;
45
using LBPUnion.ProjectLighthouse.Files;
@@ -73,6 +74,9 @@ public async Task<IActionResult> UpdateUser()
7374

7475
if (update.Biography != null)
7576
{
77+
// Deny request if in read-only mode
78+
if (ServerConfiguration.Instance.UserGeneratedContentLimits.ReadOnlyMode) return this.BadRequest();
79+
7680
if (update.Biography.Length > 512) return this.BadRequest();
7781

7882
user.Biography = update.Biography;
@@ -85,6 +89,9 @@ public async Task<IActionResult> UpdateUser()
8589
{
8690
if (string.IsNullOrWhiteSpace(resource)) continue;
8791

92+
// Deny request if in read-only mode
93+
if (ServerConfiguration.Instance.UserGeneratedContentLimits.ReadOnlyMode) return this.BadRequest();
94+
8895
if (!FileHelper.ResourceExists(resource) && !resource.StartsWith('g')) return this.BadRequest();
8996

9097
if (!GameResourceHelper.IsValidTexture(resource)) return this.BadRequest();

ProjectLighthouse.Servers.Website/Controllers/UserPageController.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,9 @@ public async Task<IActionResult> PostComment([FromRoute] int id, [FromForm] stri
3939
WebTokenEntity? token = this.database.WebTokenFromRequest(this.Request);
4040
if (token == null) return this.Redirect("~/login");
4141

42+
// Deny request if in read-only mode
43+
if (ServerConfiguration.Instance.UserGeneratedContentLimits.ReadOnlyMode) return this.BadRequest();
44+
4245
if (msg == null)
4346
{
4447
Logger.Error($"Refusing to post comment from {token.UserId} on user {id}, {nameof(msg)} is null", LogArea.Comments);

0 commit comments

Comments
 (0)