Esempio n. 1
0
 /// <summary>
 /// Initiates the RESTar interface
 /// </summary>
 /// <param name="port">The port that RESTar should listen on</param>
 /// <param name="uri">The URI that RESTar should listen on. E.g. '/rest'</param>
 /// <param name="configFilePath">The path to the config file containing API keys and
 /// allowed origins</param>
 /// <param name="prettyPrint">Should JSON output be pretty print formatted as default?
 ///  (can be changed in settings during runtime)</param>
 /// <param name="daysToSaveErrors">The number of days to save errors in the Error resource</param>
 /// <param name="requireApiKey">Should the REST API require an API key?</param>
 /// <param name="allowAllOrigins">Should any origin be allowed to make CORS requests?</param>
 /// <param name="lineEndings">The line endings to use when writing JSON</param>
 /// <param name="entityResourceProviders">External entity resource providers for the RESTar instance</param>
 /// <param name="protocolProviders">External protocol providers for the RESTar instance</param>
 /// <param name="contentTypeProviders">External content type providers for the RESTar instance</param>
 public static void Init
 (
     ushort port             = 8282,
     string uri              = "/rest",
     bool requireApiKey      = false,
     bool allowAllOrigins    = true,
     string configFilePath   = null,
     bool prettyPrint        = true,
     ushort daysToSaveErrors = 30,
     LineEndings lineEndings = LineEndings.Windows,
     IEnumerable <IEntityResourceProvider> entityResourceProviders = null,
     IEnumerable <IProtocolProvider> protocolProviders             = null,
     IEnumerable <IContentTypeProvider> contentTypeProviders       = null
 )
 {
     try
     {
         ProcessUri(ref uri);
         Settings.Init(port, uri, false, prettyPrint, daysToSaveErrors, lineEndings);
         Log.Init();
         DynamitConfig.Init(true, true);
         ResourceFactory.MakeResources(entityResourceProviders?.ToArray());
         ContentTypeController.SetupContentTypeProviders(contentTypeProviders?.ToList());
         ProtocolController.SetupProtocolProviders(protocolProviders?.ToList());
         RequireApiKey   = requireApiKey;
         AllowAllOrigins = allowAllOrigins;
         ConfigFilePath  = configFilePath;
         NetworkController.AddNetworkBindings(new ScNetworkProvider());
         Initialized = true;
         UpdateConfiguration();
         DatabaseIndex.Init();
         DbOutputFormat.Init();
         ResourceFactory.BindControllers();
         ResourceFactory.FinalCheck();
         ProtocolController.OnInit();
         Webhook.Check();
         WebhookLogSettings.Init();
         RegisterStaticIndexes();
         RunCustomMigrationLogic();
     }
     catch
     {
         Initialized     = false;
         RequireApiKey   = default;
         AllowAllOrigins = default;
         ConfigFilePath  = default;
         NetworkController.RemoveNetworkBindings();
         Settings.Clear();
         NewState();
         throw;
     }
 }
