public void CreateValidationProblemDetails_DefaultValues()
    {
        // Act
        var modelState = new ModelStateDictionary();

        modelState.AddModelError("some-key", "some-value");
        var problemDetails = Factory.CreateValidationProblemDetails(GetHttpContext(), modelState);

        // Assert
        Assert.Equal(400, problemDetails.Status);
        Assert.Equal("One or more validation errors occurred.", problemDetails.Title);
        Assert.Equal("https://tools.ietf.org/html/rfc7231#section-6.5.1", problemDetails.Type);
        Assert.Null(problemDetails.Instance);
        Assert.Null(problemDetails.Detail);
        Assert.Collection(
            problemDetails.Extensions,
            kvp =>
        {
            Assert.Equal("traceId", kvp.Key);
            Assert.Equal("some-trace", kvp.Value);
        });
        Assert.Collection(
            problemDetails.Errors,
            kvp =>
        {
            Assert.Equal("some-key", kvp.Key);
            Assert.Equal(new[] { "some-value" }, kvp.Value);
        });
    }
예제 #2
0
        public Task OnExceptionAsync(ExceptionContext context)
        {
            var errors = new ModelStateDictionary();

            switch (context.Exception)
            {
            case EntityNotFoundException exception:
                errors.AddModelError(exception.ParamName, exception.Message);
                context.Result = new NotFoundObjectResult(_pdFactory.CreateValidationProblemDetails(context.HttpContext, errors, StatusCodes.Status404NotFound))
                {
                    StatusCode = StatusCodes.Status404NotFound
                };
                break;

            case InvalidArgumentException exception:
                errors.AddModelError(exception.ParamName, exception.Message);
                context.Result = new BadRequestObjectResult(_pdFactory.CreateValidationProblemDetails(context.HttpContext, errors, StatusCodes.Status400BadRequest));
                break;

            case EntityExistException exception:
                errors.AddModelError(exception.ParamName, exception.Message);
                context.Result = new UnprocessableEntityObjectResult(_pdFactory.CreateValidationProblemDetails(context.HttpContext, errors, StatusCodes.Status422UnprocessableEntity))
                {
                    StatusCode = StatusCodes.Status422UnprocessableEntity
                };
                break;

            case InvalidUserInputException exception:
                context.Result = new UnprocessableEntityObjectResult(_pdFactory.CreateProblemDetails(context.HttpContext, StatusCodes.Status422UnprocessableEntity, null, null, exception.Message));
                break;

            case InvalidOperationException exception:
                context.Result = new UnprocessableEntityObjectResult(_pdFactory.CreateProblemDetails(context.HttpContext, StatusCodes.Status422UnprocessableEntity, null, null, exception.Message));
                break;

            case InternalException exception:
                goto default;

            default:
                var message = "";
                if (!_env.IsProduction())
                {
                    message += $"{context.Exception.Message}: {context.Exception.InnerException?.Message}";
                }
                context.Result = new ObjectResult(_pdFactory.CreateProblemDetails(context.HttpContext, StatusCodes.Status500InternalServerError, null, null, $"Unhandled exception. {message}"))
                {
                    StatusCode = StatusCodes.Status500InternalServerError
                };
                break;
            }

            return(Task.CompletedTask);
        }
예제 #3
0
        private ProblemDetails HandleException(ExceptionContext context)
        {
            switch (context.Exception)
            {
            case ArgumentException argumentException:
            {
                if (!string.IsNullOrEmpty(argumentException.ParamName))
                {
                    context.ModelState.AddModelError(argumentException.ParamName, argumentException.Message);
                }
                var problemDetails = _problemDetailsFactory.CreateValidationProblemDetails(context.HttpContext,
                                                                                           context.ModelState);
                problemDetails.Detail = argumentException.Message;


                return(problemDetails);
            }

            case InvalidOperationException invalidOperationException:
            {
                var problemDetails = _problemDetailsFactory.CreateProblemDetails(context.HttpContext);
                problemDetails.Detail = invalidOperationException.Message;
                return(problemDetails);
            }

            case ValidationException validationException:
            {
                foreach (var item in validationException.Errors)
                {
                    context.ModelState.AddModelError(item.PropertyName, item.ErrorMessage);
                }

                var problemDetails = _problemDetailsFactory.CreateValidationProblemDetails(context.HttpContext, context.ModelState);
                problemDetails.Detail = "Your request cannot pass our validations. Sorry";
                return(problemDetails);
            }

            case ApiErrorException apiErrorException:
            {
                var detail         = apiErrorException.Body.Error.Message;
                var problemDetails = _problemDetailsFactory.CreateValidationProblemDetails(context.HttpContext, context.ModelState);
                problemDetails.Detail = detail;
                return(problemDetails);
            }

            default:
                return(default);
            }
        }
