Skip to content

Admin/text and video block and task#94#165

Open
Danylo-Hrom wants to merge 5 commits into
devfrom
Admin/Text-and-video-block
Open

Admin/text and video block and task#94#165
Danylo-Hrom wants to merge 5 commits into
devfrom
Admin/Text-and-video-block

Conversation

@Danylo-Hrom
Copy link
Copy Markdown
Contributor

@Danylo-Hrom Danylo-Hrom commented Sep 8, 2025

dev

JIRA

Code reviewers

  • @github_username

Second Level Review

  • @github_username

Summary of issue

ToDo

Summary of change

ToDo

Testing approach

ToDo

CHECK LIST

  • СI passed
  • Сode coverage >=95%
  • PR is reviewed manually again (to make sure you have 100% ready code)
  • All reviewers agreed to merge the PR
  • I've checked new feature as logged in and logged out user if needed
  • PR meets all conventions

Summary by CodeRabbit

  • New Features

    • Added endpoint to create videos.
    • Added Title field to videos.
    • Added endpoint to create terms with title and description.
  • Improvements

    • Validation for video creation: title required (max 100 chars) and valid URL required.
    • Validation for term creation: title required (max 200 chars), description required, and valid Streetcode reference.
  • Tests

    • Added unit tests covering successful video creation and validation errors.
  • Chores

    • Updated project references and mappings to support new create operations.

@Danylo-Hrom Danylo-Hrom self-assigned this Sep 8, 2025
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Sep 8, 2025

Walkthrough

Introduces create flows for Video and Term: new DTOs, MediatR commands/handlers, and validators. Updates VideoController with a POST endpoint. Refactors Video DTO structure (adds Title; relocates class), removes legacy DTO file. Adjusts DAL entities (Video.Url non-nullable; Term expanded). Adds mappings, tests, and project references.

Changes

Cohort / File(s) Summary
Video DTO restructuring
Streetcode/Streetcode.BLL/DTO/Media/Video/CreateVideoDTO.cs, Streetcode/Streetcode.BLL/DTO/Media/Video/VideoDTO.cs, Streetcode/Streetcode.BLL/DTO/Media/VideoDTO.cs
Adds CreateVideoDTO inheriting VideoDTO; adds Title to VideoDTO and moves it under Media/Video namespace; removes old VideoDTO in Media path.
Video creation flow (MediatR, Validator, API, Tests)
Streetcode/Streetcode.BLL/MediatR/Media/Video/Create/CreateVideoCommand.cs, .../Create/CreateVideoHandler.cs, Streetcode/Streetcode.BLL/Validators/Media/Video/CreateVideoCommandValidator.cs, Streetcode/Streetcode.WebApi/Controllers/Media/VideoController.cs, Streetcode/Streetcode.XUnitTest/BLL/MediatR/Media/Video/CreateVideoHandlerTests.cs
Adds command, handler, and validator for creating videos; adds POST Create endpoint to VideoController; adds unit tests covering success and validation failures.
Term creation flow (DTO, Mapper, MediatR, Validator)
Streetcode/Streetcode.BLL/DTO/TextContent/TermCreateDTO.cs, Streetcode/Streetcode.BLL/Mapping/Streetcode/TextContent/TermProfile.cs, Streetcode/Streetcode.BLL/MediatR/Streetcode/Text/Create/CreateTermCommand.cs, .../Text/Create/CreateTermHandler.cs, Streetcode/Streetcode.BLL/Validators/TextContent/CreateTermValidator.cs
Adds TermCreateDTO; maps TermCreateDTO → Term; adds MediatR command/handler for creating terms; adds validator for title, description, and StreetcodeId.
DAL entity updates
Streetcode/Streetcode.DAL/Entities/Media/Video.cs, Streetcode/Streetcode.DAL/Entities/Streetcode/TextContent/Term.cs, .../TextContent/RelatedTerm.cs
Makes Video.Url non-nullable; extends Term with required Title/Description, StreetcodeId FK, and ICollection; removes BOM from RelatedTerm file.
Project references
Streetcode/Streetcode.WebApi/Streetcode.WebApi.csproj, Streetcode/Streetcode.XUnitTest/Streetcode.XUnitTest.csproj
Adds duplicate ProjectReference entries to BLL/DAL in WebApi and XUnitTest project files.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor Client
  participant API as VideoController
  participant Med as Mediator
  participant H as CreateVideoHandler
  participant Repo as RepositoryWrapper
  participant DB as DB
  participant Map as AutoMapper

  Client->>API: POST /api/video (CreateVideoDTO)
  API->>Med: Send(CreateVideoCommand)
  Med->>H: Handle(command)
  H->>Map: Map DTO -> Entity(Video)
  alt Validation fails
    H-->>Med: Result.Fail(error)
    Med-->>API: Failure
    API-->>Client: 400/422 with errors
  else Valid
    H->>Repo: VideoRepository.CreateAsync(entity)
    H->>Repo: SaveChangesAsync()
    Repo->>DB: Persist
    DB-->>Repo: Saved
    H->>Map: Map Entity -> VideoDTO
    H-->>Med: Result.Ok(VideoDTO)
    Med-->>API: Success
    API-->>Client: 200 with VideoDTO
  end
