30 Commits

Author SHA1 Message Date
a18a5c423b sessions: remove SessionsService.Get
I can't think of any scenario where getting a session by ID is required.
2025-07-25 20:22:08 -07:00
a3a63a8475 sessions: track StyleID 2025-07-25 20:19:47 -07:00
149ee727ca sessions: track GameID 2025-07-25 20:09:09 -07:00
8a5f33b1b4 times: record attempt number to time entry 2025-07-25 19:58:51 -07:00
62ffc6a365 sessions: aggregate request 2025-07-25 19:49:31 -07:00
1969f9e2fe sessions: extend with attempts 2025-07-25 19:46:17 -07:00
55c8dfd379 sessions 2025-07-25 19:43:10 -07:00
889662bc99 maps_extended: IncrementLoadCount function
All checks were successful
continuous-integration/drone/push Build is passing
2025-07-23 19:59:31 -07:00
a9bdcbb1d7 maps_extended: include Modes in MapCreate
All checks were successful
continuous-integration/drone/push Build is passing
2025-07-23 18:17:59 -07:00
5f38e94770 refactor maps_extended
All checks were successful
continuous-integration/drone/push Build is passing
2025-07-21 22:40:45 -07:00
2285e79d6b Maps For maps-service (#6)
All checks were successful
continuous-integration/drone/push Build is passing
New service with extended maps fields.

Reviewed-on: #6
Co-authored-by: Quaternions <krakow20@gmail.com>
Co-committed-by: Quaternions <krakow20@gmail.com>
2025-07-22 05:01:15 +00:00
522731d92a Revert "rename maps to maps_embedded"
All checks were successful
continuous-integration/drone/push Build is passing
This reverts commit 77d88876f6.
2025-07-21 21:55:13 -07:00
b820089a93 Revert "use maps_embedded in times and servers"
All checks were successful
continuous-integration/drone/push Build is passing
This reverts commit d9db4fefb8.
2025-07-21 21:53:53 -07:00
d9db4fefb8 use maps_embedded in times and servers
All checks were successful
continuous-integration/drone/push Build is passing
2025-07-21 21:01:11 -07:00
77d88876f6 rename maps to maps_embedded
All checks were successful
continuous-integration/drone/push Build is passing
2025-07-21 20:08:08 -07:00
d8f3fd54a6 validator: ResourceType enum
All checks were successful
continuous-integration/drone/push Build is passing
2025-07-18 20:32:49 -07:00
0c22f1035e validator: fix SetStatusUploaded
All checks were successful
continuous-integration/drone/push Build is passing
2025-07-17 22:47:11 -07:00
e4d6e3882f validator: fix ScriptFilter
All checks were successful
continuous-integration/drone/push Build is passing
2025-07-17 22:29:47 -07:00
7646d55b34 validator: return ID on Create
All checks were successful
continuous-integration/drone/push Build is passing
2025-07-17 22:08:19 -07:00
3476ecaee0 validator: rename MapFixID -> MapfixID
All checks were successful
continuous-integration/drone/push Build is passing
2025-07-17 21:54:40 -07:00
09d89e2700 Create Dedicated Validator Endpoints (#8)
### Replacing Maps Service `openapi-internal.yaml` With gRPC

These are all the endpoints used by the validator.  The plan is to delete `service_internal` and create `validator_controller` with equivalent gRPC functionality.  This can then be extended in the future for public api & maptest integration by creating new grpc endpoints that the public api & game-rpc talk to.  The gRPC extensions would be separate files (`mapfixes.proto`, `submissions.proto`, `maps.proto`) unlike `validator.proto` which has a bunch of dedicated endpoints that only the validator should use.

### Why?

To reduce the number of exposed apis.  Without this there would need to be 4 (!) exposed apis (validator openapi, web openapi, public api, gRPC for game-rpc), with it, only 2 (web api, gRPC).

### Why didn't you do this in the first place?

I didn't know how.  I think I have a handle on it now.

Reviewed-on: #8
Co-authored-by: Rhys Lloyd <krakow20@gmail.com>
Co-committed-by: Rhys Lloyd <krakow20@gmail.com>
2025-07-17 21:53:59 -07:00
d5bb0a8972 fix bad sed match
All checks were successful
continuous-integration/drone/push Build is passing
2025-07-08 04:38:56 -07:00
cd767e3390 Typo
All checks were successful
continuous-integration/drone/push Build is passing
2025-06-27 22:17:30 -04:00
5b12236c59 Add resource for auditing
All checks were successful
continuous-integration/drone/push Build is passing
2025-06-27 21:38:28 -04:00
4b9803cf66 Add ip for auditing
All checks were successful
continuous-integration/drone/push Build is passing
2025-06-27 21:33:59 -04:00
b8bc25bb8e Fix proto typo
All checks were successful
continuous-integration/drone/push Build is passing
2025-06-27 21:18:18 -04:00
34e63ea6ba Add batch rank rpc
All checks were successful
continuous-integration/drone/push Build is passing
2025-06-27 21:12:49 -04:00
6497b12c5b Add wr list rpc
All checks were successful
continuous-integration/drone/push Build is passing
2025-06-23 23:22:17 -04:00
a1d08b3ea6 Add application owner info
All checks were successful
continuous-integration/drone/push Build is passing
2025-06-22 10:50:47 -04:00
82ca9f2b0c Add dev service
All checks were successful
continuous-integration/drone/push Build is passing
2025-06-22 10:19:28 -04:00
6 changed files with 402 additions and 2 deletions

36
dev.proto Normal file
View File

@@ -0,0 +1,36 @@
syntax = "proto3";
option go_package = "git.itzana.me/strafesnet/go-grpc/dev";
package dev;
service DevService {
rpc Validate(APIValidationRequest) returns (APIValidationResponse);
}
message APIValidationRequest {
string Service = 1;
string Permission = 2;
string Key = 3;
string IP = 4;
string Resource = 5;
}
message APIValidationResponse {
// Response
bool Valid = 1;
string ErrorMessage = 2;
int32 StatusCode = 3;
// Remaining limits
uint64 RemainingBurst = 4;
uint64 RemainingDaily = 5;
uint64 RemainingMonthly = 6;
// Quota
uint64 BurstLimit = 7;
uint64 BurstDurationSeconds = 8;
uint64 DailyLimit = 9;
uint64 MonthlyLimit = 10;
// Owner info
uint64 UserID = 11;
string Application = 12;
}

82
maps_extended.proto Normal file
View File

@@ -0,0 +1,82 @@
syntax = "proto3";
option go_package = "git.itzana.me/strafesnet/go-grpc/maps_extended";
package maps_extended;
service MapsService {
rpc Get(MapId) returns (MapResponse);
rpc GetList(MapIdList) returns (MapList);
rpc Update(MapUpdate) returns (NullResponse);
rpc Create(MapCreate) returns (MapId);
rpc Delete(MapId) returns (NullResponse);
rpc List(ListRequest) returns (MapList);
rpc IncrementLoadCount(MapId) returns (NullResponse);
}
message MapIdList { repeated int64 ID = 1; }
message MapId { int64 ID = 1; }
message MapResponse {
int64 ID = 1;
string DisplayName = 2;
string Creator = 3;
uint32 GameID = 4;
int64 Date = 5;
int64 CreatedAt = 6;
int64 UpdatedAt = 7;
uint64 Submitter = 8;
uint64 Thumbnail = 9;
uint64 AssetVersion = 10;
uint32 LoadCount = 11;
uint32 Modes = 12;
}
message MapCreate {
int64 ID = 1;
string DisplayName = 2;
string Creator = 3;
uint32 GameID = 4;
int64 Date = 5;
// int64 CreatedAt = 6;
// int64 UpdatedAt = 7;
uint64 Submitter = 6;
uint64 Thumbnail = 7;
uint64 AssetVersion = 8;
// uint32 LoadCount = 11;
uint32 Modes = 9;
}
message MapUpdate {
int64 ID = 1;
optional string DisplayName = 2;
optional string Creator = 3;
optional uint32 GameID = 4;
optional int64 Date = 5;
optional uint64 Submitter = 6;
optional uint64 Thumbnail = 7;
optional uint64 AssetVersion = 8;
optional uint32 Modes = 9;
}
message MapFilter {
optional string DisplayName = 2;
optional string Creator = 3;
optional uint32 GameID = 4;
optional uint64 Submitter = 5;
}
message MapList { repeated MapResponse Maps = 1; }
message ListRequest {
MapFilter Filter = 1;
Pagination Page = 2;
}
message Pagination {
uint32 Size = 1;
uint32 Number = 2;
}
message NullResponse {}

View File

@@ -12,7 +12,7 @@ do
--tonic_out=$module \
$f
#I couldn't figure out how to configure protoc to do this
sed -i "s/#\[derive(Clone, PartialEq, ::prost::Message)\]/#\[derive(Clone, PartialEq, ::prost::Message, serde::Serialize, serde::Deserialize)\]\n#\[serde(rename_all = \"PascalCase\")\]/g" "$module/$name.rs"
sed -i "s/, PartialEq, ::prost::Message)\]/, PartialEq, ::prost::Message, serde::Serialize, serde::Deserialize)\]\n#\[serde(rename_all = \"PascalCase\")\]/g" "$module/$name.rs"
sed -i "s/ pub id:/ #\[serde(rename = \"ID\")\]\n pub id:/g" "$module/$name.rs"
sed -i "s/ pub map_id:/ #\[serde(rename = \"MapID\")\]\n pub map_id:/g" "$module/$name.rs"
sed -i "s/ pub time_id:/ #\[serde(rename = \"TimeID\")\]\n pub time_id:/g" "$module/$name.rs"

67
sessions.proto Normal file
View File

@@ -0,0 +1,67 @@
syntax = "proto3";
option go_package = "git.itzana.me/strafesnet/go-grpc/sessions";
package sessions;
service SessionsService {
rpc Create(SessionCreate) returns (SessionId);
rpc List(ListRequest) returns (SessionList);
rpc Aggregate(SessionFilter) returns (SessionAggregate);
}
message SessionIdList { repeated int64 ID = 1; }
message SessionId { int64 ID = 1; }
message SessionResponse {
int64 ID = 1;
uint64 UserID = 2;
uint64 MapID = 3;
int64 Date = 4;
uint32 Duration = 5;
uint32 Attempts = 6;
uint32 GameID = 7;
uint32 StyleID = 8;
}
message SessionCreate {
uint64 UserID = 1;
uint64 MapID = 2;
int64 Date = 3;
uint32 Duration = 4;
uint32 Attempts = 5;
uint32 GameID = 6;
uint32 StyleID = 7;
}
enum SessionSort {
SessionSortDateDescending = 0;
}
message SessionFilter {
optional uint64 UserID = 1;
optional uint64 MapID = 2;
optional uint32 GameID = 3;
optional uint32 StyleID = 4;
}
message SessionList { repeated SessionResponse Sessions = 1; }
message ListRequest {
SessionFilter Filter = 1;
Pagination Page = 2;
Sort SessionSort = 3;
}
message Pagination {
uint32 Size = 1;
uint32 Number = 2;
}
message SessionAggregate {
uint64 Duration = 1;
uint64 Attempts = 2;
}
message NullResponse {}

View File

@@ -14,7 +14,9 @@ service TimesService {
rpc Delete(IdMessage) returns (NullResponse);
rpc Get(IdMessage) returns (TimeResponse);
rpc List(ListRequest) returns (TimeList);
rpc ListWr(WrListRequest) returns (TimeList);
rpc Rank(IdMessage) returns (RankResponse);
rpc RankBatch(IdListMessage) returns (RankListResponse);
}
message TimeRequest {
@@ -26,6 +28,7 @@ message TimeRequest {
optional int32 StyleID = 6;
optional int32 ModeID = 7;
optional int32 GameID = 8;
optional uint32 Attempt = 9;
}
message TimeFilter {
@@ -49,19 +52,31 @@ message TimeResponse {
int32 StyleID = 7;
int32 ModeID = 8;
int32 GameID = 9;
// How many times did the player leave the start zone
// during their full play history of the map
uint32 Attempt = 10;
}
message IdMessage {
int64 ID = 1;
}
message IdListMessage {
repeated int64 ID = 1;
}
message TimeList {
repeated TimeResponse Times = 1;
int64 Total = 2;
}
message RankListResponse {
repeated RankResponse Ranks = 1;
}
message RankResponse {
int64 Rank = 1;
int64 ID = 2;
}
message ListRequest {
@@ -77,6 +92,11 @@ message ListRequest {
uint32 Sort = 4;
}
message WrListRequest {
TimeFilter Filter = 1;
Pagination Page = 2;
}
message Pagination {
int32 Size = 1;
int32 Number = 2;
@@ -84,4 +104,4 @@ message Pagination {
message NullResponse {
}
}

195
validator.proto Normal file
View File

@@ -0,0 +1,195 @@
syntax = "proto3";
option go_package = "git.itzana.me/strafesnet/go-grpc/validator";
package validator;
service ValidatorMapfixService {
rpc Create(MapfixCreate) returns (MapfixID);
rpc CreateAuditError(AuditErrorRequest) returns (NullResponse);
rpc CreateAuditChecklist(AuditChecklistRequest) returns (NullResponse);
rpc SetValidatedModel(ValidatedModelRequest) returns (NullResponse);
rpc SetStatusSubmitted(SubmittedRequest) returns (NullResponse);
rpc SetStatusRequestChanges(MapfixID) returns (NullResponse);
rpc SetStatusValidated(MapfixID) returns (NullResponse);
rpc SetStatusFailed(MapfixID) returns (NullResponse);
rpc SetStatusUploaded(MapfixID) returns (NullResponse);
}
service ValidatorSubmissionService {
rpc Create(SubmissionCreate) returns (SubmissionID);
rpc CreateAuditError(AuditErrorRequest) returns (NullResponse);
rpc CreateAuditChecklist(AuditChecklistRequest) returns (NullResponse);
rpc SetValidatedModel(ValidatedModelRequest) returns (NullResponse);
rpc SetStatusSubmitted(SubmittedRequest) returns (NullResponse);
rpc SetStatusRequestChanges(SubmissionID) returns (NullResponse);
rpc SetStatusValidated(SubmissionID) returns (NullResponse);
rpc SetStatusFailed(SubmissionID) returns (NullResponse);
rpc SetStatusUploaded(StatusUploadedRequest) returns (NullResponse);
}
message MapfixID { uint64 ID = 1; }
message MapfixCreate {
uint32 OperationID = 1;
uint32 GameID = 2;
uint64 AssetOwner = 3;
uint64 AssetID = 4;
uint64 AssetVersion = 5;
uint64 TargetAssetID = 6;
string DisplayName = 7;
string Creator = 8;
string Description = 9;
}
message SubmissionID { uint64 ID = 1; }
message SubmissionCreate {
uint32 OperationID = 1;
uint32 GameID = 2;
uint32 Status = 3;
uint32 Roles = 4;
uint64 AssetOwner = 5;
uint64 AssetID = 6;
uint64 AssetVersion = 7;
string DisplayName = 8;
string Creator = 9;
}
message AuditErrorRequest {
uint64 ID = 1;
string ErrorMessage = 2;
}
message Check {
string Name = 1;
string Summary = 2;
bool Passed = 3;
}
message AuditChecklistRequest {
uint64 ID = 1;
repeated Check CheckList = 2;
}
message ValidatedModelRequest {
uint64 ID = 1;
uint64 ValidatedModelID = 2;
uint64 ValidatedModelVersion = 3;
}
message SubmittedRequest {
uint64 ID = 1;
uint64 ModelVersion = 2;
string DisplayName = 3;
string Creator = 4;
uint32 GameID = 5;
}
message StatusUploadedRequest {
uint64 ID = 1;
uint64 UploadedAssetID = 2;
}
message NullResponse {}
// Operations
service ValidatorOperationService {
rpc Fail(OperationFailRequest) returns (NullResponse);
}
message OperationFailRequest {
uint32 OperationID = 1;
string StatusMessage = 2;
}
message Pagination {
uint32 Size = 1;
uint32 Number = 2;
}
// Scripts
service ValidatorScriptService {
rpc Create(ScriptCreate) returns (ScriptID);
rpc Get(ScriptID) returns (Script);
rpc List(ScriptListRequest) returns (ScriptListResponse);
}
enum ResourceType {
ResourceTypeNone = 0;
ResourceTypeMapfix = 1;
ResourceTypeSubmission = 2;
}
message ScriptCreate {
string Name = 1;
string Source = 2;
ResourceType ResourceType = 3;
optional uint64 ResourceID = 4;
}
message ScriptFilter {
optional string Name = 1;
optional string Source = 2;
optional ResourceType ResourceType = 3;
optional uint64 ResourceID = 4;
optional uint64 Hash = 5;
}
message ScriptListRequest {
ScriptFilter Filter = 1;
Pagination Page = 2;
}
message ScriptID { uint64 ID = 1; }
message Script {
uint64 ID = 1;
uint64 Hash = 2;
string Name = 3;
string Source = 4;
ResourceType ResourceType = 5;
optional uint64 ResourceID = 6;
}
message ScriptListResponse { repeated Script Scripts = 1; }
// ScriptPolicies
service ValidatorScriptPolicyService {
rpc Create(ScriptPolicyCreate) returns (ScriptPolicyID);
rpc List(ScriptPolicyListRequest) returns (ScriptPolicyListResponse);
}
enum Policy {
PolicyNone = 0;
PolicyAllowed = 1;
PolicyBlocked = 2;
PolicyDelete = 3;
PolicyReplace = 4;
}
message ScriptPolicyCreate {
uint64 FromScriptID = 1;
uint64 ToScriptID = 2;
Policy Policy = 3;
}
message ScriptPolicyFilter {
optional uint64 FromScriptHash = 1;
optional uint64 ToScriptID = 2;
optional Policy Policy = 3;
}
message ScriptPolicyListRequest {
ScriptPolicyFilter Filter = 1;
Pagination Page = 2;
}
message ScriptPolicyID { uint64 ID = 1; }
message ScriptPolicy {
uint64 ID = 1;
uint64 FromScriptHash = 2;
uint64 ToScriptID = 3;
Policy Policy = 4;
}
message ScriptPolicyListResponse { repeated ScriptPolicy ScriptPolicies = 1; }