/// <inheritdoc />
        public Task <TStorableItem> CreateAsync(TStorableItem item)
        {
            InternalContract.RequireNotNull(item, nameof(item));
            InternalContract.RequireValidated(item, nameof(item));

            TId id = default(TId);

            if (typeof(TId) == typeof(Guid))
            {
                // ReSharper disable once SuspiciousTypeConversion.Global
                id = (dynamic)Guid.NewGuid();
            }
            else if (typeof(TId) == typeof(string))
            {
                // ReSharper disable once SuspiciousTypeConversion.Global
                id = (dynamic)Guid.NewGuid().ToString();
            }
            else if (typeof(TId) == typeof(int))
            {
                lock (LockObject)
                {
                    // ReSharper disable once SuspiciousTypeConversion.Global
                    id = (dynamic)_nextInteger++;
                }
            }
            else
            {
                FulcrumAssert.Fail($"{Namespace}: 5CBE07D8-4C31-43E7-A41C-1DF0B173ABF9", $"MemoryStorage can handle Guid, string and int as type for Id, but it can't handle {typeof(TId)}.");
            }
            return(CreateAsync(id, item));
        }
        /// <summary>
        /// This method will be called indirectly from the program's Main method to configure the services
        /// </summary>
        /// <remarks>
        /// Don't override this method unless you really know what you are doing.
        /// First see if the following methods could be good enough for your needs:
        /// Always override <see cref="GetSynchronousFastLogger"/> to establish your preferred way of logging.
        /// Always override <see cref="DependencyInjectServices(IServiceCollection)"/> to inject your own services.
        /// Override <see cref="ConfigureServicesInitialUrgentPart"/> if you have things that needs to be initialized early.
        /// Override <see cref="ConfigureServicesSwagger"/> if you want to change how swagger is set up.
        /// </remarks>
        public virtual void ConfigureServices(IServiceCollection services)
        {
            try
            {
                FulcrumApplication.Validate();
                ConfigureServicesInitialUrgentPart(services);
                FulcrumApplication.ValidateButNotInProduction();
                InternalContract.RequireValidated(this, GetType().FullName);
                ConfigureServicesSwagger(services);
                DependencyInjectServices(services);
                using (var serviceScope = services.BuildServiceProvider().CreateScope())
                {
                    ValueTranslatorFilter valueTranslatorFilter = null;
                    var serviceProvider = serviceScope.ServiceProvider;
                    DependencyInjectServicesAdvanced(services, serviceProvider);
                    if (IsBusinessApi)
                    {
                        var translatorService = serviceProvider.GetService <ITranslatorService>();
                        if (translatorService == null)
                        {
                            Log.LogWarning($"Could not resolve {nameof(ITranslatorService)}");
                        }
                        else
                        {
                            ValueTranslatorHttpSender.TranslatorService = translatorService;
                            valueTranslatorFilter = new ValueTranslatorFilter(
                                translatorService,
                                () => FulcrumApplication.Context?.ClientPrincipal?.Identity?.Name);
                        }
                    }
                    var mvc = services.AddMvc(opts =>
                    {
                        if (IsBusinessApi && valueTranslatorFilter != null)
                        {
                            opts.Filters.Add(valueTranslatorFilter);
                        }
                        if (!FulcrumApplication.IsInDevelopment)
                        {
                            return;
                        }
                        Log.LogWarning($"Anonymous service usage is allowed, due to development mode.");
                        opts.Filters.Add(new AllowAnonymousFilter());
                    });
                    mvc
                    .SetCompatibilityVersion(CompatibilityVersion)
                    .ConfigureApplicationPartManager(apm =>
                                                     apm.FeatureProviders.Add(new RemoveRedundantControllers(_controllersToKeep)));
                    AddControllersToMvc(services, mvc);
                }

                Log.LogInformation($"{nameof(StartupBase)}.{nameof(ConfigureServices)} succeeded.");
            }
            catch (Exception e)
            {
                Log.LogCritical(
                    $"{nameof(StartupBase)}.{nameof(ConfigureServices)} failed. The application {FulcrumApplication.Setup?.Name} needs to be restarted.: {e.Message}",
                    e);
                throw;
            }
        }
        private async Task <PersonConsent> MapFromServerAsync(PersonConsentTable source,
                                                              CancellationToken token = default(CancellationToken))
        {
            InternalContract.RequireNotNull(source, nameof(source));
            InternalContract.RequireValidated(source, nameof(source));
            var serverConsentTask = _storage.Consent.ReadAsync(source.ConsentId, token);
            var serverPersonTask  = _storage.Person.ReadAsync(source.PersonId, token);
            var serverConsent     = await serverConsentTask;
            var serverPerson      = await serverPersonTask;

            if (serverConsent == null)
            {
                throw new FulcrumNotFoundException($"Could not find consent with id {source.ConsentId}");
            }
            if (serverPerson == null)
            {
                throw new FulcrumNotFoundException($"Could not find person with id {source.PersonId}");
            }
            var target = new PersonConsent
            {
                Id              = MapperHelper.MapToType <string, Guid>(source.Id),
                ConsentId       = MapperHelper.MapToType <string, Guid>(source.ConsentId),
                PersonName      = serverPerson.Name,
                ConsentName     = serverConsent.Name,
                Etag            = source.Etag,
                PersonId        = MapperHelper.MapToType <string, Guid>(source.PersonId),
                HasGivenConsent = source.HasGivenConsent
            };

            FulcrumAssert.IsValidated(target);
            return(target);
        }
