Przeglądaj źródła

Fix to form concurrent modification exception; fix to some filter stuff

Kenric Nugteren 2 lat temu
rodzic
commit
4669e8926b

+ 1 - 0
InABox.Client.Remote.Json/JsonClient.cs

@@ -82,6 +82,7 @@ namespace InABox.Clients
 
             //sw.Restart();
             var json = Serialization.Serialize(request);
+            var deserialized = Serialization.Deserialize<TRequest>(json);
             //Log("  * {0}{1}() Serializing data took {2}ms ({3} bytes)", Action, typeof(TEntity).Name, sw.ElapsedMilliseconds, json.Length);
             //sw.Restart();
 

+ 6 - 1
InABox.Core/DigitalForms/Forms/DigitalForm.cs

@@ -100,14 +100,19 @@ namespace InABox.Core
                 var blobs = Serialization.Deserialize<Dictionary<string, object?>>(blobData);
                 if(blobs != null)
                 {
+                    var updates = new List<Tuple<string, object?>>();
                     foreach (var (key, value) in values)
                     {
                         if ((value is string str && blobs.TryGetValue(str, out var blob))
                             || (value is Guid guid && blobs.TryGetValue(guid.ToString(), out blob)))
                         {
-                            values[key] = blob;
+                            updates.Add(new Tuple<string, object?>(key, blob));
                         }
                     }
+                    foreach(var (key, value) in updates)
+                    {
+                        values[key] = value;
+                    }
                 }
             }
             return values;

+ 44 - 27
InABox.Core/Filter.cs

@@ -913,8 +913,11 @@ namespace InABox.Core
                     catch
                     {
                         var val = Value;
-                        if (!propType.Equals(valType))
-                            val = Convert.ChangeType(val, propType);
+
+                        if (!propType.Equals(valType) && !(val is FilterConstant))
+                        {
+                            val = CoreUtils.ChangeType(val, propType);
+                        }
                         constant = Expression.Constant(val, propType);
                     }
             }
@@ -1211,28 +1214,36 @@ namespace InABox.Core
             writer.WritePropertyName("Operator");
             writer.WriteValue(op);
 
-            writer.WritePropertyName("Value");
-            var valType = val == null ? property.Type : val.GetType();
-            if (valType.IsArray)
+            if (val is FilterConstant)
             {
-                writer.WriteStartArray();
-                var arr = (val as IEnumerable)!;
-                foreach (var v in arr)
-                    writer.WriteValue(v);
-                writer.WriteEndArray();
+                writer.WritePropertyName("FilterConstant");
+                writer.WriteValue(val);
             }
-            else if (valType.IsConstructedGenericType && valType.GetGenericTypeDefinition() == typeof(SubQuery<>))
+            else
             {
-                var serialized = Serialization.Serialize(val);
-                var wrapper = new SubQuerySerializationWrapper(valType.GenericTypeArguments[0].EntityName(), serialized);
+                writer.WritePropertyName("Value");
+                var valType = val == null ? property.Type : val.GetType();
+                if (valType.IsArray)
+                {
+                    writer.WriteStartArray();
+                    var arr = (val as IEnumerable)!;
+                    foreach (var v in arr)
+                        writer.WriteValue(v);
+                    writer.WriteEndArray();
+                }
+                else if (valType.IsConstructedGenericType && valType.GetGenericTypeDefinition() == typeof(SubQuery<>))
+                {
+                    var serialized = Serialization.Serialize(val);
+                    var wrapper = new SubQuerySerializationWrapper(valType.GenericTypeArguments[0].EntityName(), serialized);
 
-                var str = Serialization.Serialize(wrapper);
+                    var str = Serialization.Serialize(wrapper);
 
-                writer.WriteValue(str);
-            }
-            else
-            {
-                writer.WriteValue(val);
+                    writer.WriteValue(str);
+                }
+                else
+                {
+                    writer.WriteValue(val);
+                }
             }
 
             if (ands != null && ands.Count > 0)
@@ -1307,17 +1318,23 @@ namespace InABox.Core
             var prop = data["Expression"].ToString();
             var exp = CoreUtils.StringToExpression(prop);
             var op = (Operator)int.Parse(data["Operator"].ToString());
-            var val = data["Value"];
-            if (op == Operator.InQuery)
-            {
-                var wrapper = Serialization.Deserialize<SubQuerySerializationWrapper>((string)val);
-                val = Activator.CreateInstance(typeof(SubQuery<>).MakeGenericType(CoreUtils.GetEntity(wrapper.Type)), null, null);
-                Serialization.DeserializeInto(wrapper.SerializedSubquery, val);
-            }
 
             result.Expression = exp;
             result.Operator = op;