예제 #4
0
                static IActionResult problemDetailsInvalidModelStateResponse(
                    ProblemDetailsFactory problemDetailsFactory,
                    ActionContext context
                    )
                {
                    var problemDetails =
                        problemDetailsFactory.CreateValidationProblemDetails(
                            context.HttpContext,
                            context.ModelState
                            );
                    ObjectResult result;
                    if (problemDetails.Status == 400)
                    {
                        // For compatibility with 2.x, continue producing BadRequestObjectResult instances if the status code is 400.
                        result = new BadRequestObjectResult(problemDetails);
                    }
                    else
                    {
                        result = new ObjectResult(problemDetails)
                        {
                            StatusCode = problemDetails.Status
                        };
                    }

                    result.ContentTypes.Add("application/problem+json");
                    result.ContentTypes.Add("application/problem+xml");

                    return(result);
                }
        public static void UseCustomInvalidModelUnprocessableEntityResponse(this ApiBehaviorOptions options)
        {
            options.InvalidModelStateResponseFactory = (actionContext) =>
            {
                ProblemDetailsFactory problemFactory = actionContext.HttpContext.RequestServices.GetRequiredService <ProblemDetailsFactory>();
                ProblemDetails        problemDetails = problemFactory.CreateValidationProblemDetails(actionContext.HttpContext, actionContext.ModelState);

                problemDetails.Instance = actionContext.HttpContext.Request.Path;
                problemDetails.Detail   = "See errors property for additional details.";

                var actionExecutingContext = actionContext as ActionExecutingContext;
                if (actionContext.ModelState.ErrorCount != 0 &&
                    (actionContext is ControllerContext || actionContext.ActionDescriptor.Parameters.Count == actionExecutingContext.ActionArguments.Count))
                {
                    problemDetails.Title    = "One or more validation errors occured.";
                    problemDetails.Status   = StatusCodes.Status422UnprocessableEntity;
                    problemDetails.Instance = $"{actionContext.HttpContext.Request.PathBase}/modelvalidationerror";

                    return(new UnprocessableEntityObjectResult(problemDetails)
                    {
                        ContentTypes = { "application/problem+json" }
                    });
                }

                problemDetails.Title  = "One or more errors occured on the input";
                problemDetails.Status = StatusCodes.Status400BadRequest;

                return(new BadRequestObjectResult(problemDetails)
                {
                    ContentTypes = { "application/problem+json" }
                });
            };
        }
예제 #6
0
        internal static IActionResult ProblemDetailsInvalidModelStateResponse(
            ProblemDetailsFactory problemDetailsFactory, ActionContext context)
        {
            var problemDetails = problemDetailsFactory.CreateValidationProblemDetails(context.HttpContext, context.ModelState);
            var result         = (HttpStatusCode?)problemDetails.Status == HttpStatusCode.BadRequest ? new BadRequestObjectResult(problemDetails) : new ObjectResult(problemDetails);

            result.ContentTypes.Add("application/problem+json");
            result.ContentTypes.Add("application/problem+xml");

            return(result);
        }
        private ProblemDetails BuildProblemDetails <TEx>(TEx ex, int status, HttpContext context) where TEx : Exception
        {
            if (ex is ValidationException valEx)
            {
                var state = new ModelStateDictionary();
                foreach (var err in valEx.Errors)
                {
                    state.AddModelError(err.Context, err.Message);
                }
                return(_problemDetailsFactory.CreateValidationProblemDetails(context, state, status, ex.Message, null, null, context.Request.Path));
            }

            return(_problemDetailsFactory.CreateProblemDetails(context, status, ex.Message, null, null, context.Request.Path));
        }
        private static ValidationProblemDetails HandleValidationProblemDetails(ValidationExceptionBase ex)
        {
            _context.Response.StatusCode = (int)ex.StatusCode;
            var modelStateDictionary = new ModelStateDictionary();

            modelStateDictionary.AddModelError(ex.Property, ex.Message);

            var problemDetails = _problemDetailsFactory.CreateValidationProblemDetails(
                _context,
                statusCode: (int)ex.StatusCode,
                detail: _includeStackTrace ? ex.ToString() : ex.Message,
                modelStateDictionary: modelStateDictionary
                );

            return(problemDetails);
        }
