Compare commits
	
		
			2 Commits
		
	
	
		
			1bb0012c40
			...
			665595b8b4
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 665595b8b4 | |||
| 29550401fd | 
| @@ -1,4 +1,5 @@ | |||||||
| using DysonNetwork.Develop.Identity; | using DysonNetwork.Develop.Identity; | ||||||
|  | using DysonNetwork.Develop.Project; | ||||||
| using Microsoft.EntityFrameworkCore; | using Microsoft.EntityFrameworkCore; | ||||||
| using Microsoft.EntityFrameworkCore.Design; | using Microsoft.EntityFrameworkCore.Design; | ||||||
|  |  | ||||||
| @@ -11,6 +12,8 @@ public class AppDatabase( | |||||||
| { | { | ||||||
|     public DbSet<Developer> Developers { get; set; } = null!; |     public DbSet<Developer> Developers { get; set; } = null!; | ||||||
|  |  | ||||||
|  |     public DbSet<DevProject> DevProjects { get; set; } = null!; | ||||||
|  |      | ||||||
|     public DbSet<CustomApp> CustomApps { get; set; } = null!; |     public DbSet<CustomApp> CustomApps { get; set; } = null!; | ||||||
|     public DbSet<CustomAppSecret> CustomAppSecrets { get; set; } = null!; |     public DbSet<CustomAppSecret> CustomAppSecrets { get; set; } = null!; | ||||||
|  |  | ||||||
|   | |||||||
| @@ -1,6 +1,7 @@ | |||||||
| using System.ComponentModel.DataAnnotations; | using System.ComponentModel.DataAnnotations; | ||||||
| using System.ComponentModel.DataAnnotations.Schema; | using System.ComponentModel.DataAnnotations.Schema; | ||||||
| using System.Text.Json.Serialization; | using System.Text.Json.Serialization; | ||||||
|  | using DysonNetwork.Develop.Project; | ||||||
| using DysonNetwork.Shared.Data; | using DysonNetwork.Shared.Data; | ||||||
| using DysonNetwork.Shared.Proto; | using DysonNetwork.Shared.Proto; | ||||||
| using Google.Protobuf; | using Google.Protobuf; | ||||||
| @@ -37,8 +38,11 @@ public class CustomApp : ModelBase, IIdentifiedResource | |||||||
|  |  | ||||||
|     [JsonIgnore] public ICollection<CustomAppSecret> Secrets { get; set; } = new List<CustomAppSecret>(); |     [JsonIgnore] public ICollection<CustomAppSecret> Secrets { get; set; } = new List<CustomAppSecret>(); | ||||||
|  |  | ||||||
|     public Guid DeveloperId { get; set; } |     public Guid ProjectId { get; set; } | ||||||
|     public Developer Developer { get; set; } = null!; |     public DevProject Project { get; set; } = null!; | ||||||
|  |      | ||||||
|  |     [NotMapped] | ||||||
|  |     public Developer Developer => Project.Developer; | ||||||
|  |  | ||||||
|     [NotMapped] public string ResourceIdentifier => "custom-app:" + Id; |     [NotMapped] public string ResourceIdentifier => "custom-app:" + Id; | ||||||
|  |  | ||||||
| @@ -72,7 +76,7 @@ public class CustomApp : ModelBase, IIdentifiedResource | |||||||
|                 RequirePkce = OauthConfig.RequirePkce, |                 RequirePkce = OauthConfig.RequirePkce, | ||||||
|                 AllowOfflineAccess = OauthConfig.AllowOfflineAccess |                 AllowOfflineAccess = OauthConfig.AllowOfflineAccess | ||||||
|             }, |             }, | ||||||
|             DeveloperId = DeveloperId.ToString(), |             ProjectId = ProjectId.ToString(), | ||||||
|             CreatedAt = CreatedAt.ToTimestamp(), |             CreatedAt = CreatedAt.ToTimestamp(), | ||||||
|             UpdatedAt = UpdatedAt.ToTimestamp() |             UpdatedAt = UpdatedAt.ToTimestamp() | ||||||
|         }; |         }; | ||||||
| @@ -92,7 +96,7 @@ public class CustomApp : ModelBase, IIdentifiedResource | |||||||
|             Shared.Proto.CustomAppStatus.Suspended => CustomAppStatus.Suspended, |             Shared.Proto.CustomAppStatus.Suspended => CustomAppStatus.Suspended, | ||||||
|             _ => CustomAppStatus.Developing |             _ => CustomAppStatus.Developing | ||||||
|         }; |         }; | ||||||
|         DeveloperId = string.IsNullOrEmpty(p.DeveloperId) ? Guid.Empty : Guid.Parse(p.DeveloperId); |         ProjectId = string.IsNullOrEmpty(p.ProjectId) ? Guid.Empty : Guid.Parse(p.ProjectId); | ||||||
|         CreatedAt = p.CreatedAt.ToInstant(); |         CreatedAt = p.CreatedAt.ToInstant(); | ||||||
|         UpdatedAt = p.UpdatedAt.ToInstant(); |         UpdatedAt = p.UpdatedAt.ToInstant(); | ||||||
|         if (p.Picture.Length > 0) Picture = System.Text.Json.JsonSerializer.Deserialize<CloudFileReferenceObject>(p.Picture.ToStringUtf8()); |         if (p.Picture.Length > 0) Picture = System.Text.Json.JsonSerializer.Deserialize<CloudFileReferenceObject>(p.Picture.ToStringUtf8()); | ||||||
|   | |||||||
| @@ -1,4 +1,5 @@ | |||||||
| using System.ComponentModel.DataAnnotations; | using System.ComponentModel.DataAnnotations; | ||||||
|  | using DysonNetwork.Develop.Project; | ||||||
| using DysonNetwork.Shared.Proto; | using DysonNetwork.Shared.Proto; | ||||||
| using Microsoft.AspNetCore.Authorization; | using Microsoft.AspNetCore.Authorization; | ||||||
| using Microsoft.AspNetCore.Mvc; | using Microsoft.AspNetCore.Mvc; | ||||||
| @@ -6,8 +7,8 @@ using Microsoft.AspNetCore.Mvc; | |||||||
| namespace DysonNetwork.Develop.Identity; | namespace DysonNetwork.Develop.Identity; | ||||||
|  |  | ||||||
| [ApiController] | [ApiController] | ||||||
| [Route("/api/developers/{pubName}/apps")] | [Route("/api/developers/{pubName}/projects/{projectId:guid}/apps")] | ||||||
| public class CustomAppController(CustomAppService customApps, DeveloperService ds) : ControllerBase | public class CustomAppController(CustomAppService customApps, DeveloperService ds, DevProjectService projectService) : ControllerBase | ||||||
| { | { | ||||||
|     public record CustomAppRequest( |     public record CustomAppRequest( | ||||||
|         [MaxLength(1024)] string? Slug, |         [MaxLength(1024)] string? Slug, | ||||||
| @@ -21,21 +22,28 @@ public class CustomAppController(CustomAppService customApps, DeveloperService d | |||||||
|     ); |     ); | ||||||
|  |  | ||||||
|     [HttpGet] |     [HttpGet] | ||||||
|     public async Task<IActionResult> ListApps([FromRoute] string pubName) |     public async Task<IActionResult> ListApps([FromRoute] string pubName, [FromRoute] Guid projectId) | ||||||
|     { |     { | ||||||
|         var developer = await ds.GetDeveloperByName(pubName); |         var developer = await ds.GetDeveloperByName(pubName); | ||||||
|         if (developer is null) return NotFound(); |         if (developer is null) return NotFound(); | ||||||
|         var apps = await customApps.GetAppsByPublisherAsync(developer.Id); |          | ||||||
|  |         var project = await projectService.GetProjectAsync(projectId, developer.Id); | ||||||
|  |         if (project is null) return NotFound(); | ||||||
|  |          | ||||||
|  |         var apps = await customApps.GetAppsByProjectAsync(projectId); | ||||||
|         return Ok(apps); |         return Ok(apps); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     [HttpGet("{id:guid}")] |     [HttpGet("{appId:guid}")] | ||||||
|     public async Task<IActionResult> GetApp([FromRoute] string pubName, Guid id) |     public async Task<IActionResult> GetApp([FromRoute] string pubName, [FromRoute] Guid projectId, [FromRoute] Guid appId) | ||||||
|     { |     { | ||||||
|         var developer = await ds.GetDeveloperByName(pubName); |         var developer = await ds.GetDeveloperByName(pubName); | ||||||
|         if (developer is null) return NotFound(); |         if (developer is null) return NotFound(); | ||||||
|  |          | ||||||
|  |         var project = await projectService.GetProjectAsync(projectId, developer.Id); | ||||||
|  |         if (project is null) return NotFound(); | ||||||
|  |  | ||||||
|         var app = await customApps.GetAppAsync(id, developerId: developer.Id); |         var app = await customApps.GetAppAsync(appId, projectId); | ||||||
|         if (app == null) |         if (app == null) | ||||||
|             return NotFound(); |             return NotFound(); | ||||||
|  |  | ||||||
| @@ -44,23 +52,40 @@ public class CustomAppController(CustomAppService customApps, DeveloperService d | |||||||
|  |  | ||||||
|     [HttpPost] |     [HttpPost] | ||||||
|     [Authorize] |     [Authorize] | ||||||
|     public async Task<IActionResult> CreateApp([FromRoute] string pubName, [FromBody] CustomAppRequest request) |     public async Task<IActionResult> CreateApp( | ||||||
|  |         [FromRoute] string pubName,  | ||||||
|  |         [FromRoute] Guid projectId, | ||||||
|  |         [FromBody] CustomAppRequest request) | ||||||
|     { |     { | ||||||
|         if (HttpContext.Items["CurrentUser"] is not Account currentUser) return Unauthorized(); |         if (HttpContext.Items["CurrentUser"] is not Account currentUser)  | ||||||
|  |             return Unauthorized(); | ||||||
|  |  | ||||||
|  |         var developer = await ds.GetDeveloperByName(pubName); | ||||||
|  |         var accountId = Guid.Parse(currentUser.Id); | ||||||
|  |         if (developer is null || developer.Id != accountId) | ||||||
|  |             return Forbid(); | ||||||
|  |              | ||||||
|  |         var project = await projectService.GetProjectAsync(projectId, developer.Id); | ||||||
|  |         if (project is null) | ||||||
|  |             return NotFound("Project not found or you don't have access"); | ||||||
|  |  | ||||||
|         if (string.IsNullOrWhiteSpace(request.Name) || string.IsNullOrWhiteSpace(request.Slug)) |         if (string.IsNullOrWhiteSpace(request.Name) || string.IsNullOrWhiteSpace(request.Slug)) | ||||||
|             return BadRequest("Name and slug are required"); |             return BadRequest("Name and slug are required"); | ||||||
|  |  | ||||||
|         var developer = await ds.GetDeveloperByName(pubName); |  | ||||||
|         if (developer is null) return NotFound(); |  | ||||||
|  |  | ||||||
|         if (!await ds.IsMemberWithRole(developer.PublisherId, Guid.Parse(currentUser.Id), PublisherMemberRole.Editor)) |         if (!await ds.IsMemberWithRole(developer.PublisherId, Guid.Parse(currentUser.Id), PublisherMemberRole.Editor)) | ||||||
|             return StatusCode(403, "You must be an editor of the developer to create a custom app"); |             return StatusCode(403, "You must be an editor of the developer to create a custom app"); | ||||||
|  |  | ||||||
|         try |         try | ||||||
|         { |         { | ||||||
|             var app = await customApps.CreateAppAsync(developer, request); |             var app = await customApps.CreateAppAsync(projectId, request); | ||||||
|             return Ok(app); |             if (app == null) | ||||||
|  |                 return BadRequest("Failed to create app"); | ||||||
|  |                  | ||||||
|  |             return CreatedAtAction( | ||||||
|  |                 nameof(GetApp),  | ||||||
|  |                 new { pubName, projectId, appId = app.Id }, | ||||||
|  |                 app | ||||||
|  |             ); | ||||||
|         } |         } | ||||||
|         catch (InvalidOperationException ex) |         catch (InvalidOperationException ex) | ||||||
|         { |         { | ||||||
| @@ -68,23 +93,30 @@ public class CustomAppController(CustomAppService customApps, DeveloperService d | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     [HttpPatch("{id:guid}")] |     [HttpPatch("{appId:guid}")] | ||||||
|     [Authorize] |     [Authorize] | ||||||
|     public async Task<IActionResult> UpdateApp( |     public async Task<IActionResult> UpdateApp( | ||||||
|         [FromRoute] string pubName, |         [FromRoute] string pubName, | ||||||
|         [FromRoute] Guid id, |         [FromRoute] Guid projectId, | ||||||
|  |         [FromRoute] Guid appId, | ||||||
|         [FromBody] CustomAppRequest request |         [FromBody] CustomAppRequest request | ||||||
|     ) |     ) | ||||||
|     { |     { | ||||||
|         if (HttpContext.Items["CurrentUser"] is not Account currentUser) return Unauthorized(); |         if (HttpContext.Items["CurrentUser"] is not Account currentUser)  | ||||||
|  |             return Unauthorized(); | ||||||
|          |          | ||||||
|         var developer = await ds.GetDeveloperByName(pubName); |         var developer = await ds.GetDeveloperByName(pubName); | ||||||
|         if (developer is null) return NotFound(); |         if (developer is null) | ||||||
|          |             return NotFound("Developer not found"); | ||||||
|  |              | ||||||
|         if (!await ds.IsMemberWithRole(developer.PublisherId, Guid.Parse(currentUser.Id), PublisherMemberRole.Editor)) |         if (!await ds.IsMemberWithRole(developer.PublisherId, Guid.Parse(currentUser.Id), PublisherMemberRole.Editor)) | ||||||
|             return StatusCode(403, "You must be an editor of the developer to update a custom app"); |             return StatusCode(403, "You must be an editor of the developer to update a custom app"); | ||||||
|  |              | ||||||
|  |         var project = await projectService.GetProjectAsync(projectId, developer.Id); | ||||||
|  |         if (project is null) | ||||||
|  |             return NotFound("Project not found or you don't have access"); | ||||||
|  |  | ||||||
|         var app = await customApps.GetAppAsync(id, developerId: developer.Id); |         var app = await customApps.GetAppAsync(appId, projectId); | ||||||
|         if (app == null) |         if (app == null) | ||||||
|             return NotFound(); |             return NotFound(); | ||||||
|  |  | ||||||
| @@ -99,28 +131,36 @@ public class CustomAppController(CustomAppService customApps, DeveloperService d | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     [HttpDelete("{id:guid}")] |     [HttpDelete("{appId:guid}")] | ||||||
|     [Authorize] |     [Authorize] | ||||||
|     public async Task<IActionResult> DeleteApp( |     public async Task<IActionResult> DeleteApp( | ||||||
|         [FromRoute] string pubName, |         [FromRoute] string pubName, | ||||||
|         [FromRoute] Guid id |         [FromRoute] Guid projectId, | ||||||
|  |         [FromRoute] Guid appId | ||||||
|     ) |     ) | ||||||
|     { |     { | ||||||
|         if (HttpContext.Items["CurrentUser"] is not Account currentUser) return Unauthorized(); |         if (HttpContext.Items["CurrentUser"] is not Account currentUser)  | ||||||
|  |             return Unauthorized(); | ||||||
|          |          | ||||||
|         var developer = await ds.GetDeveloperByName(pubName); |         var developer = await ds.GetDeveloperByName(pubName); | ||||||
|         if (developer is null) return NotFound(); |         if (developer is null) | ||||||
|          |             return NotFound("Developer not found"); | ||||||
|  |              | ||||||
|         if (!await ds.IsMemberWithRole(developer.PublisherId, Guid.Parse(currentUser.Id), PublisherMemberRole.Editor)) |         if (!await ds.IsMemberWithRole(developer.PublisherId, Guid.Parse(currentUser.Id), PublisherMemberRole.Editor)) | ||||||
|             return StatusCode(403, "You must be an editor of the developer to delete a custom app"); |             return StatusCode(403, "You must be an editor of the developer to delete a custom app"); | ||||||
|  |              | ||||||
|  |         var project = await projectService.GetProjectAsync(projectId, developer.Id); | ||||||
|  |         if (project is null) | ||||||
|  |             return NotFound("Project not found or you don't have access"); | ||||||
|  |  | ||||||
|         var app = await customApps.GetAppAsync(id, developerId: developer.Id); |         var app = await customApps.GetAppAsync(appId, projectId); | ||||||
|         if (app == null) |         if (app == null) | ||||||
|             return NotFound(); |             return NotFound(); | ||||||
|  |  | ||||||
|         var result = await customApps.DeleteAppAsync(id); |         var result = await customApps.DeleteAppAsync(appId); | ||||||
|         if (!result) |         if (!result) | ||||||
|             return NotFound(); |             return NotFound(); | ||||||
|  |              | ||||||
|         return NoContent(); |         return NoContent(); | ||||||
|     } |     } | ||||||
| } | } | ||||||
| @@ -1,3 +1,4 @@ | |||||||
|  | using DysonNetwork.Develop.Project; | ||||||
| using DysonNetwork.Shared.Data; | using DysonNetwork.Shared.Data; | ||||||
| using DysonNetwork.Shared.Proto; | using DysonNetwork.Shared.Proto; | ||||||
| using Microsoft.EntityFrameworkCore; | using Microsoft.EntityFrameworkCore; | ||||||
| @@ -11,10 +12,17 @@ public class CustomAppService( | |||||||
| ) | ) | ||||||
| { | { | ||||||
|     public async Task<CustomApp?> CreateAppAsync( |     public async Task<CustomApp?> CreateAppAsync( | ||||||
|         Developer pub, |         Guid projectId, | ||||||
|         CustomAppController.CustomAppRequest request |         CustomAppController.CustomAppRequest request | ||||||
|     ) |     ) | ||||||
|     { |     { | ||||||
|  |         var project = await db.DevProjects | ||||||
|  |             .Include(p => p.Developer) | ||||||
|  |             .FirstOrDefaultAsync(p => p.Id == projectId); | ||||||
|  |              | ||||||
|  |         if (project == null) | ||||||
|  |             return null; | ||||||
|  |              | ||||||
|         var app = new CustomApp |         var app = new CustomApp | ||||||
|         { |         { | ||||||
|             Slug = request.Slug!, |             Slug = request.Slug!, | ||||||
| @@ -23,7 +31,7 @@ public class CustomAppService( | |||||||
|             Status = request.Status ?? CustomAppStatus.Developing, |             Status = request.Status ?? CustomAppStatus.Developing, | ||||||
|             Links = request.Links, |             Links = request.Links, | ||||||
|             OauthConfig = request.OauthConfig, |             OauthConfig = request.OauthConfig, | ||||||
|             DeveloperId = pub.Id |             ProjectId = projectId | ||||||
|         }; |         }; | ||||||
|  |  | ||||||
|         if (request.PictureId is not null) |         if (request.PictureId is not null) | ||||||
| @@ -74,17 +82,23 @@ public class CustomAppService( | |||||||
|         return app; |         return app; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     public async Task<CustomApp?> GetAppAsync(Guid id, Guid? developerId = null) |     public async Task<CustomApp?> GetAppAsync(Guid id, Guid? projectId = null) | ||||||
|     { |     { | ||||||
|         var query = db.CustomApps.Where(a => a.Id == id).AsQueryable(); |         var query = db.CustomApps.AsQueryable(); | ||||||
|         if (developerId.HasValue) |          | ||||||
|             query = query.Where(a => a.DeveloperId == developerId.Value); |         if (projectId.HasValue) | ||||||
|         return await query.FirstOrDefaultAsync(); |         { | ||||||
|  |             query = query.Where(a => a.ProjectId == projectId.Value); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         return await query.FirstOrDefaultAsync(a => a.Id == id); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     public async Task<List<CustomApp>> GetAppsByPublisherAsync(Guid publisherId) |     public async Task<List<CustomApp>> GetAppsByProjectAsync(Guid projectId) | ||||||
|     { |     { | ||||||
|         return await db.CustomApps.Where(a => a.DeveloperId == publisherId).ToListAsync(); |         return await db.CustomApps | ||||||
|  |             .Where(a => a.ProjectId == projectId) | ||||||
|  |             .ToListAsync(); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     public async Task<CustomApp?> UpdateAppAsync(CustomApp app, CustomAppController.CustomAppRequest request) |     public async Task<CustomApp?> UpdateAppAsync(CustomApp app, CustomAppController.CustomAppRequest request) | ||||||
|   | |||||||
| @@ -1,4 +1,5 @@ | |||||||
| using System.ComponentModel.DataAnnotations.Schema; | using System.ComponentModel.DataAnnotations.Schema; | ||||||
|  | using DysonNetwork.Develop.Project; | ||||||
| using DysonNetwork.Shared.Proto; | using DysonNetwork.Shared.Proto; | ||||||
| using DysonNetwork.Shared.Data; | using DysonNetwork.Shared.Data; | ||||||
| using VerificationMark = DysonNetwork.Shared.Data.VerificationMark; | using VerificationMark = DysonNetwork.Shared.Data.VerificationMark; | ||||||
| @@ -10,6 +11,8 @@ public class Developer | |||||||
|     public Guid Id { get; set; } = Guid.NewGuid(); |     public Guid Id { get; set; } = Guid.NewGuid(); | ||||||
|     public Guid PublisherId { get; set; } |     public Guid PublisherId { get; set; } | ||||||
|      |      | ||||||
|  |     public List<DevProject> Projects { get; set; } = []; | ||||||
|  |      | ||||||
|     [NotMapped] public PublisherInfo? Publisher { get; set; } |     [NotMapped] public PublisherInfo? Publisher { get; set; } | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -33,7 +33,8 @@ public class DeveloperController( | |||||||
|  |  | ||||||
|         // Get custom apps count |         // Get custom apps count | ||||||
|         var customAppsCount = await db.CustomApps |         var customAppsCount = await db.CustomApps | ||||||
|             .Where(a => a.DeveloperId == developer.Id) |             .Include(a => a.Project) | ||||||
|  |             .Where(a => a.Project.DeveloperId == developer.Id) | ||||||
|             .CountAsync(); |             .CountAsync(); | ||||||
|  |  | ||||||
|         var stats = new DeveloperStats |         var stats = new DeveloperStats | ||||||
|   | |||||||
							
								
								
									
										270
									
								
								DysonNetwork.Develop/Migrations/20250818124844_AddDevProject.Designer.cs
									
									
									
										generated
									
									
									
										Normal file
									
								
							
							
						
						
									
										270
									
								
								DysonNetwork.Develop/Migrations/20250818124844_AddDevProject.Designer.cs
									
									
									
										generated
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,270 @@ | |||||||
|  | // <auto-generated /> | ||||||
|  | using System; | ||||||
|  | using DysonNetwork.Develop; | ||||||
|  | using DysonNetwork.Develop.Identity; | ||||||
|  | using DysonNetwork.Shared.Data; | ||||||
|  | using Microsoft.EntityFrameworkCore; | ||||||
|  | using Microsoft.EntityFrameworkCore.Infrastructure; | ||||||
|  | using Microsoft.EntityFrameworkCore.Migrations; | ||||||
|  | using Microsoft.EntityFrameworkCore.Storage.ValueConversion; | ||||||
|  | using NodaTime; | ||||||
|  | using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; | ||||||
|  |  | ||||||
|  | #nullable disable | ||||||
|  |  | ||||||
|  | namespace DysonNetwork.Develop.Migrations | ||||||
|  | { | ||||||
|  |     [DbContext(typeof(AppDatabase))] | ||||||
|  |     [Migration("20250818124844_AddDevProject")] | ||||||
|  |     partial class AddDevProject | ||||||
|  |     { | ||||||
|  |         /// <inheritdoc /> | ||||||
|  |         protected override void BuildTargetModel(ModelBuilder modelBuilder) | ||||||
|  |         { | ||||||
|  | #pragma warning disable 612, 618 | ||||||
|  |             modelBuilder | ||||||
|  |                 .HasAnnotation("ProductVersion", "9.0.7") | ||||||
|  |                 .HasAnnotation("Relational:MaxIdentifierLength", 63); | ||||||
|  |  | ||||||
|  |             NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); | ||||||
|  |  | ||||||
|  |             modelBuilder.Entity("DysonNetwork.Develop.Identity.CustomApp", b => | ||||||
|  |                 { | ||||||
|  |                     b.Property<Guid>("Id") | ||||||
|  |                         .ValueGeneratedOnAdd() | ||||||
|  |                         .HasColumnType("uuid") | ||||||
|  |                         .HasColumnName("id"); | ||||||
|  |  | ||||||
|  |                     b.Property<CloudFileReferenceObject>("Background") | ||||||
|  |                         .HasColumnType("jsonb") | ||||||
|  |                         .HasColumnName("background"); | ||||||
|  |  | ||||||
|  |                     b.Property<Instant>("CreatedAt") | ||||||
|  |                         .HasColumnType("timestamp with time zone") | ||||||
|  |                         .HasColumnName("created_at"); | ||||||
|  |  | ||||||
|  |                     b.Property<Instant?>("DeletedAt") | ||||||
|  |                         .HasColumnType("timestamp with time zone") | ||||||
|  |                         .HasColumnName("deleted_at"); | ||||||
|  |  | ||||||
|  |                     b.Property<string>("Description") | ||||||
|  |                         .HasMaxLength(4096) | ||||||
|  |                         .HasColumnType("character varying(4096)") | ||||||
|  |                         .HasColumnName("description"); | ||||||
|  |  | ||||||
|  |                     b.Property<CustomAppLinks>("Links") | ||||||
|  |                         .HasColumnType("jsonb") | ||||||
|  |                         .HasColumnName("links"); | ||||||
|  |  | ||||||
|  |                     b.Property<string>("Name") | ||||||
|  |                         .IsRequired() | ||||||
|  |                         .HasMaxLength(1024) | ||||||
|  |                         .HasColumnType("character varying(1024)") | ||||||
|  |                         .HasColumnName("name"); | ||||||
|  |  | ||||||
|  |                     b.Property<CustomAppOauthConfig>("OauthConfig") | ||||||
|  |                         .HasColumnType("jsonb") | ||||||
|  |                         .HasColumnName("oauth_config"); | ||||||
|  |  | ||||||
|  |                     b.Property<CloudFileReferenceObject>("Picture") | ||||||
|  |                         .HasColumnType("jsonb") | ||||||
|  |                         .HasColumnName("picture"); | ||||||
|  |  | ||||||
|  |                     b.Property<Guid>("ProjectId") | ||||||
|  |                         .HasColumnType("uuid") | ||||||
|  |                         .HasColumnName("project_id"); | ||||||
|  |  | ||||||
|  |                     b.Property<string>("Slug") | ||||||
|  |                         .IsRequired() | ||||||
|  |                         .HasMaxLength(1024) | ||||||
|  |                         .HasColumnType("character varying(1024)") | ||||||
|  |                         .HasColumnName("slug"); | ||||||
|  |  | ||||||
|  |                     b.Property<int>("Status") | ||||||
|  |                         .HasColumnType("integer") | ||||||
|  |                         .HasColumnName("status"); | ||||||
|  |  | ||||||
|  |                     b.Property<Instant>("UpdatedAt") | ||||||
|  |                         .HasColumnType("timestamp with time zone") | ||||||
|  |                         .HasColumnName("updated_at"); | ||||||
|  |  | ||||||
|  |                     b.Property<VerificationMark>("Verification") | ||||||
|  |                         .HasColumnType("jsonb") | ||||||
|  |                         .HasColumnName("verification"); | ||||||
|  |  | ||||||
|  |                     b.HasKey("Id") | ||||||
|  |                         .HasName("pk_custom_apps"); | ||||||
|  |  | ||||||
|  |                     b.HasIndex("ProjectId") | ||||||
|  |                         .HasDatabaseName("ix_custom_apps_project_id"); | ||||||
|  |  | ||||||
|  |                     b.ToTable("custom_apps", (string)null); | ||||||
|  |                 }); | ||||||
|  |  | ||||||
|  |             modelBuilder.Entity("DysonNetwork.Develop.Identity.CustomAppSecret", b => | ||||||
|  |                 { | ||||||
|  |                     b.Property<Guid>("Id") | ||||||
|  |                         .ValueGeneratedOnAdd() | ||||||
|  |                         .HasColumnType("uuid") | ||||||
|  |                         .HasColumnName("id"); | ||||||
|  |  | ||||||
|  |                     b.Property<Guid>("AppId") | ||||||
|  |                         .HasColumnType("uuid") | ||||||
|  |                         .HasColumnName("app_id"); | ||||||
|  |  | ||||||
|  |                     b.Property<Instant>("CreatedAt") | ||||||
|  |                         .HasColumnType("timestamp with time zone") | ||||||
|  |                         .HasColumnName("created_at"); | ||||||
|  |  | ||||||
|  |                     b.Property<Instant?>("DeletedAt") | ||||||
|  |                         .HasColumnType("timestamp with time zone") | ||||||
|  |                         .HasColumnName("deleted_at"); | ||||||
|  |  | ||||||
|  |                     b.Property<string>("Description") | ||||||
|  |                         .HasMaxLength(4096) | ||||||
|  |                         .HasColumnType("character varying(4096)") | ||||||
|  |                         .HasColumnName("description"); | ||||||
|  |  | ||||||
|  |                     b.Property<Instant?>("ExpiredAt") | ||||||
|  |                         .HasColumnType("timestamp with time zone") | ||||||
|  |                         .HasColumnName("expired_at"); | ||||||
|  |  | ||||||
|  |                     b.Property<bool>("IsOidc") | ||||||
|  |                         .HasColumnType("boolean") | ||||||
|  |                         .HasColumnName("is_oidc"); | ||||||
|  |  | ||||||
|  |                     b.Property<string>("Secret") | ||||||
|  |                         .IsRequired() | ||||||
|  |                         .HasMaxLength(1024) | ||||||
|  |                         .HasColumnType("character varying(1024)") | ||||||
|  |                         .HasColumnName("secret"); | ||||||
|  |  | ||||||
|  |                     b.Property<Instant>("UpdatedAt") | ||||||
|  |                         .HasColumnType("timestamp with time zone") | ||||||
|  |                         .HasColumnName("updated_at"); | ||||||
|  |  | ||||||
|  |                     b.HasKey("Id") | ||||||
|  |                         .HasName("pk_custom_app_secrets"); | ||||||
|  |  | ||||||
|  |                     b.HasIndex("AppId") | ||||||
|  |                         .HasDatabaseName("ix_custom_app_secrets_app_id"); | ||||||
|  |  | ||||||
|  |                     b.ToTable("custom_app_secrets", (string)null); | ||||||
|  |                 }); | ||||||
|  |  | ||||||
|  |             modelBuilder.Entity("DysonNetwork.Develop.Identity.Developer", b => | ||||||
|  |                 { | ||||||
|  |                     b.Property<Guid>("Id") | ||||||
|  |                         .ValueGeneratedOnAdd() | ||||||
|  |                         .HasColumnType("uuid") | ||||||
|  |                         .HasColumnName("id"); | ||||||
|  |  | ||||||
|  |                     b.Property<Guid>("PublisherId") | ||||||
|  |                         .HasColumnType("uuid") | ||||||
|  |                         .HasColumnName("publisher_id"); | ||||||
|  |  | ||||||
|  |                     b.HasKey("Id") | ||||||
|  |                         .HasName("pk_developers"); | ||||||
|  |  | ||||||
|  |                     b.ToTable("developers", (string)null); | ||||||
|  |                 }); | ||||||
|  |  | ||||||
|  |             modelBuilder.Entity("DysonNetwork.Develop.Project.DevProject", b => | ||||||
|  |                 { | ||||||
|  |                     b.Property<Guid>("Id") | ||||||
|  |                         .ValueGeneratedOnAdd() | ||||||
|  |                         .HasColumnType("uuid") | ||||||
|  |                         .HasColumnName("id"); | ||||||
|  |  | ||||||
|  |                     b.Property<Instant>("CreatedAt") | ||||||
|  |                         .HasColumnType("timestamp with time zone") | ||||||
|  |                         .HasColumnName("created_at"); | ||||||
|  |  | ||||||
|  |                     b.Property<Instant?>("DeletedAt") | ||||||
|  |                         .HasColumnType("timestamp with time zone") | ||||||
|  |                         .HasColumnName("deleted_at"); | ||||||
|  |  | ||||||
|  |                     b.Property<string>("Description") | ||||||
|  |                         .IsRequired() | ||||||
|  |                         .HasMaxLength(4096) | ||||||
|  |                         .HasColumnType("character varying(4096)") | ||||||
|  |                         .HasColumnName("description"); | ||||||
|  |  | ||||||
|  |                     b.Property<Guid>("DeveloperId") | ||||||
|  |                         .HasColumnType("uuid") | ||||||
|  |                         .HasColumnName("developer_id"); | ||||||
|  |  | ||||||
|  |                     b.Property<string>("Name") | ||||||
|  |                         .IsRequired() | ||||||
|  |                         .HasMaxLength(1024) | ||||||
|  |                         .HasColumnType("character varying(1024)") | ||||||
|  |                         .HasColumnName("name"); | ||||||
|  |  | ||||||
|  |                     b.Property<string>("Slug") | ||||||
|  |                         .IsRequired() | ||||||
|  |                         .HasMaxLength(1024) | ||||||
|  |                         .HasColumnType("character varying(1024)") | ||||||
|  |                         .HasColumnName("slug"); | ||||||
|  |  | ||||||
|  |                     b.Property<Instant>("UpdatedAt") | ||||||
|  |                         .HasColumnType("timestamp with time zone") | ||||||
|  |                         .HasColumnName("updated_at"); | ||||||
|  |  | ||||||
|  |                     b.HasKey("Id") | ||||||
|  |                         .HasName("pk_dev_projects"); | ||||||
|  |  | ||||||
|  |                     b.HasIndex("DeveloperId") | ||||||
|  |                         .HasDatabaseName("ix_dev_projects_developer_id"); | ||||||
|  |  | ||||||
|  |                     b.ToTable("dev_projects", (string)null); | ||||||
|  |                 }); | ||||||
|  |  | ||||||
|  |             modelBuilder.Entity("DysonNetwork.Develop.Identity.CustomApp", b => | ||||||
|  |                 { | ||||||
|  |                     b.HasOne("DysonNetwork.Develop.Project.DevProject", "Project") | ||||||
|  |                         .WithMany() | ||||||
|  |                         .HasForeignKey("ProjectId") | ||||||
|  |                         .OnDelete(DeleteBehavior.Cascade) | ||||||
|  |                         .IsRequired() | ||||||
|  |                         .HasConstraintName("fk_custom_apps_dev_projects_project_id"); | ||||||
|  |  | ||||||
|  |                     b.Navigation("Project"); | ||||||
|  |                 }); | ||||||
|  |  | ||||||
|  |             modelBuilder.Entity("DysonNetwork.Develop.Identity.CustomAppSecret", b => | ||||||
|  |                 { | ||||||
|  |                     b.HasOne("DysonNetwork.Develop.Identity.CustomApp", "App") | ||||||
|  |                         .WithMany("Secrets") | ||||||
|  |                         .HasForeignKey("AppId") | ||||||
|  |                         .OnDelete(DeleteBehavior.Cascade) | ||||||
|  |                         .IsRequired() | ||||||
|  |                         .HasConstraintName("fk_custom_app_secrets_custom_apps_app_id"); | ||||||
|  |  | ||||||
|  |                     b.Navigation("App"); | ||||||
|  |                 }); | ||||||
|  |  | ||||||
|  |             modelBuilder.Entity("DysonNetwork.Develop.Project.DevProject", b => | ||||||
|  |                 { | ||||||
|  |                     b.HasOne("DysonNetwork.Develop.Identity.Developer", "Developer") | ||||||
|  |                         .WithMany("Projects") | ||||||
|  |                         .HasForeignKey("DeveloperId") | ||||||
|  |                         .OnDelete(DeleteBehavior.Cascade) | ||||||
|  |                         .IsRequired() | ||||||
|  |                         .HasConstraintName("fk_dev_projects_developers_developer_id"); | ||||||
|  |  | ||||||
|  |                     b.Navigation("Developer"); | ||||||
|  |                 }); | ||||||
|  |  | ||||||
|  |             modelBuilder.Entity("DysonNetwork.Develop.Identity.CustomApp", b => | ||||||
|  |                 { | ||||||
|  |                     b.Navigation("Secrets"); | ||||||
|  |                 }); | ||||||
|  |  | ||||||
|  |             modelBuilder.Entity("DysonNetwork.Develop.Identity.Developer", b => | ||||||
|  |                 { | ||||||
|  |                     b.Navigation("Projects"); | ||||||
|  |                 }); | ||||||
|  | #pragma warning restore 612, 618 | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
| @@ -0,0 +1,96 @@ | |||||||
|  | using System; | ||||||
|  | using Microsoft.EntityFrameworkCore.Migrations; | ||||||
|  | using NodaTime; | ||||||
|  |  | ||||||
|  | #nullable disable | ||||||
|  |  | ||||||
|  | namespace DysonNetwork.Develop.Migrations | ||||||
|  | { | ||||||
|  |     /// <inheritdoc /> | ||||||
|  |     public partial class AddDevProject : Migration | ||||||
|  |     { | ||||||
|  |         /// <inheritdoc /> | ||||||
|  |         protected override void Up(MigrationBuilder migrationBuilder) | ||||||
|  |         { | ||||||
|  |             migrationBuilder.DropForeignKey( | ||||||
|  |                 name: "fk_custom_apps_developers_developer_id", | ||||||
|  |                 table: "custom_apps"); | ||||||
|  |  | ||||||
|  |             migrationBuilder.RenameColumn( | ||||||
|  |                 name: "developer_id", | ||||||
|  |                 table: "custom_apps", | ||||||
|  |                 newName: "project_id"); | ||||||
|  |  | ||||||
|  |             migrationBuilder.RenameIndex( | ||||||
|  |                 name: "ix_custom_apps_developer_id", | ||||||
|  |                 table: "custom_apps", | ||||||
|  |                 newName: "ix_custom_apps_project_id"); | ||||||
|  |  | ||||||
|  |             migrationBuilder.CreateTable( | ||||||
|  |                 name: "dev_projects", | ||||||
|  |                 columns: table => new | ||||||
|  |                 { | ||||||
|  |                     id = table.Column<Guid>(type: "uuid", nullable: false), | ||||||
|  |                     slug = table.Column<string>(type: "character varying(1024)", maxLength: 1024, nullable: false), | ||||||
|  |                     name = table.Column<string>(type: "character varying(1024)", maxLength: 1024, nullable: false), | ||||||
|  |                     description = table.Column<string>(type: "character varying(4096)", maxLength: 4096, nullable: false), | ||||||
|  |                     developer_id = table.Column<Guid>(type: "uuid", nullable: false), | ||||||
|  |                     created_at = table.Column<Instant>(type: "timestamp with time zone", nullable: false), | ||||||
|  |                     updated_at = table.Column<Instant>(type: "timestamp with time zone", nullable: false), | ||||||
|  |                     deleted_at = table.Column<Instant>(type: "timestamp with time zone", nullable: true) | ||||||
|  |                 }, | ||||||
|  |                 constraints: table => | ||||||
|  |                 { | ||||||
|  |                     table.PrimaryKey("pk_dev_projects", x => x.id); | ||||||
|  |                     table.ForeignKey( | ||||||
|  |                         name: "fk_dev_projects_developers_developer_id", | ||||||
|  |                         column: x => x.developer_id, | ||||||
|  |                         principalTable: "developers", | ||||||
|  |                         principalColumn: "id", | ||||||
|  |                         onDelete: ReferentialAction.Cascade); | ||||||
|  |                 }); | ||||||
|  |  | ||||||
|  |             migrationBuilder.CreateIndex( | ||||||
|  |                 name: "ix_dev_projects_developer_id", | ||||||
|  |                 table: "dev_projects", | ||||||
|  |                 column: "developer_id"); | ||||||
|  |  | ||||||
|  |             migrationBuilder.AddForeignKey( | ||||||
|  |                 name: "fk_custom_apps_dev_projects_project_id", | ||||||
|  |                 table: "custom_apps", | ||||||
|  |                 column: "project_id", | ||||||
|  |                 principalTable: "dev_projects", | ||||||
|  |                 principalColumn: "id", | ||||||
|  |                 onDelete: ReferentialAction.Cascade); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         /// <inheritdoc /> | ||||||
|  |         protected override void Down(MigrationBuilder migrationBuilder) | ||||||
|  |         { | ||||||
|  |             migrationBuilder.DropForeignKey( | ||||||
|  |                 name: "fk_custom_apps_dev_projects_project_id", | ||||||
|  |                 table: "custom_apps"); | ||||||
|  |  | ||||||
|  |             migrationBuilder.DropTable( | ||||||
|  |                 name: "dev_projects"); | ||||||
|  |  | ||||||
|  |             migrationBuilder.RenameColumn( | ||||||
|  |                 name: "project_id", | ||||||
|  |                 table: "custom_apps", | ||||||
|  |                 newName: "developer_id"); | ||||||
|  |  | ||||||
|  |             migrationBuilder.RenameIndex( | ||||||
|  |                 name: "ix_custom_apps_project_id", | ||||||
|  |                 table: "custom_apps", | ||||||
|  |                 newName: "ix_custom_apps_developer_id"); | ||||||
|  |  | ||||||
|  |             migrationBuilder.AddForeignKey( | ||||||
|  |                 name: "fk_custom_apps_developers_developer_id", | ||||||
|  |                 table: "custom_apps", | ||||||
|  |                 column: "developer_id", | ||||||
|  |                 principalTable: "developers", | ||||||
|  |                 principalColumn: "id", | ||||||
|  |                 onDelete: ReferentialAction.Cascade); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
| @@ -49,10 +49,6 @@ namespace DysonNetwork.Develop.Migrations | |||||||
|                         .HasColumnType("character varying(4096)") |                         .HasColumnType("character varying(4096)") | ||||||
|                         .HasColumnName("description"); |                         .HasColumnName("description"); | ||||||
|  |  | ||||||
|                     b.Property<Guid>("DeveloperId") |  | ||||||
|                         .HasColumnType("uuid") |  | ||||||
|                         .HasColumnName("developer_id"); |  | ||||||
|  |  | ||||||
|                     b.Property<CustomAppLinks>("Links") |                     b.Property<CustomAppLinks>("Links") | ||||||
|                         .HasColumnType("jsonb") |                         .HasColumnType("jsonb") | ||||||
|                         .HasColumnName("links"); |                         .HasColumnName("links"); | ||||||
| @@ -71,6 +67,10 @@ namespace DysonNetwork.Develop.Migrations | |||||||
|                         .HasColumnType("jsonb") |                         .HasColumnType("jsonb") | ||||||
|                         .HasColumnName("picture"); |                         .HasColumnName("picture"); | ||||||
|  |  | ||||||
|  |                     b.Property<Guid>("ProjectId") | ||||||
|  |                         .HasColumnType("uuid") | ||||||
|  |                         .HasColumnName("project_id"); | ||||||
|  |  | ||||||
|                     b.Property<string>("Slug") |                     b.Property<string>("Slug") | ||||||
|                         .IsRequired() |                         .IsRequired() | ||||||
|                         .HasMaxLength(1024) |                         .HasMaxLength(1024) | ||||||
| @@ -92,8 +92,8 @@ namespace DysonNetwork.Develop.Migrations | |||||||
|                     b.HasKey("Id") |                     b.HasKey("Id") | ||||||
|                         .HasName("pk_custom_apps"); |                         .HasName("pk_custom_apps"); | ||||||
|  |  | ||||||
|                     b.HasIndex("DeveloperId") |                     b.HasIndex("ProjectId") | ||||||
|                         .HasDatabaseName("ix_custom_apps_developer_id"); |                         .HasDatabaseName("ix_custom_apps_project_id"); | ||||||
|  |  | ||||||
|                     b.ToTable("custom_apps", (string)null); |                     b.ToTable("custom_apps", (string)null); | ||||||
|                 }); |                 }); | ||||||
| @@ -166,16 +166,66 @@ namespace DysonNetwork.Develop.Migrations | |||||||
|                     b.ToTable("developers", (string)null); |                     b.ToTable("developers", (string)null); | ||||||
|                 }); |                 }); | ||||||
|  |  | ||||||
|  |             modelBuilder.Entity("DysonNetwork.Develop.Project.DevProject", b => | ||||||
|  |                 { | ||||||
|  |                     b.Property<Guid>("Id") | ||||||
|  |                         .ValueGeneratedOnAdd() | ||||||
|  |                         .HasColumnType("uuid") | ||||||
|  |                         .HasColumnName("id"); | ||||||
|  |  | ||||||
|  |                     b.Property<Instant>("CreatedAt") | ||||||
|  |                         .HasColumnType("timestamp with time zone") | ||||||
|  |                         .HasColumnName("created_at"); | ||||||
|  |  | ||||||
|  |                     b.Property<Instant?>("DeletedAt") | ||||||
|  |                         .HasColumnType("timestamp with time zone") | ||||||
|  |                         .HasColumnName("deleted_at"); | ||||||
|  |  | ||||||
|  |                     b.Property<string>("Description") | ||||||
|  |                         .IsRequired() | ||||||
|  |                         .HasMaxLength(4096) | ||||||
|  |                         .HasColumnType("character varying(4096)") | ||||||
|  |                         .HasColumnName("description"); | ||||||
|  |  | ||||||
|  |                     b.Property<Guid>("DeveloperId") | ||||||
|  |                         .HasColumnType("uuid") | ||||||
|  |                         .HasColumnName("developer_id"); | ||||||
|  |  | ||||||
|  |                     b.Property<string>("Name") | ||||||
|  |                         .IsRequired() | ||||||
|  |                         .HasMaxLength(1024) | ||||||
|  |                         .HasColumnType("character varying(1024)") | ||||||
|  |                         .HasColumnName("name"); | ||||||
|  |  | ||||||
|  |                     b.Property<string>("Slug") | ||||||
|  |                         .IsRequired() | ||||||
|  |                         .HasMaxLength(1024) | ||||||
|  |                         .HasColumnType("character varying(1024)") | ||||||
|  |                         .HasColumnName("slug"); | ||||||
|  |  | ||||||
|  |                     b.Property<Instant>("UpdatedAt") | ||||||
|  |                         .HasColumnType("timestamp with time zone") | ||||||
|  |                         .HasColumnName("updated_at"); | ||||||
|  |  | ||||||
|  |                     b.HasKey("Id") | ||||||
|  |                         .HasName("pk_dev_projects"); | ||||||
|  |  | ||||||
|  |                     b.HasIndex("DeveloperId") | ||||||
|  |                         .HasDatabaseName("ix_dev_projects_developer_id"); | ||||||
|  |  | ||||||
|  |                     b.ToTable("dev_projects", (string)null); | ||||||
|  |                 }); | ||||||
|  |  | ||||||
|             modelBuilder.Entity("DysonNetwork.Develop.Identity.CustomApp", b => |             modelBuilder.Entity("DysonNetwork.Develop.Identity.CustomApp", b => | ||||||
|                 { |                 { | ||||||
|                     b.HasOne("DysonNetwork.Develop.Identity.Developer", "Developer") |                     b.HasOne("DysonNetwork.Develop.Project.DevProject", "Project") | ||||||
|                         .WithMany() |                         .WithMany() | ||||||
|                         .HasForeignKey("DeveloperId") |                         .HasForeignKey("ProjectId") | ||||||
|                         .OnDelete(DeleteBehavior.Cascade) |                         .OnDelete(DeleteBehavior.Cascade) | ||||||
|                         .IsRequired() |                         .IsRequired() | ||||||
|                         .HasConstraintName("fk_custom_apps_developers_developer_id"); |                         .HasConstraintName("fk_custom_apps_dev_projects_project_id"); | ||||||
|  |  | ||||||
|                     b.Navigation("Developer"); |                     b.Navigation("Project"); | ||||||
|                 }); |                 }); | ||||||
|  |  | ||||||
|             modelBuilder.Entity("DysonNetwork.Develop.Identity.CustomAppSecret", b => |             modelBuilder.Entity("DysonNetwork.Develop.Identity.CustomAppSecret", b => | ||||||
| @@ -190,10 +240,27 @@ namespace DysonNetwork.Develop.Migrations | |||||||
|                     b.Navigation("App"); |                     b.Navigation("App"); | ||||||
|                 }); |                 }); | ||||||
|  |  | ||||||
|  |             modelBuilder.Entity("DysonNetwork.Develop.Project.DevProject", b => | ||||||
|  |                 { | ||||||
|  |                     b.HasOne("DysonNetwork.Develop.Identity.Developer", "Developer") | ||||||
|  |                         .WithMany("Projects") | ||||||
|  |                         .HasForeignKey("DeveloperId") | ||||||
|  |                         .OnDelete(DeleteBehavior.Cascade) | ||||||
|  |                         .IsRequired() | ||||||
|  |                         .HasConstraintName("fk_dev_projects_developers_developer_id"); | ||||||
|  |  | ||||||
|  |                     b.Navigation("Developer"); | ||||||
|  |                 }); | ||||||
|  |  | ||||||
|             modelBuilder.Entity("DysonNetwork.Develop.Identity.CustomApp", b => |             modelBuilder.Entity("DysonNetwork.Develop.Identity.CustomApp", b => | ||||||
|                 { |                 { | ||||||
|                     b.Navigation("Secrets"); |                     b.Navigation("Secrets"); | ||||||
|                 }); |                 }); | ||||||
|  |  | ||||||
|  |             modelBuilder.Entity("DysonNetwork.Develop.Identity.Developer", b => | ||||||
|  |                 { | ||||||
|  |                     b.Navigation("Projects"); | ||||||
|  |                 }); | ||||||
| #pragma warning restore 612, 618 | #pragma warning restore 612, 618 | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|   | |||||||
							
								
								
									
										16
									
								
								DysonNetwork.Develop/Project/DevProject.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								DysonNetwork.Develop/Project/DevProject.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,16 @@ | |||||||
|  | using System.ComponentModel.DataAnnotations; | ||||||
|  | using DysonNetwork.Develop.Identity; | ||||||
|  | using DysonNetwork.Shared.Data; | ||||||
|  |  | ||||||
|  | namespace DysonNetwork.Develop.Project; | ||||||
|  |  | ||||||
|  | public class DevProject : ModelBase | ||||||
|  | { | ||||||
|  |     public Guid Id { get; set; } = Guid.NewGuid(); | ||||||
|  |     [MaxLength(1024)] public string Slug { get; set; } = string.Empty; | ||||||
|  |     [MaxLength(1024)] public string Name { get; set; } = string.Empty; | ||||||
|  |     [MaxLength(4096)] public string Description { get; set; } = string.Empty; | ||||||
|  |      | ||||||
|  |     public Developer Developer { get; set; } = null!; | ||||||
|  |     public Guid DeveloperId { get; set; } | ||||||
|  | } | ||||||
							
								
								
									
										107
									
								
								DysonNetwork.Develop/Project/DevProjectController.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										107
									
								
								DysonNetwork.Develop/Project/DevProjectController.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,107 @@ | |||||||
|  | using System.ComponentModel.DataAnnotations; | ||||||
|  | using DysonNetwork.Develop.Identity; | ||||||
|  | using Microsoft.AspNetCore.Authorization; | ||||||
|  | using Microsoft.AspNetCore.Mvc; | ||||||
|  | using DysonNetwork.Shared.Proto; | ||||||
|  |  | ||||||
|  | namespace DysonNetwork.Develop.Project; | ||||||
|  |  | ||||||
|  | [ApiController] | ||||||
|  | [Route("/api/developers/{pubName}/projects")] | ||||||
|  | public class DevProjectController(DevProjectService projectService, DeveloperService developerService) : ControllerBase | ||||||
|  | { | ||||||
|  |     public record DevProjectRequest( | ||||||
|  |         [MaxLength(1024)] string? Slug, | ||||||
|  |         [MaxLength(1024)] string? Name, | ||||||
|  |         [MaxLength(4096)] string? Description | ||||||
|  |     ); | ||||||
|  |  | ||||||
|  |     [HttpGet] | ||||||
|  |     public async Task<IActionResult> ListProjects([FromRoute] string pubName) | ||||||
|  |     { | ||||||
|  |         var developer = await developerService.GetDeveloperByName(pubName); | ||||||
|  |         if (developer is null) return NotFound(); | ||||||
|  |          | ||||||
|  |         var projects = await projectService.GetProjectsByDeveloperAsync(developer.Id); | ||||||
|  |         return Ok(projects); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     [HttpGet("{id:guid}")] | ||||||
|  |     public async Task<IActionResult> GetProject([FromRoute] string pubName, Guid id) | ||||||
|  |     { | ||||||
|  |         var developer = await developerService.GetDeveloperByName(pubName); | ||||||
|  |         if (developer is null) return NotFound(); | ||||||
|  |  | ||||||
|  |         var project = await projectService.GetProjectAsync(id, developer.Id); | ||||||
|  |         if (project is null) return NotFound(); | ||||||
|  |  | ||||||
|  |         return Ok(project); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     [HttpPost] | ||||||
|  |     [Authorize] | ||||||
|  |     public async Task<IActionResult> CreateProject([FromRoute] string pubName, [FromBody] DevProjectRequest request) | ||||||
|  |     { | ||||||
|  |         if (HttpContext.Items["CurrentUser"] is not Account currentUser)  | ||||||
|  |             return Unauthorized(); | ||||||
|  |  | ||||||
|  |         var developer = await developerService.GetDeveloperByName(pubName); | ||||||
|  |         if (developer is null) | ||||||
|  |             return NotFound("Developer not found"); | ||||||
|  |              | ||||||
|  |         if (!await developerService.IsMemberWithRole(developer.PublisherId, Guid.Parse(currentUser.Id), PublisherMemberRole.Editor)) | ||||||
|  |             return StatusCode(403, "You must be an editor of the developer to create a project"); | ||||||
|  |  | ||||||
|  |         if (string.IsNullOrWhiteSpace(request.Slug) || string.IsNullOrWhiteSpace(request.Name)) | ||||||
|  |             return BadRequest("Slug and Name are required"); | ||||||
|  |  | ||||||
|  |         var project = await projectService.CreateProjectAsync(developer, request); | ||||||
|  |         return CreatedAtAction( | ||||||
|  |             nameof(GetProject),  | ||||||
|  |             new { pubName, id = project.Id }, | ||||||
|  |             project | ||||||
|  |         ); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     [HttpPut("{id:guid}")] | ||||||
|  |     [Authorize] | ||||||
|  |     public async Task<IActionResult> UpdateProject( | ||||||
|  |         [FromRoute] string pubName,  | ||||||
|  |         [FromRoute] Guid id, | ||||||
|  |         [FromBody] DevProjectRequest request | ||||||
|  |     ) | ||||||
|  |     { | ||||||
|  |         if (HttpContext.Items["CurrentUser"] is not Account currentUser)  | ||||||
|  |             return Unauthorized(); | ||||||
|  |  | ||||||
|  |         var developer = await developerService.GetDeveloperByName(pubName); | ||||||
|  |         var accountId = Guid.Parse(currentUser.Id); | ||||||
|  |         if (developer is null || developer.Id != accountId) | ||||||
|  |             return Forbid(); | ||||||
|  |  | ||||||
|  |         var project = await projectService.UpdateProjectAsync(id, developer.Id, request); | ||||||
|  |         if (project is null) | ||||||
|  |             return NotFound(); | ||||||
|  |  | ||||||
|  |         return Ok(project); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     [HttpDelete("{id:guid}")] | ||||||
|  |     [Authorize] | ||||||
|  |     public async Task<IActionResult> DeleteProject([FromRoute] string pubName, [FromRoute] Guid id) | ||||||
|  |     { | ||||||
|  |         if (HttpContext.Items["CurrentUser"] is not Account currentUser)  | ||||||
|  |             return Unauthorized(); | ||||||
|  |  | ||||||
|  |         var developer = await developerService.GetDeveloperByName(pubName); | ||||||
|  |         var accountId = Guid.Parse(currentUser.Id); | ||||||
|  |         if (developer is null || developer.Id != accountId) | ||||||
|  |             return Forbid(); | ||||||
|  |  | ||||||
|  |         var success = await projectService.DeleteProjectAsync(id, developer.Id); | ||||||
|  |         if (!success) | ||||||
|  |             return NotFound(); | ||||||
|  |  | ||||||
|  |         return NoContent(); | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										77
									
								
								DysonNetwork.Develop/Project/DevProjectService.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										77
									
								
								DysonNetwork.Develop/Project/DevProjectService.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,77 @@ | |||||||
|  | using DysonNetwork.Develop.Identity; | ||||||
|  | using Microsoft.EntityFrameworkCore; | ||||||
|  | using DysonNetwork.Shared.Proto; | ||||||
|  |  | ||||||
|  | namespace DysonNetwork.Develop.Project; | ||||||
|  |  | ||||||
|  | public class DevProjectService( | ||||||
|  |     AppDatabase db, | ||||||
|  |     FileReferenceService.FileReferenceServiceClient fileRefs, | ||||||
|  |     FileService.FileServiceClient files | ||||||
|  | ) | ||||||
|  | { | ||||||
|  |     public async Task<DevProject> CreateProjectAsync( | ||||||
|  |         Developer developer, | ||||||
|  |         DevProjectController.DevProjectRequest request | ||||||
|  |     ) | ||||||
|  |     { | ||||||
|  |         var project = new DevProject | ||||||
|  |         { | ||||||
|  |             Slug = request.Slug!, | ||||||
|  |             Name = request.Name!, | ||||||
|  |             Description = request.Description ?? string.Empty, | ||||||
|  |             DeveloperId = developer.Id | ||||||
|  |         }; | ||||||
|  |  | ||||||
|  |         db.DevProjects.Add(project); | ||||||
|  |         await db.SaveChangesAsync(); | ||||||
|  |          | ||||||
|  |         return project; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public async Task<DevProject?> GetProjectAsync(Guid id, Guid? developerId = null) | ||||||
|  |     { | ||||||
|  |         var query = db.DevProjects.AsQueryable(); | ||||||
|  |          | ||||||
|  |         if (developerId.HasValue) | ||||||
|  |         { | ||||||
|  |             query = query.Where(p => p.DeveloperId == developerId.Value); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         return await query.FirstOrDefaultAsync(p => p.Id == id); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public async Task<List<DevProject>> GetProjectsByDeveloperAsync(Guid developerId) | ||||||
|  |     { | ||||||
|  |         return await db.DevProjects | ||||||
|  |             .Where(p => p.DeveloperId == developerId) | ||||||
|  |             .ToListAsync(); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public async Task<DevProject?> UpdateProjectAsync( | ||||||
|  |         Guid id, | ||||||
|  |         Guid developerId, | ||||||
|  |         DevProjectController.DevProjectRequest request | ||||||
|  |     ) | ||||||
|  |     { | ||||||
|  |         var project = await GetProjectAsync(id, developerId); | ||||||
|  |         if (project == null) return null; | ||||||
|  |  | ||||||
|  |         if (request.Slug != null) project.Slug = request.Slug; | ||||||
|  |         if (request.Name != null) project.Name = request.Name; | ||||||
|  |         if (request.Description != null) project.Description = request.Description; | ||||||
|  |  | ||||||
|  |         await db.SaveChangesAsync(); | ||||||
|  |         return project; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public async Task<bool> DeleteProjectAsync(Guid id, Guid developerId) | ||||||
|  |     { | ||||||
|  |         var project = await GetProjectAsync(id, developerId); | ||||||
|  |         if (project == null) return false; | ||||||
|  |  | ||||||
|  |         db.DevProjects.Remove(project); | ||||||
|  |         await db.SaveChangesAsync(); | ||||||
|  |         return true; | ||||||
|  |     } | ||||||
|  | } | ||||||
| @@ -4,6 +4,7 @@ using NodaTime; | |||||||
| using NodaTime.Serialization.SystemTextJson; | using NodaTime.Serialization.SystemTextJson; | ||||||
| using System.Text.Json; | using System.Text.Json; | ||||||
| using DysonNetwork.Develop.Identity; | using DysonNetwork.Develop.Identity; | ||||||
|  | using DysonNetwork.Develop.Project; | ||||||
| using DysonNetwork.Shared.Cache; | using DysonNetwork.Shared.Cache; | ||||||
| using StackExchange.Redis; | using StackExchange.Redis; | ||||||
|  |  | ||||||
| @@ -50,6 +51,7 @@ public static class ServiceCollectionExtensions | |||||||
|  |  | ||||||
|         services.AddScoped<DeveloperService>(); |         services.AddScoped<DeveloperService>(); | ||||||
|         services.AddScoped<CustomAppService>(); |         services.AddScoped<CustomAppService>(); | ||||||
|  |         services.AddScoped<DevProjectService>(); | ||||||
|  |  | ||||||
|         return services; |         return services; | ||||||
|     } |     } | ||||||
|   | |||||||
| @@ -2,6 +2,7 @@ using System.Net.Security; | |||||||
| using System.Security.Cryptography.X509Certificates; | using System.Security.Cryptography.X509Certificates; | ||||||
| using DysonNetwork.Shared.Registry; | using DysonNetwork.Shared.Registry; | ||||||
| using Yarp.ReverseProxy.Configuration; | using Yarp.ReverseProxy.Configuration; | ||||||
|  | using Yarp.ReverseProxy.Transforms; | ||||||
|  |  | ||||||
| namespace DysonNetwork.Gateway.Startup; | namespace DysonNetwork.Gateway.Startup; | ||||||
|  |  | ||||||
| @@ -15,11 +16,15 @@ public static class ServiceCollectionExtensions | |||||||
|             .AddReverseProxy() |             .AddReverseProxy() | ||||||
|             .ConfigureHttpClient((context, handler) => |             .ConfigureHttpClient((context, handler) => | ||||||
|             { |             { | ||||||
|                 var caCert = X509CertificateLoader.LoadCertificateFromFile(configuration["CaCert"]!); |                 // var caCert = X509CertificateLoader.LoadCertificateFromFile(configuration["CaCert"]!); | ||||||
|                 handler.SslOptions = new SslClientAuthenticationOptions |                 handler.SslOptions = new SslClientAuthenticationOptions | ||||||
|                 { |                 { | ||||||
|                     RemoteCertificateValidationCallback = (sender, cert, chain, errors) => true |                     RemoteCertificateValidationCallback = (sender, cert, chain, errors) => true | ||||||
|                 }; |                 }; | ||||||
|  |             }) | ||||||
|  |             .AddTransforms(context => | ||||||
|  |             { | ||||||
|  |                 context.AddForwarded(); | ||||||
|             }); |             }); | ||||||
|  |  | ||||||
|         services.AddRegistryService(configuration, addForwarder: false); |         services.AddRegistryService(configuration, addForwarder: false); | ||||||
|   | |||||||
| @@ -39,7 +39,7 @@ enum CustomAppStatus { | |||||||
|   bytes links = 9; |   bytes links = 9; | ||||||
|   CustomAppOauthConfig oauth_config = 13; |   CustomAppOauthConfig oauth_config = 13; | ||||||
|  |  | ||||||
|   string developer_id = 10; |   string project_id = 10; | ||||||
|  |  | ||||||
|   google.protobuf.Timestamp created_at = 11; |   google.protobuf.Timestamp created_at = 11; | ||||||
|   google.protobuf.Timestamp updated_at = 12; |   google.protobuf.Timestamp updated_at = 12; | ||||||
|   | |||||||
| @@ -57,6 +57,7 @@ | |||||||
| 	<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AFileResult_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003FLibrary_003FApplication_0020Support_003FJetBrains_003FRider2024_002E3_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F0b5acdd962e549369896cece0026e556214600_003F8c_003F9f6e3f4f_003FFileResult_002Ecs/@EntryIndexedValue">ForceIncluded</s:String> | 	<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AFileResult_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003FLibrary_003FApplication_0020Support_003FJetBrains_003FRider2024_002E3_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F0b5acdd962e549369896cece0026e556214600_003F8c_003F9f6e3f4f_003FFileResult_002Ecs/@EntryIndexedValue">ForceIncluded</s:String> | ||||||
| 	<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AFirebaseSender_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003FLibrary_003FApplication_0020Support_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F6aadc2cf048f477d8636fb2def7b73648200_003F5c_003F1f5bca3f_003FFirebaseSender_002Ecs/@EntryIndexedValue">ForceIncluded</s:String> | 	<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AFirebaseSender_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003FLibrary_003FApplication_0020Support_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F6aadc2cf048f477d8636fb2def7b73648200_003F5c_003F1f5bca3f_003FFirebaseSender_002Ecs/@EntryIndexedValue">ForceIncluded</s:String> | ||||||
| 	<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AForwardedHeaders_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003FLibrary_003FApplication_0020Support_003FJetBrains_003FRider2024_002E3_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003Fcfe5737f9bb84738979cbfedd11822a8ea00_003F50_003F9a335f87_003FForwardedHeaders_002Ecs/@EntryIndexedValue">ForceIncluded</s:String> | 	<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AForwardedHeaders_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003FLibrary_003FApplication_0020Support_003FJetBrains_003FRider2024_002E3_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003Fcfe5737f9bb84738979cbfedd11822a8ea00_003F50_003F9a335f87_003FForwardedHeaders_002Ecs/@EntryIndexedValue">ForceIncluded</s:String> | ||||||
|  | 	<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AForwardedTransformExtensions_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003FLibrary_003FApplication_0020Support_003FJetBrains_003FRider2025_002E2_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003Fbf3f51607a3e4e76b5b91640cd7409195c430_003F03_003F36e779df_003FForwardedTransformExtensions_002Ecs/@EntryIndexedValue">ForceIncluded</s:String> | ||||||
| 	<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AHttpContext_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003FLibrary_003FApplication_0020Support_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003Fc181aff8c6ec418494a7efcfec578fc154e00_003Fd0_003Fcc905531_003FHttpContext_002Ecs/@EntryIndexedValue">ForceIncluded</s:String> | 	<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AHttpContext_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003FLibrary_003FApplication_0020Support_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003Fc181aff8c6ec418494a7efcfec578fc154e00_003Fd0_003Fcc905531_003FHttpContext_002Ecs/@EntryIndexedValue">ForceIncluded</s:String> | ||||||
| 	<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AHttpRequestHeaders_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003FLibrary_003FApplication_0020Support_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003Fb904f9896c4049fabd596decf1be9c381dc400_003F32_003F906beb77_003FHttpRequestHeaders_002Ecs/@EntryIndexedValue">ForceIncluded</s:String> | 	<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AHttpRequestHeaders_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003FLibrary_003FApplication_0020Support_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003Fb904f9896c4049fabd596decf1be9c381dc400_003F32_003F906beb77_003FHttpRequestHeaders_002Ecs/@EntryIndexedValue">ForceIncluded</s:String> | ||||||
| 	<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AHttpStatusCode_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003FLibrary_003FApplication_0020Support_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003Fb3f2e07d4b3f4b42a41fbcf3137e534f3be00_003Fe2_003F215f9441_003FHttpStatusCode_002Ecs/@EntryIndexedValue">ForceIncluded</s:String> | 	<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AHttpStatusCode_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003FLibrary_003FApplication_0020Support_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003Fb3f2e07d4b3f4b42a41fbcf3137e534f3be00_003Fe2_003F215f9441_003FHttpStatusCode_002Ecs/@EntryIndexedValue">ForceIncluded</s:String> | ||||||
| @@ -120,6 +121,7 @@ | |||||||
| 	<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003ARequestTransform_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003FLibrary_003FApplication_0020Support_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003Fbf3f51607a3e4e76b5b91640cd7409195c430_003Fa2_003Fe06c3ffa_003FRequestTransform_002Ecs/@EntryIndexedValue">ForceIncluded</s:String> | 	<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003ARequestTransform_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003FLibrary_003FApplication_0020Support_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003Fbf3f51607a3e4e76b5b91640cd7409195c430_003Fa2_003Fe06c3ffa_003FRequestTransform_002Ecs/@EntryIndexedValue">ForceIncluded</s:String> | ||||||
| 	<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AResizeOptions_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003FLibrary_003FApplication_0020Support_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003Fef3339e864a448e2b1ec6fa7bbf4c6661fee00_003F48_003F0209e410_003FResizeOptions_002Ecs/@EntryIndexedValue">ForceIncluded</s:String> | 	<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AResizeOptions_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003FLibrary_003FApplication_0020Support_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003Fef3339e864a448e2b1ec6fa7bbf4c6661fee00_003F48_003F0209e410_003FResizeOptions_002Ecs/@EntryIndexedValue">ForceIncluded</s:String> | ||||||
| 	<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AResourceManagerStringLocalizerFactory_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003FLibrary_003FApplication_0020Support_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003Fb62f365d06c44ad695ff75960cdf97a2a800_003Fe4_003Ff6ba93b7_003FResourceManagerStringLocalizerFactory_002Ecs/@EntryIndexedValue">ForceIncluded</s:String> | 	<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AResourceManagerStringLocalizerFactory_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003FLibrary_003FApplication_0020Support_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003Fb62f365d06c44ad695ff75960cdf97a2a800_003Fe4_003Ff6ba93b7_003FResourceManagerStringLocalizerFactory_002Ecs/@EntryIndexedValue">ForceIncluded</s:String> | ||||||
|  | 	<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AReverseProxyIEndpointRouteBuilderExtensions_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003FLibrary_003FApplication_0020Support_003FJetBrains_003FRider2025_002E2_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003Fbf3f51607a3e4e76b5b91640cd7409195c430_003Fa1_003F34726adb_003FReverseProxyIEndpointRouteBuilderExtensions_002Ecs/@EntryIndexedValue">ForceIncluded</s:String> | ||||||
| 	<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AReverseProxyServiceCollectionExtensions_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003FLibrary_003FApplication_0020Support_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003Fbf3f51607a3e4e76b5b91640cd7409195c430_003F13_003F8595a157_003FReverseProxyServiceCollectionExtensions_002Ecs/@EntryIndexedValue">ForceIncluded</s:String> | 	<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AReverseProxyServiceCollectionExtensions_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003FLibrary_003FApplication_0020Support_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003Fbf3f51607a3e4e76b5b91640cd7409195c430_003F13_003F8595a157_003FReverseProxyServiceCollectionExtensions_002Ecs/@EntryIndexedValue">ForceIncluded</s:String> | ||||||
| 	<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003ARouteConfig_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003FLibrary_003FApplication_0020Support_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003Fbf3f51607a3e4e76b5b91640cd7409195c430_003F84_003F98414804_003FRouteConfig_002Ecs/@EntryIndexedValue">ForceIncluded</s:String> | 	<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003ARouteConfig_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003FLibrary_003FApplication_0020Support_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003Fbf3f51607a3e4e76b5b91640cd7409195c430_003F84_003F98414804_003FRouteConfig_002Ecs/@EntryIndexedValue">ForceIncluded</s:String> | ||||||
| 	<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003ARSA_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003FLibrary_003FApplication_0020Support_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003Fee4f989f6b8042b59b2654fdc188e287243600_003F8b_003F44e5f855_003FRSA_002Ecs/@EntryIndexedValue">ForceIncluded</s:String> | 	<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003ARSA_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003FLibrary_003FApplication_0020Support_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003Fee4f989f6b8042b59b2654fdc188e287243600_003F8b_003F44e5f855_003FRSA_002Ecs/@EntryIndexedValue">ForceIncluded</s:String> | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user