예제 #4
0
        /// <summary>
        /// Initialize <see cref="Setup"/>.
        /// </summary>
        /// <param name="name">The name of the application.</param>
        /// <param name="tenant">The tenant that the application itself runs in.</param>
        /// <param name="level">The run time level for the application itself.</param>
        /// <remarks>Will setup all mandatory fields for <see cref="Setup"/>, but you might want to override those values when this method returns."/></remarks>
        public static void Initialize(string name, Tenant tenant, RunTimeLevelEnum level)
        {
            InternalContract.RequireNotNullOrWhiteSpace(name, nameof(name));
            InternalContract.RequireValidated(tenant, nameof(tenant));
            InternalContract.Require(level != RunTimeLevelEnum.None, $"{nameof(level)} ({level}) must be set to something else than {RunTimeLevelEnum.None}");

            Setup.Name         = name;
            Setup.Tenant       = tenant;
            Setup.RunTimeLevel = level;

            Setup.ThreadHandler         = ThreadHelper.RecommendedForRuntime;
            Setup.SynchronousFastLogger = LogHelper.RecommendedSyncLoggerForRuntime;
            switch (level)
            {
            case RunTimeLevelEnum.None:
            case RunTimeLevelEnum.Development:
                Setup.LogSeverityLevelThreshold = LogSeverityLevel.Verbose;
                break;

            case RunTimeLevelEnum.Test:
                Setup.LogSeverityLevelThreshold = LogSeverityLevel.Information;
                break;

            case RunTimeLevelEnum.ProductionSimulation:
            case RunTimeLevelEnum.Production:
                Setup.LogSeverityLevelThreshold = LogSeverityLevel.Warning;
                break;

            default:
                Setup.LogSeverityLevelThreshold = LogSeverityLevel.Verbose;
                InternalContract.Fail($"Parameter {nameof(level)} had an unexpected value ({level})");
                break;
            }
        }
