From 036f11cdc0f99fd86f576f5335dae844391a0283 Mon Sep 17 00:00:00 2001 From: ivarlovlie Date: Fri, 9 Dec 2022 13:14:52 +0900 Subject: feat: Move /Data into /Models --- code/api/src/Data/Database/Api/ApiAccessToken.cs | 12 --- code/api/src/Data/Database/Base.cs | 22 ---- code/api/src/Data/Database/BaseWithOwner.cs | 36 ------- code/api/src/Data/Database/Customer/Customer.cs | 29 ------ .../src/Data/Database/Customer/CustomerContact.cs | 12 --- .../src/Data/Database/Customer/CustomerEvent.cs | 8 -- .../src/Data/Database/Customer/CustomerGroup.cs | 7 -- .../Database/Customer/CustomerGroupMembership.cs | 7 -- .../Data/Database/Internal/PasswordResetRequest.cs | 23 ----- code/api/src/Data/Database/Internal/User.cs | 37 ------- code/api/src/Data/Database/MainAppDatabase.cs | 105 ------------------- code/api/src/Data/Database/Project/Project.cs | 15 --- code/api/src/Data/Database/Project/ProjectLabel.cs | 8 -- .../api/src/Data/Database/Project/ProjectMember.cs | 8 -- code/api/src/Data/Database/Todo/Todo.cs | 17 ---- code/api/src/Data/Database/Todo/TodoCollection.cs | 11 -- .../Database/Todo/TodoCollectionAccessControl.cs | 12 --- code/api/src/Data/Database/Todo/TodoComment.cs | 8 -- code/api/src/Data/Database/Todo/TodoLabel.cs | 8 -- .../Enums/FulfillPasswordResetRequestResult.cs | 8 -- .../src/Data/Enums/PasswordResetRequestStatus.cs | 6 -- code/api/src/Data/Enums/ProjectRole.cs | 9 -- code/api/src/Data/Enums/TodoClosingStatement.cs | 13 --- code/api/src/Data/Enums/TodoVisibility.cs | 10 -- code/api/src/Data/Models/ApiSpecDocument.cs | 9 -- code/api/src/Data/Models/AppConfiguration.cs | 113 --------------------- code/api/src/Data/Models/AppPath.cs | 23 ----- code/api/src/Data/Models/KnownProblemModel.cs | 26 ----- code/api/src/Data/Models/LoggedInUserModel.cs | 8 -- code/api/src/Data/Models/RequestTimeZoneInfo.cs | 8 -- code/api/src/Data/Static/AppClaims.cs | 8 -- code/api/src/Data/Static/AppConstants.cs | 12 --- code/api/src/Data/Static/AppCookies.cs | 7 -- code/api/src/Data/Static/AppDateTime.cs | 16 --- .../api/src/Data/Static/AppEnvironmentVariables.cs | 21 ---- code/api/src/Data/Static/AppHeaders.cs | 7 -- code/api/src/Data/Static/AppPaths.cs | 17 ---- code/api/src/Data/Static/JsonSettings.cs | 11 -- .../Internal/Root/GetApplicationVersionRoute.cs | 20 ---- code/api/src/Endpoints/Internal/Root/LogRoute.cs | 16 --- code/api/src/Models/Database/Api/ApiAccessToken.cs | 12 +++ code/api/src/Models/Database/Base.cs | 22 ++++ code/api/src/Models/Database/BaseWithOwner.cs | 36 +++++++ code/api/src/Models/Database/Customer/Customer.cs | 29 ++++++ .../Models/Database/Customer/CustomerContact.cs | 12 +++ .../src/Models/Database/Customer/CustomerEvent.cs | 8 ++ .../src/Models/Database/Customer/CustomerGroup.cs | 7 ++ .../Database/Customer/CustomerGroupMembership.cs | 7 ++ .../Database/Internal/PasswordResetRequest.cs | 23 +++++ code/api/src/Models/Database/Internal/User.cs | 37 +++++++ code/api/src/Models/Database/MainAppDatabase.cs | 105 +++++++++++++++++++ code/api/src/Models/Database/Project/Project.cs | 15 +++ .../src/Models/Database/Project/ProjectLabel.cs | 8 ++ .../src/Models/Database/Project/ProjectMember.cs | 8 ++ code/api/src/Models/Database/Todo/Todo.cs | 17 ++++ .../api/src/Models/Database/Todo/TodoCollection.cs | 11 ++ .../Database/Todo/TodoCollectionAccessControl.cs | 12 +++ code/api/src/Models/Database/Todo/TodoComment.cs | 8 ++ code/api/src/Models/Database/Todo/TodoLabel.cs | 8 ++ .../Enums/FulfillPasswordResetRequestResult.cs | 8 ++ .../src/Models/Enums/PasswordResetRequestStatus.cs | 6 ++ code/api/src/Models/Enums/ProjectRole.cs | 9 ++ code/api/src/Models/Enums/TodoClosingStatement.cs | 13 +++ code/api/src/Models/Enums/TodoVisibility.cs | 10 ++ code/api/src/Models/Misc/ApiSpecDocument.cs | 9 ++ code/api/src/Models/Misc/AppConfiguration.cs | 113 +++++++++++++++++++++ code/api/src/Models/Misc/AppPath.cs | 23 +++++ code/api/src/Models/Misc/KnownProblemModel.cs | 26 +++++ code/api/src/Models/Misc/LoggedInUserModel.cs | 8 ++ code/api/src/Models/Misc/RequestTimeZoneInfo.cs | 8 ++ code/api/src/Models/Static/AppClaims.cs | 8 ++ code/api/src/Models/Static/AppConstants.cs | 12 +++ code/api/src/Models/Static/AppCookies.cs | 7 ++ code/api/src/Models/Static/AppDateTime.cs | 16 +++ .../src/Models/Static/AppEnvironmentVariables.cs | 21 ++++ code/api/src/Models/Static/AppHeaders.cs | 7 ++ code/api/src/Models/Static/AppPaths.cs | 17 ++++ code/api/src/Models/Static/JsonSettings.cs | 11 ++ code/api/src/Program.cs | 6 +- code/api/src/Utilities/Validators.cs | 12 --- 80 files changed, 720 insertions(+), 768 deletions(-) delete mode 100644 code/api/src/Data/Database/Api/ApiAccessToken.cs delete mode 100644 code/api/src/Data/Database/Base.cs delete mode 100644 code/api/src/Data/Database/BaseWithOwner.cs delete mode 100644 code/api/src/Data/Database/Customer/Customer.cs delete mode 100644 code/api/src/Data/Database/Customer/CustomerContact.cs delete mode 100644 code/api/src/Data/Database/Customer/CustomerEvent.cs delete mode 100644 code/api/src/Data/Database/Customer/CustomerGroup.cs delete mode 100644 code/api/src/Data/Database/Customer/CustomerGroupMembership.cs delete mode 100644 code/api/src/Data/Database/Internal/PasswordResetRequest.cs delete mode 100644 code/api/src/Data/Database/Internal/User.cs delete mode 100644 code/api/src/Data/Database/MainAppDatabase.cs delete mode 100644 code/api/src/Data/Database/Project/Project.cs delete mode 100644 code/api/src/Data/Database/Project/ProjectLabel.cs delete mode 100644 code/api/src/Data/Database/Project/ProjectMember.cs delete mode 100644 code/api/src/Data/Database/Todo/Todo.cs delete mode 100644 code/api/src/Data/Database/Todo/TodoCollection.cs delete mode 100644 code/api/src/Data/Database/Todo/TodoCollectionAccessControl.cs delete mode 100644 code/api/src/Data/Database/Todo/TodoComment.cs delete mode 100644 code/api/src/Data/Database/Todo/TodoLabel.cs delete mode 100644 code/api/src/Data/Enums/FulfillPasswordResetRequestResult.cs delete mode 100644 code/api/src/Data/Enums/PasswordResetRequestStatus.cs delete mode 100644 code/api/src/Data/Enums/ProjectRole.cs delete mode 100644 code/api/src/Data/Enums/TodoClosingStatement.cs delete mode 100644 code/api/src/Data/Enums/TodoVisibility.cs delete mode 100644 code/api/src/Data/Models/ApiSpecDocument.cs delete mode 100644 code/api/src/Data/Models/AppConfiguration.cs delete mode 100644 code/api/src/Data/Models/AppPath.cs delete mode 100644 code/api/src/Data/Models/KnownProblemModel.cs delete mode 100644 code/api/src/Data/Models/LoggedInUserModel.cs delete mode 100644 code/api/src/Data/Models/RequestTimeZoneInfo.cs delete mode 100644 code/api/src/Data/Static/AppClaims.cs delete mode 100644 code/api/src/Data/Static/AppConstants.cs delete mode 100644 code/api/src/Data/Static/AppCookies.cs delete mode 100644 code/api/src/Data/Static/AppDateTime.cs delete mode 100644 code/api/src/Data/Static/AppEnvironmentVariables.cs delete mode 100644 code/api/src/Data/Static/AppHeaders.cs delete mode 100644 code/api/src/Data/Static/AppPaths.cs delete mode 100644 code/api/src/Data/Static/JsonSettings.cs delete mode 100644 code/api/src/Endpoints/Internal/Root/GetApplicationVersionRoute.cs delete mode 100644 code/api/src/Endpoints/Internal/Root/LogRoute.cs create mode 100644 code/api/src/Models/Database/Api/ApiAccessToken.cs create mode 100644 code/api/src/Models/Database/Base.cs create mode 100644 code/api/src/Models/Database/BaseWithOwner.cs create mode 100644 code/api/src/Models/Database/Customer/Customer.cs create mode 100644 code/api/src/Models/Database/Customer/CustomerContact.cs create mode 100644 code/api/src/Models/Database/Customer/CustomerEvent.cs create mode 100644 code/api/src/Models/Database/Customer/CustomerGroup.cs create mode 100644 code/api/src/Models/Database/Customer/CustomerGroupMembership.cs create mode 100644 code/api/src/Models/Database/Internal/PasswordResetRequest.cs create mode 100644 code/api/src/Models/Database/Internal/User.cs create mode 100644 code/api/src/Models/Database/MainAppDatabase.cs create mode 100644 code/api/src/Models/Database/Project/Project.cs create mode 100644 code/api/src/Models/Database/Project/ProjectLabel.cs create mode 100644 code/api/src/Models/Database/Project/ProjectMember.cs create mode 100644 code/api/src/Models/Database/Todo/Todo.cs create mode 100644 code/api/src/Models/Database/Todo/TodoCollection.cs create mode 100644 code/api/src/Models/Database/Todo/TodoCollectionAccessControl.cs create mode 100644 code/api/src/Models/Database/Todo/TodoComment.cs create mode 100644 code/api/src/Models/Database/Todo/TodoLabel.cs create mode 100644 code/api/src/Models/Enums/FulfillPasswordResetRequestResult.cs create mode 100644 code/api/src/Models/Enums/PasswordResetRequestStatus.cs create mode 100644 code/api/src/Models/Enums/ProjectRole.cs create mode 100644 code/api/src/Models/Enums/TodoClosingStatement.cs create mode 100644 code/api/src/Models/Enums/TodoVisibility.cs create mode 100644 code/api/src/Models/Misc/ApiSpecDocument.cs create mode 100644 code/api/src/Models/Misc/AppConfiguration.cs create mode 100644 code/api/src/Models/Misc/AppPath.cs create mode 100644 code/api/src/Models/Misc/KnownProblemModel.cs create mode 100644 code/api/src/Models/Misc/LoggedInUserModel.cs create mode 100644 code/api/src/Models/Misc/RequestTimeZoneInfo.cs create mode 100644 code/api/src/Models/Static/AppClaims.cs create mode 100644 code/api/src/Models/Static/AppConstants.cs create mode 100644 code/api/src/Models/Static/AppCookies.cs create mode 100644 code/api/src/Models/Static/AppDateTime.cs create mode 100644 code/api/src/Models/Static/AppEnvironmentVariables.cs create mode 100644 code/api/src/Models/Static/AppHeaders.cs create mode 100644 code/api/src/Models/Static/AppPaths.cs create mode 100644 code/api/src/Models/Static/JsonSettings.cs delete mode 100644 code/api/src/Utilities/Validators.cs (limited to 'code/api') diff --git a/code/api/src/Data/Database/Api/ApiAccessToken.cs b/code/api/src/Data/Database/Api/ApiAccessToken.cs deleted file mode 100644 index 9359fc4..0000000 --- a/code/api/src/Data/Database/Api/ApiAccessToken.cs +++ /dev/null @@ -1,12 +0,0 @@ -namespace IOL.GreatOffice.Api.Data.Database; - -public class ApiAccessToken : Base -{ - public User User { get; set; } - public DateTime ExpiryDate { get; set; } - public bool AllowRead { get; set; } - public bool AllowCreate { get; set; } - public bool AllowUpdate { get; set; } - public bool AllowDelete { get; set; } - public bool HasExpired => ExpiryDate < AppDateTime.UtcNow; -} \ No newline at end of file diff --git a/code/api/src/Data/Database/Base.cs b/code/api/src/Data/Database/Base.cs deleted file mode 100644 index 900b923..0000000 --- a/code/api/src/Data/Database/Base.cs +++ /dev/null @@ -1,22 +0,0 @@ -namespace IOL.GreatOffice.Api.Data.Database; - -public class Base -{ - protected Base() { - Id = Guid.NewGuid(); - CreatedAt = AppDateTime.UtcNow; - } - - public Guid Id { get; init; } - public DateTime CreatedAt { get; init; } - public DateTime? ModifiedAt { get; private set; } - public DateTime? DeletedAt { get; private set; } - public bool Deleted { get; private set; } - - public void SetModified() => ModifiedAt = AppDateTime.UtcNow; - - public void SetDeleted() { - Deleted = true; - DeletedAt = AppDateTime.UtcNow; - } -} \ No newline at end of file diff --git a/code/api/src/Data/Database/BaseWithOwner.cs b/code/api/src/Data/Database/BaseWithOwner.cs deleted file mode 100644 index ad9b33a..0000000 --- a/code/api/src/Data/Database/BaseWithOwner.cs +++ /dev/null @@ -1,36 +0,0 @@ -namespace IOL.GreatOffice.Api.Data.Database; - -/// -/// Base class for all entities with ownership. -/// -public class BaseWithOwner : Base -{ - protected BaseWithOwner() { } - - protected BaseWithOwner(LoggedInUserModel loggedInUser) { - CreatedBy = loggedInUser.Id; - } - - public Guid? UserId { get; private set; } - public Guid? TenantId { get; private set; } - public Guid? ModifiedBy { get; private set; } - public Guid? CreatedBy { get; private set; } - public Guid? DeletedBy { get; private set; } - public User OwningUser { get; set; } - public Tenant OwningTenant { get; set; } - - public void SetDeleted(Guid userId) { - DeletedBy = userId; - SetDeleted(); - } - - public void SetModified(Guid userId) { - ModifiedBy = userId; - SetModified(); - } - - public void SetOwnerIds(Guid userId = default, Guid tenantId = default) { - if (tenantId != default) TenantId = tenantId; - if (userId != default) UserId = userId; - } -} \ No newline at end of file diff --git a/code/api/src/Data/Database/Customer/Customer.cs b/code/api/src/Data/Database/Customer/Customer.cs deleted file mode 100644 index 8e153c6..0000000 --- a/code/api/src/Data/Database/Customer/Customer.cs +++ /dev/null @@ -1,29 +0,0 @@ -namespace IOL.GreatOffice.Api.Data.Database; - -public class Customer : BaseWithOwner -{ - public Customer() { } - public Customer(LoggedInUserModel loggedInUserModel) : base(loggedInUserModel) { } - - public string CustomerNumber { get; set; } - public string Name { get; set; } - public string Description { get; set; } - public string Address1 { get; set; } - public string Address2 { get; set; } - public string PostalCode { get; set; } - public string PostalCity { get; set; } - public string Country { get; set; } - public string Phone { get; set; } - public string Email { get; set; } - public string VATNumber { get; set; } - public string ORGNumber { get; set; } - public string DefaultReference { get; set; } - public string Website { get; set; } - public string Currency { get; set; } - public Guid? OwnerId { get; set; } - public User Owner { get; set; } - public ICollection Groups { get; set; } - public ICollection Contacts { get; set; } - public ICollection Events { get; set; } - public ICollection Projects { get; set; } -} \ No newline at end of file diff --git a/code/api/src/Data/Database/Customer/CustomerContact.cs b/code/api/src/Data/Database/Customer/CustomerContact.cs deleted file mode 100644 index f5a951d..0000000 --- a/code/api/src/Data/Database/Customer/CustomerContact.cs +++ /dev/null @@ -1,12 +0,0 @@ -namespace IOL.GreatOffice.Api.Data.Database; - -public class CustomerContact : BaseWithOwner -{ - public Customer Customer { get; set; } - public string FirstName { get; set; } - public string LastName { get; set; } - public string Email { get; set; } - public string Phone { get; set; } - public string WorkTitle { get; set; } - public string Note { get; set; } -} diff --git a/code/api/src/Data/Database/Customer/CustomerEvent.cs b/code/api/src/Data/Database/Customer/CustomerEvent.cs deleted file mode 100644 index a87da4c..0000000 --- a/code/api/src/Data/Database/Customer/CustomerEvent.cs +++ /dev/null @@ -1,8 +0,0 @@ -namespace IOL.GreatOffice.Api.Data.Database; - -public class CustomerEvent : BaseWithOwner -{ - public Customer Customer { get; set; } - public string Title { get; set; } - public string Note { get; set; } -} diff --git a/code/api/src/Data/Database/Customer/CustomerGroup.cs b/code/api/src/Data/Database/Customer/CustomerGroup.cs deleted file mode 100644 index 9438f3c..0000000 --- a/code/api/src/Data/Database/Customer/CustomerGroup.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace IOL.GreatOffice.Api.Data.Database; - -public class CustomerGroup : BaseWithOwner -{ - public string Name { get; set; } - public ICollection Customers { get; set; } -} \ No newline at end of file diff --git a/code/api/src/Data/Database/Customer/CustomerGroupMembership.cs b/code/api/src/Data/Database/Customer/CustomerGroupMembership.cs deleted file mode 100644 index ec0d4af..0000000 --- a/code/api/src/Data/Database/Customer/CustomerGroupMembership.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace IOL.GreatOffice.Api.Data.Database; - -public class CustomerGroupMembership : Base -{ - public Customer Customer { get; set; } - public CustomerGroup Group { get; set; } -} \ No newline at end of file diff --git a/code/api/src/Data/Database/Internal/PasswordResetRequest.cs b/code/api/src/Data/Database/Internal/PasswordResetRequest.cs deleted file mode 100644 index ee73fd2..0000000 --- a/code/api/src/Data/Database/Internal/PasswordResetRequest.cs +++ /dev/null @@ -1,23 +0,0 @@ -namespace IOL.GreatOffice.Api.Data.Database; - -public class PasswordResetRequest -{ - public PasswordResetRequest() { } - - public PasswordResetRequest(User user) { - CreatedAt = AppDateTime.UtcNow; - Id = Guid.NewGuid(); - User = user; - } - - public Guid Id { get; set; } - public Guid UserId { get; set; } - public User User { get; set; } - public DateTime CreatedAt { get; set; } - - [NotMapped] - public DateTime ExpirationDate => CreatedAt.AddMinutes(15); - - [NotMapped] - public bool IsExpired => DateTime.Compare(ExpirationDate, AppDateTime.UtcNow) < 0; -} diff --git a/code/api/src/Data/Database/Internal/User.cs b/code/api/src/Data/Database/Internal/User.cs deleted file mode 100644 index 9db5d35..0000000 --- a/code/api/src/Data/Database/Internal/User.cs +++ /dev/null @@ -1,37 +0,0 @@ -namespace IOL.GreatOffice.Api.Data.Database; - -public class User : Base -{ - public User() { } - - public User(string username) { - Username = username; - } - - public string FirstName { get; set; } - public string LastName { get; set; } - public string Email { get; set; } - public string Username { get; set; } - public string Password { get; set; } - public ICollection Tenants { get; set; } - - public string DisplayName() { - if (FirstName.HasValue() && LastName.HasValue()) return FirstName + " " + LastName; - return FirstName.HasValue() ? FirstName : Email; - } - - public void HashAndSetPassword(string password) { - Password = PasswordHelper.HashPassword(password); - } - - public bool VerifyPassword(string password) { - return PasswordHelper.Verify(password, Password); - } - - public IEnumerable DefaultClaims() { - return new Claim[] { - new(AppClaims.USER_ID, Id.ToString()), - new(AppClaims.NAME, Username), - }; - } -} \ No newline at end of file diff --git a/code/api/src/Data/Database/MainAppDatabase.cs b/code/api/src/Data/Database/MainAppDatabase.cs deleted file mode 100644 index eaf7781..0000000 --- a/code/api/src/Data/Database/MainAppDatabase.cs +++ /dev/null @@ -1,105 +0,0 @@ -using Microsoft.AspNetCore.DataProtection.EntityFrameworkCore; - -namespace IOL.GreatOffice.Api.Data.Database; - -public class MainAppDatabase : DbContext, IDataProtectionKeyContext -{ - public MainAppDatabase(DbContextOptions options) : base(options) { } - public DbSet Users { get; set; } - public DbSet PasswordResetRequests { get; set; } - public DbSet AccessTokens { get; set; } - public DbSet Tenants { get; set; } - public DbSet DataProtectionKeys { get; set; } - public DbSet Projects { get; set; } - public DbSet ProjectLabels { get; set; } - public DbSet Customers { get; set; } - public DbSet CustomersContacts { get; set; } - public DbSet CustomerEvents { get; set; } - public DbSet CustomerGroups { get; set; } - public DbSet TodoLabels { get; set; } - public DbSet TodoProjectAccessControls { get; set; } - public DbSet TodoProjects { get; set; } - public DbSet TodoComments { get; set; } - public DbSet Todos { get; set; } - - protected override void OnModelCreating(ModelBuilder modelBuilder) { - modelBuilder.Entity(e => { - e.HasMany(n => n.Tenants); - e.ToTable("users"); - }); - modelBuilder.Entity(e => { - e.HasOne(c => c.User); - e.ToTable("password_reset_requests"); - }); - modelBuilder.Entity(e => { - e.HasOne(n => n.User); - e.ToTable("api_access_tokens"); - }); - modelBuilder.Entity(e => { - e.HasMany(n => n.Users); - e.ToTable("tenants"); - }); - modelBuilder.Entity(e => { - e.HasMany(n => n.Members); - e.HasMany(n => n.Customers); - e.ToTable("projects"); - }); - modelBuilder.Entity(e => { - e.HasOne(n => n.Project); - e.HasOne(n => n.User); - e.ToTable("project_members"); - }); - modelBuilder.Entity(e => { - e.HasOne(n => n.Project); - e.ToTable("project_labels"); - }); - modelBuilder.Entity(e => { - e.HasOne(n => n.Owner); - e.HasMany(n => n.Events); - e.HasMany(n => n.Contacts); - e.HasMany(n => n.Groups); - e.HasMany(n => n.Projects); - e.ToTable("customers"); - }); - modelBuilder.Entity(e => { - e.HasOne(n => n.Customer); - e.ToTable("customer_contacts"); - }); - modelBuilder.Entity(e => { - e.HasOne(n => n.Customer); - e.ToTable("customer_events"); - }); - modelBuilder.Entity(e => { - e.HasMany(n => n.Customers); - e.ToTable("customer_groups"); - }); - modelBuilder.Entity(e => { - e.HasOne(n => n.Collection); - e.HasOne(n => n.AssignedTo); - e.HasOne(n => n.ClosedBy); - e.HasMany(n => n.Labels); - e.HasMany(n => n.Comments); - e.ToTable("todos"); - }); - modelBuilder.Entity(e => { - e.HasOne(n => n.Project); - e.HasMany(n => n.AccessControls); - e.ToTable("todo_collections"); - }); - modelBuilder.Entity(e => { - e.HasOne(n => n.Todo); - e.ToTable("todo_comments"); - }); - modelBuilder.Entity(e => { - e.HasOne(n => n.Todo); - e.ToTable("todo_labels"); - }); - modelBuilder.Entity(e => { - e.HasOne(n => n.User); - e.HasOne(n => n.Collection); - e.ToTable("todo_collection_access_controls"); - }); - - base.OnModelCreating(modelBuilder); - } -} \ No newline at end of file diff --git a/code/api/src/Data/Database/Project/Project.cs b/code/api/src/Data/Database/Project/Project.cs deleted file mode 100644 index de9e2cb..0000000 --- a/code/api/src/Data/Database/Project/Project.cs +++ /dev/null @@ -1,15 +0,0 @@ -namespace IOL.GreatOffice.Api.Data.Database; - -public class Project : BaseWithOwner -{ - public Project() { } - - public Project(LoggedInUserModel loggedInUserModel) : base(loggedInUserModel) { } - public string Name { get; set; } - public string Description { get; set; } - public DateTime? Start { get; set; } - public DateTime? Stop { get; set; } - public ICollection Customers { get; set; } - public ICollection Members { get; set; } - public ICollection Labels { get; set; } -} \ No newline at end of file diff --git a/code/api/src/Data/Database/Project/ProjectLabel.cs b/code/api/src/Data/Database/Project/ProjectLabel.cs deleted file mode 100644 index 0e1dc5d..0000000 --- a/code/api/src/Data/Database/Project/ProjectLabel.cs +++ /dev/null @@ -1,8 +0,0 @@ -namespace IOL.GreatOffice.Api.Data.Database; - -public class ProjectLabel : BaseWithOwner -{ - public string Value { get; set; } - public string Color { get; set; } - public Project Project { get; set; } -} diff --git a/code/api/src/Data/Database/Project/ProjectMember.cs b/code/api/src/Data/Database/Project/ProjectMember.cs deleted file mode 100644 index a5e0682..0000000 --- a/code/api/src/Data/Database/Project/ProjectMember.cs +++ /dev/null @@ -1,8 +0,0 @@ -namespace IOL.GreatOffice.Api.Data.Database; - -public class ProjectMember : Base -{ - public Project Project { get; set; } - public User User { get; set; } - public ProjectRole Role { get; set; } -} \ No newline at end of file diff --git a/code/api/src/Data/Database/Todo/Todo.cs b/code/api/src/Data/Database/Todo/Todo.cs deleted file mode 100644 index 2d7f109..0000000 --- a/code/api/src/Data/Database/Todo/Todo.cs +++ /dev/null @@ -1,17 +0,0 @@ -namespace IOL.GreatOffice.Api.Data.Database; - -public class Todo : BaseWithOwner -{ - public string PublicId { get; set; } - public Guid? AssignedToId { get; set; } - public Guid? ClosedById { get; set; } - public Guid CollectionId { get; set; } - public DateTime? ClosedAt { get; set; } - public string Title { get; set; } - public string Description { get; set; } - public ICollection Labels { get; set; } - public ICollection Comments { get; set; } - public User AssignedTo { get; set; } - public User ClosedBy { get; set; } - public TodoCollection Collection { get; set; } -} \ No newline at end of file diff --git a/code/api/src/Data/Database/Todo/TodoCollection.cs b/code/api/src/Data/Database/Todo/TodoCollection.cs deleted file mode 100644 index 470e5e7..0000000 --- a/code/api/src/Data/Database/Todo/TodoCollection.cs +++ /dev/null @@ -1,11 +0,0 @@ -namespace IOL.GreatOffice.Api.Data.Database; - -public class TodoCollection : BaseWithOwner -{ - public string Name { get; set; } - public string Description { get; set; } - public TodoVisibility Visibility { get; set; } - public Guid? ProjectId { get; set; } - public Project Project { get; set; } - public ICollection AccessControls { get; set; } -} \ No newline at end of file diff --git a/code/api/src/Data/Database/Todo/TodoCollectionAccessControl.cs b/code/api/src/Data/Database/Todo/TodoCollectionAccessControl.cs deleted file mode 100644 index 1676c06..0000000 --- a/code/api/src/Data/Database/Todo/TodoCollectionAccessControl.cs +++ /dev/null @@ -1,12 +0,0 @@ -namespace IOL.GreatOffice.Api.Data.Database; - -public class TodoCollectionAccessControl : Base -{ - public TodoCollection Collection { get; set; } - public User User { get; set; } - public Guid? UserId { get; set; } - public bool CanBrowse { get; set; } - public bool CanSubmit { get; set; } - public bool CanComment { get; set; } - public bool CanEdit { get; set; } -} \ No newline at end of file diff --git a/code/api/src/Data/Database/Todo/TodoComment.cs b/code/api/src/Data/Database/Todo/TodoComment.cs deleted file mode 100644 index 32ac3a3..0000000 --- a/code/api/src/Data/Database/Todo/TodoComment.cs +++ /dev/null @@ -1,8 +0,0 @@ -namespace IOL.GreatOffice.Api.Data.Database; - -public class TodoComment : BaseWithOwner -{ - public string Value { get; set; } - public Todo Todo { get; set; } - public TodoClosingStatement? ClosingStatement { get; set; } -} \ No newline at end of file diff --git a/code/api/src/Data/Database/Todo/TodoLabel.cs b/code/api/src/Data/Database/Todo/TodoLabel.cs deleted file mode 100644 index 7753ade..0000000 --- a/code/api/src/Data/Database/Todo/TodoLabel.cs +++ /dev/null @@ -1,8 +0,0 @@ -namespace IOL.GreatOffice.Api.Data.Database; - -public class TodoLabel : BaseWithOwner -{ - public string Name { get; set; } - public string Color { get; set; } - public Todo Todo { get; set; } -} diff --git a/code/api/src/Data/Enums/FulfillPasswordResetRequestResult.cs b/code/api/src/Data/Enums/FulfillPasswordResetRequestResult.cs deleted file mode 100644 index 2a84c48..0000000 --- a/code/api/src/Data/Enums/FulfillPasswordResetRequestResult.cs +++ /dev/null @@ -1,8 +0,0 @@ -namespace IOL.GreatOffice.Api.Data.Enums; - -public enum FulfillPasswordResetRequestResult -{ - REQUEST_NOT_FOUND, - USER_NOT_FOUND, - FULFILLED -} \ No newline at end of file diff --git a/code/api/src/Data/Enums/PasswordResetRequestStatus.cs b/code/api/src/Data/Enums/PasswordResetRequestStatus.cs deleted file mode 100644 index 5629e6f..0000000 --- a/code/api/src/Data/Enums/PasswordResetRequestStatus.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace IOL.GreatOffice.Api.Data.Enums; - -public enum PasswordResetRequestStatus -{ - -} \ No newline at end of file diff --git a/code/api/src/Data/Enums/ProjectRole.cs b/code/api/src/Data/Enums/ProjectRole.cs deleted file mode 100644 index c4a3f29..0000000 --- a/code/api/src/Data/Enums/ProjectRole.cs +++ /dev/null @@ -1,9 +0,0 @@ -namespace IOL.GreatOffice.Api.Data.Enums; - -public enum ProjectRole -{ - EXTERNAL, - RESOURCE, - LEADER, - OWNER -} \ No newline at end of file diff --git a/code/api/src/Data/Enums/TodoClosingStatement.cs b/code/api/src/Data/Enums/TodoClosingStatement.cs deleted file mode 100644 index d838031..0000000 --- a/code/api/src/Data/Enums/TodoClosingStatement.cs +++ /dev/null @@ -1,13 +0,0 @@ -namespace IOL.GreatOffice.Api.Data.Enums; - -public enum TodoClosingStatement -{ - REPORTED, - RESOLVED, - FIXED, - IMPLEMENTED, - WONT_FIX, - BY_DESIGN, - INVALID, - DUPLICATE -} \ No newline at end of file diff --git a/code/api/src/Data/Enums/TodoVisibility.cs b/code/api/src/Data/Enums/TodoVisibility.cs deleted file mode 100644 index 2c8fa83..0000000 --- a/code/api/src/Data/Enums/TodoVisibility.cs +++ /dev/null @@ -1,10 +0,0 @@ - -namespace IOL.GreatOffice.Api.Data.Enums; - -public enum TodoVisibility -{ - PRIVATE = 0, - UNLISTED = 1, - INTERNAL = 2, - PUBLIC = 3, -} \ No newline at end of file diff --git a/code/api/src/Data/Models/ApiSpecDocument.cs b/code/api/src/Data/Models/ApiSpecDocument.cs deleted file mode 100644 index 1c7d936..0000000 --- a/code/api/src/Data/Models/ApiSpecDocument.cs +++ /dev/null @@ -1,9 +0,0 @@ -namespace IOL.GreatOffice.Api.Data.Models; - -public class ApiSpecDocument -{ - public string VersionName { get; set; } - public string SwaggerPath { get; set; } - public ApiVersion Version { get; set; } - public OpenApiInfo OpenApiInfo { get; set; } -} diff --git a/code/api/src/Data/Models/AppConfiguration.cs b/code/api/src/Data/Models/AppConfiguration.cs deleted file mode 100644 index 2a9afc2..0000000 --- a/code/api/src/Data/Models/AppConfiguration.cs +++ /dev/null @@ -1,113 +0,0 @@ -using System.Security.Cryptography.X509Certificates; - -namespace IOL.GreatOffice.Api.Data.Models; - -public class AppConfiguration -{ - /// - /// An reachable ip address or url that points to a postgres database. - /// - public string DB_HOST { get; set; } - - /// - /// The port number to use with DB_HOST to point to the postgres database. - /// - public string DB_PORT { get; set; } - - /// - /// The database user to authenticate against postgres with. - /// - public string DB_USER { get; set; } - - /// - /// The password for the database user to authenticate against postgres with. - /// - public string DB_PASSWORD { get; set; } - - /// - /// The name of the main app database. - /// - public string DB_NAME { get; set; } - - /// - /// An reachable ip address or url that points to a postgres(quartz) database. - /// - public string QUARTZ_DB_HOST { get; set; } - - /// - /// The port number to use with QUARTZ_DB_HOST to point to the postgres(quartz) database. - /// - public string QUARTZ_DB_PORT { get; set; } - - /// - /// The database user to authenticate against postgres(quartz) with. - /// - public string QUARTZ_DB_USER { get; set; } - - /// - /// The password for the database user to authenticate against postgres(quartz) with. - /// - public string QUARTZ_DB_PASSWORD { get; set; } - - /// - /// The name of the quartz database. - /// - public string QUARTZ_DB_NAME { get; set; } - - /// - /// API key to use when pushing logs to SEQ - /// - public string SEQ_API_KEY { get; set; } - - /// - /// Url pointing to the seq instance that processes server logs - /// - public string SEQ_API_URL { get; set; } - - /// - /// A token used when sending email via Postmakr - /// - public string POSTMARK_TOKEN { get; set; } - - /// - /// The address to send emails from, needs to be setup as a sender in postmark - /// - public string EMAIL_FROM_ADDRESS { get; set; } - - /// - /// The absolute url to the frontend app - /// - public string CANONICAL_FRONTEND_URL { get; set; } - - /// - /// A random string used to encrypt/decrypt for general purposes - /// - public string APP_AES_KEY { get; set; } - - /// - /// A base64 string containing a passwordless pfx cert - /// - public string APP_CERT { get; set; } - - public X509Certificate2 CERT1() => new(Convert.FromBase64String(APP_CERT)); - - public object GetPublicVersion() { - return new { - DB_HOST, - DB_PORT, - DB_USER, - DB_PASSWORD = DB_PASSWORD.Obfuscate() ?? "", - QUARTZ_DB_HOST, - QUARTZ_DB_PORT, - QUARTZ_DB_USER, - QUARTZ_DB_PASSWORD = QUARTZ_DB_PASSWORD.Obfuscate() ?? "", - SEQ_API_KEY = SEQ_API_KEY.Obfuscate() ?? "", - SEQ_API_URL, - POSTMARK_TOKEN = POSTMARK_TOKEN.Obfuscate() ?? "", - EMAIL_FROM_ADDRESS, - APP_AES_KEY = APP_AES_KEY.Obfuscate() ?? "", - CERT1 = CERT1().PublicKey.Oid.FriendlyName, - CANONICAL_FRONTEND_URL - }; - } -} \ No newline at end of file diff --git a/code/api/src/Data/Models/AppPath.cs b/code/api/src/Data/Models/AppPath.cs deleted file mode 100644 index e47e48c..0000000 --- a/code/api/src/Data/Models/AppPath.cs +++ /dev/null @@ -1,23 +0,0 @@ -namespace IOL.GreatOffice.Api.Data.Models; - -public sealed record AppPath -{ - public string HostPath { get; init; } - public string WebPath { get; init; } - - public string GetHostPathForFilename(string filename, string fallback = "") { - if (filename.IsNullOrWhiteSpace()) { - return fallback; - } - - return Path.Combine(HostPath, filename); - } - - public string GetWebPathForFilename(string filename, string fallback = "") { - if (filename.IsNullOrWhiteSpace()) { - return fallback; - } - - return Path.Combine(WebPath, filename); - } -} diff --git a/code/api/src/Data/Models/KnownProblemModel.cs b/code/api/src/Data/Models/KnownProblemModel.cs deleted file mode 100644 index 9acc85c..0000000 --- a/code/api/src/Data/Models/KnownProblemModel.cs +++ /dev/null @@ -1,26 +0,0 @@ -namespace IOL.GreatOffice.Api.Data.Models; - -public class KnownProblemModel -{ - public KnownProblemModel(string title = default, string subtitle = default, Dictionary errors = default) { - Title = title; - Subtitle = subtitle; - Errors = errors ?? new(); - } - - public string Title { get; set; } - public string Subtitle { get; set; } - public Dictionary Errors { get; set; } - public string TraceId { get; set; } - - public void AddError(string field, string errorText) { - if (!Errors.ContainsKey(field)) { - Errors.Add(field, new[] {errorText}); - } else { - var currentErrors = Errors[field]; - var newErrors = currentErrors.Concat(new[] {errorText}); - Errors.Remove(field); - Errors.Add(field, newErrors.ToArray()); - } - } -} \ No newline at end of file diff --git a/code/api/src/Data/Models/LoggedInUserModel.cs b/code/api/src/Data/Models/LoggedInUserModel.cs deleted file mode 100644 index 541d4a5..0000000 --- a/code/api/src/Data/Models/LoggedInUserModel.cs +++ /dev/null @@ -1,8 +0,0 @@ -namespace IOL.GreatOffice.Api.Data.Models; - -public class LoggedInUserModel -{ - public Guid Id { get; set; } - public string Username { get; set; } - public Guid TenantId { get; set; } -} \ No newline at end of file diff --git a/code/api/src/Data/Models/RequestTimeZoneInfo.cs b/code/api/src/Data/Models/RequestTimeZoneInfo.cs deleted file mode 100644 index 4c5aa13..0000000 --- a/code/api/src/Data/Models/RequestTimeZoneInfo.cs +++ /dev/null @@ -1,8 +0,0 @@ -namespace IOL.GreatOffice.Api.Data.Models; - -public class RequestTimeZoneInfo -{ - public TimeZoneInfo TimeZoneInfo { get; set; } - public int Offset { get; set; } - public DateTime LocalDateTime { get; set; } -} \ No newline at end of file diff --git a/code/api/src/Data/Static/AppClaims.cs b/code/api/src/Data/Static/AppClaims.cs deleted file mode 100644 index 8b6d3a8..0000000 --- a/code/api/src/Data/Static/AppClaims.cs +++ /dev/null @@ -1,8 +0,0 @@ -namespace IOL.GreatOffice.Api.Data.Static; - -public static class AppClaims -{ - public const string USER_ID = "user_id"; - public const string NAME = "name"; - public const string GITHUB_ACCESS_TOKEN = ""; -} diff --git a/code/api/src/Data/Static/AppConstants.cs b/code/api/src/Data/Static/AppConstants.cs deleted file mode 100644 index d0a888b..0000000 --- a/code/api/src/Data/Static/AppConstants.cs +++ /dev/null @@ -1,12 +0,0 @@ -namespace IOL.GreatOffice.Api.Data.Static; - -public static class AppConstants -{ - public const string API_NAME = "Greatoffice API"; - public const string BASIC_AUTH_SCHEME = "BasicAuthenticationScheme"; - public const string TOKEN_ALLOW_READ = "TOKEN_ALLOW_READ"; - public const string TOKEN_ALLOW_CREATE = "TOKEN_ALLOW_CREATE"; - public const string TOKEN_ALLOW_UPDATE = "TOKEN_ALLOW_UPDATE"; - public const string TOKEN_ALLOW_DELETE = "TOKEN_ALLOW_DELETE"; - public const string VAULT_CACHE_KEY = "VAULT_CACHE_KEY"; -} diff --git a/code/api/src/Data/Static/AppCookies.cs b/code/api/src/Data/Static/AppCookies.cs deleted file mode 100644 index 57204dd..0000000 --- a/code/api/src/Data/Static/AppCookies.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace IOL.GreatOffice.Api.Data.Static; - -public static class AppCookies -{ - public static readonly string Locale = "go_locale"; - public static readonly string Session = "go_session"; -} \ No newline at end of file diff --git a/code/api/src/Data/Static/AppDateTime.cs b/code/api/src/Data/Static/AppDateTime.cs deleted file mode 100644 index 880d2a8..0000000 --- a/code/api/src/Data/Static/AppDateTime.cs +++ /dev/null @@ -1,16 +0,0 @@ -namespace IOL.GreatOffice.Api.Data.Static; - -public static class AppDateTime -{ - private static DateTime? dateTime; - - public static DateTime UtcNow => dateTime ?? DateTime.UtcNow; - - public static void Set(DateTime setDateTime) { - dateTime = setDateTime; - } - - public static void Reset() { - dateTime = null; - } -} diff --git a/code/api/src/Data/Static/AppEnvironmentVariables.cs b/code/api/src/Data/Static/AppEnvironmentVariables.cs deleted file mode 100644 index c3f821d..0000000 --- a/code/api/src/Data/Static/AppEnvironmentVariables.cs +++ /dev/null @@ -1,21 +0,0 @@ -namespace IOL.GreatOffice.Api.Data.Static; - -public static class AppEnvironmentVariables -{ - /// - /// An access token that can be used to access the Hashicorp Vault instance that is available at VAULT_URL - /// - public const string VAULT_TOKEN = "VAULT_TOKEN"; - /// - /// An url pointing to the Hashicorp Vault instance the app should use - /// - public const string VAULT_URL = "VAULT_URL"; - /// - /// The duration of which to keep a local cached version of the configuration - /// - public const string VAULT_CACHE_TTL = "VAULT_CACHE_TTL"; - /// - /// The vault key name for the main configuration json object, described by - /// - public const string MAIN_CONFIG_SHEET = "MAIN_CONFIG_SHEET"; -} diff --git a/code/api/src/Data/Static/AppHeaders.cs b/code/api/src/Data/Static/AppHeaders.cs deleted file mode 100644 index d534aba..0000000 --- a/code/api/src/Data/Static/AppHeaders.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace IOL.GreatOffice.Api.Data.Static; - -public static class AppHeaders -{ - public const string BROWSER_TIME_ZONE = "X-TimeZone"; - public const string IS_KNOWN_PROBLEM = "X-IsKnownProblem"; -} diff --git a/code/api/src/Data/Static/AppPaths.cs b/code/api/src/Data/Static/AppPaths.cs deleted file mode 100644 index a24f5af..0000000 --- a/code/api/src/Data/Static/AppPaths.cs +++ /dev/null @@ -1,17 +0,0 @@ - -namespace IOL.GreatOffice.Api.Data.Static; - -public static class AppPaths -{ - public static AppPath AppData => new() { - HostPath = Path.Combine(Directory.GetCurrentDirectory(), "AppData") - }; - - public static AppPath DataProtectionKeys => new() { - HostPath = Path.Combine(Directory.GetCurrentDirectory(), "AppData", "dp-keys") - }; - - public static AppPath Frontend => new() { - HostPath = Path.Combine(Directory.GetCurrentDirectory(), "Frontend") - }; -} diff --git a/code/api/src/Data/Static/JsonSettings.cs b/code/api/src/Data/Static/JsonSettings.cs deleted file mode 100644 index a163c11..0000000 --- a/code/api/src/Data/Static/JsonSettings.cs +++ /dev/null @@ -1,11 +0,0 @@ -namespace IOL.GreatOffice.Api.Data.Static; - -public static class JsonSettings -{ - public static Action Default { get; } = options => { - options.JsonSerializerOptions.ReferenceHandler = ReferenceHandler.IgnoreCycles; - options.JsonSerializerOptions.PropertyNameCaseInsensitive = true; - options.JsonSerializerOptions.NumberHandling = JsonNumberHandling.AllowReadingFromString; - options.JsonSerializerOptions.PropertyNamingPolicy = JsonNamingPolicy.CamelCase; - }; -} diff --git a/code/api/src/Endpoints/Internal/Root/GetApplicationVersionRoute.cs b/code/api/src/Endpoints/Internal/Root/GetApplicationVersionRoute.cs deleted file mode 100644 index 34180d1..0000000 --- a/code/api/src/Endpoints/Internal/Root/GetApplicationVersionRoute.cs +++ /dev/null @@ -1,20 +0,0 @@ -namespace IOL.GreatOffice.Api.Endpoints.Internal.Root; - -public class GetApplicationVersionRoute : RouteBaseSync.WithoutRequest.WithActionResult -{ - private readonly IWebHostEnvironment _environment; - - public GetApplicationVersionRoute(IWebHostEnvironment environment) { - _environment = environment; - } - - /// - /// Get the running api version number. - /// - /// - [HttpGet("~/_/version")] - public override ActionResult Handle() { - var versionFilePath = Path.Combine(_environment.WebRootPath, "version.txt"); - return Ok(System.IO.File.ReadAllText(versionFilePath)); - } -} \ No newline at end of file diff --git a/code/api/src/Endpoints/Internal/Root/LogRoute.cs b/code/api/src/Endpoints/Internal/Root/LogRoute.cs deleted file mode 100644 index 2c69e94..0000000 --- a/code/api/src/Endpoints/Internal/Root/LogRoute.cs +++ /dev/null @@ -1,16 +0,0 @@ -namespace IOL.GreatOffice.Api.Endpoints.Internal.Root; - -public class LogRoute : RouteBaseSync.WithRequest.WithoutResult -{ - private readonly ILogger _logger; - - public LogRoute(ILogger logger) { - _logger = logger; - } - - [AllowAnonymous] - [HttpPost("~/_/log")] - public override void Handle([FromBody] string request) { - _logger.LogInformation(request); - } -} \ No newline at end of file diff --git a/code/api/src/Models/Database/Api/ApiAccessToken.cs b/code/api/src/Models/Database/Api/ApiAccessToken.cs new file mode 100644 index 0000000..9359fc4 --- /dev/null +++ b/code/api/src/Models/Database/Api/ApiAccessToken.cs @@ -0,0 +1,12 @@ +namespace IOL.GreatOffice.Api.Data.Database; + +public class ApiAccessToken : Base +{ + public User User { get; set; } + public DateTime ExpiryDate { get; set; } + public bool AllowRead { get; set; } + public bool AllowCreate { get; set; } + public bool AllowUpdate { get; set; } + public bool AllowDelete { get; set; } + public bool HasExpired => ExpiryDate < AppDateTime.UtcNow; +} \ No newline at end of file diff --git a/code/api/src/Models/Database/Base.cs b/code/api/src/Models/Database/Base.cs new file mode 100644 index 0000000..900b923 --- /dev/null +++ b/code/api/src/Models/Database/Base.cs @@ -0,0 +1,22 @@ +namespace IOL.GreatOffice.Api.Data.Database; + +public class Base +{ + protected Base() { + Id = Guid.NewGuid(); + CreatedAt = AppDateTime.UtcNow; + } + + public Guid Id { get; init; } + public DateTime CreatedAt { get; init; } + public DateTime? ModifiedAt { get; private set; } + public DateTime? DeletedAt { get; private set; } + public bool Deleted { get; private set; } + + public void SetModified() => ModifiedAt = AppDateTime.UtcNow; + + public void SetDeleted() { + Deleted = true; + DeletedAt = AppDateTime.UtcNow; + } +} \ No newline at end of file diff --git a/code/api/src/Models/Database/BaseWithOwner.cs b/code/api/src/Models/Database/BaseWithOwner.cs new file mode 100644 index 0000000..ad9b33a --- /dev/null +++ b/code/api/src/Models/Database/BaseWithOwner.cs @@ -0,0 +1,36 @@ +namespace IOL.GreatOffice.Api.Data.Database; + +/// +/// Base class for all entities with ownership. +/// +public class BaseWithOwner : Base +{ + protected BaseWithOwner() { } + + protected BaseWithOwner(LoggedInUserModel loggedInUser) { + CreatedBy = loggedInUser.Id; + } + + public Guid? UserId { get; private set; } + public Guid? TenantId { get; private set; } + public Guid? ModifiedBy { get; private set; } + public Guid? CreatedBy { get; private set; } + public Guid? DeletedBy { get; private set; } + public User OwningUser { get; set; } + public Tenant OwningTenant { get; set; } + + public void SetDeleted(Guid userId) { + DeletedBy = userId; + SetDeleted(); + } + + public void SetModified(Guid userId) { + ModifiedBy = userId; + SetModified(); + } + + public void SetOwnerIds(Guid userId = default, Guid tenantId = default) { + if (tenantId != default) TenantId = tenantId; + if (userId != default) UserId = userId; + } +} \ No newline at end of file diff --git a/code/api/src/Models/Database/Customer/Customer.cs b/code/api/src/Models/Database/Customer/Customer.cs new file mode 100644 index 0000000..8e153c6 --- /dev/null +++ b/code/api/src/Models/Database/Customer/Customer.cs @@ -0,0 +1,29 @@ +namespace IOL.GreatOffice.Api.Data.Database; + +public class Customer : BaseWithOwner +{ + public Customer() { } + public Customer(LoggedInUserModel loggedInUserModel) : base(loggedInUserModel) { } + + public string CustomerNumber { get; set; } + public string Name { get; set; } + public string Description { get; set; } + public string Address1 { get; set; } + public string Address2 { get; set; } + public string PostalCode { get; set; } + public string PostalCity { get; set; } + public string Country { get; set; } + public string Phone { get; set; } + public string Email { get; set; } + public string VATNumber { get; set; } + public string ORGNumber { get; set; } + public string DefaultReference { get; set; } + public string Website { get; set; } + public string Currency { get; set; } + public Guid? OwnerId { get; set; } + public User Owner { get; set; } + public ICollection Groups { get; set; } + public ICollection Contacts { get; set; } + public ICollection Events { get; set; } + public ICollection Projects { get; set; } +} \ No newline at end of file diff --git a/code/api/src/Models/Database/Customer/CustomerContact.cs b/code/api/src/Models/Database/Customer/CustomerContact.cs new file mode 100644 index 0000000..f5a951d --- /dev/null +++ b/code/api/src/Models/Database/Customer/CustomerContact.cs @@ -0,0 +1,12 @@ +namespace IOL.GreatOffice.Api.Data.Database; + +public class CustomerContact : BaseWithOwner +{ + public Customer Customer { get; set; } + public string FirstName { get; set; } + public string LastName { get; set; } + public string Email { get; set; } + public string Phone { get; set; } + public string WorkTitle { get; set; } + public string Note { get; set; } +} diff --git a/code/api/src/Models/Database/Customer/CustomerEvent.cs b/code/api/src/Models/Database/Customer/CustomerEvent.cs new file mode 100644 index 0000000..a87da4c --- /dev/null +++ b/code/api/src/Models/Database/Customer/CustomerEvent.cs @@ -0,0 +1,8 @@ +namespace IOL.GreatOffice.Api.Data.Database; + +public class CustomerEvent : BaseWithOwner +{ + public Customer Customer { get; set; } + public string Title { get; set; } + public string Note { get; set; } +} diff --git a/code/api/src/Models/Database/Customer/CustomerGroup.cs b/code/api/src/Models/Database/Customer/CustomerGroup.cs new file mode 100644 index 0000000..9438f3c --- /dev/null +++ b/code/api/src/Models/Database/Customer/CustomerGroup.cs @@ -0,0 +1,7 @@ +namespace IOL.GreatOffice.Api.Data.Database; + +public class CustomerGroup : BaseWithOwner +{ + public string Name { get; set; } + public ICollection Customers { get; set; } +} \ No newline at end of file diff --git a/code/api/src/Models/Database/Customer/CustomerGroupMembership.cs b/code/api/src/Models/Database/Customer/CustomerGroupMembership.cs new file mode 100644 index 0000000..ec0d4af --- /dev/null +++ b/code/api/src/Models/Database/Customer/CustomerGroupMembership.cs @@ -0,0 +1,7 @@ +namespace IOL.GreatOffice.Api.Data.Database; + +public class CustomerGroupMembership : Base +{ + public Customer Customer { get; set; } + public CustomerGroup Group { get; set; } +} \ No newline at end of file diff --git a/code/api/src/Models/Database/Internal/PasswordResetRequest.cs b/code/api/src/Models/Database/Internal/PasswordResetRequest.cs new file mode 100644 index 0000000..ee73fd2 --- /dev/null +++ b/code/api/src/Models/Database/Internal/PasswordResetRequest.cs @@ -0,0 +1,23 @@ +namespace IOL.GreatOffice.Api.Data.Database; + +public class PasswordResetRequest +{ + public PasswordResetRequest() { } + + public PasswordResetRequest(User user) { + CreatedAt = AppDateTime.UtcNow; + Id = Guid.NewGuid(); + User = user; + } + + public Guid Id { get; set; } + public Guid UserId { get; set; } + public User User { get; set; } + public DateTime CreatedAt { get; set; } + + [NotMapped] + public DateTime ExpirationDate => CreatedAt.AddMinutes(15); + + [NotMapped] + public bool IsExpired => DateTime.Compare(ExpirationDate, AppDateTime.UtcNow) < 0; +} diff --git a/code/api/src/Models/Database/Internal/User.cs b/code/api/src/Models/Database/Internal/User.cs new file mode 100644 index 0000000..9db5d35 --- /dev/null +++ b/code/api/src/Models/Database/Internal/User.cs @@ -0,0 +1,37 @@ +namespace IOL.GreatOffice.Api.Data.Database; + +public class User : Base +{ + public User() { } + + public User(string username) { + Username = username; + } + + public string FirstName { get; set; } + public string LastName { get; set; } + public string Email { get; set; } + public string Username { get; set; } + public string Password { get; set; } + public ICollection Tenants { get; set; } + + public string DisplayName() { + if (FirstName.HasValue() && LastName.HasValue()) return FirstName + " " + LastName; + return FirstName.HasValue() ? FirstName : Email; + } + + public void HashAndSetPassword(string password) { + Password = PasswordHelper.HashPassword(password); + } + + public bool VerifyPassword(string password) { + return PasswordHelper.Verify(password, Password); + } + + public IEnumerable DefaultClaims() { + return new Claim[] { + new(AppClaims.USER_ID, Id.ToString()), + new(AppClaims.NAME, Username), + }; + } +} \ No newline at end of file diff --git a/code/api/src/Models/Database/MainAppDatabase.cs b/code/api/src/Models/Database/MainAppDatabase.cs new file mode 100644 index 0000000..eaf7781 --- /dev/null +++ b/code/api/src/Models/Database/MainAppDatabase.cs @@ -0,0 +1,105 @@ +using Microsoft.AspNetCore.DataProtection.EntityFrameworkCore; + +namespace IOL.GreatOffice.Api.Data.Database; + +public class MainAppDatabase : DbContext, IDataProtectionKeyContext +{ + public MainAppDatabase(DbContextOptions options) : base(options) { } + public DbSet Users { get; set; } + public DbSet PasswordResetRequests { get; set; } + public DbSet AccessTokens { get; set; } + public DbSet Tenants { get; set; } + public DbSet DataProtectionKeys { get; set; } + public DbSet Projects { get; set; } + public DbSet ProjectLabels { get; set; } + public DbSet Customers { get; set; } + public DbSet CustomersContacts { get; set; } + public DbSet CustomerEvents { get; set; } + public DbSet CustomerGroups { get; set; } + public DbSet TodoLabels { get; set; } + public DbSet TodoProjectAccessControls { get; set; } + public DbSet TodoProjects { get; set; } + public DbSet TodoComments { get; set; } + public DbSet Todos { get; set; } + + protected override void OnModelCreating(ModelBuilder modelBuilder) { + modelBuilder.Entity(e => { + e.HasMany(n => n.Tenants); + e.ToTable("users"); + }); + modelBuilder.Entity(e => { + e.HasOne(c => c.User); + e.ToTable("password_reset_requests"); + }); + modelBuilder.Entity(e => { + e.HasOne(n => n.User); + e.ToTable("api_access_tokens"); + }); + modelBuilder.Entity(e => { + e.HasMany(n => n.Users); + e.ToTable("tenants"); + }); + modelBuilder.Entity(e => { + e.HasMany(n => n.Members); + e.HasMany(n => n.Customers); + e.ToTable("projects"); + }); + modelBuilder.Entity(e => { + e.HasOne(n => n.Project); + e.HasOne(n => n.User); + e.ToTable("project_members"); + }); + modelBuilder.Entity(e => { + e.HasOne(n => n.Project); + e.ToTable("project_labels"); + }); + modelBuilder.Entity(e => { + e.HasOne(n => n.Owner); + e.HasMany(n => n.Events); + e.HasMany(n => n.Contacts); + e.HasMany(n => n.Groups); + e.HasMany(n => n.Projects); + e.ToTable("customers"); + }); + modelBuilder.Entity(e => { + e.HasOne(n => n.Customer); + e.ToTable("customer_contacts"); + }); + modelBuilder.Entity(e => { + e.HasOne(n => n.Customer); + e.ToTable("customer_events"); + }); + modelBuilder.Entity(e => { + e.HasMany(n => n.Customers); + e.ToTable("customer_groups"); + }); + modelBuilder.Entity(e => { + e.HasOne(n => n.Collection); + e.HasOne(n => n.AssignedTo); + e.HasOne(n => n.ClosedBy); + e.HasMany(n => n.Labels); + e.HasMany(n => n.Comments); + e.ToTable("todos"); + }); + modelBuilder.Entity(e => { + e.HasOne(n => n.Project); + e.HasMany(n => n.AccessControls); + e.ToTable("todo_collections"); + }); + modelBuilder.Entity(e => { + e.HasOne(n => n.Todo); + e.ToTable("todo_comments"); + }); + modelBuilder.Entity(e => { + e.HasOne(n => n.Todo); + e.ToTable("todo_labels"); + }); + modelBuilder.Entity(e => { + e.HasOne(n => n.User); + e.HasOne(n => n.Collection); + e.ToTable("todo_collection_access_controls"); + }); + + base.OnModelCreating(modelBuilder); + } +} \ No newline at end of file diff --git a/code/api/src/Models/Database/Project/Project.cs b/code/api/src/Models/Database/Project/Project.cs new file mode 100644 index 0000000..de9e2cb --- /dev/null +++ b/code/api/src/Models/Database/Project/Project.cs @@ -0,0 +1,15 @@ +namespace IOL.GreatOffice.Api.Data.Database; + +public class Project : BaseWithOwner +{ + public Project() { } + + public Project(LoggedInUserModel loggedInUserModel) : base(loggedInUserModel) { } + public string Name { get; set; } + public string Description { get; set; } + public DateTime? Start { get; set; } + public DateTime? Stop { get; set; } + public ICollection Customers { get; set; } + public ICollection Members { get; set; } + public ICollection Labels { get; set; } +} \ No newline at end of file diff --git a/code/api/src/Models/Database/Project/ProjectLabel.cs b/code/api/src/Models/Database/Project/ProjectLabel.cs new file mode 100644 index 0000000..0e1dc5d --- /dev/null +++ b/code/api/src/Models/Database/Project/ProjectLabel.cs @@ -0,0 +1,8 @@ +namespace IOL.GreatOffice.Api.Data.Database; + +public class ProjectLabel : BaseWithOwner +{ + public string Value { get; set; } + public string Color { get; set; } + public Project Project { get; set; } +} diff --git a/code/api/src/Models/Database/Project/ProjectMember.cs b/code/api/src/Models/Database/Project/ProjectMember.cs new file mode 100644 index 0000000..a5e0682 --- /dev/null +++ b/code/api/src/Models/Database/Project/ProjectMember.cs @@ -0,0 +1,8 @@ +namespace IOL.GreatOffice.Api.Data.Database; + +public class ProjectMember : Base +{ + public Project Project { get; set; } + public User User { get; set; } + public ProjectRole Role { get; set; } +} \ No newline at end of file diff --git a/code/api/src/Models/Database/Todo/Todo.cs b/code/api/src/Models/Database/Todo/Todo.cs new file mode 100644 index 0000000..2d7f109 --- /dev/null +++ b/code/api/src/Models/Database/Todo/Todo.cs @@ -0,0 +1,17 @@ +namespace IOL.GreatOffice.Api.Data.Database; + +public class Todo : BaseWithOwner +{ + public string PublicId { get; set; } + public Guid? AssignedToId { get; set; } + public Guid? ClosedById { get; set; } + public Guid CollectionId { get; set; } + public DateTime? ClosedAt { get; set; } + public string Title { get; set; } + public string Description { get; set; } + public ICollection Labels { get; set; } + public ICollection Comments { get; set; } + public User AssignedTo { get; set; } + public User ClosedBy { get; set; } + public TodoCollection Collection { get; set; } +} \ No newline at end of file diff --git a/code/api/src/Models/Database/Todo/TodoCollection.cs b/code/api/src/Models/Database/Todo/TodoCollection.cs new file mode 100644 index 0000000..470e5e7 --- /dev/null +++ b/code/api/src/Models/Database/Todo/TodoCollection.cs @@ -0,0 +1,11 @@ +namespace IOL.GreatOffice.Api.Data.Database; + +public class TodoCollection : BaseWithOwner +{ + public string Name { get; set; } + public string Description { get; set; } + public TodoVisibility Visibility { get; set; } + public Guid? ProjectId { get; set; } + public Project Project { get; set; } + public ICollection AccessControls { get; set; } +} \ No newline at end of file diff --git a/code/api/src/Models/Database/Todo/TodoCollectionAccessControl.cs b/code/api/src/Models/Database/Todo/TodoCollectionAccessControl.cs new file mode 100644 index 0000000..1676c06 --- /dev/null +++ b/code/api/src/Models/Database/Todo/TodoCollectionAccessControl.cs @@ -0,0 +1,12 @@ +namespace IOL.GreatOffice.Api.Data.Database; + +public class TodoCollectionAccessControl : Base +{ + public TodoCollection Collection { get; set; } + public User User { get; set; } + public Guid? UserId { get; set; } + public bool CanBrowse { get; set; } + public bool CanSubmit { get; set; } + public bool CanComment { get; set; } + public bool CanEdit { get; set; } +} \ No newline at end of file diff --git a/code/api/src/Models/Database/Todo/TodoComment.cs b/code/api/src/Models/Database/Todo/TodoComment.cs new file mode 100644 index 0000000..32ac3a3 --- /dev/null +++ b/code/api/src/Models/Database/Todo/TodoComment.cs @@ -0,0 +1,8 @@ +namespace IOL.GreatOffice.Api.Data.Database; + +public class TodoComment : BaseWithOwner +{ + public string Value { get; set; } + public Todo Todo { get; set; } + public TodoClosingStatement? ClosingStatement { get; set; } +} \ No newline at end of file diff --git a/code/api/src/Models/Database/Todo/TodoLabel.cs b/code/api/src/Models/Database/Todo/TodoLabel.cs new file mode 100644 index 0000000..7753ade --- /dev/null +++ b/code/api/src/Models/Database/Todo/TodoLabel.cs @@ -0,0 +1,8 @@ +namespace IOL.GreatOffice.Api.Data.Database; + +public class TodoLabel : BaseWithOwner +{ + public string Name { get; set; } + public string Color { get; set; } + public Todo Todo { get; set; } +} diff --git a/code/api/src/Models/Enums/FulfillPasswordResetRequestResult.cs b/code/api/src/Models/Enums/FulfillPasswordResetRequestResult.cs new file mode 100644 index 0000000..2a84c48 --- /dev/null +++ b/code/api/src/Models/Enums/FulfillPasswordResetRequestResult.cs @@ -0,0 +1,8 @@ +namespace IOL.GreatOffice.Api.Data.Enums; + +public enum FulfillPasswordResetRequestResult +{ + REQUEST_NOT_FOUND, + USER_NOT_FOUND, + FULFILLED +} \ No newline at end of file diff --git a/code/api/src/Models/Enums/PasswordResetRequestStatus.cs b/code/api/src/Models/Enums/PasswordResetRequestStatus.cs new file mode 100644 index 0000000..5629e6f --- /dev/null +++ b/code/api/src/Models/Enums/PasswordResetRequestStatus.cs @@ -0,0 +1,6 @@ +namespace IOL.GreatOffice.Api.Data.Enums; + +public enum PasswordResetRequestStatus +{ + +} \ No newline at end of file diff --git a/code/api/src/Models/Enums/ProjectRole.cs b/code/api/src/Models/Enums/ProjectRole.cs new file mode 100644 index 0000000..c4a3f29 --- /dev/null +++ b/code/api/src/Models/Enums/ProjectRole.cs @@ -0,0 +1,9 @@ +namespace IOL.GreatOffice.Api.Data.Enums; + +public enum ProjectRole +{ + EXTERNAL, + RESOURCE, + LEADER, + OWNER +} \ No newline at end of file diff --git a/code/api/src/Models/Enums/TodoClosingStatement.cs b/code/api/src/Models/Enums/TodoClosingStatement.cs new file mode 100644 index 0000000..d838031 --- /dev/null +++ b/code/api/src/Models/Enums/TodoClosingStatement.cs @@ -0,0 +1,13 @@ +namespace IOL.GreatOffice.Api.Data.Enums; + +public enum TodoClosingStatement +{ + REPORTED, + RESOLVED, + FIXED, + IMPLEMENTED, + WONT_FIX, + BY_DESIGN, + INVALID, + DUPLICATE +} \ No newline at end of file diff --git a/code/api/src/Models/Enums/TodoVisibility.cs b/code/api/src/Models/Enums/TodoVisibility.cs new file mode 100644 index 0000000..2c8fa83 --- /dev/null +++ b/code/api/src/Models/Enums/TodoVisibility.cs @@ -0,0 +1,10 @@ + +namespace IOL.GreatOffice.Api.Data.Enums; + +public enum TodoVisibility +{ + PRIVATE = 0, + UNLISTED = 1, + INTERNAL = 2, + PUBLIC = 3, +} \ No newline at end of file diff --git a/code/api/src/Models/Misc/ApiSpecDocument.cs b/code/api/src/Models/Misc/ApiSpecDocument.cs new file mode 100644 index 0000000..1c7d936 --- /dev/null +++ b/code/api/src/Models/Misc/ApiSpecDocument.cs @@ -0,0 +1,9 @@ +namespace IOL.GreatOffice.Api.Data.Models; + +public class ApiSpecDocument +{ + public string VersionName { get; set; } + public string SwaggerPath { get; set; } + public ApiVersion Version { get; set; } + public OpenApiInfo OpenApiInfo { get; set; } +} diff --git a/code/api/src/Models/Misc/AppConfiguration.cs b/code/api/src/Models/Misc/AppConfiguration.cs new file mode 100644 index 0000000..2a9afc2 --- /dev/null +++ b/code/api/src/Models/Misc/AppConfiguration.cs @@ -0,0 +1,113 @@ +using System.Security.Cryptography.X509Certificates; + +namespace IOL.GreatOffice.Api.Data.Models; + +public class AppConfiguration +{ + /// + /// An reachable ip address or url that points to a postgres database. + /// + public string DB_HOST { get; set; } + + /// + /// The port number to use with DB_HOST to point to the postgres database. + /// + public string DB_PORT { get; set; } + + /// + /// The database user to authenticate against postgres with. + /// + public string DB_USER { get; set; } + + /// + /// The password for the database user to authenticate against postgres with. + /// + public string DB_PASSWORD { get; set; } + + /// + /// The name of the main app database. + /// + public string DB_NAME { get; set; } + + /// + /// An reachable ip address or url that points to a postgres(quartz) database. + /// + public string QUARTZ_DB_HOST { get; set; } + + /// + /// The port number to use with QUARTZ_DB_HOST to point to the postgres(quartz) database. + /// + public string QUARTZ_DB_PORT { get; set; } + + /// + /// The database user to authenticate against postgres(quartz) with. + /// + public string QUARTZ_DB_USER { get; set; } + + /// + /// The password for the database user to authenticate against postgres(quartz) with. + /// + public string QUARTZ_DB_PASSWORD { get; set; } + + /// + /// The name of the quartz database. + /// + public string QUARTZ_DB_NAME { get; set; } + + /// + /// API key to use when pushing logs to SEQ + /// + public string SEQ_API_KEY { get; set; } + + /// + /// Url pointing to the seq instance that processes server logs + /// + public string SEQ_API_URL { get; set; } + + /// + /// A token used when sending email via Postmakr + /// + public string POSTMARK_TOKEN { get; set; } + + /// + /// The address to send emails from, needs to be setup as a sender in postmark + /// + public string EMAIL_FROM_ADDRESS { get; set; } + + /// + /// The absolute url to the frontend app + /// + public string CANONICAL_FRONTEND_URL { get; set; } + + /// + /// A random string used to encrypt/decrypt for general purposes + /// + public string APP_AES_KEY { get; set; } + + /// + /// A base64 string containing a passwordless pfx cert + /// + public string APP_CERT { get; set; } + + public X509Certificate2 CERT1() => new(Convert.FromBase64String(APP_CERT)); + + public object GetPublicVersion() { + return new { + DB_HOST, + DB_PORT, + DB_USER, + DB_PASSWORD = DB_PASSWORD.Obfuscate() ?? "", + QUARTZ_DB_HOST, + QUARTZ_DB_PORT, + QUARTZ_DB_USER, + QUARTZ_DB_PASSWORD = QUARTZ_DB_PASSWORD.Obfuscate() ?? "", + SEQ_API_KEY = SEQ_API_KEY.Obfuscate() ?? "", + SEQ_API_URL, + POSTMARK_TOKEN = POSTMARK_TOKEN.Obfuscate() ?? "", + EMAIL_FROM_ADDRESS, + APP_AES_KEY = APP_AES_KEY.Obfuscate() ?? "", + CERT1 = CERT1().PublicKey.Oid.FriendlyName, + CANONICAL_FRONTEND_URL + }; + } +} \ No newline at end of file diff --git a/code/api/src/Models/Misc/AppPath.cs b/code/api/src/Models/Misc/AppPath.cs new file mode 100644 index 0000000..e47e48c --- /dev/null +++ b/code/api/src/Models/Misc/AppPath.cs @@ -0,0 +1,23 @@ +namespace IOL.GreatOffice.Api.Data.Models; + +public sealed record AppPath +{ + public string HostPath { get; init; } + public string WebPath { get; init; } + + public string GetHostPathForFilename(string filename, string fallback = "") { + if (filename.IsNullOrWhiteSpace()) { + return fallback; + } + + return Path.Combine(HostPath, filename); + } + + public string GetWebPathForFilename(string filename, string fallback = "") { + if (filename.IsNullOrWhiteSpace()) { + return fallback; + } + + return Path.Combine(WebPath, filename); + } +} diff --git a/code/api/src/Models/Misc/KnownProblemModel.cs b/code/api/src/Models/Misc/KnownProblemModel.cs new file mode 100644 index 0000000..9acc85c --- /dev/null +++ b/code/api/src/Models/Misc/KnownProblemModel.cs @@ -0,0 +1,26 @@ +namespace IOL.GreatOffice.Api.Data.Models; + +public class KnownProblemModel +{ + public KnownProblemModel(string title = default, string subtitle = default, Dictionary errors = default) { + Title = title; + Subtitle = subtitle; + Errors = errors ?? new(); + } + + public string Title { get; set; } + public string Subtitle { get; set; } + public Dictionary Errors { get; set; } + public string TraceId { get; set; } + + public void AddError(string field, string errorText) { + if (!Errors.ContainsKey(field)) { + Errors.Add(field, new[] {errorText}); + } else { + var currentErrors = Errors[field]; + var newErrors = currentErrors.Concat(new[] {errorText}); + Errors.Remove(field); + Errors.Add(field, newErrors.ToArray()); + } + } +} \ No newline at end of file diff --git a/code/api/src/Models/Misc/LoggedInUserModel.cs b/code/api/src/Models/Misc/LoggedInUserModel.cs new file mode 100644 index 0000000..541d4a5 --- /dev/null +++ b/code/api/src/Models/Misc/LoggedInUserModel.cs @@ -0,0 +1,8 @@ +namespace IOL.GreatOffice.Api.Data.Models; + +public class LoggedInUserModel +{ + public Guid Id { get; set; } + public string Username { get; set; } + public Guid TenantId { get; set; } +} \ No newline at end of file diff --git a/code/api/src/Models/Misc/RequestTimeZoneInfo.cs b/code/api/src/Models/Misc/RequestTimeZoneInfo.cs new file mode 100644 index 0000000..4c5aa13 --- /dev/null +++ b/code/api/src/Models/Misc/RequestTimeZoneInfo.cs @@ -0,0 +1,8 @@ +namespace IOL.GreatOffice.Api.Data.Models; + +public class RequestTimeZoneInfo +{ + public TimeZoneInfo TimeZoneInfo { get; set; } + public int Offset { get; set; } + public DateTime LocalDateTime { get; set; } +} \ No newline at end of file diff --git a/code/api/src/Models/Static/AppClaims.cs b/code/api/src/Models/Static/AppClaims.cs new file mode 100644 index 0000000..8b6d3a8 --- /dev/null +++ b/code/api/src/Models/Static/AppClaims.cs @@ -0,0 +1,8 @@ +namespace IOL.GreatOffice.Api.Data.Static; + +public static class AppClaims +{ + public const string USER_ID = "user_id"; + public const string NAME = "name"; + public const string GITHUB_ACCESS_TOKEN = ""; +} diff --git a/code/api/src/Models/Static/AppConstants.cs b/code/api/src/Models/Static/AppConstants.cs new file mode 100644 index 0000000..d0a888b --- /dev/null +++ b/code/api/src/Models/Static/AppConstants.cs @@ -0,0 +1,12 @@ +namespace IOL.GreatOffice.Api.Data.Static; + +public static class AppConstants +{ + public const string API_NAME = "Greatoffice API"; + public const string BASIC_AUTH_SCHEME = "BasicAuthenticationScheme"; + public const string TOKEN_ALLOW_READ = "TOKEN_ALLOW_READ"; + public const string TOKEN_ALLOW_CREATE = "TOKEN_ALLOW_CREATE"; + public const string TOKEN_ALLOW_UPDATE = "TOKEN_ALLOW_UPDATE"; + public const string TOKEN_ALLOW_DELETE = "TOKEN_ALLOW_DELETE"; + public const string VAULT_CACHE_KEY = "VAULT_CACHE_KEY"; +} diff --git a/code/api/src/Models/Static/AppCookies.cs b/code/api/src/Models/Static/AppCookies.cs new file mode 100644 index 0000000..57204dd --- /dev/null +++ b/code/api/src/Models/Static/AppCookies.cs @@ -0,0 +1,7 @@ +namespace IOL.GreatOffice.Api.Data.Static; + +public static class AppCookies +{ + public static readonly string Locale = "go_locale"; + public static readonly string Session = "go_session"; +} \ No newline at end of file diff --git a/code/api/src/Models/Static/AppDateTime.cs b/code/api/src/Models/Static/AppDateTime.cs new file mode 100644 index 0000000..880d2a8 --- /dev/null +++ b/code/api/src/Models/Static/AppDateTime.cs @@ -0,0 +1,16 @@ +namespace IOL.GreatOffice.Api.Data.Static; + +public static class AppDateTime +{ + private static DateTime? dateTime; + + public static DateTime UtcNow => dateTime ?? DateTime.UtcNow; + + public static void Set(DateTime setDateTime) { + dateTime = setDateTime; + } + + public static void Reset() { + dateTime = null; + } +} diff --git a/code/api/src/Models/Static/AppEnvironmentVariables.cs b/code/api/src/Models/Static/AppEnvironmentVariables.cs new file mode 100644 index 0000000..c3f821d --- /dev/null +++ b/code/api/src/Models/Static/AppEnvironmentVariables.cs @@ -0,0 +1,21 @@ +namespace IOL.GreatOffice.Api.Data.Static; + +public static class AppEnvironmentVariables +{ + /// + /// An access token that can be used to access the Hashicorp Vault instance that is available at VAULT_URL + /// + public const string VAULT_TOKEN = "VAULT_TOKEN"; + /// + /// An url pointing to the Hashicorp Vault instance the app should use + /// + public const string VAULT_URL = "VAULT_URL"; + /// + /// The duration of which to keep a local cached version of the configuration + /// + public const string VAULT_CACHE_TTL = "VAULT_CACHE_TTL"; + /// + /// The vault key name for the main configuration json object, described by + /// + public const string MAIN_CONFIG_SHEET = "MAIN_CONFIG_SHEET"; +} diff --git a/code/api/src/Models/Static/AppHeaders.cs b/code/api/src/Models/Static/AppHeaders.cs new file mode 100644 index 0000000..d534aba --- /dev/null +++ b/code/api/src/Models/Static/AppHeaders.cs @@ -0,0 +1,7 @@ +namespace IOL.GreatOffice.Api.Data.Static; + +public static class AppHeaders +{ + public const string BROWSER_TIME_ZONE = "X-TimeZone"; + public const string IS_KNOWN_PROBLEM = "X-IsKnownProblem"; +} diff --git a/code/api/src/Models/Static/AppPaths.cs b/code/api/src/Models/Static/AppPaths.cs new file mode 100644 index 0000000..a24f5af --- /dev/null +++ b/code/api/src/Models/Static/AppPaths.cs @@ -0,0 +1,17 @@ + +namespace IOL.GreatOffice.Api.Data.Static; + +public static class AppPaths +{ + public static AppPath AppData => new() { + HostPath = Path.Combine(Directory.GetCurrentDirectory(), "AppData") + }; + + public static AppPath DataProtectionKeys => new() { + HostPath = Path.Combine(Directory.GetCurrentDirectory(), "AppData", "dp-keys") + }; + + public static AppPath Frontend => new() { + HostPath = Path.Combine(Directory.GetCurrentDirectory(), "Frontend") + }; +} diff --git a/code/api/src/Models/Static/JsonSettings.cs b/code/api/src/Models/Static/JsonSettings.cs new file mode 100644 index 0000000..a163c11 --- /dev/null +++ b/code/api/src/Models/Static/JsonSettings.cs @@ -0,0 +1,11 @@ +namespace IOL.GreatOffice.Api.Data.Static; + +public static class JsonSettings +{ + public static Action Default { get; } = options => { + options.JsonSerializerOptions.ReferenceHandler = ReferenceHandler.IgnoreCycles; + options.JsonSerializerOptions.PropertyNameCaseInsensitive = true; + options.JsonSerializerOptions.NumberHandling = JsonNumberHandling.AllowReadingFromString; + options.JsonSerializerOptions.PropertyNamingPolicy = JsonNamingPolicy.CamelCase; + }; +} diff --git a/code/api/src/Program.cs b/code/api/src/Program.cs index 014b2bf..8f4348a 100644 --- a/code/api/src/Program.cs +++ b/code/api/src/Program.cs @@ -51,6 +51,7 @@ public static class Program builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped(); + builder.Services.AddScoped(); builder.Services.AddSingleton(); builder.Services.AddHttpClient(); builder.Services.AddHttpClient(); @@ -76,7 +77,6 @@ public static class Program })); builder.Host.UseSerilog(Log.Logger); - builder.WebHost.ConfigureKestrel(kestrel => { kestrel.AddServerHeader = false; }); if (builder.Environment.IsDevelopment()) { builder.Services.AddCors(); @@ -94,7 +94,7 @@ public static class Program .AddSupportedUICultures(supportedCultures); options.ApplyCurrentCultureToResponseHeaders = true; }); - + builder.Services.Configure(options => { options.AddInitialRequestCultureProvider(new CustomRequestCultureProvider(async context => // Get culture from specific cookie @@ -241,7 +241,7 @@ public static class Program return 1; } finally { - Log.Information("Shut down complete, flusing logs..."); + Log.Information("Shut down complete, flushing logs..."); Log.CloseAndFlush(); } } diff --git a/code/api/src/Utilities/Validators.cs b/code/api/src/Utilities/Validators.cs deleted file mode 100644 index fa3a144..0000000 --- a/code/api/src/Utilities/Validators.cs +++ /dev/null @@ -1,12 +0,0 @@ -using System.Text.RegularExpressions; - -namespace IOL.GreatOffice.Api.Utilities; - -public static class Validators -{ - private static readonly Regex EMAIL_REGEX = new(""); - - public static bool IsValidEmail(this string email) { - return EMAIL_REGEX.IsMatch(email); - } -} \ No newline at end of file -- cgit v1.3