Loading
sequenceDiagram
  autonumber
  actor Caller
  participant Med as Mediator
  participant H as CreateTermHandler
  participant Repo as RepositoryWrapper
  participant DB as DB
  participant Map as AutoMapper

  Caller->>Med: Send(CreateTermCommand(TermCreateDTO))
  Med->>H: Handle(command)
  H->>Map: Map DTO -> Term
  alt Mapping/save fails
    H-->>Med: Result.Fail(error)
    Med-->>Caller: Failure
  else Success
    H->>Repo: TermRepository.CreateAsync(term)
    H->>Repo: SaveChangesAsync()
    Repo->>DB: Persist
    DB-->>Repo: Saved
    H->>Map: Map Term -> TermDTO
    H-->>Med: Result.Ok(TermDTO)
    Med-->>Caller: Success
  end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Suggested reviewers

  • VladysMoroz
  • weazy12
  • Markian-Grybok

Pre-merge checks (2 warnings, 1 inconclusive)

❌ Failed Checks (2 warnings, 1 inconclusive)
Check Name Status Explanation Resolution
Description Check ⚠️ Warning The current description merely replicates the template with placeholder “ToDo” items and lacks any actual summary of the issue, summary of change, or testing approach sections, so it fails to provide context or rationale for the extensive DTO, handler, validator, mapping, and controller additions. Populate each template section with concrete details: explain the issue driving the PR, outline the specific DTOs, commands, handlers, validators, and controller endpoints added, and describe how these changes are tested and verified.
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
Title Check ❓ Inconclusive The title “Admin/text and video block and task#94” is vague and uses path-like terminology plus an internal task reference, but it does not clearly communicate the primary feature or change implemented in this PR. It neither succinctly summarizes the addition of create endpoints, DTOs, handlers, and validators for videos and terms nor highlights the developer’s main focus. Rename the title to a concise, single-sentence summary of the main change, for example: “Add create endpoints and DTOs for video and term entities.”

Poem

I thump my paws: new terms take flight,
Videos hop from DTO to light.
Validators nibble every byte,
Handlers burrow, saving right.
In fields of code, I gleefully write—
Create and map, then test the night. 🥕✨

Tip

👮 Agentic pre-merge checks are now available in preview!

Pro plan users can now enable pre-merge checks in their settings to enforce checklists before merging PRs.

  • Built-in checks – Quickly apply ready-made checks to enforce title conventions, require pull request descriptions that follow templates, validate linked issues for compliance, and more.
  • Custom agentic checks – Define your own rules using CodeRabbit’s advanced agentic capabilities to enforce organization-specific policies and workflows. For example, you can instruct CodeRabbit’s agent to verify that API documentation is updated whenever API schema files are modified in a PR. Note: Upto 5 custom checks are currently allowed during the preview period. Pricing for this feature will be announced in a few weeks.

Example:

reviews:
  pre_merge_checks:
    custom_checks:
		  - name: "Undocumented Breaking Changes"
			  mode: "warning"
			  instructions: |
				  Flag potential breaking changes that are not documented:
				  1. Identify changes to public APIs/exports, CLI flags, environment variables, configuration keys, database schemas, or HTTP/GraphQL endpoints (including removed/renamed items and changes to types, required params, return values, defaults, or behavior).
				  2. Ignore purely internal/private changes (e.g., code not exported from package entry points or marked internal).
				  3. Verify documentation exists: a "Breaking Change" section in the PR description and updates to CHANGELOG.md.
✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch Admin/Text-and-video-block

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@sonarqubecloud
Copy link
Copy Markdown

sonarqubecloud Bot commented Sep 8, 2025

Quality Gate Failed Quality Gate failed

Failed conditions
48.1% Coverage on New Code (required ≥ 80%)

See analysis details on SonarQube Cloud

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
Streetcode/Streetcode.XUnitTest/Streetcode.XUnitTest.csproj (1)

50-53: Remove redundant ProjectReference group in Streetcode.XUnitTest.csproj
The BLL and DAL references appear at lines 11–12 and again at 51–52; remove one occurrence so each project is referenced only once.

🧹 Nitpick comments (20)
Streetcode/Streetcode.DAL/Entities/Media/Video.cs (1)

18-20: Constrain Url at the model level (length/format).

Add a reasonable max length and (optionally) URL format attribute to catch invalid data early.

     [Required]
-    public string Url { get; set; }
+    [MaxLength(2048)]
+    [Url]
+    public string Url { get; set; }
Streetcode/Streetcode.BLL/DTO/Media/Video/VideoDTO.cs (1)