-            result.Value = CoreUtils.ChangeType(val, exp.Type);
+            if(data.TryGetValue("Value", out var val))
+            {
+                if (op == Operator.InQuery)
+                {
+                    var wrapper = Serialization.Deserialize<SubQuerySerializationWrapper>((string)val);
+                    val = Activator.CreateInstance(typeof(SubQuery<>).MakeGenericType(CoreUtils.GetEntity(wrapper.Type)), null, null);
+                    Serialization.DeserializeInto(wrapper.SerializedSubquery, val);
+                }
+                result.Value = CoreUtils.ChangeType(val, exp.Type);
+            }
+            else if(data.TryGetValue("FilterConstant", out var filterConstant))
+            {
+                result.Value = CoreUtils.ChangeType<FilterConstant>(filterConstant);
+            }
 
             if (data.ContainsKey("Ors"))
             {

+ 14 - 20
InABox.Server/Rest/RestListener.cs

@@ -166,7 +166,7 @@ namespace InABox.API
         /// <returns></returns>
         private IResponseBuilder GetNotify(IRequest request)
         {
-            var requestObj = Serialization.Deserialize<NotifyRequest>(request.Content);
+            var requestObj = Deserialize<NotifyRequest>(request.Content, true);
             if (!CredentialsCache.SessionExists(requestObj.Credentials.Session))
             {
                 return request.Respond().Status(ResponseStatus.NotFound);
@@ -186,7 +186,7 @@ namespace InABox.API
 
         private IResponseBuilder Validate(IRequest request)
         {
-            var requestObj = Serialization.Deserialize<ValidateRequest>(request.Content);
+            var requestObj = Deserialize<ValidateRequest>(request.Content, true);
             var response = RestService.Validate(requestObj);
 
             var serialized = Serialization.Serialize(response);
@@ -197,7 +197,7 @@ namespace InABox.API
 
         private IResponseBuilder Check2FA(IRequest request)
         {
-            var requestObj = Serialization.Deserialize<Check2FARequest>(request.Content);
+            var requestObj = Deserialize<Check2FARequest>(request.Content, true);
             var response = RestService.Check2FA(requestObj);
 
             var serialized = Serialization.Serialize(response);
@@ -225,42 +225,37 @@ namespace InABox.API
 
         private static QueryResponse<T> List<T>(IRequest request) where T : Entity, new()
         {
-            var requestObject = Deserialize<QueryRequest<T>>(request.Content);
+            var requestObject = Deserialize<QueryRequest<T>>(request.Content, true);
             return RestService<T>.List(requestObject);
         }
         private static SaveResponse<T> Save<T>(IRequest request) where T : Entity, new()
         {
-            var requestObject = Deserialize<SaveRequest<T>>(request.Content);
+            var requestObject = Deserialize<SaveRequest<T>>(request.Content, true);
             return RestService<T>.Save(requestObject);
         }
         private static DeleteResponse<T> Delete<T>(IRequest request) where T : Entity, new()
         {
-            var requestObject = Deserialize<DeleteRequest<T>>(request.Content);
+            var requestObject = Deserialize<DeleteRequest<T>>(request.Content, true);
             return RestService<T>.Delete(requestObject);
         }
         private static MultiSaveResponse<T> MultiSave<T>(IRequest request) where T : Entity, new()
         {
-            var requestObject = Deserialize<MultiSaveRequest<T>>(request.Content);
+            var requestObject = Deserialize<MultiSaveRequest<T>>(request.Content, true);
             return RestService<T>.MultiSave(requestObject);
         }
         private static MultiDeleteResponse<T> MultiDelete<T>(IRequest request) where T : Entity, new()
         {
-            var requestObject = Deserialize<MultiDeleteRequest<T>>(request.Content);
+            var requestObject = Deserialize<MultiDeleteRequest<T>>(request.Content, true);
             return RestService<T>.MultiDelete(requestObject);
         }
 
-        private static T Deserialize<T>(Stream stream)
+        private static T Deserialize<T>(Stream? stream, bool strict = false)
         {
+            if (stream is null)
+                throw new Exception("Stream is null");
             var str = new StreamReader(stream).ReadToEnd();
-            try
-            {
-                return Serialization.Deserialize<T>(str);
-            }
-            catch (Exception e)
-            {
-                Logger.Send(LogType.Information, "", $"Error while deserializing MultiQueryRequest: {e.Message}\nJSON: {str}");
-                throw new Exception("Deserialization Error");
-            }
+            return Serialization.Deserialize<T>(str, strict)
+                ?? throw new Exception("Deserialization failed");
         }
 
         /// <summary>
@@ -271,10 +266,9 @@ namespace InABox.API
         private ValueTask<IResponse?> HandleDatabaseRequest(IRequest request)
         {
             var endpoint = request.Target.Current.Value;
-            var entityIndex = 0;
             if (endpoint.StartsWith("QueryMultiple"))
             {
-                var requestObject = Deserialize<MultiQueryRequest>(request.Content);
+                var requestObject = Deserialize<MultiQueryRequest>(request.Content, true);
 
                 var result = RestService.QueryMultiple(requestObject, false);
                 var serialized = Serialization.Serialize(result);