Scream Test Backend Overhaul #237
@@ -6,6 +6,12 @@ info:
|
||||
tags:
|
||||
- name: Mapfixes
|
||||
description: Mapfix operations
|
||||
- name: Operations
|
||||
description: Long-running operations
|
||||
- name: Scripts
|
||||
description: Script operations
|
||||
- name: ScriptPolicy
|
||||
description: Script policy operations
|
||||
- name: Submissions
|
||||
description: Submission operations
|
||||
paths:
|
||||
@@ -539,7 +545,7 @@ paths:
|
||||
summary: Get list of scripts
|
||||
operationId: listScripts
|
||||
tags:
|
||||
- Script
|
||||
- Scripts
|
||||
parameters:
|
||||
- $ref: "#/components/parameters/Page"
|
||||
- $ref: "#/components/parameters/Limit"
|
||||
|
||||
@@ -11,6 +11,7 @@ import (
|
||||
"git.itzana.me/strafesnet/maps-service/pkg/datastore/gormstore"
|
||||
internal "git.itzana.me/strafesnet/maps-service/pkg/internal"
|
||||
"git.itzana.me/strafesnet/maps-service/pkg/roblox"
|
||||
"git.itzana.me/strafesnet/maps-service/pkg/web_api"
|
||||
"git.itzana.me/strafesnet/maps-service/pkg/service"
|
||||
"git.itzana.me/strafesnet/maps-service/pkg/service_internal"
|
||||
"github.com/nats-io/nats.go"
|
||||
@@ -130,36 +131,37 @@ func serve(ctx *cli.Context) error {
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
svc := &service.Service{
|
||||
DB: db,
|
||||
Nats: js,
|
||||
Maps: maps.NewMapsServiceClient(conn),
|
||||
Users: users.NewUsersServiceClient(conn),
|
||||
Roblox: roblox.Client{
|
||||
svc_inner := service.NewService(
|
||||
db,
|
||||
js,
|
||||
maps.NewMapsServiceClient(conn),
|
||||
users.NewUsersServiceClient(conn),
|
||||
)
|
||||
|
||||
svc_external := web_api.NewService(
|
||||
&svc_inner,
|
||||
roblox.Client{
|
||||
HttpClient: http.DefaultClient,
|
||||
ApiKey: ctx.String("rbx-api-key"),
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
conn, err = grpc.Dial(ctx.String("auth-rpc-host"), grpc.WithTransportCredentials(insecure.NewCredentials()))
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
sec := service.SecurityHandler{
|
||||
sec := web_api.SecurityHandler{
|
||||
Client: auth.NewAuthServiceClient(conn),
|
||||
}
|
||||
|
||||
srv, err := api.NewServer(svc, sec, api.WithPathPrefix("/v1"))
|
||||
srv_external, err := api.NewServer(&svc_external, sec, api.WithPathPrefix("/v1"))
|
||||
if err != nil {
|
||||
log.WithError(err).Fatal("failed to initialize api server")
|
||||
}
|
||||
|
||||
svc2 := &service_internal.Service{
|
||||
DB: db,
|
||||
Nats: js,
|
||||
}
|
||||
svc_internal := service_internal.NewService(&svc_inner)
|
||||
|
||||
srv2, err := internal.NewServer(svc2, internal.WithPathPrefix("/v1"))
|
||||
srv_internal, err := internal.NewServer(&svc_internal, internal.WithPathPrefix("/v1"))
|
||||
if err != nil {
|
||||
log.WithError(err).Fatal("failed to initialize api server")
|
||||
}
|
||||
@@ -168,12 +170,12 @@ func serve(ctx *cli.Context) error {
|
||||
|
||||
// First server
|
||||
go func(errChan chan error) {
|
||||
errChan <- http.ListenAndServe(fmt.Sprintf(":%d", ctx.Int("port-internal")), srv2)
|
||||
errChan <- http.ListenAndServe(fmt.Sprintf(":%d", ctx.Int("port-internal")), srv_internal)
|
||||
}(errChan)
|
||||
|
||||
// Second server
|
||||
go func(errChan chan error) {
|
||||
errChan <- http.ListenAndServe(fmt.Sprintf(":%d", ctx.Int("port")), srv)
|
||||
errChan <- http.ListenAndServe(fmt.Sprintf(":%d", ctx.Int("port")), srv_external)
|
||||
}(errChan)
|
||||
|
||||
// Wait for the first error or completion of both tasks
|
||||
|
||||
33
pkg/model/roles.go
Normal file
33
pkg/model/roles.go
Normal file
@@ -0,0 +1,33 @@
|
||||
package model
|
||||
|
||||
// Submissions roles bitflag
|
||||
type Roles int32
|
||||
var (
|
||||
RolesSubmissionUpload Roles = 1<<6
|
||||
RolesSubmissionReview Roles = 1<<5
|
||||
RolesSubmissionRelease Roles = 1<<4
|
||||
RolesScriptWrite Roles = 1<<3
|
||||
RolesMapfixUpload Roles = 1<<2
|
||||
RolesMapfixReview Roles = 1<<1
|
||||
RolesMapDownload Roles = 1<<0
|
||||
RolesEmpty Roles = 0
|
||||
)
|
||||
|
||||
// StrafesNET group roles
|
||||
type GroupRole int32
|
||||
var (
|
||||
// has ScriptWrite
|
||||
RoleQuat GroupRole = 255
|
||||
RoleItzaname GroupRole = 254
|
||||
RoleStagingDeveloper GroupRole = 240
|
||||
RolesAll Roles = ^RolesEmpty
|
||||
// has SubmissionUpload
|
||||
RoleMapAdmin GroupRole = 128
|
||||
RolesMapAdmin Roles = RolesSubmissionRelease|RolesSubmissionUpload|RolesSubmissionReview|RolesMapCouncil
|
||||
// has MapfixReview
|
||||
RoleMapCouncil GroupRole = 64
|
||||
RolesMapCouncil Roles = RolesMapfixReview|RolesMapfixUpload|RolesMapAccess
|
||||
// access to downloading maps
|
||||
RoleMapAccess GroupRole = 32
|
||||
RolesMapAccess Roles = RolesMapDownload
|
||||
)
|
||||
@@ -16,7 +16,7 @@ func (svc *Service) ListAuditEvents(ctx context.Context, resource model.Resource
|
||||
filter.Add("resource_type", resource.Type)
|
||||
filter.Add("resource_id", resource.ID)
|
||||
|
||||
items, err := svc.DB.AuditEvents().List(ctx, filter, page)
|
||||
items, err := svc.db.AuditEvents().List(ctx, filter, page)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -32,7 +32,7 @@ func (svc *Service) ListAuditEvents(ctx context.Context, resource model.Resource
|
||||
idList.ID = append(idList.ID, userId)
|
||||
}
|
||||
|
||||
userList, err := svc.Users.GetList(ctx, &idList)
|
||||
userList, err := svc.users.GetList(ctx, &idList)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -74,7 +74,7 @@ func (svc *Service) CreateAuditEventAction(ctx context.Context, userId uint64, r
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = svc.DB.AuditEvents().Create(ctx, model.AuditEvent{
|
||||
_, err = svc.db.AuditEvents().Create(ctx, model.AuditEvent{
|
||||
ID: 0,
|
||||
User: userId,
|
||||
ResourceType: resource.Type,
|
||||
@@ -95,7 +95,7 @@ func (svc *Service) CreateAuditEventComment(ctx context.Context, userId uint64,
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = svc.DB.AuditEvents().Create(ctx, model.AuditEvent{
|
||||
_, err = svc.db.AuditEvents().Create(ctx, model.AuditEvent{
|
||||
ID: 0,
|
||||
User: userId,
|
||||
ResourceType: resource.Type,
|
||||
@@ -116,7 +116,7 @@ func (svc *Service) CreateAuditEventChangeModel(ctx context.Context, userId uint
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = svc.DB.AuditEvents().Create(ctx, model.AuditEvent{
|
||||
_, err = svc.db.AuditEvents().Create(ctx, model.AuditEvent{
|
||||
ID: 0,
|
||||
User: userId,
|
||||
ResourceType: resource.Type,
|
||||
@@ -130,3 +130,67 @@ func (svc *Service) CreateAuditEventChangeModel(ctx context.Context, userId uint
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
func (svc *Service) CreateAuditEventChangeValidatedModel(ctx context.Context, userId uint64, resource model.Resource, event_data model.AuditEventDataChangeValidatedModel) error {
|
||||
EventData, err := json.Marshal(event_data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = svc.db.AuditEvents().Create(ctx, model.AuditEvent{
|
||||
ID: 0,
|
||||
User: userId,
|
||||
ResourceType: resource.Type,
|
||||
ResourceID: resource.ID,
|
||||
EventType: model.AuditEventTypeChangeValidatedModel,
|
||||
EventData: EventData,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (svc *Service) CreateAuditEventError(ctx context.Context, userId uint64, resource model.Resource, event_data model.AuditEventDataError) error {
|
||||
EventData, err := json.Marshal(event_data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = svc.db.AuditEvents().Create(ctx, model.AuditEvent{
|
||||
ID: 0,
|
||||
User: userId,
|
||||
ResourceType: resource.Type,
|
||||
ResourceID: resource.ID,
|
||||
EventType: model.AuditEventTypeError,
|
||||
EventData: EventData,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (svc *Service) CreateAuditEventCheckList(ctx context.Context, userId uint64, resource model.Resource, event_data model.AuditEventDataCheckList) error {
|
||||
EventData, err := json.Marshal(event_data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = svc.db.AuditEvents().Create(ctx, model.AuditEvent{
|
||||
ID: 0,
|
||||
User: userId,
|
||||
ResourceType: resource.Type,
|
||||
ResourceID: resource.ID,
|
||||
EventType: model.AuditEventTypeCheckList,
|
||||
EventData: EventData,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -2,114 +2,115 @@ package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"git.itzana.me/strafesnet/go-grpc/maps"
|
||||
"git.itzana.me/strafesnet/maps-service/pkg/api"
|
||||
"git.itzana.me/strafesnet/maps-service/pkg/roblox"
|
||||
"git.itzana.me/strafesnet/maps-service/pkg/model"
|
||||
)
|
||||
|
||||
// ListMaps implements listMaps operation.
|
||||
//
|
||||
// Get list of maps.
|
||||
//
|
||||
// GET /maps
|
||||
func (svc *Service) ListMaps(ctx context.Context, params api.ListMapsParams) ([]api.Map, error) {
|
||||
filter := maps.MapFilter{}
|
||||
// Optional map used to update an object
|
||||
type MapUpdate maps.MapRequest
|
||||
|
||||
if params.DisplayName.IsSet(){
|
||||
filter.DisplayName = ¶ms.DisplayName.Value
|
||||
}
|
||||
if params.Creator.IsSet(){
|
||||
filter.Creator = ¶ms.Creator.Value
|
||||
}
|
||||
if params.GameID.IsSet(){
|
||||
filter.GameID = ¶ms.GameID.Value
|
||||
func NewMapUpdate(id int64) *MapUpdate {
|
||||
item := MapUpdate{
|
||||
ID: id,
|
||||
}
|
||||
return &item
|
||||
}
|
||||
func (update *MapUpdate) SetDisplayName(display_name string) {
|
||||
update.DisplayName = &display_name
|
||||
}
|
||||
func (update *MapUpdate) SetCreator(creator string) {
|
||||
update.Creator = &creator
|
||||
}
|
||||
func (update *MapUpdate) SetGameID(game_id int32) {
|
||||
update.GameID = &game_id
|
||||
}
|
||||
func (update *MapUpdate) SetDate(date int64) {
|
||||
update.Date = &date
|
||||
}
|
||||
|
||||
mapList, err := svc.Maps.List(ctx, &maps.ListRequest{
|
||||
Filter: &filter,
|
||||
Page: &maps.Pagination{
|
||||
Size: params.Limit,
|
||||
Number: params.Page,
|
||||
},
|
||||
// Optional map used to find matching objects
|
||||
type MapFilter maps.MapFilter
|
||||
|
||||
func NewMapFilter() *MapFilter {
|
||||
item := MapFilter{}
|
||||
return &item
|
||||
}
|
||||
func (filter *MapFilter) SetDisplayName(display_name string) {
|
||||
filter.DisplayName = &display_name
|
||||
}
|
||||
func (filter *MapFilter) SetCreator(creator string) {
|
||||
filter.Creator = &creator
|
||||
}
|
||||
func (filter *MapFilter) SetGameID(game_id int32) {
|
||||
filter.GameID = &game_id
|
||||
}
|
||||
|
||||
func (svc *Service) CreateMap(ctx context.Context, item model.Map) (int64, error) {
|
||||
date := item.Date.Unix()
|
||||
id_message, err := svc.maps.Create(ctx, &maps.MapRequest{
|
||||
ID: item.ID,
|
||||
DisplayName: &item.DisplayName,
|
||||
Creator: &item.Creator,
|
||||
GameID: &item.GameID,
|
||||
Date: &date,
|
||||
})
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
return id_message.ID, nil
|
||||
}
|
||||
|
||||
func (svc *Service) ListMaps(ctx context.Context, filter *MapFilter, page model.Page) ([]model.Map, error) {
|
||||
page_request := maps.Pagination{
|
||||
Size: page.Size,
|
||||
Number: page.Number,
|
||||
}
|
||||
request := maps.ListRequest{
|
||||
Filter: (*maps.MapFilter)(filter),
|
||||
Page: &page_request,
|
||||
}
|
||||
|
||||
items, err := svc.maps.List(ctx, &request)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var resp []api.Map
|
||||
for _, item := range mapList.Maps {
|
||||
resp = append(resp, api.Map{
|
||||
ID: item.ID,
|
||||
DisplayName: item.DisplayName,
|
||||
Creator: item.Creator,
|
||||
GameID: item.GameID,
|
||||
Date: item.Date,
|
||||
})
|
||||
resp := make([]model.Map, len(items.Maps))
|
||||
for i, item := range items.Maps {
|
||||
resp[i].ID = item.ID
|
||||
resp[i].DisplayName = item.DisplayName
|
||||
resp[i].Creator = item.Creator
|
||||
resp[i].GameID = item.GameID
|
||||
resp[i].Date = time.Unix(item.Date, 0)
|
||||
}
|
||||
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
// GetMap implements getScript operation.
|
||||
//
|
||||
// Get the specified script by ID.
|
||||
//
|
||||
// GET /maps/{MapID}
|
||||
func (svc *Service) GetMap(ctx context.Context, params api.GetMapParams) (*api.Map, error) {
|
||||
mapResponse, err := svc.Maps.Get(ctx, &maps.IdMessage{
|
||||
ID: params.MapID,
|
||||
})
|
||||
func (svc *Service) DeleteMap(ctx context.Context, id int64) error {
|
||||
_, err := svc.maps.Delete(ctx, &maps.IdMessage{ID: id})
|
||||
return err
|
||||
}
|
||||
|
||||
func (svc *Service) GetMap(ctx context.Context, id int64) (*model.Map, error) {
|
||||
item, err := svc.maps.Get(ctx, &maps.IdMessage{ID: id})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &api.Map{
|
||||
ID: mapResponse.ID,
|
||||
DisplayName: mapResponse.DisplayName,
|
||||
Creator: mapResponse.Creator,
|
||||
GameID: mapResponse.GameID,
|
||||
Date: mapResponse.Date,
|
||||
return &model.Map{
|
||||
ID: item.ID,
|
||||
DisplayName: item.DisplayName,
|
||||
Creator: item.Creator,
|
||||
GameID: item.GameID,
|
||||
Date: time.Unix(item.Date, 0),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// GetMapAssetLocation invokes getMapAssetLocation operation.
|
||||
//
|
||||
// Get location of map asset.
|
||||
//
|
||||
// GET /maps/{MapID}/location
|
||||
func (svc *Service) GetMapAssetLocation(ctx context.Context, params api.GetMapAssetLocationParams) (ok api.GetMapAssetLocationOK, err error) {
|
||||
userInfo, success := ctx.Value("UserInfo").(UserInfoHandle)
|
||||
if !success {
|
||||
return ok, ErrUserInfo
|
||||
}
|
||||
|
||||
has_role, err := userInfo.HasRoleMapDownload()
|
||||
if err != nil {
|
||||
return ok, err
|
||||
}
|
||||
|
||||
if !has_role {
|
||||
return ok, ErrPermissionDeniedNeedRoleMapDownload
|
||||
}
|
||||
|
||||
// Ensure map exists in the db!
|
||||
// This could otherwise be used to access any asset
|
||||
_, err = svc.Maps.Get(ctx, &maps.IdMessage{
|
||||
ID: params.MapID,
|
||||
})
|
||||
if err != nil {
|
||||
return ok, err
|
||||
}
|
||||
|
||||
info, err := svc.Roblox.GetAssetLocation(roblox.GetAssetLatestRequest{
|
||||
AssetID: uint64(params.MapID),
|
||||
})
|
||||
if err != nil{
|
||||
return ok, err
|
||||
}
|
||||
|
||||
ok.Data = strings.NewReader(info.Location)
|
||||
return ok, nil
|
||||
func (svc *Service) UpdateMap(ctx context.Context, pmap *MapUpdate) error {
|
||||
_, err := svc.maps.Update(ctx, (*maps.MapRequest)(pmap))
|
||||
return err
|
||||
}
|
||||
|
||||
114
pkg/service/nats_mapfix.go
Normal file
114
pkg/service/nats_mapfix.go
Normal file
@@ -0,0 +1,114 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
|
||||
"git.itzana.me/strafesnet/maps-service/pkg/model"
|
||||
)
|
||||
|
||||
func (svc *Service) NatsCreateMapfix(
|
||||
OperationID int32,
|
||||
ModelID uint64,
|
||||
TargetAssetID uint64,
|
||||
Description string,
|
||||
) error {
|
||||
create_request := model.CreateMapfixRequest{
|
||||
OperationID: OperationID,
|
||||
ModelID: ModelID,
|
||||
TargetAssetID: TargetAssetID,
|
||||
Description: Description,
|
||||
}
|
||||
|
||||
j, err := json.Marshal(create_request)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = svc.nats.Publish("maptest.mapfixes.create", []byte(j))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (svc *Service) NatsCheckMapfix(
|
||||
MapfixID int64,
|
||||
ModelID uint64,
|
||||
SkipChecks bool,
|
||||
) error {
|
||||
validate_request := model.CheckMapfixRequest{
|
||||
MapfixID: MapfixID,
|
||||
ModelID: ModelID,
|
||||
SkipChecks: SkipChecks,
|
||||
}
|
||||
|
||||
j, err := json.Marshal(validate_request)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = svc.nats.Publish("maptest.mapfixes.check", []byte(j))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (svc *Service) NatsUploadMapfix(
|
||||
MapfixID int64,
|
||||
ModelID uint64,
|
||||
ModelVersion uint64,
|
||||
TargetAssetID uint64,
|
||||
) error {
|
||||
upload_fix_request := model.UploadMapfixRequest{
|
||||
MapfixID: MapfixID,
|
||||
ModelID: ModelID,
|
||||
ModelVersion: ModelVersion,
|
||||
TargetAssetID: TargetAssetID,
|
||||
}
|
||||
|
||||
j, err := json.Marshal(upload_fix_request)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = svc.nats.Publish("maptest.mapfixes.upload", []byte(j))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (svc *Service) NatsValidateMapfix(
|
||||
MapfixID int64,
|
||||
ModelID uint64,
|
||||
ModelVersion uint64,
|
||||
ValidatedAssetID uint64,
|
||||
) error {
|
||||
validate_request := model.ValidateMapfixRequest{
|
||||
MapfixID: MapfixID,
|
||||
ModelID: ModelID,
|
||||
ModelVersion: ModelVersion,
|
||||
ValidatedModelID: nil,
|
||||
}
|
||||
|
||||
// sentinel values because we're not using rust
|
||||
if ValidatedAssetID != 0 {
|
||||
validate_request.ValidatedModelID = &ValidatedAssetID
|
||||
}
|
||||
|
||||
j, err := json.Marshal(validate_request)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = svc.nats.Publish("maptest.mapfixes.validate", []byte(j))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
120
pkg/service/nats_submission.go
Normal file
120
pkg/service/nats_submission.go
Normal file
@@ -0,0 +1,120 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
|
||||
"git.itzana.me/strafesnet/maps-service/pkg/model"
|
||||
)
|
||||
|
||||
func (svc *Service) NatsCreateSubmission(
|
||||
OperationID int32,
|
||||
ModelID uint64,
|
||||
DisplayName string,
|
||||
Creator string,
|
||||
GameID uint32,
|
||||
Status uint32,
|
||||
Roles uint32,
|
||||
) error {
|
||||
create_request := model.CreateSubmissionRequest{
|
||||
OperationID: OperationID,
|
||||
ModelID: ModelID,
|
||||
DisplayName: DisplayName,
|
||||
Creator: Creator,
|
||||
GameID: GameID,
|
||||
Status: Status,
|
||||
Roles: Roles,
|
||||
}
|
||||
|
||||
j, err := json.Marshal(create_request)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = svc.nats.Publish("maptest.submissions.create", []byte(j))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (svc *Service) NatsCheckSubmission(
|
||||
SubmissionID int64,
|
||||
ModelID uint64,
|
||||
SkipChecks bool,
|
||||
) error {
|
||||
validate_request := model.CheckSubmissionRequest{
|
||||
SubmissionID: SubmissionID,
|
||||
ModelID: ModelID,
|
||||
SkipChecks: SkipChecks,
|
||||
}
|
||||
|
||||
j, err := json.Marshal(validate_request)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = svc.nats.Publish("maptest.submissions.check", []byte(j))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (svc *Service) NatsUploadSubmission(
|
||||
SubmissionID int64,
|
||||
ModelID uint64,
|
||||
ModelVersion uint64,
|
||||
ModelName string,
|
||||
) error {
|
||||
upload_new_request := model.UploadSubmissionRequest{
|
||||
SubmissionID: SubmissionID,
|
||||
ModelID: ModelID,
|
||||
ModelVersion: ModelVersion,
|
||||
ModelName: ModelName,
|
||||
}
|
||||
|
||||
j, err := json.Marshal(upload_new_request)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = svc.nats.Publish("maptest.submissions.upload", []byte(j))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (svc *Service) NatsValidateSubmission(
|
||||
SubmissionID int64,
|
||||
ModelID uint64,
|
||||
ModelVersion uint64,
|
||||
ValidatedModelID uint64,
|
||||
) error {
|
||||
validate_request := model.ValidateSubmissionRequest{
|
||||
SubmissionID: SubmissionID,
|
||||
ModelID: ModelID,
|
||||
ModelVersion: ModelVersion,
|
||||
ValidatedModelID: nil,
|
||||
}
|
||||
|
||||
// sentinel values because we're not using rust
|
||||
if ValidatedModelID != 0 {
|
||||
validate_request.ValidatedModelID = &ValidatedModelID
|
||||
}
|
||||
|
||||
j, err := json.Marshal(validate_request)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = svc.nats.Publish("maptest.submissions.validate", []byte(j))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -2,45 +2,54 @@ package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"git.itzana.me/strafesnet/maps-service/pkg/api"
|
||||
"git.itzana.me/strafesnet/maps-service/pkg/datastore"
|
||||
"git.itzana.me/strafesnet/maps-service/pkg/model"
|
||||
)
|
||||
|
||||
// GetOperation implements getOperation operation.
|
||||
//
|
||||
// Get the specified operation by ID.
|
||||
//
|
||||
// GET /operations/{OperationID}
|
||||
func (svc *Service) GetOperation(ctx context.Context, params api.GetOperationParams) (*api.Operation, error) {
|
||||
userInfo, ok := ctx.Value("UserInfo").(UserInfoHandle)
|
||||
if !ok {
|
||||
return nil, ErrUserInfo
|
||||
}
|
||||
type OperationFailParams datastore.OptionalMap
|
||||
|
||||
// You must be the operation owner to read it
|
||||
|
||||
operation, err := svc.DB.Operations().Get(ctx, params.OperationID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
userId, err := userInfo.GetUserID()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// check if caller is the submitter
|
||||
has_role := userId == operation.Owner
|
||||
if !has_role {
|
||||
return nil, ErrPermissionDeniedNotSubmitter
|
||||
}
|
||||
|
||||
return &api.Operation{
|
||||
OperationID: operation.ID,
|
||||
Date: operation.CreatedAt.Unix(),
|
||||
Owner: int64(operation.Owner),
|
||||
Status: int32(operation.StatusID),
|
||||
StatusMessage: operation.StatusMessage,
|
||||
Path: operation.Path,
|
||||
}, nil
|
||||
func NewOperationFailParams(
|
||||
status_message string,
|
||||
) OperationFailParams {
|
||||
filter := datastore.Optional()
|
||||
filter.Add("status_id", model.OperationStatusFailed)
|
||||
filter.Add("status_message", status_message)
|
||||
return OperationFailParams(filter)
|
||||
}
|
||||
|
||||
type OperationCompleteParams datastore.OptionalMap
|
||||
|
||||
func NewOperationCompleteParams(
|
||||
path string,
|
||||
) OperationCompleteParams {
|
||||
filter := datastore.Optional()
|
||||
filter.Add("status_id", model.OperationStatusCompleted)
|
||||
filter.Add("path", path)
|
||||
return OperationCompleteParams(filter)
|
||||
}
|
||||
|
||||
func (svc *Service) CreateOperation(ctx context.Context, operation model.Operation) (model.Operation, error) {
|
||||
return svc.db.Operations().Create(ctx, operation)
|
||||
}
|
||||
|
||||
func (svc *Service) CountOperationsSince(ctx context.Context, owner int64, since time.Time) (int64, error) {
|
||||
return svc.db.Operations().CountSince(ctx, owner, since)
|
||||
}
|
||||
|
||||
func (svc *Service) DeleteOperation(ctx context.Context, id int32) error {
|
||||
return svc.db.Operations().Delete(ctx, id)
|
||||
}
|
||||
|
||||
func (svc *Service) GetOperation(ctx context.Context, id int32) (model.Operation, error) {
|
||||
return svc.db.Operations().Get(ctx, id)
|
||||
}
|
||||
|
||||
func (svc *Service) FailOperation(ctx context.Context, id int32, params OperationFailParams) error {
|
||||
return svc.db.Operations().Update(ctx, id, datastore.OptionalMap(params))
|
||||
}
|
||||
|
||||
func (svc *Service) CompleteOperation(ctx context.Context, id int32, params OperationCompleteParams) error {
|
||||
return svc.db.Operations().Update(ctx, id, datastore.OptionalMap(params))
|
||||
}
|
||||
|
||||
@@ -3,169 +3,43 @@ package service
|
||||
import (
|
||||
"context"
|
||||
|
||||
"git.itzana.me/strafesnet/maps-service/pkg/api"
|
||||
"git.itzana.me/strafesnet/maps-service/pkg/datastore"
|
||||
"git.itzana.me/strafesnet/maps-service/pkg/model"
|
||||
)
|
||||
|
||||
// CreateScriptPolicy implements createScriptPolicy operation.
|
||||
//
|
||||
// Create a new script policy.
|
||||
//
|
||||
// POST /script-policy
|
||||
func (svc *Service) CreateScriptPolicy(ctx context.Context, req *api.ScriptPolicyCreate) (*api.ScriptPolicyID, error) {
|
||||
userInfo, ok := ctx.Value("UserInfo").(UserInfoHandle)
|
||||
if !ok {
|
||||
return nil, ErrUserInfo
|
||||
}
|
||||
type ScriptPolicyFilter datastore.OptionalMap
|
||||
|
||||
has_role, err := userInfo.HasRoleScriptWrite()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !has_role {
|
||||
return nil, ErrPermissionDenied
|
||||
}
|
||||
|
||||
from_script, err := svc.DB.Scripts().Get(ctx, req.FromScriptID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// the existence of ToScriptID does not need to be validated because it's checked by a foreign key constraint.
|
||||
|
||||
script, err := svc.DB.ScriptPolicy().Create(ctx, model.ScriptPolicy{
|
||||
ID: 0,
|
||||
FromScriptHash: from_script.Hash,
|
||||
ToScriptID: req.ToScriptID,
|
||||
Policy: model.Policy(req.Policy),
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &api.ScriptPolicyID{
|
||||
ScriptPolicyID: script.ID,
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
||||
// ListScriptPolicy implements listScriptPolicy operation.
|
||||
//
|
||||
// Get list of script policies.
|
||||
//
|
||||
// GET /script-policy
|
||||
func (svc *Service) ListScriptPolicy(ctx context.Context, params api.ListScriptPolicyParams) ([]api.ScriptPolicy, error) {
|
||||
func NewScriptPolicyFilter() ScriptPolicyFilter {
|
||||
filter := datastore.Optional()
|
||||
|
||||
if params.FromScriptHash.IsSet(){
|
||||
hash, err := model.HashParse(params.FromScriptHash.Value)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
filter.Add("from_script_hash", int64(hash)) // No type safety!
|
||||
}
|
||||
if params.ToScriptID.IsSet(){
|
||||
filter.Add("to_script_id", params.ToScriptID.Value)
|
||||
}
|
||||
if params.Policy.IsSet(){
|
||||
filter.Add("policy", params.Policy.Value)
|
||||
}
|
||||
|
||||
items, err := svc.DB.ScriptPolicy().List(ctx, filter, model.Page{
|
||||
Number: params.Page,
|
||||
Size: params.Limit,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var resp []api.ScriptPolicy
|
||||
for _, item := range items {
|
||||
resp = append(resp, api.ScriptPolicy{
|
||||
ID: item.ID,
|
||||
FromScriptHash: model.HashFormat(uint64(item.FromScriptHash)),
|
||||
ToScriptID: item.ToScriptID,
|
||||
Policy: int32(item.Policy),
|
||||
})
|
||||
}
|
||||
|
||||
return resp, nil
|
||||
return ScriptPolicyFilter(filter)
|
||||
}
|
||||
func (filter ScriptPolicyFilter) SetFromScriptHash(from_script_hash int64) {
|
||||
// Finally, type safety!
|
||||
datastore.OptionalMap(filter).Add("from_script_hash", from_script_hash)
|
||||
}
|
||||
func (filter ScriptPolicyFilter) SetToScriptID(to_script_id int64) {
|
||||
datastore.OptionalMap(filter).Add("to_script_id", to_script_id)
|
||||
}
|
||||
func (filter ScriptPolicyFilter) SetPolicy(policy int32) {
|
||||
datastore.OptionalMap(filter).Add("policy", policy)
|
||||
}
|
||||
|
||||
// DeleteScriptPolicy implements deleteScriptPolicy operation.
|
||||
//
|
||||
// Delete the specified script policy by ID.
|
||||
//
|
||||
// DELETE /script-policy/{ScriptPolicyID}
|
||||
func (svc *Service) DeleteScriptPolicy(ctx context.Context, params api.DeleteScriptPolicyParams) error {
|
||||
userInfo, ok := ctx.Value("UserInfo").(UserInfoHandle)
|
||||
if !ok {
|
||||
return ErrUserInfo
|
||||
}
|
||||
|
||||
has_role, err := userInfo.HasRoleScriptWrite()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !has_role {
|
||||
return ErrPermissionDenied
|
||||
}
|
||||
|
||||
return svc.DB.ScriptPolicy().Delete(ctx, params.ScriptPolicyID)
|
||||
func (svc *Service) CreateScriptPolicy(ctx context.Context, script model.ScriptPolicy) (model.ScriptPolicy, error) {
|
||||
return svc.db.ScriptPolicy().Create(ctx, script)
|
||||
}
|
||||
|
||||
// GetScriptPolicy implements getScriptPolicy operation.
|
||||
//
|
||||
// Get the specified script policy by ID.
|
||||
//
|
||||
// GET /script-policy/{ScriptPolicyID}
|
||||
func (svc *Service) GetScriptPolicy(ctx context.Context, params api.GetScriptPolicyParams) (*api.ScriptPolicy, error) {
|
||||
policy, err := svc.DB.ScriptPolicy().Get(ctx, params.ScriptPolicyID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &api.ScriptPolicy{
|
||||
ID: policy.ID,
|
||||
FromScriptHash: model.HashFormat(uint64(policy.FromScriptHash)),
|
||||
ToScriptID: policy.ToScriptID,
|
||||
Policy: int32(policy.Policy),
|
||||
}, nil
|
||||
func (svc *Service) ListScriptPolicies(ctx context.Context, filter ScriptPolicyFilter, page model.Page) ([]model.ScriptPolicy, error) {
|
||||
return svc.db.ScriptPolicy().List(ctx, datastore.OptionalMap(filter), page)
|
||||
}
|
||||
|
||||
// UpdateScriptPolicy implements updateScriptPolicy operation.
|
||||
//
|
||||
// Update the specified script policy by ID.
|
||||
//
|
||||
// POST /script-policy/{ScriptPolicyID}
|
||||
func (svc *Service) UpdateScriptPolicy(ctx context.Context, req *api.ScriptPolicyUpdate, params api.UpdateScriptPolicyParams) error {
|
||||
userInfo, ok := ctx.Value("UserInfo").(UserInfoHandle)
|
||||
if !ok {
|
||||
return ErrUserInfo
|
||||
}
|
||||
|
||||
has_role, err := userInfo.HasRoleScriptWrite()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !has_role {
|
||||
return ErrPermissionDenied
|
||||
}
|
||||
|
||||
pmap := datastore.Optional()
|
||||
if from_script_id, ok := req.FromScriptID.Get(); ok {
|
||||
from_script, err := svc.DB.Scripts().Get(ctx, from_script_id)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
pmap.Add("from_script_hash", from_script.Hash)
|
||||
}
|
||||
if to_script_id, ok := req.ToScriptID.Get(); ok {
|
||||
pmap.Add("to_script_id", to_script_id)
|
||||
}
|
||||
if policy, ok := req.Policy.Get(); ok {
|
||||
pmap.Add("policy", policy)
|
||||
}
|
||||
return svc.DB.ScriptPolicy().Update(ctx, req.ID, pmap)
|
||||
func (svc *Service) DeleteScriptPolicy(ctx context.Context, id int64) error {
|
||||
return svc.db.ScriptPolicy().Delete(ctx, id)
|
||||
}
|
||||
|
||||
func (svc *Service) GetScriptPolicy(ctx context.Context, id int64) (model.ScriptPolicy, error) {
|
||||
return svc.db.ScriptPolicy().Get(ctx, id)
|
||||
}
|
||||
|
||||
func (svc *Service) UpdateScriptPolicy(ctx context.Context, id int64, pmap ScriptPolicyFilter) error {
|
||||
return svc.db.ScriptPolicy().Update(ctx, id, datastore.OptionalMap(pmap))
|
||||
}
|
||||
|
||||
@@ -3,173 +3,48 @@ package service
|
||||
import (
|
||||
"context"
|
||||
|
||||
"git.itzana.me/strafesnet/maps-service/pkg/api"
|
||||
"git.itzana.me/strafesnet/maps-service/pkg/datastore"
|
||||
"git.itzana.me/strafesnet/maps-service/pkg/model"
|
||||
)
|
||||
|
||||
// CreateScript implements createScript operation.
|
||||
//
|
||||
// Create a new script.
|
||||
//
|
||||
// POST /scripts
|
||||
func (svc *Service) CreateScript(ctx context.Context, req *api.ScriptCreate) (*api.ScriptID, error) {
|
||||
userInfo, ok := ctx.Value("UserInfo").(UserInfoHandle)
|
||||
if !ok {
|
||||
return nil, ErrUserInfo
|
||||
}
|
||||
type ScriptFilter datastore.OptionalMap
|
||||
|
||||
has_role, err := userInfo.HasRoleScriptWrite()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !has_role {
|
||||
return nil, ErrPermissionDenied
|
||||
}
|
||||
|
||||
script, err := svc.DB.Scripts().Create(ctx, model.Script{
|
||||
ID: 0,
|
||||
Name: req.Name,
|
||||
Hash: int64(model.HashSource(req.Source)),
|
||||
Source: req.Source,
|
||||
ResourceType: model.ResourceType(req.ResourceType),
|
||||
ResourceID: req.ResourceID.Or(0),
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &api.ScriptID{
|
||||
ScriptID: script.ID,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// ListScripts implements listScripts operation.
|
||||
//
|
||||
// Get list of scripts.
|
||||
//
|
||||
// GET /scripts
|
||||
func (svc *Service) ListScripts(ctx context.Context, params api.ListScriptsParams) ([]api.Script, error) {
|
||||
func NewScriptFilter() ScriptFilter {
|
||||
filter := datastore.Optional()
|
||||
|
||||
if params.Hash.IsSet(){
|
||||
hash, err := model.HashParse(params.Hash.Value)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
filter.Add("hash", int64(hash)) // No type safety!
|
||||
}
|
||||
if params.Name.IsSet(){
|
||||
filter.Add("name", params.Name.Value)
|
||||
}
|
||||
if params.Source.IsSet(){
|
||||
filter.Add("source", params.Source.Value)
|
||||
}
|
||||
if params.ResourceType.IsSet(){
|
||||
filter.Add("resource_type", params.ResourceType.Value)
|
||||
}
|
||||
if params.ResourceID.IsSet(){
|
||||
filter.Add("resource_id", params.ResourceID.Value)
|
||||
}
|
||||
|
||||
items, err := svc.DB.Scripts().List(ctx, filter, model.Page{
|
||||
Number: params.Page,
|
||||
Size: params.Limit,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var resp []api.Script
|
||||
for _, item := range items {
|
||||
resp = append(resp, api.Script{
|
||||
ID: item.ID,
|
||||
Name: item.Name,
|
||||
Hash: model.HashFormat(uint64(item.Hash)),
|
||||
Source: item.Source,
|
||||
ResourceType: int32(item.ResourceType),
|
||||
ResourceID: item.ResourceID,
|
||||
})
|
||||
}
|
||||
|
||||
return resp, nil
|
||||
return ScriptFilter(filter)
|
||||
}
|
||||
func (filter ScriptFilter) SetName(name string) {
|
||||
datastore.OptionalMap(filter).Add("name", name)
|
||||
}
|
||||
func (filter ScriptFilter) SetSource(source string) {
|
||||
datastore.OptionalMap(filter).Add("source", source)
|
||||
}
|
||||
func (filter ScriptFilter) SetHash(hash int64) {
|
||||
datastore.OptionalMap(filter).Add("hash", hash)
|
||||
}
|
||||
func (filter ScriptFilter) SetResourceType(resource_type int32) {
|
||||
datastore.OptionalMap(filter).Add("resource_type", resource_type)
|
||||
}
|
||||
func (filter ScriptFilter) SetResourceID(resource_id int64) {
|
||||
datastore.OptionalMap(filter).Add("resource_id", resource_id)
|
||||
}
|
||||
|
||||
// DeleteScript implements deleteScript operation.
|
||||
//
|
||||
// Delete the specified script by ID.
|
||||
//
|
||||
// DELETE /scripts/{ScriptID}
|
||||
func (svc *Service) DeleteScript(ctx context.Context, params api.DeleteScriptParams) error {
|
||||
userInfo, ok := ctx.Value("UserInfo").(UserInfoHandle)
|
||||
if !ok {
|
||||
return ErrUserInfo
|
||||
}
|
||||
|
||||
has_role, err := userInfo.HasRoleScriptWrite()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !has_role {
|
||||
return ErrPermissionDenied
|
||||
}
|
||||
|
||||
return svc.DB.Scripts().Delete(ctx, params.ScriptID)
|
||||
func (svc *Service) CreateScript(ctx context.Context, script model.Script) (model.Script, error) {
|
||||
return svc.db.Scripts().Create(ctx, script)
|
||||
}
|
||||
|
||||
// GetScript implements getScript operation.
|
||||
//
|
||||
// Get the specified script by ID.
|
||||
//
|
||||
// GET /scripts/{ScriptID}
|
||||
func (svc *Service) GetScript(ctx context.Context, params api.GetScriptParams) (*api.Script, error) {
|
||||
script, err := svc.DB.Scripts().Get(ctx, params.ScriptID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &api.Script{
|
||||
ID: script.ID,
|
||||
Name: script.Name,
|
||||
Hash: model.HashFormat(uint64(script.Hash)),
|
||||
Source: script.Source,
|
||||
ResourceType: int32(script.ResourceType),
|
||||
ResourceID: script.ResourceID,
|
||||
}, nil
|
||||
func (svc *Service) ListScripts(ctx context.Context, filter ScriptFilter, page model.Page) ([]model.Script, error) {
|
||||
return svc.db.Scripts().List(ctx, datastore.OptionalMap(filter), page)
|
||||
}
|
||||
|
||||
// UpdateScript implements updateScript operation.
|
||||
//
|
||||
// Update the specified script by ID.
|
||||
//
|
||||
// PATCH /scripts/{ScriptID}
|
||||
func (svc *Service) UpdateScript(ctx context.Context, req *api.ScriptUpdate, params api.UpdateScriptParams) error {
|
||||
userInfo, ok := ctx.Value("UserInfo").(UserInfoHandle)
|
||||
if !ok {
|
||||
return ErrUserInfo
|
||||
}
|
||||
|
||||
has_role, err := userInfo.HasRoleScriptWrite()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !has_role {
|
||||
return ErrPermissionDenied
|
||||
}
|
||||
|
||||
pmap := datastore.Optional()
|
||||
if Name, ok := req.Name.Get(); ok {
|
||||
pmap.Add("name", Name)
|
||||
}
|
||||
if source, ok := req.Source.Get(); ok {
|
||||
pmap.Add("source", source)
|
||||
pmap.Add("hash", int64(model.HashSource(source))) // No type safety!
|
||||
}
|
||||
if ResourceType, ok := req.ResourceType.Get(); ok {
|
||||
pmap.Add("resource_type", ResourceType)
|
||||
}
|
||||
if ResourceID, ok := req.ResourceID.Get(); ok {
|
||||
pmap.Add("resource_id", ResourceID)
|
||||
}
|
||||
return svc.DB.Scripts().Update(ctx, req.ID, pmap)
|
||||
func (svc *Service) DeleteScript(ctx context.Context, id int64) error {
|
||||
return svc.db.Scripts().Delete(ctx, id)
|
||||
}
|
||||
|
||||
func (svc *Service) GetScript(ctx context.Context, id int64) (model.Script, error) {
|
||||
return svc.db.Scripts().Get(ctx, id)
|
||||
}
|
||||
|
||||
func (svc *Service) UpdateScript(ctx context.Context, id int64, pmap ScriptFilter) error {
|
||||
return svc.db.Scripts().Update(ctx, id, datastore.OptionalMap(pmap))
|
||||
}
|
||||
|
||||
@@ -1,63 +1,29 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"git.itzana.me/strafesnet/go-grpc/maps"
|
||||
"git.itzana.me/strafesnet/go-grpc/users"
|
||||
"git.itzana.me/strafesnet/maps-service/pkg/api"
|
||||
"git.itzana.me/strafesnet/maps-service/pkg/datastore"
|
||||
"git.itzana.me/strafesnet/maps-service/pkg/roblox"
|
||||
"github.com/nats-io/nats.go"
|
||||
)
|
||||
|
||||
var (
|
||||
// ErrPermissionDenied caller does not have the required role
|
||||
ErrPermissionDenied = errors.New("Permission denied")
|
||||
// ErrUserInfo user info is missing for some reason
|
||||
ErrUserInfo = errors.New("Missing user info")
|
||||
ErrDelayReset = errors.New("Please give the validator at least 10 seconds to operate before attempting to reset the status")
|
||||
ErrPermissionDeniedNotSubmitter = fmt.Errorf("%w: You must be the submitter to perform this action", ErrPermissionDenied)
|
||||
ErrPermissionDeniedNeedRoleSubmissionRelease = fmt.Errorf("%w: Need Role SubmissionRelease", ErrPermissionDenied)
|
||||
ErrPermissionDeniedNeedRoleMapfixUpload = fmt.Errorf("%w: Need Role MapfixUpload", ErrPermissionDenied)
|
||||
ErrPermissionDeniedNeedRoleMapfixReview = fmt.Errorf("%w: Need Role MapfixReview", ErrPermissionDenied)
|
||||
ErrPermissionDeniedNeedRoleSubmissionUpload = fmt.Errorf("%w: Need Role SubmissionUpload", ErrPermissionDenied)
|
||||
ErrPermissionDeniedNeedRoleSubmissionReview = fmt.Errorf("%w: Need Role SubmissionReview", ErrPermissionDenied)
|
||||
ErrPermissionDeniedNeedRoleMapDownload = fmt.Errorf("%w: Need Role MapDownload", ErrPermissionDenied)
|
||||
ErrPermissionDeniedNeedRoleScriptWrite = fmt.Errorf("%w: Need Role ScriptWrite", ErrPermissionDenied)
|
||||
ErrPermissionDeniedNeedRoleMaptest = fmt.Errorf("%w: Need Role Maptest", ErrPermissionDenied)
|
||||
ErrNegativeID = errors.New("A negative ID was provided")
|
||||
)
|
||||
|
||||
type Service struct {
|
||||
DB datastore.Datastore
|
||||
Nats nats.JetStreamContext
|
||||
Maps maps.MapsServiceClient
|
||||
Users users.UsersServiceClient
|
||||
Roblox roblox.Client
|
||||
db datastore.Datastore
|
||||
nats nats.JetStreamContext
|
||||
maps maps.MapsServiceClient
|
||||
users users.UsersServiceClient
|
||||
}
|
||||
|
||||
// NewError creates *ErrorStatusCode from error returned by handler.
|
||||
//
|
||||
// Used for common default response.
|
||||
func (svc *Service) NewError(ctx context.Context, err error) *api.ErrorStatusCode {
|
||||
status := 500
|
||||
if errors.Is(err, datastore.ErrNotExist) {
|
||||
status = 404
|
||||
}
|
||||
if errors.Is(err, ErrPermissionDenied) {
|
||||
status = 403
|
||||
}
|
||||
if errors.Is(err, ErrUserInfo) {
|
||||
status = 401
|
||||
}
|
||||
return &api.ErrorStatusCode{
|
||||
StatusCode: status,
|
||||
Response: api.Error{
|
||||
Code: int64(status),
|
||||
Message: err.Error(),
|
||||
},
|
||||
func NewService(
|
||||
db datastore.Datastore,
|
||||
nats nats.JetStreamContext,
|
||||
maps maps.MapsServiceClient,
|
||||
users users.UsersServiceClient,
|
||||
) Service {
|
||||
return Service{
|
||||
db: db,
|
||||
nats: nats,
|
||||
maps: maps,
|
||||
users: users,
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,92 +0,0 @@
|
||||
package service_internal
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
|
||||
"git.itzana.me/strafesnet/maps-service/pkg/model"
|
||||
)
|
||||
|
||||
func (svc *Service) CreateAuditEventAction(ctx context.Context, userId uint64, resource model.Resource, event_data model.AuditEventDataAction) error {
|
||||
EventData, err := json.Marshal(event_data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = svc.DB.AuditEvents().Create(ctx, model.AuditEvent{
|
||||
ID: 0,
|
||||
User: userId,
|
||||
ResourceType: resource.Type,
|
||||
ResourceID: resource.ID,
|
||||
EventType: model.AuditEventTypeAction,
|
||||
EventData: EventData,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (svc *Service) CreateAuditEventChangeValidatedModel(ctx context.Context, userId uint64, resource model.Resource, event_data model.AuditEventDataChangeValidatedModel) error {
|
||||
EventData, err := json.Marshal(event_data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = svc.DB.AuditEvents().Create(ctx, model.AuditEvent{
|
||||
ID: 0,
|
||||
User: userId,
|
||||
ResourceType: resource.Type,
|
||||
ResourceID: resource.ID,
|
||||
EventType: model.AuditEventTypeChangeValidatedModel,
|
||||
EventData: EventData,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (svc *Service) CreateAuditEventError(ctx context.Context, userId uint64, resource model.Resource, event_data model.AuditEventDataError) error {
|
||||
EventData, err := json.Marshal(event_data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = svc.DB.AuditEvents().Create(ctx, model.AuditEvent{
|
||||
ID: 0,
|
||||
User: userId,
|
||||
ResourceType: resource.Type,
|
||||
ResourceID: resource.ID,
|
||||
EventType: model.AuditEventTypeError,
|
||||
EventData: EventData,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (svc *Service) CreateAuditEventCheckList(ctx context.Context, userId uint64, resource model.Resource, event_data model.AuditEventDataCheckList) error {
|
||||
EventData, err := json.Marshal(event_data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = svc.DB.AuditEvents().Create(ctx, model.AuditEvent{
|
||||
ID: 0,
|
||||
User: userId,
|
||||
ResourceType: resource.Type,
|
||||
ResourceID: resource.ID,
|
||||
EventType: model.AuditEventTypeCheckList,
|
||||
EventData: EventData,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -8,6 +8,7 @@ import (
|
||||
"git.itzana.me/strafesnet/maps-service/pkg/datastore"
|
||||
internal "git.itzana.me/strafesnet/maps-service/pkg/internal"
|
||||
"git.itzana.me/strafesnet/maps-service/pkg/model"
|
||||
"git.itzana.me/strafesnet/maps-service/pkg/service"
|
||||
)
|
||||
|
||||
var(
|
||||
@@ -38,12 +39,12 @@ func (svc *Service) UpdateMapfixValidatedModel(ctx context.Context, params inter
|
||||
ValidatedModelVersion := uint64(params.ValidatedModelVersion)
|
||||
|
||||
// check if Status is ChangesRequested|Submitted|UnderConstruction
|
||||
pmap := datastore.Optional()
|
||||
pmap.Add("validated_asset_id", ValidatedModelID)
|
||||
pmap.Add("validated_asset_version", ValidatedModelVersion)
|
||||
update := service.NewMapfixUpdate()
|
||||
update.SetValidatedAssetID(ValidatedModelID)
|
||||
update.SetValidatedAssetVersion(ValidatedModelVersion)
|
||||
// DO NOT reset completed when validated model is updated
|
||||
// pmap.Add("completed", false)
|
||||
err := svc.DB.Mapfixes().IfStatusThenUpdate(ctx, params.MapfixID, []model.MapfixStatus{model.MapfixStatusValidating}, pmap)
|
||||
// update.Add("completed", false)
|
||||
err := svc.inner.UpdateMapfixIfStatus(ctx, params.MapfixID, []model.MapfixStatus{model.MapfixStatusValidating}, update)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -53,7 +54,7 @@ func (svc *Service) UpdateMapfixValidatedModel(ctx context.Context, params inter
|
||||
ValidatedModelVersion: ValidatedModelVersion,
|
||||
}
|
||||
|
||||
return svc.CreateAuditEventChangeValidatedModel(
|
||||
return svc.inner.CreateAuditEventChangeValidatedModel(
|
||||
ctx,
|
||||
ValidtorUserID,
|
||||
model.Resource{
|
||||
@@ -72,13 +73,14 @@ func (svc *Service) UpdateMapfixValidatedModel(ctx context.Context, params inter
|
||||
func (svc *Service) ActionMapfixSubmitted(ctx context.Context, params internal.ActionMapfixSubmittedParams) error {
|
||||
// transaction
|
||||
target_status := model.MapfixStatusSubmitted
|
||||
smap := datastore.Optional()
|
||||
smap.Add("status_id", target_status)
|
||||
smap.Add("asset_version", params.ModelVersion)
|
||||
smap.Add("display_name", params.DisplayName)
|
||||
smap.Add("creator", params.Creator)
|
||||
smap.Add("game_id", params.GameID)
|
||||
err := svc.DB.Mapfixes().IfStatusThenUpdate(ctx, params.MapfixID, []model.MapfixStatus{model.MapfixStatusSubmitting}, smap)
|
||||
update := service.NewMapfixUpdate()
|
||||
update.SetStatusID(target_status)
|
||||
update.SetAssetVersion(uint64(params.ModelVersion))
|
||||
update.SetDisplayName(params.DisplayName)
|
||||
update.SetCreator(params.Creator)
|
||||
update.SetGameID(uint32(params.GameID))
|
||||
allow_statuses := []model.MapfixStatus{model.MapfixStatusSubmitting}
|
||||
err := svc.inner.UpdateMapfixIfStatus(ctx, params.MapfixID, allow_statuses, update)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -87,7 +89,7 @@ func (svc *Service) ActionMapfixSubmitted(ctx context.Context, params internal.A
|
||||
TargetStatus: uint32(target_status),
|
||||
}
|
||||
|
||||
return svc.CreateAuditEventAction(
|
||||
return svc.inner.CreateAuditEventAction(
|
||||
ctx,
|
||||
ValidtorUserID,
|
||||
model.Resource{
|
||||
@@ -106,9 +108,9 @@ func (svc *Service) ActionMapfixSubmitted(ctx context.Context, params internal.A
|
||||
func (svc *Service) ActionMapfixRequestChanges(ctx context.Context, params internal.ActionMapfixRequestChangesParams) error {
|
||||
// transaction
|
||||
target_status := model.MapfixStatusChangesRequested
|
||||
smap := datastore.Optional()
|
||||
smap.Add("status_id", target_status)
|
||||
err := svc.DB.Mapfixes().IfStatusThenUpdate(ctx, params.MapfixID, []model.MapfixStatus{model.MapfixStatusSubmitting}, smap)
|
||||
update := service.NewMapfixUpdate()
|
||||
update.SetStatusID(target_status)
|
||||
err := svc.inner.UpdateMapfixIfStatus(ctx, params.MapfixID, []model.MapfixStatus{model.MapfixStatusSubmitting}, update)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -117,7 +119,7 @@ func (svc *Service) ActionMapfixRequestChanges(ctx context.Context, params inter
|
||||
TargetStatus: uint32(target_status),
|
||||
}
|
||||
|
||||
return svc.CreateAuditEventAction(
|
||||
return svc.inner.CreateAuditEventAction(
|
||||
ctx,
|
||||
ValidtorUserID,
|
||||
model.Resource{
|
||||
@@ -135,9 +137,9 @@ func (svc *Service) ActionMapfixRequestChanges(ctx context.Context, params inter
|
||||
// POST /mapfixes/{MapfixID}/status/validator-validated
|
||||
func (svc *Service) ActionMapfixValidated(ctx context.Context, params internal.ActionMapfixValidatedParams) error {
|
||||
// transaction
|
||||
smap := datastore.Optional()
|
||||
smap.Add("status_id", model.MapfixStatusValidated)
|
||||
return svc.DB.Mapfixes().IfStatusThenUpdate(ctx, params.MapfixID, []model.MapfixStatus{model.MapfixStatusValidating}, smap)
|
||||
update := service.NewMapfixUpdate()
|
||||
update.SetStatusID(model.MapfixStatusValidated)
|
||||
return svc.inner.UpdateMapfixIfStatus(ctx, params.MapfixID, []model.MapfixStatus{model.MapfixStatusValidating}, update)
|
||||
}
|
||||
|
||||
// ActionMapfixAccepted implements actionMapfixAccepted operation.
|
||||
@@ -148,9 +150,9 @@ func (svc *Service) ActionMapfixValidated(ctx context.Context, params internal.A
|
||||
func (svc *Service) ActionMapfixAccepted(ctx context.Context, params internal.ActionMapfixAcceptedParams) error {
|
||||
// transaction
|
||||
target_status := model.MapfixStatusAcceptedUnvalidated
|
||||
smap := datastore.Optional()
|
||||
smap.Add("status_id", target_status)
|
||||
err := svc.DB.Mapfixes().IfStatusThenUpdate(ctx, params.MapfixID, []model.MapfixStatus{model.MapfixStatusValidating}, smap)
|
||||
update := service.NewMapfixUpdate()
|
||||
update.SetStatusID(target_status)
|
||||
err := svc.inner.UpdateMapfixIfStatus(ctx, params.MapfixID, []model.MapfixStatus{model.MapfixStatusValidating}, update)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -160,7 +162,7 @@ func (svc *Service) ActionMapfixAccepted(ctx context.Context, params internal.Ac
|
||||
TargetStatus: uint32(target_status),
|
||||
}
|
||||
|
||||
return svc.CreateAuditEventAction(
|
||||
return svc.inner.CreateAuditEventAction(
|
||||
ctx,
|
||||
ValidtorUserID,
|
||||
model.Resource{
|
||||
@@ -179,9 +181,9 @@ func (svc *Service) ActionMapfixAccepted(ctx context.Context, params internal.Ac
|
||||
func (svc *Service) ActionMapfixUploaded(ctx context.Context, params internal.ActionMapfixUploadedParams) error {
|
||||
// transaction
|
||||
target_status := model.MapfixStatusUploaded
|
||||
smap := datastore.Optional()
|
||||
smap.Add("status_id", target_status)
|
||||
err := svc.DB.Mapfixes().IfStatusThenUpdate(ctx, params.MapfixID, []model.MapfixStatus{model.MapfixStatusUploading}, smap)
|
||||
update := service.NewMapfixUpdate()
|
||||
update.SetStatusID(target_status)
|
||||
err := svc.inner.UpdateMapfixIfStatus(ctx, params.MapfixID, []model.MapfixStatus{model.MapfixStatusUploading}, update)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -190,7 +192,7 @@ func (svc *Service) ActionMapfixUploaded(ctx context.Context, params internal.Ac
|
||||
TargetStatus: uint32(target_status),
|
||||
}
|
||||
|
||||
return svc.CreateAuditEventAction(
|
||||
return svc.inner.CreateAuditEventAction(
|
||||
ctx,
|
||||
ValidtorUserID,
|
||||
model.Resource{
|
||||
@@ -211,7 +213,7 @@ func (svc *Service) CreateMapfixAuditError(ctx context.Context, params internal.
|
||||
Error: params.ErrorMessage,
|
||||
}
|
||||
|
||||
return svc.CreateAuditEventError(
|
||||
return svc.inner.CreateAuditEventError(
|
||||
ctx,
|
||||
ValidtorUserID,
|
||||
model.Resource{
|
||||
@@ -241,7 +243,7 @@ func (svc *Service) CreateMapfixAuditCheckList(ctx context.Context, check_list i
|
||||
CheckList: check_list2,
|
||||
}
|
||||
|
||||
return svc.CreateAuditEventCheckList(
|
||||
return svc.inner.CreateAuditEventCheckList(
|
||||
ctx,
|
||||
ValidtorUserID,
|
||||
model.Resource{
|
||||
@@ -270,11 +272,11 @@ func (svc *Service) CreateMapfix(ctx context.Context, request *internal.MapfixCr
|
||||
|
||||
// Check if an active mapfix with the same asset id exists
|
||||
{
|
||||
filter := datastore.Optional()
|
||||
filter.Add("asset_id", request.AssetID)
|
||||
filter.Add("asset_version", request.AssetVersion)
|
||||
filter.Add("status_id", ActiveMapfixStatuses)
|
||||
active_mapfixes, err := svc.DB.Mapfixes().List(ctx, filter, model.Page{
|
||||
filter := service.NewMapfixFilter()
|
||||
filter.SetAssetID(AssetID)
|
||||
filter.SetAssetVersion(AssetVersion)
|
||||
filter.SetStatuses(ActiveMapfixStatuses)
|
||||
active_mapfixes, err := svc.inner.ListMapfixes(ctx, filter, model.Page{
|
||||
Number: 1,
|
||||
Size: 1,
|
||||
},datastore.ListSortDisabled)
|
||||
@@ -286,7 +288,7 @@ func (svc *Service) CreateMapfix(ctx context.Context, request *internal.MapfixCr
|
||||
}
|
||||
}
|
||||
|
||||
operation, err := svc.DB.Operations().Get(ctx, request.OperationID)
|
||||
operation, err := svc.inner.GetOperation(ctx, request.OperationID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -297,7 +299,7 @@ func (svc *Service) CreateMapfix(ctx context.Context, request *internal.MapfixCr
|
||||
return nil, ErrNotAssetOwner
|
||||
}
|
||||
|
||||
mapfix, err := svc.DB.Mapfixes().Create(ctx, model.Mapfix{
|
||||
mapfix, err := svc.inner.CreateMapfix(ctx, model.Mapfix{
|
||||
ID: 0,
|
||||
DisplayName: request.DisplayName,
|
||||
Creator: request.Creator,
|
||||
@@ -315,10 +317,8 @@ func (svc *Service) CreateMapfix(ctx context.Context, request *internal.MapfixCr
|
||||
}
|
||||
|
||||
// mark the operation as completed and provide the path
|
||||
pmap := datastore.Optional()
|
||||
pmap.Add("status_id", model.OperationStatusCompleted)
|
||||
pmap.Add("path", fmt.Sprintf("/mapfixes/%d", mapfix.ID))
|
||||
err = svc.DB.Operations().Update(ctx, request.OperationID, pmap)
|
||||
params := service.NewOperationCompleteParams(fmt.Sprintf("/mapfixes/%d", mapfix.ID))
|
||||
err = svc.inner.CompleteOperation(ctx, request.OperationID, params)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -3,9 +3,8 @@ package service_internal
|
||||
import (
|
||||
"context"
|
||||
|
||||
"git.itzana.me/strafesnet/maps-service/pkg/datastore"
|
||||
internal "git.itzana.me/strafesnet/maps-service/pkg/internal"
|
||||
"git.itzana.me/strafesnet/maps-service/pkg/model"
|
||||
"git.itzana.me/strafesnet/maps-service/pkg/service"
|
||||
)
|
||||
|
||||
// ActionOperationFailed implements actionOperationFailed operation.
|
||||
@@ -14,8 +13,8 @@ import (
|
||||
//
|
||||
// POST /operations/{OperationID}/status/operation-failed
|
||||
func (svc *Service) ActionOperationFailed(ctx context.Context, params internal.ActionOperationFailedParams) (error) {
|
||||
pmap := datastore.Optional()
|
||||
pmap.Add("status_id", model.OperationStatusFailed)
|
||||
pmap.Add("status_message", params.StatusMessage)
|
||||
return svc.DB.Operations().Update(ctx, params.OperationID, pmap)
|
||||
fail_params := service.NewOperationFailParams(
|
||||
params.StatusMessage,
|
||||
)
|
||||
return svc.inner.FailOperation(ctx, params.OperationID, fail_params)
|
||||
}
|
||||
|
||||
@@ -3,9 +3,9 @@ package service_internal
|
||||
import (
|
||||
"context"
|
||||
|
||||
"git.itzana.me/strafesnet/maps-service/pkg/datastore"
|
||||
api "git.itzana.me/strafesnet/maps-service/pkg/internal"
|
||||
"git.itzana.me/strafesnet/maps-service/pkg/model"
|
||||
"git.itzana.me/strafesnet/maps-service/pkg/service"
|
||||
)
|
||||
|
||||
// CreateScriptPolicy implements createScriptPolicy operation.
|
||||
@@ -14,14 +14,14 @@ import (
|
||||
//
|
||||
// POST /script-policy
|
||||
func (svc *Service) CreateScriptPolicy(ctx context.Context, req *api.ScriptPolicyCreate) (*api.ScriptPolicyID, error) {
|
||||
from_script, err := svc.DB.Scripts().Get(ctx, req.FromScriptID)
|
||||
from_script, err := svc.inner.GetScript(ctx, req.FromScriptID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// the existence of ToScriptID does not need to be validated because it's checked by a foreign key constraint.
|
||||
|
||||
script, err := svc.DB.ScriptPolicy().Create(ctx, model.ScriptPolicy{
|
||||
script, err := svc.inner.CreateScriptPolicy(ctx, model.ScriptPolicy{
|
||||
ID: 0,
|
||||
FromScriptHash: from_script.Hash,
|
||||
ToScriptID: req.ToScriptID,
|
||||
@@ -42,23 +42,23 @@ func (svc *Service) CreateScriptPolicy(ctx context.Context, req *api.ScriptPolic
|
||||
//
|
||||
// GET /script-policy
|
||||
func (svc *Service) ListScriptPolicy(ctx context.Context, params api.ListScriptPolicyParams) ([]api.ScriptPolicy, error) {
|
||||
filter := datastore.Optional()
|
||||
filter := service.NewScriptPolicyFilter()
|
||||
|
||||
if params.FromScriptHash.IsSet(){
|
||||
hash, err := model.HashParse(params.FromScriptHash.Value)
|
||||
if hash_hex, ok := params.FromScriptHash.Get(); ok{
|
||||
hash_parsed, err := model.HashParse(hash_hex)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
filter.Add("from_script_hash", int64(hash)) // No type safety!
|
||||
filter.SetFromScriptHash(int64(hash_parsed))
|
||||
}
|
||||
if params.ToScriptID.IsSet(){
|
||||
filter.Add("to_script_id", params.ToScriptID.Value)
|
||||
if to_script_id, to_script_id_ok := params.ToScriptID.Get(); to_script_id_ok{
|
||||
filter.SetToScriptID(to_script_id)
|
||||
}
|
||||
if params.Policy.IsSet(){
|
||||
filter.Add("policy", params.Policy.Value)
|
||||
if policy, policy_ok := params.Policy.Get(); policy_ok{
|
||||
filter.SetPolicy(policy)
|
||||
}
|
||||
|
||||
items, err := svc.DB.ScriptPolicy().List(ctx, filter, model.Page{
|
||||
items, err := svc.inner.ListScriptPolicies(ctx, filter, model.Page{
|
||||
Number: params.Page,
|
||||
Size: params.Limit,
|
||||
})
|
||||
|
||||
@@ -3,9 +3,9 @@ package service_internal
|
||||
import (
|
||||
"context"
|
||||
|
||||
"git.itzana.me/strafesnet/maps-service/pkg/datastore"
|
||||
api "git.itzana.me/strafesnet/maps-service/pkg/internal"
|
||||
"git.itzana.me/strafesnet/maps-service/pkg/model"
|
||||
"git.itzana.me/strafesnet/maps-service/pkg/service"
|
||||
)
|
||||
|
||||
// CreateScript implements createScript operation.
|
||||
@@ -14,7 +14,7 @@ import (
|
||||
//
|
||||
// POST /scripts
|
||||
func (svc *Service) CreateScript(ctx context.Context, req *api.ScriptCreate) (*api.ScriptID, error) {
|
||||
script, err := svc.DB.Scripts().Create(ctx, model.Script{
|
||||
script, err := svc.inner.CreateScript(ctx, model.Script{
|
||||
ID: 0,
|
||||
Name: req.Name,
|
||||
Hash: int64(model.HashSource(req.Source)),
|
||||
@@ -37,29 +37,28 @@ func (svc *Service) CreateScript(ctx context.Context, req *api.ScriptCreate) (*a
|
||||
//
|
||||
// GET /scripts
|
||||
func (svc *Service) ListScripts(ctx context.Context, params api.ListScriptsParams) ([]api.Script, error) {
|
||||
filter := datastore.Optional()
|
||||
|
||||
if params.Hash.IsSet(){
|
||||
hash, err := model.HashParse(params.Hash.Value)
|
||||
filter := service.NewScriptFilter()
|
||||
if hash_hex, ok := params.Hash.Get(); ok{
|
||||
hash_parsed, err := model.HashParse(hash_hex)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
filter.Add("hash", int64(hash)) // No type safety!
|
||||
filter.SetHash(int64(hash_parsed))
|
||||
}
|
||||
if params.Name.IsSet(){
|
||||
filter.Add("name", params.Name.Value)
|
||||
if name, name_ok := params.Name.Get(); name_ok{
|
||||
filter.SetName(name)
|
||||
}
|
||||
if params.Source.IsSet(){
|
||||
filter.Add("source", params.Source.Value)
|
||||
if source, source_ok := params.Source.Get(); source_ok{
|
||||
filter.SetSource(source)
|
||||
}
|
||||
if params.ResourceType.IsSet(){
|
||||
filter.Add("resource_type", params.ResourceType.Value)
|
||||
if resource_type, resource_type_ok := params.ResourceType.Get(); resource_type_ok{
|
||||
filter.SetResourceType(resource_type)
|
||||
}
|
||||
if params.ResourceID.IsSet(){
|
||||
filter.Add("resource_id", params.ResourceID.Value)
|
||||
if resource_id, resource_id_ok := params.ResourceID.Get(); resource_id_ok{
|
||||
filter.SetResourceID(resource_id)
|
||||
}
|
||||
|
||||
items, err := svc.DB.Scripts().List(ctx, filter, model.Page{
|
||||
items, err := svc.inner.ListScripts(ctx, filter, model.Page{
|
||||
Number: params.Page,
|
||||
Size: params.Limit,
|
||||
})
|
||||
@@ -88,7 +87,7 @@ func (svc *Service) ListScripts(ctx context.Context, params api.ListScriptsParam
|
||||
//
|
||||
// GET /scripts/{ScriptID}
|
||||
func (svc *Service) GetScript(ctx context.Context, params api.GetScriptParams) (*api.Script, error) {
|
||||
script, err := svc.DB.Scripts().Get(ctx, params.ScriptID)
|
||||
script, err := svc.inner.GetScript(ctx, params.ScriptID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ import (
|
||||
|
||||
"git.itzana.me/strafesnet/maps-service/pkg/datastore"
|
||||
internal "git.itzana.me/strafesnet/maps-service/pkg/internal"
|
||||
"github.com/nats-io/nats.go"
|
||||
"git.itzana.me/strafesnet/maps-service/pkg/service"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -19,8 +19,15 @@ var (
|
||||
)
|
||||
|
||||
type Service struct {
|
||||
DB datastore.Datastore
|
||||
Nats nats.JetStreamContext
|
||||
inner *service.Service
|
||||
}
|
||||
|
||||
func NewService(
|
||||
inner *service.Service,
|
||||
) Service {
|
||||
return Service{
|
||||
inner: inner,
|
||||
}
|
||||
}
|
||||
|
||||
// yay duplicate code
|
||||
|
||||
@@ -38,12 +38,13 @@ func (svc *Service) UpdateSubmissionValidatedModel(ctx context.Context, params i
|
||||
ValidatedModelVersion := uint64(params.ValidatedModelVersion)
|
||||
|
||||
// check if Status is ChangesRequested|Submitted|UnderConstruction
|
||||
pmap := datastore.Optional()
|
||||
pmap.Add("validated_asset_id", ValidatedModelID)
|
||||
pmap.Add("validated_asset_version", ValidatedModelVersion)
|
||||
update := service.NewSubmissionUpdate()
|
||||
update.SetValidatedAssetID(ValidatedModelID)
|
||||
update.SetValidatedAssetVersion(ValidatedModelVersion)
|
||||
// DO NOT reset completed when validated model is updated
|
||||
// pmap.Add("completed", false)
|
||||
err := svc.DB.Submissions().IfStatusThenUpdate(ctx, params.SubmissionID, []model.SubmissionStatus{model.SubmissionStatusValidating}, pmap)
|
||||
// update.Add("completed", false)
|
||||
allowed_statuses := []model.SubmissionStatus{model.SubmissionStatusValidating}
|
||||
err := svc.inner.UpdateSubmissionIfStatus(ctx, params.SubmissionID, allowed_statuses, update)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -53,7 +54,7 @@ func (svc *Service) UpdateSubmissionValidatedModel(ctx context.Context, params i
|
||||
ValidatedModelVersion: ValidatedModelVersion,
|
||||
}
|
||||
|
||||
return svc.CreateAuditEventChangeValidatedModel(
|
||||
return svc.inner.CreateAuditEventChangeValidatedModel(
|
||||
ctx,
|
||||
ValidtorUserID,
|
||||
model.Resource{
|
||||
@@ -72,13 +73,14 @@ func (svc *Service) UpdateSubmissionValidatedModel(ctx context.Context, params i
|
||||
func (svc *Service) ActionSubmissionSubmitted(ctx context.Context, params internal.ActionSubmissionSubmittedParams) error {
|
||||
// transaction
|
||||
target_status := model.SubmissionStatusSubmitted
|
||||
smap := datastore.Optional()
|
||||
smap.Add("status_id", target_status)
|
||||
smap.Add("asset_version", params.ModelVersion)
|
||||
smap.Add("display_name", params.DisplayName)
|
||||
smap.Add("creator", params.Creator)
|
||||
smap.Add("game_id", params.GameID)
|
||||
err := svc.DB.Submissions().IfStatusThenUpdate(ctx, params.SubmissionID, []model.SubmissionStatus{model.SubmissionStatusSubmitting}, smap)
|
||||
update := service.NewSubmissionUpdate()
|
||||
update.SetStatusID(target_status)
|
||||
update.SetAssetVersion(uint64(params.ModelVersion))
|
||||
update.SetDisplayName(params.DisplayName)
|
||||
update.SetCreator(params.Creator)
|
||||
update.SetGameID(uint32(params.GameID))
|
||||
allowed_statuses := []model.SubmissionStatus{model.SubmissionStatusSubmitting}
|
||||
err := svc.inner.UpdateSubmissionIfStatus(ctx, params.SubmissionID, allowed_statuses, update)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -87,7 +89,7 @@ func (svc *Service) ActionSubmissionSubmitted(ctx context.Context, params intern
|
||||
TargetStatus: uint32(target_status),
|
||||
}
|
||||
|
||||
return svc.CreateAuditEventAction(
|
||||
return svc.inner.CreateAuditEventAction(
|
||||
ctx,
|
||||
ValidtorUserID,
|
||||
model.Resource{
|
||||
@@ -106,9 +108,10 @@ func (svc *Service) ActionSubmissionSubmitted(ctx context.Context, params intern
|
||||
func (svc *Service) ActionSubmissionRequestChanges(ctx context.Context, params internal.ActionSubmissionRequestChangesParams) error {
|
||||
// transaction
|
||||
target_status := model.SubmissionStatusChangesRequested
|
||||
smap := datastore.Optional()
|
||||
smap.Add("status_id", target_status)
|
||||
err := svc.DB.Submissions().IfStatusThenUpdate(ctx, params.SubmissionID, []model.SubmissionStatus{model.SubmissionStatusSubmitting}, smap)
|
||||
update := service.NewSubmissionUpdate()
|
||||
update.SetStatusID(target_status)
|
||||
allowed_statuses :=[]model.SubmissionStatus{model.SubmissionStatusSubmitting}
|
||||
err := svc.inner.UpdateSubmissionIfStatus(ctx, params.SubmissionID, allowed_statuses, update)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -118,7 +121,7 @@ func (svc *Service) ActionSubmissionRequestChanges(ctx context.Context, params i
|
||||
TargetStatus: uint32(target_status),
|
||||
}
|
||||
|
||||
return svc.CreateAuditEventAction(
|
||||
return svc.inner.CreateAuditEventAction(
|
||||
ctx,
|
||||
ValidtorUserID,
|
||||
model.Resource{
|
||||
@@ -137,9 +140,10 @@ func (svc *Service) ActionSubmissionRequestChanges(ctx context.Context, params i
|
||||
func (svc *Service) ActionSubmissionValidated(ctx context.Context, params internal.ActionSubmissionValidatedParams) error {
|
||||
// transaction
|
||||
target_status := model.SubmissionStatusValidated
|
||||
smap := datastore.Optional()
|
||||
smap.Add("status_id", target_status)
|
||||
err := svc.DB.Submissions().IfStatusThenUpdate(ctx, params.SubmissionID, []model.SubmissionStatus{model.SubmissionStatusValidating}, smap)
|
||||
update := service.NewSubmissionUpdate()
|
||||
update.SetStatusID(target_status)
|
||||
allowed_statuses :=[]model.SubmissionStatus{model.SubmissionStatusValidating}
|
||||
err := svc.inner.UpdateSubmissionIfStatus(ctx, params.SubmissionID, allowed_statuses, update)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -148,7 +152,7 @@ func (svc *Service) ActionSubmissionValidated(ctx context.Context, params intern
|
||||
TargetStatus: uint32(target_status),
|
||||
}
|
||||
|
||||
return svc.CreateAuditEventAction(
|
||||
return svc.inner.CreateAuditEventAction(
|
||||
ctx,
|
||||
ValidtorUserID,
|
||||
model.Resource{
|
||||
@@ -167,9 +171,10 @@ func (svc *Service) ActionSubmissionValidated(ctx context.Context, params intern
|
||||
func (svc *Service) ActionSubmissionAccepted(ctx context.Context, params internal.ActionSubmissionAcceptedParams) error {
|
||||
// transaction
|
||||
target_status := model.SubmissionStatusAcceptedUnvalidated
|
||||
smap := datastore.Optional()
|
||||
smap.Add("status_id", target_status)
|
||||
err := svc.DB.Submissions().IfStatusThenUpdate(ctx, params.SubmissionID, []model.SubmissionStatus{model.SubmissionStatusValidating}, smap)
|
||||
update := service.NewSubmissionUpdate()
|
||||
update.SetStatusID(target_status)
|
||||
allowed_statuses :=[]model.SubmissionStatus{model.SubmissionStatusValidating}
|
||||
err := svc.inner.UpdateSubmissionIfStatus(ctx, params.SubmissionID, allowed_statuses, update)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -179,7 +184,7 @@ func (svc *Service) ActionSubmissionAccepted(ctx context.Context, params interna
|
||||
TargetStatus: uint32(target_status),
|
||||
}
|
||||
|
||||
return svc.CreateAuditEventAction(
|
||||
return svc.inner.CreateAuditEventAction(
|
||||
ctx,
|
||||
ValidtorUserID,
|
||||
model.Resource{
|
||||
@@ -198,10 +203,11 @@ func (svc *Service) ActionSubmissionAccepted(ctx context.Context, params interna
|
||||
func (svc *Service) ActionSubmissionUploaded(ctx context.Context, params internal.ActionSubmissionUploadedParams) error {
|
||||
// transaction
|
||||
target_status := model.SubmissionStatusUploaded
|
||||
smap := datastore.Optional()
|
||||
smap.Add("status_id", target_status)
|
||||
smap.Add("uploaded_asset_id", params.UploadedAssetID)
|
||||
err := svc.DB.Submissions().IfStatusThenUpdate(ctx, params.SubmissionID, []model.SubmissionStatus{model.SubmissionStatusUploading}, smap)
|
||||
update := service.NewSubmissionUpdate()
|
||||
update.SetStatusID(target_status)
|
||||
update.SetUploadedAssetID(uint64(params.UploadedAssetID))
|
||||
allowed_statuses :=[]model.SubmissionStatus{model.SubmissionStatusUploading}
|
||||
err := svc.inner.UpdateSubmissionIfStatus(ctx, params.SubmissionID, allowed_statuses, update)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -210,7 +216,7 @@ func (svc *Service) ActionSubmissionUploaded(ctx context.Context, params interna
|
||||
TargetStatus: uint32(target_status),
|
||||
}
|
||||
|
||||
return svc.CreateAuditEventAction(
|
||||
return svc.inner.CreateAuditEventAction(
|
||||
ctx,
|
||||
ValidtorUserID,
|
||||
model.Resource{
|
||||
@@ -231,7 +237,7 @@ func (svc *Service) CreateSubmissionAuditError(ctx context.Context, params inter
|
||||
Error: params.ErrorMessage,
|
||||
}
|
||||
|
||||
return svc.CreateAuditEventError(
|
||||
return svc.inner.CreateAuditEventError(
|
||||
ctx,
|
||||
ValidtorUserID,
|
||||
model.Resource{
|
||||
@@ -261,7 +267,7 @@ func (svc *Service) CreateSubmissionAuditCheckList(ctx context.Context, check_li
|
||||
CheckList: check_list2,
|
||||
}
|
||||
|
||||
return svc.CreateAuditEventCheckList(
|
||||
return svc.inner.CreateAuditEventCheckList(
|
||||
ctx,
|
||||
ValidtorUserID,
|
||||
model.Resource{
|
||||
@@ -286,15 +292,15 @@ func (svc *Service) CreateSubmission(ctx context.Context, request *internal.Subm
|
||||
var AssetID=uint64(request.AssetID);
|
||||
var AssetVersion=uint64(request.AssetVersion);
|
||||
var Status=model.SubmissionStatus(request.Status);
|
||||
var roles=service.Roles(request.Roles);
|
||||
var roles=model.Roles(request.Roles);
|
||||
|
||||
// Check if an active submission with the same asset id exists
|
||||
{
|
||||
filter := datastore.Optional()
|
||||
filter.Add("asset_id", request.AssetID)
|
||||
filter.Add("asset_version", request.AssetVersion)
|
||||
filter.Add("status_id", ActiveSubmissionStatuses)
|
||||
active_submissions, err := svc.DB.Submissions().List(ctx, filter, model.Page{
|
||||
filter := service.NewSubmissionFilter()
|
||||
filter.SetAssetID(AssetID)
|
||||
filter.SetAssetVersion(AssetVersion)
|
||||
filter.SetStatuses(ActiveSubmissionStatuses)
|
||||
active_submissions, err := svc.inner.ListSubmissions(ctx, filter, model.Page{
|
||||
Number: 1,
|
||||
Size: 1,
|
||||
},datastore.ListSortDisabled)
|
||||
@@ -306,7 +312,7 @@ func (svc *Service) CreateSubmission(ctx context.Context, request *internal.Subm
|
||||
}
|
||||
}
|
||||
|
||||
operation, err := svc.DB.Operations().Get(ctx, request.OperationID)
|
||||
operation, err := svc.inner.GetOperation(ctx, request.OperationID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -314,13 +320,13 @@ func (svc *Service) CreateSubmission(ctx context.Context, request *internal.Subm
|
||||
// check if user owns asset
|
||||
is_submitter := operation.Owner == Submitter
|
||||
// check if user is map admin
|
||||
has_submission_review := roles & service.RolesSubmissionReview == service.RolesSubmissionReview
|
||||
has_submission_review := roles & model.RolesSubmissionReview == model.RolesSubmissionReview
|
||||
// if neither, u not allowed
|
||||
if !is_submitter && !has_submission_review {
|
||||
return nil, ErrNotAssetOwner
|
||||
}
|
||||
|
||||
submission, err := svc.DB.Submissions().Create(ctx, model.Submission{
|
||||
submission, err := svc.inner.CreateSubmission(ctx, model.Submission{
|
||||
ID: 0,
|
||||
DisplayName: request.DisplayName,
|
||||
Creator: request.Creator,
|
||||
@@ -336,10 +342,8 @@ func (svc *Service) CreateSubmission(ctx context.Context, request *internal.Subm
|
||||
}
|
||||
|
||||
// mark the operation as completed and provide the path
|
||||
pmap := datastore.Optional()
|
||||
pmap.Add("status_id", model.OperationStatusCompleted)
|
||||
pmap.Add("path", fmt.Sprintf("/submissions/%d", submission.ID))
|
||||
err = svc.DB.Operations().Update(ctx, request.OperationID, pmap)
|
||||
params := service.NewOperationCompleteParams(fmt.Sprintf("/submissions/%d", submission.ID))
|
||||
err = svc.inner.CompleteOperation(ctx, request.OperationID, params)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
1068
pkg/web_api/mapfixes.go
Normal file
1068
pkg/web_api/mapfixes.go
Normal file
File diff suppressed because it is too large
Load Diff
112
pkg/web_api/maps.go
Normal file
112
pkg/web_api/maps.go
Normal file
@@ -0,0 +1,112 @@
|
||||
package web_api
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strings"
|
||||
|
||||
"git.itzana.me/strafesnet/maps-service/pkg/api"
|
||||
"git.itzana.me/strafesnet/maps-service/pkg/model"
|
||||
"git.itzana.me/strafesnet/maps-service/pkg/roblox"
|
||||
"git.itzana.me/strafesnet/maps-service/pkg/service"
|
||||
)
|
||||
|
||||
// ListMaps implements listMaps operation.
|
||||
//
|
||||
// Get list of maps.
|
||||
//
|
||||
// GET /maps
|
||||
func (svc *Service) ListMaps(ctx context.Context, params api.ListMapsParams) ([]api.Map, error) {
|
||||
filter := service.NewMapFilter()
|
||||
|
||||
if display_name, display_name_ok := params.DisplayName.Get(); display_name_ok{
|
||||
filter.SetDisplayName(display_name)
|
||||
}
|
||||
if creator, creator_ok := params.Creator.Get(); creator_ok{
|
||||
filter.SetCreator(creator)
|
||||
}
|
||||
if game_id, game_id_ok := params.GameID.Get(); game_id_ok{
|
||||
filter.SetGameID(game_id)
|
||||
}
|
||||
|
||||
items, err := svc.inner.ListMaps(ctx,
|
||||
filter,
|
||||
model.Page{
|
||||
Size: params.Limit,
|
||||
Number: params.Page,
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var resp []api.Map
|
||||
for _, item := range items {
|
||||
resp = append(resp, api.Map{
|
||||
ID: item.ID,
|
||||
DisplayName: item.DisplayName,
|
||||
Creator: item.Creator,
|
||||
GameID: item.GameID,
|
||||
Date: item.Date.Unix(),
|
||||
})
|
||||
}
|
||||
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
// GetMap implements getScript operation.
|
||||
//
|
||||
// Get the specified script by ID.
|
||||
//
|
||||
// GET /maps/{MapID}
|
||||
func (svc *Service) GetMap(ctx context.Context, params api.GetMapParams) (*api.Map, error) {
|
||||
mapResponse, err := svc.inner.GetMap(ctx, params.MapID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &api.Map{
|
||||
ID: mapResponse.ID,
|
||||
DisplayName: mapResponse.DisplayName,
|
||||
Creator: mapResponse.Creator,
|
||||
GameID: mapResponse.GameID,
|
||||
Date: mapResponse.Date.Unix(),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// GetMapAssetLocation invokes getMapAssetLocation operation.
|
||||
//
|
||||
// Get location of map asset.
|
||||
//
|
||||
// GET /maps/{MapID}/location
|
||||
func (svc *Service) GetMapAssetLocation(ctx context.Context, params api.GetMapAssetLocationParams) (ok api.GetMapAssetLocationOK, err error) {
|
||||
userInfo, success := ctx.Value("UserInfo").(UserInfoHandle)
|
||||
if !success {
|
||||
return ok, ErrUserInfo
|
||||
}
|
||||
|
||||
has_role, err := userInfo.HasRoleMapDownload()
|
||||
if err != nil {
|
||||
return ok, err
|
||||
}
|
||||
|
||||
if !has_role {
|
||||
return ok, ErrPermissionDeniedNeedRoleMapDownload
|
||||
}
|
||||
|
||||
// Ensure map exists in the db!
|
||||
// This could otherwise be used to access any asset
|
||||
_, err = svc.inner.GetMap(ctx, params.MapID)
|
||||
if err != nil {
|
||||
return ok, err
|
||||
}
|
||||
|
||||
info, err := svc.roblox.GetAssetLocation(roblox.GetAssetLatestRequest{
|
||||
AssetID: uint64(params.MapID),
|
||||
})
|
||||
if err != nil{
|
||||
return ok, err
|
||||
}
|
||||
|
||||
ok.Data = strings.NewReader(info.Location)
|
||||
return ok, nil
|
||||
}
|
||||
46
pkg/web_api/operations.go
Normal file
46
pkg/web_api/operations.go
Normal file
@@ -0,0 +1,46 @@
|
||||
package web_api
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"git.itzana.me/strafesnet/maps-service/pkg/api"
|
||||
)
|
||||
|
||||
// GetOperation implements getOperation operation.
|
||||
//
|
||||
// Get the specified operation by ID.
|
||||
//
|
||||
// GET /operations/{OperationID}
|
||||
func (svc *Service) GetOperation(ctx context.Context, params api.GetOperationParams) (*api.Operation, error) {
|
||||
userInfo, ok := ctx.Value("UserInfo").(UserInfoHandle)
|
||||
if !ok {
|
||||
return nil, ErrUserInfo
|
||||
}
|
||||
|
||||
// You must be the operation owner to read it
|
||||
|
||||
operation, err := svc.inner.GetOperation(ctx, params.OperationID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
userId, err := userInfo.GetUserID()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// check if caller is the submitter
|
||||
has_role := userId == operation.Owner
|
||||
if !has_role {
|
||||
return nil, ErrPermissionDeniedNotSubmitter
|
||||
}
|
||||
|
||||
return &api.Operation{
|
||||
OperationID: operation.ID,
|
||||
Date: operation.CreatedAt.Unix(),
|
||||
Owner: int64(operation.Owner),
|
||||
Status: int32(operation.StatusID),
|
||||
StatusMessage: operation.StatusMessage,
|
||||
Path: operation.Path,
|
||||
}, nil
|
||||
}
|
||||
149
pkg/web_api/script_policy.go
Normal file
149
pkg/web_api/script_policy.go
Normal file
@@ -0,0 +1,149 @@
|
||||
package web_api
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"git.itzana.me/strafesnet/maps-service/pkg/api"
|
||||
"git.itzana.me/strafesnet/maps-service/pkg/model"
|
||||
"git.itzana.me/strafesnet/maps-service/pkg/service"
|
||||
)
|
||||
|
||||
// CreateScriptPolicy implements createScriptPolicy operation.
|
||||
//
|
||||
// Create a new script policy.
|
||||
//
|
||||
// POST /script-policy
|
||||
func (svc *Service) CreateScriptPolicy(ctx context.Context, req *api.ScriptPolicyCreate) (*api.ScriptPolicyID, error) {
|
||||
err := CheckHasRoleScriptWrite(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
from_script, err := svc.inner.GetScript(ctx, req.FromScriptID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// the existence of ToScriptID does not need to be validated because it's checked by a foreign key constraint.
|
||||
|
||||
script, err := svc.inner.CreateScriptPolicy(ctx, model.ScriptPolicy{
|
||||
ID: 0,
|
||||
FromScriptHash: from_script.Hash,
|
||||
ToScriptID: req.ToScriptID,
|
||||
Policy: model.Policy(req.Policy),
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &api.ScriptPolicyID{
|
||||
ScriptPolicyID: script.ID,
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
||||
// ListScriptPolicy implements listScriptPolicy operation.
|
||||
//
|
||||
// Get list of script policies.
|
||||
//
|
||||
// GET /script-policy
|
||||
func (svc *Service) ListScriptPolicy(ctx context.Context, params api.ListScriptPolicyParams) ([]api.ScriptPolicy, error) {
|
||||
filter := service.NewScriptPolicyFilter()
|
||||
|
||||
if hash_hex, ok := params.FromScriptHash.Get(); ok{
|
||||
hash_parsed, err := model.HashParse(hash_hex)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
filter.SetFromScriptHash(int64(hash_parsed))
|
||||
}
|
||||
if to_script_id, to_script_id_ok := params.ToScriptID.Get(); to_script_id_ok{
|
||||
filter.SetToScriptID(to_script_id)
|
||||
}
|
||||
if policy, policy_ok := params.Policy.Get(); policy_ok{
|
||||
filter.SetPolicy(policy)
|
||||
}
|
||||
|
||||
|
||||
items, err := svc.inner.ListScriptPolicies(ctx, filter, model.Page{
|
||||
Number: params.Page,
|
||||
Size: params.Limit,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var resp []api.ScriptPolicy
|
||||
for _, item := range items {
|
||||
resp = append(resp, api.ScriptPolicy{
|
||||
ID: item.ID,
|
||||
FromScriptHash: model.HashFormat(uint64(item.FromScriptHash)),
|
||||
ToScriptID: item.ToScriptID,
|
||||
Policy: int32(item.Policy),
|
||||
})
|
||||
}
|
||||
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
// DeleteScriptPolicy implements deleteScriptPolicy operation.
|
||||
//
|
||||
// Delete the specified script policy by ID.
|
||||
//
|
||||
// DELETE /script-policy/{ScriptPolicyID}
|
||||
func (svc *Service) DeleteScriptPolicy(ctx context.Context, params api.DeleteScriptPolicyParams) error {
|
||||
err := CheckHasRoleScriptWrite(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return svc.inner.DeleteScriptPolicy(ctx, params.ScriptPolicyID)
|
||||
}
|
||||
|
||||
// GetScriptPolicy implements getScriptPolicy operation.
|
||||
//
|
||||
// Get the specified script policy by ID.
|
||||
//
|
||||
// GET /script-policy/{ScriptPolicyID}
|
||||
func (svc *Service) GetScriptPolicy(ctx context.Context, params api.GetScriptPolicyParams) (*api.ScriptPolicy, error) {
|
||||
policy, err := svc.inner.GetScriptPolicy(ctx, params.ScriptPolicyID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &api.ScriptPolicy{
|
||||
ID: policy.ID,
|
||||
FromScriptHash: model.HashFormat(uint64(policy.FromScriptHash)),
|
||||
ToScriptID: policy.ToScriptID,
|
||||
Policy: int32(policy.Policy),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// UpdateScriptPolicy implements updateScriptPolicy operation.
|
||||
//
|
||||
// Update the specified script policy by ID.
|
||||
//
|
||||
// POST /script-policy/{ScriptPolicyID}
|
||||
func (svc *Service) UpdateScriptPolicy(ctx context.Context, req *api.ScriptPolicyUpdate, params api.UpdateScriptPolicyParams) error {
|
||||
err := CheckHasRoleScriptWrite(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
filter := service.NewScriptPolicyFilter()
|
||||
if from_script_id, ok := req.FromScriptID.Get(); ok {
|
||||
from_script, err := svc.inner.GetScript(ctx, from_script_id)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
filter.SetFromScriptHash(from_script.Hash)
|
||||
}
|
||||
if to_script_id, to_script_id_ok := req.ToScriptID.Get(); to_script_id_ok{
|
||||
filter.SetToScriptID(to_script_id)
|
||||
}
|
||||
if policy, policy_ok := req.Policy.Get(); policy_ok{
|
||||
filter.SetPolicy(policy)
|
||||
}
|
||||
|
||||
return svc.inner.UpdateScriptPolicy(ctx, req.ID, filter)
|
||||
}
|
||||
170
pkg/web_api/scripts.go
Normal file
170
pkg/web_api/scripts.go
Normal file
@@ -0,0 +1,170 @@
|
||||
package web_api
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"git.itzana.me/strafesnet/maps-service/pkg/api"
|
||||
"git.itzana.me/strafesnet/maps-service/pkg/model"
|
||||
"git.itzana.me/strafesnet/maps-service/pkg/service"
|
||||
)
|
||||
|
||||
func CheckHasRoleScriptWrite(ctx context.Context) error {
|
||||
userInfo, ok := ctx.Value("UserInfo").(UserInfoHandle)
|
||||
if !ok {
|
||||
return ErrUserInfo
|
||||
}
|
||||
|
||||
has_role, err := userInfo.HasRoleScriptWrite()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !has_role {
|
||||
return ErrPermissionDeniedNeedRoleScriptWrite
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// CreateScript implements createScript operation.
|
||||
//
|
||||
// Create a new script.
|
||||
//
|
||||
// POST /scripts
|
||||
func (svc *Service) CreateScript(ctx context.Context, req *api.ScriptCreate) (*api.ScriptID, error) {
|
||||
err := CheckHasRoleScriptWrite(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
script, err := svc.inner.CreateScript(ctx, model.Script{
|
||||
ID: 0,
|
||||
Name: req.Name,
|
||||
Hash: int64(model.HashSource(req.Source)),
|
||||
Source: req.Source,
|
||||
ResourceType: model.ResourceType(req.ResourceType),
|
||||
ResourceID: req.ResourceID.Or(0),
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &api.ScriptID{
|
||||
ScriptID: script.ID,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// ListScripts implements listScripts operation.
|
||||
//
|
||||
// Get list of scripts.
|
||||
//
|
||||
// GET /scripts
|
||||
func (svc *Service) ListScripts(ctx context.Context, params api.ListScriptsParams) ([]api.Script, error) {
|
||||
filter := service.NewScriptFilter()
|
||||
|
||||
if hash_hex, ok := params.Hash.Get(); ok{
|
||||
hash_parsed, err := model.HashParse(hash_hex)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
filter.SetHash(int64(hash_parsed))
|
||||
}
|
||||
if name, name_ok := params.Name.Get(); name_ok{
|
||||
filter.SetName(name)
|
||||
}
|
||||
if source, source_ok := params.Source.Get(); source_ok{
|
||||
filter.SetSource(source)
|
||||
}
|
||||
if resource_type, resource_type_ok := params.ResourceType.Get(); resource_type_ok{
|
||||
filter.SetResourceType(resource_type)
|
||||
}
|
||||
if resource_id, resource_id_ok := params.ResourceID.Get(); resource_id_ok{
|
||||
filter.SetResourceID(resource_id)
|
||||
}
|
||||
|
||||
|
||||
items, err := svc.inner.ListScripts(ctx, filter, model.Page{
|
||||
Number: params.Page,
|
||||
Size: params.Limit,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var resp []api.Script
|
||||
for _, item := range items {
|
||||
resp = append(resp, api.Script{
|
||||
ID: item.ID,
|
||||
Name: item.Name,
|
||||
Hash: model.HashFormat(uint64(item.Hash)),
|
||||
Source: item.Source,
|
||||
ResourceType: int32(item.ResourceType),
|
||||
ResourceID: item.ResourceID,
|
||||
})
|
||||
}
|
||||
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
// DeleteScript implements deleteScript operation.
|
||||
//
|
||||
// Delete the specified script by ID.
|
||||
//
|
||||
// DELETE /scripts/{ScriptID}
|
||||
func (svc *Service) DeleteScript(ctx context.Context, params api.DeleteScriptParams) error {
|
||||
err := CheckHasRoleScriptWrite(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return svc.inner.DeleteScript(ctx, params.ScriptID)
|
||||
}
|
||||
|
||||
// GetScript implements getScript operation.
|
||||
//
|
||||
// Get the specified script by ID.
|
||||
//
|
||||
// GET /scripts/{ScriptID}
|
||||
func (svc *Service) GetScript(ctx context.Context, params api.GetScriptParams) (*api.Script, error) {
|
||||
script, err := svc.inner.GetScript(ctx, params.ScriptID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &api.Script{
|
||||
ID: script.ID,
|
||||
Name: script.Name,
|
||||
Hash: model.HashFormat(uint64(script.Hash)),
|
||||
Source: script.Source,
|
||||
ResourceType: int32(script.ResourceType),
|
||||
ResourceID: script.ResourceID,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// UpdateScript implements updateScript operation.
|
||||
//
|
||||
// Update the specified script by ID.
|
||||
//
|
||||
// PATCH /scripts/{ScriptID}
|
||||
func (svc *Service) UpdateScript(ctx context.Context, req *api.ScriptUpdate, params api.UpdateScriptParams) error {
|
||||
err := CheckHasRoleScriptWrite(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
filter := service.NewScriptFilter()
|
||||
if name, name_ok := req.Name.Get(); name_ok{
|
||||
filter.SetName(name)
|
||||
}
|
||||
if source, source_ok := req.Source.Get(); source_ok{
|
||||
filter.SetSource(source)
|
||||
filter.SetHash(int64(model.HashSource(source)))
|
||||
}
|
||||
if resource_type, resource_type_ok := req.ResourceType.Get(); resource_type_ok{
|
||||
filter.SetResourceType(resource_type)
|
||||
}
|
||||
if resource_id, resource_id_ok := req.ResourceID.Get(); resource_id_ok{
|
||||
filter.SetResourceID(resource_id)
|
||||
}
|
||||
|
||||
return svc.inner.UpdateScript(ctx, req.ID, filter)
|
||||
}
|
||||
@@ -1,10 +1,12 @@
|
||||
package service
|
||||
package web_api
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
|
||||
"git.itzana.me/strafesnet/go-grpc/auth"
|
||||
"git.itzana.me/strafesnet/maps-service/pkg/api"
|
||||
"git.itzana.me/strafesnet/maps-service/pkg/model"
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -14,38 +16,6 @@ var (
|
||||
ErrInvalidSession = errors.New("Session invalid")
|
||||
)
|
||||
|
||||
// Submissions roles bitflag
|
||||
type Roles int32
|
||||
var (
|
||||
RolesSubmissionUpload Roles = 1<<6
|
||||
RolesSubmissionReview Roles = 1<<5
|
||||
RolesSubmissionRelease Roles = 1<<4
|
||||
RolesScriptWrite Roles = 1<<3
|
||||
RolesMapfixUpload Roles = 1<<2
|
||||
RolesMapfixReview Roles = 1<<1
|
||||
RolesMapDownload Roles = 1<<0
|
||||
RolesEmpty Roles = 0
|
||||
)
|
||||
|
||||
// StrafesNET group roles
|
||||
type GroupRole int32
|
||||
var (
|
||||
// has ScriptWrite
|
||||
RoleQuat GroupRole = 255
|
||||
RoleItzaname GroupRole = 254
|
||||
RoleStagingDeveloper GroupRole = 240
|
||||
RolesAll Roles = ^RolesEmpty
|
||||
// has SubmissionUpload
|
||||
RoleMapAdmin GroupRole = 128
|
||||
RolesMapAdmin Roles = RolesSubmissionRelease|RolesSubmissionUpload|RolesSubmissionReview|RolesMapCouncil
|
||||
// has MapfixReview
|
||||
RoleMapCouncil GroupRole = 64
|
||||
RolesMapCouncil Roles = RolesMapfixReview|RolesMapfixUpload|RolesMapAccess
|
||||
// access to downloading maps
|
||||
RoleMapAccess GroupRole = 32
|
||||
RolesMapAccess Roles = RolesMapDownload
|
||||
)
|
||||
|
||||
type UserInfoHandle struct {
|
||||
// Would love to know a better way to do this
|
||||
svc *SecurityHandler
|
||||
@@ -88,7 +58,7 @@ func (usr UserInfoHandle) Validate() (bool, error) {
|
||||
}
|
||||
return validate.Valid, nil
|
||||
}
|
||||
func (usr UserInfoHandle) hasRoles(wantRoles Roles) (bool, error) {
|
||||
func (usr UserInfoHandle) hasRoles(wantRoles model.Roles) (bool, error) {
|
||||
haveroles, err := usr.GetRoles()
|
||||
if err != nil {
|
||||
return false, err
|
||||
@@ -96,27 +66,27 @@ func (usr UserInfoHandle) hasRoles(wantRoles Roles) (bool, error) {
|
||||
|
||||
return haveroles & wantRoles == wantRoles, nil
|
||||
}
|
||||
func (usr UserInfoHandle) GetRoles() (Roles, error) {
|
||||
func (usr UserInfoHandle) GetRoles() (model.Roles, error) {
|
||||
roles, err := usr.svc.Client.GetGroupRole(*usr.ctx, &auth.IdMessage{
|
||||
SessionID: usr.sessionId,
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return RolesEmpty, err
|
||||
return model.RolesEmpty, err
|
||||
}
|
||||
|
||||
// map roles into bitflag
|
||||
rolesBitflag := RolesEmpty;
|
||||
rolesBitflag := model.RolesEmpty;
|
||||
for _, r := range roles.Roles {
|
||||
switch GroupRole(r.Rank){
|
||||
case RoleQuat, RoleItzaname, RoleStagingDeveloper:
|
||||
rolesBitflag|=RolesAll
|
||||
case RoleMapAdmin:
|
||||
rolesBitflag|=RolesMapAdmin
|
||||
case RoleMapCouncil:
|
||||
rolesBitflag|=RolesMapCouncil
|
||||
case RoleMapAccess:
|
||||
rolesBitflag|=RolesMapAccess
|
||||
switch model.GroupRole(r.Rank){
|
||||
case model.RoleQuat, model.RoleItzaname, model.RoleStagingDeveloper:
|
||||
rolesBitflag|=model.RolesAll
|
||||
case model.RoleMapAdmin:
|
||||
rolesBitflag|=model.RolesMapAdmin
|
||||
case model.RoleMapCouncil:
|
||||
rolesBitflag|=model.RolesMapCouncil
|
||||
case model.RoleMapAccess:
|
||||
rolesBitflag|=model.RolesMapAccess
|
||||
}
|
||||
}
|
||||
return rolesBitflag, nil
|
||||
@@ -124,25 +94,25 @@ func (usr UserInfoHandle) GetRoles() (Roles, error) {
|
||||
|
||||
// RoleThumbnail
|
||||
func (usr UserInfoHandle) HasRoleMapfixUpload() (bool, error) {
|
||||
return usr.hasRoles(RolesMapfixUpload)
|
||||
return usr.hasRoles(model.RolesMapfixUpload)
|
||||
}
|
||||
func (usr UserInfoHandle) HasRoleMapfixReview() (bool, error) {
|
||||
return usr.hasRoles(RolesMapfixReview)
|
||||
return usr.hasRoles(model.RolesMapfixReview)
|
||||
}
|
||||
func (usr UserInfoHandle) HasRoleMapDownload() (bool, error) {
|
||||
return usr.hasRoles(RolesMapDownload)
|
||||
return usr.hasRoles(model.RolesMapDownload)
|
||||
}
|
||||
func (usr UserInfoHandle) HasRoleSubmissionRelease() (bool, error) {
|
||||
return usr.hasRoles(RolesSubmissionRelease)
|
||||
return usr.hasRoles(model.RolesSubmissionRelease)
|
||||
}
|
||||
func (usr UserInfoHandle) HasRoleSubmissionUpload() (bool, error) {
|
||||
return usr.hasRoles(RolesSubmissionUpload)
|
||||
return usr.hasRoles(model.RolesSubmissionUpload)
|
||||
}
|
||||
func (usr UserInfoHandle) HasRoleSubmissionReview() (bool, error) {
|
||||
return usr.hasRoles(RolesSubmissionReview)
|
||||
return usr.hasRoles(model.RolesSubmissionReview)
|
||||
}
|
||||
func (usr UserInfoHandle) HasRoleScriptWrite() (bool, error) {
|
||||
return usr.hasRoles(RolesScriptWrite)
|
||||
return usr.hasRoles(model.RolesScriptWrite)
|
||||
}
|
||||
/// Not implemented
|
||||
func (usr UserInfoHandle) HasRoleMaptest() (bool, error) {
|
||||
68
pkg/web_api/service.go
Normal file
68
pkg/web_api/service.go
Normal file
@@ -0,0 +1,68 @@
|
||||
package web_api
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"git.itzana.me/strafesnet/maps-service/pkg/api"
|
||||
"git.itzana.me/strafesnet/maps-service/pkg/datastore"
|
||||
"git.itzana.me/strafesnet/maps-service/pkg/roblox"
|
||||
"git.itzana.me/strafesnet/maps-service/pkg/service"
|
||||
)
|
||||
|
||||
var (
|
||||
// ErrPermissionDenied caller does not have the required role
|
||||
ErrPermissionDenied = errors.New("Permission denied")
|
||||
// ErrUserInfo user info is missing for some reason
|
||||
ErrUserInfo = errors.New("Missing user info")
|
||||
ErrDelayReset = errors.New("Please give the validator at least 10 seconds to operate before attempting to reset the status")
|
||||
ErrPermissionDeniedNotSubmitter = fmt.Errorf("%w: You must be the submitter to perform this action", ErrPermissionDenied)
|
||||
ErrPermissionDeniedNeedRoleSubmissionRelease = fmt.Errorf("%w: Need Role SubmissionRelease", ErrPermissionDenied)
|
||||
ErrPermissionDeniedNeedRoleMapfixUpload = fmt.Errorf("%w: Need Role MapfixUpload", ErrPermissionDenied)
|
||||
ErrPermissionDeniedNeedRoleMapfixReview = fmt.Errorf("%w: Need Role MapfixReview", ErrPermissionDenied)
|
||||
ErrPermissionDeniedNeedRoleSubmissionUpload = fmt.Errorf("%w: Need Role SubmissionUpload", ErrPermissionDenied)
|
||||
ErrPermissionDeniedNeedRoleSubmissionReview = fmt.Errorf("%w: Need Role SubmissionReview", ErrPermissionDenied)
|
||||
ErrPermissionDeniedNeedRoleMapDownload = fmt.Errorf("%w: Need Role MapDownload", ErrPermissionDenied)
|
||||
ErrPermissionDeniedNeedRoleScriptWrite = fmt.Errorf("%w: Need Role ScriptWrite", ErrPermissionDenied)
|
||||
ErrPermissionDeniedNeedRoleMaptest = fmt.Errorf("%w: Need Role Maptest", ErrPermissionDenied)
|
||||
ErrNegativeID = errors.New("A negative ID was provided")
|
||||
)
|
||||
|
||||
type Service struct {
|
||||
inner *service.Service
|
||||
roblox roblox.Client
|
||||
}
|
||||
|
||||
func NewService(
|
||||
inner *service.Service,
|
||||
roblox roblox.Client,
|
||||
) Service {
|
||||
return Service{
|
||||
inner: inner,
|
||||
roblox: roblox,
|
||||
}
|
||||
}
|
||||
|
||||
// NewError creates *ErrorStatusCode from error returned by handler.
|
||||
//
|
||||
// Used for common default response.
|
||||
func (svc *Service) NewError(ctx context.Context, err error) *api.ErrorStatusCode {
|
||||
status := 500
|
||||
if errors.Is(err, datastore.ErrNotExist) {
|
||||
status = 404
|
||||
}
|
||||
if errors.Is(err, ErrPermissionDenied) {
|
||||
status = 403
|
||||
}
|
||||
if errors.Is(err, ErrUserInfo) {
|
||||
status = 401
|
||||
}
|
||||
return &api.ErrorStatusCode{
|
||||
StatusCode: status,
|
||||
Response: api.Error{
|
||||
Code: int64(status),
|
||||
Message: err.Error(),
|
||||
},
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package service
|
||||
package web_api
|
||||
|
||||
import (
|
||||
"context"
|
||||
1174
pkg/web_api/submissions.go
Normal file
1174
pkg/web_api/submissions.go
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user