8-8: Align DTO nullability with DAL: make Url non-nullable.

DAL now enforces non-null Url; returning string? in DTO leaks inconsistency and forces extra null checks in consumers.

-    public string? Url { get; set; }
+    public string Url { get; set; }
Streetcode/Streetcode.DAL/Entities/Streetcode/TextContent/RelatedTerm.cs (1)

13-16: Required + nullable string is inconsistent.

[Required] on string? Word contradicts nullability. Make it non-nullable to match intent and DB constraint.

-        [Required]
-        [MaxLength(50)]
-        public string? Word { get; set; }
+        [Required]
+        [MaxLength(50)]
+        public string Word { get; set; }
Streetcode/Streetcode.WebApi/Streetcode.WebApi.csproj (1)

62-64: Duplicate Streetcode.BLL ProjectReference — keep a single reference.

Two identical references exist; remove one.

   <ItemGroup>
-    <ProjectReference Include="..\Streetcode.BLL\Streetcode.BLL.csproj" />
+    <ProjectReference Include="..\Streetcode.BLL\Streetcode.BLL.csproj" />
   </ItemGroup>

-  <ItemGroup>
-    <ProjectReference Include="..\Streetcode.BLL\Streetcode.BLL.csproj" />
-  </ItemGroup>
+  <!-- removed duplicate ProjectReference -->

Also applies to: 16-18

Streetcode/Streetcode.BLL/Validators/TextContent/CreateTermValidator.cs (1)

4-4: Namespace consistency with folder structure.

Other validators typically live under ...Validators...; consider pluralizing for consistency and discoverability.

-namespace Streetcode.BLL.Validator.Streetcode.Term.Create;
+namespace Streetcode.BLL.Validators.Streetcode.Term.Create;
Streetcode/Streetcode.BLL/MediatR/Streetcode/Text/Create/CreateTermCommand.cs (1)

7-7: Align command payload property naming with CreateVideo for consistency

Consider renaming Term to CreateTermRequest to mirror CreateVideoCommand and keep pipelines uniform.

-public record CreateTermCommand(TermCreateDTO Term) : IRequest<Result<TermDTO>>;
+public record CreateTermCommand(TermCreateDTO CreateTermRequest) : IRequest<Result<TermDTO>>;
Streetcode/Streetcode.BLL/Validators/Media/Video/CreateVideoCommandValidator.cs (2)

4-4: Namespace should match folder and existing convention

Use Validators (plural) to stay consistent and simplify assembly scanning.

-namespace Streetcode.BLL.Validator.Media.Video;
+namespace Streetcode.BLL.Validators.Media.Video;

10-17: Tighten rules, stop on first failure, and provide clear messages

Prevent whitespace-only values, stop subsequent checks after a failure, and add explicit messages.

-RuleFor(c => c.CreateVideoRequest.Title)
-    .NotEmpty()
-    .MaximumLength(100);
+RuleFor(c => c.CreateVideoRequest.Title)
+    .Cascade(CascadeMode.Stop)
+    .NotEmpty().WithMessage("Title is required.")
+    .Must(t => !string.IsNullOrWhiteSpace(t)).WithMessage("Title cannot be whitespace.")
+    .MaximumLength(100).WithMessage("Title must not exceed 100 characters.");

-RuleFor(c => c.CreateVideoRequest.Url)
-    .NotEmpty()
-    .Must(url => Uri.IsWellFormedUriString(url, UriKind.Absolute));
+RuleFor(c => c.CreateVideoRequest.Url)
+    .Cascade(CascadeMode.Stop)
+    .NotEmpty().WithMessage("URL is required.")
+    .Must(url => Uri.IsWellFormedUriString(url, UriKind.Absolute))
+    .WithMessage("URL must be absolute and well-formed.");
Streetcode/Streetcode.BLL/DTO/TextContent/TermCreateDTO.cs (1)

5-10: Guard against null/whitespace in Title/Description via validator

DTO is fine; ensure a corresponding validator enforces non-empty values and reasonable length. If not present, add it.

I can draft CreateTermValidator mirroring the Video rules if you’d like.

Streetcode/Streetcode.BLL/MediatR/Streetcode/Text/Create/CreateTermHandler.cs (2)

36-38: Pass CancellationToken to repo calls

Propagate cancellationToken to support request aborts.

- await _repository.TermRepository.CreateAsync(entity);
- var result = await _repository.SaveChangesAsync();
+ await _repository.TermRepository.CreateAsync(entity, cancellationToken);
+ var result = await _repository.SaveChangesAsync(cancellationToken);

41-43: Optionally verify DTO mapping result

Very unlikely with a valid profile, but guarding improves resilience.