Esempio n. 2
0
        internal static MetaConditions Parse(IReadOnlyCollection <IUriCondition> uriMetaConditions, IEntityResource resource)
        {
            if (!uriMetaConditions.Any())
            {
                return(null);
            }
            var renames = uriMetaConditions.Where(c => c.Key.EqualsNoCase("rename"));
            var regular = uriMetaConditions.Where(c => !c.Key.EqualsNoCase("rename"));
            var mc      = new MetaConditions {
                Empty = false
            };
            ICollection <string> dynamicDomain = default;

            void make(IEnumerable <IUriCondition> conds) => conds.ForEach(cond =>
            {
                var(key, op, valueLiteral) = (cond.Key, cond.Operator, cond.ValueLiteral);
                if (op != EQUALS)
                {
                    throw new InvalidSyntax(InvalidMetaConditionOperator,
                                            "Invalid operator for meta-condition. One and only one '=' is allowed");
                }
                if (!Enum.TryParse(key, true, out RESTarMetaCondition metaCondition))
                {
                    throw new InvalidSyntax(InvalidMetaConditionKey,
                                            $"Invalid meta-condition '{key}'. Available meta-conditions: {AllMetaConditions}");
                }

                var expectedType = metaCondition.GetExpectedType();

                switch (valueLiteral)
                {
                case null:
                case "null":
                case "": return;

                case "∞":
                    valueLiteral = int.MaxValue.ToString();
                    break;

                case "-∞":
                    valueLiteral = int.MinValue.ToString();
                    break;
                }

                var(first, length) = (valueLiteral.FirstOrDefault(), valueLiteral.Length);

                switch (first)
                {
                case '\'':
                case '\"':
                    if (length > 1 && valueLiteral[length - 1] == first)
                    {
                        valueLiteral = valueLiteral.Substring(1, length - 2);
                    }
                    break;
                }

                dynamic value;
                try
                {
                    value = Convert.ChangeType(valueLiteral, expectedType) ?? throw new Exception();
                }
                catch
                {
                    throw new InvalidSyntax(InvalidMetaConditionValueType,
                                            $"Invalid data type assigned to meta-condition '{key}'. Expected {GetTypeString(expectedType)}.");
                }
                switch (metaCondition)
                {
                case RESTarMetaCondition.Unsafe:
                    mc.Unsafe = value;
                    break;

                case RESTarMetaCondition.Limit:
                    mc.Limit = (Limit)(int)value;
                    break;

                case RESTarMetaCondition.Offset:
                    mc.Offset = (Offset)(int)value;
                    break;

                case RESTarMetaCondition.Order_asc:
                    mc.OrderBy = new OrderByAscending(resource, (string)value, dynamicDomain);
                    break;

                case RESTarMetaCondition.Order_desc:
                    mc.OrderBy = new OrderByDescending(resource, (string)value, dynamicDomain);
                    break;

                case RESTarMetaCondition.Select:
                    mc.Select = new Select(resource, (string)value, dynamicDomain);
                    break;

                case RESTarMetaCondition.Add:
                    mc.Add = new Add(resource, (string)value, dynamicDomain);
                    break;

                case RESTarMetaCondition.Rename:
                    mc.Rename = new Rename(resource, (string)value, out dynamicDomain);
                    break;

                case RESTarMetaCondition.Distinct:
                    if ((bool)value)
                    {
                        mc.Distinct = new Distinct();
                    }
                    break;

                case RESTarMetaCondition.Search:
                    mc.Search = new Search((string)value);
                    break;

                case RESTarMetaCondition.Search_regex:
                    mc.Search = new RegexSearch((string)value);
                    break;

                case RESTarMetaCondition.Safepost:
                    mc.SafePost = value;
                    break;

                case RESTarMetaCondition.Format:
                    var formatName = (string)value;
                    var format     = DbOutputFormat.GetByName(formatName) ?? throw new InvalidSyntax(UnknownFormatter,
                                                                                                     $"Could not find any output format by '{formatName}'. See RESTar.Admin.OutputFormat " +
                                                                                                     "for available output formats");
                    mc.Formatter = format.Format;
                    break;

                default: throw new ArgumentOutOfRangeException();
                }
            });

            make(renames);
            make(regular);

            mc.Processors            = new IProcessor[] { mc.Add, mc.Rename, mc.Select }.Where(p => p != null).ToArray();
            mc.HasProcessors         = mc.Processors.Any();
            mc.CanUseExternalCounter = mc.Search == null && mc.Distinct == null && mc.Limit.Number == -1 && mc.Offset.Number == 0;

            if (mc.OrderBy != null)
            {
                if (mc.Rename?.Any(p => p.Key.Key.EqualsNoCase(mc.OrderBy.Key)) == true &&
                    !mc.Rename.Any(p => p.Value.EqualsNoCase(mc.OrderBy.Key)))
                {
                    throw new InvalidSyntax(InvalidMetaConditionSyntax,
                                            $"The {(mc.OrderBy is OrderByAscending ? RESTarMetaCondition.Order_asc : RESTarMetaCondition.Order_desc)} " +
                                            "meta-condition cannot refer to a property x that is to be renamed " +
                                            "unless some other property is renamed to x");
                }
            }

            if (mc.Select != null && mc.Rename != null)
            {
                if (mc.Select.Any(pc => mc.Rename.Any(p => p.Key.Key.EqualsNoCase(pc.Key)) &&
                                  !mc.Rename.Any(p => p.Value.EqualsNoCase(pc.Key))))
                {
                    throw new InvalidSyntax(InvalidMetaConditionSyntax,
                                            "A 'Select' meta-condition cannot refer to a property x that is " +
                                            "to be renamed unless some other property is renamed to x. Use the " +
                                            "new property name instead.");
                }
            }

            return(mc);
        }