From e4c2837ad9a52e127fff87165cbb76ea682711f1 Mon Sep 17 00:00:00 2001 From: Natalia Portillo Date: Thu, 13 Nov 2025 18:22:44 +0000 Subject: [PATCH] Automatically convert services into controllers. --- .../Controllers/BookScansController.cs | 166 +++++++++ .../Controllers/BooksController.cs | 167 +++++++++ .../Controllers/BrowserTestsController.cs | 55 +++ .../Controllers/CompaniesByBookController.cs | 101 ++++++ .../CompaniesByDocumentController.cs | 101 ++++++ .../CompaniesByMagazineController.cs | 101 ++++++ .../CompaniesBySoftwareFamilyController.cs | 101 ++++++ .../CompaniesBySoftwareVariantController.cs | 101 ++++++ .../CompaniesBySoftwareVersionController.cs | 101 ++++++ .../Controllers/CompaniesController.cs | 330 ++++++++++++++++++ .../Controllers/CompanyLogosController.cs | 143 ++++++++ .../Controllers/ComputersController.cs | 121 +++++++ .../Controllers/ConsolesController.cs | 121 +++++++ .../CurrencyInflationController.cs | 133 +++++++ .../Controllers/CurrencyPeggingController.cs | 145 ++++++++ .../DocumentCompaniesController.cs | 128 +++++++ .../Controllers/DocumentPeopleController.cs | 139 ++++++++ .../Controllers/DocumentRolesController.cs | 85 +++++ .../Controllers/DocumentScansController.cs | 161 +++++++++ .../DocumentsByMachineController.cs | 97 +++++ .../DocumentsByMachineFamilyController.cs | 97 +++++ .../Controllers/DocumentsController.cs | 147 ++++++++ .../Controllers/DumpsController.cs | 147 ++++++++ .../Controllers/GpusByMachineController.cs | 99 ++++++ Marechai.Server/Controllers/GpusController.cs | 175 ++++++++++ ...ctionSetExtensionsByProcessorController.cs | 98 ++++++ .../InstructionSetExtensionsController.cs | 132 +++++++ .../Controllers/InstructionSetsController.cs | 128 +++++++ .../Controllers/Iso31661NumericController.cs | 51 +++ .../Controllers/Iso4217Controller.cs | 50 +++ .../Controllers/LicensesController.cs | 140 ++++++++ .../Controllers/MachineFamiliesController.cs | 128 +++++++ .../Controllers/MachinePhotosController.cs | 214 ++++++++++++ .../Controllers/MachinesController.cs | 271 ++++++++++++++ .../Controllers/MagazineIssuesController.cs | 149 ++++++++ .../Controllers/MagazineScansController.cs | 161 +++++++++ .../MagazinesByMachineController.cs | 97 +++++ .../MagazinesByMachineFamilyController.cs | 97 +++++ .../Controllers/MagazinesController.cs | 164 +++++++++ .../Controllers/MediaController.cs | 228 ++++++++++++ .../MemoriesByMachineController.cs | 105 ++++++ Marechai.Server/Controllers/NewsController.cs | 174 +++++++++ .../Controllers/PeopleByBookController.cs | 106 ++++++ .../Controllers/PeopleByDocumentController.cs | 104 ++++++ .../Controllers/PeopleByMagazineController.cs | 104 ++++++ .../Controllers/PeopleController.cs | 164 +++++++++ .../ProcessorsByMachineController.cs | 101 ++++++ .../Controllers/ProcessorsController.cs | 269 ++++++++++++++ .../Controllers/ResolutionsByGpuController.cs | 111 ++++++ .../ResolutionsByScreenController.cs | 111 ++++++ .../Controllers/ResolutionsController.cs | 147 ++++++++ .../Controllers/ScreensByMachineController.cs | 117 +++++++ .../Controllers/ScreensController.cs | 180 ++++++++++ .../Controllers/SoftwareFamiliesController.cs | 131 +++++++ .../Controllers/SoftwareVariantsController.cs | 184 ++++++++++ .../Controllers/SoftwareVersionsController.cs | 154 ++++++++ .../SoundSynthsByMachineController.cs | 99 ++++++ .../Controllers/SoundSynthsController.cs | 188 ++++++++++ .../Controllers/StorageByMachineController.cs | 102 ++++++ 59 files changed, 8021 insertions(+) create mode 100644 Marechai.Server/Controllers/BookScansController.cs create mode 100644 Marechai.Server/Controllers/BooksController.cs create mode 100644 Marechai.Server/Controllers/BrowserTestsController.cs create mode 100644 Marechai.Server/Controllers/CompaniesByBookController.cs create mode 100644 Marechai.Server/Controllers/CompaniesByDocumentController.cs create mode 100644 Marechai.Server/Controllers/CompaniesByMagazineController.cs create mode 100644 Marechai.Server/Controllers/CompaniesBySoftwareFamilyController.cs create mode 100644 Marechai.Server/Controllers/CompaniesBySoftwareVariantController.cs create mode 100644 Marechai.Server/Controllers/CompaniesBySoftwareVersionController.cs create mode 100644 Marechai.Server/Controllers/CompaniesController.cs create mode 100644 Marechai.Server/Controllers/CompanyLogosController.cs create mode 100644 Marechai.Server/Controllers/ComputersController.cs create mode 100644 Marechai.Server/Controllers/ConsolesController.cs create mode 100644 Marechai.Server/Controllers/CurrencyInflationController.cs create mode 100644 Marechai.Server/Controllers/CurrencyPeggingController.cs create mode 100644 Marechai.Server/Controllers/DocumentCompaniesController.cs create mode 100644 Marechai.Server/Controllers/DocumentPeopleController.cs create mode 100644 Marechai.Server/Controllers/DocumentRolesController.cs create mode 100644 Marechai.Server/Controllers/DocumentScansController.cs create mode 100644 Marechai.Server/Controllers/DocumentsByMachineController.cs create mode 100644 Marechai.Server/Controllers/DocumentsByMachineFamilyController.cs create mode 100644 Marechai.Server/Controllers/DocumentsController.cs create mode 100644 Marechai.Server/Controllers/DumpsController.cs create mode 100644 Marechai.Server/Controllers/GpusByMachineController.cs create mode 100644 Marechai.Server/Controllers/GpusController.cs create mode 100644 Marechai.Server/Controllers/InstructionSetExtensionsByProcessorController.cs create mode 100644 Marechai.Server/Controllers/InstructionSetExtensionsController.cs create mode 100644 Marechai.Server/Controllers/InstructionSetsController.cs create mode 100644 Marechai.Server/Controllers/Iso31661NumericController.cs create mode 100644 Marechai.Server/Controllers/Iso4217Controller.cs create mode 100644 Marechai.Server/Controllers/LicensesController.cs create mode 100644 Marechai.Server/Controllers/MachineFamiliesController.cs create mode 100644 Marechai.Server/Controllers/MachinePhotosController.cs create mode 100644 Marechai.Server/Controllers/MachinesController.cs create mode 100644 Marechai.Server/Controllers/MagazineIssuesController.cs create mode 100644 Marechai.Server/Controllers/MagazineScansController.cs create mode 100644 Marechai.Server/Controllers/MagazinesByMachineController.cs create mode 100644 Marechai.Server/Controllers/MagazinesByMachineFamilyController.cs create mode 100644 Marechai.Server/Controllers/MagazinesController.cs create mode 100644 Marechai.Server/Controllers/MediaController.cs create mode 100644 Marechai.Server/Controllers/MemoriesByMachineController.cs create mode 100644 Marechai.Server/Controllers/NewsController.cs create mode 100644 Marechai.Server/Controllers/PeopleByBookController.cs create mode 100644 Marechai.Server/Controllers/PeopleByDocumentController.cs create mode 100644 Marechai.Server/Controllers/PeopleByMagazineController.cs create mode 100644 Marechai.Server/Controllers/PeopleController.cs create mode 100644 Marechai.Server/Controllers/ProcessorsByMachineController.cs create mode 100644 Marechai.Server/Controllers/ProcessorsController.cs create mode 100644 Marechai.Server/Controllers/ResolutionsByGpuController.cs create mode 100644 Marechai.Server/Controllers/ResolutionsByScreenController.cs create mode 100644 Marechai.Server/Controllers/ResolutionsController.cs create mode 100644 Marechai.Server/Controllers/ScreensByMachineController.cs create mode 100644 Marechai.Server/Controllers/ScreensController.cs create mode 100644 Marechai.Server/Controllers/SoftwareFamiliesController.cs create mode 100644 Marechai.Server/Controllers/SoftwareVariantsController.cs create mode 100644 Marechai.Server/Controllers/SoftwareVersionsController.cs create mode 100644 Marechai.Server/Controllers/SoundSynthsByMachineController.cs create mode 100644 Marechai.Server/Controllers/SoundSynthsController.cs create mode 100644 Marechai.Server/Controllers/StorageByMachineController.cs diff --git a/Marechai.Server/Controllers/BookScansController.cs b/Marechai.Server/Controllers/BookScansController.cs new file mode 100644 index 00000000..d0ca0911 --- /dev/null +++ b/Marechai.Server/Controllers/BookScansController.cs @@ -0,0 +1,166 @@ +/******************************************************************************* +// MARECHAI: Master repository of computing history artifacts information +// --------------------------------------------------------------------------- +// +// Author(s) : Natalia Portillo +// +// --[ License ] ----------------------------------------------------------- +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +// --------------------------------------------------------------------------- +// Copyright © 2003-2025 Natalia Portillo +*******************************************************************************/ + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Security.Claims; +using System.Threading.Tasks; +using Marechai.Data.Dtos; +using Marechai.Database.Models; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Localization; + +namespace Marechai.Server.Controllers; + +[Route("/book-scans")] +[ApiController] +public class BookScansController(MarechaiContext context) : ControllerBase +{ + [HttpGet] + [AllowAnonymous] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task> GetGuidsByBookAsync(long bookId) => + await context.BookScans.Where(p => p.BookId == bookId).Select(p => p.Id).ToListAsync(); + + [HttpGet] + [AllowAnonymous] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task GetAsync(Guid id) => await context.BookScans.Where(p => p.Id == id) + .Select(p => new BookScanDto + { + Author = p.Author, + BookId = p.Book.Id, + ColorSpace = p.ColorSpace, + Comments = p.Comments, + CreationDate = p.CreationDate, + ExifVersion = p.ExifVersion, + HorizontalResolution = + p.HorizontalResolution, + Id = p.Id, + ResolutionUnit = + p.ResolutionUnit, + Page = p.Page, + ScannerManufacturer = + p.ScannerManufacturer, + ScannerModel = p.ScannerModel, + SoftwareUsed = p.SoftwareUsed, + Type = p.Type, + UploadDate = p.UploadDate, + UserId = p.UserId, + VerticalResolution = + p.VerticalResolution, + OriginalExtension = + p.OriginalExtension + }) + .FirstOrDefaultAsync(); + + [HttpPost] + [Authorize(Roles = "Admin,UberAdmin")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task UpdateAsync(BookScanDto dto) + { + string userId = User.FindFirstValue(ClaimTypes.Sid); + if(userId is null) return; + BookScan model = await context.BookScans.FindAsync(dto.Id); + + if(model is null) return; + + model.Author = dto.Author; + model.ColorSpace = dto.ColorSpace; + model.Comments = dto.Comments; + model.CreationDate = dto.CreationDate; + model.ExifVersion = dto.ExifVersion; + model.HorizontalResolution = dto.HorizontalResolution; + model.ResolutionUnit = dto.ResolutionUnit; + model.Page = dto.Page; + model.ScannerManufacturer = dto.ScannerManufacturer; + model.ScannerModel = dto.ScannerModel; + model.Type = dto.Type; + model.SoftwareUsed = dto.SoftwareUsed; + model.VerticalResolution = dto.VerticalResolution; + + await context.SaveChangesWithUserAsync(userId); + } + + [HttpPost] + [Authorize(Roles = "Admin,UberAdmin")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task CreateAsync(BookScanDto dto) + { + string userId = User.FindFirstValue(ClaimTypes.Sid); + if(userId is null) return null; + var model = new BookScan + { + Author = dto.Author, + BookId = dto.BookId, + ColorSpace = dto.ColorSpace, + Comments = dto.Comments, + CreationDate = dto.CreationDate, + ExifVersion = dto.ExifVersion, + HorizontalResolution = dto.HorizontalResolution, + Id = dto.Id, + ResolutionUnit = dto.ResolutionUnit, + Page = dto.Page, + ScannerManufacturer = dto.ScannerManufacturer, + ScannerModel = dto.ScannerModel, + Type = dto.Type, + SoftwareUsed = dto.SoftwareUsed, + UploadDate = dto.UploadDate, + UserId = dto.UserId, + VerticalResolution = dto.VerticalResolution, + OriginalExtension = dto.OriginalExtension + }; + + await context.BookScans.AddAsync(model); + await context.SaveChangesWithUserAsync(userId); + + return model.Id; + } + + [HttpDelete] + [Authorize(Roles = "Admin,UberAdmin")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task DeleteAsync(Guid id) + { + string userId = User.FindFirstValue(ClaimTypes.Sid); + if(userId is null) return; + BookScan item = await context.BookScans.FindAsync(id); + + if(item is null) return; + + context.BookScans.Remove(item); + + await context.SaveChangesWithUserAsync(userId); + } +} diff --git a/Marechai.Server/Controllers/BooksController.cs b/Marechai.Server/Controllers/BooksController.cs new file mode 100644 index 00000000..be815097 --- /dev/null +++ b/Marechai.Server/Controllers/BooksController.cs @@ -0,0 +1,167 @@ +/******************************************************************************* +// MARECHAI: Master repository of computing history artifacts information +// --------------------------------------------------------------------------- +// +// Author(s) : Natalia Portillo +// +// --[ License ] ----------------------------------------------------------- +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +// --------------------------------------------------------------------------- +// Copyright © 2003-2025 Natalia Portillo +*******************************************************************************/ + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Security.Claims; +using System.Threading.Tasks; +using Marechai.Data.Dtos; +using Marechai.Database.Models; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Localization; + +namespace Marechai.Server.Controllers; + +[Route("/books")] +[ApiController] +public class BooksController(MarechaiContext context) : ControllerBase +{ + [HttpGet] + [AllowAnonymous] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task> GetAsync() => await context.Books.OrderBy(b => b.NativeTitle) + .ThenBy(b => b.Published) + .ThenBy(b => b.Title) + .Select(b => new BookDto + { + Id = b.Id, + Title = b.Title, + NativeTitle = b.NativeTitle, + Published = b.Published, + Synopsis = b.Synopsis, + Isbn = b.Isbn, + CountryId = b.CountryId, + Pages = b.Pages, + Edition = b.Edition, + PreviousId = b.PreviousId, + SourceId = b.SourceId, + Country = b.Country.Name + }) + .ToListAsync(); + + [HttpGet] + [AllowAnonymous] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task GetAsync(long id) => await context.Books.Where(b => b.Id == id) + .Select(b => new BookDto + { + Id = b.Id, + Title = b.Title, + NativeTitle = b.NativeTitle, + Published = b.Published, + Synopsis = b.Synopsis, + Isbn = b.Isbn, + CountryId = b.CountryId, + Pages = b.Pages, + Edition = b.Edition, + PreviousId = b.PreviousId, + SourceId = b.SourceId, + Country = b.Country.Name + }) + .FirstOrDefaultAsync(); + + [HttpPost] + [Authorize(Roles = "Admin,UberAdmin")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task UpdateAsync(BookDto dto) + { + string userId = User.FindFirstValue(ClaimTypes.Sid); + if(userId is null) return; + Book model = await context.Books.FindAsync(dto.Id); + + if(model is null) return; + + model.Title = dto.Title; + model.NativeTitle = dto.NativeTitle; + model.Published = dto.Published; + model.Synopsis = dto.Synopsis; + model.CountryId = dto.CountryId; + model.Isbn = dto.Isbn; + model.Pages = dto.Pages; + model.Edition = dto.Edition; + model.PreviousId = dto.PreviousId; + model.SourceId = dto.SourceId; + await context.SaveChangesWithUserAsync(userId); + } + + [HttpPost] + [Authorize(Roles = "Admin,UberAdmin")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task CreateAsync(BookDto dto) + { + string userId = User.FindFirstValue(ClaimTypes.Sid); + if(userId is null) return 0; + var model = new Book + { + Title = dto.Title, + NativeTitle = dto.NativeTitle, + Published = dto.Published, + Synopsis = dto.Synopsis, + CountryId = dto.CountryId, + Isbn = dto.Isbn, + Pages = dto.Pages, + Edition = dto.Edition, + PreviousId = dto.PreviousId, + SourceId = dto.SourceId + }; + + await context.Books.AddAsync(model); + await context.SaveChangesWithUserAsync(userId); + + return model.Id; + } + + [HttpGet] + [AllowAnonymous] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task GetSynopsisTextAsync(int id) => + (await context.Books.FirstOrDefaultAsync(d => d.Id == id))?.Synopsis; + + [HttpDelete] + [Authorize(Roles = "Admin,UberAdmin")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task DeleteAsync(long id) + { + string userId = User.FindFirstValue(ClaimTypes.Sid); + if(userId is null) return; + Book item = await context.Books.FindAsync(id); + + if(item is null) return; + + context.Books.Remove(item); + + await context.SaveChangesWithUserAsync(userId); + } +} diff --git a/Marechai.Server/Controllers/BrowserTestsController.cs b/Marechai.Server/Controllers/BrowserTestsController.cs new file mode 100644 index 00000000..dbca6018 --- /dev/null +++ b/Marechai.Server/Controllers/BrowserTestsController.cs @@ -0,0 +1,55 @@ +/******************************************************************************* +// MARECHAI: Master repository of computing history artifacts information +// --------------------------------------------------------------------------- +// +// Author(s) : Natalia Portillo +// +// --[ License ] ----------------------------------------------------------- +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +// --------------------------------------------------------------------------- +// Copyright © 2003-2025 Natalia Portillo +*******************************************************************************/ + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Security.Claims; +using System.Threading.Tasks; +using Marechai.Data.Dtos; +using Marechai.Database.Models; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Localization; + +namespace Marechai.Server.Controllers; + +[Route("/browser-tests")] +[ApiController] +public class BrowserTestsController(MarechaiContext context) : ControllerBase +{ + [HttpGet] + [AllowAnonymous] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public Task> GetAsync() => context.BrowserTests.OrderBy(b => b.Browser) + .ThenBy(b => b.Version) + .ThenBy(b => b.Os) + .ThenBy(b => b.Platform) + .ThenBy(b => b.UserAgent) + .ToListAsync(); +} diff --git a/Marechai.Server/Controllers/CompaniesByBookController.cs b/Marechai.Server/Controllers/CompaniesByBookController.cs new file mode 100644 index 00000000..6de79100 --- /dev/null +++ b/Marechai.Server/Controllers/CompaniesByBookController.cs @@ -0,0 +1,101 @@ +/******************************************************************************* +// MARECHAI: Master repository of computing history artifacts information +// --------------------------------------------------------------------------- +// +// Author(s) : Natalia Portillo +// +// --[ License ] ----------------------------------------------------------- +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +// --------------------------------------------------------------------------- +// Copyright © 2003-2025 Natalia Portillo +*******************************************************************************/ + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Security.Claims; +using System.Threading.Tasks; +using Marechai.Data.Dtos; +using Marechai.Database.Models; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Localization; + +namespace Marechai.Server.Controllers; + +[Route("/companies-by-book")] +[ApiController] +public class CompaniesByBookController(MarechaiContext context) : ControllerBase +{ + [HttpGet] + [AllowAnonymous] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task> GetByBook(long bookId) => await context.CompaniesByBooks + .Where(p => p.BookId == bookId) + .Select(p => new CompanyByBookDto + { + Id = p.Id, + Company = p.Company.Name, + CompanyId = p.CompanyId, + RoleId = p.RoleId, + Role = p.Role.Name, + BookId = p.BookId + }) + .OrderBy(p => p.Company) + .ThenBy(p => p.Role) + .ToListAsync(); + + [HttpDelete] + [Authorize(Roles = "Admin,UberAdmin")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task DeleteAsync(long id) + { + string userId = User.FindFirstValue(ClaimTypes.Sid); + if(userId is null) return; + CompaniesByBook item = await context.CompaniesByBooks.FindAsync(id); + + if(item is null) return; + + context.CompaniesByBooks.Remove(item); + + await context.SaveChangesWithUserAsync(userId); + } + + [HttpPost] + [Authorize(Roles = "Admin,UberAdmin")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task CreateAsync(int companyId, long bookId, string roleId) + { + string userId = User.FindFirstValue(ClaimTypes.Sid); + if(userId is null) return 0; + var item = new CompaniesByBook + { + CompanyId = companyId, + BookId = bookId, + RoleId = roleId + }; + + await context.CompaniesByBooks.AddAsync(item); + await context.SaveChangesWithUserAsync(userId); + + return item.Id; + } +} diff --git a/Marechai.Server/Controllers/CompaniesByDocumentController.cs b/Marechai.Server/Controllers/CompaniesByDocumentController.cs new file mode 100644 index 00000000..4684d027 --- /dev/null +++ b/Marechai.Server/Controllers/CompaniesByDocumentController.cs @@ -0,0 +1,101 @@ +/******************************************************************************* +// MARECHAI: Master repository of computing history artifacts information +// --------------------------------------------------------------------------- +// +// Author(s) : Natalia Portillo +// +// --[ License ] ----------------------------------------------------------- +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +// --------------------------------------------------------------------------- +// Copyright © 2003-2025 Natalia Portillo +*******************************************************************************/ + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Security.Claims; +using System.Threading.Tasks; +using Marechai.Data.Dtos; +using Marechai.Database.Models; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Localization; + +namespace Marechai.Server.Controllers; + +[Route("/companies-by-document")] +[ApiController] +public class CompaniesByDocumentController(MarechaiContext context) : ControllerBase +{ + [HttpGet] + [AllowAnonymous] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task> GetByDocument(long documentId) => await context + .CompaniesByDocuments.Where(p => p.DocumentId == documentId) + .Select(p => new CompanyByDocumentDto + { + Id = p.Id, + Company = p.Company.Name, + CompanyId = p.CompanyId, + RoleId = p.RoleId, + Role = p.Role.Name, + DocumentId = p.DocumentId + }) + .OrderBy(p => p.Company) + .ThenBy(p => p.Role) + .ToListAsync(); + + [HttpDelete] + [Authorize(Roles = "Admin,UberAdmin")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task DeleteAsync(long id) + { + string userId = User.FindFirstValue(ClaimTypes.Sid); + if(userId is null) return; + CompaniesByDocument item = await context.CompaniesByDocuments.FindAsync(id); + + if(item is null) return; + + context.CompaniesByDocuments.Remove(item); + + await context.SaveChangesWithUserAsync(userId); + } + + [HttpPost] + [Authorize(Roles = "Admin,UberAdmin")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task CreateAsync(int companyId, long documentId, string roleId) + { + string userId = User.FindFirstValue(ClaimTypes.Sid); + if(userId is null) return 0; + var item = new CompaniesByDocument + { + CompanyId = companyId, + DocumentId = documentId, + RoleId = roleId + }; + + await context.CompaniesByDocuments.AddAsync(item); + await context.SaveChangesWithUserAsync(userId); + + return item.Id; + } +} diff --git a/Marechai.Server/Controllers/CompaniesByMagazineController.cs b/Marechai.Server/Controllers/CompaniesByMagazineController.cs new file mode 100644 index 00000000..05c12686 --- /dev/null +++ b/Marechai.Server/Controllers/CompaniesByMagazineController.cs @@ -0,0 +1,101 @@ +/******************************************************************************* +// MARECHAI: Master repository of computing history artifacts information +// --------------------------------------------------------------------------- +// +// Author(s) : Natalia Portillo +// +// --[ License ] ----------------------------------------------------------- +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +// --------------------------------------------------------------------------- +// Copyright © 2003-2025 Natalia Portillo +*******************************************************************************/ + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Security.Claims; +using System.Threading.Tasks; +using Marechai.Data.Dtos; +using Marechai.Database.Models; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Localization; + +namespace Marechai.Server.Controllers; + +[Route("/companies-by-magazine")] +[ApiController] +public class CompaniesByMagazineController(MarechaiContext context) : ControllerBase +{ + [HttpGet] + [AllowAnonymous] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task> GetByMagazine(long magazineId) => await context + .CompaniesByMagazines.Where(p => p.MagazineId == magazineId) + .Select(p => new CompanyByMagazineDto + { + Id = p.Id, + Company = p.Company.Name, + CompanyId = p.CompanyId, + RoleId = p.RoleId, + Role = p.Role.Name, + MagazineId = p.MagazineId + }) + .OrderBy(p => p.Company) + .ThenBy(p => p.Role) + .ToListAsync(); + + [HttpDelete] + [Authorize(Roles = "Admin,UberAdmin")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task DeleteAsync(long id) + { + string userId = User.FindFirstValue(ClaimTypes.Sid); + if(userId is null) return; + CompaniesByMagazine item = await context.CompaniesByMagazines.FindAsync(id); + + if(item is null) return; + + context.CompaniesByMagazines.Remove(item); + + await context.SaveChangesWithUserAsync(userId); + } + + [HttpPost] + [Authorize(Roles = "Admin,UberAdmin")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task CreateAsync(int companyId, long magazineId, string roleId) + { + string userId = User.FindFirstValue(ClaimTypes.Sid); + if(userId is null) return 0; + var item = new CompaniesByMagazine + { + CompanyId = companyId, + MagazineId = magazineId, + RoleId = roleId + }; + + await context.CompaniesByMagazines.AddAsync(item); + await context.SaveChangesWithUserAsync(userId); + + return item.Id; + } +} diff --git a/Marechai.Server/Controllers/CompaniesBySoftwareFamilyController.cs b/Marechai.Server/Controllers/CompaniesBySoftwareFamilyController.cs new file mode 100644 index 00000000..6de57941 --- /dev/null +++ b/Marechai.Server/Controllers/CompaniesBySoftwareFamilyController.cs @@ -0,0 +1,101 @@ +/******************************************************************************* +// MARECHAI: Master repository of computing history artifacts information +// --------------------------------------------------------------------------- +// +// Author(s) : Natalia Portillo +// +// --[ License ] ----------------------------------------------------------- +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +// --------------------------------------------------------------------------- +// Copyright © 2003-2025 Natalia Portillo +*******************************************************************************/ + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Security.Claims; +using System.Threading.Tasks; +using Marechai.Data.Dtos; +using Marechai.Database.Models; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Localization; + +namespace Marechai.Server.Controllers; + +[Route("/companies-by-software-family")] +[ApiController] +public class CompaniesBySoftwareFamilyController(MarechaiContext context) : ControllerBase +{ + [HttpGet] + [AllowAnonymous] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task> GetBySoftwareFamily(ulong softwareFamilyId) => + await context.CompaniesBySoftwareFamilies.Where(p => p.SoftwareFamilyId == softwareFamilyId) + .Select(p => new CompanyBySoftwareFamilyDto + { + Id = p.Id, + Company = p.Company.Name, + CompanyId = p.CompanyId, + RoleId = p.RoleId, + Role = p.Role.Name, + SoftwareFamilyId = p.SoftwareFamilyId + }) + .OrderBy(p => p.Company) + .ThenBy(p => p.Role) + .ToListAsync(); + + [HttpDelete] + [Authorize(Roles = "Admin,UberAdmin")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task DeleteAsync(ulong id) + { + string userId = User.FindFirstValue(ClaimTypes.Sid); + if(userId is null) return; + CompaniesBySoftwareFamily item = await context.CompaniesBySoftwareFamilies.FindAsync(id); + + if(item is null) return; + + context.CompaniesBySoftwareFamilies.Remove(item); + + await context.SaveChangesWithUserAsync(userId); + } + + [HttpPost] + [Authorize(Roles = "Admin,UberAdmin")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task CreateAsync(int companyId, ulong softwareFamilyId, string roleId) + { + string userId = User.FindFirstValue(ClaimTypes.Sid); + if(userId is null) return null; + var item = new CompaniesBySoftwareFamily + { + CompanyId = companyId, + SoftwareFamilyId = softwareFamilyId, + RoleId = roleId + }; + + await context.CompaniesBySoftwareFamilies.AddAsync(item); + await context.SaveChangesWithUserAsync(userId); + + return item.Id; + } +} diff --git a/Marechai.Server/Controllers/CompaniesBySoftwareVariantController.cs b/Marechai.Server/Controllers/CompaniesBySoftwareVariantController.cs new file mode 100644 index 00000000..76178313 --- /dev/null +++ b/Marechai.Server/Controllers/CompaniesBySoftwareVariantController.cs @@ -0,0 +1,101 @@ +/******************************************************************************* +// MARECHAI: Master repository of computing history artifacts information +// --------------------------------------------------------------------------- +// +// Author(s) : Natalia Portillo +// +// --[ License ] ----------------------------------------------------------- +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +// --------------------------------------------------------------------------- +// Copyright © 2003-2025 Natalia Portillo +*******************************************************************************/ + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Security.Claims; +using System.Threading.Tasks; +using Marechai.Data.Dtos; +using Marechai.Database.Models; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Localization; + +namespace Marechai.Server.Controllers; + +[Route("/companies-by-software-variant")] +[ApiController] +public class CompaniesBySoftwareVariantController(MarechaiContext context) : ControllerBase +{ + [HttpGet] + [AllowAnonymous] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task> GetBySoftwareVariant(ulong softwareVariantId) => + await context.CompaniesBySoftwareVariants.Where(p => p.SoftwareVariantId == softwareVariantId) + .Select(p => new CompanyBySoftwareVariantDto + { + Id = p.Id, + Company = p.Company.Name, + CompanyId = p.CompanyId, + RoleId = p.RoleId, + Role = p.Role.Name, + SoftwareVariantId = p.SoftwareVariantId + }) + .OrderBy(p => p.Company) + .ThenBy(p => p.Role) + .ToListAsync(); + + [HttpDelete] + [Authorize(Roles = "Admin,UberAdmin")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task DeleteAsync(ulong id) + { + string userId = User.FindFirstValue(ClaimTypes.Sid); + if(userId is null) return; + CompaniesBySoftwareVariant item = await context.CompaniesBySoftwareVariants.FindAsync(id); + + if(item is null) return; + + context.CompaniesBySoftwareVariants.Remove(item); + + await context.SaveChangesWithUserAsync(userId); + } + + [HttpPost] + [Authorize(Roles = "Admin,UberAdmin")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task CreateAsync(int companyId, ulong softwareVariantId, string roleId) + { + string userId = User.FindFirstValue(ClaimTypes.Sid); + if(userId is null) return null; + var item = new CompaniesBySoftwareVariant + { + CompanyId = companyId, + SoftwareVariantId = softwareVariantId, + RoleId = roleId + }; + + await context.CompaniesBySoftwareVariants.AddAsync(item); + await context.SaveChangesWithUserAsync(userId); + + return item.Id; + } +} diff --git a/Marechai.Server/Controllers/CompaniesBySoftwareVersionController.cs b/Marechai.Server/Controllers/CompaniesBySoftwareVersionController.cs new file mode 100644 index 00000000..cd600631 --- /dev/null +++ b/Marechai.Server/Controllers/CompaniesBySoftwareVersionController.cs @@ -0,0 +1,101 @@ +/******************************************************************************* +// MARECHAI: Master repository of computing history artifacts information +// --------------------------------------------------------------------------- +// +// Author(s) : Natalia Portillo +// +// --[ License ] ----------------------------------------------------------- +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +// --------------------------------------------------------------------------- +// Copyright © 2003-2025 Natalia Portillo +*******************************************************************************/ + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Security.Claims; +using System.Threading.Tasks; +using Marechai.Data.Dtos; +using Marechai.Database.Models; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Localization; + +namespace Marechai.Server.Controllers; + +[Route("/companies-by-software-version")] +[ApiController] +public class CompaniesBySoftwareVersionController(MarechaiContext context) : ControllerBase +{ + [HttpGet] + [AllowAnonymous] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task> GetBySoftwareVersion(ulong softwareVersionId) => + await context.CompaniesBySoftwareVersions.Where(p => p.SoftwareVersionId == softwareVersionId) + .Select(p => new CompanyBySoftwareVersionDto + { + Id = p.Id, + Company = p.Company.Name, + CompanyId = p.CompanyId, + RoleId = p.RoleId, + Role = p.Role.Name, + SoftwareVersionId = p.SoftwareVersionId + }) + .OrderBy(p => p.Company) + .ThenBy(p => p.Role) + .ToListAsync(); + + [HttpDelete] + [Authorize(Roles = "Admin,UberAdmin")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task DeleteAsync(ulong id) + { + string userId = User.FindFirstValue(ClaimTypes.Sid); + if(userId is null) return; + CompaniesBySoftwareVersion item = await context.CompaniesBySoftwareVersions.FindAsync(id); + + if(item is null) return; + + context.CompaniesBySoftwareVersions.Remove(item); + + await context.SaveChangesWithUserAsync(userId); + } + + [HttpPost] + [Authorize(Roles = "Admin,UberAdmin")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task CreateAsync(int companyId, ulong softwareVersionId, string roleId) + { + string userId = User.FindFirstValue(ClaimTypes.Sid); + if(userId is null) return null; + var item = new CompaniesBySoftwareVersion + { + CompanyId = companyId, + SoftwareVersionId = softwareVersionId, + RoleId = roleId + }; + + await context.CompaniesBySoftwareVersions.AddAsync(item); + await context.SaveChangesWithUserAsync(userId); + + return item.Id; + } +} diff --git a/Marechai.Server/Controllers/CompaniesController.cs b/Marechai.Server/Controllers/CompaniesController.cs new file mode 100644 index 00000000..c642e0d6 --- /dev/null +++ b/Marechai.Server/Controllers/CompaniesController.cs @@ -0,0 +1,330 @@ +/******************************************************************************* +// MARECHAI: Master repository of computing history artifacts information +// --------------------------------------------------------------------------- +// +// Author(s) : Natalia Portillo +// +// --[ License ] ----------------------------------------------------------- +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +// --------------------------------------------------------------------------- +// Copyright © 2003-2025 Natalia Portillo +*******************************************************************************/ + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Security.Claims; +using System.Threading.Tasks; +using Marechai.Data.Dtos; +using Marechai.Database.Models; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Localization; + +namespace Marechai.Server.Controllers; + +[Route("/companies")] +[ApiController] +public class CompaniesController(MarechaiContext context, IStringLocalizer localizer) : ControllerBase +{ + [HttpGet] + [AllowAnonymous] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task> GetAsync() => await context.Companies.Include(c => c.Logos) + .OrderBy(c => c.Name) + .Select(c => new CompanyDto + { + Id = c.Id, + LastLogo = + c.Logos + .OrderByDescending(l => l.Year) + .FirstOrDefault() + .Guid, + Name = c.Name, + Founded = c.Founded, + Sold = c.Sold, + SoldToId = c.SoldToId, + CountryId = c.CountryId, + Status = c.Status, + Website = c.Website, + Twitter = c.Twitter, + Facebook = c.Facebook, + Address = c.Address, + City = c.City, + Province = c.Province, + PostalCode = c.PostalCode, + Country = c.Country.Name, + FoundedDayIsUnknown = + c.FoundedDayIsUnknown, + FoundedMonthIsUnknown = + c.FoundedMonthIsUnknown, + SoldDayIsUnknown = + c.SoldDayIsUnknown, + SoldMonthIsUnknown = + c.SoldMonthIsUnknown, + LegalName = c.LegalName + }) + .ToListAsync(); + + [HttpGet] + [AllowAnonymous] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task GetAsync(int id) => await context.Companies.Where(c => c.Id == id) + .Select(c => new CompanyDto + { + Id = c.Id, + LastLogo = + c.Logos + .OrderByDescending(l => l.Year) + .FirstOrDefault() + .Guid, + Name = c.Name, + Founded = c.Founded, + Sold = c.Sold, + SoldToId = c.SoldToId, + CountryId = c.CountryId, + Status = c.Status, + Website = c.Website, + Twitter = c.Twitter, + Facebook = c.Facebook, + Address = c.Address, + City = c.City, + Province = c.Province, + PostalCode = c.PostalCode, + Country = c.Country.Name, + FoundedDayIsUnknown = + c.FoundedDayIsUnknown, + FoundedMonthIsUnknown = + c.FoundedMonthIsUnknown, + SoldDayIsUnknown = + c.SoldDayIsUnknown, + SoldMonthIsUnknown = + c.SoldMonthIsUnknown, + LegalName = c.LegalName + }) + .FirstOrDefaultAsync(); + + [HttpPost] + [Authorize(Roles = "Admin,UberAdmin")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task UpdateAsync(CompanyDto dto) + { + string userId = User.FindFirstValue(ClaimTypes.Sid); + if(userId is null) return; + Company model = await context.Companies.FindAsync(dto.Id); + + if(model is null) return; + + model.Name = dto.Name; + model.Founded = dto.Founded; + model.Sold = dto.Sold; + model.SoldToId = dto.SoldToId; + model.CountryId = dto.CountryId; + model.Status = dto.Status; + model.Website = dto.Website; + model.Twitter = dto.Twitter; + model.Facebook = dto.Facebook; + model.Address = dto.Address; + model.City = dto.City; + model.Province = dto.Province; + model.PostalCode = dto.PostalCode; + model.FoundedDayIsUnknown = dto.FoundedDayIsUnknown; + model.FoundedMonthIsUnknown = dto.FoundedMonthIsUnknown; + model.SoldDayIsUnknown = dto.SoldDayIsUnknown; + model.SoldMonthIsUnknown = dto.SoldMonthIsUnknown; + model.LegalName = dto.LegalName; + await context.SaveChangesWithUserAsync(userId); + } + + [HttpPost] + [Authorize(Roles = "Admin,UberAdmin")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task CreateAsync(CompanyDto dto) + { + string userId = User.FindFirstValue(ClaimTypes.Sid); + if(userId is null) return 0; + var model = new Company + { + Name = dto.Name, + Founded = dto.Founded, + Sold = dto.Sold, + SoldToId = dto.SoldToId, + CountryId = dto.CountryId, + Status = dto.Status, + Website = dto.Website, + Twitter = dto.Twitter, + Facebook = dto.Facebook, + Address = dto.Address, + City = dto.City, + Province = dto.Province, + PostalCode = dto.PostalCode, + FoundedDayIsUnknown = dto.FoundedDayIsUnknown, + FoundedMonthIsUnknown = dto.FoundedMonthIsUnknown, + SoldDayIsUnknown = dto.SoldDayIsUnknown, + SoldMonthIsUnknown = dto.SoldMonthIsUnknown, + LegalName = dto.LegalName + }; + + await context.Companies.AddAsync(model); + await context.SaveChangesWithUserAsync(userId); + + return model.Id; + } + + [HttpGet] + [AllowAnonymous] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task> GetMachinesAsync(int id) => await context.Machines.Where(m => m.CompanyId == id) + .OrderBy(m => m.Name) + .Select(m => new Machine + { + Id = m.Id, + Name = m.Name, + Type = m.Type + }) + .ToListAsync(); + + [HttpGet] + [AllowAnonymous] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task GetDescriptionTextAsync(int id) + { + CompanyDescription description = await context.CompanyDescriptions.FirstOrDefaultAsync(d => d.CompanyId == id); + + return description?.Html ?? description?.Text; + } + + [HttpGet] + [AllowAnonymous] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task GetSoldToAsync(int? id) => await context.Companies.Select(c => new Company + { + Id = c.Id, + Name = c.Name + }) + .FirstOrDefaultAsync(c => c.Id == id); + + [HttpGet] + [AllowAnonymous] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task GetCountryNameAsync(int id) => + (await context.Iso31661Numeric.FirstOrDefaultAsync(c => c.Id == id))?.Name; + + [HttpGet] + [AllowAnonymous] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public Task> GetCompaniesByCountryAsync(int countryId) => context.Companies + .Include(c => c.Logos) + .Where(c => c.CountryId == countryId) + .OrderBy(c => c.Name) + .Select(c => new CompanyDto + { + Id = c.Id, + LastLogo = c.Logos.OrderByDescending(l => l.Year).FirstOrDefault().Guid, + Name = c.Name + }) + .ToListAsync(); + + [HttpGet] + [AllowAnonymous] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public Task> GetCompaniesByLetterAsync(char id) => context.Companies.Include(c => c.Logos) + .Where(c => EF.Functions.Like(c.Name, $"{id}%")) + .OrderBy(c => c.Name) + .Select(c => new CompanyDto + { + Id = c.Id, + LastLogo = c.Logos.OrderByDescending(l => l.Year).FirstOrDefault().Guid, + Name = c.Name + }) + .ToListAsync(); + + [HttpDelete] + [Authorize(Roles = "Admin,UberAdmin")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task DeleteAsync(int id) + { + string userId = User.FindFirstValue(ClaimTypes.Sid); + if(userId is null) return; + Company item = await context.Companies.FindAsync(id); + + if(item is null) return; + + context.Companies.Remove(item); + + await context.SaveChangesWithUserAsync(userId); + } + + [HttpGet] + [AllowAnonymous] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task GetDescriptionAsync(int id) => await context.CompanyDescriptions + .Where(d => d.CompanyId == id) + .Select(d => new CompanyDescriptionDto + { + Id = d.Id, + CompanyId = d.CompanyId, + Html = d.Html, + Markdown = d.Text + }) + .FirstOrDefaultAsync(); + + [HttpPost] + [Authorize(Roles = "Admin,UberAdmin")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task CreateOrUpdateDescriptionAsync(int id, CompanyDescriptionDto description) + { + string userId = User.FindFirstValue(ClaimTypes.Sid); + if(userId is null) return 0; + CompanyDescription current = await context.CompanyDescriptions.FirstOrDefaultAsync(d => d.CompanyId == id); + + if(current is null) + { + current = new CompanyDescription + { + CompanyId = id, + Html = description.Html, + Text = description.Markdown + }; + + await context.CompanyDescriptions.AddAsync(current); + } + else + { + current.Html = description.Html; + current.Text = description.Markdown; + } + + await context.SaveChangesWithUserAsync(userId); + + return current.Id; + } +} diff --git a/Marechai.Server/Controllers/CompanyLogosController.cs b/Marechai.Server/Controllers/CompanyLogosController.cs new file mode 100644 index 00000000..20e5571e --- /dev/null +++ b/Marechai.Server/Controllers/CompanyLogosController.cs @@ -0,0 +1,143 @@ +/******************************************************************************* +// MARECHAI: Master repository of computing history artifacts information +// --------------------------------------------------------------------------- +// +// Author(s) : Natalia Portillo +// +// --[ License ] ----------------------------------------------------------- +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +// --------------------------------------------------------------------------- +// Copyright © 2003-2025 Natalia Portillo +*******************************************************************************/ + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Security.Claims; +using System.Threading.Tasks; +using Marechai.Data.Dtos; +using Marechai.Database.Models; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Localization; + +namespace Marechai.Server.Controllers; + +[Route("/company-logos")] +[ApiController] +public class CompanyLogosController(MarechaiContext context, IWebHostEnvironment host) : ControllerBase +{ + [HttpGet] + [AllowAnonymous] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task> GetByCompany(int companyId) => + await context.CompanyLogos.Where(l => l.CompanyId == companyId).OrderBy(l => l.Year).ToListAsync(); + + [HttpDelete] + [Authorize(Roles = "Admin,UberAdmin")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task DeleteAsync(int id) + { + string userId = User.FindFirstValue(ClaimTypes.Sid); + if(userId is null) return; + CompanyLogo logo = await context.CompanyLogos.Where(l => l.Id == id).FirstOrDefaultAsync(); + + if(logo is null) return; + + context.CompanyLogos.Remove(logo); + await context.SaveChangesWithUserAsync(userId); + + if(File.Exists(Path.Combine(_webRootPath, "assets/logos", logo.Guid + ".svg"))) + File.Delete(Path.Combine(_webRootPath, "assets/logos", logo.Guid + ".svg")); + + if(File.Exists(Path.Combine(_webRootPath, "assets/logos/webp/1x", logo.Guid + ".webp"))) + File.Delete(Path.Combine(_webRootPath, "assets/logos/webp/1x", logo.Guid + ".webp")); + + if(File.Exists(Path.Combine(_webRootPath, "assets/logos/webp/2x", logo.Guid + ".webp"))) + File.Delete(Path.Combine(_webRootPath, "assets/logos/webp/2x", logo.Guid + ".webp")); + + if(File.Exists(Path.Combine(_webRootPath, "assets/logos/webp/3x", logo.Guid + ".webp"))) + File.Delete(Path.Combine(_webRootPath, "assets/logos/webp/3x", logo.Guid + ".webp")); + + if(File.Exists(Path.Combine(_webRootPath, "assets/logos/png/1x", logo.Guid + ".png"))) + File.Delete(Path.Combine(_webRootPath, "assets/logos/png/1x", logo.Guid + ".png")); + + if(File.Exists(Path.Combine(_webRootPath, "assets/logos/png/2x", logo.Guid + ".png"))) + File.Delete(Path.Combine(_webRootPath, "assets/logos/png/2x", logo.Guid + ".png")); + + if(File.Exists(Path.Combine(_webRootPath, "assets/logos/png/3x", logo.Guid + ".png"))) + File.Delete(Path.Combine(_webRootPath, "assets/logos/png/3x", logo.Guid + ".png")); + + if(File.Exists(Path.Combine(_webRootPath, "assets/logos/thumbs/webp/1x", logo.Guid + ".webp"))) + File.Delete(Path.Combine(_webRootPath, "assets/logos/thumbs/webp/1x", logo.Guid + ".webp")); + + if(File.Exists(Path.Combine(_webRootPath, "assets/logos/thumbs/webp/2x", logo.Guid + ".webp"))) + File.Delete(Path.Combine(_webRootPath, "assets/logos/thumbs/webp/2x", logo.Guid + ".webp")); + + if(File.Exists(Path.Combine(_webRootPath, "assets/logos/thumbs/webp/3x", logo.Guid + ".webp"))) + File.Delete(Path.Combine(_webRootPath, "assets/logos/thumbs/webp/3x", logo.Guid + ".webp")); + + if(File.Exists(Path.Combine(_webRootPath, "assets/logos/thumbs/png/1x", logo.Guid + ".png"))) + File.Delete(Path.Combine(_webRootPath, "assets/logos/thumbs/png/1x", logo.Guid + ".png")); + + if(File.Exists(Path.Combine(_webRootPath, "assets/logos/thumbs/png/2x", logo.Guid + ".png"))) + File.Delete(Path.Combine(_webRootPath, "assets/logos/thumbs/png/2x", logo.Guid + ".png")); + + if(File.Exists(Path.Combine(_webRootPath, "assets/logos/thumbs/png/3x", logo.Guid + ".png"))) + File.Delete(Path.Combine(_webRootPath, "assets/logos/thumbs/png/3x", logo.Guid + ".png")); + } + + [HttpGet] + [AllowAnonymous] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task ChangeYearAsync(int id, int? year) + { + string userId = User.FindFirstValue(ClaimTypes.Sid); + if(userId is null) return; + CompanyLogo logo = await context.CompanyLogos.Where(l => l.Id == id).FirstOrDefaultAsync(); + + if(logo is null) return; + + logo.Year = year; + await context.SaveChangesWithUserAsync(userId); + } + + [HttpPost] + [Authorize(Roles = "Admin,UberAdmin")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task CreateAsync(int companyId, Guid guid, int? year) + { + string userId = User.FindFirstValue(ClaimTypes.Sid); + if(userId is null) return 0; + var logo = new CompanyLogo + { + Guid = guid, + Year = year, + CompanyId = companyId + }; + + await context.CompanyLogos.AddAsync(logo); + await context.SaveChangesWithUserAsync(userId); + + return logo.Id; + } +} diff --git a/Marechai.Server/Controllers/ComputersController.cs b/Marechai.Server/Controllers/ComputersController.cs new file mode 100644 index 00000000..bd682e8b --- /dev/null +++ b/Marechai.Server/Controllers/ComputersController.cs @@ -0,0 +1,121 @@ +/******************************************************************************* +// MARECHAI: Master repository of computing history artifacts information +// --------------------------------------------------------------------------- +// +// Author(s) : Natalia Portillo +// +// --[ License ] ----------------------------------------------------------- +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +// --------------------------------------------------------------------------- +// Copyright © 2003-2025 Natalia Portillo +*******************************************************************************/ + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Security.Claims; +using System.Threading.Tasks; +using Marechai.Data.Dtos; +using Marechai.Database.Models; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Localization; + +namespace Marechai.Server.Controllers; + +[Route("/computers")] +[ApiController] +public class ComputersController(MarechaiContext context) : ControllerBase +{ + [HttpGet] + [AllowAnonymous] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task GetComputersCountAsync() => + await context.Machines.CountAsync(c => c.Type == MachineType.Computer); + + [HttpGet] + [AllowAnonymous] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public Task GetMinimumYearAsync() => context.Machines + .Where(t => t.Type == MachineType.Computer && + t.Introduced.HasValue && + t.Introduced.Value.Year > 1000) + .MinAsync(t => t.Introduced.Value.Year); + + [HttpGet] + [AllowAnonymous] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public Task GetMaximumYearAsync() => context.Machines + .Where(t => t.Type == MachineType.Computer && + t.Introduced.HasValue && + t.Introduced.Value.Year > 1000) + .MaxAsync(t => t.Introduced.Value.Year); + + [HttpGet] + [AllowAnonymous] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task> GetComputersByLetterAsync(char c) => await context.Machines + .Include(m => m.Company) + .Where(m => m.Type == MachineType.Computer && EF.Functions.Like(m.Name, $"{c}%")) + .OrderBy(m => m.Company.Name) + .ThenBy(m => m.Name) + .Select(m => new MachineDto + { + Id = m.Id, + Name = m.Name, + Company = m.Company.Name + }) + .ToListAsync(); + + [HttpGet] + [AllowAnonymous] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task> GetComputersByYearAsync(int year) => await context.Machines + .Include(m => m.Company) + .Where(m => m.Type == MachineType.Computer && m.Introduced != null && m.Introduced.Value.Year == year) + .OrderBy(m => m.Company.Name) + .ThenBy(m => m.Name) + .Select(m => new MachineDto + { + Id = m.Id, + Name = m.Name, + Company = m.Company.Name + }) + .ToListAsync(); + + [HttpGet] + [AllowAnonymous] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task> GetComputersAsync() => await context.Machines.Include(m => m.Company) + .Where(m => m.Type == MachineType.Computer) + .OrderBy(m => m.Company.Name) + .ThenBy(m => m.Name) + .Select(m => new MachineDto + { + Id = m.Id, + Name = m.Name, + Company = m.Company.Name + }) + .ToListAsync(); +} diff --git a/Marechai.Server/Controllers/ConsolesController.cs b/Marechai.Server/Controllers/ConsolesController.cs new file mode 100644 index 00000000..76a024bd --- /dev/null +++ b/Marechai.Server/Controllers/ConsolesController.cs @@ -0,0 +1,121 @@ +/******************************************************************************* +// MARECHAI: Master repository of computing history artifacts information +// --------------------------------------------------------------------------- +// +// Author(s) : Natalia Portillo +// +// --[ License ] ----------------------------------------------------------- +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +// --------------------------------------------------------------------------- +// Copyright © 2003-2025 Natalia Portillo +*******************************************************************************/ + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Security.Claims; +using System.Threading.Tasks; +using Marechai.Data.Dtos; +using Marechai.Database.Models; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Localization; + +namespace Marechai.Server.Controllers; + +[Route("/consoles")] +[ApiController] +public class ConsolesController(MarechaiContext context) : ControllerBase +{ + [HttpGet] + [AllowAnonymous] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task GetConsolesCountAsync() => + await context.Machines.CountAsync(c => c.Type == MachineType.Console); + + [HttpGet] + [AllowAnonymous] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public Task GetMinimumYearAsync() => context.Machines + .Where(t => t.Type == MachineType.Console && + t.Introduced.HasValue && + t.Introduced.Value.Year > 1000) + .MinAsync(t => t.Introduced.Value.Year); + + [HttpGet] + [AllowAnonymous] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public Task GetMaximumYearAsync() => context.Machines + .Where(t => t.Type == MachineType.Console && + t.Introduced.HasValue && + t.Introduced.Value.Year > 1000) + .MaxAsync(t => t.Introduced.Value.Year); + + [HttpGet] + [AllowAnonymous] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task> GetConsolesByLetterAsync(char c) => await context.Machines + .Include(m => m.Company) + .Where(m => m.Type == MachineType.Console && EF.Functions.Like(m.Name, $"{c}%")) + .OrderBy(m => m.Company.Name) + .ThenBy(m => m.Name) + .Select(m => new MachineDto + { + Id = m.Id, + Name = m.Name, + Company = m.Company.Name + }) + .ToListAsync(); + + [HttpGet] + [AllowAnonymous] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task> GetConsolesByYearAsync(int year) => await context.Machines + .Include(m => m.Company) + .Where(m => m.Type == MachineType.Console && m.Introduced != null && m.Introduced.Value.Year == year) + .OrderBy(m => m.Company.Name) + .ThenBy(m => m.Name) + .Select(m => new MachineDto + { + Id = m.Id, + Name = m.Name, + Company = m.Company.Name + }) + .ToListAsync(); + + [HttpGet] + [AllowAnonymous] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task> GetConsolesAsync() => await context.Machines.Include(m => m.Company) + .Where(m => m.Type == MachineType.Console) + .OrderBy(m => m.Company.Name) + .ThenBy(m => m.Name) + .Select(m => new MachineDto + { + Id = m.Id, + Name = m.Name, + Company = m.Company.Name + }) + .ToListAsync(); +} diff --git a/Marechai.Server/Controllers/CurrencyInflationController.cs b/Marechai.Server/Controllers/CurrencyInflationController.cs new file mode 100644 index 00000000..e4af14f9 --- /dev/null +++ b/Marechai.Server/Controllers/CurrencyInflationController.cs @@ -0,0 +1,133 @@ +/******************************************************************************* +// MARECHAI: Master repository of computing history artifacts information +// --------------------------------------------------------------------------- +// +// Author(s) : Natalia Portillo +// +// --[ License ] ----------------------------------------------------------- +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +// --------------------------------------------------------------------------- +// Copyright © 2003-2025 Natalia Portillo +*******************************************************************************/ + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Security.Claims; +using System.Threading.Tasks; +using Marechai.Data.Dtos; +using Marechai.Database.Models; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Localization; + +namespace Marechai.Server.Controllers; + +[Route("/currency-inflation")] +[ApiController] +public class CurrencyInflationController(MarechaiContext context) : ControllerBase +{ + [HttpGet] + [AllowAnonymous] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task> GetAsync() => await context.CurrenciesInflation + .OrderBy(i => i.Currency.Name) + .ThenBy(i => i.Year) + .Select(i => new CurrencyInflationDto + { + Id = i.Id, + CurrencyCode = i.Currency.Code, + CurrencyName = i.Currency.Name, + Year = i.Year, + Inflation = i.Inflation + }) + .ToListAsync(); + + [HttpGet] + [AllowAnonymous] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task GetAsync(int id) => await context.CurrenciesInflation + .Where(b => b.Id == id) + .Select(i => new CurrencyInflationDto + { + Id = i.Id, + CurrencyCode = i.Currency.Code, + CurrencyName = i.Currency.Name, + Year = i.Year, + Inflation = i.Inflation + }) + .FirstOrDefaultAsync(); + + [HttpPost] + [Authorize(Roles = "Admin,UberAdmin")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task UpdateAsync(CurrencyInflationDto dto) + { + string userId = User.FindFirstValue(ClaimTypes.Sid); + if(userId is null) return; + CurrencyInflation model = await context.CurrenciesInflation.FindAsync(dto.Id); + + if(model is null) return; + + model.CurrencyCode = dto.CurrencyCode; + model.Year = dto.Year; + model.Inflation = dto.Inflation; + await context.SaveChangesWithUserAsync(userId); + } + + [HttpPost] + [Authorize(Roles = "Admin,UberAdmin")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task CreateAsync(CurrencyInflationDto dto) + { + string userId = User.FindFirstValue(ClaimTypes.Sid); + if(userId is null) return 0; + var model = new CurrencyInflation + { + CurrencyCode = dto.CurrencyCode, + Year = dto.Year, + Inflation = dto.Inflation + }; + + await context.CurrenciesInflation.AddAsync(model); + await context.SaveChangesWithUserAsync(userId); + + return model.Id; + } + + [HttpDelete] + [Authorize(Roles = "Admin,UberAdmin")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task DeleteAsync(int id) + { + string userId = User.FindFirstValue(ClaimTypes.Sid); + if(userId is null) return; + CurrencyInflation item = await context.CurrenciesInflation.FindAsync(id); + + if(item is null) return; + + context.CurrenciesInflation.Remove(item); + + await context.SaveChangesWithUserAsync(userId); + } +} diff --git a/Marechai.Server/Controllers/CurrencyPeggingController.cs b/Marechai.Server/Controllers/CurrencyPeggingController.cs new file mode 100644 index 00000000..01d21373 --- /dev/null +++ b/Marechai.Server/Controllers/CurrencyPeggingController.cs @@ -0,0 +1,145 @@ +/******************************************************************************* +// MARECHAI: Master repository of computing history artifacts information +// --------------------------------------------------------------------------- +// +// Author(s) : Natalia Portillo +// +// --[ License ] ----------------------------------------------------------- +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +// --------------------------------------------------------------------------- +// Copyright © 2003-2025 Natalia Portillo +*******************************************************************************/ + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Security.Claims; +using System.Threading.Tasks; +using Marechai.Data.Dtos; +using Marechai.Database.Models; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Localization; + +namespace Marechai.Server.Controllers; + +[Route("/currency-pegging")] +[ApiController] +public class CurrencyPeggingController(MarechaiContext context) : ControllerBase +{ + [HttpGet] + [AllowAnonymous] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task> GetAsync() => await context.CurrenciesPegging + .OrderBy(i => i.Source.Name) + .ThenBy(i => i.Destination.Name) + .ThenBy(i => i.Start) + .ThenBy(i => i.End) + .Select(i => new CurrencyPeggingDto + { + Id = i.Id, + SourceCode = i.Source.Code, + SourceName = i.Source.Name, + DestinationCode = i.Source.Code, + DestinationName = i.Source.Name, + Ratio = i.Ratio, + Start = i.Start, + End = i.End + }) + .ToListAsync(); + + [HttpGet] + [AllowAnonymous] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task GetAsync(int id) => await context.CurrenciesPegging + .Where(b => b.Id == id) + .Select(i => new CurrencyPeggingDto + { + Id = i.Id, + SourceCode = i.Source.Code, + SourceName = i.Source.Name, + DestinationCode = i.Destination.Code, + DestinationName = i.Destination.Name, + Ratio = i.Ratio, + Start = i.Start, + End = i.End + }) + .FirstOrDefaultAsync(); + + [HttpPost] + [Authorize(Roles = "Admin,UberAdmin")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task UpdateAsync(CurrencyPeggingDto dto) + { + string userId = User.FindFirstValue(ClaimTypes.Sid); + if(userId is null) return; + CurrencyPegging model = await context.CurrenciesPegging.FindAsync(dto.Id); + + if(model is null) return; + + model.SourceCode = dto.SourceCode; + model.DestinationCode = dto.DestinationCode; + model.Ratio = dto.Ratio; + model.Start = dto.Start; + model.End = dto.End; + await context.SaveChangesWithUserAsync(userId); + } + + [HttpPost] + [Authorize(Roles = "Admin,UberAdmin")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task CreateAsync(CurrencyPeggingDto dto) + { + string userId = User.FindFirstValue(ClaimTypes.Sid); + if(userId is null) return 0; + var model = new CurrencyPegging + { + SourceCode = dto.SourceCode, + DestinationCode = dto.DestinationCode, + Ratio = dto.Ratio, + Start = dto.Start, + End = dto.End + }; + + await context.CurrenciesPegging.AddAsync(model); + await context.SaveChangesWithUserAsync(userId); + + return model.Id; + } + + [HttpDelete] + [Authorize(Roles = "Admin,UberAdmin")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task DeleteAsync(int id) + { + string userId = User.FindFirstValue(ClaimTypes.Sid); + if(userId is null) return; + CurrencyPegging item = await context.CurrenciesPegging.FindAsync(id); + + if(item is null) return; + + context.CurrenciesPegging.Remove(item); + + await context.SaveChangesWithUserAsync(userId); + } +} diff --git a/Marechai.Server/Controllers/DocumentCompaniesController.cs b/Marechai.Server/Controllers/DocumentCompaniesController.cs new file mode 100644 index 00000000..a8b897cb --- /dev/null +++ b/Marechai.Server/Controllers/DocumentCompaniesController.cs @@ -0,0 +1,128 @@ +/******************************************************************************* +// MARECHAI: Master repository of computing history artifacts information +// --------------------------------------------------------------------------- +// +// Author(s) : Natalia Portillo +// +// --[ License ] ----------------------------------------------------------- +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +// --------------------------------------------------------------------------- +// Copyright © 2003-2025 Natalia Portillo +*******************************************************************************/ + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Security.Claims; +using System.Threading.Tasks; +using Marechai.Data.Dtos; +using Marechai.Database.Models; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Localization; + +namespace Marechai.Server.Controllers; + +[Route("/document-companies")] +[ApiController] +public class DocumentCompaniesController(MarechaiContext context) : ControllerBase +{ + [HttpGet] + [AllowAnonymous] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task> GetAsync() => await context.DocumentCompanies + .OrderBy(c => c.Name) + .Select(d => new DocumentCompanyDto + { + Id = d.Id, + Name = d.Name, + Company = d.Company.Name, + CompanyId = d.CompanyId + }) + .ToListAsync(); + + [HttpGet] + [AllowAnonymous] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task GetAsync(int id) => await context.DocumentCompanies + .Where(d => d.Id == id) + .Select(d => new DocumentCompanyDto + { + Id = d.Id, + Name = d.Name, + CompanyId = d.CompanyId + }) + .FirstOrDefaultAsync(); + + [HttpPost] + [Authorize(Roles = "Admin,UberAdmin")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task UpdateAsync(DocumentCompanyDto dto) + { + string userId = User.FindFirstValue(ClaimTypes.Sid); + if(userId is null) return; + DocumentCompany model = await context.DocumentCompanies.FindAsync(dto.Id); + + if(model is null) return; + + model.CompanyId = dto.CompanyId; + model.Name = dto.Name; + + await context.SaveChangesWithUserAsync(userId); + } + + [HttpPost] + [Authorize(Roles = "Admin,UberAdmin")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task CreateAsync(DocumentCompanyDto dto) + { + string userId = User.FindFirstValue(ClaimTypes.Sid); + if(userId is null) return 0; + var model = new DocumentCompany + { + CompanyId = dto.CompanyId, + Name = dto.Name + }; + + await context.DocumentCompanies.AddAsync(model); + await context.SaveChangesWithUserAsync(userId); + + return model.Id; + } + + [HttpDelete] + [Authorize(Roles = "Admin,UberAdmin")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task DeleteAsync(int id) + { + string userId = User.FindFirstValue(ClaimTypes.Sid); + if(userId is null) return; + DocumentCompany item = await context.DocumentCompanies.FindAsync(id); + + if(item is null) return; + + context.DocumentCompanies.Remove(item); + + await context.SaveChangesWithUserAsync(userId); + } +} diff --git a/Marechai.Server/Controllers/DocumentPeopleController.cs b/Marechai.Server/Controllers/DocumentPeopleController.cs new file mode 100644 index 00000000..8b66ffe5 --- /dev/null +++ b/Marechai.Server/Controllers/DocumentPeopleController.cs @@ -0,0 +1,139 @@ +/******************************************************************************* +// MARECHAI: Master repository of computing history artifacts information +// --------------------------------------------------------------------------- +// +// Author(s) : Natalia Portillo +// +// --[ License ] ----------------------------------------------------------- +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +// --------------------------------------------------------------------------- +// Copyright © 2003-2025 Natalia Portillo +*******************************************************************************/ + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Security.Claims; +using System.Threading.Tasks; +using Marechai.Data.Dtos; +using Marechai.Database.Models; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Localization; + +namespace Marechai.Server.Controllers; + +[Route("/document-people")] +[ApiController] +public class DocumentPeopleController(MarechaiContext context) : ControllerBase +{ + [HttpGet] + [AllowAnonymous] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task> GetAsync() => await context.DocumentPeople + .OrderBy(d => d.DisplayName) + .ThenBy(d => d.Alias) + .ThenBy(d => d.Name) + .ThenBy(d => d.Surname) + .Select(d => new DocumentPersonDto + { + Id = d.Id, + Name = d.FullName, + Person = d.Person.FullName, + PersonId = d.PersonId + }) + .ToListAsync(); + + [HttpGet] + [AllowAnonymous] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task GetAsync(int id) => await context.DocumentPeople.Where(p => p.Id == id) + .Select(d => new DocumentPersonDto + { + Id = d.Id, + Alias = d.Alias, + Name = d.Name, + Surname = d.Surname, + DisplayName = d.DisplayName, + PersonId = d.PersonId + }) + .FirstOrDefaultAsync(); + + [HttpPost] + [Authorize(Roles = "Admin,UberAdmin")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task UpdateAsync(DocumentPersonDto dto) + { + string userId = User.FindFirstValue(ClaimTypes.Sid); + if(userId is null) return; + DocumentPerson model = await context.DocumentPeople.FindAsync(dto.Id); + + if(model is null) return; + + model.Alias = dto.Alias; + model.Name = dto.Name; + model.Surname = dto.Surname; + model.DisplayName = dto.DisplayName; + model.PersonId = dto.PersonId; + + await context.SaveChangesWithUserAsync(userId); + } + + [HttpPost] + [Authorize(Roles = "Admin,UberAdmin")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task CreateAsync(DocumentPersonDto dto) + { + string userId = User.FindFirstValue(ClaimTypes.Sid); + if(userId is null) return 0; + var model = new DocumentPerson + { + Alias = dto.Alias, + Name = dto.Name, + Surname = dto.Surname, + DisplayName = dto.DisplayName, + PersonId = dto.PersonId + }; + + await context.AddAsync(model); + await context.SaveChangesWithUserAsync(userId); + + return model.Id; + } + + [HttpDelete] + [Authorize(Roles = "Admin,UberAdmin")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task DeleteAsync(int id) + { + string userId = User.FindFirstValue(ClaimTypes.Sid); + if(userId is null) return; + DocumentPerson item = await context.DocumentPeople.FindAsync(id); + + if(item is null) return; + + context.DocumentPeople.Remove(item); + + await context.SaveChangesWithUserAsync(userId); + } +} diff --git a/Marechai.Server/Controllers/DocumentRolesController.cs b/Marechai.Server/Controllers/DocumentRolesController.cs new file mode 100644 index 00000000..6309b6af --- /dev/null +++ b/Marechai.Server/Controllers/DocumentRolesController.cs @@ -0,0 +1,85 @@ +/******************************************************************************* +// MARECHAI: Master repository of computing history artifacts information +// --------------------------------------------------------------------------- +// +// Author(s) : Natalia Portillo +// +// --[ License ] ----------------------------------------------------------- +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +// --------------------------------------------------------------------------- +// Copyright © 2003-2025 Natalia Portillo +*******************************************************************************/ + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Security.Claims; +using System.Threading.Tasks; +using Marechai.Data.Dtos; +using Marechai.Database.Models; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Localization; + +namespace Marechai.Server.Controllers; + +[Route("/document-roles")] +[ApiController] +public class DocumentRolesController(MarechaiContext context) : ControllerBase +{ + [HttpGet] + [AllowAnonymous] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task> GetAsync() => await context.DocumentRoles.OrderBy(c => c.Name) + .Select(c => new DocumentRoleDto + { + Id = c.Id, + Name = c.Name, + Enabled = c.Enabled + }) + .ToListAsync(); + + [HttpGet] + [AllowAnonymous] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task> GetEnabledAsync() => await context.DocumentRoles + .Where(c => c.Enabled) + .OrderBy(c => c.Name) + .Select(c => new DocumentRoleDto + { + Id = c.Id, + Name = c.Name, + Enabled = c.Enabled + }) + .ToListAsync(); + + [HttpGet] + [AllowAnonymous] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task GetAsync(string id) => await context.DocumentRoles.Where(c => c.Id == id) + .Select(c => new DocumentRoleDto + { + Id = c.Id, + Name = c.Name, + Enabled = c.Enabled + }) + .FirstOrDefaultAsync(); +} diff --git a/Marechai.Server/Controllers/DocumentScansController.cs b/Marechai.Server/Controllers/DocumentScansController.cs new file mode 100644 index 00000000..4af8f7a5 --- /dev/null +++ b/Marechai.Server/Controllers/DocumentScansController.cs @@ -0,0 +1,161 @@ +/******************************************************************************* +// MARECHAI: Master repository of computing history artifacts information +// --------------------------------------------------------------------------- +// +// Author(s) : Natalia Portillo +// +// --[ License ] ----------------------------------------------------------- +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +// --------------------------------------------------------------------------- +// Copyright © 2003-2025 Natalia Portillo +*******************************************************************************/ + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Security.Claims; +using System.Threading.Tasks; +using Marechai.Data.Dtos; +using Marechai.Database.Models; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Localization; + +namespace Marechai.Server.Controllers; + +[Route("/document-scans")] +[ApiController] +public class DocumentScansController(MarechaiContext context) : ControllerBase +{ + [HttpGet] + [AllowAnonymous] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task> GetGuidsByDocumentAsync(long bookId) => + await context.DocumentScans.Where(p => p.DocumentId == bookId).Select(p => p.Id).ToListAsync(); + + [HttpGet] + [AllowAnonymous] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task GetAsync(Guid id) => await context.DocumentScans.Where(p => p.Id == id) + .Select(p => new DocumentScanDto + { + Author = p.Author, + DocumentId = p.Document.Id, + ColorSpace = p.ColorSpace, + Comments = p.Comments, + CreationDate = p.CreationDate, + ExifVersion = p.ExifVersion, + HorizontalResolution = p.HorizontalResolution, + Id = p.Id, + ResolutionUnit = p.ResolutionUnit, + Page = p.Page, + ScannerManufacturer = p.ScannerManufacturer, + ScannerModel = p.ScannerModel, + SoftwareUsed = p.SoftwareUsed, + Type = p.Type, + UploadDate = p.UploadDate, + UserId = p.UserId, + VerticalResolution = p.VerticalResolution, + OriginalExtension = p.OriginalExtension + }) + .FirstOrDefaultAsync(); + + [HttpPost] + [Authorize(Roles = "Admin,UberAdmin")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task UpdateAsync(DocumentScanDto dto) + { + string userId = User.FindFirstValue(ClaimTypes.Sid); + if(userId is null) return; + DocumentScan model = await context.DocumentScans.FindAsync(dto.Id); + + if(model is null) return; + + model.Author = dto.Author; + model.ColorSpace = dto.ColorSpace; + model.Comments = dto.Comments; + model.CreationDate = dto.CreationDate; + model.ExifVersion = dto.ExifVersion; + model.HorizontalResolution = dto.HorizontalResolution; + model.ResolutionUnit = dto.ResolutionUnit; + model.Page = dto.Page; + model.ScannerManufacturer = dto.ScannerManufacturer; + model.ScannerModel = dto.ScannerModel; + model.Type = dto.Type; + model.SoftwareUsed = dto.SoftwareUsed; + model.VerticalResolution = dto.VerticalResolution; + + await context.SaveChangesWithUserAsync(userId); + } + + [HttpPost] + [Authorize(Roles = "Admin,UberAdmin")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task CreateAsync(DocumentScanDto dto) + { + string userId = User.FindFirstValue(ClaimTypes.Sid); + if(userId is null) return null; + var model = new DocumentScan + { + Author = dto.Author, + DocumentId = dto.DocumentId, + ColorSpace = dto.ColorSpace, + Comments = dto.Comments, + CreationDate = dto.CreationDate, + ExifVersion = dto.ExifVersion, + HorizontalResolution = dto.HorizontalResolution, + Id = dto.Id, + ResolutionUnit = dto.ResolutionUnit, + Page = dto.Page, + ScannerManufacturer = dto.ScannerManufacturer, + ScannerModel = dto.ScannerModel, + Type = dto.Type, + SoftwareUsed = dto.SoftwareUsed, + UploadDate = dto.UploadDate, + UserId = dto.UserId, + VerticalResolution = dto.VerticalResolution, + OriginalExtension = dto.OriginalExtension + }; + + await context.DocumentScans.AddAsync(model); + await context.SaveChangesWithUserAsync(userId); + + return model.Id; + } + + [HttpDelete] + [Authorize(Roles = "Admin,UberAdmin")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task DeleteAsync(Guid id) + { + string userId = User.FindFirstValue(ClaimTypes.Sid); + if(userId is null) return; + DocumentScan item = await context.DocumentScans.FindAsync(id); + + if(item is null) return; + + context.DocumentScans.Remove(item); + + await context.SaveChangesWithUserAsync(userId); + } +} diff --git a/Marechai.Server/Controllers/DocumentsByMachineController.cs b/Marechai.Server/Controllers/DocumentsByMachineController.cs new file mode 100644 index 00000000..b58994b8 --- /dev/null +++ b/Marechai.Server/Controllers/DocumentsByMachineController.cs @@ -0,0 +1,97 @@ +/******************************************************************************* +// MARECHAI: Master repository of computing history artifacts information +// --------------------------------------------------------------------------- +// +// Author(s) : Natalia Portillo +// +// --[ License ] ----------------------------------------------------------- +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +// --------------------------------------------------------------------------- +// Copyright © 2003-2025 Natalia Portillo +*******************************************************************************/ + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Security.Claims; +using System.Threading.Tasks; +using Marechai.Data.Dtos; +using Marechai.Database.Models; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Localization; + +namespace Marechai.Server.Controllers; + +[Route("/documents-by-machine")] +[ApiController] +public class DocumentsByMachineController(MarechaiContext context) : ControllerBase +{ + [HttpGet] + [AllowAnonymous] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task> GetByDocument(long bookId) => await context.DocumentsByMachines + .Where(p => p.DocumentId == bookId) + .Select(p => new DocumentByMachineDto + { + Id = p.Id, + DocumentId = p.DocumentId, + MachineId = p.MachineId, + Machine = p.Machine.Name + }) + .OrderBy(p => p.Machine) + .ToListAsync(); + + [HttpDelete] + [Authorize(Roles = "Admin,UberAdmin")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task DeleteAsync(long id) + { + string userId = User.FindFirstValue(ClaimTypes.Sid); + if(userId is null) return; + DocumentsByMachine item = await context.DocumentsByMachines.FindAsync(id); + + if(item is null) return; + + context.DocumentsByMachines.Remove(item); + + await context.SaveChangesWithUserAsync(userId); + } + + [HttpPost] + [Authorize(Roles = "Admin,UberAdmin")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task CreateAsync(int machineId, long bookId) + { + string userId = User.FindFirstValue(ClaimTypes.Sid); + if(userId is null) return 0; + var item = new DocumentsByMachine + { + MachineId = machineId, + DocumentId = bookId + }; + + await context.DocumentsByMachines.AddAsync(item); + await context.SaveChangesWithUserAsync(userId); + + return item.Id; + } +} diff --git a/Marechai.Server/Controllers/DocumentsByMachineFamilyController.cs b/Marechai.Server/Controllers/DocumentsByMachineFamilyController.cs new file mode 100644 index 00000000..ed9ab6d4 --- /dev/null +++ b/Marechai.Server/Controllers/DocumentsByMachineFamilyController.cs @@ -0,0 +1,97 @@ +/******************************************************************************* +// MARECHAI: Master repository of computing history artifacts information +// --------------------------------------------------------------------------- +// +// Author(s) : Natalia Portillo +// +// --[ License ] ----------------------------------------------------------- +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +// --------------------------------------------------------------------------- +// Copyright © 2003-2025 Natalia Portillo +*******************************************************************************/ + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Security.Claims; +using System.Threading.Tasks; +using Marechai.Data.Dtos; +using Marechai.Database.Models; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Localization; + +namespace Marechai.Server.Controllers; + +[Route("/documents-by-machine-family")] +[ApiController] +public class DocumentsByMachineFamilyController(MarechaiContext context) : ControllerBase +{ + [HttpGet] + [AllowAnonymous] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task> GetByDocument(long bookId) => await context + .DocumentsByMachineFamilies.Where(p => p.DocumentId == bookId) + .Select(p => new DocumentByMachineFamilyDto + { + Id = p.Id, + DocumentId = p.DocumentId, + MachineFamilyId = p.MachineFamilyId, + MachineFamily = p.MachineFamily.Name + }) + .OrderBy(p => p.MachineFamily) + .ToListAsync(); + + [HttpDelete] + [Authorize(Roles = "Admin,UberAdmin")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task DeleteAsync(long id) + { + string userId = User.FindFirstValue(ClaimTypes.Sid); + if(userId is null) return; + DocumentsByMachineFamily item = await context.DocumentsByMachineFamilies.FindAsync(id); + + if(item is null) return; + + context.DocumentsByMachineFamilies.Remove(item); + + await context.SaveChangesWithUserAsync(userId); + } + + [HttpPost] + [Authorize(Roles = "Admin,UberAdmin")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task CreateAsync(int machineFamilyId, long bookId) + { + string userId = User.FindFirstValue(ClaimTypes.Sid); + if(userId is null) return 0; + var item = new DocumentsByMachineFamily + { + MachineFamilyId = machineFamilyId, + DocumentId = bookId + }; + + await context.DocumentsByMachineFamilies.AddAsync(item); + await context.SaveChangesWithUserAsync(userId); + + return item.Id; + } +} diff --git a/Marechai.Server/Controllers/DocumentsController.cs b/Marechai.Server/Controllers/DocumentsController.cs new file mode 100644 index 00000000..64ac0c38 --- /dev/null +++ b/Marechai.Server/Controllers/DocumentsController.cs @@ -0,0 +1,147 @@ +/******************************************************************************* +// MARECHAI: Master repository of computing history artifacts information +// --------------------------------------------------------------------------- +// +// Author(s) : Natalia Portillo +// +// --[ License ] ----------------------------------------------------------- +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +// --------------------------------------------------------------------------- +// Copyright © 2003-2025 Natalia Portillo +*******************************************************************************/ + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Security.Claims; +using System.Threading.Tasks; +using Marechai.Data.Dtos; +using Marechai.Database.Models; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Localization; + +namespace Marechai.Server.Controllers; + +[Route("/documents")] +[ApiController] +public class DocumentsController(MarechaiContext context) : ControllerBase +{ + [HttpGet] + [AllowAnonymous] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task> GetAsync() => await context.Documents.OrderBy(b => b.NativeTitle) + .ThenBy(b => b.Published) + .ThenBy(b => b.Title) + .Select(b => new DocumentDto + { + Id = b.Id, + Title = b.Title, + NativeTitle = b.NativeTitle, + Published = b.Published, + Synopsis = b.Synopsis, + CountryId = b.CountryId, + Country = b.Country.Name + }) + .ToListAsync(); + + [HttpGet] + [AllowAnonymous] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task GetAsync(long id) => await context.Documents.Where(b => b.Id == id) + .Select(b => new DocumentDto + { + Id = b.Id, + Title = b.Title, + NativeTitle = b.NativeTitle, + Published = b.Published, + Synopsis = b.Synopsis, + CountryId = b.CountryId, + Country = b.Country.Name + }) + .FirstOrDefaultAsync(); + + [HttpPost] + [Authorize(Roles = "Admin,UberAdmin")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task UpdateAsync(DocumentDto dto) + { + string userId = User.FindFirstValue(ClaimTypes.Sid); + if(userId is null) return; + Document model = await context.Documents.FindAsync(dto.Id); + + if(model is null) return; + + model.Title = dto.Title; + model.NativeTitle = dto.NativeTitle; + model.Published = dto.Published; + model.Synopsis = dto.Synopsis; + model.CountryId = dto.CountryId; + await context.SaveChangesWithUserAsync(userId); + } + + [HttpPost] + [Authorize(Roles = "Admin,UberAdmin")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task CreateAsync(DocumentDto dto) + { + string userId = User.FindFirstValue(ClaimTypes.Sid); + if(userId is null) return 0; + var model = new Document + { + Title = dto.Title, + NativeTitle = dto.NativeTitle, + Published = dto.Published, + Synopsis = dto.Synopsis, + CountryId = dto.CountryId + }; + + await context.Documents.AddAsync(model); + await context.SaveChangesWithUserAsync(userId); + + return model.Id; + } + + [HttpGet] + [AllowAnonymous] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task GetSynopsisTextAsync(int id) => + (await context.Documents.FirstOrDefaultAsync(d => d.Id == id))?.Synopsis; + + [HttpDelete] + [Authorize(Roles = "Admin,UberAdmin")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task DeleteAsync(long id) + { + string userId = User.FindFirstValue(ClaimTypes.Sid); + if(userId is null) return; + Document item = await context.Documents.FindAsync(id); + + if(item is null) return; + + context.Documents.Remove(item); + + await context.SaveChangesWithUserAsync(userId); + } +} diff --git a/Marechai.Server/Controllers/DumpsController.cs b/Marechai.Server/Controllers/DumpsController.cs new file mode 100644 index 00000000..ca97462f --- /dev/null +++ b/Marechai.Server/Controllers/DumpsController.cs @@ -0,0 +1,147 @@ +/******************************************************************************* +// MARECHAI: Master repository of computing history artifacts information +// --------------------------------------------------------------------------- +// +// Author(s) : Natalia Portillo +// +// --[ License ] ----------------------------------------------------------- +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +// --------------------------------------------------------------------------- +// Copyright © 2003-2025 Natalia Portillo +*******************************************************************************/ + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Security.Claims; +using System.Threading.Tasks; +using Marechai.Data.Dtos; +using Marechai.Database.Models; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Localization; + +namespace Marechai.Server.Controllers; + +[Route("/dumps")] +[ApiController] +public class DumpsController(MarechaiContext context) : ControllerBase +{ + [HttpGet] + [AllowAnonymous] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task> GetAsync() => await context.Dumps.OrderBy(d => d.Dumper) + .ThenBy(d => d.DumpingGroup) + .ThenBy(b => b.Media.Title) + .ThenBy(d => d.DumpDate) + .Select(d => new DumpDto + { + Id = d.Id, + Dumper = d.Dumper, + UserId = d.UserId, + DumpingGroup = d.DumpingGroup, + DumpDate = d.DumpDate, + UserName = d.User.UserName, + MediaId = d.MediaId, + MediaTitle = d.Media.Title, + MediaDumpId = d.MediaDumpId + }) + .ToListAsync(); + + [HttpGet] + [AllowAnonymous] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task GetAsync(ulong id) => await context.Dumps.Where(d => d.Id == id) + .Select(d => new DumpDto + { + Id = d.Id, + Dumper = d.Dumper, + UserId = d.User.Id, + DumpingGroup = d.DumpingGroup, + DumpDate = d.DumpDate, + UserName = d.User.UserName, + MediaId = d.MediaId, + MediaTitle = d.Media.Title, + MediaDumpId = d.MediaDumpId + }) + .FirstOrDefaultAsync(); + + [HttpPost] + [Authorize(Roles = "Admin,UberAdmin")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task UpdateAsync(DumpDto dto) + { + string userId = User.FindFirstValue(ClaimTypes.Sid); + if(userId is null) return; + Dump model = await context.Dumps.FindAsync(dto.Id); + + if(model is null) return; + + model.Dumper = dto.Dumper; + model.UserId = dto.UserId; + model.DumpingGroup = dto.DumpingGroup; + model.DumpDate = dto.DumpDate; + model.MediaId = dto.MediaId; + model.MediaDumpId = dto.MediaDumpId; + await context.SaveChangesWithUserAsync(userId); + } + + [HttpPost] + [Authorize(Roles = "Admin,UberAdmin")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task CreateAsync(DumpDto dto) + { + string userId = User.FindFirstValue(ClaimTypes.Sid); + if(userId is null) return null; + var model = new Dump + { + Dumper = dto.Dumper, + UserId = dto.UserId, + DumpingGroup = dto.DumpingGroup, + DumpDate = dto.DumpDate, + MediaId = dto.MediaId, + MediaDumpId = dto.MediaDumpId + }; + + await context.Dumps.AddAsync(model); + await context.SaveChangesWithUserAsync(userId); + + return model.Id; + } + + [HttpDelete] + [Authorize(Roles = "Admin,UberAdmin")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task DeleteAsync(ulong id) + { + string userId = User.FindFirstValue(ClaimTypes.Sid); + if(userId is null) return; + Dump item = await context.Dumps.FindAsync(id); + + if(item is null) return; + + context.Dumps.Remove(item); + + await context.SaveChangesWithUserAsync(userId); + } +} diff --git a/Marechai.Server/Controllers/GpusByMachineController.cs b/Marechai.Server/Controllers/GpusByMachineController.cs new file mode 100644 index 00000000..8d0bef96 --- /dev/null +++ b/Marechai.Server/Controllers/GpusByMachineController.cs @@ -0,0 +1,99 @@ +/******************************************************************************* +// MARECHAI: Master repository of computing history artifacts information +// --------------------------------------------------------------------------- +// +// Author(s) : Natalia Portillo +// +// --[ License ] ----------------------------------------------------------- +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +// --------------------------------------------------------------------------- +// Copyright © 2003-2025 Natalia Portillo +*******************************************************************************/ + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Security.Claims; +using System.Threading.Tasks; +using Marechai.Data.Dtos; +using Marechai.Database.Models; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Localization; + +namespace Marechai.Server.Controllers; + +[Route("/gpus-by-machine")] +[ApiController] +public class GpusByMachineController(MarechaiContext context) : ControllerBase +{ + [HttpGet] + [AllowAnonymous] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task> GetByMachine(int machineId) => await context.GpusByMachine + .Where(g => g.MachineId == machineId) + .Select(g => new GpuByMachineDto + { + Id = g.Id, + Name = g.Gpu.Name, + CompanyName = g.Gpu.Company.Name, + GpuId = g.GpuId, + MachineId = g.MachineId + }) + .OrderBy(g => g.CompanyName) + .ThenBy(g => g.Name) + .ToListAsync(); + + [HttpDelete] + [Authorize(Roles = "Admin,UberAdmin")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task DeleteAsync(long id) + { + string userId = User.FindFirstValue(ClaimTypes.Sid); + if(userId is null) return; + GpusByMachine item = await context.GpusByMachine.FindAsync(id); + + if(item is null) return; + + context.GpusByMachine.Remove(item); + + await context.SaveChangesWithUserAsync(userId); + } + + [HttpPost] + [Authorize(Roles = "Admin,UberAdmin")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task CreateAsync(int gpuId, int machineId) + { + string userId = User.FindFirstValue(ClaimTypes.Sid); + if(userId is null) return 0; + var item = new GpusByMachine + { + GpuId = gpuId, + MachineId = machineId + }; + + await context.GpusByMachine.AddAsync(item); + await context.SaveChangesWithUserAsync(userId); + + return item.Id; + } +} diff --git a/Marechai.Server/Controllers/GpusController.cs b/Marechai.Server/Controllers/GpusController.cs new file mode 100644 index 00000000..1916b67d --- /dev/null +++ b/Marechai.Server/Controllers/GpusController.cs @@ -0,0 +1,175 @@ +/******************************************************************************* +// MARECHAI: Master repository of computing history artifacts information +// --------------------------------------------------------------------------- +// +// Author(s) : Natalia Portillo +// +// --[ License ] ----------------------------------------------------------- +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +// --------------------------------------------------------------------------- +// Copyright © 2003-2025 Natalia Portillo +*******************************************************************************/ + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Security.Claims; +using System.Threading.Tasks; +using Marechai.Data.Dtos; +using Marechai.Database.Models; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Localization; + +namespace Marechai.Server.Controllers; + +[Route("/gpus")] +[ApiController] +public class GpusController(MarechaiContext context) : ControllerBase +{ + [HttpGet] + [AllowAnonymous] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task> GetAsync() => await context.Gpus.OrderBy(g => g.Company.Name) + .ThenBy(g => g.Name) + .ThenBy(g => g.Introduced) + .Select(g => new GpuDto + { + Id = g.Id, + Company = g.Company.Name, + Introduced = g.Introduced, + ModelCode = g.ModelCode, + Name = g.Name + }) + .ToListAsync(); + + [HttpGet] + [AllowAnonymous] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task> GetByMachineAsync(int machineId) => await context.GpusByMachine + .Where(g => g.MachineId == machineId) + .Select(g => g.Gpu) + .OrderBy(g => g.Company.Name) + .ThenBy(g => g.Name) + .Select(g => new GpuDto + { + Id = g.Id, + Name = g.Name, + Company = g.Company.Name, + CompanyId = g.Company.Id, + ModelCode = g.ModelCode, + Introduced = g.Introduced, + Package = g.Package, + Process = g.Process, + ProcessNm = g.ProcessNm, + DieSize = g.DieSize, + Transistors = g.Transistors + }) + .ToListAsync(); + + [HttpGet] + [AllowAnonymous] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task GetAsync(int id) => await context.Gpus.Where(g => g.Id == id) + .Select(g => new GpuDto + { + Id = g.Id, + Name = g.Name, + CompanyId = g.Company.Id, + ModelCode = g.ModelCode, + Introduced = g.Introduced, + Package = g.Package, + Process = g.Process, + ProcessNm = g.ProcessNm, + DieSize = g.DieSize, + Transistors = g.Transistors + }) + .FirstOrDefaultAsync(); + + [HttpPost] + [Authorize(Roles = "Admin,UberAdmin")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task UpdateAsync(GpuDto dto) + { + string userId = User.FindFirstValue(ClaimTypes.Sid); + if(userId is null) return; + Gpu model = await context.Gpus.FindAsync(dto.Id); + + if(model is null) return; + + model.Name = dto.Name; + model.CompanyId = dto.CompanyId; + model.ModelCode = dto.ModelCode; + model.Introduced = dto.Introduced; + model.Package = dto.Package; + model.Process = dto.Process; + model.ProcessNm = dto.ProcessNm; + model.DieSize = dto.DieSize; + model.Transistors = dto.Transistors; + + await context.SaveChangesWithUserAsync(userId); + } + + [HttpPost] + [Authorize(Roles = "Admin,UberAdmin")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task CreateAsync(GpuDto dto) + { + string userId = User.FindFirstValue(ClaimTypes.Sid); + if(userId is null) return 0; + var model = new Gpu + { + Name = dto.Name, + CompanyId = dto.CompanyId, + ModelCode = dto.ModelCode, + Introduced = dto.Introduced, + Package = dto.Package, + Process = dto.Process, + ProcessNm = dto.ProcessNm, + DieSize = dto.DieSize, + Transistors = dto.Transistors + }; + + await context.Gpus.AddAsync(model); + await context.SaveChangesWithUserAsync(userId); + + return model.Id; + } + + [HttpDelete] + [Authorize(Roles = "Admin,UberAdmin")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task DeleteAsync(int id) + { + string userId = User.FindFirstValue(ClaimTypes.Sid); + if(userId is null) return; + Gpu item = await context.Gpus.FindAsync(id); + + if(item is null) return; + + context.Gpus.Remove(item); + + await context.SaveChangesWithUserAsync(userId); + } +} diff --git a/Marechai.Server/Controllers/InstructionSetExtensionsByProcessorController.cs b/Marechai.Server/Controllers/InstructionSetExtensionsByProcessorController.cs new file mode 100644 index 00000000..96e34694 --- /dev/null +++ b/Marechai.Server/Controllers/InstructionSetExtensionsByProcessorController.cs @@ -0,0 +1,98 @@ +/******************************************************************************* +// MARECHAI: Master repository of computing history artifacts information +// --------------------------------------------------------------------------- +// +// Author(s) : Natalia Portillo +// +// --[ License ] ----------------------------------------------------------- +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +// --------------------------------------------------------------------------- +// Copyright © 2003-2025 Natalia Portillo +*******************************************************************************/ + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Security.Claims; +using System.Threading.Tasks; +using Marechai.Data.Dtos; +using Marechai.Database.Models; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Localization; + +namespace Marechai.Server.Controllers; + +[Route("/instruction-set-extensions-by-processor")] +[ApiController] +public class InstructionSetExtensionsByProcessorController(MarechaiContext context) : ControllerBase +{ + [HttpGet] + [AllowAnonymous] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task> GetByProcessor(int processorId) => + await context.InstructionSetExtensionsByProcessor.Where(e => e.ProcessorId == processorId) + .Select(e => new InstructionSetExtensionByProcessorDto + { + Id = e.Id, + Extension = e.Extension.Extension, + Processor = e.Processor.Name, + ProcessorId = e.ProcessorId, + ExtensionId = e.ExtensionId + }) + .OrderBy(e => e.Extension) + .ToListAsync(); + + [HttpDelete] + [Authorize(Roles = "Admin,UberAdmin")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task DeleteAsync(int id) + { + string userId = User.FindFirstValue(ClaimTypes.Sid); + if(userId is null) return; + InstructionSetExtensionsByProcessor item = await context.InstructionSetExtensionsByProcessor.FindAsync(id); + + if(item is null) return; + + context.InstructionSetExtensionsByProcessor.Remove(item); + + await context.SaveChangesWithUserAsync(userId); + } + + [HttpPost] + [Authorize(Roles = "Admin,UberAdmin")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task CreateAsync(int processorId, int extensionId) + { + string userId = User.FindFirstValue(ClaimTypes.Sid); + if(userId is null) return 0; + var item = new InstructionSetExtensionsByProcessor + { + ProcessorId = processorId, + ExtensionId = extensionId + }; + + await context.InstructionSetExtensionsByProcessor.AddAsync(item); + await context.SaveChangesWithUserAsync(userId); + + return item.Id; + } +} diff --git a/Marechai.Server/Controllers/InstructionSetExtensionsController.cs b/Marechai.Server/Controllers/InstructionSetExtensionsController.cs new file mode 100644 index 00000000..bfa64283 --- /dev/null +++ b/Marechai.Server/Controllers/InstructionSetExtensionsController.cs @@ -0,0 +1,132 @@ +/******************************************************************************* +// MARECHAI: Master repository of computing history artifacts information +// --------------------------------------------------------------------------- +// +// Author(s) : Natalia Portillo +// +// --[ License ] ----------------------------------------------------------- +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +// --------------------------------------------------------------------------- +// Copyright © 2003-2025 Natalia Portillo +*******************************************************************************/ + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Security.Claims; +using System.Threading.Tasks; +using Marechai.Data.Dtos; +using Marechai.Database.Models; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Localization; + +namespace Marechai.Server.Controllers; + +[Route("/instruction-set-extensions")] +[ApiController] +public class InstructionSetExtensionsController(MarechaiContext context) : ControllerBase +{ + [HttpGet] + [AllowAnonymous] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task> GetAsync() => await context.InstructionSetExtensions + .OrderBy(e => e.Extension) + .Select(e => new InstructionSetExtension + { + Extension = e.Extension, + Id = e.Id + }) + .ToListAsync(); + + [HttpGet] + [AllowAnonymous] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task GetAsync(int id) => await context.InstructionSetExtensions + .Where(e => e.Id == id) + .Select(e => new InstructionSetExtension + { + Extension = e.Extension, + Id = e.Id + }) + .FirstOrDefaultAsync(); + + [HttpPost] + [Authorize(Roles = "Admin,UberAdmin")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task UpdateAsync(InstructionSetExtension viewModel) + { + string userId = User.FindFirstValue(ClaimTypes.Sid); + if(userId is null) return; + InstructionSetExtension model = await context.InstructionSetExtensions.FindAsync(viewModel.Id); + + if(model is null) return; + + model.Extension = viewModel.Extension; + + await context.SaveChangesWithUserAsync(userId); + } + + [HttpPost] + [Authorize(Roles = "Admin,UberAdmin")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task CreateAsync(InstructionSetExtension viewModel) + { + string userId = User.FindFirstValue(ClaimTypes.Sid); + if(userId is null) return 0; + var model = new InstructionSetExtension + { + Extension = viewModel.Extension + }; + + await context.InstructionSetExtensions.AddAsync(model); + await context.SaveChangesWithUserAsync(userId); + + return model.Id; + } + + [HttpDelete] + [Authorize(Roles = "Admin,UberAdmin")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task DeleteAsync(int id) + { + string userId = User.FindFirstValue(ClaimTypes.Sid); + if(userId is null) return; + InstructionSetExtension item = await context.InstructionSetExtensions.FindAsync(id); + + if(item is null) return; + + context.InstructionSetExtensions.Remove(item); + + await context.SaveChangesWithUserAsync(userId); + } + + [HttpGet] + [AllowAnonymous] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public bool VerifyUnique(string extension) => + !context.InstructionSetExtensions.Any(i => string.Equals(i.Extension, + extension, + StringComparison.InvariantCultureIgnoreCase)); +} diff --git a/Marechai.Server/Controllers/InstructionSetsController.cs b/Marechai.Server/Controllers/InstructionSetsController.cs new file mode 100644 index 00000000..d5259bb5 --- /dev/null +++ b/Marechai.Server/Controllers/InstructionSetsController.cs @@ -0,0 +1,128 @@ +/******************************************************************************* +// MARECHAI: Master repository of computing history artifacts information +// --------------------------------------------------------------------------- +// +// Author(s) : Natalia Portillo +// +// --[ License ] ----------------------------------------------------------- +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +// --------------------------------------------------------------------------- +// Copyright © 2003-2025 Natalia Portillo +*******************************************************************************/ + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Security.Claims; +using System.Threading.Tasks; +using Marechai.Data.Dtos; +using Marechai.Database.Models; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Localization; + +namespace Marechai.Server.Controllers; + +[Route("/instruction-sets")] +[ApiController] +public class InstructionSetsController(MarechaiContext context) : ControllerBase +{ + [HttpGet] + [AllowAnonymous] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task> GetAsync() => await context.InstructionSets.OrderBy(e => e.Name) + .Select(e => new InstructionSet + { + Name = e.Name, + Id = e.Id + }) + .ToListAsync(); + + [HttpGet] + [AllowAnonymous] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task GetAsync(int id) => await context.InstructionSets.Where(e => e.Id == id) + .Select(e => new InstructionSet + { + Name = e.Name, + Id = e.Id + }) + .FirstOrDefaultAsync(); + + [HttpPost] + [Authorize(Roles = "Admin,UberAdmin")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task UpdateAsync(InstructionSet viewModel) + { + string userId = User.FindFirstValue(ClaimTypes.Sid); + if(userId is null) return; + InstructionSet model = await context.InstructionSets.FindAsync(viewModel.Id); + + if(model is null) return; + + model.Name = viewModel.Name; + + await context.SaveChangesWithUserAsync(userId); + } + + [HttpPost] + [Authorize(Roles = "Admin,UberAdmin")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task CreateAsync(InstructionSet viewModel) + { + string userId = User.FindFirstValue(ClaimTypes.Sid); + if(userId is null) return 0; + var model = new InstructionSet + { + Name = viewModel.Name + }; + + await context.InstructionSets.AddAsync(model); + await context.SaveChangesWithUserAsync(userId); + + return model.Id; + } + + [HttpDelete] + [Authorize(Roles = "Admin,UberAdmin")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task DeleteAsync(int id) + { + string userId = User.FindFirstValue(ClaimTypes.Sid); + if(userId is null) return; + InstructionSet item = await context.InstructionSets.FindAsync(id); + + if(item is null) return; + + context.InstructionSets.Remove(item); + + await context.SaveChangesWithUserAsync(userId); + } + + [HttpGet] + [AllowAnonymous] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public bool VerifyUnique(string name) => + !context.InstructionSets.Any(i => string.Equals(i.Name, name, StringComparison.InvariantCultureIgnoreCase)); +} diff --git a/Marechai.Server/Controllers/Iso31661NumericController.cs b/Marechai.Server/Controllers/Iso31661NumericController.cs new file mode 100644 index 00000000..37c47f56 --- /dev/null +++ b/Marechai.Server/Controllers/Iso31661NumericController.cs @@ -0,0 +1,51 @@ +/******************************************************************************* +// MARECHAI: Master repository of computing history artifacts information +// --------------------------------------------------------------------------- +// +// Author(s) : Natalia Portillo +// +// --[ License ] ----------------------------------------------------------- +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +// --------------------------------------------------------------------------- +// Copyright © 2003-2025 Natalia Portillo +*******************************************************************************/ + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Security.Claims; +using System.Threading.Tasks; +using Marechai.Data.Dtos; +using Marechai.Database.Models; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Localization; + +namespace Marechai.Server.Controllers; + +[Route("/iso31661-numeric")] +[ApiController] +public class Iso31661NumericController(MarechaiContext context) : ControllerBase +{ + [HttpGet] + [AllowAnonymous] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task> GetAsync() => + await context.Iso31661Numeric.OrderBy(c => c.Name).ToListAsync(); +} diff --git a/Marechai.Server/Controllers/Iso4217Controller.cs b/Marechai.Server/Controllers/Iso4217Controller.cs new file mode 100644 index 00000000..c76022f1 --- /dev/null +++ b/Marechai.Server/Controllers/Iso4217Controller.cs @@ -0,0 +1,50 @@ +/******************************************************************************* +// MARECHAI: Master repository of computing history artifacts information +// --------------------------------------------------------------------------- +// +// Author(s) : Natalia Portillo +// +// --[ License ] ----------------------------------------------------------- +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +// --------------------------------------------------------------------------- +// Copyright © 2003-2025 Natalia Portillo +*******************************************************************************/ + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Security.Claims; +using System.Threading.Tasks; +using Marechai.Data.Dtos; +using Marechai.Database.Models; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Localization; + +namespace Marechai.Server.Controllers; + +[Route("/iso4217")] +[ApiController] +public class Iso4217Controller(MarechaiContext context) : ControllerBase +{ + [HttpGet] + [AllowAnonymous] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task> GetAsync() => await context.Iso4217.OrderBy(c => c.Name).ToListAsync(); +} diff --git a/Marechai.Server/Controllers/LicensesController.cs b/Marechai.Server/Controllers/LicensesController.cs new file mode 100644 index 00000000..01eb7db7 --- /dev/null +++ b/Marechai.Server/Controllers/LicensesController.cs @@ -0,0 +1,140 @@ +/******************************************************************************* +// MARECHAI: Master repository of computing history artifacts information +// --------------------------------------------------------------------------- +// +// Author(s) : Natalia Portillo +// +// --[ License ] ----------------------------------------------------------- +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +// --------------------------------------------------------------------------- +// Copyright © 2003-2025 Natalia Portillo +*******************************************************************************/ + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Security.Claims; +using System.Threading.Tasks; +using Marechai.Data.Dtos; +using Marechai.Database.Models; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Localization; + +namespace Marechai.Server.Controllers; + +[Route("/licenses")] +[ApiController] +public class LicensesController(MarechaiContext context) : ControllerBase +{ + [HttpGet] + [AllowAnonymous] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task> GetAsync() => await context.Licenses.OrderBy(l => l.Name) + .Select(l => new License + { + FsfApproved = l.FsfApproved, + Id = l.Id, + Link = l.Link, + Name = l.Name, + OsiApproved = l.OsiApproved, + SPDX = l.SPDX + }) + .ToListAsync(); + + [HttpGet] + [AllowAnonymous] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task GetAsync(int id) => await context.Licenses.Where(l => l.Id == id) + .Select(l => new License + { + FsfApproved = l.FsfApproved, + Id = l.Id, + Link = l.Link, + Name = l.Name, + OsiApproved = l.OsiApproved, + SPDX = l.SPDX, + Text = l.Text + }) + .FirstOrDefaultAsync(); + + [HttpPost] + [Authorize(Roles = "Admin,UberAdmin")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task UpdateAsync(License viewModel) + { + string userId = User.FindFirstValue(ClaimTypes.Sid); + if(userId is null) return; + License model = await context.Licenses.FindAsync(viewModel.Id); + + if(model is null) return; + + model.FsfApproved = viewModel.FsfApproved; + model.Link = viewModel.Link; + model.Name = viewModel.Name; + model.OsiApproved = viewModel.OsiApproved; + model.SPDX = viewModel.SPDX; + model.Text = viewModel.Text; + + await context.SaveChangesWithUserAsync(userId); + } + + [HttpPost] + [Authorize(Roles = "Admin,UberAdmin")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task CreateAsync(License viewModel) + { + string userId = User.FindFirstValue(ClaimTypes.Sid); + if(userId is null) return 0; + var model = new License + { + FsfApproved = viewModel.FsfApproved, + Link = viewModel.Link, + Name = viewModel.Name, + OsiApproved = viewModel.OsiApproved, + SPDX = viewModel.SPDX, + Text = viewModel.Text + }; + + await context.Licenses.AddAsync(model); + await context.SaveChangesWithUserAsync(userId); + + return model.Id; + } + + [HttpDelete] + [Authorize(Roles = "Admin,UberAdmin")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task DeleteAsync(int id) + { + string userId = User.FindFirstValue(ClaimTypes.Sid); + if(userId is null) return; + License item = await context.Licenses.FindAsync(id); + + if(item is null) return; + + context.Licenses.Remove(item); + + await context.SaveChangesWithUserAsync(userId); + } +} diff --git a/Marechai.Server/Controllers/MachineFamiliesController.cs b/Marechai.Server/Controllers/MachineFamiliesController.cs new file mode 100644 index 00000000..b3c1ca90 --- /dev/null +++ b/Marechai.Server/Controllers/MachineFamiliesController.cs @@ -0,0 +1,128 @@ +/******************************************************************************* +// MARECHAI: Master repository of computing history artifacts information +// --------------------------------------------------------------------------- +// +// Author(s) : Natalia Portillo +// +// --[ License ] ----------------------------------------------------------- +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +// --------------------------------------------------------------------------- +// Copyright © 2003-2025 Natalia Portillo +*******************************************************************************/ + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Security.Claims; +using System.Threading.Tasks; +using Marechai.Data.Dtos; +using Marechai.Database.Models; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Localization; + +namespace Marechai.Server.Controllers; + +[Route("/machine-families")] +[ApiController] +public class MachineFamiliesController(MarechaiContext context) : ControllerBase +{ + [HttpGet] + [AllowAnonymous] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task> GetAsync() => await context.MachineFamilies + .OrderBy(m => m.Company.Name) + .ThenBy(m => m.Name) + .Select(m => new MachineFamilyDto + { + Id = m.Id, + Company = m.Company.Name, + Name = m.Name + }) + .OrderBy(m => m.Name) + .ToListAsync(); + + [HttpGet] + [AllowAnonymous] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task GetAsync(int id) => await context.MachineFamilies.Where(f => f.Id == id) + .Select(m => new MachineFamilyDto + { + Id = m.Id, + CompanyId = m.CompanyId, + Name = m.Name + }) + .FirstOrDefaultAsync(); + + [HttpPost] + [Authorize(Roles = "Admin,UberAdmin")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task UpdateAsync(MachineFamilyDto dto) + { + string userId = User.FindFirstValue(ClaimTypes.Sid); + if(userId is null) return; + MachineFamily model = await context.MachineFamilies.FindAsync(dto.Id); + + if(model is null) return; + + model.Name = dto.Name; + model.CompanyId = dto.CompanyId; + + await context.SaveChangesWithUserAsync(userId); + } + + [HttpPost] + [Authorize(Roles = "Admin,UberAdmin")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task CreateAsync(MachineFamilyDto dto) + { + string userId = User.FindFirstValue(ClaimTypes.Sid); + if(userId is null) return 0; + var model = new MachineFamily + { + Name = dto.Name, + CompanyId = dto.CompanyId + }; + + await context.MachineFamilies.AddAsync(model); + await context.SaveChangesWithUserAsync(userId); + + return model.Id; + } + + [HttpDelete] + [Authorize(Roles = "Admin,UberAdmin")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task DeleteAsync(int id) + { + string userId = User.FindFirstValue(ClaimTypes.Sid); + if(userId is null) return; + MachineFamily item = await context.MachineFamilies.FindAsync(id); + + if(item is null) return; + + context.MachineFamilies.Remove(item); + + await context.SaveChangesWithUserAsync(userId); + } +} diff --git a/Marechai.Server/Controllers/MachinePhotosController.cs b/Marechai.Server/Controllers/MachinePhotosController.cs new file mode 100644 index 00000000..16aac1ba --- /dev/null +++ b/Marechai.Server/Controllers/MachinePhotosController.cs @@ -0,0 +1,214 @@ +/******************************************************************************* +// MARECHAI: Master repository of computing history artifacts information +// --------------------------------------------------------------------------- +// +// Author(s) : Natalia Portillo +// +// --[ License ] ----------------------------------------------------------- +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +// --------------------------------------------------------------------------- +// Copyright © 2003-2025 Natalia Portillo +*******************************************************************************/ + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Security.Claims; +using System.Threading.Tasks; +using Marechai.Data.Dtos; +using Marechai.Database.Models; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Localization; + +namespace Marechai.Server.Controllers; + +[Route("/machine-photos")] +[ApiController] +public class MachinePhotosController(MarechaiContext context) : ControllerBase +{ + [HttpGet] + [AllowAnonymous] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task> GetGuidsByMachineAsync(int machineId) => + await context.MachinePhotos.Where(p => p.MachineId == machineId).Select(p => p.Id).ToListAsync(); + + [HttpGet] + [AllowAnonymous] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task GetAsync(Guid id) => await context.MachinePhotos.Where(p => p.Id == id) + .Select(p => new MachinePhotoDto + { + Aperture = p.Aperture, + Author = p.Author, + CameraManufacturer = p.CameraManufacturer, + CameraModel = p.CameraModel, + ColorSpace = p.ColorSpace, + Comments = p.Comments, + Contrast = p.Contrast, + CreationDate = p.CreationDate, + DigitalZoomRatio = p.DigitalZoomRatio, + ExifVersion = p.ExifVersion, + ExposureTime = p.ExposureTime, + ExposureMethod = p.ExposureMethod, + ExposureProgram = p.ExposureProgram, + Flash = p.Flash, + Focal = p.Focal, + FocalLength = p.FocalLength, + FocalLengthEquivalent = + p.FocalLengthEquivalent, + HorizontalResolution = + p.HorizontalResolution, + Id = p.Id, + IsoRating = p.IsoRating, + Lens = p.Lens, + LicenseId = p.LicenseId, + LicenseName = p.License.Name, + LightSource = p.LightSource, + MachineCompanyName = + p.Machine.Company.Name, + MachineId = p.MachineId, + MachineName = p.Machine.Name, + MeteringMode = p.MeteringMode, + ResolutionUnit = p.ResolutionUnit, + Orientation = p.Orientation, + Saturation = p.Saturation, + SceneCaptureType = p.SceneCaptureType, + SensingMethod = p.SensingMethod, + Sharpness = p.Sharpness, + SoftwareUsed = p.SoftwareUsed, + Source = p.Source, + SubjectDistanceRange = + p.SubjectDistanceRange, + UploadDate = p.UploadDate, + UserId = p.UserId, + VerticalResolution = p.VerticalResolution, + WhiteBalance = p.WhiteBalance, + OriginalExtension = p.OriginalExtension + }) + .FirstOrDefaultAsync(); + + [HttpPost] + [Authorize(Roles = "Admin,UberAdmin")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task UpdateAsync(MachinePhotoDto dto) + { + string userId = User.FindFirstValue(ClaimTypes.Sid); + if(userId is null) return; + MachinePhoto model = await context.MachinePhotos.FindAsync(dto.Id); + + if(model is null) return; + + model.Aperture = dto.Aperture; + model.Author = dto.Author; + model.CameraManufacturer = dto.CameraManufacturer; + model.CameraModel = dto.CameraModel; + model.ColorSpace = dto.ColorSpace; + model.Comments = dto.Comments; + model.Contrast = dto.Contrast; + model.CreationDate = dto.CreationDate; + model.DigitalZoomRatio = dto.DigitalZoomRatio; + model.ExifVersion = dto.ExifVersion; + model.ExposureTime = dto.ExposureTime; + model.ExposureMethod = dto.ExposureMethod; + model.ExposureProgram = dto.ExposureProgram; + model.Flash = dto.Flash; + model.Focal = dto.Focal; + model.FocalLength = dto.FocalLength; + model.FocalLengthEquivalent = dto.FocalLengthEquivalent; + model.HorizontalResolution = dto.HorizontalResolution; + model.IsoRating = dto.IsoRating; + model.Lens = dto.Lens; + model.LicenseId = dto.LicenseId; + model.LightSource = dto.LightSource; + model.MeteringMode = dto.MeteringMode; + model.ResolutionUnit = dto.ResolutionUnit; + model.Orientation = dto.Orientation; + model.Saturation = dto.Saturation; + model.SceneCaptureType = dto.SceneCaptureType; + model.SensingMethod = dto.SensingMethod; + model.Sharpness = dto.Sharpness; + model.SoftwareUsed = dto.SoftwareUsed; + model.Source = dto.Source; + model.SubjectDistanceRange = dto.SubjectDistanceRange; + model.VerticalResolution = dto.VerticalResolution; + model.WhiteBalance = dto.WhiteBalance; + + await context.SaveChangesWithUserAsync(userId); + } + + [HttpPost] + [Authorize(Roles = "Admin,UberAdmin")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task CreateAsync(MachinePhotoDto dto) + { + string userId = User.FindFirstValue(ClaimTypes.Sid); + if(userId is null) return null; + var model = new MachinePhoto + { + Aperture = dto.Aperture, + Author = dto.Author, + CameraManufacturer = dto.CameraManufacturer, + CameraModel = dto.CameraModel, + ColorSpace = dto.ColorSpace, + Comments = dto.Comments, + Contrast = dto.Contrast, + CreationDate = dto.CreationDate, + DigitalZoomRatio = dto.DigitalZoomRatio, + ExifVersion = dto.ExifVersion, + ExposureTime = dto.ExposureTime, + ExposureMethod = dto.ExposureMethod, + ExposureProgram = dto.ExposureProgram, + Flash = dto.Flash, + Focal = dto.Focal, + FocalLength = dto.FocalLength, + FocalLengthEquivalent = dto.FocalLengthEquivalent, + HorizontalResolution = dto.HorizontalResolution, + Id = dto.Id, + IsoRating = dto.IsoRating, + Lens = dto.Lens, + LicenseId = dto.LicenseId, + LightSource = dto.LightSource, + MachineId = dto.MachineId, + MeteringMode = dto.MeteringMode, + ResolutionUnit = dto.ResolutionUnit, + Orientation = dto.Orientation, + Saturation = dto.Saturation, + SceneCaptureType = dto.SceneCaptureType, + SensingMethod = dto.SensingMethod, + Sharpness = dto.Sharpness, + SoftwareUsed = dto.SoftwareUsed, + Source = dto.Source, + SubjectDistanceRange = dto.SubjectDistanceRange, + UploadDate = dto.UploadDate, + UserId = dto.UserId, + VerticalResolution = dto.VerticalResolution, + WhiteBalance = dto.WhiteBalance, + OriginalExtension = dto.OriginalExtension + }; + + await context.MachinePhotos.AddAsync(model); + await context.SaveChangesWithUserAsync(userId); + + return model.Id; + } +} diff --git a/Marechai.Server/Controllers/MachinesController.cs b/Marechai.Server/Controllers/MachinesController.cs new file mode 100644 index 00000000..c09e7619 --- /dev/null +++ b/Marechai.Server/Controllers/MachinesController.cs @@ -0,0 +1,271 @@ +/******************************************************************************* +// MARECHAI: Master repository of computing history artifacts information +// --------------------------------------------------------------------------- +// +// Author(s) : Natalia Portillo +// +// --[ License ] ----------------------------------------------------------- +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +// --------------------------------------------------------------------------- +// Copyright © 2003-2025 Natalia Portillo +*******************************************************************************/ + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Security.Claims; +using System.Threading.Tasks; +using Marechai.Data.Dtos; +using Marechai.Database.Models; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Localization; + +namespace Marechai.Server.Controllers; + +[Route("/machines")] +[ApiController] +public class MachinesController(MarechaiContext context, + IStringLocalizer localizer, + GpusService gpusService, + ProcessorsService processorsService, + SoundSynthsService soundSynthsService) : ControllerBase +{ + [HttpGet] + [AllowAnonymous] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task> GetAsync() => await context.Machines.OrderBy(m => m.Company.Name) + .ThenBy(m => m.Name) + .ThenBy(m => m.Family.Name) + .Select(m => new MachineDto + { + Id = m.Id, + Company = m.Company.Name, + Name = m.Name, + Model = m.Model, + Introduced = m.Introduced, + Type = m.Type, + Family = m.Family.Name + }) + .ToListAsync(); + + [HttpGet] + [AllowAnonymous] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task GetAsync(int id) => await context.Machines.Where(m => m.Id == id) + .Select(m => new MachineDto + { + Id = m.Id, + Company = m.Company.Name, + CompanyId = m.CompanyId, + Name = m.Name, + Model = m.Model, + Introduced = m.Introduced, + Type = m.Type, + FamilyId = m.FamilyId + }) + .FirstOrDefaultAsync(); + + [HttpPost] + [Authorize(Roles = "Admin,UberAdmin")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task UpdateAsync(MachineDto dto) + { + string userId = User.FindFirstValue(ClaimTypes.Sid); + if(userId is null) return; + Machine model = await context.Machines.FindAsync(dto.Id); + + if(model is null) return; + + model.CompanyId = dto.CompanyId; + model.Name = dto.Name; + model.Model = dto.Model; + model.Introduced = dto.Introduced; + model.Type = dto.Type; + model.FamilyId = dto.FamilyId; + + var news = new News + { + AddedId = model.Id, + Date = DateTime.UtcNow + }; + + switch(model.Type) + { + case MachineType.Computer: + news.Type = NewsType.UpdatedComputerInDb; + + break; + case MachineType.Console: + news.Type = NewsType.UpdatedConsoleInDb; + + break; + default: + news = null; + + break; + } + + if(news != null) await context.News.AddAsync(news); + + await context.SaveChangesWithUserAsync(userId); + } + + [HttpPost] + [Authorize(Roles = "Admin,UberAdmin")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task CreateAsync(MachineDto dto) + { + string userId = User.FindFirstValue(ClaimTypes.Sid); + if(userId is null) return 0; + var model = new Machine + { + CompanyId = dto.CompanyId, + Name = dto.Name, + Model = dto.Model, + Introduced = dto.Introduced, + Type = dto.Type, + FamilyId = dto.FamilyId + }; + + await context.Machines.AddAsync(model); + await context.SaveChangesWithUserAsync(userId); + + var news = new News + { + AddedId = model.Id, + Date = DateTime.UtcNow + }; + + switch(model.Type) + { + case MachineType.Computer: + news.Type = NewsType.NewComputerInDb; + + break; + case MachineType.Console: + news.Type = NewsType.NewConsoleInDb; + + break; + default: + news = null; + + break; + } + + if(news != null) + { + await context.News.AddAsync(news); + await context.SaveChangesWithUserAsync(userId); + } + + return model.Id; + } + + [HttpGet] + [AllowAnonymous] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task GetMachine(int id) + { + Machine machine = await context.Machines.FindAsync(id); + + if(machine is null) return null; + + var model = new MachineDto + { + Introduced = machine.Introduced, + Name = machine.Name, + CompanyId = machine.CompanyId, + Model = machine.Model, + Type = machine.Type + }; + + Company company = await context.Companies.FindAsync(model.CompanyId); + + if(company != null) + { + model.Company = company.Name; + + IQueryable logos = context.CompanyLogos.Where(l => l.CompanyId == company.Id); + + if(model.Introduced.HasValue) + { + model.CompanyLogo = (await logos.FirstOrDefaultAsync(l => l.Year >= model.Introduced.Value.Year))?.Guid; + } + + if(model.CompanyLogo is null && logos.Any()) model.CompanyLogo = (await logos.FirstAsync())?.Guid; + } + + MachineFamily family = await context.MachineFamilies.FindAsync(machine.FamilyId); + + if(family != null) + { + model.FamilyName = family.Name; + model.FamilyId = family.Id; + } + + model.Gpus = await gpusService.GetByMachineAsync(machine.Id); + + model.Memory = await context.MemoryByMachine.Where(m => m.MachineId == machine.Id) + .Select(m => new MemoryDto + { + Type = m.Type, + Usage = m.Usage, + Size = m.Size, + Speed = m.Speed + }) + .ToListAsync(); + + model.Processors = await processorsService.GetByMachineAsync(machine.Id); + + model.SoundSynthesizers = await soundSynthsService.GetByMachineAsync(machine.Id); + + model.Storage = await context.StorageByMachine.Where(s => s.MachineId == machine.Id) + .Select(s => new StorageDto + { + Type = s.Type, + Interface = s.Interface, + Capacity = s.Capacity + }) + .ToListAsync(); + + return model; + } + + [HttpDelete] + [Authorize(Roles = "Admin,UberAdmin")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task DeleteAsync(int id) + { + string userId = User.FindFirstValue(ClaimTypes.Sid); + if(userId is null) return; + Machine item = await context.Machines.FindAsync(id); + + if(item is null) return; + + context.Machines.Remove(item); + + await context.SaveChangesWithUserAsync(userId); + } +} diff --git a/Marechai.Server/Controllers/MagazineIssuesController.cs b/Marechai.Server/Controllers/MagazineIssuesController.cs new file mode 100644 index 00000000..9e19a1dc --- /dev/null +++ b/Marechai.Server/Controllers/MagazineIssuesController.cs @@ -0,0 +1,149 @@ +/******************************************************************************* +// MARECHAI: Master repository of computing history artifacts information +// --------------------------------------------------------------------------- +// +// Author(s) : Natalia Portillo +// +// --[ License ] ----------------------------------------------------------- +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +// --------------------------------------------------------------------------- +// Copyright © 2003-2025 Natalia Portillo +*******************************************************************************/ + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Security.Claims; +using System.Threading.Tasks; +using Marechai.Data.Dtos; +using Marechai.Database.Models; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Localization; + +namespace Marechai.Server.Controllers; + +[Route("/magazine-issues")] +[ApiController] +public class MagazineIssuesController(MarechaiContext context) : ControllerBase +{ + [HttpGet] + [AllowAnonymous] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task> GetAsync() => await context.MagazineIssues + .OrderBy(b => b.Magazine.Title) + .ThenBy(b => b.Published) + .ThenBy(b => b.Caption) + .Select(b => new MagazineIssueDto + { + Id = b.Id, + MagazineId = b.MagazineId, + MagazineTitle = b.Magazine.Title, + Caption = b.Caption, + NativeCaption = b.NativeCaption, + Published = b.Published, + ProductCode = b.ProductCode, + Pages = b.Pages, + IssueNumber = b.IssueNumber + }) + .ToListAsync(); + + [HttpGet] + [AllowAnonymous] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task GetAsync(long id) => await context.MagazineIssues.Where(b => b.Id == id) + .Select(b => new MagazineIssueDto + { + Id = b.Id, + MagazineId = b.MagazineId, + MagazineTitle = b.Magazine.Title, + Caption = b.Caption, + NativeCaption = b.NativeCaption, + Published = b.Published, + ProductCode = b.ProductCode, + Pages = b.Pages, + IssueNumber = b.IssueNumber + }) + .FirstOrDefaultAsync(); + + [HttpPost] + [Authorize(Roles = "Admin,UberAdmin")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task UpdateAsync(MagazineIssueDto dto) + { + string userId = User.FindFirstValue(ClaimTypes.Sid); + if(userId is null) return; + MagazineIssue model = await context.MagazineIssues.FindAsync(dto.Id); + + if(model is null) return; + + model.MagazineId = dto.MagazineId; + model.Caption = dto.Caption; + model.NativeCaption = dto.NativeCaption; + model.Published = dto.Published; + model.ProductCode = dto.ProductCode; + model.Pages = dto.Pages; + model.IssueNumber = dto.IssueNumber; + await context.SaveChangesWithUserAsync(userId); + } + + [HttpPost] + [Authorize(Roles = "Admin,UberAdmin")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task CreateAsync(MagazineIssueDto dto) + { + string userId = User.FindFirstValue(ClaimTypes.Sid); + if(userId is null) return 0; + var model = new MagazineIssue + { + MagazineId = dto.MagazineId, + Caption = dto.Caption, + NativeCaption = dto.NativeCaption, + Published = dto.Published, + ProductCode = dto.ProductCode, + Pages = dto.Pages, + IssueNumber = dto.IssueNumber + }; + + await context.MagazineIssues.AddAsync(model); + await context.SaveChangesWithUserAsync(userId); + + return model.Id; + } + + [HttpDelete] + [Authorize(Roles = "Admin,UberAdmin")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task DeleteAsync(long id) + { + string userId = User.FindFirstValue(ClaimTypes.Sid); + if(userId is null) return; + MagazineIssue item = await context.MagazineIssues.FindAsync(id); + + if(item is null) return; + + context.MagazineIssues.Remove(item); + + await context.SaveChangesWithUserAsync(userId); + } +} diff --git a/Marechai.Server/Controllers/MagazineScansController.cs b/Marechai.Server/Controllers/MagazineScansController.cs new file mode 100644 index 00000000..43505ddb --- /dev/null +++ b/Marechai.Server/Controllers/MagazineScansController.cs @@ -0,0 +1,161 @@ +/******************************************************************************* +// MARECHAI: Master repository of computing history artifacts information +// --------------------------------------------------------------------------- +// +// Author(s) : Natalia Portillo +// +// --[ License ] ----------------------------------------------------------- +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +// --------------------------------------------------------------------------- +// Copyright © 2003-2025 Natalia Portillo +*******************************************************************************/ + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Security.Claims; +using System.Threading.Tasks; +using Marechai.Data.Dtos; +using Marechai.Database.Models; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Localization; + +namespace Marechai.Server.Controllers; + +[Route("/magazine-scans")] +[ApiController] +public class MagazineScansController(MarechaiContext context) : ControllerBase +{ + [HttpGet] + [AllowAnonymous] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task> GetGuidsByMagazineAsync(long bookId) => + await context.MagazineScans.Where(p => p.MagazineId == bookId).Select(p => p.Id).ToListAsync(); + + [HttpGet] + [AllowAnonymous] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task GetAsync(Guid id) => await context.MagazineScans.Where(p => p.Id == id) + .Select(p => new MagazineScanDto + { + Author = p.Author, + MagazineId = p.Magazine.Id, + ColorSpace = p.ColorSpace, + Comments = p.Comments, + CreationDate = p.CreationDate, + ExifVersion = p.ExifVersion, + HorizontalResolution = p.HorizontalResolution, + Id = p.Id, + ResolutionUnit = p.ResolutionUnit, + Page = p.Page, + ScannerManufacturer = p.ScannerManufacturer, + ScannerModel = p.ScannerModel, + SoftwareUsed = p.SoftwareUsed, + Type = p.Type, + UploadDate = p.UploadDate, + UserId = p.UserId, + VerticalResolution = p.VerticalResolution, + OriginalExtension = p.OriginalExtension + }) + .FirstOrDefaultAsync(); + + [HttpPost] + [Authorize(Roles = "Admin,UberAdmin")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task UpdateAsync(MagazineScanDto dto) + { + string userId = User.FindFirstValue(ClaimTypes.Sid); + if(userId is null) return; + MagazineScan model = await context.MagazineScans.FindAsync(dto.Id); + + if(model is null) return; + + model.Author = dto.Author; + model.ColorSpace = dto.ColorSpace; + model.Comments = dto.Comments; + model.CreationDate = dto.CreationDate; + model.ExifVersion = dto.ExifVersion; + model.HorizontalResolution = dto.HorizontalResolution; + model.ResolutionUnit = dto.ResolutionUnit; + model.Page = dto.Page; + model.ScannerManufacturer = dto.ScannerManufacturer; + model.ScannerModel = dto.ScannerModel; + model.Type = dto.Type; + model.SoftwareUsed = dto.SoftwareUsed; + model.VerticalResolution = dto.VerticalResolution; + + await context.SaveChangesWithUserAsync(userId); + } + + [HttpPost] + [Authorize(Roles = "Admin,UberAdmin")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task CreateAsync(MagazineScanDto dto) + { + string userId = User.FindFirstValue(ClaimTypes.Sid); + if(userId is null) return null; + var model = new MagazineScan + { + Author = dto.Author, + MagazineId = dto.MagazineId, + ColorSpace = dto.ColorSpace, + Comments = dto.Comments, + CreationDate = dto.CreationDate, + ExifVersion = dto.ExifVersion, + HorizontalResolution = dto.HorizontalResolution, + Id = dto.Id, + ResolutionUnit = dto.ResolutionUnit, + Page = dto.Page, + ScannerManufacturer = dto.ScannerManufacturer, + ScannerModel = dto.ScannerModel, + Type = dto.Type, + SoftwareUsed = dto.SoftwareUsed, + UploadDate = dto.UploadDate, + UserId = dto.UserId, + VerticalResolution = dto.VerticalResolution, + OriginalExtension = dto.OriginalExtension + }; + + await context.MagazineScans.AddAsync(model); + await context.SaveChangesWithUserAsync(userId); + + return model.Id; + } + + [HttpDelete] + [Authorize(Roles = "Admin,UberAdmin")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task DeleteAsync(Guid id) + { + string userId = User.FindFirstValue(ClaimTypes.Sid); + if(userId is null) return; + MagazineScan item = await context.MagazineScans.FindAsync(id); + + if(item is null) return; + + context.MagazineScans.Remove(item); + + await context.SaveChangesWithUserAsync(userId); + } +} diff --git a/Marechai.Server/Controllers/MagazinesByMachineController.cs b/Marechai.Server/Controllers/MagazinesByMachineController.cs new file mode 100644 index 00000000..3d4a7833 --- /dev/null +++ b/Marechai.Server/Controllers/MagazinesByMachineController.cs @@ -0,0 +1,97 @@ +/******************************************************************************* +// MARECHAI: Master repository of computing history artifacts information +// --------------------------------------------------------------------------- +// +// Author(s) : Natalia Portillo +// +// --[ License ] ----------------------------------------------------------- +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +// --------------------------------------------------------------------------- +// Copyright © 2003-2025 Natalia Portillo +*******************************************************************************/ + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Security.Claims; +using System.Threading.Tasks; +using Marechai.Data.Dtos; +using Marechai.Database.Models; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Localization; + +namespace Marechai.Server.Controllers; + +[Route("/magazines-by-machine")] +[ApiController] +public class MagazinesByMachineController(MarechaiContext context) : ControllerBase +{ + [HttpGet] + [AllowAnonymous] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task> GetByMagazine(long bookId) => await context.MagazinesByMachines + .Where(p => p.MagazineId == bookId) + .Select(p => new MagazineByMachineDto + { + Id = p.Id, + MagazineId = p.MagazineId, + MachineId = p.MachineId, + Machine = p.Machine.Name + }) + .OrderBy(p => p.Machine) + .ToListAsync(); + + [HttpDelete] + [Authorize(Roles = "Admin,UberAdmin")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task DeleteAsync(long id) + { + string userId = User.FindFirstValue(ClaimTypes.Sid); + if(userId is null) return; + MagazinesByMachine item = await context.MagazinesByMachines.FindAsync(id); + + if(item is null) return; + + context.MagazinesByMachines.Remove(item); + + await context.SaveChangesWithUserAsync(userId); + } + + [HttpPost] + [Authorize(Roles = "Admin,UberAdmin")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task CreateAsync(int machineId, long bookId) + { + string userId = User.FindFirstValue(ClaimTypes.Sid); + if(userId is null) return 0; + var item = new MagazinesByMachine + { + MachineId = machineId, + MagazineId = bookId + }; + + await context.MagazinesByMachines.AddAsync(item); + await context.SaveChangesWithUserAsync(userId); + + return item.Id; + } +} diff --git a/Marechai.Server/Controllers/MagazinesByMachineFamilyController.cs b/Marechai.Server/Controllers/MagazinesByMachineFamilyController.cs new file mode 100644 index 00000000..3b59eb07 --- /dev/null +++ b/Marechai.Server/Controllers/MagazinesByMachineFamilyController.cs @@ -0,0 +1,97 @@ +/******************************************************************************* +// MARECHAI: Master repository of computing history artifacts information +// --------------------------------------------------------------------------- +// +// Author(s) : Natalia Portillo +// +// --[ License ] ----------------------------------------------------------- +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +// --------------------------------------------------------------------------- +// Copyright © 2003-2025 Natalia Portillo +*******************************************************************************/ + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Security.Claims; +using System.Threading.Tasks; +using Marechai.Data.Dtos; +using Marechai.Database.Models; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Localization; + +namespace Marechai.Server.Controllers; + +[Route("/magazines-by-machine-family")] +[ApiController] +public class MagazinesByMachineFamilyController(MarechaiContext context) : ControllerBase +{ + [HttpGet] + [AllowAnonymous] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task> GetByMagazine(long bookId) => await context + .MagazinesByMachinesFamilies.Where(p => p.MagazineId == bookId) + .Select(p => new MagazineByMachineFamilyDto + { + Id = p.Id, + MagazineId = p.MagazineId, + MachineFamilyId = p.MachineFamilyId, + MachineFamily = p.MachineFamily.Name + }) + .OrderBy(p => p.MachineFamily) + .ToListAsync(); + + [HttpDelete] + [Authorize(Roles = "Admin,UberAdmin")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task DeleteAsync(long id) + { + string userId = User.FindFirstValue(ClaimTypes.Sid); + if(userId is null) return; + MagazinesByMachineFamily item = await context.MagazinesByMachinesFamilies.FindAsync(id); + + if(item is null) return; + + context.MagazinesByMachinesFamilies.Remove(item); + + await context.SaveChangesWithUserAsync(userId); + } + + [HttpPost] + [Authorize(Roles = "Admin,UberAdmin")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task CreateAsync(int machineFamilyId, long bookId) + { + string userId = User.FindFirstValue(ClaimTypes.Sid); + if(userId is null) return 0; + var item = new MagazinesByMachineFamily + { + MachineFamilyId = machineFamilyId, + MagazineId = bookId + }; + + await context.MagazinesByMachinesFamilies.AddAsync(item); + await context.SaveChangesWithUserAsync(userId); + + return item.Id; + } +} diff --git a/Marechai.Server/Controllers/MagazinesController.cs b/Marechai.Server/Controllers/MagazinesController.cs new file mode 100644 index 00000000..e08d3317 --- /dev/null +++ b/Marechai.Server/Controllers/MagazinesController.cs @@ -0,0 +1,164 @@ +/******************************************************************************* +// MARECHAI: Master repository of computing history artifacts information +// --------------------------------------------------------------------------- +// +// Author(s) : Natalia Portillo +// +// --[ License ] ----------------------------------------------------------- +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +// --------------------------------------------------------------------------- +// Copyright © 2003-2025 Natalia Portillo +*******************************************************************************/ + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Security.Claims; +using System.Threading.Tasks; +using Marechai.Data.Dtos; +using Marechai.Database.Models; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Localization; + +namespace Marechai.Server.Controllers; + +[Route("/magazines")] +[ApiController] +public class MagazinesController(MarechaiContext context) : ControllerBase +{ + [HttpGet] + [AllowAnonymous] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task> GetAsync() => await context.Magazines.OrderBy(b => b.NativeTitle) + .ThenBy(b => b.FirstPublication) + .ThenBy(b => b.Title) + .Select(b => new MagazineDto + { + Id = b.Id, + Title = b.Title, + NativeTitle = b.NativeTitle, + FirstPublication = b.FirstPublication, + Synopsis = b.Synopsis, + Issn = b.Issn, + CountryId = b.CountryId, + Country = b.Country.Name + }) + .ToListAsync(); + + [HttpGet] + [AllowAnonymous] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task> GetTitlesAsync() => await context.Magazines.OrderBy(b => b.Title) + .ThenBy(b => b.FirstPublication) + .Select(b => new MagazineDto + { + Id = b.Id, + Title = $"{b.Title} ({b.Country.Name}" + }) + .ToListAsync(); + + [HttpGet] + [AllowAnonymous] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task GetAsync(long id) => await context.Magazines.Where(b => b.Id == id) + .Select(b => new MagazineDto + { + Id = b.Id, + Title = b.Title, + NativeTitle = b.NativeTitle, + FirstPublication = b.FirstPublication, + Synopsis = b.Synopsis, + Issn = b.Issn, + CountryId = b.CountryId, + Country = b.Country.Name + }) + .FirstOrDefaultAsync(); + + [HttpPost] + [Authorize(Roles = "Admin,UberAdmin")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task UpdateAsync(MagazineDto dto) + { + string userId = User.FindFirstValue(ClaimTypes.Sid); + if(userId is null) return; + Magazine model = await context.Magazines.FindAsync(dto.Id); + + if(model is null) return; + + model.Title = dto.Title; + model.NativeTitle = dto.NativeTitle; + model.FirstPublication = dto.FirstPublication; + model.Synopsis = dto.Synopsis; + model.CountryId = dto.CountryId; + model.Issn = dto.Issn; + await context.SaveChangesWithUserAsync(userId); + } + + [HttpPost] + [Authorize(Roles = "Admin,UberAdmin")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task CreateAsync(MagazineDto dto) + { + string userId = User.FindFirstValue(ClaimTypes.Sid); + if(userId is null) return 0; + var model = new Magazine + { + Title = dto.Title, + NativeTitle = dto.NativeTitle, + FirstPublication = dto.FirstPublication, + Synopsis = dto.Synopsis, + CountryId = dto.CountryId, + Issn = dto.Issn + }; + + await context.Magazines.AddAsync(model); + await context.SaveChangesWithUserAsync(userId); + + return model.Id; + } + + [HttpGet] + [AllowAnonymous] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task GetSynopsisTextAsync(int id) => + (await context.Magazines.FirstOrDefaultAsync(d => d.Id == id))?.Synopsis; + + [HttpDelete] + [Authorize(Roles = "Admin,UberAdmin")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task DeleteAsync(long id) + { + string userId = User.FindFirstValue(ClaimTypes.Sid); + if(userId is null) return; + Magazine item = await context.Magazines.FindAsync(id); + + if(item is null) return; + + context.Magazines.Remove(item); + + await context.SaveChangesWithUserAsync(userId); + } +} diff --git a/Marechai.Server/Controllers/MediaController.cs b/Marechai.Server/Controllers/MediaController.cs new file mode 100644 index 00000000..90a6444a --- /dev/null +++ b/Marechai.Server/Controllers/MediaController.cs @@ -0,0 +1,228 @@ +/******************************************************************************* +// MARECHAI: Master repository of computing history artifacts information +// --------------------------------------------------------------------------- +// +// Author(s) : Natalia Portillo +// +// --[ License ] ----------------------------------------------------------- +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +// --------------------------------------------------------------------------- +// Copyright © 2003-2025 Natalia Portillo +*******************************************************************************/ + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Security.Claims; +using System.Threading.Tasks; +using Marechai.Data.Dtos; +using Marechai.Database.Models; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Localization; + +namespace Marechai.Server.Controllers; + +[Route("/media")] +[ApiController] +public class MediaController(MarechaiContext context) : ControllerBase +{ + [HttpGet] + [AllowAnonymous] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task> GetAsync() => await context.Media.OrderBy(d => d.Title) + .Select(d => new MediaDto + { + Id = d.Id, + Title = d.Title, + Sequence = d.Sequence, + LastSequence = d.LastSequence, + Type = d.Type, + WriteOffset = d.WriteOffset, + Sides = d.Sides, + Layers = d.Layers, + Sessions = d.Sessions, + Tracks = d.Tracks, + Sectors = d.Sectors, + Size = d.Size, + CopyProtection = d.CopyProtection, + PartNumber = d.PartNumber, + SerialNumber = d.SerialNumber, + Barcode = d.Barcode, + CatalogueNumber = d.CatalogueNumber, + Manufacturer = d.Manufacturer, + Model = d.Model, + Revision = d.Revision, + Firmware = d.Firmware, + PhysicalBlockSize = d.PhysicalBlockSize, + LogicalBlockSize = d.LogicalBlockSize, + BlockSizes = d.BlockSizes, + StorageInterface = d.StorageInterface, + TableOfContents = d.TableOfContents + }) + .ToListAsync(); + + [HttpGet] + [AllowAnonymous] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task> GetTitlesAsync() => await context.Media.OrderBy(d => d.Title) + .Select(d => new MediaDto + { + Id = d.Id, + Title = d.Title + }) + .ToListAsync(); + + [HttpGet] + [AllowAnonymous] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task GetAsync(ulong id) => await context.Media.Where(d => d.Id == id) + .Select(d => new MediaDto + { + Id = d.Id, + Title = d.Title, + Sequence = d.Sequence, + LastSequence = d.LastSequence, + Type = d.Type, + WriteOffset = d.WriteOffset, + Sides = d.Sides, + Layers = d.Layers, + Sessions = d.Sessions, + Tracks = d.Tracks, + Sectors = d.Sectors, + Size = d.Size, + CopyProtection = d.CopyProtection, + PartNumber = d.PartNumber, + SerialNumber = d.SerialNumber, + Barcode = d.Barcode, + CatalogueNumber = d.CatalogueNumber, + Manufacturer = d.Manufacturer, + Model = d.Model, + Revision = d.Revision, + Firmware = d.Firmware, + PhysicalBlockSize = d.PhysicalBlockSize, + LogicalBlockSize = d.LogicalBlockSize, + BlockSizes = d.BlockSizes, + StorageInterface = d.StorageInterface, + TableOfContents = d.TableOfContents + }) + .FirstOrDefaultAsync(); + + [HttpPost] + [Authorize(Roles = "Admin,UberAdmin")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task UpdateAsync(MediaDto dto) + { + string userId = User.FindFirstValue(ClaimTypes.Sid); + if(userId is null) return; + Media model = await context.Media.FindAsync(dto.Id); + + if(model is null) return; + + model.Title = dto.Title; + model.Sequence = dto.Sequence; + model.LastSequence = dto.LastSequence; + model.Type = dto.Type; + model.WriteOffset = dto.WriteOffset; + model.Sides = dto.Sides; + model.Layers = dto.Layers; + model.Sessions = dto.Sessions; + model.Tracks = dto.Tracks; + model.Sectors = dto.Sectors; + model.Size = dto.Size; + model.CopyProtection = dto.CopyProtection; + model.PartNumber = dto.PartNumber; + model.SerialNumber = dto.SerialNumber; + model.Barcode = dto.Barcode; + model.CatalogueNumber = dto.CatalogueNumber; + model.Manufacturer = dto.Manufacturer; + model.Model = dto.Model; + model.Revision = dto.Revision; + model.Firmware = dto.Firmware; + model.PhysicalBlockSize = dto.PhysicalBlockSize; + model.LogicalBlockSize = dto.LogicalBlockSize; + model.BlockSizes = dto.BlockSizes; + model.StorageInterface = dto.StorageInterface; + model.TableOfContents = dto.TableOfContents; + await context.SaveChangesWithUserAsync(userId); + } + + [HttpPost] + [Authorize(Roles = "Admin,UberAdmin")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task CreateAsync(MediaDto dto) + { + string userId = User.FindFirstValue(ClaimTypes.Sid); + if(userId is null) return null; + var model = new Media + { + Title = dto.Title, + Sequence = dto.Sequence, + LastSequence = dto.LastSequence, + Type = dto.Type, + WriteOffset = dto.WriteOffset, + Sides = dto.Sides, + Layers = dto.Layers, + Sessions = dto.Sessions, + Tracks = dto.Tracks, + Sectors = dto.Sectors, + Size = dto.Size, + CopyProtection = dto.CopyProtection, + PartNumber = dto.PartNumber, + SerialNumber = dto.SerialNumber, + Barcode = dto.Barcode, + CatalogueNumber = dto.CatalogueNumber, + Manufacturer = dto.Manufacturer, + Model = dto.Model, + Revision = dto.Revision, + Firmware = dto.Firmware, + PhysicalBlockSize = dto.PhysicalBlockSize, + LogicalBlockSize = dto.LogicalBlockSize, + BlockSizes = dto.BlockSizes, + StorageInterface = dto.StorageInterface, + TableOfContents = dto.TableOfContents + }; + + await context.Media.AddAsync(model); + await context.SaveChangesWithUserAsync(userId); + + return model.Id; + } + + [HttpDelete] + [Authorize(Roles = "Admin,UberAdmin")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task DeleteAsync(ulong id) + { + string userId = User.FindFirstValue(ClaimTypes.Sid); + if(userId is null) return; + Media item = await context.Media.FindAsync(id); + + if(item is null) return; + + context.Media.Remove(item); + + await context.SaveChangesWithUserAsync(userId); + } +} diff --git a/Marechai.Server/Controllers/MemoriesByMachineController.cs b/Marechai.Server/Controllers/MemoriesByMachineController.cs new file mode 100644 index 00000000..5914cb7d --- /dev/null +++ b/Marechai.Server/Controllers/MemoriesByMachineController.cs @@ -0,0 +1,105 @@ +/******************************************************************************* +// MARECHAI: Master repository of computing history artifacts information +// --------------------------------------------------------------------------- +// +// Author(s) : Natalia Portillo +// +// --[ License ] ----------------------------------------------------------- +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +// --------------------------------------------------------------------------- +// Copyright © 2003-2025 Natalia Portillo +*******************************************************************************/ + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Security.Claims; +using System.Threading.Tasks; +using Marechai.Data.Dtos; +using Marechai.Database.Models; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Localization; + +namespace Marechai.Server.Controllers; + +[Route("/memories-by-machine")] +[ApiController] +public class MemoriesByMachineController(MarechaiContext context) : ControllerBase +{ + [HttpGet] + [AllowAnonymous] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task> GetByMachine(int machineId) => await context.MemoryByMachine + .Where(m => m.MachineId == machineId) + .Select(m => new MemoryByMachineDto + { + Id = m.Id, + Type = m.Type, + Usage = m.Usage, + Size = m.Size, + Speed = m.Speed, + MachineId = m.MachineId + }) + .OrderBy(m => m.Type) + .ThenBy(m => m.Usage) + .ThenBy(m => m.Size) + .ThenBy(m => m.Speed) + .ToListAsync(); + + [HttpDelete] + [Authorize(Roles = "Admin,UberAdmin")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task DeleteAsync(long id) + { + string userId = User.FindFirstValue(ClaimTypes.Sid); + if(userId is null) return; + MemoryByMachine item = await context.MemoryByMachine.FindAsync(id); + + if(item is null) return; + + context.MemoryByMachine.Remove(item); + + await context.SaveChangesWithUserAsync(userId); + } + + [HttpPost] + [Authorize(Roles = "Admin,UberAdmin")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task CreateAsync(int machineId, MemoryType type, MemoryUsage usage, long? size, double? speed) + { + string userId = User.FindFirstValue(ClaimTypes.Sid); + if(userId is null) return 0; + var item = new MemoryByMachine + { + MachineId = machineId, + Type = type, + Usage = usage, + Size = size, + Speed = speed + }; + + await context.MemoryByMachine.AddAsync(item); + await context.SaveChangesWithUserAsync(userId); + + return item.Id; + } +} diff --git a/Marechai.Server/Controllers/NewsController.cs b/Marechai.Server/Controllers/NewsController.cs new file mode 100644 index 00000000..ec29e5fa --- /dev/null +++ b/Marechai.Server/Controllers/NewsController.cs @@ -0,0 +1,174 @@ +/******************************************************************************* +// MARECHAI: Master repository of computing history artifacts information +// --------------------------------------------------------------------------- +// +// Author(s) : Natalia Portillo +// +// --[ License ] ----------------------------------------------------------- +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +// --------------------------------------------------------------------------- +// Copyright © 2003-2025 Natalia Portillo +*******************************************************************************/ + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Security.Claims; +using System.Threading.Tasks; +using Marechai.Data.Dtos; +using Marechai.Database.Models; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Localization; + +namespace Marechai.Server.Controllers; + +[Route("/news")] +[ApiController] +public class NewsController(MarechaiContext context, IStringLocalizer localizer) : ControllerBase +{ + [HttpGet] + [AllowAnonymous] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task> GetAsync() => await context.News.OrderByDescending(n => n.Date) + .Select(n => new NewsDto + { + Id = n.Id, + Timestamp = n.Date, + Type = n.Type, + AffectedId = n.AddedId + }) + .ToListAsync(); + + [HttpGet] + [AllowAnonymous] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public List GetNews() + { + List news = new(); + + foreach(News @new in context.News.OrderByDescending(t => t.Date).Take(10).ToList()) + { + Machine machine = context.Machines.Find(@new.AddedId); + + if(machine is null) continue; + + switch(@new.Type) + { + case NewsType.NewComputerInDb: + news.Add(new NewsDto(@new.AddedId, + localizer["New computer in database"], + @new.Date, + "machine", + $"{machine.Company.Name} {machine.Name}")); + + break; + case NewsType.NewConsoleInDb: + news.Add(new NewsDto(@new.AddedId, + localizer["New console in database"], + @new.Date, + "machine", + $"{machine.Company.Name} {machine.Name}")); + + break; + + case NewsType.NewComputerInCollection: + news.Add(new NewsDto(@new.AddedId, + localizer["New computer in collection"], + @new.Date, + "machine", + $"{machine.Company.Name} {machine.Name}")); + + break; + + case NewsType.NewConsoleInCollection: + news.Add(new NewsDto(@new.AddedId, + localizer["New console in collection"], + @new.Date, + "machine", + $"{machine.Company.Name} {machine.Name}")); + + break; + + case NewsType.UpdatedComputerInDb: + news.Add(new NewsDto(@new.AddedId, + localizer["Updated computer in database"], + @new.Date, + "machine", + $"{machine.Company.Name} {machine.Name}")); + + break; + + case NewsType.UpdatedConsoleInDb: + news.Add(new NewsDto(@new.AddedId, + localizer["Updated console in database"], + @new.Date, + "machine", + $"{machine.Company.Name} {machine.Name}")); + + break; + + case NewsType.UpdatedComputerInCollection: + news.Add(new NewsDto(@new.AddedId, + localizer["Updated computer in collection"], + @new.Date, + "machine", + $"{machine.Company.Name} {machine.Name}")); + + break; + + case NewsType.UpdatedConsoleInCollection: + news.Add(new NewsDto(@new.AddedId, + localizer["Updated console in collection"], + @new.Date, + "machine", + $"{machine.Company.Name} {machine.Name}")); + + break; + + case NewsType.NewMoneyDonation: + // TODO + break; + + default: + continue; + } + } + + return news; + } + + [HttpDelete] + [Authorize(Roles = "Admin,UberAdmin")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task DeleteAsync(int id) + { + string userId = User.FindFirstValue(ClaimTypes.Sid); + if(userId is null) return; + News item = await context.News.FindAsync(id); + + if(item is null) return; + + context.News.Remove(item); + + await context.SaveChangesWithUserAsync(userId); + } +} diff --git a/Marechai.Server/Controllers/PeopleByBookController.cs b/Marechai.Server/Controllers/PeopleByBookController.cs new file mode 100644 index 00000000..46a3be36 --- /dev/null +++ b/Marechai.Server/Controllers/PeopleByBookController.cs @@ -0,0 +1,106 @@ +/******************************************************************************* +// MARECHAI: Master repository of computing history artifacts information +// --------------------------------------------------------------------------- +// +// Author(s) : Natalia Portillo +// +// --[ License ] ----------------------------------------------------------- +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +// --------------------------------------------------------------------------- +// Copyright © 2003-2025 Natalia Portillo +*******************************************************************************/ + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Security.Claims; +using System.Threading.Tasks; +using Marechai.Data.Dtos; +using Marechai.Database.Models; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Localization; + +namespace Marechai.Server.Controllers; + +[Route("/people-by-book")] +[ApiController] +public class PeopleByBookController(MarechaiContext context) : ControllerBase +{ + [HttpGet] + [AllowAnonymous] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task> GetByBook(long bookId) => (await context.PeopleByBooks + .Where(p => p.BookId == bookId) + .Select(p => new PersonByBookDto + { + Id = p.Id, + Name = p.Person.Name, + Surname = p.Person.Surname, + Alias = p.Person.Alias, + DisplayName = + p.Person.DisplayName, + PersonId = p.PersonId, + RoleId = p.RoleId, + Role = p.Role.Name, + BookId = p.BookId + }) + .ToListAsync()) + .OrderBy(p => p.FullName) + .ThenBy(p => p.Role) + .ToList(); + + [HttpDelete] + [Authorize(Roles = "Admin,UberAdmin")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task DeleteAsync(long id) + { + string userId = User.FindFirstValue(ClaimTypes.Sid); + if(userId is null) return; + PeopleByBook item = await context.PeopleByBooks.FindAsync(id); + + if(item is null) return; + + context.PeopleByBooks.Remove(item); + + await context.SaveChangesWithUserAsync(userId); + } + + [HttpPost] + [Authorize(Roles = "Admin,UberAdmin")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task CreateAsync(int personId, long bookId, string roleId) + { + string userId = User.FindFirstValue(ClaimTypes.Sid); + if(userId is null) return 0; + var item = new PeopleByBook + { + PersonId = personId, + BookId = bookId, + RoleId = roleId + }; + + await context.PeopleByBooks.AddAsync(item); + await context.SaveChangesWithUserAsync(userId); + + return item.Id; + } +} diff --git a/Marechai.Server/Controllers/PeopleByDocumentController.cs b/Marechai.Server/Controllers/PeopleByDocumentController.cs new file mode 100644 index 00000000..e4240bcd --- /dev/null +++ b/Marechai.Server/Controllers/PeopleByDocumentController.cs @@ -0,0 +1,104 @@ +/******************************************************************************* +// MARECHAI: Master repository of computing history artifacts information +// --------------------------------------------------------------------------- +// +// Author(s) : Natalia Portillo +// +// --[ License ] ----------------------------------------------------------- +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +// --------------------------------------------------------------------------- +// Copyright © 2003-2025 Natalia Portillo +*******************************************************************************/ + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Security.Claims; +using System.Threading.Tasks; +using Marechai.Data.Dtos; +using Marechai.Database.Models; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Localization; + +namespace Marechai.Server.Controllers; + +[Route("/people-by-document")] +[ApiController] +public class PeopleByDocumentController(MarechaiContext context) : ControllerBase +{ + [HttpGet] + [AllowAnonymous] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task> GetByDocument(long documentId) => (await context + .PeopleByDocuments.Where(p => p.DocumentId == documentId) + .Select(p => new PersonByDocumentDto + { + Id = p.Id, + Name = p.Person.Name, + Surname = p.Person.Surname, + Alias = p.Person.Alias, + DisplayName = p.Person.DisplayName, + PersonId = p.PersonId, + RoleId = p.RoleId, + Role = p.Role.Name, + DocumentId = p.DocumentId + }) + .ToListAsync()).OrderBy(p => p.FullName) + .ThenBy(p => p.Role) + .ToList(); + + [HttpDelete] + [Authorize(Roles = "Admin,UberAdmin")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task DeleteAsync(long id) + { + string userId = User.FindFirstValue(ClaimTypes.Sid); + if(userId is null) return; + PeopleByDocument item = await context.PeopleByDocuments.FindAsync(id); + + if(item is null) return; + + context.PeopleByDocuments.Remove(item); + + await context.SaveChangesWithUserAsync(userId); + } + + [HttpPost] + [Authorize(Roles = "Admin,UberAdmin")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task CreateAsync(int personId, long documentId, string roleId) + { + string userId = User.FindFirstValue(ClaimTypes.Sid); + if(userId is null) return 0; + var item = new PeopleByDocument + { + PersonId = personId, + DocumentId = documentId, + RoleId = roleId + }; + + await context.PeopleByDocuments.AddAsync(item); + await context.SaveChangesWithUserAsync(userId); + + return item.Id; + } +} diff --git a/Marechai.Server/Controllers/PeopleByMagazineController.cs b/Marechai.Server/Controllers/PeopleByMagazineController.cs new file mode 100644 index 00000000..bab8a67b --- /dev/null +++ b/Marechai.Server/Controllers/PeopleByMagazineController.cs @@ -0,0 +1,104 @@ +/******************************************************************************* +// MARECHAI: Master repository of computing history artifacts information +// --------------------------------------------------------------------------- +// +// Author(s) : Natalia Portillo +// +// --[ License ] ----------------------------------------------------------- +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +// --------------------------------------------------------------------------- +// Copyright © 2003-2025 Natalia Portillo +*******************************************************************************/ + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Security.Claims; +using System.Threading.Tasks; +using Marechai.Data.Dtos; +using Marechai.Database.Models; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Localization; + +namespace Marechai.Server.Controllers; + +[Route("/people-by-magazine")] +[ApiController] +public class PeopleByMagazineController(MarechaiContext context) : ControllerBase +{ + [HttpGet] + [AllowAnonymous] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task> GetByMagazine(long magazineId) => (await context + .PeopleByMagazines.Where(p => p.MagazineId == magazineId) + .Select(p => new PersonByMagazineDto + { + Id = p.Id, + Name = p.Person.Name, + Surname = p.Person.Surname, + Alias = p.Person.Alias, + DisplayName = p.Person.DisplayName, + PersonId = p.PersonId, + RoleId = p.RoleId, + Role = p.Role.Name, + MagazineId = p.MagazineId + }) + .ToListAsync()).OrderBy(p => p.FullName) + .ThenBy(p => p.Role) + .ToList(); + + [HttpDelete] + [Authorize(Roles = "Admin,UberAdmin")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task DeleteAsync(long id) + { + string userId = User.FindFirstValue(ClaimTypes.Sid); + if(userId is null) return; + PeopleByMagazine item = await context.PeopleByMagazines.FindAsync(id); + + if(item is null) return; + + context.PeopleByMagazines.Remove(item); + + await context.SaveChangesWithUserAsync(userId); + } + + [HttpPost] + [Authorize(Roles = "Admin,UberAdmin")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task CreateAsync(int personId, long magazineId, string roleId) + { + string userId = User.FindFirstValue(ClaimTypes.Sid); + if(userId is null) return 0; + var item = new PeopleByMagazine + { + PersonId = personId, + MagazineId = magazineId, + RoleId = roleId + }; + + await context.PeopleByMagazines.AddAsync(item); + await context.SaveChangesWithUserAsync(userId); + + return item.Id; + } +} diff --git a/Marechai.Server/Controllers/PeopleController.cs b/Marechai.Server/Controllers/PeopleController.cs new file mode 100644 index 00000000..6b191ca0 --- /dev/null +++ b/Marechai.Server/Controllers/PeopleController.cs @@ -0,0 +1,164 @@ +/******************************************************************************* +// MARECHAI: Master repository of computing history artifacts information +// --------------------------------------------------------------------------- +// +// Author(s) : Natalia Portillo +// +// --[ License ] ----------------------------------------------------------- +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +// --------------------------------------------------------------------------- +// Copyright © 2003-2025 Natalia Portillo +*******************************************************************************/ + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Security.Claims; +using System.Threading.Tasks; +using Marechai.Data.Dtos; +using Marechai.Database.Models; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Localization; + +namespace Marechai.Server.Controllers; + +[Route("/people")] +[ApiController] +public class PeopleController(MarechaiContext context) : ControllerBase +{ + [HttpGet] + [AllowAnonymous] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task> GetAsync() => await context.People.OrderBy(p => p.DisplayName) + .ThenBy(p => p.Alias) + .ThenBy(p => p.Name) + .ThenBy(p => p.Surname) + .Select(p => new PersonDto + { + Id = p.Id, + Name = p.Name, + Surname = p.Surname, + CountryOfBirth = p.CountryOfBirth.Name, + BirthDate = p.BirthDate, + DeathDate = p.DeathDate, + Webpage = p.Webpage, + Twitter = p.Twitter, + Facebook = p.Facebook, + Photo = p.Photo, + Alias = p.Alias, + DisplayName = p.DisplayName + }) + .ToListAsync(); + + [HttpGet] + [AllowAnonymous] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task GetAsync(int id) => await context.People.Where(p => p.Id == id) + .Select(p => new PersonDto + { + Id = p.Id, + Name = p.Name, + Surname = p.Surname, + CountryOfBirthId = p.CountryOfBirthId, + BirthDate = p.BirthDate, + DeathDate = p.DeathDate, + Webpage = p.Webpage, + Twitter = p.Twitter, + Facebook = p.Facebook, + Photo = p.Photo, + Alias = p.Alias, + DisplayName = p.DisplayName + }) + .FirstOrDefaultAsync(); + + [HttpPost] + [Authorize(Roles = "Admin,UberAdmin")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task UpdateAsync(PersonDto dto) + { + string userId = User.FindFirstValue(ClaimTypes.Sid); + if(userId is null) return; + Person model = await context.People.FindAsync(dto.Id); + + if(model is null) return; + + model.Name = dto.Name; + model.Surname = dto.Surname; + model.CountryOfBirthId = dto.CountryOfBirthId; + model.BirthDate = dto.BirthDate; + model.DeathDate = dto.DeathDate; + model.Webpage = dto.Webpage; + model.Twitter = dto.Twitter; + model.Facebook = dto.Facebook; + model.Photo = dto.Photo; + model.Alias = dto.Alias; + model.DisplayName = dto.DisplayName; + + await context.SaveChangesWithUserAsync(userId); + } + + [HttpPost] + [Authorize(Roles = "Admin,UberAdmin")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task CreateAsync(PersonDto dto) + { + string userId = User.FindFirstValue(ClaimTypes.Sid); + if(userId is null) return 0; + var model = new Person + { + Name = dto.Name, + Surname = dto.Surname, + CountryOfBirthId = dto.CountryOfBirthId, + BirthDate = dto.BirthDate, + DeathDate = dto.DeathDate, + Webpage = dto.Webpage, + Twitter = dto.Twitter, + Facebook = dto.Facebook, + Photo = dto.Photo, + Alias = dto.Alias, + DisplayName = dto.DisplayName + }; + + await context.People.AddAsync(model); + await context.SaveChangesWithUserAsync(userId); + + return model.Id; + } + + [HttpDelete] + [Authorize(Roles = "Admin,UberAdmin")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task DeleteAsync(int id) + { + string userId = User.FindFirstValue(ClaimTypes.Sid); + if(userId is null) return; + Person item = await context.People.FindAsync(id); + + if(item is null) return; + + context.People.Remove(item); + + await context.SaveChangesWithUserAsync(userId); + } +} diff --git a/Marechai.Server/Controllers/ProcessorsByMachineController.cs b/Marechai.Server/Controllers/ProcessorsByMachineController.cs new file mode 100644 index 00000000..54252cc8 --- /dev/null +++ b/Marechai.Server/Controllers/ProcessorsByMachineController.cs @@ -0,0 +1,101 @@ +/******************************************************************************* +// MARECHAI: Master repository of computing history artifacts information +// --------------------------------------------------------------------------- +// +// Author(s) : Natalia Portillo +// +// --[ License ] ----------------------------------------------------------- +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +// --------------------------------------------------------------------------- +// Copyright © 2003-2025 Natalia Portillo +*******************************************************************************/ + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Security.Claims; +using System.Threading.Tasks; +using Marechai.Data.Dtos; +using Marechai.Database.Models; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Localization; + +namespace Marechai.Server.Controllers; + +[Route("/processors-by-machine")] +[ApiController] +public class ProcessorsByMachineController(MarechaiContext context) : ControllerBase +{ + [HttpGet] + [AllowAnonymous] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task> GetByMachine(int machineId) => await context + .ProcessorsByMachine.Where(p => p.MachineId == machineId) + .Select(p => new ProcessorByMachineDto + { + Id = p.Id, + Name = p.Processor.Name, + CompanyName = p.Processor.Company.Name, + ProcessorId = p.ProcessorId, + MachineId = p.MachineId, + Speed = p.Speed + }) + .OrderBy(p => p.CompanyName) + .ThenBy(p => p.Name) + .ToListAsync(); + + [HttpDelete] + [Authorize(Roles = "Admin,UberAdmin")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task DeleteAsync(long id) + { + string userId = User.FindFirstValue(ClaimTypes.Sid); + if(userId is null) return; + ProcessorsByMachine item = await context.ProcessorsByMachine.FindAsync(id); + + if(item is null) return; + + context.ProcessorsByMachine.Remove(item); + + await context.SaveChangesWithUserAsync(userId); + } + + [HttpPost] + [Authorize(Roles = "Admin,UberAdmin")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task CreateAsync(int processorId, int machineId, float? speed) + { + string userId = User.FindFirstValue(ClaimTypes.Sid); + if(userId is null) return 0; + var item = new ProcessorsByMachine + { + ProcessorId = processorId, + MachineId = machineId, + Speed = speed + }; + + await context.ProcessorsByMachine.AddAsync(item); + await context.SaveChangesWithUserAsync(userId); + + return item.Id; + } +} diff --git a/Marechai.Server/Controllers/ProcessorsController.cs b/Marechai.Server/Controllers/ProcessorsController.cs new file mode 100644 index 00000000..a3956588 --- /dev/null +++ b/Marechai.Server/Controllers/ProcessorsController.cs @@ -0,0 +1,269 @@ +/******************************************************************************* +// MARECHAI: Master repository of computing history artifacts information +// --------------------------------------------------------------------------- +// +// Author(s) : Natalia Portillo +// +// --[ License ] ----------------------------------------------------------- +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +// --------------------------------------------------------------------------- +// Copyright © 2003-2025 Natalia Portillo +*******************************************************************************/ + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Security.Claims; +using System.Threading.Tasks; +using Marechai.Data.Dtos; +using Marechai.Database.Models; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Localization; + +namespace Marechai.Server.Controllers; + +[Route("/processors")] +[ApiController] +public class ProcessorsController(MarechaiContext context) : ControllerBase +{ + [HttpGet] + [AllowAnonymous] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task> GetAsync() => await context.Processors + .Select(p => new ProcessorDto + { + Name = p.Name, + CompanyName = p.Company.Name, + CompanyId = p.Company.Id, + ModelCode = p.ModelCode, + Introduced = p.Introduced, + Speed = p.Speed, + Package = p.Package, + Gprs = p.Gprs, + GprSize = p.GprSize, + Fprs = p.Fprs, + FprSize = p.FprSize, + Cores = p.Cores, + ThreadsPerCore = p.ThreadsPerCore, + Process = p.Process, + ProcessNm = p.ProcessNm, + DieSize = p.DieSize, + Transistors = p.Transistors, + DataBus = p.DataBus, + AddrBus = p.AddrBus, + SimdRegisters = p.SimdRegisters, + SimdSize = p.SimdSize, + L1Instruction = p.L1Instruction, + L1Data = p.L1Data, + L2 = p.L2, + L3 = p.L3, + InstructionSet = p.InstructionSet.Name, + Id = p.Id, + InstructionSetExtensions = + p.InstructionSetExtensions + .Select(e => e.Extension + .Extension) + .ToList() + }) + .OrderBy(p => p.CompanyName) + .ThenBy(p => p.Name) + .ToListAsync(); + + [HttpGet] + [AllowAnonymous] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task> GetByMachineAsync(int machineId) => await context.ProcessorsByMachine + .Where(p => p.MachineId == machineId) + .Select(p => new ProcessorDto + { + Name = p.Processor.Name, + CompanyName = p.Processor.Company.Name, + CompanyId = p.Processor.Company.Id, + ModelCode = p.Processor.ModelCode, + Introduced = p.Processor.Introduced, + Speed = p.Speed, + Package = p.Processor.Package, + Gprs = p.Processor.Gprs, + GprSize = p.Processor.GprSize, + Fprs = p.Processor.Fprs, + FprSize = p.Processor.FprSize, + Cores = p.Processor.Cores, + ThreadsPerCore = p.Processor.ThreadsPerCore, + Process = p.Processor.Process, + ProcessNm = p.Processor.ProcessNm, + DieSize = p.Processor.DieSize, + Transistors = p.Processor.Transistors, + DataBus = p.Processor.DataBus, + AddrBus = p.Processor.AddrBus, + SimdRegisters = p.Processor.SimdRegisters, + SimdSize = p.Processor.SimdSize, + L1Instruction = p.Processor.L1Instruction, + L1Data = p.Processor.L1Data, + L2 = p.Processor.L2, + L3 = p.Processor.L3, + InstructionSet = p.Processor.InstructionSet.Name, + Id = p.Processor.Id, + InstructionSetExtensions = + p.Processor.InstructionSetExtensions.Select(e => e.Extension.Extension).ToList() + }) + .OrderBy(p => p.CompanyName) + .ThenBy(p => p.Name) + .ToListAsync(); + + [HttpGet] + [AllowAnonymous] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task GetAsync(int id) => await context.Processors.Where(p => p.Id == id) + .Select(p => new ProcessorDto + { + Name = p.Name, + CompanyName = p.Company.Name, + CompanyId = p.Company.Id, + ModelCode = p.ModelCode, + Introduced = p.Introduced, + Speed = p.Speed, + Package = p.Package, + Gprs = p.Gprs, + GprSize = p.GprSize, + Fprs = p.Fprs, + FprSize = p.FprSize, + Cores = p.Cores, + ThreadsPerCore = p.ThreadsPerCore, + Process = p.Process, + ProcessNm = p.ProcessNm, + DieSize = p.DieSize, + Transistors = p.Transistors, + DataBus = p.DataBus, + AddrBus = p.AddrBus, + SimdRegisters = p.SimdRegisters, + SimdSize = p.SimdSize, + L1Instruction = p.L1Instruction, + L1Data = p.L1Data, + L2 = p.L2, + L3 = p.L3, + InstructionSet = + p.InstructionSet.Name, + InstructionSetId = p.InstructionSetId + }) + .FirstOrDefaultAsync(); + + [HttpPost] + [Authorize(Roles = "Admin,UberAdmin")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task UpdateAsync(ProcessorDto dto) + { + string userId = User.FindFirstValue(ClaimTypes.Sid); + if(userId is null) return; + Processor model = await context.Processors.FindAsync(dto.Id); + + if(model is null) return; + + model.AddrBus = dto.AddrBus; + model.CompanyId = dto.CompanyId; + model.Cores = dto.Cores; + model.DataBus = dto.DataBus; + model.DieSize = dto.DieSize; + model.Fprs = dto.Fprs; + model.FprSize = dto.FprSize; + model.Gprs = dto.Gprs; + model.GprSize = dto.GprSize; + model.InstructionSetId = dto.InstructionSetId; + model.Introduced = dto.Introduced; + model.L1Data = dto.L1Data; + model.L1Instruction = dto.L1Instruction; + model.L2 = dto.L2; + model.L3 = dto.L3; + model.ModelCode = dto.ModelCode; + model.Name = dto.Name; + model.Package = dto.Package; + model.Process = dto.Process; + model.ProcessNm = dto.ProcessNm; + model.SimdRegisters = dto.SimdRegisters; + model.SimdSize = dto.SimdSize; + model.Speed = dto.Speed; + model.ThreadsPerCore = dto.ThreadsPerCore; + model.Transistors = dto.Transistors; + + await context.SaveChangesWithUserAsync(userId); + } + + [HttpPost] + [Authorize(Roles = "Admin,UberAdmin")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task CreateAsync(ProcessorDto dto) + { + string userId = User.FindFirstValue(ClaimTypes.Sid); + if(userId is null) return 0; + var model = new Processor + { + AddrBus = dto.AddrBus, + CompanyId = dto.CompanyId, + Cores = dto.Cores, + DataBus = dto.DataBus, + DieSize = dto.DieSize, + Fprs = dto.Fprs, + FprSize = dto.FprSize, + Gprs = dto.Gprs, + GprSize = dto.GprSize, + InstructionSetId = dto.InstructionSetId, + Introduced = dto.Introduced, + L1Data = dto.L1Data, + L1Instruction = dto.L1Instruction, + L2 = dto.L2, + L3 = dto.L3, + ModelCode = dto.ModelCode, + Name = dto.Name, + Package = dto.Package, + Process = dto.Process, + ProcessNm = dto.ProcessNm, + SimdRegisters = dto.SimdRegisters, + SimdSize = dto.SimdSize, + Speed = dto.Speed, + ThreadsPerCore = dto.ThreadsPerCore, + Transistors = dto.Transistors + }; + + await context.Processors.AddAsync(model); + await context.SaveChangesWithUserAsync(userId); + + return model.Id; + } + + [HttpDelete] + [Authorize(Roles = "Admin,UberAdmin")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task DeleteAsync(int id) + { + string userId = User.FindFirstValue(ClaimTypes.Sid); + if(userId is null) return; + Processor item = await context.Processors.FindAsync(id); + + if(item is null) return; + + context.Processors.Remove(item); + + await context.SaveChangesWithUserAsync(userId); + } +} diff --git a/Marechai.Server/Controllers/ResolutionsByGpuController.cs b/Marechai.Server/Controllers/ResolutionsByGpuController.cs new file mode 100644 index 00000000..ff201d34 --- /dev/null +++ b/Marechai.Server/Controllers/ResolutionsByGpuController.cs @@ -0,0 +1,111 @@ +/******************************************************************************* +// MARECHAI: Master repository of computing history artifacts information +// --------------------------------------------------------------------------- +// +// Author(s) : Natalia Portillo +// +// --[ License ] ----------------------------------------------------------- +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +// --------------------------------------------------------------------------- +// Copyright © 2003-2025 Natalia Portillo +*******************************************************************************/ + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Security.Claims; +using System.Threading.Tasks; +using Marechai.Data.Dtos; +using Marechai.Database.Models; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Localization; + +namespace Marechai.Server.Controllers; + +[Route("/resolutions-by-gpu")] +[ApiController] +public class ResolutionsByGpuController(MarechaiContext context) : ControllerBase +{ + [HttpGet] + [AllowAnonymous] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task> GetByGpu(int resolutionId) => (await context.ResolutionsByGpu + .Where(r => r.ResolutionId == resolutionId) + .Select(r => new ResolutionByGpuDto + { + Id = r.Id, + GpuId = r.GpuId, + Resolution = new ResolutionDto + { + Id = r.Resolution.Id, + Width = r.Resolution.Width, + Height = r.Resolution.Height, + Colors = r.Resolution.Colors, + Palette = r.Resolution.Palette, + Chars = r.Resolution.Chars, + Grayscale = r.Resolution.Grayscale + }, + ResolutionId = r.ResolutionId + }) + .ToListAsync()).OrderBy(r => r.Resolution.Width) + .ThenBy(r => r.Resolution.Height) + .ThenBy(r => r.Resolution.Chars) + .ThenBy(r => r.Resolution.Grayscale) + .ThenBy(r => r.Resolution.Colors) + .ThenBy(r => r.Resolution.Palette) + .ToList(); + + [HttpDelete] + [Authorize(Roles = "Admin,UberAdmin")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task DeleteAsync(long id) + { + string userId = User.FindFirstValue(ClaimTypes.Sid); + if(userId is null) return; + ResolutionsByGpu item = await context.ResolutionsByGpu.FindAsync(id); + + if(item is null) return; + + context.ResolutionsByGpu.Remove(item); + + await context.SaveChangesWithUserAsync(userId); + } + + [HttpPost] + [Authorize(Roles = "Admin,UberAdmin")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task CreateAsync(int resolutionId, int gpuId) + { + string userId = User.FindFirstValue(ClaimTypes.Sid); + if(userId is null) return 0; + var item = new ResolutionsByGpu + { + GpuId = gpuId, + ResolutionId = resolutionId + }; + + await context.ResolutionsByGpu.AddAsync(item); + await context.SaveChangesWithUserAsync(userId); + + return item.Id; + } +} diff --git a/Marechai.Server/Controllers/ResolutionsByScreenController.cs b/Marechai.Server/Controllers/ResolutionsByScreenController.cs new file mode 100644 index 00000000..0e0b3322 --- /dev/null +++ b/Marechai.Server/Controllers/ResolutionsByScreenController.cs @@ -0,0 +1,111 @@ +/******************************************************************************* +// MARECHAI: Master repository of computing history artifacts information +// --------------------------------------------------------------------------- +// +// Author(s) : Natalia Portillo +// +// --[ License ] ----------------------------------------------------------- +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +// --------------------------------------------------------------------------- +// Copyright © 2003-2025 Natalia Portillo +*******************************************************************************/ + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Security.Claims; +using System.Threading.Tasks; +using Marechai.Data.Dtos; +using Marechai.Database.Models; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Localization; + +namespace Marechai.Server.Controllers; + +[Route("/resolutions-by-screen")] +[ApiController] +public class ResolutionsByScreenController(MarechaiContext context) : ControllerBase +{ + [HttpGet] + [AllowAnonymous] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task> GetByScreen(int resolutionId) => (await context + .ResolutionsByScreen.Where(r => r.ResolutionId == resolutionId) + .Select(r => new ResolutionByScreenDto + { + Id = r.Id, + ScreenId = r.ScreenId, + Resolution = new ResolutionDto + { + Id = r.Resolution.Id, + Width = r.Resolution.Width, + Height = r.Resolution.Height, + Colors = r.Resolution.Colors, + Palette = r.Resolution.Palette, + Chars = r.Resolution.Chars, + Grayscale = r.Resolution.Grayscale + }, + ResolutionId = r.ResolutionId + }) + .ToListAsync()).OrderBy(r => r.Resolution.Width) + .ThenBy(r => r.Resolution.Height) + .ThenBy(r => r.Resolution.Chars) + .ThenBy(r => r.Resolution.Grayscale) + .ThenBy(r => r.Resolution.Colors) + .ThenBy(r => r.Resolution.Palette) + .ToList(); + + [HttpDelete] + [Authorize(Roles = "Admin,UberAdmin")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task DeleteAsync(long id) + { + string userId = User.FindFirstValue(ClaimTypes.Sid); + if(userId is null) return; + ResolutionsByScreen item = await context.ResolutionsByScreen.FindAsync(id); + + if(item is null) return; + + context.ResolutionsByScreen.Remove(item); + + await context.SaveChangesWithUserAsync(userId); + } + + [HttpPost] + [Authorize(Roles = "Admin,UberAdmin")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task CreateAsync(int resolutionId, int screenId) + { + string userId = User.FindFirstValue(ClaimTypes.Sid); + if(userId is null) return 0; + var item = new ResolutionsByScreen + { + ScreenId = screenId, + ResolutionId = resolutionId + }; + + await context.ResolutionsByScreen.AddAsync(item); + await context.SaveChangesWithUserAsync(userId); + + return item.Id; + } +} diff --git a/Marechai.Server/Controllers/ResolutionsController.cs b/Marechai.Server/Controllers/ResolutionsController.cs new file mode 100644 index 00000000..5974f6fb --- /dev/null +++ b/Marechai.Server/Controllers/ResolutionsController.cs @@ -0,0 +1,147 @@ +/******************************************************************************* +// MARECHAI: Master repository of computing history artifacts information +// --------------------------------------------------------------------------- +// +// Author(s) : Natalia Portillo +// +// --[ License ] ----------------------------------------------------------- +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +// --------------------------------------------------------------------------- +// Copyright © 2003-2025 Natalia Portillo +*******************************************************************************/ + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Security.Claims; +using System.Threading.Tasks; +using Marechai.Data.Dtos; +using Marechai.Database.Models; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Localization; + +namespace Marechai.Server.Controllers; + +[Route("/resolutions")] +[ApiController] +public class ResolutionsController(MarechaiContext context) : ControllerBase +{ + [HttpGet] + [AllowAnonymous] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task> GetAsync() => await context.Resolutions + .Select(r => new ResolutionDto + { + Id = r.Id, + Width = r.Width, + Height = r.Height, + Colors = r.Colors, + Palette = r.Palette, + Chars = r.Chars, + Grayscale = r.Grayscale + }) + .OrderBy(r => r.Width) + .ThenBy(r => r.Height) + .ThenBy(r => r.Chars) + .ThenBy(r => r.Grayscale) + .ThenBy(r => r.Colors) + .ThenBy(r => r.Palette) + .ToListAsync(); + + [HttpGet] + [AllowAnonymous] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task GetAsync(int id) => await context.Resolutions.Where(r => r.Id == id) + .Select(r => new ResolutionDto + { + Id = r.Id, + Width = r.Width, + Height = r.Height, + Colors = r.Colors, + Palette = r.Palette, + Chars = r.Chars, + Grayscale = r.Grayscale + }) + .FirstOrDefaultAsync(); + + [HttpPost] + [Authorize(Roles = "Admin,UberAdmin")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task UpdateAsync(ResolutionDto dto) + { + string userId = User.FindFirstValue(ClaimTypes.Sid); + if(userId is null) return; + Resolution model = await context.Resolutions.FindAsync(dto.Id); + + if(model is null) return; + + model.Chars = dto.Chars; + model.Colors = dto.Colors; + model.Grayscale = dto.Grayscale; + model.Height = dto.Height; + model.Palette = dto.Palette; + model.Width = dto.Width; + + await context.SaveChangesWithUserAsync(userId); + } + + [HttpPost] + [Authorize(Roles = "Admin,UberAdmin")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task CreateAsync(ResolutionDto dto) + { + string userId = User.FindFirstValue(ClaimTypes.Sid); + if(userId is null) return 0; + var model = new Resolution + { + Chars = dto.Chars, + Colors = dto.Colors, + Grayscale = dto.Grayscale, + Height = dto.Height, + Palette = dto.Palette, + Width = dto.Width + }; + + await context.Resolutions.AddAsync(model); + await context.SaveChangesWithUserAsync(userId); + + return model.Id; + } + + [HttpDelete] + [Authorize(Roles = "Admin,UberAdmin")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task DeleteAsync(int id) + { + string userId = User.FindFirstValue(ClaimTypes.Sid); + if(userId is null) return; + Resolution item = await context.Resolutions.FindAsync(id); + + if(item is null) return; + + context.Resolutions.Remove(item); + + await context.SaveChangesWithUserAsync(userId); + } +} diff --git a/Marechai.Server/Controllers/ScreensByMachineController.cs b/Marechai.Server/Controllers/ScreensByMachineController.cs new file mode 100644 index 00000000..fba2fd3b --- /dev/null +++ b/Marechai.Server/Controllers/ScreensByMachineController.cs @@ -0,0 +1,117 @@ +/******************************************************************************* +// MARECHAI: Master repository of computing history artifacts information +// --------------------------------------------------------------------------- +// +// Author(s) : Natalia Portillo +// +// --[ License ] ----------------------------------------------------------- +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +// --------------------------------------------------------------------------- +// Copyright © 2003-2025 Natalia Portillo +*******************************************************************************/ + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Security.Claims; +using System.Threading.Tasks; +using Marechai.Data.Dtos; +using Marechai.Database.Models; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Localization; + +namespace Marechai.Server.Controllers; + +[Route("/screens-by-machine")] +[ApiController] +public class ScreensByMachineController(MarechaiContext context) : ControllerBase +{ + [HttpGet] + [AllowAnonymous] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task> GetByMachine(int machineId) => await context.ScreensByMachine + .Where(s => s.MachineId == machineId) + .Select(s => new ScreenByMachineDto + { + Id = s.Id, + ScreenId = s.ScreenId, + MachineId = s.MachineId, + Screen = new ScreenDto + { + Diagonal = s.Screen.Diagonal, + EffectiveColors = s.Screen.EffectiveColors, + Height = s.Screen.Height, + Id = s.Screen.Id, + NativeResolution = new ResolutionDto + { + Chars = s.Screen.NativeResolution.Chars, + Colors = s.Screen.NativeResolution.Colors, + Grayscale = s.Screen.NativeResolution.Grayscale, + Height = s.Screen.NativeResolution.Height, + Id = s.Screen.NativeResolutionId, + Palette = s.Screen.NativeResolution.Palette, + Width = s.Screen.NativeResolution.Width + }, + NativeResolutionId = s.Screen.NativeResolutionId, + Type = s.Screen.Type, + Width = s.Screen.Width + } + }) + .ToListAsync(); + + [HttpDelete] + [Authorize(Roles = "Admin,UberAdmin")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task DeleteAsync(long id) + { + string userId = User.FindFirstValue(ClaimTypes.Sid); + if(userId is null) return; + ScreensByMachine item = await context.ScreensByMachine.FindAsync(id); + + if(item is null) return; + + context.ScreensByMachine.Remove(item); + + await context.SaveChangesWithUserAsync(userId); + } + + [HttpPost] + [Authorize(Roles = "Admin,UberAdmin")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task CreateAsync(int machineId, int screenId) + { + string userId = User.FindFirstValue(ClaimTypes.Sid); + if(userId is null) return 0; + if(context.ScreensByMachine.Any(s => s.MachineId == machineId && s.ScreenId == screenId)) return 0; + + var item = new ScreensByMachine + { + ScreenId = screenId, + MachineId = machineId + }; + + await context.ScreensByMachine.AddAsync(item); + await context.SaveChangesWithUserAsync(userId); + + return item.Id; + } +} diff --git a/Marechai.Server/Controllers/ScreensController.cs b/Marechai.Server/Controllers/ScreensController.cs new file mode 100644 index 00000000..70895f82 --- /dev/null +++ b/Marechai.Server/Controllers/ScreensController.cs @@ -0,0 +1,180 @@ +/******************************************************************************* +// MARECHAI: Master repository of computing history artifacts information +// --------------------------------------------------------------------------- +// +// Author(s) : Natalia Portillo +// +// --[ License ] ----------------------------------------------------------- +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +// --------------------------------------------------------------------------- +// Copyright © 2003-2025 Natalia Portillo +*******************************************************************************/ + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Security.Claims; +using System.Threading.Tasks; +using Marechai.Data.Dtos; +using Marechai.Database.Models; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Localization; + +namespace Marechai.Server.Controllers; + +[Route("/screens")] +[ApiController] +public class ScreensController(MarechaiContext context) : ControllerBase +{ + [HttpGet] + [AllowAnonymous] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task> GetAsync() => (await context.Screens.Select(s => new ScreenDto + { + Diagonal = s.Diagonal, + EffectiveColors = s.EffectiveColors, + Height = s.Height, + Id = s.Id, + Type = s.Type, + Width = s.Width, + NativeResolutionId = + s.NativeResolutionId, + NativeResolution = + new ResolutionDto + { + Chars = s.NativeResolution + .Chars, + Colors = s.NativeResolution + .Colors, + Grayscale = s.NativeResolution + .Grayscale, + Height = s.NativeResolution + .Height, + Id = + s.NativeResolution.Id, + Palette = s.NativeResolution + .Palette, + Width = s.NativeResolution + .Width + } + }) + .ToListAsync()).OrderBy(s => s.Diagonal) + .ThenBy(s => s.EffectiveColors) + .ThenBy(s => s.NativeResolution.ToString()) + .ThenBy(s => s.Type) + .ThenBy(s => s.Size) + .ToList(); + + [HttpGet] + [AllowAnonymous] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task GetAsync(int id) => await context.Screens.Where(s => s.Id == id) + .Select(s => new ScreenDto + { + Diagonal = s.Diagonal, + EffectiveColors = s.EffectiveColors, + Height = s.Height, + Id = s.Id, + NativeResolution = new ResolutionDto + { + Chars = s.NativeResolution.Chars, + Colors = s.NativeResolution.Colors, + Grayscale = s.NativeResolution + .Grayscale, + Height = s.NativeResolution.Height, + Id = s.NativeResolution.Id, + Palette = + s.NativeResolution.Palette, + Width = s.NativeResolution.Width + }, + NativeResolutionId = s.NativeResolutionId, + Type = s.Type, + Width = s.Width + }) + .FirstOrDefaultAsync(); + + [HttpPost] + [Authorize(Roles = "Admin,UberAdmin")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task UpdateAsync(ScreenDto dto) + { + string userId = User.FindFirstValue(ClaimTypes.Sid); + if(userId is null) return; + Screen model = await context.Screens.FindAsync(dto.Id); + + if(model is null) return; + + Resolution nativeResolution = await context.Resolutions.FindAsync(dto.NativeResolutionId); + + if(nativeResolution is null) return; + + model.Diagonal = dto.Diagonal; + model.EffectiveColors = dto.EffectiveColors; + model.Height = dto.Height; + model.NativeResolutionId = dto.NativeResolutionId; + model.Type = dto.Type; + model.Width = dto.Width; + + await context.SaveChangesWithUserAsync(userId); + } + + [HttpPost] + [Authorize(Roles = "Admin,UberAdmin")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task CreateAsync(ScreenDto dto) + { + string userId = User.FindFirstValue(ClaimTypes.Sid); + if(userId is null) return 0; + var model = new Screen + { + Diagonal = dto.Diagonal, + EffectiveColors = dto.EffectiveColors, + Height = dto.Height, + NativeResolutionId = dto.NativeResolutionId, + Type = dto.Type, + Width = dto.Width + }; + + await context.Screens.AddAsync(model); + await context.SaveChangesWithUserAsync(userId); + + return model.Id; + } + + [HttpDelete] + [Authorize(Roles = "Admin,UberAdmin")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task DeleteAsync(int id) + { + string userId = User.FindFirstValue(ClaimTypes.Sid); + if(userId is null) return; + Screen item = await context.Screens.FindAsync(id); + + if(item is null) return; + + context.Screens.Remove(item); + + await context.SaveChangesWithUserAsync(userId); + } +} diff --git a/Marechai.Server/Controllers/SoftwareFamiliesController.cs b/Marechai.Server/Controllers/SoftwareFamiliesController.cs new file mode 100644 index 00000000..024c6495 --- /dev/null +++ b/Marechai.Server/Controllers/SoftwareFamiliesController.cs @@ -0,0 +1,131 @@ +/******************************************************************************* +// MARECHAI: Master repository of computing history artifacts information +// --------------------------------------------------------------------------- +// +// Author(s) : Natalia Portillo +// +// --[ License ] ----------------------------------------------------------- +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +// --------------------------------------------------------------------------- +// Copyright © 2003-2025 Natalia Portillo +*******************************************************************************/ + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Security.Claims; +using System.Threading.Tasks; +using Marechai.Data.Dtos; +using Marechai.Database.Models; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Localization; + +namespace Marechai.Server.Controllers; + +[Route("/software-families")] +[ApiController] +public class SoftwareFamiliesController(MarechaiContext context) : ControllerBase +{ + [HttpGet] + [AllowAnonymous] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task> GetAsync() => await context.SoftwareFamilies.OrderBy(b => b.Name) + .Select(b => new SoftwareFamilyDto + { + Id = b.Id, + Name = b.Name, + Parent = b.Parent.Name, + Introduced = b.Introduced, + ParentId = b.ParentId + }) + .ToListAsync(); + + [HttpGet] + [AllowAnonymous] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task GetAsync(ulong id) => await context.SoftwareFamilies + .Where(b => b.Id == id) + .Select(b => new SoftwareFamilyDto + { + Id = b.Id, + Name = b.Name, + Parent = b.Parent.Name, + Introduced = b.Introduced, + ParentId = b.ParentId + }) + .FirstOrDefaultAsync(); + + [HttpPost] + [Authorize(Roles = "Admin,UberAdmin")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task UpdateAsync(SoftwareFamilyDto dto) + { + string userId = User.FindFirstValue(ClaimTypes.Sid); + if(userId is null) return; + SoftwareFamily model = await context.SoftwareFamilies.FindAsync(dto.Id); + + if(model is null) return; + + model.Name = dto.Name; + model.ParentId = dto.ParentId; + model.Introduced = dto.Introduced; + await context.SaveChangesWithUserAsync(userId); + } + + [HttpPost] + [Authorize(Roles = "Admin,UberAdmin")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task CreateAsync(SoftwareFamilyDto dto) + { + string userId = User.FindFirstValue(ClaimTypes.Sid); + if(userId is null) return null; + var model = new SoftwareFamily + { + Name = dto.Name, + ParentId = dto.ParentId, + Introduced = dto.Introduced + }; + + await context.SoftwareFamilies.AddAsync(model); + await context.SaveChangesWithUserAsync(userId); + + return model.Id; + } + + [HttpDelete] + [Authorize(Roles = "Admin,UberAdmin")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task DeleteAsync(ulong id) + { + string userId = User.FindFirstValue(ClaimTypes.Sid); + if(userId is null) return; + SoftwareFamily item = await context.SoftwareFamilies.FindAsync(id); + + if(item is null) return; + + context.SoftwareFamilies.Remove(item); + + await context.SaveChangesWithUserAsync(userId); + } +} diff --git a/Marechai.Server/Controllers/SoftwareVariantsController.cs b/Marechai.Server/Controllers/SoftwareVariantsController.cs new file mode 100644 index 00000000..15f258d5 --- /dev/null +++ b/Marechai.Server/Controllers/SoftwareVariantsController.cs @@ -0,0 +1,184 @@ +/******************************************************************************* +// MARECHAI: Master repository of computing history artifacts information +// --------------------------------------------------------------------------- +// +// Author(s) : Natalia Portillo +// +// --[ License ] ----------------------------------------------------------- +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +// --------------------------------------------------------------------------- +// Copyright © 2003-2025 Natalia Portillo +*******************************************************************************/ + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Security.Claims; +using System.Threading.Tasks; +using Marechai.Data.Dtos; +using Marechai.Database.Models; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Localization; + +namespace Marechai.Server.Controllers; + +[Route("/software-variants")] +[ApiController] +public class SoftwareVariantsController(MarechaiContext context) : ControllerBase +{ + [HttpGet] + [AllowAnonymous] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task> GetAsync() => await context.SoftwareVariants + .OrderBy(b => b.SoftwareVersion.Family.Name) + .ThenBy(b => b.SoftwareVersion.Version) + .ThenBy(b => b.Name) + .ThenBy(b => b.Version) + .ThenBy(b => b.Introduced) + .Select(b => new SoftwareVariantDto + { + Id = b.Id, + Name = b.Name, + Version = b.Version, + Introduced = b.Introduced, + ParentId = b.ParentId, + Parent = b.Parent.Name ?? b.Parent.Version, + SoftwareVersionId = b.SoftwareVersionId, + SoftwareVersion = + b.SoftwareVersion.Name ?? + b.SoftwareVersion.Version, + MinimumMemory = b.MinimumMemory, + RecommendedMemory = b.RecommendedMemory, + RequiredStorage = b.RequiredStorage, + PartNumber = b.PartNumber, + SerialNumber = b.SerialNumber, + ProductCode = b.ProductCode, + CatalogueNumber = b.CatalogueNumber, + DistributionMode = b.DistributionMode + }) + .ToListAsync(); + + [HttpGet] + [AllowAnonymous] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task GetAsync(ulong id) => await context.SoftwareVariants + .Where(b => b.Id == id) + .Select(b => new SoftwareVariantDto + { + Id = b.Id, + Name = b.Name, + Version = b.Version, + Introduced = b.Introduced, + ParentId = b.ParentId, + Parent = + b.Parent.Name ?? b.Parent.Version, + SoftwareVersionId = b.SoftwareVersionId, + SoftwareVersion = + b.SoftwareVersion.Name ?? + b.SoftwareVersion.Version, + MinimumMemory = b.MinimumMemory, + RecommendedMemory = b.RecommendedMemory, + RequiredStorage = b.RequiredStorage, + PartNumber = b.PartNumber, + SerialNumber = b.SerialNumber, + ProductCode = b.ProductCode, + CatalogueNumber = b.CatalogueNumber, + DistributionMode = b.DistributionMode + }) + .FirstOrDefaultAsync(); + + [HttpPost] + [Authorize(Roles = "Admin,UberAdmin")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task UpdateAsync(SoftwareVariantDto dto) + { + string userId = User.FindFirstValue(ClaimTypes.Sid); + if(userId is null) return; + SoftwareVariant model = await context.SoftwareVariants.FindAsync(dto.Id); + + if(model is null) return; + + model.Name = dto.Name; + model.Version = dto.Version; + model.Introduced = dto.Introduced; + model.ParentId = dto.ParentId; + model.SoftwareVersionId = dto.SoftwareVersionId; + model.MinimumMemory = dto.MinimumMemory; + model.RecommendedMemory = dto.RecommendedMemory; + model.RequiredStorage = dto.RequiredStorage; + model.PartNumber = dto.PartNumber; + model.SerialNumber = dto.SerialNumber; + model.ProductCode = dto.ProductCode; + model.CatalogueNumber = dto.CatalogueNumber; + model.DistributionMode = dto.DistributionMode; + + await context.SaveChangesWithUserAsync(userId); + } + + [HttpPost] + [Authorize(Roles = "Admin,UberAdmin")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task CreateAsync(SoftwareVariantDto dto) + { + string userId = User.FindFirstValue(ClaimTypes.Sid); + if(userId is null) return null; + var model = new SoftwareVariant + { + Name = dto.Name, + Version = dto.Version, + Introduced = dto.Introduced, + ParentId = dto.ParentId, + SoftwareVersionId = dto.SoftwareVersionId, + MinimumMemory = dto.MinimumMemory, + RecommendedMemory = dto.RecommendedMemory, + RequiredStorage = dto.RequiredStorage, + PartNumber = dto.PartNumber, + SerialNumber = dto.SerialNumber, + ProductCode = dto.ProductCode, + CatalogueNumber = dto.CatalogueNumber, + DistributionMode = dto.DistributionMode + }; + + await context.SoftwareVariants.AddAsync(model); + await context.SaveChangesWithUserAsync(userId); + + return model.Id; + } + + [HttpDelete] + [Authorize(Roles = "Admin,UberAdmin")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task DeleteAsync(ulong id) + { + string userId = User.FindFirstValue(ClaimTypes.Sid); + if(userId is null) return; + SoftwareVariant item = await context.SoftwareVariants.FindAsync(id); + + if(item is null) return; + + context.SoftwareVariants.Remove(item); + + await context.SaveChangesWithUserAsync(userId); + } +} diff --git a/Marechai.Server/Controllers/SoftwareVersionsController.cs b/Marechai.Server/Controllers/SoftwareVersionsController.cs new file mode 100644 index 00000000..446e80d9 --- /dev/null +++ b/Marechai.Server/Controllers/SoftwareVersionsController.cs @@ -0,0 +1,154 @@ +/******************************************************************************* +// MARECHAI: Master repository of computing history artifacts information +// --------------------------------------------------------------------------- +// +// Author(s) : Natalia Portillo +// +// --[ License ] ----------------------------------------------------------- +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +// --------------------------------------------------------------------------- +// Copyright © 2003-2025 Natalia Portillo +*******************************************************************************/ + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Security.Claims; +using System.Threading.Tasks; +using Marechai.Data.Dtos; +using Marechai.Database.Models; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Localization; + +namespace Marechai.Server.Controllers; + +[Route("/software-versions")] +[ApiController] +public class SoftwareVersionsController(MarechaiContext context) : ControllerBase +{ + [HttpGet] + [AllowAnonymous] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task> GetAsync() => await context.SoftwareVersions + .OrderBy(b => b.Family.Name) + .ThenBy(b => b.Version) + .ThenBy(b => b.Introduced) + .Select(b => new SoftwareVersionDto + { + Id = b.Id, + Family = b.Family.Name, + Name = b.Name, + Codename = b.Codename, + Version = b.Version, + Introduced = b.Introduced, + Previous = b.Previous.Name, + License = b.License.Name, + FamilyId = b.FamilyId, + LicenseId = b.LicenseId, + PreviousId = b.PreviousId + }) + .ToListAsync(); + + [HttpGet] + [AllowAnonymous] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task GetAsync(ulong id) => await context.SoftwareVersions + .Where(b => b.Id == id) + .Select(b => new SoftwareVersionDto + { + Id = b.Id, + Family = b.Family.Name, + Name = b.Name, + Codename = b.Codename, + Version = b.Version, + Introduced = b.Introduced, + Previous = b.Previous.Name, + License = b.License.Name, + FamilyId = b.FamilyId, + LicenseId = b.LicenseId, + PreviousId = b.PreviousId + }) + .FirstOrDefaultAsync(); + + [HttpPost] + [Authorize(Roles = "Admin,UberAdmin")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task UpdateAsync(SoftwareVersionDto dto) + { + string userId = User.FindFirstValue(ClaimTypes.Sid); + if(userId is null) return; + SoftwareVersion model = await context.SoftwareVersions.FindAsync(dto.Id); + + if(model is null) return; + + model.Name = dto.Name; + model.Codename = dto.Codename; + model.Version = dto.Version; + model.Introduced = dto.Introduced; + model.FamilyId = dto.FamilyId; + model.LicenseId = dto.LicenseId; + model.PreviousId = dto.PreviousId; + await context.SaveChangesWithUserAsync(userId); + } + + [HttpPost] + [Authorize(Roles = "Admin,UberAdmin")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task CreateAsync(SoftwareVersionDto dto) + { + string userId = User.FindFirstValue(ClaimTypes.Sid); + if(userId is null) return null; + var model = new SoftwareVersion + { + Name = dto.Name, + Codename = dto.Codename, + Version = dto.Version, + Introduced = dto.Introduced, + FamilyId = dto.FamilyId, + LicenseId = dto.LicenseId, + PreviousId = dto.PreviousId + }; + + await context.SoftwareVersions.AddAsync(model); + await context.SaveChangesWithUserAsync(userId); + + return model.Id; + } + + [HttpDelete] + [Authorize(Roles = "Admin,UberAdmin")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task DeleteAsync(ulong id) + { + string userId = User.FindFirstValue(ClaimTypes.Sid); + if(userId is null) return; + SoftwareVersion item = await context.SoftwareVersions.FindAsync(id); + + if(item is null) return; + + context.SoftwareVersions.Remove(item); + + await context.SaveChangesWithUserAsync(userId); + } +} diff --git a/Marechai.Server/Controllers/SoundSynthsByMachineController.cs b/Marechai.Server/Controllers/SoundSynthsByMachineController.cs new file mode 100644 index 00000000..ed8652cb --- /dev/null +++ b/Marechai.Server/Controllers/SoundSynthsByMachineController.cs @@ -0,0 +1,99 @@ +/******************************************************************************* +// MARECHAI: Master repository of computing history artifacts information +// --------------------------------------------------------------------------- +// +// Author(s) : Natalia Portillo +// +// --[ License ] ----------------------------------------------------------- +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +// --------------------------------------------------------------------------- +// Copyright © 2003-2025 Natalia Portillo +*******************************************************************************/ + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Security.Claims; +using System.Threading.Tasks; +using Marechai.Data.Dtos; +using Marechai.Database.Models; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Localization; + +namespace Marechai.Server.Controllers; + +[Route("/sound-synths-by-machine")] +[ApiController] +public class SoundSynthsByMachineController(MarechaiContext context) : ControllerBase +{ + [HttpGet] + [AllowAnonymous] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task> GetByMachine(int machineId) => await context.SoundByMachine + .Where(g => g.MachineId == machineId) + .Select(g => new SoundSynthByMachineDto + { + Id = g.Id, + Name = g.SoundSynth.Name, + CompanyName = g.SoundSynth.Company.Name, + SoundSynthId = g.SoundSynthId, + MachineId = g.MachineId + }) + .OrderBy(g => g.CompanyName) + .ThenBy(g => g.Name) + .ToListAsync(); + + [HttpDelete] + [Authorize(Roles = "Admin,UberAdmin")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task DeleteAsync(long id) + { + string userId = User.FindFirstValue(ClaimTypes.Sid); + if(userId is null) return; + SoundByMachine item = await context.SoundByMachine.FindAsync(id); + + if(item is null) return; + + context.SoundByMachine.Remove(item); + + await context.SaveChangesWithUserAsync(userId); + } + + [HttpPost] + [Authorize(Roles = "Admin,UberAdmin")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task CreateAsync(int soundSynthId, int machineId) + { + string userId = User.FindFirstValue(ClaimTypes.Sid); + if(userId is null) return 0; + var item = new SoundByMachine + { + SoundSynthId = soundSynthId, + MachineId = machineId + }; + + await context.SoundByMachine.AddAsync(item); + await context.SaveChangesWithUserAsync(userId); + + return item.Id; + } +} diff --git a/Marechai.Server/Controllers/SoundSynthsController.cs b/Marechai.Server/Controllers/SoundSynthsController.cs new file mode 100644 index 00000000..8fdacbf9 --- /dev/null +++ b/Marechai.Server/Controllers/SoundSynthsController.cs @@ -0,0 +1,188 @@ +/******************************************************************************* +// MARECHAI: Master repository of computing history artifacts information +// --------------------------------------------------------------------------- +// +// Author(s) : Natalia Portillo +// +// --[ License ] ----------------------------------------------------------- +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +// --------------------------------------------------------------------------- +// Copyright © 2003-2025 Natalia Portillo +*******************************************************************************/ + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Security.Claims; +using System.Threading.Tasks; +using Marechai.Data.Dtos; +using Marechai.Database.Models; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Localization; + +namespace Marechai.Server.Controllers; + +[Route("/sound-synths")] +[ApiController] +public class SoundSynthsController(MarechaiContext context) : ControllerBase +{ + [HttpGet] + [AllowAnonymous] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task> GetAsync() => await context.SoundSynths.OrderBy(s => s.Company.Name) + .ThenBy(s => s.Name) + .ThenBy(s => s.ModelCode) + .Select(s => new SoundSynthDto + { + Id = s.Id, + Name = s.Name, + CompanyId = s.Company.Id, + CompanyName = s.Company.Name, + ModelCode = s.ModelCode, + Introduced = s.Introduced, + Voices = s.Voices, + Frequency = s.Frequency, + Depth = s.Depth, + SquareWave = s.SquareWave, + WhiteNoise = s.WhiteNoise, + Type = s.Type + }) + .ToListAsync(); + + [HttpGet] + [AllowAnonymous] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task> GetByMachineAsync(int machineId) => await context.SoundByMachine + .Where(s => s.MachineId == machineId) + .Select(s => s.SoundSynth) + .OrderBy(s => s.Company.Name) + .ThenBy(s => s.Name) + .ThenBy(s => s.ModelCode) + .Select(s => new SoundSynthDto + { + Id = s.Id, + Name = s.Name, + CompanyId = s.Company.Id, + CompanyName = s.Company.Name, + ModelCode = s.ModelCode, + Introduced = s.Introduced, + Voices = s.Voices, + Frequency = s.Frequency, + Depth = s.Depth, + SquareWave = s.SquareWave, + WhiteNoise = s.WhiteNoise, + Type = s.Type + }) + .ToListAsync(); + + [HttpGet] + [AllowAnonymous] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task GetAsync(int id) => await context.SoundSynths.Where(s => s.Id == id) + .Select(s => new SoundSynthDto + { + Id = s.Id, + Name = s.Name, + CompanyId = s.Company.Id, + CompanyName = s.Company.Name, + ModelCode = s.ModelCode, + Introduced = s.Introduced, + Voices = s.Voices, + Frequency = s.Frequency, + Depth = s.Depth, + SquareWave = s.SquareWave, + WhiteNoise = s.WhiteNoise, + Type = s.Type + }) + .FirstOrDefaultAsync(); + + [HttpPost] + [Authorize(Roles = "Admin,UberAdmin")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task UpdateAsync(SoundSynthDto dto) + { + string userId = User.FindFirstValue(ClaimTypes.Sid); + if(userId is null) return; + SoundSynth model = await context.SoundSynths.FindAsync(dto.Id); + + if(model is null) return; + + model.Depth = dto.Depth; + model.Frequency = dto.Frequency; + model.Introduced = dto.Introduced; + model.Name = dto.Name; + model.Type = dto.Type; + model.Voices = dto.Voices; + model.CompanyId = dto.CompanyId; + model.ModelCode = dto.ModelCode; + model.SquareWave = dto.SquareWave; + model.WhiteNoise = dto.WhiteNoise; + + await context.SaveChangesWithUserAsync(userId); + } + + [HttpPost] + [Authorize(Roles = "Admin,UberAdmin")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task CreateAsync(SoundSynthDto dto) + { + string userId = User.FindFirstValue(ClaimTypes.Sid); + if(userId is null) return 0; + var model = new SoundSynth + { + Depth = dto.Depth, + Frequency = dto.Frequency, + Introduced = dto.Introduced, + Name = dto.Name, + Type = dto.Type, + Voices = dto.Voices, + CompanyId = dto.CompanyId, + ModelCode = dto.ModelCode, + SquareWave = dto.SquareWave, + WhiteNoise = dto.WhiteNoise + }; + + await context.SoundSynths.AddAsync(model); + await context.SaveChangesWithUserAsync(userId); + + return model.Id; + } + + [HttpDelete] + [Authorize(Roles = "Admin,UberAdmin")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task DeleteAsync(int id) + { + string userId = User.FindFirstValue(ClaimTypes.Sid); + if(userId is null) return; + SoundSynth item = await context.SoundSynths.FindAsync(id); + + if(item is null) return; + + context.SoundSynths.Remove(item); + + await context.SaveChangesWithUserAsync(userId); + } +} diff --git a/Marechai.Server/Controllers/StorageByMachineController.cs b/Marechai.Server/Controllers/StorageByMachineController.cs new file mode 100644 index 00000000..1c47acfc --- /dev/null +++ b/Marechai.Server/Controllers/StorageByMachineController.cs @@ -0,0 +1,102 @@ +/******************************************************************************* +// MARECHAI: Master repository of computing history artifacts information +// --------------------------------------------------------------------------- +// +// Author(s) : Natalia Portillo +// +// --[ License ] ----------------------------------------------------------- +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +// --------------------------------------------------------------------------- +// Copyright © 2003-2025 Natalia Portillo +*******************************************************************************/ + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Security.Claims; +using System.Threading.Tasks; +using Marechai.Data.Dtos; +using Marechai.Database.Models; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Localization; + +namespace Marechai.Server.Controllers; + +[Route("/storage-by-machine")] +[ApiController] +public class StorageByMachineController(MarechaiContext context) : ControllerBase +{ + [HttpGet] + [AllowAnonymous] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task> GetByMachine(int machineId) => await context.StorageByMachine + .Where(s => s.MachineId == machineId) + .Select(s => new StorageByMachineDto + { + Id = s.Id, + Type = s.Type, + Interface = s.Interface, + Capacity = s.Capacity, + MachineId = s.MachineId + }) + .OrderBy(s => s.Type) + .ThenBy(s => s.Interface) + .ThenBy(s => s.Capacity) + .ToListAsync(); + + [HttpDelete] + [Authorize(Roles = "Admin,UberAdmin")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task DeleteAsync(long id) + { + string userId = User.FindFirstValue(ClaimTypes.Sid); + if(userId is null) return; + StorageByMachine item = await context.StorageByMachine.FindAsync(id); + + if(item is null) return; + + context.StorageByMachine.Remove(item); + + await context.SaveChangesWithUserAsync(userId); + } + + [HttpPost] + [Authorize(Roles = "Admin,UberAdmin")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task CreateAsync(int machineId, StorageType type, StorageInterface @interface, long? capacity) + { + string userId = User.FindFirstValue(ClaimTypes.Sid); + if(userId is null) return 0; + var item = new StorageByMachine + { + MachineId = machineId, + Type = type, + Interface = @interface, + Capacity = capacity + }; + + await context.StorageByMachine.AddAsync(item); + await context.SaveChangesWithUserAsync(userId); + + return item.Id; + } +}