- var dto = _mapper.Map<TermDTO>(entity);
- return Result.Ok(dto);
+ var dto = _mapper.Map<TermDTO>(entity);
+ return dto is not null ? Result.Ok(dto) : Result.Fail("Failed to map Term entity to DTO.");
Streetcode/Streetcode.BLL/MediatR/Media/Video/Create/CreateVideoHandler.cs (3)

4-4: Avoid dependency on Microsoft.IdentityModel.Tokens for string checks

Use BCL string.IsNullOrWhiteSpace instead of IsNullOrEmpty() extension; drop this using.

-using Microsoft.IdentityModel.Tokens;

29-50: Consider passing CancellationToken to repo calls

Improves cancellation responsiveness.

- var entity = await _repositoryWrapper.VideoRepository.CreateAsync(newVideo);
- var resultIsSuccess = await _repositoryWrapper.SaveChangesAsync() > 0;
+ var entity = await _repositoryWrapper.VideoRepository.CreateAsync(newVideo, cancellationToken);
+ var resultIsSuccess = await _repositoryWrapper.SaveChangesAsync(cancellationToken) > 0;

29-50: Do we need a uniqueness/duplication guard (e.g., Url per StreetcodeId)?

Tests set up GetFirstOrDefaultAsync but the handler doesn’t check duplicates. Confirm desired behavior and, if needed, add a pre-create existence check.

I can extend the handler to query for an existing video by StreetcodeId+Url (or Title) and return a 409-style failure.

Streetcode/Streetcode.XUnitTest/BLL/MediatR/Media/Video/CreateVideoHandlerTests.cs (1)

125-155: Update URL error assertion and drop unused repo setups

Align message with handler and remove unused GetFirstOrDefaultAsync setups in these failure-path tests.

- _repositoryWrapperMock
-     .Setup(r => r.VideoRepository.GetFirstOrDefaultAsync(It.IsAny<Expression<Func<Entity, bool>>>(), default))
-     .ReturnsAsync((Entity)null);
...
- result.Errors.First().Message.Should().Contain("��������� �� ���� � ����'�������.");
+ result.Errors.First().Message.Should().Contain("URL is required and must be absolute and well-formed.");
Streetcode/Streetcode.DAL/Entities/Streetcode/TextContent/Term.cs (5)

1-1: Remove unused using.

using System; isn’t used.

-using System;

8-10: Add a uniqueness/index for fast lookups and to prevent duplicates per Streetcode.

If business logic expects a Term title to be unique within a Streetcode, add a composite unique index.

Add the attribute and ensure using Microsoft.EntityFrameworkCore; is present:

+using Microsoft.EntityFrameworkCore;
@@
-    [Table("terms", Schema = "streetcode")]
+    [Index(nameof(StreetcodeId), nameof(Title), IsUnique = true)]
+    [Table("terms", Schema = "streetcode")]
     public class Term

15-17: [Required] is redundant on non-nullable reference type.

EF Core infers non-nullability from string (with NRTs enabled). Consider removing [Required]; keep max length.

-        [Required]
         [MaxLength(50)]
         public string Title { get; set; } = string.Empty;

If you also want to prevent empty/whitespace values, enforce via FluentValidation or add [MinLength(1)].


19-21: Confirm whether Description must be mandatory.

If optional, make it nullable and drop [Required]. If mandatory, consider guarding against empty strings.

Option A (optional field):

-        [Required]
-        [MaxLength(500)]
-        public string Description { get; set; } = string.Empty;
+        [MaxLength(500)]
+        public string? Description { get; set; }

Option B (required and non-empty):

-        [Required]
+        [Required]
+        [MinLength(1)]
         [MaxLength(500)]
         public string Description { get; set; } = string.Empty;

26-26: Prefer HashSet and/or virtual for EF collections.

For better set semantics and proxy support, consider:

-        public ICollection<RelatedTerm> RelatedTerms { get; set; } = new List<RelatedTerm>();
+        public virtual ICollection<RelatedTerm> RelatedTerms { get; set; } = new HashSet<RelatedTerm>();

Note: Keep virtual only if lazy-loading proxies are used.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between efc93c6 and c99304d.

