From 3d771249a1841fbc9230a14ca7c252d4566a33ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stanis=C5=82aw?= <62651497+staszkiet@users.noreply.github.com> Date: Fri, 13 Jun 2025 16:07:20 +0200 Subject: [PATCH 1/6] Add blob --- .../Common/Blob/Abstractions/IBlobService.cs | 6 + .../Common/Blob/Services/BlobService.cs | 29 ++ .../Events/Abstractions/IEventService.cs | 2 +- .../Events/Controllers/EventsController.cs | 2 +- .../Events/DTOs/Request/CreateEventDto.cs | 3 +- TickAPI/TickAPI/Events/Models/Event.cs | 1 + .../TickAPI/Events/Services/EventService.cs | 15 +- .../20250613140026_blobmigration.Designer.cs | 400 ++++++++++++++++++ .../20250613140026_blobmigration.cs | 28 ++ .../TickApiDbContextModelSnapshot.cs | 3 + TickAPI/TickAPI/Program.cs | 3 + TickAPI/TickAPI/TickAPI.csproj | 1 + 12 files changed, 487 insertions(+), 6 deletions(-) create mode 100644 TickAPI/TickAPI/Common/Blob/Abstractions/IBlobService.cs create mode 100644 TickAPI/TickAPI/Common/Blob/Services/BlobService.cs create mode 100644 TickAPI/TickAPI/Migrations/20250613140026_blobmigration.Designer.cs create mode 100644 TickAPI/TickAPI/Migrations/20250613140026_blobmigration.cs diff --git a/TickAPI/TickAPI/Common/Blob/Abstractions/IBlobService.cs b/TickAPI/TickAPI/Common/Blob/Abstractions/IBlobService.cs new file mode 100644 index 0000000..9ae6b1a --- /dev/null +++ b/TickAPI/TickAPI/Common/Blob/Abstractions/IBlobService.cs @@ -0,0 +1,6 @@ +namespace TickAPI.Common.Blob.Abstractions; + +public interface IBlobService +{ + public Task UploadToBlobContainerAsync(string name, IFormFile image); +} \ No newline at end of file diff --git a/TickAPI/TickAPI/Common/Blob/Services/BlobService.cs b/TickAPI/TickAPI/Common/Blob/Services/BlobService.cs new file mode 100644 index 0000000..f042a20 --- /dev/null +++ b/TickAPI/TickAPI/Common/Blob/Services/BlobService.cs @@ -0,0 +1,29 @@ +using Azure.Identity; +using Azure.Storage.Blobs; +using TickAPI.Common.Blob.Abstractions; + +namespace TickAPI.Common.Blob.Services; + +public class BlobService : IBlobService +{ + private string _connectionString; + private string _containerName; + + public BlobService(IConfiguration configuration) + { + _connectionString = configuration["BlobStorage:ConnectionString"]; + _containerName = configuration["BlobStorage:ContainerName"]; + } + + public async Task UploadToBlobContainerAsync(string name, IFormFile image) + { + var container = new BlobContainerClient(_connectionString, _containerName); + Guid id = Guid.NewGuid(); + string blobName = name + id; + var blob = container.GetBlobClient(blobName); + var stream = new MemoryStream(); + await image.CopyToAsync(stream); + var response = blob.Upload(stream); + return blob.Uri.ToString(); + } +} \ No newline at end of file diff --git a/TickAPI/TickAPI/Events/Abstractions/IEventService.cs b/TickAPI/TickAPI/Events/Abstractions/IEventService.cs index 9475a4f..af2f26c 100644 --- a/TickAPI/TickAPI/Events/Abstractions/IEventService.cs +++ b/TickAPI/TickAPI/Events/Abstractions/IEventService.cs @@ -15,7 +15,7 @@ public interface IEventService { public Task> CreateNewEventAsync(string name, string description, DateTime startDate, DateTime endDate, uint? minimumAge, CreateAddressDto createAddress, List categories, - List ticketTypes,EventStatus eventStatus, string organizerEmail); + List ticketTypes,EventStatus eventStatus, string organizerEmail, IFormFile? images); public Task>> GetOrganizerEventsAsync(Organizer organizer, int page, int pageSize, EventFiltersDto? eventFilters = null); public Task> GetOrganizerEventsPaginationDetailsAsync(Organizer organizer, int pageSize); public Task>> GetEventsAsync(int page, int pageSize, EventFiltersDto? eventFilters = null); diff --git a/TickAPI/TickAPI/Events/Controllers/EventsController.cs b/TickAPI/TickAPI/Events/Controllers/EventsController.cs index 1662943..04307f7 100644 --- a/TickAPI/TickAPI/Events/Controllers/EventsController.cs +++ b/TickAPI/TickAPI/Events/Controllers/EventsController.cs @@ -39,7 +39,7 @@ public async Task> CreateEvent([FromBody] C var newEventResult = await _eventService.CreateNewEventAsync(request.Name, request.Description, request.StartDate, request.EndDate, request.MinimumAge, request.CreateAddress, request.Categories - , request.TicketTypes ,request.EventStatus, email); + , request.TicketTypes ,request.EventStatus, email, request.Image); if (newEventResult.IsError) return newEventResult.ToObjectResult(); diff --git a/TickAPI/TickAPI/Events/DTOs/Request/CreateEventDto.cs b/TickAPI/TickAPI/Events/DTOs/Request/CreateEventDto.cs index 5b6f447..064ae42 100644 --- a/TickAPI/TickAPI/Events/DTOs/Request/CreateEventDto.cs +++ b/TickAPI/TickAPI/Events/DTOs/Request/CreateEventDto.cs @@ -14,5 +14,6 @@ public record CreateEventDto( List Categories, List TicketTypes, EventStatus EventStatus, - CreateAddressDto CreateAddress + CreateAddressDto CreateAddress, + IFormFile? Image ); \ No newline at end of file diff --git a/TickAPI/TickAPI/Events/Models/Event.cs b/TickAPI/TickAPI/Events/Models/Event.cs index 50ca434..8bdb9cd 100644 --- a/TickAPI/TickAPI/Events/Models/Event.cs +++ b/TickAPI/TickAPI/Events/Models/Event.cs @@ -18,6 +18,7 @@ public class Event public ICollection TicketTypes { get; set; } public EventStatus EventStatus { get; set; } public Address Address { get; set; } + public string? ImageUrl { get; set; } } public enum EventStatus diff --git a/TickAPI/TickAPI/Events/Services/EventService.cs b/TickAPI/TickAPI/Events/Services/EventService.cs index e6cd0cf..78a3732 100644 --- a/TickAPI/TickAPI/Events/Services/EventService.cs +++ b/TickAPI/TickAPI/Events/Services/EventService.cs @@ -21,6 +21,7 @@ using TickAPI.Tickets.Abstractions; using TickAPI.TicketTypes.DTOs.Request; using TickAPI.TicketTypes.Models; +using TickAPI.Common.Blob.Abstractions; namespace TickAPI.Events.Services; @@ -35,8 +36,9 @@ public class EventService : IEventService private readonly ITicketService _ticketService; private readonly ICustomerRepository _customerRepository; private readonly IMailService _mailService; + private readonly IBlobService _blobService; - public EventService(IEventRepository eventRepository, IOrganizerService organizerService, IAddressService addressService, IDateTimeService dateTimeService, IPaginationService paginationService, ICategoryService categoryService, ITicketService ticketService, ICustomerRepository customerRepository, IMailService mailService) + public EventService(IEventRepository eventRepository, IOrganizerService organizerService, IAddressService addressService, IDateTimeService dateTimeService, IPaginationService paginationService, ICategoryService categoryService, ITicketService ticketService, ICustomerRepository customerRepository, IMailService mailService, IBlobService blobService) { _eventRepository = eventRepository; _organizerService = organizerService; @@ -47,11 +49,12 @@ public EventService(IEventRepository eventRepository, IOrganizerService organize _ticketService = ticketService; _customerRepository = customerRepository; _mailService = mailService; + _blobService = blobService; } public async Task> CreateNewEventAsync(string name, string description, DateTime startDate, DateTime endDate, uint? minimumAge, CreateAddressDto createAddress, List categories, List ticketTypes, - EventStatus eventStatus, string organizerEmail) + EventStatus eventStatus, string organizerEmail, IFormFile? image) { var organizerResult = await _organizerService.GetOrganizerByEmailAsync(organizerEmail); if (!organizerResult.IsSuccess) @@ -82,7 +85,12 @@ public async Task> CreateNewEventAsync(string name, string descri { return Result.PropagateError(categoriesByNameResult); } - + + string? imageUrl = null; + if (image != null) + { + imageUrl = await _blobService.UploadToBlobContainerAsync(name, image); + } var @event = new Event { Name = name, @@ -95,6 +103,7 @@ public async Task> CreateNewEventAsync(string name, string descri Organizer = organizerResult.Value!, EventStatus = eventStatus, TicketTypes = ticketTypesConverted, + ImageUrl = imageUrl }; await _eventRepository.AddNewEventAsync(@event); return Result.Success(@event); diff --git a/TickAPI/TickAPI/Migrations/20250613140026_blobmigration.Designer.cs b/TickAPI/TickAPI/Migrations/20250613140026_blobmigration.Designer.cs new file mode 100644 index 0000000..255440b --- /dev/null +++ b/TickAPI/TickAPI/Migrations/20250613140026_blobmigration.Designer.cs @@ -0,0 +1,400 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using TickAPI.Common.TickApiDbContext; + +#nullable disable + +namespace TickAPI.Migrations +{ + [DbContext(typeof(TickApiDbContext))] + [Migration("20250613140026_blobmigration")] + partial class blobmigration + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "9.0.2") + .HasAnnotation("Relational:MaxIdentifierLength", 128); + + SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); + + modelBuilder.Entity("CategoryEvent", b => + { + b.Property("CategoriesId") + .HasColumnType("uniqueidentifier"); + + b.Property("EventsId") + .HasColumnType("uniqueidentifier"); + + b.HasKey("CategoriesId", "EventsId"); + + b.HasIndex("EventsId"); + + b.ToTable("CategoryEvent"); + }); + + modelBuilder.Entity("TickAPI.Addresses.Models.Address", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("City") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("Country") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("FlatNumber") + .HasColumnType("bigint"); + + b.Property("HouseNumber") + .HasColumnType("bigint"); + + b.Property("PostalCode") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("Street") + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.ToTable("Addresses"); + }); + + modelBuilder.Entity("TickAPI.Admins.Models.Admin", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("Email") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("Login") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.ToTable("Admins"); + }); + + modelBuilder.Entity("TickAPI.Categories.Models.Category", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("Name") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.ToTable("Categories"); + + b.HasData( + new + { + Id = new Guid("ec3daf69-baa9-4fcd-a674-c09884a57272"), + Name = "Music" + }, + new + { + Id = new Guid("de89dd76-3b29-43e1-8f4b-5278b1b8bde2"), + Name = "Sports" + }, + new + { + Id = new Guid("ea58370b-2a17-4770-abea-66399ad69fb8"), + Name = "Conferences" + }, + new + { + Id = new Guid("4a086d9e-59de-4fd1-a1b2-bd9b5eec797c"), + Name = "Theatre" + }, + new + { + Id = new Guid("5f8dbe65-30be-453f-8f22-191a11b2977b"), + Name = "Comedy" + }, + new + { + Id = new Guid("4421327a-4bc8-4706-bec0-666f78ed0c69"), + Name = "Workshops" + }); + }); + + modelBuilder.Entity("TickAPI.Customers.Models.Customer", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("Email") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("FirstName") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("LastName") + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.ToTable("Customers"); + }); + + modelBuilder.Entity("TickAPI.Events.Models.Event", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("AddressId") + .HasColumnType("uniqueidentifier"); + + b.Property("Description") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("EndDate") + .HasColumnType("datetime2"); + + b.Property("EventStatus") + .HasColumnType("int"); + + b.Property("ImageUrl") + .HasColumnType("nvarchar(max)"); + + b.Property("MinimumAge") + .HasColumnType("bigint"); + + b.Property("Name") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("OrganizerId") + .HasColumnType("uniqueidentifier"); + + b.Property("StartDate") + .HasColumnType("datetime2"); + + b.HasKey("Id"); + + b.HasIndex("AddressId"); + + b.HasIndex("OrganizerId"); + + b.ToTable("Events"); + }); + + modelBuilder.Entity("TickAPI.Organizers.Models.Organizer", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("DisplayName") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("Email") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("FirstName") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("IsVerified") + .HasColumnType("bit"); + + b.Property("LastName") + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.ToTable("Organizers"); + }); + + modelBuilder.Entity("TickAPI.TicketTypes.Models.TicketType", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("AvailableFrom") + .HasColumnType("datetime2"); + + b.Property("Currency") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("Description") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("EventId") + .HasColumnType("uniqueidentifier"); + + b.Property("MaxCount") + .HasColumnType("bigint"); + + b.Property("Price") + .HasColumnType("decimal(18,2)"); + + b.HasKey("Id"); + + b.HasIndex("EventId"); + + b.ToTable("TicketTypes"); + }); + + modelBuilder.Entity("TickAPI.Tickets.Models.Ticket", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("ForResell") + .HasColumnType("bit"); + + b.Property("NameOnTicket") + .HasColumnType("nvarchar(max)"); + + b.Property("OwnerId") + .HasColumnType("uniqueidentifier"); + + b.Property("ResellCurrency") + .HasColumnType("nvarchar(max)"); + + b.Property("ResellPrice") + .HasColumnType("decimal(18,2)"); + + b.Property("Seats") + .HasColumnType("nvarchar(max)"); + + b.Property("TypeId") + .HasColumnType("uniqueidentifier"); + + b.Property("Used") + .HasColumnType("bit"); + + b.HasKey("Id"); + + b.HasIndex("OwnerId"); + + b.HasIndex("TypeId"); + + b.ToTable("Tickets"); + }); + + modelBuilder.Entity("CategoryEvent", b => + { + b.HasOne("TickAPI.Categories.Models.Category", null) + .WithMany() + .HasForeignKey("CategoriesId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("TickAPI.Events.Models.Event", null) + .WithMany() + .HasForeignKey("EventsId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("TickAPI.Events.Models.Event", b => + { + b.HasOne("TickAPI.Addresses.Models.Address", "Address") + .WithMany() + .HasForeignKey("AddressId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("TickAPI.Organizers.Models.Organizer", "Organizer") + .WithMany("Events") + .HasForeignKey("OrganizerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Address"); + + b.Navigation("Organizer"); + }); + + modelBuilder.Entity("TickAPI.TicketTypes.Models.TicketType", b => + { + b.HasOne("TickAPI.Events.Models.Event", "Event") + .WithMany("TicketTypes") + .HasForeignKey("EventId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Event"); + }); + + modelBuilder.Entity("TickAPI.Tickets.Models.Ticket", b => + { + b.HasOne("TickAPI.Customers.Models.Customer", "Owner") + .WithMany("Tickets") + .HasForeignKey("OwnerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("TickAPI.TicketTypes.Models.TicketType", "Type") + .WithMany("Tickets") + .HasForeignKey("TypeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Owner"); + + b.Navigation("Type"); + }); + + modelBuilder.Entity("TickAPI.Customers.Models.Customer", b => + { + b.Navigation("Tickets"); + }); + + modelBuilder.Entity("TickAPI.Events.Models.Event", b => + { + b.Navigation("TicketTypes"); + }); + + modelBuilder.Entity("TickAPI.Organizers.Models.Organizer", b => + { + b.Navigation("Events"); + }); + + modelBuilder.Entity("TickAPI.TicketTypes.Models.TicketType", b => + { + b.Navigation("Tickets"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/TickAPI/TickAPI/Migrations/20250613140026_blobmigration.cs b/TickAPI/TickAPI/Migrations/20250613140026_blobmigration.cs new file mode 100644 index 0000000..d39274a --- /dev/null +++ b/TickAPI/TickAPI/Migrations/20250613140026_blobmigration.cs @@ -0,0 +1,28 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace TickAPI.Migrations +{ + /// + public partial class blobmigration : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "ImageUrl", + table: "Events", + type: "nvarchar(max)", + nullable: true); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "ImageUrl", + table: "Events"); + } + } +} diff --git a/TickAPI/TickAPI/Migrations/TickApiDbContextModelSnapshot.cs b/TickAPI/TickAPI/Migrations/TickApiDbContextModelSnapshot.cs index 71d888e..18032ed 100644 --- a/TickAPI/TickAPI/Migrations/TickApiDbContextModelSnapshot.cs +++ b/TickAPI/TickAPI/Migrations/TickApiDbContextModelSnapshot.cs @@ -179,6 +179,9 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Property("EventStatus") .HasColumnType("int"); + b.Property("ImageUrl") + .HasColumnType("nvarchar(max)"); + b.Property("MinimumAge") .HasColumnType("bigint"); diff --git a/TickAPI/TickAPI/Program.cs b/TickAPI/TickAPI/Program.cs index 53441b3..5a983d6 100644 --- a/TickAPI/TickAPI/Program.cs +++ b/TickAPI/TickAPI/Program.cs @@ -33,6 +33,8 @@ using TickAPI.Categories.Abstractions; using TickAPI.Categories.Respositories; using TickAPI.Categories.Services; +using TickAPI.Common.Blob.Abstractions; +using TickAPI.Common.Blob.Services; using TickAPI.Common.Claims.Abstractions; using TickAPI.Common.Claims.Services; using TickAPI.Common.Redis.Abstractions; @@ -146,6 +148,7 @@ builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped(); +builder.Services.AddScoped(); // Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle builder.Services.AddEndpointsApiExplorer(); diff --git a/TickAPI/TickAPI/TickAPI.csproj b/TickAPI/TickAPI/TickAPI.csproj index fb79365..adc0f04 100644 --- a/TickAPI/TickAPI/TickAPI.csproj +++ b/TickAPI/TickAPI/TickAPI.csproj @@ -8,6 +8,7 @@ + From fcb5fbf8e1da28e39257fca83f106058897b9196 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stanis=C5=82aw?= <62651497+staszkiet@users.noreply.github.com> Date: Fri, 13 Jun 2025 16:18:55 +0200 Subject: [PATCH 2/6] appsettings example --- TickAPI/TickAPI/appsettings.example.json | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/TickAPI/TickAPI/appsettings.example.json b/TickAPI/TickAPI/appsettings.example.json index c7e46ab..cb999f1 100644 --- a/TickAPI/TickAPI/appsettings.example.json +++ b/TickAPI/TickAPI/appsettings.example.json @@ -37,5 +37,9 @@ "ShoppingCart": { "SyncIntervalMinutes": 5, "LifetimeMinutes": 15 + }, + "BlobStorage": { + "ConnectionString": "string", + "ContainerName": "resellio" } } \ No newline at end of file From c3c28c93104149a9d8fd87f9b6b666c56bb1f362 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stanis=C5=82aw?= <62651497+staszkiet@users.noreply.github.com> Date: Fri, 13 Jun 2025 21:41:17 +0200 Subject: [PATCH 3/6] Working blob --- .../TickAPI/Common/Blob/Services/BlobService.cs | 15 ++++++++++++++- .../Events/Controllers/EventsController.cs | 2 +- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/TickAPI/TickAPI/Common/Blob/Services/BlobService.cs b/TickAPI/TickAPI/Common/Blob/Services/BlobService.cs index f042a20..d1af679 100644 --- a/TickAPI/TickAPI/Common/Blob/Services/BlobService.cs +++ b/TickAPI/TickAPI/Common/Blob/Services/BlobService.cs @@ -1,5 +1,6 @@ using Azure.Identity; using Azure.Storage.Blobs; +using Azure.Storage.Blobs.Models; using TickAPI.Common.Blob.Abstractions; namespace TickAPI.Common.Blob.Services; @@ -21,9 +22,21 @@ public async Task UploadToBlobContainerAsync(string name, IFormFile imag Guid id = Guid.NewGuid(); string blobName = name + id; var blob = container.GetBlobClient(blobName); + var contentType = image.ContentType; var stream = new MemoryStream(); await image.CopyToAsync(stream); - var response = blob.Upload(stream); + stream.Position = 0; + + var uploadOptions = new BlobUploadOptions + { + HttpHeaders = new BlobHttpHeaders + { + ContentType = contentType + } + }; + + var response = await blob.UploadAsync(stream, uploadOptions); + return blob.Uri.ToString(); } } \ No newline at end of file diff --git a/TickAPI/TickAPI/Events/Controllers/EventsController.cs b/TickAPI/TickAPI/Events/Controllers/EventsController.cs index 04307f7..9cdaa44 100644 --- a/TickAPI/TickAPI/Events/Controllers/EventsController.cs +++ b/TickAPI/TickAPI/Events/Controllers/EventsController.cs @@ -28,7 +28,7 @@ public EventsController(IEventService eventService, IClaimsService claimsService [AuthorizeWithPolicy(AuthPolicies.VerifiedOrganizerPolicy)] [HttpPost] - public async Task> CreateEvent([FromBody] CreateEventDto request) + public async Task> CreateEvent([FromForm] CreateEventDto request) { var emailResult = _claimsService.GetEmailFromClaims(User.Claims); if (emailResult.IsError) From b71fea8a96e5bf02c67fac981eb9307c44564b05 Mon Sep 17 00:00:00 2001 From: staszkiet Date: Sat, 14 Jun 2025 18:06:28 +0200 Subject: [PATCH 4/6] minor fixes --- .../Controllers/EventsControllerTests.cs | 6 +- .../Events/Services/EventServiceTests.cs | 74 ++++++++++++------- TickAPI/TickAPI.Tests/Events/Utils.cs | 6 +- .../Common/Blob/Abstractions/IBlobService.cs | 2 +- .../Common/Blob/Services/BlobService.cs | 14 +--- .../Response/GetEventDetailsResponseDto.cs | 3 +- .../DTOs/Response/GetEventResponseDto.cs | 3 +- .../TickAPI/Events/Services/EventService.cs | 7 +- 8 files changed, 66 insertions(+), 49 deletions(-) diff --git a/TickAPI/TickAPI.Tests/Events/Controllers/EventsControllerTests.cs b/TickAPI/TickAPI.Tests/Events/Controllers/EventsControllerTests.cs index 6d8b112..ef3fad5 100644 --- a/TickAPI/TickAPI.Tests/Events/Controllers/EventsControllerTests.cs +++ b/TickAPI/TickAPI.Tests/Events/Controllers/EventsControllerTests.cs @@ -45,11 +45,11 @@ public async Task CreateEvent_WhenDataIsValid_ShouldReturnSuccess() new CreateEventTicketTypeDto("V.I.P", 10, 500.9m, "zł", new DateTime(2025, 5, 10)), ]; CreateAddressDto createAddress = new CreateAddressDto("United States", "New York", "Main st", 20, null, "00-000"); - CreateEventDto eventDto = new CreateEventDto(name, description, startDate, endDate, minimumAge, categories, ticketTypes, eventStatus, createAddress); + CreateEventDto eventDto = new CreateEventDto(name, description, startDate, endDate, minimumAge, categories, ticketTypes, eventStatus, createAddress, null); var eventServiceMock = new Mock(); eventServiceMock - .Setup(m => m.CreateNewEventAsync(name, description, startDate, endDate, minimumAge, createAddress, categories , ticketTypes, eventStatus, email)) + .Setup(m => m.CreateNewEventAsync(name, description, startDate, endDate, minimumAge, createAddress, categories , ticketTypes, eventStatus, email, null)) .ReturnsAsync(Result.Success(new Event())); var claims = new List @@ -123,7 +123,7 @@ public async Task CreateEvent_WhenMissingEmailClaims_ShouldReturnBadRequest() }; // act - var res = await sut.CreateEvent(new CreateEventDto(name, description, startDate, endDate, minimumAge, categories, ticketTypes, eventStatus, createAddress)); + var res = await sut.CreateEvent(new CreateEventDto(name, description, startDate, endDate, minimumAge, categories, ticketTypes, eventStatus, createAddress, null)); // Assert var result = Assert.IsType>(res); diff --git a/TickAPI/TickAPI.Tests/Events/Services/EventServiceTests.cs b/TickAPI/TickAPI.Tests/Events/Services/EventServiceTests.cs index 9d335c6..ad14287 100644 --- a/TickAPI/TickAPI.Tests/Events/Services/EventServiceTests.cs +++ b/TickAPI/TickAPI.Tests/Events/Services/EventServiceTests.cs @@ -9,6 +9,7 @@ using TickAPI.Categories.Abstractions; using TickAPI.Categories.DTOs.Request; using TickAPI.Categories.Models; +using TickAPI.Common.Blob.Abstractions; using TickAPI.Common.Mail.Abstractions; using TickAPI.Common.Results; using TickAPI.Events.Models; @@ -116,10 +117,10 @@ public async Task CreateNewEventAsync_WhenEventDataIsValid_ShouldReturnNewEvent( var customerRepositoryMock = new Mock(); var mailServiceMock = new Mock(); - - var sut = new EventService(eventRepositoryMock.Object, organizerServiceMock.Object, addressServiceMock.Object, dateTimeServiceMock.Object, paginationServiceMock.Object, categoryServiceMock.Object, ticketServiceMock.Object, customerRepositoryMock.Object, mailServiceMock.Object); + var blobServiceMock = new Mock(); + var sut = new EventService(eventRepositoryMock.Object, organizerServiceMock.Object, addressServiceMock.Object, dateTimeServiceMock.Object, paginationServiceMock.Object, categoryServiceMock.Object, ticketServiceMock.Object, customerRepositoryMock.Object, mailServiceMock.Object, blobServiceMock.Object); // Act - var result = await sut.CreateNewEventAsync(name, description, startDate, endDate, minimumAge, createAddress, categories, ticketTypes, eventStatus, organizerEmail); + var result = await sut.CreateNewEventAsync(name, description, startDate, endDate, minimumAge, createAddress, categories, ticketTypes, eventStatus, organizerEmail, null); // Assert Assert.True(result.IsSuccess); @@ -191,12 +192,13 @@ public async Task CreateNewEventAsync_WhenEndDateIsBeforeStartDate_ShouldReturnB var customerRepositoryMock = new Mock(); var mailServiceMock = new Mock(); + var blobServiceMock = new Mock(); - var sut = new EventService(eventRepositoryMock.Object, organizerServiceMock.Object, addressServiceMock.Object, dateTimeServiceMock.Object, paginationServiceMock.Object, categoryServiceMock.Object, ticketServiceMock.Object, customerRepositoryMock.Object, mailServiceMock.Object); + var sut = new EventService(eventRepositoryMock.Object, organizerServiceMock.Object, addressServiceMock.Object, dateTimeServiceMock.Object, paginationServiceMock.Object, categoryServiceMock.Object, ticketServiceMock.Object, customerRepositoryMock.Object, mailServiceMock.Object, blobServiceMock.Object); // Act - var res = await sut.CreateNewEventAsync(name, description, startDate, endDate, minimumAge, createAddress, categories, ticketTypes, eventStatus, organizerEmail); + var res = await sut.CreateNewEventAsync(name, description, startDate, endDate, minimumAge, createAddress, categories, ticketTypes, eventStatus, organizerEmail, null); // Assert Assert.False(res.IsSuccess); @@ -249,11 +251,11 @@ public async Task CreateNewEventAsync_WhenTicketTypeAvailabilityIsAfterEventsEnd var customerRepositoryMock = new Mock(); var mailServiceMock = new Mock(); - - var sut = new EventService(eventRepositoryMock.Object, organizerServiceMock.Object, addressServiceMock.Object, dateTimeServiceMock.Object, paginationServiceMock.Object, categoryServiceMock.Object, ticketServiceMock.Object, customerRepositoryMock.Object, mailServiceMock.Object); + var blobServiceMock = new Mock(); + var sut = new EventService(eventRepositoryMock.Object, organizerServiceMock.Object, addressServiceMock.Object, dateTimeServiceMock.Object, paginationServiceMock.Object, categoryServiceMock.Object, ticketServiceMock.Object, customerRepositoryMock.Object, mailServiceMock.Object, blobServiceMock.Object); // Act - var res = await sut.CreateNewEventAsync(name, description, startDate, endDate, minimumAge, createAddress, categories, ticketTypes, eventStatus, organizerEmail); + var res = await sut.CreateNewEventAsync(name, description, startDate, endDate, minimumAge, createAddress, categories, ticketTypes, eventStatus, organizerEmail, null); // Assert Assert.False(res.IsSuccess); @@ -305,11 +307,12 @@ public async Task CreateNewEventAsync_WhenStartDateIsBeforeNow_ShouldReturnBadRe var customerRepositoryMock = new Mock(); var mailServiceMock = new Mock(); + var blobServiceMock = new Mock(); - var sut = new EventService(eventRepositoryMock.Object, organizerServiceMock.Object, addressServiceMock.Object, dateTimeServiceMock.Object, paginationServiceMock.Object, categoryServiceMock.Object, ticketServiceMock.Object, customerRepositoryMock.Object, mailServiceMock.Object); + var sut = new EventService(eventRepositoryMock.Object, organizerServiceMock.Object, addressServiceMock.Object, dateTimeServiceMock.Object, paginationServiceMock.Object, categoryServiceMock.Object, ticketServiceMock.Object, customerRepositoryMock.Object, mailServiceMock.Object, blobServiceMock.Object); // Act - var res = await sut.CreateNewEventAsync(name, description, startDate, endDate, minimumAge, createAddress, categories, ticketTypes, eventStatus, organizerEmail); + var res = await sut.CreateNewEventAsync(name, description, startDate, endDate, minimumAge, createAddress, categories, ticketTypes, eventStatus, organizerEmail, null); // Assert Assert.False(res.IsSuccess); @@ -376,8 +379,9 @@ public async Task GetOrganizerEvents_WhenPaginationSucceeds_ShouldReturnPaginate var customerRepositoryMock = new Mock(); var mailServiceMock = new Mock(); + var blobServiceMock = new Mock(); - var sut = new EventService(eventRepositoryMock.Object, organizerServiceMock.Object, addressServiceMock.Object, dateTimeServiceMock.Object, paginationServiceMock.Object, categoryServiceMock.Object, ticketServiceMock.Object, customerRepositoryMock.Object, mailServiceMock.Object); + var sut = new EventService(eventRepositoryMock.Object, organizerServiceMock.Object, addressServiceMock.Object, dateTimeServiceMock.Object, paginationServiceMock.Object, categoryServiceMock.Object, ticketServiceMock.Object, customerRepositoryMock.Object, mailServiceMock.Object, blobServiceMock.Object); // Act var result = await sut.GetOrganizerEventsAsync(organizer, page, pageSize); @@ -429,8 +433,9 @@ public async Task GetOrganizerEvents_WhenPaginationFails_ShouldPropagateError() var customerRepositoryMock = new Mock(); var mailServiceMock = new Mock(); + var blobServiceMock = new Mock(); - var sut = new EventService(eventRepositoryMock.Object, organizerServiceMock.Object, addressServiceMock.Object, dateTimeServiceMock.Object, paginationServiceMock.Object, categoryServiceMock.Object, ticketServiceMock.Object, customerRepositoryMock.Object, mailServiceMock.Object); + var sut = new EventService(eventRepositoryMock.Object, organizerServiceMock.Object, addressServiceMock.Object, dateTimeServiceMock.Object, paginationServiceMock.Object, categoryServiceMock.Object, ticketServiceMock.Object, customerRepositoryMock.Object, mailServiceMock.Object, blobServiceMock.Object); // Act var result = await sut.GetOrganizerEventsAsync(organizer, page, pageSize); @@ -495,8 +500,9 @@ public async Task GetEventsAsync_WhenPaginationSucceeds_ShouldReturnPaginatedEve var customerRepositoryMock = new Mock(); var mailServiceMock = new Mock(); + var blobServiceMock = new Mock(); - var sut = new EventService(eventRepositoryMock.Object, organizerServiceMock.Object, addressServiceMock.Object, dateTimeServiceMock.Object, paginationServiceMock.Object, categoryServiceMock.Object, ticketServiceMock.Object, customerRepositoryMock.Object, mailServiceMock.Object); + var sut = new EventService(eventRepositoryMock.Object, organizerServiceMock.Object, addressServiceMock.Object, dateTimeServiceMock.Object, paginationServiceMock.Object, categoryServiceMock.Object, ticketServiceMock.Object, customerRepositoryMock.Object, mailServiceMock.Object, blobServiceMock.Object); // Act var result = await sut.GetEventsAsync(page, pageSize); @@ -543,8 +549,9 @@ public async Task GetEventsAsync_WhenPaginationFails_ShouldPropagateError() var customerRepositoryMock = new Mock(); var mailServiceMock = new Mock(); + var blobServiceMock = new Mock(); - var sut = new EventService(eventRepositoryMock.Object, organizerServiceMock.Object, addressServiceMock.Object, dateTimeServiceMock.Object, paginationServiceMock.Object, categoryServiceMock.Object, ticketServiceMock.Object, customerRepositoryMock.Object, mailServiceMock.Object); + var sut = new EventService(eventRepositoryMock.Object, organizerServiceMock.Object, addressServiceMock.Object, dateTimeServiceMock.Object, paginationServiceMock.Object, categoryServiceMock.Object, ticketServiceMock.Object, customerRepositoryMock.Object, mailServiceMock.Object, blobServiceMock.Object); // Act var result = await sut.GetEventsAsync(page, pageSize); @@ -585,8 +592,9 @@ public async Task GetEventsPaginationDetailsAsync_WhenSuccessful_ShouldReturnPag var customerRepositoryMock = new Mock(); var mailServiceMock = new Mock(); + var blobServiceMock = new Mock(); - var sut = new EventService(eventRepositoryMock.Object, organizerServiceMock.Object, addressServiceMock.Object, dateTimeServiceMock.Object, paginationServiceMock.Object, categoryServiceMock.Object, ticketServiceMock.Object, customerRepositoryMock.Object, mailServiceMock.Object); + var sut = new EventService(eventRepositoryMock.Object, organizerServiceMock.Object, addressServiceMock.Object, dateTimeServiceMock.Object, paginationServiceMock.Object, categoryServiceMock.Object, ticketServiceMock.Object, customerRepositoryMock.Object, mailServiceMock.Object, blobServiceMock.Object); // Act var result = await sut.GetEventsPaginationDetailsAsync(pageSize); @@ -626,8 +634,9 @@ public async Task GetEventsPaginationDetailsAsync_WhenFails_ShouldReturnError() var customerRepositoryMock = new Mock(); var mailServiceMock = new Mock(); - var sut = new EventService(eventRepositoryMock.Object, organizerServiceMock.Object, addressServiceMock.Object, dateTimeServiceMock.Object, paginationServiceMock.Object, categoryServiceMock.Object, ticketServiceMock.Object, customerRepositoryMock.Object, mailServiceMock.Object); + var blobServiceMock = new Mock(); + var sut = new EventService(eventRepositoryMock.Object, organizerServiceMock.Object, addressServiceMock.Object, dateTimeServiceMock.Object, paginationServiceMock.Object, categoryServiceMock.Object, ticketServiceMock.Object, customerRepositoryMock.Object, mailServiceMock.Object, blobServiceMock.Object); // Act var result = await sut.GetEventsPaginationDetailsAsync(pageSize); @@ -665,8 +674,9 @@ public async Task GetEventDetailsAsync_WhenSuccessful_ShouldReturnEventDetails() var customerRepositoryMock = new Mock(); var mailServiceMock = new Mock(); - var sut = new EventService(eventRepositoryMock.Object, organizerServiceMock.Object, addressServiceMock.Object, dateTimeServiceMock.Object, paginationServiceMock.Object, categoryServiceMock.Object, ticketServiceMock.Object, customerRepositoryMock.Object, mailServiceMock.Object); + var blobServiceMock = new Mock(); + var sut = new EventService(eventRepositoryMock.Object, organizerServiceMock.Object, addressServiceMock.Object, dateTimeServiceMock.Object, paginationServiceMock.Object, categoryServiceMock.Object, ticketServiceMock.Object, customerRepositoryMock.Object, mailServiceMock.Object, blobServiceMock.Object); // Act var result = await sut.GetEventDetailsAsync(@event.Id); @@ -704,8 +714,9 @@ public async Task GetEventDetailsAsync_WhenFails_ShouldReturnEventError() var customerRepositoryMock = new Mock(); var mailServiceMock = new Mock(); - var sut = new EventService(eventRepositoryMock.Object, organizerServiceMock.Object, addressServiceMock.Object, dateTimeServiceMock.Object, paginationServiceMock.Object, categoryServiceMock.Object, ticketServiceMock.Object, customerRepositoryMock.Object, mailServiceMock.Object); + var blobServiceMock = new Mock(); + var sut = new EventService(eventRepositoryMock.Object, organizerServiceMock.Object, addressServiceMock.Object, dateTimeServiceMock.Object, paginationServiceMock.Object, categoryServiceMock.Object, ticketServiceMock.Object, customerRepositoryMock.Object, mailServiceMock.Object, blobServiceMock.Object); // Act var result = await sut.GetEventDetailsAsync(@event.Id); @@ -811,8 +822,9 @@ public async Task EditEventAsync_WhenDataValid_ShouldUpdateEvent() var customerRepositoryMock = new Mock(); var mailServiceMock = new Mock(); - var sut = new EventService(eventRepositoryMock.Object, organizerServiceMock.Object, addressServiceMock.Object, dateTimeServiceMock.Object, paginationServiceMock.Object, categoryServiceMock.Object, ticketServiceMock.Object, customerRepositoryMock.Object, mailServiceMock.Object); + var blobServiceMock = new Mock(); + var sut = new EventService(eventRepositoryMock.Object, organizerServiceMock.Object, addressServiceMock.Object, dateTimeServiceMock.Object, paginationServiceMock.Object, categoryServiceMock.Object, ticketServiceMock.Object, customerRepositoryMock.Object, mailServiceMock.Object, blobServiceMock.Object); // Act var result = await sut.EditEventAsync( organizer, @@ -880,8 +892,9 @@ public async Task EditEventAsync_WhenEventNotFound_ShouldReturnError() var customerRepositoryMock = new Mock(); var mailServiceMock = new Mock(); - var sut = new EventService(eventRepositoryMock.Object, organizerServiceMock.Object, addressServiceMock.Object, dateTimeServiceMock.Object, paginationServiceMock.Object, categoryServiceMock.Object, ticketServiceMock.Object, customerRepositoryMock.Object, mailServiceMock.Object); + var blobServiceMock = new Mock(); + var sut = new EventService(eventRepositoryMock.Object, organizerServiceMock.Object, addressServiceMock.Object, dateTimeServiceMock.Object, paginationServiceMock.Object, categoryServiceMock.Object, ticketServiceMock.Object, customerRepositoryMock.Object, mailServiceMock.Object, blobServiceMock.Object); // Act var result = await sut.EditEventAsync( organizer, @@ -952,8 +965,9 @@ public async Task EditEventAsync_WhenEndDateBeforeStartDate_ShouldReturnBadReque var customerRepositoryMock = new Mock(); var mailServiceMock = new Mock(); - var sut = new EventService(eventRepositoryMock.Object, organizerServiceMock.Object, addressServiceMock.Object, dateTimeServiceMock.Object, paginationServiceMock.Object, categoryServiceMock.Object, ticketServiceMock.Object, customerRepositoryMock.Object, mailServiceMock.Object); + var blobServiceMock = new Mock(); + var sut = new EventService(eventRepositoryMock.Object, organizerServiceMock.Object, addressServiceMock.Object, dateTimeServiceMock.Object, paginationServiceMock.Object, categoryServiceMock.Object, ticketServiceMock.Object, customerRepositoryMock.Object, mailServiceMock.Object, blobServiceMock.Object); // Act var result = await sut.EditEventAsync( organizer, @@ -1025,8 +1039,9 @@ public async Task EditEventAsync_WhenStartDateChangedAndInPast_ShouldReturnBadRe var customerRepositoryMock = new Mock(); var mailServiceMock = new Mock(); - var sut = new EventService(eventRepositoryMock.Object, organizerServiceMock.Object, addressServiceMock.Object, dateTimeServiceMock.Object, paginationServiceMock.Object, categoryServiceMock.Object, ticketServiceMock.Object, customerRepositoryMock.Object, mailServiceMock.Object); + var blobServiceMock = new Mock(); + var sut = new EventService(eventRepositoryMock.Object, organizerServiceMock.Object, addressServiceMock.Object, dateTimeServiceMock.Object, paginationServiceMock.Object, categoryServiceMock.Object, ticketServiceMock.Object, customerRepositoryMock.Object, mailServiceMock.Object, blobServiceMock.Object); // Act var result = await sut.EditEventAsync( organizer, @@ -1142,8 +1157,9 @@ public async Task EditEventAsync_StartDateNotChangedAndInPast_ShouldUpdateEvent( var customerRepositoryMock = new Mock(); var mailServiceMock = new Mock(); - var sut = new EventService(eventRepositoryMock.Object, organizerServiceMock.Object, addressServiceMock.Object, dateTimeServiceMock.Object, paginationServiceMock.Object, categoryServiceMock.Object, ticketServiceMock.Object, customerRepositoryMock.Object, mailServiceMock.Object); + var blobServiceMock = new Mock(); + var sut = new EventService(eventRepositoryMock.Object, organizerServiceMock.Object, addressServiceMock.Object, dateTimeServiceMock.Object, paginationServiceMock.Object, categoryServiceMock.Object, ticketServiceMock.Object, customerRepositoryMock.Object, mailServiceMock.Object, blobServiceMock.Object); // Act var result = await sut.EditEventAsync( organizer, @@ -1228,8 +1244,9 @@ public async Task EditEventAsync_WhenTicketTypeAvailableFromAfterEndDate_ShouldR var customerRepositoryMock = new Mock(); var mailServiceMock = new Mock(); - var sut = new EventService(eventRepositoryMock.Object, organizerServiceMock.Object, addressServiceMock.Object, dateTimeServiceMock.Object, paginationServiceMock.Object, categoryServiceMock.Object, ticketServiceMock.Object, customerRepositoryMock.Object, mailServiceMock.Object); + var blobServiceMock = new Mock(); + var sut = new EventService(eventRepositoryMock.Object, organizerServiceMock.Object, addressServiceMock.Object, dateTimeServiceMock.Object, paginationServiceMock.Object, categoryServiceMock.Object, ticketServiceMock.Object, customerRepositoryMock.Object, mailServiceMock.Object, blobServiceMock.Object); // Act var result = await sut.EditEventAsync( organizer, @@ -1304,8 +1321,9 @@ public async Task EditEventAsync_WhenAddressServiceFails_ShouldPropagateError() var customerRepositoryMock = new Mock(); var mailServiceMock = new Mock(); - var sut = new EventService(eventRepositoryMock.Object, organizerServiceMock.Object, addressServiceMock.Object, dateTimeServiceMock.Object, paginationServiceMock.Object, categoryServiceMock.Object, ticketServiceMock.Object, customerRepositoryMock.Object, mailServiceMock.Object); + var blobServiceMock = new Mock(); + var sut = new EventService(eventRepositoryMock.Object, organizerServiceMock.Object, addressServiceMock.Object, dateTimeServiceMock.Object, paginationServiceMock.Object, categoryServiceMock.Object, ticketServiceMock.Object, customerRepositoryMock.Object, mailServiceMock.Object, blobServiceMock.Object); // Act var result = await sut.EditEventAsync( organizer, @@ -1393,8 +1411,9 @@ public async Task EditEventAsync_WhenCategoryServiceFails_ShouldPropagateError() var customerRepositoryMock = new Mock(); var mailServiceMock = new Mock(); - var sut = new EventService(eventRepositoryMock.Object, organizerServiceMock.Object, addressServiceMock.Object, dateTimeServiceMock.Object, paginationServiceMock.Object, categoryServiceMock.Object, ticketServiceMock.Object, customerRepositoryMock.Object, mailServiceMock.Object); + var blobServiceMock = new Mock(); + var sut = new EventService(eventRepositoryMock.Object, organizerServiceMock.Object, addressServiceMock.Object, dateTimeServiceMock.Object, paginationServiceMock.Object, categoryServiceMock.Object, ticketServiceMock.Object, customerRepositoryMock.Object, mailServiceMock.Object, blobServiceMock.Object); // Act var result = await sut.EditEventAsync( organizer, @@ -1490,8 +1509,9 @@ public async Task EditEventAsync_WhenSaveEventFails_ShouldPropagateError() var customerRepositoryMock = new Mock(); var mailServiceMock = new Mock(); - var sut = new EventService(eventRepositoryMock.Object, organizerServiceMock.Object, addressServiceMock.Object, dateTimeServiceMock.Object, paginationServiceMock.Object, categoryServiceMock.Object, ticketServiceMock.Object, customerRepositoryMock.Object, mailServiceMock.Object); + var blobServiceMock = new Mock(); + var sut = new EventService(eventRepositoryMock.Object, organizerServiceMock.Object, addressServiceMock.Object, dateTimeServiceMock.Object, paginationServiceMock.Object, categoryServiceMock.Object, ticketServiceMock.Object, customerRepositoryMock.Object, mailServiceMock.Object, blobServiceMock.Object); // Act var result = await sut.EditEventAsync( organizer, diff --git a/TickAPI/TickAPI.Tests/Events/Utils.cs b/TickAPI/TickAPI.Tests/Events/Utils.cs index 1fa0c76..7980a47 100644 --- a/TickAPI/TickAPI.Tests/Events/Utils.cs +++ b/TickAPI/TickAPI.Tests/Events/Utils.cs @@ -51,7 +51,8 @@ public static GetEventResponseDto CreateSampleEventResponseDto(string name) new GetEventResponsePriceInfoDto(300, "PLN"), [new GetEventResponseCategoryDto("Test")], EventStatus.TicketsAvailable, - new GetEventResponseAddressDto("United States", "New York", "10001", "Main St", 123, null) + new GetEventResponseAddressDto("United States", "New York", "10001", "Main St", 123, null), + null ); } @@ -69,7 +70,8 @@ [new GetEventResponseCategoryDto("Test")], new GetEventDetailsResponseTicketTypeDto(Guid.Parse("7ecfc61a-32d2-4124-a95c-cb5834a49990"), "Description #2", 300, "PLN", new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc), 30), new GetEventDetailsResponseTicketTypeDto(Guid.Parse("7be2ae57-2394-4854-bf11-9567ce7e0ab6"), "Description #3", 200, "PLN", new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc), 20)], EventStatus.TicketsAvailable, - new GetEventResponseAddressDto("United States", "New York", "10001", "Main St", 123, null) + new GetEventResponseAddressDto("United States", "New York", "10001", "Main St", 123, null), + null ); } } diff --git a/TickAPI/TickAPI/Common/Blob/Abstractions/IBlobService.cs b/TickAPI/TickAPI/Common/Blob/Abstractions/IBlobService.cs index 9ae6b1a..f253b67 100644 --- a/TickAPI/TickAPI/Common/Blob/Abstractions/IBlobService.cs +++ b/TickAPI/TickAPI/Common/Blob/Abstractions/IBlobService.cs @@ -2,5 +2,5 @@ public interface IBlobService { - public Task UploadToBlobContainerAsync(string name, IFormFile image); + public Task UploadToBlobContainerAsync(IFormFile image); } \ No newline at end of file diff --git a/TickAPI/TickAPI/Common/Blob/Services/BlobService.cs b/TickAPI/TickAPI/Common/Blob/Services/BlobService.cs index d1af679..9d79bfa 100644 --- a/TickAPI/TickAPI/Common/Blob/Services/BlobService.cs +++ b/TickAPI/TickAPI/Common/Blob/Services/BlobService.cs @@ -16,26 +16,18 @@ public BlobService(IConfiguration configuration) _containerName = configuration["BlobStorage:ContainerName"]; } - public async Task UploadToBlobContainerAsync(string name, IFormFile image) + public async Task UploadToBlobContainerAsync(IFormFile image) { var container = new BlobContainerClient(_connectionString, _containerName); Guid id = Guid.NewGuid(); - string blobName = name + id; + string blobName = id.ToString(); var blob = container.GetBlobClient(blobName); - var contentType = image.ContentType; var stream = new MemoryStream(); await image.CopyToAsync(stream); stream.Position = 0; - var uploadOptions = new BlobUploadOptions - { - HttpHeaders = new BlobHttpHeaders - { - ContentType = contentType - } - }; - var response = await blob.UploadAsync(stream, uploadOptions); + var response = await blob.UploadAsync(stream); return blob.Uri.ToString(); } diff --git a/TickAPI/TickAPI/Events/DTOs/Response/GetEventDetailsResponseDto.cs b/TickAPI/TickAPI/Events/DTOs/Response/GetEventDetailsResponseDto.cs index c5ea721..60e2862 100644 --- a/TickAPI/TickAPI/Events/DTOs/Response/GetEventDetailsResponseDto.cs +++ b/TickAPI/TickAPI/Events/DTOs/Response/GetEventDetailsResponseDto.cs @@ -12,5 +12,6 @@ public record GetEventDetailsResponseDto( List Categories, List TicketTypes, EventStatus Status, - GetEventResponseAddressDto Address + GetEventResponseAddressDto Address, + string? ImageUrl ); \ No newline at end of file diff --git a/TickAPI/TickAPI/Events/DTOs/Response/GetEventResponseDto.cs b/TickAPI/TickAPI/Events/DTOs/Response/GetEventResponseDto.cs index a280251..6c15242 100644 --- a/TickAPI/TickAPI/Events/DTOs/Response/GetEventResponseDto.cs +++ b/TickAPI/TickAPI/Events/DTOs/Response/GetEventResponseDto.cs @@ -13,5 +13,6 @@ public record GetEventResponseDto( GetEventResponsePriceInfoDto MaximumPrice, List Categories, EventStatus Status, - GetEventResponseAddressDto Address + GetEventResponseAddressDto Address, + string? ImageUrl ); diff --git a/TickAPI/TickAPI/Events/Services/EventService.cs b/TickAPI/TickAPI/Events/Services/EventService.cs index 032ba37..286ddce 100644 --- a/TickAPI/TickAPI/Events/Services/EventService.cs +++ b/TickAPI/TickAPI/Events/Services/EventService.cs @@ -89,7 +89,7 @@ public async Task> CreateNewEventAsync(string name, string descri string? imageUrl = null; if (image != null) { - imageUrl = await _blobService.UploadToBlobContainerAsync(name, image); + imageUrl = await _blobService.UploadToBlobContainerAsync(image); } var @event = new Event { @@ -187,7 +187,8 @@ public async Task> GetEventDetailsAsync(Guid categories, ticketTypes, ev.EventStatus, - address + address, + ev.ImageUrl ); return Result.Success(details); @@ -318,7 +319,7 @@ private static GetEventResponseDto MapEventToGetEventResponseDto(Event ev) var maximumPrice = new GetEventResponsePriceInfoDto(ttMaximumPrice.Price, ttMaximumPrice.Currency); return new GetEventResponseDto(ev.Id, ev.Name, ev.Description, ev.StartDate, ev.EndDate, ev.MinimumAge, - minimumPrice, maximumPrice, categories, ev.EventStatus, address); + minimumPrice, maximumPrice, categories, ev.EventStatus, address, ev.ImageUrl); } private Result CheckEventDates(DateTime startDate, DateTime endDate, IEnumerable ticketTypes, bool skipStartDateEvaluation = false) From 85457a027be23a24f0869b93a0a198b445066ee3 Mon Sep 17 00:00:00 2001 From: staszkiet Date: Sat, 14 Jun 2025 19:04:35 +0200 Subject: [PATCH 5/6] try catch block --- .../Common/Blob/Services/BlobService.cs | 30 +++++++++++-------- 1 file changed, 18 insertions(+), 12 deletions(-) diff --git a/TickAPI/TickAPI/Common/Blob/Services/BlobService.cs b/TickAPI/TickAPI/Common/Blob/Services/BlobService.cs index 9d79bfa..d56dd49 100644 --- a/TickAPI/TickAPI/Common/Blob/Services/BlobService.cs +++ b/TickAPI/TickAPI/Common/Blob/Services/BlobService.cs @@ -18,17 +18,23 @@ public BlobService(IConfiguration configuration) public async Task UploadToBlobContainerAsync(IFormFile image) { - var container = new BlobContainerClient(_connectionString, _containerName); - Guid id = Guid.NewGuid(); - string blobName = id.ToString(); - var blob = container.GetBlobClient(blobName); - var stream = new MemoryStream(); - await image.CopyToAsync(stream); - stream.Position = 0; - - - var response = await blob.UploadAsync(stream); - - return blob.Uri.ToString(); + try + { + var container = new BlobContainerClient(_connectionString, _containerName); + Guid id = Guid.NewGuid(); + string blobName = id.ToString(); + var blob = container.GetBlobClient(blobName); + var stream = new MemoryStream(); + await image.CopyToAsync(stream); + stream.Position = 0; + var response = await blob.UploadAsync(stream); + + return blob.Uri.ToString(); + } + catch (Exception e) + { + return null; + } + } } \ No newline at end of file From 3fd5c9c4bb65cb8910376a7e9159c94d5f6aa49f Mon Sep 17 00:00:00 2001 From: staszkiet Date: Sat, 14 Jun 2025 19:08:47 +0200 Subject: [PATCH 6/6] better try catch --- .../Common/Blob/Services/BlobService.cs | 28 +++++++------------ .../TickAPI/Events/Services/EventService.cs | 9 +++++- 2 files changed, 18 insertions(+), 19 deletions(-) diff --git a/TickAPI/TickAPI/Common/Blob/Services/BlobService.cs b/TickAPI/TickAPI/Common/Blob/Services/BlobService.cs index d56dd49..b58a5c8 100644 --- a/TickAPI/TickAPI/Common/Blob/Services/BlobService.cs +++ b/TickAPI/TickAPI/Common/Blob/Services/BlobService.cs @@ -18,23 +18,15 @@ public BlobService(IConfiguration configuration) public async Task UploadToBlobContainerAsync(IFormFile image) { - try - { - var container = new BlobContainerClient(_connectionString, _containerName); - Guid id = Guid.NewGuid(); - string blobName = id.ToString(); - var blob = container.GetBlobClient(blobName); - var stream = new MemoryStream(); - await image.CopyToAsync(stream); - stream.Position = 0; - var response = await blob.UploadAsync(stream); - - return blob.Uri.ToString(); - } - catch (Exception e) - { - return null; - } - + var container = new BlobContainerClient(_connectionString, _containerName); + Guid id = Guid.NewGuid(); + string blobName = id.ToString(); + var blob = container.GetBlobClient(blobName); + var stream = new MemoryStream(); + await image.CopyToAsync(stream); + stream.Position = 0; + var response = await blob.UploadAsync(stream); + + return blob.Uri.ToString(); } } \ No newline at end of file diff --git a/TickAPI/TickAPI/Events/Services/EventService.cs b/TickAPI/TickAPI/Events/Services/EventService.cs index 286ddce..546da79 100644 --- a/TickAPI/TickAPI/Events/Services/EventService.cs +++ b/TickAPI/TickAPI/Events/Services/EventService.cs @@ -89,7 +89,14 @@ public async Task> CreateNewEventAsync(string name, string descri string? imageUrl = null; if (image != null) { - imageUrl = await _blobService.UploadToBlobContainerAsync(image); + try + { + imageUrl = await _blobService.UploadToBlobContainerAsync(image); + } + catch (Exception e) + { + return Result.Failure(statusCode:500, e.Message); + } } var @event = new Event {