Skip to content

Commit aeeeece

Browse files
authored
Merge branch 'main' into w-clear
2 parents 50b7016 + ef7a165 commit aeeeece

16 files changed

Lines changed: 213 additions & 44 deletions

File tree

Refresh.Interfaces.APIv3/Endpoints/ApiTypes/Errors/ApiAuthenticationError.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@ public class ApiAuthenticationError : ApiError
99
public const string NoPermissionsForCreationWhen = "You lack the permissions to create this type of resource.";
1010
public static readonly ApiAuthenticationError NoPermissionsForCreation = new(NoPermissionsForCreationWhen);
1111

12+
public const string ReadOnlyErrorWhen = "The server is currently in read-only mode.";
13+
public static readonly ApiAuthenticationError ReadOnlyError = new(ReadOnlyErrorWhen);
14+
1215
public const string NotAuthenticatedWhen = "You are not authenticated.";
1316
public static readonly ApiAuthenticationError NotAuthenticated = new(NotAuthenticatedWhen);
1417

Refresh.Interfaces.APIv3/Endpoints/CommentApiEndpoints.cs

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
using Bunkum.Core.RateLimit;
55
using Bunkum.Protocols.Http;
66
using Refresh.Common.Constants;
7+
using Refresh.Core.Configuration;
78
using Refresh.Core.RateLimits.Comments;
89
using Refresh.Core.RateLimits.Relations;
910
using Refresh.Core.Types.Data;
@@ -51,8 +52,11 @@ public ApiListResponse<ApiProfileCommentResponse> GetCommentsOnProfile(RequestCo
5152
public ApiResponse<ApiProfileCommentResponse> PostCommentOnProfile(RequestContext context,
5253
DataContext dataContext, GameUser user, ApiCommentPostRequest body,
5354
[DocSummary(SharedParamDescriptions.UserIdParam)] string id,
54-
[DocSummary(SharedParamDescriptions.UserIdTypeParam)] string idType)
55+
[DocSummary(SharedParamDescriptions.UserIdTypeParam)] string idType, GameServerConfig config)
5556
{
57+
if (user.IsWriteBlocked(config))
58+
return ApiAuthenticationError.ReadOnlyError;
59+
5660
GameUser? profile = dataContext.Database.GetUserByIdAndType(idType, id);
5761
if (profile == null) return ApiNotFoundError.UserMissingError;
5862

@@ -99,8 +103,11 @@ public ApiOkResponse DeleteProfileComment(RequestContext context, DataContext da
99103
[RateLimitSettings(CommonRelationEndpointLimits.TimeoutDuration, CommonRelationEndpointLimits.RequestAmount,
100104
CommonRelationEndpointLimits.BlockDuration, CommonRelationEndpointLimits.RequestBucket)]
101105
public ApiOkResponse RateProfileComment(RequestContext context, DataContext dataContext, GameUser user, int id,
102-
[DocSummary("The user's new rating for the comment. -1 = dislike, 0 = neutral, 1 = like.")] string rawRating)
106+
[DocSummary("The user's new rating for the comment. -1 = dislike, 0 = neutral, 1 = like.")] string rawRating, GameServerConfig config)
103107
{
108+
if (user.IsWriteBlocked(config))
109+
return ApiAuthenticationError.ReadOnlyError;
110+
104111
GameProfileComment? comment = dataContext.Database.GetProfileCommentById(id);
105112
if (comment == null) return ApiNotFoundError.CommentMissingError;
106113

@@ -138,8 +145,11 @@ public ApiListResponse<ApiLevelCommentResponse> GetCommentsOnLevel(RequestContex
138145
[RateLimitSettings(CommentUploadEndpointLimits.TimeoutDuration, CommentUploadEndpointLimits.RequestAmount,
139146
CommentUploadEndpointLimits.BlockDuration, CommentUploadEndpointLimits.RequestBucket)]
140147
public ApiResponse<ApiLevelCommentResponse> PostCommentOnLevel(RequestContext context,
141-
DataContext dataContext, int id, GameUser user, ApiCommentPostRequest body)
148+
DataContext dataContext, int id, GameUser user, ApiCommentPostRequest body, GameServerConfig config)
142149
{
150+
if (user.IsWriteBlocked(config))
151+
return ApiAuthenticationError.ReadOnlyError;
152+
143153
GameLevel? level = dataContext.Database.GetLevelById(id);
144154
if (level == null) return ApiNotFoundError.LevelMissingError;
145155

@@ -186,8 +196,11 @@ public ApiOkResponse DeleteLevelComment(RequestContext context, DataContext data
186196
[RateLimitSettings(CommonRelationEndpointLimits.TimeoutDuration, CommonRelationEndpointLimits.RequestAmount,
187197
CommonRelationEndpointLimits.BlockDuration, CommonRelationEndpointLimits.RequestBucket)]
188198
public ApiOkResponse RateLevelComment(RequestContext context, DataContext dataContext, GameUser user, int id,
189-
[DocSummary("The user's new rating for the comment. -1 = dislike, 0 = neutral, 1 = like.")] string rawRating)
199+
[DocSummary("The user's new rating for the comment. -1 = dislike, 0 = neutral, 1 = like.")] string rawRating, GameServerConfig config)
190200
{
201+
if (user.IsWriteBlocked(config))
202+
return ApiAuthenticationError.ReadOnlyError;
203+
191204
GameLevelComment? comment = dataContext.Database.GetLevelCommentById(id);
192205
if (comment == null) return ApiNotFoundError.CommentMissingError;
193206

Refresh.Interfaces.APIv3/Endpoints/LevelApiEndpoints.cs

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
using Refresh.Common.Constants;
88
using Refresh.Common.Verification;
99
using Refresh.Core.Authentication.Permission;
10+
using Refresh.Core.Configuration;
1011
using Refresh.Core.RateLimits.Levels;
1112
using Refresh.Core.RateLimits.Playlists;
1213
using Refresh.Core.RateLimits.Presence;
@@ -63,9 +64,12 @@ public ApiResponse<ApiGameLevelResponse> GetLevelByRootResource(RequestContext c
6364
[DocError(typeof(ApiNotFoundError), ApiNotFoundError.LevelMissingErrorWhen)]
6465
[DocError(typeof(ApiAuthenticationError), ApiAuthenticationError.NoPermissionsForObjectWhen)]
6566
[RateLimitSettings(420, 8, 300, "level-update-api")]
66-
public ApiResponse<ApiGameLevelResponse> EditLevelById(RequestContext context,
67-
[DocSummary("The ID of the level")] int id, ApiEditLevelRequest body, DataContext dataContext)
67+
public ApiResponse<ApiGameLevelResponse> EditLevelById(RequestContext context, GameUser user,
68+
[DocSummary("The ID of the level")] int id, ApiEditLevelRequest body, DataContext dataContext, GameServerConfig config)
6869
{
70+
if (user.IsWriteBlocked(config))
71+
return ApiAuthenticationError.ReadOnlyError;
72+
6973
GameLevel? level = dataContext.Database.GetLevelById(id);
7074
if (level == null) return ApiNotFoundError.LevelMissingError;
7175

@@ -162,9 +166,12 @@ public ApiResponse<ApiGameLevelOwnRelationsResponse> GetLevelRelationsOfUser(Req
162166
[DocError(typeof(ApiNotFoundError), ApiNotFoundError.LevelMissingErrorWhen)]
163167
[RateLimitSettings(CommonRelationEndpointLimits.TimeoutDuration, CommonRelationEndpointLimits.RequestAmount,
164168
CommonRelationEndpointLimits.BlockDuration, CommonRelationEndpointLimits.RequestBucket)]
165-
public ApiOkResponse FavouriteLevel(RequestContext context, GameDatabaseContext database, GameUser user,
166-
[DocSummary("The ID of the level")] int id, DataContext dataContext)
169+
public ApiOkResponse HeartLevel(RequestContext context, GameDatabaseContext database, GameUser user,
170+
[DocSummary("The ID of the level")] int id, DataContext dataContext, GameServerConfig config)
167171
{
172+
if (user.IsWriteBlocked(config))
173+
return ApiAuthenticationError.ReadOnlyError;
174+
168175
GameLevel? level = database.GetLevelById(id);
169176
if (level == null) return ApiNotFoundError.LevelMissingError;
170177

@@ -179,8 +186,11 @@ public ApiOkResponse FavouriteLevel(RequestContext context, GameDatabaseContext
179186
[RateLimitSettings(CommonRelationEndpointLimits.TimeoutDuration, CommonRelationEndpointLimits.RequestAmount,
180187
CommonRelationEndpointLimits.BlockDuration, CommonRelationEndpointLimits.RequestBucket)]
181188
public ApiOkResponse UnheartLevel(RequestContext context, GameDatabaseContext database, GameUser user,
182-
[DocSummary("The ID of the level")] int id, DataContext dataContext)
189+
[DocSummary("The ID of the level")] int id, DataContext dataContext, GameServerConfig config)
183190
{
191+
if (user.IsWriteBlocked(config))
192+
return ApiAuthenticationError.ReadOnlyError;
193+
184194
GameLevel? level = database.GetLevelById(id);
185195
if (level == null) return ApiNotFoundError.LevelMissingError;
186196

@@ -232,7 +242,7 @@ public ApiOkResponse DequeueLevel(RequestContext context, GameDatabaseContext da
232242
[RateLimitSettings(CommonRelationEndpointLimits.TimeoutDuration, CommonRelationEndpointLimits.RequestAmount,
233243
CommonRelationEndpointLimits.BlockDuration, CommonRelationEndpointLimits.RequestBucket)]
234244
public ApiOkResponse ClearQueuedLevels(RequestContext context, GameDatabaseContext database,
235-
IDataStore dataStore, GameUser user, DataContext dataContext)
245+
GameUser user, DataContext dataContext)
236246
{
237247
database.ClearQueue(user);
238248
dataContext.Cache.ClearQueueByUser(user);

Refresh.Interfaces.APIv3/Endpoints/PlaylistApiEndpoints.cs

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
using Refresh.Interfaces.APIv3.Endpoints.DataTypes.Response.Playlists;
1515
using Refresh.Interfaces.APIv3.Extensions;
1616
using Refresh.Core.RateLimits.Playlists;
17+
using Refresh.Core.Configuration;
1718

1819
namespace Refresh.Interfaces.APIv3.Endpoints;
1920

@@ -54,8 +55,11 @@ public class PlaylistApiEndpoints : EndpointGroup
5455
[DocQueryParam("parentId", "If set, the new playlist will be added to the playlist specified by ID here instead of the root playlist. "
5556
+ "If the specified playlist doesn't exist or is not owned by the user calling this endpoint, nothing will happen.")]
5657
public ApiResponse<ApiGamePlaylistResponse> CreatePlaylist(RequestContext context, DataContext dataContext,
57-
GameUser user, ApiPlaylistCreationRequest body)
58+
GameUser user, ApiPlaylistCreationRequest body, GameServerConfig config)
5859
{
60+
if (user.IsWriteBlocked(config))
61+
return ApiAuthenticationError.ReadOnlyError;
62+
5963
ApiError? error = this.ValidatePlaylist(body, dataContext);
6064
if (error != null) return error;
6165

@@ -96,8 +100,11 @@ public ApiResponse<ApiGamePlaylistResponse> CreatePlaylist(RequestContext contex
96100
[RateLimitSettings(PlaylistCreationEndpointLimits.UploadTimeoutDuration, PlaylistCreationEndpointLimits.MaxCreateAmount,
97101
PlaylistCreationEndpointLimits.UploadBlockDuration, PlaylistCreationEndpointLimits.CreateBucket)]
98102
public ApiResponse<ApiGamePlaylistResponse> UpdatePlaylist(RequestContext context, DataContext dataContext,
99-
GameUser user, ApiPlaylistCreationRequest body, int id)
103+
GameUser user, ApiPlaylistCreationRequest body, int id, GameServerConfig config)
100104
{
105+
if (user.IsWriteBlocked(config))
106+
return ApiAuthenticationError.ReadOnlyError;
107+
101108
GamePlaylist? playlist = dataContext.Database.GetPlaylistById(id);
102109
if (playlist == null) return ApiNotFoundError.PlaylistMissingError;
103110

@@ -149,8 +156,11 @@ public ApiResponse<ApiGamePlaylistResponse> GetPlaylistById(RequestContext conte
149156
[RateLimitSettings(PlaylistModificationEndpointLimits.TimeoutDuration, PlaylistModificationEndpointLimits.RequestAmount,
150157
PlaylistModificationEndpointLimits.BlockDuration, PlaylistModificationEndpointLimits.RequestBucket)]
151158
public ApiOkResponse AddLevelToPlaylist(RequestContext context, DataContext dataContext,
152-
GameUser user, int playlistId, int levelId)
159+
GameUser user, int playlistId, int levelId, GameServerConfig config)
153160
{
161+
if (user.IsWriteBlocked(config))
162+
return ApiAuthenticationError.ReadOnlyError;
163+
154164
GamePlaylist? playlist = dataContext.Database.GetPlaylistById(playlistId);
155165
if (playlist == null) return ApiNotFoundError.ParentPlaylistMissingError;
156166

@@ -172,8 +182,11 @@ public ApiOkResponse AddLevelToPlaylist(RequestContext context, DataContext data
172182
[RateLimitSettings(PlaylistModificationEndpointLimits.TimeoutDuration, PlaylistModificationEndpointLimits.RequestAmount,
173183
PlaylistModificationEndpointLimits.BlockDuration, PlaylistModificationEndpointLimits.RequestBucket)]
174184
public ApiOkResponse RemoveLevelFromPlaylist(RequestContext context, DataContext dataContext,
175-
GameUser user, int playlistId, int levelId)
185+
GameUser user, int playlistId, int levelId, GameServerConfig config)
176186
{
187+
if (user.IsWriteBlocked(config))
188+
return ApiAuthenticationError.ReadOnlyError;
189+
177190
GamePlaylist? playlist = dataContext.Database.GetPlaylistById(playlistId);
178191
if (playlist == null) return ApiNotFoundError.ParentPlaylistMissingError;
179192

@@ -195,8 +208,11 @@ public ApiOkResponse RemoveLevelFromPlaylist(RequestContext context, DataContext
195208
[RateLimitSettings(PlaylistModificationEndpointLimits.TimeoutDuration, PlaylistModificationEndpointLimits.RequestAmount,
196209
PlaylistModificationEndpointLimits.BlockDuration, PlaylistModificationEndpointLimits.RequestBucket)]
197210
public ApiOkResponse AddPlaylistToPlaylist(RequestContext context, DataContext dataContext,
198-
GameUser user, int playlistId, int subPlaylistId)
211+
GameUser user, int playlistId, int subPlaylistId, GameServerConfig config)
199212
{
213+
if (user.IsWriteBlocked(config))
214+
return ApiAuthenticationError.ReadOnlyError;
215+
200216
GamePlaylist? parent = dataContext.Database.GetPlaylistById(playlistId);
201217
if (parent == null) return ApiNotFoundError.ParentPlaylistMissingError;
202218

@@ -218,8 +234,11 @@ public ApiOkResponse AddPlaylistToPlaylist(RequestContext context, DataContext d
218234
[RateLimitSettings(PlaylistModificationEndpointLimits.TimeoutDuration, PlaylistModificationEndpointLimits.RequestAmount,
219235
PlaylistModificationEndpointLimits.BlockDuration, PlaylistModificationEndpointLimits.RequestBucket)]
220236
public ApiOkResponse RemovePlaylistFromPlaylist(RequestContext context, DataContext dataContext,
221-
GameUser user, int playlistId, int subPlaylistId)
237+
GameUser user, int playlistId, int subPlaylistId, GameServerConfig config)
222238
{
239+
if (user.IsWriteBlocked(config))
240+
return ApiAuthenticationError.ReadOnlyError;
241+
223242
GamePlaylist? parent = dataContext.Database.GetPlaylistById(playlistId);
224243
if (parent == null) return ApiNotFoundError.ParentPlaylistMissingError;
225244

Refresh.Interfaces.APIv3/Endpoints/ResourceApiEndpoints.cs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,6 @@ public ApiResponse<ApiGameAssetResponse> GetPspAssetInfo(RequestContext context,
161161
[DocError(typeof(ApiValidationError), ApiValidationError.BodyTooLongErrorWhen)]
162162
[DocError(typeof(ApiValidationError), ApiValidationError.CannotReadAssetErrorWhen)]
163163
[DocError(typeof(ApiValidationError), ApiValidationError.BodyMustBeImageErrorWhen)]
164-
[DocError(typeof(ApiAuthenticationError), ApiAuthenticationError.NoPermissionsForCreationWhen)]
165164
[RateLimitSettings(420, 10, 300, "image-upload-api")]
166165
public ApiResponse<ApiGameAssetResponse> UploadImageAsset(RequestContext context, GameDatabaseContext database,
167166
IDataStore dataStore, AssetImporter importer, GameServerConfig config,
@@ -176,7 +175,7 @@ IntegrationConfig integration
176175
// If we're blocking asset uploads, throw unless the user is an admin.
177176
// We also have the ability to block asset uploads for trusted users (when they would normally bypass this)
178177
if (user.IsWriteBlocked(config))
179-
return ApiAuthenticationError.NoPermissionsForCreation;
178+
return ApiAuthenticationError.ReadOnlyError;
180179

181180
if (!CommonPatterns.Sha1Regex().IsMatch(hash)) return ApiValidationError.HashInvalidError;
182181

Refresh.Interfaces.APIv3/Endpoints/ReviewApiEndpoints.cs

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
using Bunkum.Core.Storage;
66
using Bunkum.Protocols.Http;
77
using Refresh.Common.Constants;
8+
using Refresh.Core.Configuration;
89
using Refresh.Core.RateLimits.Relations;
910
using Refresh.Core.RateLimits.Reviews;
1011
using Refresh.Core.Types.Data;
@@ -101,8 +102,11 @@ private List<Label> ValidateLabels(List<Label> input)
101102
ReviewUploadEndpointLimits.BlockDuration, ReviewUploadEndpointLimits.RequestBucket)]
102103
public ApiResponse<ApiGameReviewResponse> PostReviewToLevel(RequestContext context,
103104
GameDatabaseContext database, IDataStore dataStore, GameUser user,
104-
[DocSummary("The ID of the level")] int id, ApiSubmitReviewRequest body, DataContext dataContext)
105+
[DocSummary("The ID of the level")] int id, ApiSubmitReviewRequest body, DataContext dataContext, GameServerConfig config)
105106
{
107+
if (user.IsWriteBlocked(config))
108+
return ApiAuthenticationError.ReadOnlyError;
109+
106110
GameLevel? level = database.GetLevelById(id);
107111
if (level == null) return ApiNotFoundError.LevelMissingError;
108112

@@ -147,8 +151,11 @@ public ApiResponse<ApiGameReviewResponse> PostReviewToLevel(RequestContext conte
147151
ReviewUploadEndpointLimits.BlockDuration, ReviewUploadEndpointLimits.RequestBucket)]
148152
public ApiResponse<ApiGameReviewResponse> UpdateReviewById(RequestContext context,
149153
GameDatabaseContext database, IDataStore dataStore, GameUser user,
150-
[DocSummary("The ID of the review")] int id, ApiSubmitReviewRequest body, DataContext dataContext)
154+
[DocSummary("The ID of the review")] int id, ApiSubmitReviewRequest body, DataContext dataContext, GameServerConfig config)
151155
{
156+
if (user.IsWriteBlocked(config))
157+
return ApiAuthenticationError.ReadOnlyError;
158+
152159
GameReview? review = database.GetReviewById(id);
153160
if (review == null) return ApiNotFoundError.ReviewMissingError;
154161

@@ -209,8 +216,11 @@ public ApiOkResponse DeleteReviewById(RequestContext context,
209216
public ApiOkResponse RateReviewById(RequestContext context,
210217
GameDatabaseContext database, IDataStore dataStore, GameUser user,
211218
[DocSummary("The ID of the review")] int id, DataContext dataContext,
212-
[DocSummary("The user's new rating. -1 = dislike, 0 = neutral, 1 = like.")] string rawRating)
219+
[DocSummary("The user's new rating. -1 = dislike, 0 = neutral, 1 = like.")] string rawRating, GameServerConfig config)
213220
{
221+
if (user.IsWriteBlocked(config))
222+
return ApiAuthenticationError.ReadOnlyError;
223+
214224
GameReview? review = database.GetReviewById(id);
215225
if (review == null) return ApiNotFoundError.ReviewMissingError;
216226

Refresh.Interfaces.APIv3/Endpoints/UserApiEndpoints.cs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,8 +49,11 @@ public ApiResponse<ApiGameUserResponse> GetUser(RequestContext context, GameData
4949
CommonRelationEndpointLimits.BlockDuration, CommonRelationEndpointLimits.RequestBucket)]
5050
public ApiOkResponse HeartUser(RequestContext context, GameDatabaseContext database,
5151
[DocSummary(SharedParamDescriptions.UserIdParam)] string id,
52-
[DocSummary(SharedParamDescriptions.UserIdTypeParam)] string idType, DataContext dataContext, GameUser user)
52+
[DocSummary(SharedParamDescriptions.UserIdTypeParam)] string idType, DataContext dataContext, GameUser user, GameServerConfig config)
5353
{
54+
if (user.IsWriteBlocked(config))
55+
return ApiAuthenticationError.ReadOnlyError;
56+
5457
GameUser? target = database.GetUserByIdAndType(idType, id);
5558
if(target == null) return ApiNotFoundError.UserMissingError;
5659

@@ -72,8 +75,11 @@ public ApiOkResponse HeartUser(RequestContext context, GameDatabaseContext datab
7275
CommonRelationEndpointLimits.BlockDuration, CommonRelationEndpointLimits.RequestBucket)]
7376
public ApiOkResponse UnheartUser(RequestContext context, GameDatabaseContext database,
7477
[DocSummary(SharedParamDescriptions.UserIdParam)] string id,
75-
[DocSummary(SharedParamDescriptions.UserIdTypeParam)] string idType, DataContext dataContext, GameUser user)
78+
[DocSummary(SharedParamDescriptions.UserIdTypeParam)] string idType, DataContext dataContext, GameUser user, GameServerConfig config)
7679
{
80+
if (user.IsWriteBlocked(config))
81+
return ApiAuthenticationError.ReadOnlyError;
82+
7783
GameUser? target = database.GetUserByIdAndType(idType, id);
7884
if(target == null) return ApiNotFoundError.UserMissingError;
7985

0 commit comments

Comments
 (0)