📒 Files selected for processing (18)
  • Streetcode/Streetcode.BLL/DTO/Media/Video/CreateVideoDTO.cs (1 hunks)
  • Streetcode/Streetcode.BLL/DTO/Media/Video/VideoDTO.cs (1 hunks)
  • Streetcode/Streetcode.BLL/DTO/Media/VideoDTO.cs (0 hunks)
  • Streetcode/Streetcode.BLL/DTO/TextContent/TermCreateDTO.cs (1 hunks)
  • Streetcode/Streetcode.BLL/Mapping/Streetcode/TextContent/TermProfile.cs (1 hunks)
  • Streetcode/Streetcode.BLL/MediatR/Media/Video/Create/CreateVideoCommand.cs (1 hunks)
  • Streetcode/Streetcode.BLL/MediatR/Media/Video/Create/CreateVideoHandler.cs (1 hunks)
  • Streetcode/Streetcode.BLL/MediatR/Streetcode/Text/Create/CreateTermCommand.cs (1 hunks)
  • Streetcode/Streetcode.BLL/MediatR/Streetcode/Text/Create/CreateTermHandler.cs (1 hunks)
  • Streetcode/Streetcode.BLL/Validators/Media/Video/CreateVideoCommandValidator.cs (1 hunks)
  • Streetcode/Streetcode.BLL/Validators/TextContent/CreateTermValidator.cs (1 hunks)
  • Streetcode/Streetcode.DAL/Entities/Media/Video.cs (1 hunks)
  • Streetcode/Streetcode.DAL/Entities/Streetcode/TextContent/RelatedTerm.cs (2 hunks)
  • Streetcode/Streetcode.DAL/Entities/Streetcode/TextContent/Term.cs (1 hunks)
  • Streetcode/Streetcode.WebApi/Controllers/Media/VideoController.cs (2 hunks)
  • Streetcode/Streetcode.WebApi/Streetcode.WebApi.csproj (1 hunks)
  • Streetcode/Streetcode.XUnitTest/BLL/MediatR/Media/Video/CreateVideoHandlerTests.cs (1 hunks)
  • Streetcode/Streetcode.XUnitTest/Streetcode.XUnitTest.csproj (1 hunks)
💤 Files with no reviewable changes (1)
  • Streetcode/Streetcode.BLL/DTO/Media/VideoDTO.cs
🧰 Additional context used
🧬 Code graph analysis (9)
Streetcode/Streetcode.BLL/Mapping/Streetcode/TextContent/TermProfile.cs (1)
Streetcode/Streetcode.BLL/DTO/TextContent/TermCreateDTO.cs (1)
  • TermCreateDTO (3-10)
Streetcode/Streetcode.BLL/DTO/Media/Video/CreateVideoDTO.cs (1)
Streetcode/Streetcode.BLL/DTO/Media/Video/VideoDTO.cs (1)
  • VideoDTO (3-10)
Streetcode/Streetcode.BLL/MediatR/Media/Video/Create/CreateVideoCommand.cs (3)
Streetcode/Streetcode.BLL/DTO/Media/Video/CreateVideoDTO.cs (1)
  • CreateVideoDTO (3-5)
Streetcode/Streetcode.BLL/MediatR/Media/Video/Create/CreateVideoHandler.cs (2)
  • Result (52-73)
  • Result (75-79)
Streetcode/Streetcode.BLL/DTO/Media/Video/VideoDTO.cs (1)
  • VideoDTO (3-10)
Streetcode/Streetcode.BLL/MediatR/Streetcode/Text/Create/CreateTermCommand.cs (1)
Streetcode/Streetcode.BLL/DTO/TextContent/TermCreateDTO.cs (1)
  • TermCreateDTO (3-10)
Streetcode/Streetcode.BLL/MediatR/Streetcode/Text/Create/CreateTermHandler.cs (2)
Streetcode/Streetcode.BLL/Services/Logging/LoggerService.cs (1)
  • LogError (35-40)
Streetcode/Streetcode.BLL/MediatR/Streetcode/RelatedTerm/Create/CreateRelatedTermHandler.cs (1)
  • CreateRelatedTermHandler (12-71)
Streetcode/Streetcode.BLL/MediatR/Media/Video/Create/CreateVideoHandler.cs (2)
Streetcode/Streetcode.BLL/DTO/Media/Video/VideoDTO.cs (1)
  • VideoDTO (3-10)
Streetcode/Streetcode.BLL/Services/Logging/LoggerService.cs (1)
  • LogError (35-40)
Streetcode/Streetcode.XUnitTest/BLL/MediatR/Media/Video/CreateVideoHandlerTests.cs (2)
Streetcode/Streetcode.BLL/MediatR/Media/Video/Create/CreateVideoHandler.cs (3)
  • CreateVideoHandler (13-80)
  • CreateVideoHandler (19-27)
  • Task (29-50)
Streetcode/Streetcode.BLL/DTO/Media/Video/CreateVideoDTO.cs (1)
  • CreateVideoDTO (3-5)
Streetcode/Streetcode.WebApi/Controllers/Media/VideoController.cs (2)
Streetcode/Streetcode.BLL/MediatR/Media/Video/Create/CreateVideoHandler.cs (1)
  • Task (29-50)
Streetcode/Streetcode.BLL/DTO/Media/Video/CreateVideoDTO.cs (1)
  • CreateVideoDTO (3-5)
Streetcode/Streetcode.DAL/Entities/Streetcode/TextContent/Term.cs (1)
Streetcode/Streetcode.DAL/Entities/Streetcode/TextContent/RelatedTerm.cs (1)
  • Table (6-19)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: Build and analyze
  • GitHub Check: Build and analyze
  • GitHub Check: Build and analyze