예제 #5
0
        /// <summary>
        /// This middleware is a collection of all the middleware features that are provided by Nexus Link. Use <paramref name="options"/>
        /// to specify exactly how they should behave.
        /// </summary>
        /// <param name="next">The inner handler</param>
        /// <param name="options">Options that controls which features to use and how they should behave.</param>
        public NexusLinkMiddleware(RequestDelegate next, NexusLinkMiddlewareOptions options)
        {
            InternalContract.RequireValidated(options, nameof(options));

            Next    = next;
            Options = options;
        }
 /// <summary>
 /// Constructor
 /// </summary>
 public CircuitBreaker(CircuitBreakerOptions options)
 {
     InternalContract.RequireNotNull(options, nameof(options));
     InternalContract.RequireValidated(options, nameof(options));
     _options = options;
     _options.CoolDownStrategy.Reset();
     _commonCancellationTokenSource = new CancellationTokenSource();
 }
        public Task <IStorableProduct> CreateAsync(IStorableProduct storableProduct)
        {
            InternalContract.RequireNotNull(storableProduct, nameof(storableProduct));
            InternalContract.RequireValidated(storableProduct, nameof(storableProduct));

            ThrowConflictIfProductWithIdExists(storableProduct.Id);
            return(Task.FromResult(storableProduct));
        }
 /// <summary>
 /// Put the item in the cache.
 /// </summary>
 private async Task CacheSetAsync(PageEnvelope <TModel> pageEnvelope, string keyPrefix, CancellationToken token)
 {
     InternalContract.RequireNotDefaultValue(pageEnvelope, nameof(pageEnvelope));
     InternalContract.RequireValidated(pageEnvelope, nameof(pageEnvelope));
     var serializedCacheEnvelope = ToSerializedCacheEnvelope(pageEnvelope);
     var key = GetCacheKeyForPage(keyPrefix, pageEnvelope.PageInfo.Offset, pageEnvelope.PageInfo.Limit);
     await Cache.SetAsync(key, serializedCacheEnvelope, CacheOptions, token);
 }
예제 #9
0
        /// <summary>
        /// This middleware is a collection of all the middleware features that are provided by Nexus Link. Use <paramref name="options"/>
        /// to specify exactly how they should behave.
        /// </summary>
        /// <param name="next">The inner handler</param>
        /// <param name="options">Options that controls which features to use and how they should behave.</param>
        public NexusLinkMiddleware(RequestDelegate next, IOptions <NexusLinkMiddlewareOptions> options)
        {
            InternalContract.RequireNotNull(options.Value, nameof(options));
            InternalContract.RequireValidated(options.Value, nameof(options));

            Next    = next;
            Options = options.Value;
        }
예제 #10
0
        public Task <IProduct> ReadAsync(IConceptValue id)
        {
            InternalContract.RequireNotNull(id, nameof(id));
            InternalContract.RequireValidated(id, nameof(id));
            var dalProduct = await _productPersistance.ReadAsync(ToDal(id)).ConfigureAwait(false);

            return(FromDal(dalProduct));
        }
예제 #11
0
        /// <summary>
        /// Constructor
        /// </summary>
        /// <param name="options"></param>
        /// <param name="tableMetadata"></param>
        protected TableBase(IDatabaseOptions options, ISqlTableMetadata tableMetadata)
        {
            InternalContract.RequireNotNull(options, nameof(options));
            InternalContract.RequireValidated(tableMetadata, nameof(tableMetadata));

            Database      = new Database(options);
            TableMetadata = tableMetadata;
        }
        private string ToUrlParameter(Address address)
        {
            InternalContract.RequireNotNull(address, nameof(address));
            InternalContract.RequireValidated(address, nameof(address));
            var oneLine = $"{address.Row1}, {address.Row2}, {address.PostCode} {address.PostTown}, {address.Country}";

            return(Uri.EscapeDataString(oneLine));
        }
        public async Task <GeocodingResponse> GeocodeAsync(Address address)
        {
            InternalContract.RequireNotNull(address, nameof(address));
            InternalContract.RequireValidated(address, nameof(address));
            var relativeUrl = $"/json?address={ToUrlParameter(address)}";

            return(await _restClient.GetAsync <GeocodingResponse>(relativeUrl));
        }
