private static ProblemDetails HandleKnownException(Exception exception, ModelStateDictionary modelState) { ProblemDetails problemDetails; switch (exception) { case IdentityResultException ex: modelState ??= new ModelStateDictionary(); foreach (var error in ex.Errors) { modelState.TryAddModelError(error.Code, error.Description); } problemDetails = ProblemDetailsFactory.New(HttpStatusCode.BadRequest, modelState, ex); break; case NotFoundException ex: problemDetails = ProblemDetailsFactory.New(HttpStatusCode.NotFound, ex); break; case EmailNotConfirmedException ex: problemDetails = ProblemDetailsFactory.New(HttpStatusCode.BadRequest, ex); break; default: problemDetails = ProblemDetailsFactory.New(HttpStatusCode.BadRequest, exception); break; } return(problemDetails); }
public ActionResult DeleteMessage(string channelid, string sequence) { logger.LogInformation($"Deleting message(sequence): {sequence} in channel(id): {channelid}."); Message message; SPVChannelsHTTPError error; if (!long.TryParse(sequence, out long seq) || (message = messageRepository.GetMessageMetaData(channelid, seq)) == null) { error = SPVChannelsHTTPError.NotFound; return(NotFound(ProblemDetailsFactory.CreateProblemDetails(HttpContext, error.Code, error.Description))); } var channel = channelRepository.GetChannelByExternalId(channelid); if (channel.MinAgeDays.HasValue && message.ReceivedTS.AddDays(channel.MinAgeDays.Value).Date.CompareTo(DateTime.UtcNow) > 0) { error = SPVChannelsHTTPError.RetentionNotExpired; return(BadRequest(ProblemDetailsFactory.CreateProblemDetails(HttpContext, error.Code, error.Description))); } messageRepository.DeleteMessage(message.Id); logger.LogInformation($"Message deleted."); return(NoContent()); }
private ObjectResult Problem(bool dumpStack) { var ex = HttpContext.Features.Get <IExceptionHandlerPathFeature>().Error; string title = string.Empty; var statusCode = (int)HttpStatusCode.InternalServerError; if (ex is DomainException) { title = "Internal system error occurred"; statusCode = (int)HttpStatusCode.InternalServerError; } if (ex is BadRequestException) { title = "Bad client request"; statusCode = (int)HttpStatusCode.BadRequest; } var pd = ProblemDetailsFactory.CreateProblemDetails( HttpContext, statusCode: statusCode, title: title, detail: ex.Message); if (dumpStack) { pd.Extensions.Add("stackTrace", ex.ToString()); } var result = new ObjectResult(pd) { StatusCode = statusCode }; return(result); }
public ActionResult <APITokenViewModelGet> Post(string accountid, string channelid, [FromBody] APITokenViewModelCreate data) { logger.LogInformation($"Generate API Token for accountid: {accountid} and channel: {channelid}."); if (!long.TryParse(accountid, out long aid)) { var error = SPVChannelsHTTPError.NotFound; return(NotFound(ProblemDetailsFactory.CreateProblemDetails(HttpContext, error.Code, error.Description))); } var channel = channelRepository.GetChannelByExternalId(channelid); if (channel == null) { var error = SPVChannelsHTTPError.NotFound; return(NotFound(ProblemDetailsFactory.CreateProblemDetails(HttpContext, error.Code, error.Description))); } var newAPIToken = apiTokenRepository.CreateAPIToken(data.ToDomainObject(aid, channel.Id)); var returnResult = new APITokenViewModelGet(newAPIToken); logger.LogInformation($"API Token(id) {returnResult.Id} was generated."); return(Ok(returnResult)); }
private static async Task WriteResponse(HttpContext context) { _context = context; var exceptionDetails = context.Features.Get <IExceptionHandlerFeature>(); var ex = exceptionDetails?.Error; if (ex != null) { context.Response.ContentType = "application/problem+json"; _problemDetailsFactory = context?.RequestServices?.GetRequiredService <ProblemDetailsFactory>(); ProblemDetails problemDetails = ex switch { CustomExceptionBase customException => HandleProblemDetails(customException), ValidationExceptionBase validationException => HandleValidationProblemDetails(validationException), _ => HandleDefault(ex), }; var stream = _context.Response.Body; if (problemDetails is ValidationProblemDetails validationProblemDetails) { await JsonSerializer.SerializeAsync(stream, validationProblemDetails); } else { await JsonSerializer.SerializeAsync(stream, problemDetails); } } }
public async Task <ActionResult <IEnumerable <MessageViewModelGet> > > MarkMessage(string channelid, long sequence, [FromQuery] bool?older, [FromBody] MessageViewModelMark data) { logger.LogInformation($"Flag message {sequence} from {channelid} as {(data.Read ? "read" : "unread")}."); // Retrieve token information from identity APIToken apiToken = await authRepository.GetAPITokenAsync(HttpContext.User.Identity.Name); // Validate that sequence exists if (!messageRepository.SequenceExists(apiToken.Id, sequence)) { logger.LogInformation($"Sequence {sequence} not found for API Token {apiToken.Id}."); return(NotFound(ProblemDetailsFactory.CreateProblemDetails(HttpContext, (int)HttpStatusCode.NotFound, $"Sequence not found."))); } // Mark messages messageRepository.MarkMessages(channelid, apiToken.Id, sequence, older ?? false, data.Read); logger.LogInformation($"Message {sequence} was flagged as {(data.Read ? "read" : "unread")}."); return(Ok()); }
public static void Configure(IApplicationBuilder app, ILoggerFactory loggerFactory, IWriteToFileText writeToFileText) { app.UseExceptionHandler(errorApp => { errorApp.Run(async context => { var errorFeature = context.Features.Get <IExceptionHandlerFeature>(); var exception = errorFeature.Error; var isConnectionTrusted = context.Request.IsTrusted(); var problemDetails = ProblemDetailsFactory.Build(exception, isConnectionTrusted); var logger = LoggerConfigurations.Configure(loggerFactory, writeToFileText); var logString = $"Processing request {context.Request.Path},\n Status Code: {problemDetails.Status.Value},\n Details:{exception.Demystify().ToString() ?? problemDetails.Detail}\n"; if (!(exception is BusinessLogicException)) { logger.LogError(logString); } context.Response.StatusCode = problemDetails.Status.Value; context.Response.WriteJson(problemDetails, "application/problem+json"); }); }); }
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" } }); }; }
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 async Task <ActionResult <FeeQuoteConfigViewModelGet> > Post([FromBody] FeeQuoteViewModelCreate data) { logger.LogInformation($"Create new FeeQuote form data: {data} ."); data.CreatedAt = clock.UtcNow(); var domainModel = data.ToDomainObject(clock.UtcNow()); var br = this.ReturnBadRequestIfInvalid(domainModel); if (br != null) { return(br); } var newFeeQuote = await feeQuoteRepository.InsertFeeQuoteAsync(domainModel); if (newFeeQuote == null) { var problemDetail = ProblemDetailsFactory.CreateProblemDetails(HttpContext, (int)HttpStatusCode.BadRequest); problemDetail.Status = (int)HttpStatusCode.BadRequest; problemDetail.Title = $"FeeQuote not created. Check errors."; return(BadRequest(problemDetail)); } var returnResult = new FeeQuoteConfigViewModelGet(newFeeQuote); logger.LogInformation($"FeeQuote(id) {returnResult.Id} was generated."); return(CreatedAtAction(nameof(GetFeeQuoteById), new { id = returnResult.Id }, returnResult)); }
public ActionResult <APITokenViewModelGet> GetAPIToken( string accountid, // only used for documentation string channelid, // only used for documentation string tokenid) { logger.LogInformation($"Get API token by tokenid: {tokenid} for account {accountid} and {channelid}."); var error = SPVChannelsHTTPError.NotFound; if (!long.TryParse(tokenid, out long id)) { return(NotFound(ProblemDetailsFactory.CreateProblemDetails(HttpContext, error.Code, error.Description))); } var apiToken = apiTokenRepository.GetAPITokenById(id); if (apiToken == null) { logger.LogInformation($"API token with tokenid: {tokenid} does not exist."); return(NotFound(ProblemDetailsFactory.CreateProblemDetails(HttpContext, error.Code, error.Description))); } logger.LogInformation($"Returning API token by tokenid: {tokenid}."); return(Ok(new APITokenViewModelGet(apiToken))); }
private static ProblemDetails HandleInternalServerError( Exception exception, bool isTrusted) { var problemDetails = ProblemDetailsFactory.New( HttpStatusCode.InternalServerError, isTrusted ? exception.Demystify().ToString() : exception.Message); return(problemDetails); }
public IdempotencyMiddleware(ILogger <IdempotencyMiddleware> logger, IIdempotencyPersistenceProvider persistence, ProblemDetailsFactory problemDetailsFactory) { _logger = logger; _persistence = persistence; _problemDetailsFactory = problemDetailsFactory; _keyPrefix = string.Empty; _idempotencyKey = string.Empty; _prefixedIdempotencyKey = string.Empty; }
public async Task InvokeAsync(HttpContext context, ProblemDetailsFactory problemDetailsFactory) { await this.next(context).ConfigureAwait(true); if (context.Response.StatusCode == (int)HttpStatusCode.NotFound || context.Response.ContentLength is null or 0) { var notFoundProblemDetails = problemDetailsFactory.CreateProblemDetails(context, (int)HttpStatusCode.NotFound); await context.Response.WriteAsJsonAsync(notFoundProblemDetails).ConfigureAwait(true); } }
public ApiKeyAuthenticationHandler( IOptionsMonitor <ApiKeyAuthenticationOptions> options, ILoggerFactory logger, UrlEncoder encoder, ISystemClock clock, IApiKeyService apiKeyService, ProblemDetailsFactory problemDetailsFactory) : base(options, logger, encoder, clock) { _apiKeyService = apiKeyService ?? throw new ArgumentNullException(nameof(apiKeyService)); _problemDetailsFactory = problemDetailsFactory ?? throw new ArgumentNullException(nameof(problemDetailsFactory)); }
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); }
public async Task MergeStudent([FromRoute] int id, [FromBody] StudentMerge data) { var student = await _context.Students .FirstOrDefaultAsync(it => it.ID == id); if (student == null) { throw new ProblemDetailsException(ProblemDetailsFactory.CreateProblemDetails(this.HttpContext, 404)); } data.AdaptTo(student); await _context.SaveChangesAsync(); }
public async Task <ActionResult <SubmitTransactionResponseViewModel> > SubmitTxsRawAsync( [FromQuery] string callbackUrl, [FromQuery] string callbackEncryption, [FromQuery] string callbackToken, [FromQuery] bool merkleProof, [FromQuery] bool dsCheck ) { if (!IdentityProviderStore.GetUserAndIssuer(User, Request.Headers, out var identity)) { return(Unauthorized("Incorrectly formatted token")); } // callbackUrl is validated as part of domainObject - no special validation here byte[] data; using (var ms = new MemoryStream()) { await Request.Body.CopyToAsync(ms); data = ms.ToArray(); } byte[][] transactionAsBytes; try { // This is not very efficient, since we will reparse bytes into NBitcoin.Transaction later again transactionAsBytes = HelperTools.ParseTransactionsIntoBytes(data); } catch (Exception) { var problemDetail = ProblemDetailsFactory.CreateProblemDetails(HttpContext, (int)HttpStatusCode.BadRequest); problemDetail.Title = "Unable to parse incoming stream of transactions"; return(BadRequest(problemDetail)); } var request = transactionAsBytes.Select( t => new SubmitTransaction { RawTx = t, CallbackUrl = callbackUrl, CallbackEncryption = callbackEncryption, CallbackToken = callbackToken, MerkleProof = merkleProof, DsCheck = dsCheck }).ToArray(); var result = new SubmitTransactionsResponseViewModel( await mapi.SubmitTransactionsAsync(request, identity)); return(await SignIfRequiredAsync(result, result.MinerId)); }
public async Task UpdateStudent([FromRoute] int id, [FromBody] StudentDto data) { var student = await _context.Students.Include(it => it.Enrollments) .FirstOrDefaultAsync(it => it.ID == id); if (student == null) { throw new ProblemDetailsException(ProblemDetailsFactory.CreateProblemDetails(this.HttpContext, 404)); } _mapper.From(data) .EntityFromContext(_context) .AdaptTo(student); await _context.SaveChangesAsync(); }
private static ProblemDetails ResolveProblemDetails(ProblemDetailsFactory problemDetailsFactory, IExceptionHandlerFeature contextFeature) { var problemDetails = default(ProblemDetails); if (contextFeature.Error is BadHttpRequestException badHttpRequestException) { problemDetails = problemDetailsFactory.GetValidationProblem(badHttpRequestException.Message); } else { problemDetails = problemDetailsFactory.GetInternalServerError(contextFeature.Error); } return(problemDetails); }
private static ProblemDetails HandleBadHttpRequestException( BadHttpRequestException exception, bool isTrusted) { var propertyInfo = typeof(BadHttpRequestException).GetProperty( "StatusCode", BindingFlags.NonPublic | BindingFlags.Instance); var statusCode = (int?)propertyInfo?.GetValue(exception); var problemDetails = ProblemDetailsFactory.New( statusCode == null ? HttpStatusCode.InternalServerError : (HttpStatusCode)statusCode, isTrusted ? exception.Demystify().ToString() : exception.Message); return(problemDetails); }
public async Task <ActionResult> Put(string id, NodeViewModelCreate data) { if (!string.IsNullOrEmpty(data.Id) && data.Id.ToLower() != id.ToLower()) { var problemDetail = ProblemDetailsFactory.CreateProblemDetails(HttpContext, (int)HttpStatusCode.BadRequest); problemDetail.Title = "The public id does not match the one from message body"; return(BadRequest(problemDetail)); } if (!await nodes.UpdateNodeAsync(data.ToDomainObject())) { return(NotFound()); } return(NoContent()); }
public ActionResult <ChannelViewModelList> GetChannels(string accountid) { logger.LogInformation($"Get list of channels for account(id) {accountid}."); if (!long.TryParse(accountid, out long id)) { var error = SPVChannelsHTTPError.NotFound; return(BadRequest(ProblemDetailsFactory.CreateProblemDetails(HttpContext, error.Code, error.Description))); } var channelList = channelRepository.GetChannels(id); logger.LogInformation($"Returning {channelList.Count()} channels for account(id): {id}."); return(Ok(new ChannelViewModelList(channelList.Select(x => new ChannelViewModelGet(x, Url.Link("GetMessages", new { channelid = x.ExternalId })))))); }
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)); }
public async Task <ActionResult <NodeViewModelGet> > Post(NodeViewModelCreate data) { var created = await nodes.CreateNodeAsync(data.ToDomainObject()); if (created == null) { var problemDetail = ProblemDetailsFactory.CreateProblemDetails(HttpContext, (int)HttpStatusCode.BadRequest); problemDetail.Status = (int)HttpStatusCode.Conflict; problemDetail.Title = $"Node '{data.Id}' already exists"; return(Conflict(problemDetail)); } // if this node is first being added on empty DB it will insert bestblockhash await blockParser.InitializeDB(); return(CreatedAtAction(nameof(Get), new { id = created.ToExternalId() }, new NodeViewModelGet(created))); }
private ProblemDetails ErrorDetails(Exception error) { if (error is InvalidOperationException) { var invalidOperationError = (InvalidOperationException)error; var errorMessages = new Dictionary <string, string[]>() { { "failureReason", new string[] { invalidOperationError.Message } } }; return(new ValidationProblemDetails(errorMessages) { Status = StatusCodes.Status400BadRequest }); } return(ProblemDetailsFactory.CreateProblemDetails(HttpContext)); }
public async Task <ActionResult <QueryTransactionStatusResponseViewModel> > QueryTransactionStatus(string id) { if (!IdentityProviderStore.GetUserAndIssuer(User, Request.Headers, out _)) { return(Unauthorized("Incorrectly formatted token")); } if (!uint256.TryParse(id, out _)) { var problemDetail = ProblemDetailsFactory.CreateProblemDetails(HttpContext, (int)HttpStatusCode.BadRequest); problemDetail.Title = "Invalid format of TransactionId"; return(BadRequest(problemDetail)); } var result = new QueryTransactionStatusResponseViewModel( await mapi.QueryTransaction(id)); return(await SignIfRequiredAsync(result, result.MinerId)); }
public ActionResult RevokeAPIToken( string accountid, // only used for documentation string channelid, // only used for documentation string tokenid) { logger.LogInformation($"API Token(id) {tokenid} for account(id) {accountid} and channel(id) {channelid} is being revoked."); if (!long.TryParse(tokenid, out long id)) { var error = SPVChannelsHTTPError.NotFound; return(NotFound(ProblemDetailsFactory.CreateProblemDetails(HttpContext, error.Code, error.Description))); } apiTokenRepository.RevokeAPIToken(id); logger.LogInformation($"API Token(id) {tokenid} was revoked."); return(NoContent()); }
public async Task <ActionResult <SubmitTransactionResponseViewModel> > SubmitTxsAsync( SubmitTransactionViewModel[] data, [FromQuery] string defaultCallbackUrl, [FromQuery] string defaultCallbackToken, [FromQuery] string defaultCallbackEncryption, [FromQuery] bool defaultMerkleProof, [FromQuery] string defaultMerkleFormat, [FromQuery] bool defaultDsCheck) { if (!IdentityProviderStore.GetUserAndIssuer(User, Request.Headers, out var identity)) { return(Unauthorized("Incorrectly formatted token")); } var domainModel = data.Select(x => x.ToDomainModel(defaultCallbackUrl, defaultCallbackToken, defaultCallbackEncryption, defaultMerkleProof, defaultMerkleFormat, defaultDsCheck)).ToArray(); SubmitTransactionsResponseViewModel result; try { result = new SubmitTransactionsResponseViewModel( await mapi.SubmitTransactionsAsync(domainModel, identity)); } catch (BadRequestException ex) { logger.LogError($"Error while submiting transactions. {ex.Message}."); var problemDetail = ProblemDetailsFactory.CreateProblemDetails(HttpContext, (int)HttpStatusCode.BadRequest); problemDetail.Title = ex.Message; return(BadRequest(problemDetail)); } return(await SignIfRequiredAsync(result, result.MinerId)); }