🔇 Additional comments (8)
Streetcode/Streetcode.DAL/Entities/Media/Video.cs (1)

18-20: Verify EF migration for non-nullable Url
Could not locate a migration altering media.videos.Url to non-nullable; ensure you’ve added an EF AlterColumn migration and handled any existing NULL values via backfill or data cleanup.

Streetcode/Streetcode.BLL/Mapping/Streetcode/TextContent/TermProfile.cs (1)

12-12: Mapping for TermCreateDTO → Term looks good.

Streetcode/Streetcode.BLL/MediatR/Media/Video/Create/CreateVideoCommand.cs (1)

7-7: LGTM: command contract is clear and consistent

No issues spotted.

Streetcode/Streetcode.BLL/MediatR/Streetcode/Text/Create/CreateTermHandler.cs (1)

25-34: Good null-mapping guard and error logging

Mapping null-check and logging look correct.

Streetcode/Streetcode.XUnitTest/BLL/MediatR/Media/Video/CreateVideoHandlerTests.cs (2)

35-68: Happy-path coverage looks good

Mocks and assertions correctly validate create flow success.


71-89: Null DTO case: OK

Failure path is exercised and assertions are clear.

Streetcode/Streetcode.DAL/Entities/Streetcode/TextContent/Term.cs (2)

8-13: LGTM on entity key mapping.

[Table], [Key], and identity setup look correct.


23-24: Confirm and fix the misapplied ForeignKey attribute
The [ForeignKey(nameof(Streetcode))] on StreetcodeId will be ignored if Term doesn’t declare a public Streetcode? Streetcode navigation and Streetcode doesn’t expose ICollection<Term> Terms. Manual verification required—confirm those navs exist (or not), then either remove the attribute to rely on conventions or add the missing navigation (annotated or by naming convention).

