scripts: name property
All checks were successful
continuous-integration/drone/push Build is passing

This commit is contained in:
Quaternions 2024-12-14 12:31:31 -08:00
parent f4abc30c21
commit db52b1dcd4
12 changed files with 213 additions and 34 deletions

View File

@ -613,6 +613,7 @@ components:
Script:
required:
- ID
- Name
- Hash
- Source
- SubmissionID
@ -621,6 +622,10 @@ components:
ID:
type: integer
format: int64
Name:
type: string
minLength: 64
maxLength: 64
Hash:
type: string
minLength: 16
@ -633,10 +638,15 @@ components:
format: int64
ScriptCreate:
required:
- Name
- Source
# - SubmissionID
type: object
properties:
Name:
type: string
minLength: 64
maxLength: 64
Source:
type: string
maxLength: 1048576
@ -651,6 +661,10 @@ components:
ID:
type: integer
format: int64
Name:
type: string
minLength: 64
maxLength: 64
Source:
type: string
maxLength: 1048576

View File

@ -740,6 +740,10 @@ func (s *Script) encodeFields(e *jx.Encoder) {
e.FieldStart("ID")
e.Int64(s.ID)
}
{
e.FieldStart("Name")
e.Str(s.Name)
}
{
e.FieldStart("Hash")
e.Str(s.Hash)
@ -754,11 +758,12 @@ func (s *Script) encodeFields(e *jx.Encoder) {
}
}
var jsonFieldsNameOfScript = [4]string{
var jsonFieldsNameOfScript = [5]string{
0: "ID",
1: "Hash",
2: "Source",
3: "SubmissionID",
1: "Name",
2: "Hash",
3: "Source",
4: "SubmissionID",
}
// Decode decodes Script from json.
@ -782,8 +787,20 @@ func (s *Script) Decode(d *jx.Decoder) error {
}(); err != nil {
return errors.Wrap(err, "decode field \"ID\"")
}
case "Hash":
case "Name":
requiredBitSet[0] |= 1 << 1
if err := func() error {
v, err := d.Str()
s.Name = string(v)
if err != nil {
return err
}
return nil
}(); err != nil {
return errors.Wrap(err, "decode field \"Name\"")
}
case "Hash":
requiredBitSet[0] |= 1 << 2
if err := func() error {
v, err := d.Str()
s.Hash = string(v)
@ -795,7 +812,7 @@ func (s *Script) Decode(d *jx.Decoder) error {
return errors.Wrap(err, "decode field \"Hash\"")
}
case "Source":
requiredBitSet[0] |= 1 << 2
requiredBitSet[0] |= 1 << 3
if err := func() error {
v, err := d.Str()
s.Source = string(v)
@ -807,7 +824,7 @@ func (s *Script) Decode(d *jx.Decoder) error {
return errors.Wrap(err, "decode field \"Source\"")
}
case "SubmissionID":
requiredBitSet[0] |= 1 << 3
requiredBitSet[0] |= 1 << 4
if err := func() error {
v, err := d.Int64()
s.SubmissionID = int64(v)
@ -828,7 +845,7 @@ func (s *Script) Decode(d *jx.Decoder) error {
// Validate required fields.
var failures []validate.FieldError
for i, mask := range [1]uint8{
0b00001111,
0b00011111,
} {
if result := (requiredBitSet[i] & mask) ^ mask; result != 0 {
// Mask only required fields and check equality to mask using XOR.
@ -883,6 +900,10 @@ func (s *ScriptCreate) Encode(e *jx.Encoder) {
// encodeFields encodes fields.
func (s *ScriptCreate) encodeFields(e *jx.Encoder) {
{
e.FieldStart("Name")
e.Str(s.Name)
}
{
e.FieldStart("Source")
e.Str(s.Source)
@ -895,9 +916,10 @@ func (s *ScriptCreate) encodeFields(e *jx.Encoder) {
}
}
var jsonFieldsNameOfScriptCreate = [2]string{
0: "Source",
1: "SubmissionID",
var jsonFieldsNameOfScriptCreate = [3]string{
0: "Name",
1: "Source",
2: "SubmissionID",
}
// Decode decodes ScriptCreate from json.
@ -909,8 +931,20 @@ func (s *ScriptCreate) Decode(d *jx.Decoder) error {
if err := d.ObjBytes(func(d *jx.Decoder, k []byte) error {
switch string(k) {
case "Source":
case "Name":
requiredBitSet[0] |= 1 << 0
if err := func() error {
v, err := d.Str()
s.Name = string(v)
if err != nil {
return err
}
return nil
}(); err != nil {
return errors.Wrap(err, "decode field \"Name\"")
}
case "Source":
requiredBitSet[0] |= 1 << 1
if err := func() error {
v, err := d.Str()
s.Source = string(v)
@ -941,7 +975,7 @@ func (s *ScriptCreate) Decode(d *jx.Decoder) error {
// Validate required fields.
var failures []validate.FieldError
for i, mask := range [1]uint8{
0b00000001,
0b00000011,
} {
if result := (requiredBitSet[i] & mask) ^ mask; result != 0 {
// Mask only required fields and check equality to mask using XOR.
@ -1538,6 +1572,12 @@ func (s *ScriptUpdate) encodeFields(e *jx.Encoder) {
e.FieldStart("ID")
e.Int64(s.ID)
}
{
if s.Name.Set {
e.FieldStart("Name")
s.Name.Encode(e)
}
}
{
if s.Source.Set {
e.FieldStart("Source")
@ -1552,10 +1592,11 @@ func (s *ScriptUpdate) encodeFields(e *jx.Encoder) {
}
}
var jsonFieldsNameOfScriptUpdate = [3]string{
var jsonFieldsNameOfScriptUpdate = [4]string{
0: "ID",
1: "Source",
2: "SubmissionID",
1: "Name",
2: "Source",
3: "SubmissionID",
}
// Decode decodes ScriptUpdate from json.
@ -1579,6 +1620,16 @@ func (s *ScriptUpdate) Decode(d *jx.Decoder) error {
}(); err != nil {
return errors.Wrap(err, "decode field \"ID\"")
}
case "Name":
if err := func() error {
s.Name.Reset()
if err := s.Name.Decode(d); err != nil {
return err
}
return nil
}(); err != nil {
return errors.Wrap(err, "decode field \"Name\"")
}
case "Source":
if err := func() error {
s.Source.Reset()

View File

@ -425,6 +425,7 @@ func (s *Pagination) SetLimit(val int32) {
// Ref: #/components/schemas/Script
type Script struct {
ID int64 `json:"ID"`
Name string `json:"Name"`
Hash string `json:"Hash"`
Source string `json:"Source"`
SubmissionID int64 `json:"SubmissionID"`
@ -435,6 +436,11 @@ func (s *Script) GetID() int64 {
return s.ID
}
// GetName returns the value of Name.
func (s *Script) GetName() string {
return s.Name
}
// GetHash returns the value of Hash.
func (s *Script) GetHash() string {
return s.Hash
@ -455,6 +461,11 @@ func (s *Script) SetID(val int64) {
s.ID = val
}
// SetName sets the value of Name.
func (s *Script) SetName(val string) {
s.Name = val
}
// SetHash sets the value of Hash.
func (s *Script) SetHash(val string) {
s.Hash = val
@ -472,10 +483,16 @@ func (s *Script) SetSubmissionID(val int64) {
// Ref: #/components/schemas/ScriptCreate
type ScriptCreate struct {
Name string `json:"Name"`
Source string `json:"Source"`
SubmissionID OptInt64 `json:"SubmissionID"`
}
// GetName returns the value of Name.
func (s *ScriptCreate) GetName() string {
return s.Name
}
// GetSource returns the value of Source.
func (s *ScriptCreate) GetSource() string {
return s.Source
@ -486,6 +503,11 @@ func (s *ScriptCreate) GetSubmissionID() OptInt64 {
return s.SubmissionID
}
// SetName sets the value of Name.
func (s *ScriptCreate) SetName(val string) {
s.Name = val
}
// SetSource sets the value of Source.
func (s *ScriptCreate) SetSource(val string) {
s.Source = val
@ -680,6 +702,7 @@ func (s *ScriptPolicyUpdate) SetPolicy(val OptInt32) {
// Ref: #/components/schemas/ScriptUpdate
type ScriptUpdate struct {
ID int64 `json:"ID"`
Name OptString `json:"Name"`
Source OptString `json:"Source"`
SubmissionID OptInt64 `json:"SubmissionID"`
}
@ -689,6 +712,11 @@ func (s *ScriptUpdate) GetID() int64 {
return s.ID
}
// GetName returns the value of Name.
func (s *ScriptUpdate) GetName() OptString {
return s.Name
}
// GetSource returns the value of Source.
func (s *ScriptUpdate) GetSource() OptString {
return s.Source
@ -704,6 +732,11 @@ func (s *ScriptUpdate) SetID(val int64) {
s.ID = val
}
// SetName sets the value of Name.
func (s *ScriptUpdate) SetName(val OptString) {
s.Name = val
}
// SetSource sets the value of Source.
func (s *ScriptUpdate) SetSource(val OptString) {
s.Source = val

View File

@ -148,6 +148,25 @@ func (s *Script) Validate() error {
}
var failures []validate.FieldError
if err := func() error {
if err := (validate.String{
MinLength: 64,
MinLengthSet: true,
MaxLength: 64,
MaxLengthSet: true,
Email: false,
Hostname: false,
Regex: nil,
}).Validate(string(s.Name)); err != nil {
return errors.Wrap(err, "string")
}
return nil
}(); err != nil {
failures = append(failures, validate.FieldError{
Name: "Name",
Error: err,
})
}
if err := func() error {
if err := (validate.String{
MinLength: 16,
@ -198,6 +217,25 @@ func (s *ScriptCreate) Validate() error {
}
var failures []validate.FieldError
if err := func() error {
if err := (validate.String{
MinLength: 64,
MinLengthSet: true,
MaxLength: 64,
MaxLengthSet: true,
Email: false,
Hostname: false,
Regex: nil,
}).Validate(string(s.Name)); err != nil {
return errors.Wrap(err, "string")
}
return nil
}(); err != nil {
failures = append(failures, validate.FieldError{
Name: "Name",
Error: err,
})
}
if err := func() error {
if err := (validate.String{
MinLength: 0,
@ -298,6 +336,32 @@ func (s *ScriptUpdate) Validate() error {
}
var failures []validate.FieldError
if err := func() error {
if value, ok := s.Name.Get(); ok {
if err := func() error {
if err := (validate.String{
MinLength: 64,
MinLengthSet: true,
MaxLength: 64,
MaxLengthSet: true,
Email: false,
Hostname: false,
Regex: nil,
}).Validate(string(value)); err != nil {
return errors.Wrap(err, "string")
}
return nil
}(); err != nil {
return err
}
}
return nil
}(); err != nil {
failures = append(failures, validate.FieldError{
Name: "Name",
Error: err,
})
}
if err := func() error {
if value, ok := s.Source.Get(); ok {
if err := func() error {

View File

@ -4,6 +4,7 @@ import "time"
type Script struct {
ID int64 `gorm:"primaryKey"`
Name string
Hash uint64
Source string
SubmissionID int64 // which submission did this script first appear in

View File

@ -27,6 +27,7 @@ func (svc *Service) CreateScript(ctx context.Context, req *api.ScriptCreate) (*a
script, err := svc.DB.Scripts().Create(ctx, model.Script{
ID: 0,
Name: req.Name,
Hash: siphash.Hash(0, 0, []byte(req.Source)),
Source: req.Source,
SubmissionID: req.SubmissionID.Or(0),
@ -78,6 +79,7 @@ func (svc *Service) GetScript(ctx context.Context, params api.GetScriptParams) (
return &api.Script{
ID: script.ID,
Name: script.Name,
Hash: fmt.Sprintf("%x", script.Hash),
Source: script.Source,
SubmissionID: script.SubmissionID,
@ -100,6 +102,9 @@ func (svc *Service) UpdateScript(ctx context.Context, req *api.ScriptUpdate, par
}
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", siphash.Hash(0, 0, []byte(source)))

View File

@ -952,7 +952,7 @@ checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3"
[[package]]
name = "submissions-api"
version = "0.2.3-pre1"
version = "0.2.3-scriptname2"
dependencies = [
"reqwest",
"serde",

View File

@ -1,6 +1,6 @@
[package]
name = "submissions-api"
version = "0.2.3-pre1"
version = "0.2.3-scriptname2"
edition = "2021"
publish = ["strafesnet"]
repository = "https://git.itzana.me/StrafesNET/maps-service"

View File

@ -13,14 +13,16 @@ pub struct GetScriptRequest{
#[derive(serde::Deserialize)]
pub struct ScriptResponse{
pub ID:i64,
pub Name:String,
pub Hash:String,
pub Source:String,
pub SubmissionID:i64,
}
#[allow(nonstandard_style)]
#[derive(serde::Serialize)]
pub struct CreateScriptRequest{
pub Source:String,
pub struct CreateScriptRequest<'a>{
pub Name:&'a str,
pub Source:&'a str,
pub SubmissionID:Option<i64>,
}
#[allow(nonstandard_style)]
@ -39,8 +41,8 @@ pub enum Policy{
Replace=4,
}
pub struct ScriptPolicyHashRequest{
pub hash:String,
pub struct ScriptPolicyHashRequest<'a>{
pub hash:&'a str,
}
#[allow(nonstandard_style)]
#[derive(serde::Deserialize)]
@ -85,7 +87,7 @@ impl Context{
.error_for_status().map_err(Error::Reqwest)?
.json().await.map_err(Error::Reqwest)
}
pub async fn create_script(&self,config:CreateScriptRequest)->Result<ScriptIDResponse,Error>{
pub async fn create_script<'a>(&self,config:CreateScriptRequest<'a>)->Result<ScriptIDResponse,Error>{
let url_raw=format!("{}/scripts",self.0.base_url);
let url=reqwest::Url::parse(url_raw.as_str()).map_err(Error::ParseError)?;
@ -95,7 +97,7 @@ impl Context{
.error_for_status().map_err(Error::Reqwest)?
.json().await.map_err(Error::Reqwest)
}
pub async fn get_script_policy_from_hash(&self,config:ScriptPolicyHashRequest)->Result<ScriptPolicyResponse,Error>{
pub async fn get_script_policy_from_hash<'a>(&self,config:ScriptPolicyHashRequest<'a>)->Result<ScriptPolicyResponse,Error>{
let url_raw=format!("{}/script-policy/hash/{}",self.0.base_url,config.hash);
let url=reqwest::Url::parse(url_raw.as_str()).map_err(Error::ParseError)?;

4
validation/Cargo.lock generated
View File

@ -1804,9 +1804,9 @@ checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3"
[[package]]
name = "submissions-api"
version = "0.2.3-pre1"
version = "0.2.3-scriptname2"
source = "sparse+https://git.itzana.me/api/packages/strafesnet/cargo/"
checksum = "6f5f7afe0137bd065c750f6d8c05892532cd50b9feba588847c10df37e660ad2"
checksum = "b20db7cc0f6bda2b2ff4c413fe7bbdeddc2f6d88cf8ef9c2f8cd998d1f0b9b68"
dependencies = [
"reqwest",
"serde",

View File

@ -4,7 +4,7 @@ version = "0.1.0"
edition = "2021"
[dependencies]
submissions-api = { version = "0.2.3-pre1", features = ["internal","external"], registry = "strafesnet" }
submissions-api = { version = "0.2.3-scriptname2", features = ["internal","external"], registry = "strafesnet" }
async-nats = "0.38.0"
futures = "0.3.31"
rbx_asset = { version = "0.2.5", registry = "strafesnet" }

View File

@ -14,6 +14,11 @@ enum Policy{
Replace(String),
}
struct NamePolicy{
name:String,
policy:Policy,
}
// this is awful
fn interpret_get_script_policy_response(reponse:Result<ScriptPolicyResponse,submissions_api::Error>)->Result<Option<ScriptPolicyResponse>,submissions_api::Error>{
match reponse{
@ -93,18 +98,21 @@ impl Validator{
// collect unique scripts
let script_refs=get_script_refs(&dom);
let mut script_map=std::collections::HashMap::<String,Policy>::new();
let mut script_map=std::collections::HashMap::<String,NamePolicy>::new();
for &script_ref in &script_refs{
if let Some(script)=dom.get_by_ref(script_ref){
if let Some(rbx_dom_weak::types::Variant::String(source))=script.properties.get("Source"){
script_map.insert(source.clone(),Policy::None);
script_map.insert(source.clone(),NamePolicy{
name:script.name.clone(),
policy:Policy::None,
});
}
}
}
// send all script hashes to REST endpoint and retrieve the replacements
futures::stream::iter(script_map.iter_mut().map(Ok))
.try_for_each_concurrent(Some(SCRIPT_CONCURRENCY),|(source,replacement)|async{
.try_for_each_concurrent(Some(SCRIPT_CONCURRENCY),|(source,NamePolicy{policy,name})|async{
// get the hash
let mut hasher=siphasher::sip::SipHasher::new();
std::hash::Hasher::write(&mut hasher,source.as_bytes());
@ -113,13 +121,13 @@ impl Validator{
// fetch the script policy
let script_policy=interpret_get_script_policy_response(
self.api.get_script_policy_from_hash(submissions_api::external::ScriptPolicyHashRequest{
hash:format!("{:x}",hash),
hash:format!("{:x}",hash).as_str(),
}).await
).map_err(ValidateError::ApiGetScriptPolicy)?;
// write the policy to the script_map, fetching the replacement code if necessary
if let Some(script_policy)=script_policy{
*replacement=match script_policy.Policy{
*policy=match script_policy.Policy{
submissions_api::external::Policy::None=>Policy::None,
submissions_api::external::Policy::Allowed=>Policy::Allowed,
submissions_api::external::Policy::Blocked=>Policy::Blocked,
@ -134,7 +142,8 @@ impl Validator{
}else{
// upload the script
let script=self.api.create_script(submissions_api::external::CreateScriptRequest{
Source:source.clone(),
Name:name.as_str(),
Source:source.as_str(),
SubmissionID:Some(validate_info.SubmissionID),
}).await.map_err(ValidateError::ApiCreateScript)?;
@ -155,7 +164,7 @@ impl Validator{
for &script_ref in &script_refs{
if let Some(script)=dom.get_by_ref_mut(script_ref){
if let Some(rbx_dom_weak::types::Variant::String(source))=script.properties.get_mut("Source"){
match script_map.get(source.as_str()){
match script_map.get(source.as_str()).map(|p|&p.policy){
Some(Policy::Blocked)=>return Err(ValidateError::Blocked),
None
|Some(Policy::None)