예제 #14
0
 /// <summary>
 /// Constructor
 /// </summary>
 public CircuitBreakerWithThrottling(CircuitBreakerWithThrottlingOptions options)
     : base(options)
 {
     InternalContract.RequireNotNull(options, nameof(options));
     InternalContract.RequireValidated(options, nameof(options));
     _options = options;
     _options.ThrottlingCoolDownStrategy.Reset();
 }
        public Task <IStorableProduct> UpdateAsync(IStorableProduct storableProduct)
        {
            InternalContract.RequireNotNull(storableProduct, nameof(storableProduct));
            InternalContract.RequireValidated(storableProduct, nameof(storableProduct));

            GetProductOrThrowNotFound(storableProduct.Id);

            return(Task.FromResult(storableProduct));
        }
예제 #16
0
        /// <inheritdoc />
        public async Task <string> CreateAsync(Applicant item, CancellationToken token = new CancellationToken())
        {
            InternalContract.RequireNotNull(item, nameof(item));
            InternalContract.RequireValidated(item, nameof(item));
            var lead = new Lead().From(item);
            var id   = await _crmSystem.LeadFunctionality.CreateAsync(lead);

            return(id.ToIdString());
        }
예제 #17
0
        public static IEnumerable <TModel> FilterAndSort <TModel>(IEnumerable <TModel> items, SearchDetails <TModel> details)
        {
            InternalContract.RequireNotNull(details, nameof(details));
            InternalContract.RequireValidated(details, nameof(details));
            var filtered = items.Where(item => IsMatch(item, details));
            var sorted   = Sort(filtered, details);

            return(sorted);
        }
        public void IsValidatedOk()
        {
            var validatable = new Validatable
            {
                Name = "Jim"
            };

            InternalContract.RequireValidated(validatable, nameof(validatable));
        }
예제 #19
0
        public async Task <IProduct> UpdateAsync(IProduct product)
        {
            InternalContract.RequireNotNull(product, nameof(product));
            InternalContract.RequireValidated(product, nameof(product));

            var dalProduct = await _productPersistance.UpdateAsync(ToDal(product)).ConfigureAwait(false);

            return(FromDal(dalProduct));
        }
        /// <inheritdoc />
        public async Task <TModel> CreateChildAndReturnAsync(TId parentId, TModelCreate item, CancellationToken cancellationToken = default)
        {
            InternalContract.RequireNotNull(item, nameof(item));
            InternalContract.RequireValidated(item, nameof(item));
            var createdItem = await _service.CreateAndReturnAsync(item, cancellationToken);

            FulcrumAssert.IsNotNull(createdItem, CodeLocation.AsString());
            FulcrumAssert.IsValidated(createdItem, CodeLocation.AsString());
            return(createdItem);
        }
        /// <inheritdoc />
        public Task CreateWithSpecifiedIdAsync(string masterId, string slaveId, PersonConsentCreate item,
                                               CancellationToken token = new CancellationToken())
        {
            InternalContract.RequireNotNull(item, nameof(item));
            InternalContract.RequireValidated(item, nameof(item));
            InternalContract.Require(masterId == item.PersonId, $"{nameof(masterId)} ({masterId} must have the same value as {nameof(item)}.{nameof(item.PersonId)} ({item.PersonId}).");
            InternalContract.Require(slaveId == item.ConsentId, $"{nameof(slaveId)} ({slaveId} must have the same value as {nameof(item)}.{nameof(item.ConsentId)} ({item.ConsentId}).");
            var serverItem = MapToServer(item);

            return(_storage.PersonConsent.CreateAsync(serverItem, token));
        }
        /// <inheritdoc />
        public ConsentTable MapToServer(Consent source)
        {
            InternalContract.RequireNotNull(source, nameof(source));
            InternalContract.RequireValidated(source, nameof(source));
            var id     = MapperHelper.MapToType <Guid, string>(source.Id);
            var target = MapToServer(source as ConsentCreate);

            target.Id   = id;
            target.Etag = source.Etag;
            FulcrumAssert.IsValidated(target);
            return(target);
        }
        /// <inheritdoc />
        public ConsentTable MapToServer(ConsentCreate source)
        {
            InternalContract.RequireNotNull(source, nameof(source));
            InternalContract.RequireValidated(source, nameof(source));
            var target = new ConsentTable()
            {
                Name = source.Name
            };

            FulcrumAssert.IsValidated(target);
            return(target);
        }