예제 #9
0
        public void ConfigureServices(IServiceCollection services)
        {
            RegisterServices(services);
            RegisterDateTimeProvider(services);

            ConfigureDatabase(services);

            ConfigureCors(services);

            services.AddMediatR(typeof(Login.Handler).Assembly);
            services.AddGenericMediatorHandlers();
            services.AddAutoMapper(
                typeof(LoginDtoMappingProfile).Assembly,
                typeof(Modify.MappingProfile).Assembly);
            services.AddHealthChecks().AddDbContextCheck <ArpaContext>();

            services.Configure <ApiBehaviorOptions>(options => options.SuppressInferBindingSourcesForParameters = true);
            services
            .AddControllers()
            .AddJsonOptions(options => options.JsonSerializerOptions.Converters
                            .Add(new DateTimeJsonConverter()))
            .AddApplicationPart(typeof(Startup).Assembly)
            .AddFluentValidation(config =>
            {
                config.RegisterValidatorsFromAssemblyContaining <LoginDtoValidator>();
                config.RegisterValidatorsFromAssemblyContaining <Validator>();
                config.ValidatorFactoryType = typeof(HttpContextServiceProviderValidatorFactory);     // Workaround https://github.com/micro-elements/MicroElements.Swashbuckle.FluentValidation#error-systeminvalidoperationexception-cannot-resolve-ivalidatort-from-root-provider-because-it-requires-scoped-service-tdependency
            })
            .ConfigureApiBehaviorOptions(options =>
            {
                options.InvalidModelStateResponseFactory = context =>
                {
                    ProblemDetailsFactory problemDetailsFactory = context.HttpContext.RequestServices.GetRequiredService <ProblemDetailsFactory>();
                    ValidationProblemDetails problemDetails     = problemDetailsFactory.CreateValidationProblemDetails(context.HttpContext, context.ModelState, statusCode: 422);
                    var result = new UnprocessableEntityObjectResult(problemDetails);
                    result.ContentTypes.Add("application/problem+json");
                    result.ContentTypes.Add("application/problem+xml");
                    return(result);
                };
            });

            ConfigureSwagger(services);

            ConfigureAuthentication(services);

            ConfigureAuthorization(services);
        }
        public IActionResult Authentication(SimDeviceAuthenticationRequest simDeviceAuthenticationRequest)
        {
            var simMsisdn        = simDeviceAuthenticationRequest.SimMsisdn;
            var simImsi          = simDeviceAuthenticationRequest.SimImsi;
            var simIccId         = simDeviceAuthenticationRequest.SimIccId;
            var certBase64String = simDeviceAuthenticationRequest.ClientCertificationBase64;

            var subjectCn = CertificateUtil.GetSubjectCommonNameByCertificationBase64(certBase64String);

            if (subjectCn == null)
            {
                var validationProblemDetails = ProblemDetailsFactory.CreateValidationProblemDetails(HttpContext, ModelState);
                validationProblemDetails.Errors.Add(new KeyValuePair <string, string[]>("ClientCertificationBase64", new[] { "certification_invalid" }));
                return(BadRequest(validationProblemDetails));
            }

            var simDevice = _authenticationRepository.GetSimDevice(simMsisdn, simImsi, simIccId, subjectCn);

            if (simDevice == null)
            {
                Sim sim = _authenticationRepository.GetSim(simMsisdn, simImsi, simIccId);
                if (sim == null)
                {
                    _logger.LogWarning($"Not Found SIM:{simMsisdn}");
                }
                else
                {
                    CreateSimAndDeviceAuthenticationFailureLog(sim);
                    _radiusDbRepository.UpdateRadreply(sim.UserName + "@" + sim.SimGroup.UserNameSuffix);
                }
                return(Unauthorized(NotMatchSimDevice));
            }
            // 認証成功のSimDeviceによって それに対応する LoginできるUser を検索します
            var canLogonUsers = _authenticationRepository.GetLoginUsers(subjectCn);

            _radiusDbRepository.UpdateRadreply(simDevice.Sim.UserName + "@" + simDevice.Sim.SimGroup.UserNameSuffix, simDevice.IsolatedNw2Ip);
            CreateSimAndDeviceAuthenticationSuccessLog(simDevice);

            // SimDeviceによって 認証状態を検索する すでに登録したら SimAndDeviceAuthenticated を更新します
            var simDeviceAuthenticationStateDone = CreateSimAndDeviceAuthenticated(simDevice);

            var simDeviceAuthenticationResponse =
                CreateSimDeviceAuthenticationResponse(simDeviceAuthenticationStateDone, simDevice, canLogonUsers);

            return(Ok(simDeviceAuthenticationResponse));
        }
 /// <summary>
 /// Creates a <see cref="ValidationProblemDetails" /> instance that configures defaults based on values specified in <see cref="ApiBehaviorOptions" />.
 /// </summary>
 /// <param name="httpContext">The <see cref="HttpContext" />.</param>
 /// <param name="modelStateDictionary">The <see cref="ModelStateDictionary" />.</param>
 /// <param name="statusCode">The value for <see cref="ProblemDetails.Status" />.</param>
 /// <param name="title">The value for <see cref="ProblemDetails.Title" />.</param>
 /// <param name="type">The value for <see cref="ProblemDetails.Type" />.</param>
 /// <param name="detail">The value for <see cref="ProblemDetails.Detail" />.</param>
 /// <param name="instance">The value for <see cref="ProblemDetails.Instance" />.</param>
 /// <returns>The <see cref="ValidationProblemDetails" /> instance.</returns>
 public override ValidationProblemDetails CreateValidationProblemDetails(
     HttpContext httpContext,
     ModelStateDictionary modelStateDictionary,
     int?statusCode  = null,
     string title    = null,
     string type     = null,
     string detail   = null,
     string instance = null)
 {
     return(ReplaceTraceId(_inner.CreateValidationProblemDetails(httpContext,
                                                                 modelStateDictionary,
                                                                 statusCode,
                                                                 title,
                                                                 type,
                                                                 detail,
                                                                 instance
                                                                 )));
 }
        // creates validation problem details instance.
        // borrowed from netcore: https://github.com/dotnet/aspnetcore/blob/main/src/Mvc/Mvc.Core/src/ControllerBase.cs#L1970
        protected ValidationProblemDetails?GetValidationProblemDetails(
            string?detail   = null,
            string?instance = null,
            int?statusCode  = null,
            string?title    = null,
            string?type     = null,
            [ActionResultObjectValue] ModelStateDictionary?modelStateDictionary = null)
        {
            modelStateDictionary ??= ModelState;

            ValidationProblemDetails?validationProblem;

            if (ProblemDetailsFactory == null)
            {
                // ProblemDetailsFactory may be null in unit testing scenarios. Improvise to make this more testable.
                validationProblem = new ValidationProblemDetails(modelStateDictionary)
                {
                    Detail   = detail,
                    Instance = instance,
                    Status   = statusCode,
                    Title    = title,
                    Type     = type,
                };
            }
            else
            {
                validationProblem = ProblemDetailsFactory?.CreateValidationProblemDetails(
                    HttpContext,
                    modelStateDictionary,
                    statusCode: statusCode,
                    title: title,
                    type: type,
                    detail: detail,
                    instance: instance);
            }

            return(validationProblem);
        }
        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddControllers(setup =>
            {
                setup.ReturnHttpNotAcceptable = true;
            }
                                    ).AddXmlDataContractSerializerFormatters()
            .AddFluentValidation(configuration => configuration.RegisterValidatorsFromAssemblyContaining <Startup>())
            .ConfigureApiBehaviorOptions(setupAction =>
            {
                setupAction.InvalidModelStateResponseFactory = context =>
                {
                    ProblemDetailsFactory problemDetailsFactory = context.HttpContext.RequestServices
                                                                  .GetRequiredService <ProblemDetailsFactory>();

                    ValidationProblemDetails problemDetails = problemDetailsFactory.CreateValidationProblemDetails(
                        context.HttpContext,
                        context.ModelState);

                    problemDetails.Detail   = "Check error field for details";
                    problemDetails.Instance = context.HttpContext.Request.Path;

                    var actionExecutiongContext = context as ActionExecutingContext;

                    if ((context.ModelState.ErrorCount > 0) &&
                        (actionExecutiongContext?.ActionArguments.Count == context.ActionDescriptor.Parameters.Count))
                    {
                        problemDetails.Type   = "https://google.com";
                        problemDetails.Status = StatusCodes.Status422UnprocessableEntity;
                        problemDetails.Title  = "Failed to validate";

                        return(new UnprocessableEntityObjectResult(problemDetails)
                        {
                            ContentTypes = { "application/problem+json" }
                        });
                    }

                    problemDetails.Status = StatusCodes.Status400BadRequest;
                    problemDetails.Title  = "Failed to parse the content";
                    return(new BadRequestObjectResult(problemDetails)
                    {
                        ContentTypes = { "application/problem+json" }
                    });
                };
            });
            services.AddDbContext <UserDbContext>();
            services.AddDbContext <IdentityUserDbContext>();

            services.AddIdentity <AccountInfo, AccountRole>(options =>
            {
                options.Password.RequireDigit           = false;
                options.Password.RequireNonAlphanumeric = false;
                options.Password.RequiredLength         = 6;
                options.Password.RequireLowercase       = false;
                options.Password.RequireUppercase       = false;
            }).AddEntityFrameworkStores <IdentityUserDbContext>();

            services.AddAutoMapper(AppDomain.CurrentDomain.GetAssemblies());

            services.AddSingleton <ILogger, Logger>();
            services.AddSingleton <ILoggerProvider, LoggerProvider>();

            services.AddScoped <IPersonalUserRepository, PersonalUserRepository>();
            services.AddScoped <ICorporationUserRepository, CorporationUserRepository>();
            services.AddScoped <ICountryRepository, CountryRepository>();
            services.AddScoped <IRoleRepository, RoleRepository>();

            services.AddScoped <IPersonalUsersService, PersonalUsersService>();
            services.AddScoped <ICountryService, CountryService>();
            services.AddScoped <IRolesService, RolesService>();
            services.AddScoped <ICorporationUsersService, CorporationUsersService>();

            services.AddSwaggerGen(setupAction =>
            {
                setupAction.SwaggerDoc("UserServiceOpenApiSpecification",
                                       new Microsoft.OpenApi.Models.OpenApiInfo()
                {
                    Title       = "User Service API",
                    Version     = "1",
                    Description = "API for creating, updating and fetcing users, roles and countries",
                    Contact     = new Microsoft.OpenApi.Models.OpenApiContact
                    {
                        Name  = "Djordje Stefanovic",
                        Email = "*****@*****.**",
                    }
                });
            });
        }