Comment on lines +3 to +5
public class CreateVideoDTO : VideoDTO
{
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Create DTO must not expose Id — avoid overposting/identity insert issues.

Inheriting from VideoDTO brings Id into the create contract. A client can set it, leading to inserts with explicit identity or unexpected behavior in EF.

Refactor CreateVideoDTO to its own shape without Id:

-namespace Streetcode.BLL.DTO.Media.Video
-{
-    public class CreateVideoDTO : VideoDTO
-    {
-    }
-}
+namespace Streetcode.BLL.DTO.Media.Video
+{
+    public class CreateVideoDTO
+    {
+        public required string Title { get; set; }  // validator enforces max 100
+        public string? Description { get; set; }
+        public required string Url { get; set; }
+        public int StreetcodeId { get; set; }
+    }
+}

If keeping inheritance temporarily, at minimum ensure AutoMapper ignores Id in the create mapping: ForMember(d => d.Id, opt => opt.Ignore());

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
public class CreateVideoDTO : VideoDTO
{
}
namespace Streetcode.BLL.DTO.Media.Video
{
public class CreateVideoDTO
{
public required string Title { get; set; } // validator enforces max 100
public string? Description { get; set; }
public required string Url { get; set; }
public int StreetcodeId { get; set; }
}
}
🤖 Prompt for AI Agents
In Streetcode/Streetcode.BLL/DTO/Media/Video/CreateVideoDTO.cs around lines 3-5,
the CreateVideoDTO currently inherits VideoDTO and therefore exposes Id which
can cause overposting/identity insert issues; change CreateVideoDTO to a
standalone DTO type that declares the create-time properties (title, url,
duration, etc.) but omits Id, and update any usages to the new shape; if you
must keep inheritance temporarily, update the AutoMapper profile for the create
mapping to explicitly ignore Id (ForMember(d => d.Id, opt => opt.Ignore())) so
incoming Id values are not mapped.

Comment on lines +52 to +73
private Result<VideoDTO>? VideoValidation(CreateVideoCommand request, Entity? newVideo)
{
if (newVideo == null)
{
const string errorMsg = "Cannot convert null to Video.";
return LogAndFail(request, errorMsg);
}

if (newVideo.Title.Length > 100)
{
const string errorMsg = "��������� ���� �� ���� ���� ����� 100 �������.";
return LogAndFail(request, errorMsg);
}

if (newVideo.Url.IsNullOrEmpty())
{
const string errorMsg = "��������� �� ���� � ����'�������.";
return LogAndFail(request, errorMsg);
}

return null;
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Fix potential NRE, replace mojibake messages, and use BCL null/whitespace checks

newVideo.Title.Length will throw if Title is null; error texts appear corrupted; and IsNullOrEmpty() extension is unnecessary. Use string.IsNullOrWhiteSpace, check length safely, and provide clear messages.

-    private Result<VideoDTO>? VideoValidation(CreateVideoCommand request, Entity? newVideo)
+    private Result<VideoDTO>? VideoValidation(CreateVideoCommand request, Entity? newVideo)
     {
         if (newVideo == null)
         {
-            const string errorMsg = "Cannot convert null to Video.";
+            const string errorMsg = "Cannot convert null to Video.";
             return LogAndFail(request, errorMsg);
         }
 
-        if (newVideo.Title.Length > 100)
+        if (string.IsNullOrWhiteSpace(newVideo.Title) || newVideo.Title!.Length > 100)
         {
-            const string errorMsg = "��������� ���� �� ���� ���� ����� 100 �������.";
+            const string errorMsg = "Title is required and must not exceed 100 characters.";
             return LogAndFail(request, errorMsg);
         }
 
-        if (newVideo.Url.IsNullOrEmpty())
+        if (string.IsNullOrWhiteSpace(newVideo.Url) || !Uri.IsWellFormedUriString(newVideo.Url, UriKind.Absolute))
         {
-            const string errorMsg = "��������� �� ���� � ����'�������.";
+            const string errorMsg = "URL is required and must be absolute and well-formed.";
             return LogAndFail(request, errorMsg);
         }
 
         return null;
     }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
private Result<VideoDTO>? VideoValidation(CreateVideoCommand request, Entity? newVideo)
{
if (newVideo == null)
{
const string errorMsg = "Cannot convert null to Video.";
return LogAndFail(request, errorMsg);
}
if (newVideo.Title.Length > 100)
{
const string errorMsg = "Çàãîëîâîê â³äåî íå ìîæå áóòè á³ëüøå 100 ñèìâîë³â.";
return LogAndFail(request, errorMsg);
}
if (newVideo.Url.IsNullOrEmpty())
{
const string errorMsg = "Ïîñèëàííÿ íà â³äåî º îáîâ'ÿçêîâèì.";
return LogAndFail(request, errorMsg);
}
return null;
}
private Result<VideoDTO>? VideoValidation(CreateVideoCommand request, Entity? newVideo)
{
if (newVideo == null)
{
const string errorMsg = "Cannot convert null to Video.";
return LogAndFail(request, errorMsg);
}
if (string.IsNullOrWhiteSpace(newVideo.Title) || newVideo.Title!.Length > 100)
{
const string errorMsg = "Title is required and must not exceed 100 characters.";
return LogAndFail(request, errorMsg);
}
if (string.IsNullOrWhiteSpace(newVideo.Url) || !Uri.IsWellFormedUriString(newVideo.Url, UriKind.Absolute))
{
const string errorMsg = "URL is required and must be absolute and well-formed.";
return LogAndFail(request, errorMsg);
}
return null;
}
🤖 Prompt for AI Agents
In Streetcode/Streetcode.BLL/MediatR/Media/Video/Create/CreateVideoHandler.cs
around lines 52-73, the validation reads properties without null-safety and
contains corrupted messages; update the method to first null-check newVideo,
then use string.IsNullOrWhiteSpace(newVideo.Title) or safe access (e.g. if
(string.IsNullOrWhiteSpace(newVideo.Title)) ...) before checking length, use
newVideo.Title.Length only after ensuring Title is not null, replace
IsNullOrEmpty() extension with string.IsNullOrWhiteSpace(newVideo.Url), and
replace the mojibake error texts with clear English messages (e.g. "Title is
required", "Title must be at most 100 characters", "URL is required"); keep
returning LogAndFail(request, errorMsg) on failures.

Comment on lines +10 to +12
RuleFor(cmd => cmd.Term.Title)
.NotEmpty()
.MaximumLength(200);
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Verification agent

🧩 Analysis chain

Confirm DB constraint parity for Title length (200).

Ensure Term.Title in DAL has [MaxLength(200)] (or equivalent) to avoid runtime DB truncation errors.


🏁 Script executed:

#!/bin/bash
# Verify DAL constraint for Term.Title
rg -nP '(class\\s+Term\\b|\\[MaxLength\\(\\s*200\\s*\\)\\])' -C3 --type=cs

Length of output: 25219


🏁 Script executed:

#!/bin/bash
# Locate the Term entity class in DAL and verify Title length annotation
echo "Searching for Term entity definition…"
rg -nP 'public\s+class\s+Term\b' -C3 --type=cs

echo
echo "Checking for [MaxLength(200)] on Title property in Term entity…"
TERM_FILE=$(rg -lP 'public\s+class\s+Term\b' --type=cs)
rg -nP '\[MaxLength\(\s*200\s*\)\]' -C3 "$TERM_FILE"

Length of output: 788


Add DB constraint for Term.Title
The Title property in Streetcode/Streetcode.DAL/Entities/Streetcode/TextContent/Term.cs lacks a [MaxLength(200)] attribute (or equivalent EF Core fluent‐API .HasMaxLength(200)), mismatching the BLL validator’s 200-char limit and risking runtime truncation errors.

🤖 Prompt for AI Agents
In Streetcode/Streetcode.BLL/Validators/TextContent/CreateTermValidator.cs
around lines 10-12, the BLL enforces a 200-char max for Term.Title but the Term
entity lacks a corresponding DB constraint; update
Streetcode/Streetcode.DAL/Entities/Streetcode/TextContent/Term.cs to add
[MaxLength(200)] (or configure .HasMaxLength(200) in the DbContext fluent API)
on the Title property and then add and run an EF Core migration to persist the
schema change so the database matches the validator.

Comment on lines +30 to +34
[HttpPost]
public async Task<IActionResult> Create([FromBody] CreateVideoDTO video)
{
return HandleResult(await Mediator.Send(new CreateVideoCommand(video)));
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Verification agent

🧩 Analysis chain

POST Create endpoint: OK; verify existing GET route ambiguity

Create action wiring is fine. However, current GET routes use identical templates "{int}" for both GetByStreetcodeId and GetById, which leads to ambiguous matches at runtime. Consider distinct templates (example below).

Example fix outside this hunk (for lines 18-26):

[HttpGet("by-streetcode/{streetcodeId:int}")]
public async Task<IActionResult> GetByStreetcodeId([FromRoute] int streetcodeId) =>
    HandleResult(await Mediator.Send(new GetVideoByStreetcodeIdQuery(streetcodeId)));

[HttpGet("{id:int}")]
public async Task<IActionResult> GetById([FromRoute] int id) =>
    HandleResult(await Mediator.Send(new GetVideoByIdQuery(id)));

🏁 Script executed:

#!/bin/bash
# Locate the VideoController file
file=$(fd --hidden --full-path VideoController.cs)

# Show all HttpGet attributes with context
rg -nC2 "\[HttpGet" "$file"

# Show GetByStreetcodeId action with context
rg -nC2 "GetByStreetcodeId" "$file"

# Show GetById action with context
rg -nC2 "GetById" "$file"

Length of output: 1277


Differentiate GET route templates to avoid ambiguity
Change GetByStreetcodeId to use a unique template (e.g. [HttpGet("by-streetcode/{streetcodeId:int}")]) instead of "{streetcodeId:int}", so it won’t collide with GetById’s "{id:int}".

🤖 Prompt for AI Agents
In Streetcode/Streetcode.WebApi/Controllers/Media/VideoController.cs around
lines 30 to 34, the GET action that returns videos by streetcodeId uses the same
numeric route template as GetById and can collide; change its route attribute to
a unique template such as [HttpGet("by-streetcode/{streetcodeId:int}")] (and
update any route names or client calls/Swagger references accordingly) so the
two endpoints no longer conflict.

Comment on lines +91 to +123
[Fact]
public async Task Handle_TitleMaxLength_ReturnsError()
{
var requestDto = new CreateVideoDTO
{
Title = new string('*', 101),
Description = "Description",
Url = "https://google.com",
StreetcodeId = 1
};

var mappedEntity = new Entity
{
Title = new string('*', 101),
Description = "Description",
Url = "https://google.com",
StreetcodeId = 1
};

_mapperMock.Setup(m => m.Map<Entity>(requestDto)).Returns(mappedEntity);

_repositoryWrapperMock
.Setup(r => r.VideoRepository.GetFirstOrDefaultAsync(It.IsAny<Expression<Func<Entity, bool>>>(), default))
.ReturnsAsync((Entity)null);

_repositoryWrapperMock.Setup(r => r.VideoRepository.CreateAsync(mappedEntity)).ReturnsAsync(mappedEntity);
_repositoryWrapperMock.Setup(r => r.SaveChangesAsync()).ReturnsAsync(1);

var result = await _handler.Handle(new CreateVideoCommand(requestDto), CancellationToken.None);

result.IsFailed.Should().BeTrue();
result.Errors.First().Message.Should().Contain("��������� ���� �� ���� ���� ����� 100 �������.");
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Update expected message to match corrected validation text

Tests currently assert mojibake. Align with clear message from handler.

- result.Errors.First().Message.Should().Contain("��������� ���� �� ���� ���� ����� 100 �������.");
+ result.Errors.First().Message.Should().Contain("Title is required and must not exceed 100 characters.");

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In
Streetcode/Streetcode.XUnitTest/BLL/MediatR/Media/Video/CreateVideoHandlerTests.cs
around lines 91 to 123, the test asserts a mojibake string for the title-length
validation; update the assertion to match the corrected validation message
emitted by the handler (replace the current expected message "Çàãîëîâîê â³äåî íå
ìîæå áóòè á³ëüøå 100 ñèìâîë³â." with the proper Ukrainian text, e.g. "Заголовок
відео не може бути більше 100 символів."). Ensure the test still checks IsFailed
is true and that Errors.First().Message.Contains(...) uses the corrected string.

Copy link
Copy Markdown
Contributor

@weazy12 weazy12 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Move your validation into Validation folder. Write unit tests for all your new features and resolve all conversations from coderabbit.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants