/// <inheritdoc/> protected override async Task <EventModel> ProtectedHandleAsync(GetByIdQuery request, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); var principal = PrincipalProvider.GetPrincipal(); if (principal == null) { throw new ForbiddenException("Not authenticated"); } Expression <Func <EventEntity, bool> > expression = PredicateBuilder.Create <EventEntity>(e => e.Id == Guid.Parse(request.Id)); if (!principal.IsInRole(RoleType.Administrator)) { expression = expression.And(e => e.UserId == principal.Identity.Name); } var result = Context.EventRepository .GetQuery() .Where(expression) .FirstOrDefault(); if (result == null) { throw new NotFoundException(nameof(WebhookEntity), request.Id); } var model = EventModel.Create(result, Serializer); await Task.CompletedTask; return(model); }
/// <inheritdoc/> protected override async Task <ResultModel> ProtectedHandleAsync(GetByIdQuery request, CancellationToken cancellationToken) { var principal = PrincipalProvider.GetPrincipal(); if (principal == null) { throw new ForbiddenException("Not authenticated"); } Expression <Func <ResultEntity, bool> > expression = PredicateBuilder.Create <ResultEntity>(e => e.Id == Guid.Parse(request.Id)); if (!principal.IsInRole(RoleType.Administrator)) { expression = expression.And(e => e.Task.Object.UserId == principal.Identity.Name); } var entity = await Context.ResultRepository.GetFirstOrDefaultAsync(expression, cancellationToken); if (entity == null) { throw new NotFoundException(nameof(ResultEntity), request.Id); } return(ResultModel.Create(entity, Serializer)); }
/// <summary> /// Asynchronously handles the command request. /// </summary> /// <param name="request">The command request.</param> /// <param name="cancellationToken">The cancellation token.</param> /// <returns>A task that represents the asynchronous operation. /// The task result contains the result of the command request.</returns> public async Task <TResponse> Handle(TRequest request, CancellationToken cancellationToken) { try { cancellationToken.ThrowIfCancellationRequested(); var response = await ProtectedHandleAsync(request, cancellationToken); if (SubEventType != SubEventType.None) { var principal = PrincipalProvider.GetPrincipal(); var auditData = new AuditDataModel() { Entity = response, Command = request }; await Audit.AddDefaultEventAsync(principal, auditData, SubEventType); } return(response); } catch (Exception) { Context.RollBackTransaction(); throw; } }
/// <inheritdoc/> protected override async Task <PaginationResultModel <EventModel> > ProtectedHandleAsync(GetPaginatedQuery request, CancellationToken cancellationToken) { var principal = PrincipalProvider.GetPrincipal(); if (principal == null) { throw new ForbiddenException("Not authenticated"); } Expression <Func <EventEntity, bool> > expression = PredicateBuilder.True <EventEntity>(); if (!principal.IsInRole(RoleType.Administrator)) { expression = expression.And(e => e.UserId == principal.Identity.Name); } int total = await Context.EventRepository.CountAsync(expression, cancellationToken); var query = Context.EventRepository .GetQuery(expression) .OrderByDescending(e => e.CreatedDate) .Skip(request.Page * request.Limit) .Take(request.Limit); var entities = await Context.ToListAsync(query, cancellationToken); var models = entities.Select(e => EventModel.Create(e, Serializer)); return(PaginationResultModel <EventModel> .Create(models, request.Page, request.Limit, total)); }
/// <inheritdoc/> protected override async Task <FileByteResultModel> ProtectedHandleAsync(GetZipQuery request, CancellationToken cancellationToken) { var principal = PrincipalProvider.GetPrincipal(); if (principal == null) { throw new ForbiddenException("Not authenticated"); } Expression <Func <ResultEntity, bool> > expression = PredicateBuilder.Create <ResultEntity>(e => e.Id == Guid.Parse(request.Id)); if (!principal.IsInRole(RoleType.Administrator)) { expression = expression.And(e => e.Task.Object.UserId == principal.Identity.Name); } var entity = await Context.ResultRepository.GetFirstOrDefaultAsync(expression, cancellationToken); if (entity == null) { throw new NotFoundException(nameof(ResultEntity), request.Id); } if (string.IsNullOrWhiteSpace(entity.BasePath)) { throw new UnexpectedNullException($"The base path of result {request.Id} is null."); } var fs = fileSystemStrategy.Create(configuration.Options.WorkingDirectory); if (fs == null) { throw new UnexpectedNullException("Filesystem could not be created based on the working directory."); } var fullBasePath = fs.Path.Combine(configuration.Options.WorkingDirectory, entity.BasePath); var items = fs.Directory.EnumerateFiles(fullBasePath, "*.*", SearchOption.TopDirectoryOnly); var archive = writer.Create(CompressionType.None); await writer.AddFilesAsync(items, dfp => dfp, en => en.Substring(fullBasePath.Length), archive, cancellationToken); var stream = new MemoryStream(); writer.Write(stream, archive); var result = new FileByteResultModel() { FileContents = stream.ToArray(), ContentType = "application/zip", FileDownloadName = $"{Constants.ApplicationNameShort}_{request.Id}_{DateTime.Now.ToString("yyyyMMdd_HHmmss")}.zip" }; return(result); }
/// <inheritdoc/> protected override async Task <ObjectModel> ProtectedHandleAsync(GetByIdQuery request, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); var principal = PrincipalProvider.GetPrincipal(); if (principal == null) { throw new ForbiddenException("Not authenticated"); } Expression <Func <ObjectEntity, bool> > expression = PredicateBuilder.Create <ObjectEntity>(e => e.Id == Guid.Parse(request.Id)); if (!principal.IsInRole(RoleType.Administrator)) { expression = expression.And(e => e.UserId == principal.Identity.Name); } var result = Context.ObjectRepository .GetQuery() .Where(expression) .Select(e => new { Object = e, Tasks = e.Tasks.OrderByDescending(e1 => e1.CreatedDate).Take(Constants.DefaultPaginationLimit), Results = e.Tasks.OrderByDescending(e1 => e1.CreatedDate).Select(e1 => e1.Result).Take(Constants.DefaultPaginationLimit) }) .FirstOrDefault(); if (result == null) { throw new NotFoundException(nameof(ObjectEntity), request.Id); } var model = ObjectModel.Create(result.Object, result.Tasks, result.Results, Serializer); await Task.CompletedTask; return(model); }
/// <inheritdoc/> protected override async Task <WebhookModel> ProtectedHandleAsync(CreateWebhookCommand request, CancellationToken cancellationToken) { var principal = PrincipalProvider.GetPrincipal(); if (principal == null) { throw new ForbiddenException("Not authenticated"); } int webhookLimit; if (principal.IsInRole(RoleType.Administrator)) { webhookLimit = 0; } else { webhookLimit = apiConfiguration.Options.WebhookLimit; } processMutex = new Mutex(false, this.GetMethodName()); return(await processMutex.Execute(new TimeSpan(0, 0, 2), async() => { if (webhookLimit > 0) { var count = await Context.WebhookRepository.CountAsync( e => e.UserId == principal.Identity.Name, cancellationToken); if (count >= webhookLimit) { throw new AmiException($"The webhook limit of {webhookLimit} has been reached."); } } Guid guid = idGenerator.GenerateId(); string enabledEvents = request.EnabledEvents.Contains(constants.WildcardCharacter) ? constants.WildcardCharacter.Embed(constants.ValueSeparator) : request.EnabledEvents.ToArray().ToString(",", constants.ValueSeparator); var entity = new WebhookEntity() { Id = guid, CreatedDate = DateTime.UtcNow, ModifiedDate = DateTime.UtcNow, Url = request.Url, ApiVersion = request.ApiVersion, Secret = request.Secret, EnabledEvents = enabledEvents, UserId = principal.Identity.Name }; Context.WebhookRepository.Add(entity); await Context.SaveChangesAsync(cancellationToken); var result = WebhookModel.Create(entity, constants); return result; })); }
/// <inheritdoc/> protected override async Task <ObjectModel> ProtectedHandleAsync(CreateObjectCommand request, CancellationToken cancellationToken) { var principal = PrincipalProvider.GetPrincipal(); if (principal == null) { throw new ForbiddenException("Not authenticated"); } int objectLimit = 0; if (principal.IsInRole(RoleType.User)) { objectLimit = apiConfiguration.Options.ObjectLimit; } else { objectLimit = apiConfiguration.Options.ObjectLimitAnonymous; } processMutex = new Mutex(false, this.GetMethodName()); return(await processMutex.Execute(new TimeSpan(0, 0, 2), async() => { if (objectLimit > 0) { var count = await Context.ObjectRepository.CountAsync(e => e.UserId == principal.Identity.Name, cancellationToken); if (count >= objectLimit) { throw new AmiException($"The object limit of {objectLimit} has been reached."); } } string fileExtension = fileSystem.Path.GetExtension(request.OriginalFilename); Guid guid = idGenerator.GenerateId(); string path = fileSystem.Path.Combine("Binary", "Objects", guid.ToString()); string destFilename = string.Concat(guid.ToString(), fileExtension); string destPath = fileSystem.Path.Combine(path, destFilename); fileSystem.Directory.CreateDirectory(fileSystem.Path.Combine(appConfiguration.Options.WorkingDirectory, path)); fileSystem.File.Move(request.SourcePath, fileSystem.Path.Combine(appConfiguration.Options.WorkingDirectory, destPath)); var entity = new ObjectEntity() { Id = guid, CreatedDate = DateTime.UtcNow, ModifiedDate = DateTime.UtcNow, OriginalFilename = request.OriginalFilename, SourcePath = destPath, UserId = principal.Identity.Name }; Context.ObjectRepository.Add(entity); await Context.SaveChangesAsync(cancellationToken); var result = ObjectModel.Create(entity); await Events.CreateAsync(entity.UserId, EventType.ObjectCreated, result, cancellationToken); await Gateway.NotifyGroupsAsync(entity.UserId, EventType.ObjectCreated, result, cancellationToken); return result; })); }
/// <inheritdoc/> protected override async Task <TaskModel> ProtectedHandleAsync(CreateTaskCommand request, CancellationToken cancellationToken) { var principal = PrincipalProvider.GetPrincipal(); if (principal == null) { throw new ForbiddenException("Not authenticated"); } if (request.Command.CommandType != CommandType.ProcessObjectCommand || request.Command.GetType() != typeof(ProcessObjectCommand)) { throw new NotSupportedException("The provided command type is not supported."); } var command = request.Command as ProcessObjectCommand; Guid objectId = Guid.Parse(command.Id); var objectOwnerId = Context.ObjectRepository.GetQuery(e => e.Id == objectId).Select(e => e.UserId).FirstOrDefault(); if (!AuthService.IsAuthorized(objectOwnerId)) { throw new ForbiddenException("Not authorized"); } processMutex = new Mutex(false, this.GetMethodName()); return(await processMutex.Execute(new TimeSpan(0, 0, 2), async() => { var activeCount = await Context.TaskRepository.CountAsync(e => e.ObjectId == objectId && (e.Status == (int)Domain.Enums.TaskStatus.Created || e.Status == (int)Domain.Enums.TaskStatus.Queued || e.Status == (int)Domain.Enums.TaskStatus.Processing)); if (activeCount > 0) { throw new AmiException("The specified object is already actively being processed."); } var position = await Context.TaskRepository.CountAsync(e => e.Status == (int)Domain.Enums.TaskStatus.Queued); var entity = new TaskEntity() { Id = idGenerator.GenerateId(), CreatedDate = DateTime.UtcNow, ModifiedDate = DateTime.UtcNow, QueuedDate = DateTime.UtcNow, Status = (int)Domain.Enums.TaskStatus.Queued, Progress = 0, Position = position, CommandType = (int)CommandType.ProcessObjectCommand, CommandSerialized = serializer.Serialize(command), UserId = principal.Identity.Name, ObjectId = objectId }; Context.TaskRepository.Add(entity); await Context.SaveChangesAsync(cancellationToken); var result = await mediator.Send(new GetByIdQuery() { Id = entity.Id.ToString() }); if (result == null) { throw new UnexpectedNullException($"The task '{entity.Id.ToString()}' could not be retrieved after creating it."); } if (entity.Object != null) { await Events.CreateAsync(entity.Object.UserId, EventType.TaskCreated, result, cancellationToken); await Gateway.NotifyGroupsAsync(entity.Object.UserId, EventType.TaskCreated, result, cancellationToken); } backgroundService.EnqueueTask(result.Id); return result; })); }