예제 #14
0
        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddResponseCaching();

            services.AddControllers(setupAction =>
            {
                setupAction.ReturnHttpNotAcceptable = true;
                setupAction.CacheProfiles.Add("240SecondsCacheProfile",
                                              new CacheProfile()
                {
                    Duration = 240
                });
            }).AddNewtonsoftJson()
            .AddXmlDataContractSerializerFormatters()
            .ConfigureApiBehaviorOptions(options =>
            {
                options.InvalidModelStateResponseFactory = context =>
                {
                    ProblemDetailsFactory problemDetailsFactory = context.HttpContext.RequestServices
                                                                  .GetRequiredService <ProblemDetailsFactory>();
                    var problemDetails = problemDetailsFactory.CreateValidationProblemDetails(
                        context.HttpContext, context.ModelState);
                    problemDetails.Instance = context.HttpContext.Request.Path;

                    var actionExecutingContext = context as ActionExecutingContext;

                    if ((context.ModelState.ErrorCount > 0) &&
                        (actionExecutingContext?.ActionArguments.Count == context.ActionDescriptor.Parameters.Count))
                    {
                        problemDetails.Status = StatusCodes.Status422UnprocessableEntity;
                        problemDetails.Title  = "One or more validation errors occurred.";
                        return(new UnprocessableEntityObjectResult(problemDetails)
                        {
                            ContentTypes = { "application/problem+json" }
                        });
                    }
                    problemDetails.Status = StatusCodes.Status400BadRequest;
                    problemDetails.Title  = "One or more errors on input occurred.";
                    return(new BadRequestObjectResult(problemDetails)
                    {
                        ContentTypes = { "application/problem+json" }
                    });
                };
            });

            services.Configure <MvcOptions>(config =>
            {
                var jsonFormatter = (NewtonsoftJsonOutputFormatter)(config.OutputFormatters.FirstOrDefault(of => of.GetType() == typeof(NewtonsoftJsonOutputFormatter)));
                if (jsonFormatter != null)
                {
                    jsonFormatter.SupportedMediaTypes.Add("application/vnd.marvin.hateoas+json");
                }
            });

            services.AddAutoMapper(AppDomain.CurrentDomain.GetAssemblies());
            services.AddMemoryCache();
            services.AddSingleton <IAsyncCacheProvider, MemoryCacheProvider>();
            IPolicyRegistry <string> registry = services.AddPolicyRegistry();

            services.AddHttpClient <IAuthenticationClientAsync, AuthenticationClientAsync>().ConfigurePrimaryHttpMessageHandler(h =>
            {
                var handler             = new HttpClientHandler();
                var certificateFilepath = Configuration["BetfairApi:Authentication:CertificateFilepath"];
                var cert = new X509Certificate2(certificateFilepath, "", X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.PersistKeySet | X509KeyStorageFlags.Exportable);
                handler.ClientCertificates.Add(cert);
                return(handler);
            });
            services.Configure <DataProviderMappings>((settings) =>
            {
                Configuration.GetSection("DataProviders").Bind(settings);
            });
            services.AddHttpClient <IRequestInvokerAsync, RequestInvokerAsync>();
            string connectionString = Configuration["ConnectionStrings:BetfairMetadataServiceDb"];

            services.AddDbContext <BetfairMetadataServiceContext>(o => o.UseSqlServer(connectionString));

            services.AddScoped <IBatchReader <DataProvider>, ConfigurationBatchDataProviderReader>();
            services.AddScoped <IReader <DataProvider, int>, ConfigurationDataProviderReader>();

            services.AddScoped <IReader <EventType, string>, BetfairEventTypeReader>();
            services.AddScoped <IReader <Competition, string>, BetfairCompetitionReader>();

            services.AddScoped <IBetfairBatchReader <EventType>, BetfairEventTypesBatchReader>();
            services.AddScoped <IBetfairBatchReader <Competition>, BetfairCompetitionsBatchReader>();
            services.AddScoped <IBetfairBatchReader <Event>, BetfairEventsBatchReader>();
            services.AddScoped <IBetfairBatchReader <MarketType>, BetfairMarketTypesBatchReader>();
            services.AddScoped <IBetfairBatchReader <Market>, BetfairMarketsBatchReader>();

            services.AddScoped <Func <int, IExternalEventTypesRepository> >(sp =>
                                                                            dataProviderId =>
            {
                switch (dataProviderId)
                {
                case (1):
                    return(new BetfairEventTypesRepository(sp.GetRequiredService <IBetfairBatchReader <EventType> >()));

                default:
                    return(null);
                }
            });
            services.AddScoped <Func <int, IExternalCompetitionsRepository> >(sp =>
                                                                              dataProviderId =>
            {
                switch (dataProviderId)
                {
                case (1):
                    return(new BetfairCompetitionsRepository(sp.GetRequiredService <IBetfairBatchReader <Competition> >()));

                default:
                    return(null);
                }
            });

            services.AddScoped <Func <int, IExternalEventsRepository> >(sp =>
                                                                        dataProviderId =>
            {
                switch (dataProviderId)
                {
                case (1):
                    return(new BetfairEventsRepository(sp.GetRequiredService <IBetfairBatchReader <Event> >()));

                default:
                    return(null);
                }
            });

            services.AddScoped <Func <int, IExternalMarketTypesRepository> >(sp =>
                                                                             dataProviderId =>
            {
                switch (dataProviderId)
                {
                case (1):
                    return(new BetfairMarketTypesRepository(sp.GetRequiredService <IBetfairBatchReader <MarketType> >()));

                default:
                    return(null);
                }
            });

            services.AddScoped <Func <int, IExternalMarketsRepository> >(sp =>
                                                                         dataProviderId =>
            {
                switch (dataProviderId)
                {
                case (1):
                    return(new BetfairMarketsRepository(sp.GetRequiredService <IBetfairBatchReader <Market> >()));

                default:
                    return(null);
                }
            });

            services.AddScoped <IDeleter <EventTypeMarketType>, EventTypeMarketTypeFetchRootDeleter>();
            services.AddScoped <ISaver <EventTypeMarketType>, EventTypeMarketTypeFetchRootSaver>();
            services.AddScoped <IReader <EventTypeMarketType, Tuple <int, string, string> >, EventTypeMarketTypeFetchRootReader>();

            services.AddScoped <IDeleter <CompetitionMarketType>, CompetitionMarketTypeFetchRootDeleter>();
            services.AddScoped <ISaver <CompetitionMarketType>, CompetitionMarketTypeFetchRootSaver>();
            services.AddScoped <IReader <CompetitionMarketType, Tuple <int, string, string> >, CompetitionMarketTypeFetchRootReader>();

            services.AddScoped <IEntityUpserter, EntityUpserter>();
            services.AddScoped(typeof(IBatchReader <>), typeof(BatchReader <>));
            services.AddScoped <IReader <Domain.Internal.EventType, string>, Reader <Domain.Internal.EventType> >();
            services.AddScoped <IReader <Domain.Internal.Competition, string>, Reader <Domain.Internal.Competition> >();
            services.AddScoped <IReader <Domain.Internal.Event, string>, Reader <Domain.Internal.Event> >();
            services.AddScoped <IReader <Domain.Internal.Market, string>, Reader <Domain.Internal.Market> >();
            services.AddScoped <IReader <Domain.Internal.Selection, string>, Reader <Domain.Internal.Selection> >();

            services.AddScoped <BetfairCompetitionsWorker>();
            services.AddScoped <IWorker>(sp => new CompositeWorker(
                                             new IWorker[]
            {
                sp.GetRequiredService <BetfairCompetitionsWorker>()
            }));
            services.AddScoped <ICompetitionMarketTypeWorker, BetfairCompetitionWorker>();
        }