예제 #24
0
        private async Task <PersonTable> MapToServerAsync(PersonCreate source, CancellationToken token = default(CancellationToken))
        {
            InternalContract.RequireNotNull(source, nameof(source));
            InternalContract.RequireValidated(source, nameof(source));
            var target = new PersonTable
            {
                Name = source.Name
            };

            FulcrumAssert.IsValidated(target);
            return(await Task.FromResult(target));
        }
예제 #25
0
        /// <inheritdoc />
        public async Task <TModel> FindUniqueAsync(SearchDetails <TModel> details, CancellationToken cancellationToken = default)
        {
            InternalContract.RequireNotNull(details, nameof(details));
            InternalContract.RequireValidated(details, nameof(details));
            var page = await _service.SearchAsync(details, 0, 2, cancellationToken);

            if (page.PageInfo.Returned > 1)
            {
                throw new FulcrumBusinessRuleException($"Expected to find one unique value, but found multiple items when searching for model {typeof(TModel).Name} with search details {nameof(details)}:\r{details}");
            }

            return(page.Data.FirstOrDefault());
        }
예제 #26
0
        /// <inheritdoc />
        public async Task <TModel> FindUniqueChildAsync(TId parentId, SearchDetails <TModel> details, CancellationToken cancellationToken = default)
        {
            InternalContract.RequireNotNull(details, nameof(details));
            InternalContract.RequireValidated(details, nameof(details));
            var page = await _service.SearchChildrenAsync(parentId, details, 0, 2, cancellationToken);

            if (page.PageInfo.Returned > 1)
            {
                throw new FulcrumContractException($"Expected to find unique value, but found multiple items for search for model {typeof(TModel).Name} with {nameof(details)}:\r{details}");
            }

            return(page.Data.FirstOrDefault());
        }
        private PersonConsentTable MapToServer(PersonConsentCreate source)
        {
            InternalContract.RequireNotNull(source, nameof(source));
            InternalContract.RequireValidated(source, nameof(source));
            var target = new PersonConsentTable
            {
                HasGivenConsent = source.HasGivenConsent,
                PersonId        = MapperHelper.MapToType <Guid, string>(source.PersonId),
                ConsentId       = MapperHelper.MapToType <Guid, string>(source.ConsentId),
            };

            FulcrumAssert.IsValidated(target);
            return(target);
        }
        /// <inheritdoc />
        public Consent MapFromServer(ConsentTable source)
        {
            InternalContract.RequireNotNull(source, nameof(source));
            InternalContract.RequireValidated(source, nameof(source));
            var target = new Consent
            {
                Id   = MapperHelper.MapToType <string, Guid>(source.Id),
                Name = source.Name,
                Etag = source.Etag
            };

            FulcrumAssert.IsValidated(target);
            return(target);
        }
예제 #29
0
        private async Task <PersonTable> MapToServerAsync(Person source, CancellationToken token = default(CancellationToken))
        {
            InternalContract.RequireNotNull(source, nameof(source));
            InternalContract.RequireValidated(source, nameof(source));
            var target = new PersonTable
            {
                Id   = MapperHelper.MapToType <Guid, string>(source.Id),
                Name = source.Name,
                Etag = source.Etag
            };

            FulcrumAssert.IsValidated(target);
            return(await Task.FromResult(target));
        }
예제 #30
0
        private Address CreateAndMapFromServer(AddressTable source)
        {
            InternalContract.RequireNotNull(source, nameof(source));
            InternalContract.RequireValidated(source, nameof(source));
            var target = new Address
            {
                Type   = MapperHelper.MapToType <string, int>(source.Type),
                Street = source.Street,
                City   = source.City
            };

            FulcrumAssert.IsValidated(target);
            return(target);
        }