예제 #15
0
        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddControllers(setup =>
            {
                //Content negotiation in Accept header of users request
                setup.Filters.Add <ValidationFilter>();
                setup.ReturnHttpNotAcceptable = true;
            }
                                    ).AddXmlDataContractSerializerFormatters()
            .AddFluentValidation(configuration => configuration.RegisterValidatorsFromAssemblyContaining <Startup>())
            .ConfigureApiBehaviorOptions(setupAction => //Deo koji se odnosi na podržavanje Problem Details for HTTP APIs
            {
                setupAction.InvalidModelStateResponseFactory = context =>
                {
                    //Kreiramo problem details objekat
                    ProblemDetailsFactory problemDetailsFactory = context.HttpContext.RequestServices
                                                                  .GetRequiredService <ProblemDetailsFactory>();

                    //Prosleđujemo trenutni kontekst i ModelState, ovo prevodi validacione greške iz ModelState-a u RFC format
                    ValidationProblemDetails problemDetails = problemDetailsFactory.CreateValidationProblemDetails(
                        context.HttpContext,
                        context.ModelState);

                    //Ubacujemo dodatne podatke
                    problemDetails.Detail   = "Check error field for details";
                    problemDetails.Instance = context.HttpContext.Request.Path;

                    //po defaultu se sve vraća kao status 400 BadRequest, to je ok kada nisu u pitanju validacione greške,
                    //ako jesu hoćemo da koristimo status 422 UnprocessibleEntity
                    //tražimo info koji status kod da koristimo
                    var actionExecutiongContext = context as ActionExecutingContext;

                    //proveravamo da li postoji neka greška u ModelState-u, a takođe proveravamo da li su svi prosleđeni parametri dobro parsirani
                    //ako je sve ok parsirano ali postoje greške u validaciji hoćemo da vratimo status 422
                    if ((context.ModelState.ErrorCount > 0) &&
                        (actionExecutiongContext?.ActionArguments.Count == context.ActionDescriptor.Parameters.Count))
                    {
                        problemDetails.Type   = "https://google.com"; //inače treba da stoji link ka stranici sa detaljima greške
                        problemDetails.Status = StatusCodes.Status422UnprocessableEntity;
                        problemDetails.Title  = "Failed to validate";

                        //sve vraćamo kao UnprocessibleEntity objekat
                        return(new UnprocessableEntityObjectResult(problemDetails)
                        {
                            ContentTypes = { "application/problem+json" }
                        });
                    }

                    //ukoliko postoji nešto što nije moglo da se parsira hoćemo da vraćamo status 400 kao i do sada
                    problemDetails.Status = StatusCodes.Status400BadRequest;
                    problemDetails.Title  = "Failed to parse the content";
                    return(new BadRequestObjectResult(problemDetails)
                    {
                        ContentTypes = { "application/problem+json" }
                    });
                };
            });
            services.AddDbContext <UserDbContext>();
            services.AddDbContext <IdentityUserDbContext>();
            //Adding Identity
            services.AddIdentity <AccountInfo, AccountRole>(options =>
            {
                options.Password.RequireDigit           = false;
                options.Password.RequireNonAlphanumeric = false;
                options.Password.RequiredLength         = 6;
                options.Password.RequireLowercase       = false;
                options.Password.RequireUppercase       = false;
            }).AddEntityFrameworkStores <IdentityUserDbContext>();

            services.AddAutoMapper(AppDomain.CurrentDomain.GetAssemblies());

            services.AddScoped <IPersonalUserRepository, PersonalUserRepository>();
            services.AddScoped <ICorporationUserRepository, CorporationUserRepository>();
            services.AddScoped <ICityRepository, CityRepository>();
            services.AddScoped <IRoleRepository, RoleRepository>();
            services.AddScoped <IPersonalUsersService, PersonalUsersService>();
            services.AddScoped <ICitiesService, CitiesService>();
            services.AddScoped <IRolesService, RolesService>();
            services.AddScoped <ICorporationUsersService, CorporationUsersService>();
            services.AddScoped <ResourceOwnerFilter>();


            var jwtSettings = new JwtSettings();

            Configuration.Bind(nameof(jwtSettings), jwtSettings);
            services.AddSingleton(jwtSettings);


            services.AddAuthentication(x =>
            {
                x.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
                x.DefaultScheme             = JwtBearerDefaults.AuthenticationScheme;
                x.DefaultChallengeScheme    = JwtBearerDefaults.AuthenticationScheme;
            })
            .AddJwtBearer(x =>
            {
                x.SaveToken = true;
                x.TokenValidationParameters = new TokenValidationParameters
                {
                    ValidateIssuerSigningKey = true,
                    IssuerSigningKey         = new SymmetricSecurityKey(Encoding.ASCII.GetBytes(jwtSettings.Secret)),
                    ValidateIssuer           = false,
                    ValidateAudience         = false,
                    RequireExpirationTime    = false,
                    ValidateLifetime         = true
                };
            });


            services.AddSwaggerGen(setupAction =>
            {
                setupAction.SwaggerDoc("UserServiceOpenApiSpecification",
                                       new Microsoft.OpenApi.Models.OpenApiInfo()
                {
                    Title       = "User Service API",
                    Version     = "1",
                    Description = "API for creating, updating and fetcing users, roles and cities",
                    Contact     = new Microsoft.OpenApi.Models.OpenApiContact
                    {
                        Name  = "Natalija Gajić",
                        Email = "*****@*****.**",
                    },
                    License = new Microsoft.OpenApi.Models.OpenApiLicense
                    {
                        Name = "FTN licence"
                    }
                });
                setupAction.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme
                {
                    Description = "JWT Authorization header using the Bearer scheme. \r\n\r\n Enter 'Bearer' [space] and then your token in the text input below.\r\n\r\nExample: \"Bearer 12345abcdef\"",
                    Name        = "Authorization",
                    In          = ParameterLocation.Header,
                    Type        = SecuritySchemeType.ApiKey,
                    Scheme      = "Bearer"
                });
                setupAction.AddSecurityRequirement(new OpenApiSecurityRequirement()
                {
                    {
                        new OpenApiSecurityScheme
                        {
                            Reference = new OpenApiReference
                            {
                                Type = ReferenceType.SecurityScheme,
                                Id   = "Bearer"
                            },
                            Scheme = "oauth2",
                            Name   = "Bearer",
                            In     = ParameterLocation.Header,
                        },
                        new List <string>()
                    }
                });
            });
        }