1

Тема: Errors SonarQube in WebApi project

Підкажіть як пофіксити помилку яку видає СонарКуб. Можливо хтось юзає Сонар і знає що це таке.


Проект - https://gitlab.com/Sasha87/todo-list-app

Помилки:

File:TodoListApp.WebApi/Controllers/TodoTaskController.cs

1) Line:70
Message:Split this method into two, one handling parameters check and the other handling the asynchronous code.
Rule: csharpsquid:S4457
Issue type: Code Smell
Why is this an issue?
Major

2) Line:97
Message:Split this method into two, one handling parameters check and the other handling the asynchronous code.
Rule: csharpsquid:S4457
Issue type: Code Smell
Why is this an issue?

Major
3) Line:158
Message:Split this method into two, one handling parameters check and the other handling the asynchronous code.
Rule: csharpsquid:S4457
Issue type: Code Smell
Why is this an issue?

Major
4) Line:191
Message:Split this method into two, one handling parameters check and the other handling the asynchronous code.
Rule: csharpsquid:S4457
Issue type: Code Smell
Why is this an issue?

Major
5) Line:242
Message:Split this method into two, one handling parameters check and the other handling the asynchronous code.
Rule: csharpsquid:S4457
Issue type: Code Smell
Why is this an issue?

Major
6)Line:272
Message:Split this method into two, one handling parameters check and the other handling the asynchronous code.
Rule: csharpsquid:S4457
Issue type: Code Smell
Why is this an issue?

Це код :

using System.Security.Claims;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using TodoListApp.Services;
using TodoListApp.WebApi.Models.Comment;
using TodoListApp.WebApi.Models.Tag;
using TodoListApp.WebApi.Models.TodoTask;

namespace TodoListApp.WebApi.Controllers;

[Authorize]
[ApiController]
[Route("api/todolist/{listId}/tasks")]
public class TodoTaskController : ControllerBase
{
    private static readonly Action<ILogger, int, int, string, Exception> LogAddCommentFailure =
        LoggerMessage.Define<int, int, string>(
            LogLevel.Error,
            new EventId(1, nameof(AddComment)),
            "AddComment failed for task {TaskId} in list {ListId} by user {UserId}");

    private readonly ITodoTaskService taskService;
    private readonly IAccessService access;
    private readonly ILogger<TodoTaskController> logger;

    public TodoTaskController(ITodoTaskService taskService, IAccessService access, ILogger<TodoTaskController> logger)
    {
        this.taskService = taskService;
        this.access = access;
        this.logger = logger;
    }

    [HttpGet]
    public async Task<ActionResult<List<TodoTaskReadDto>>> GetTasks(int listId)
    {
        var userId = this.GetValidatedUserId();
        if (userId == null)
        {
            return this.Unauthorized();
        }

        if (!await this.HasListAccess(listId, userId))
        {
            return this.Forbid();
        }

        var tasks = await this.taskService.GetTasksAsync(listId);
        return this.Ok(tasks);
    }

    [HttpGet("{taskId}")]
    public async Task<ActionResult<TodoTaskReadDto>> GetTask(int listId, int taskId)
    {
        var userId = this.GetValidatedUserId();
        if (userId == null)
        {
            return this.Unauthorized();
        }

        if (!await this.HasListAccess(listId, userId))
        {
            return this.Forbid();
        }

        var task = await this.taskService.GetTaskAsync(listId, taskId);
        return task == null ? this.NotFound() : this.Ok(task);
    }

    [HttpPost]
    public async Task<IActionResult> CreateTask(int listId, [FromBody] TodoTaskCreateDto dto)
    {
        ArgumentNullException.ThrowIfNull(dto);

        if (!this.ValidateModel())
        {
            return this.BadRequest(this.ModelState);
        }

        var userId = this.GetValidatedUserId();
        if (userId == null)
        {
            return this.Unauthorized();
        }

        if (!await this.HasListAccess(listId, userId))
        {
            return this.Forbid();
        }

        var taskId = await this.taskService.CreateTaskAsync(listId, dto);
        return taskId.HasValue
            ? this.CreatedAtAction(nameof(this.GetTask), new { listId, taskId = taskId.Value }, new { taskId = taskId.Value })
            : this.BadRequest("Failed to create task.");
    }

    [HttpPut("{taskId}")]
    public async Task<IActionResult> UpdateTask(int listId, int taskId, [FromBody] TodoTaskUpdateDto dto)
    {
        ArgumentNullException.ThrowIfNull(dto);

        if (!this.ValidateModel())
        {
            return this.BadRequest(this.ModelState);
        }

        var userId = this.GetValidatedUserId();
        if (userId == null)
        {
            return this.Unauthorized();
        }

        if (!await this.HasTaskAccess(listId, taskId, userId))
        {
            return this.Forbid();
        }

        var result = await this.taskService.UpdateTaskAsync(listId, taskId, dto);
        return result ? this.Ok() : this.NotFound();
    }

    [HttpDelete("{taskId}")]
    public async Task<IActionResult> DeleteTask(int listId, int taskId)
    {
        var userId = this.GetValidatedUserId();
        if (userId == null)
        {
            return this.Unauthorized();
        }

        if (!await this.HasTaskAccess(listId, taskId, userId))
        {
            return this.Forbid();
        }

        var result = await this.taskService.DeleteTaskAsync(listId, taskId);
        return result ? this.Ok() : this.NotFound();
    }

    [HttpGet("{taskId}/comments")]
    public async Task<IActionResult> GetComments(int listId, int taskId)
    {
        var userId = this.GetValidatedUserId();
        if (userId == null)
        {
            return this.Unauthorized();
        }

        if (!await this.HasListAccess(listId, userId))
        {
            return this.Forbid();
        }

        var comments = await this.taskService.GetCommentsAsync(listId, taskId);
        return this.Ok(comments);
    }

    [HttpPost("{taskId}/comments")]
    public async Task<IActionResult> AddComment(int listId, int taskId, [FromForm] CommentCreateDto dto)
    {
        ArgumentNullException.ThrowIfNull(dto);

        if (!this.ValidateModel())
        {
            return this.BadRequest(this.ModelState);
        }

        var userId = this.GetValidatedUserId();
        if (userId == null)
        {
            return this.Unauthorized();
        }

        if (!await this.HasTaskAccess(listId, taskId, userId))
        {
            return this.Forbid();
        }

        try
        {
            var result = await this.taskService.AddCommentAsync(listId, taskId, dto.Text, userId);
            return result ? this.Ok() : this.NotFound();
        }
        catch (HttpRequestException ex)
        {
            LogAddCommentFailure(this.logger, taskId, listId, userId, ex);
            return this.StatusCode(500, "Internal server error");
        }
    }

    [HttpPut("{taskId}/comments/{commentId}")]
    public async Task<IActionResult> EditComment(int listId, int taskId, int commentId, [FromBody] CommentUpdateDto dto)
    {
        ArgumentNullException.ThrowIfNull(dto);

        var userId = this.GetUserId();
        if (string.IsNullOrWhiteSpace(userId))
        {
            return this.Forbid();
        }

        var result = await this.taskService.EditCommentAsync(listId, taskId, commentId, dto.Text, userId);
        return result ? this.Ok() : this.NotFound();
    }

    [HttpDelete("{taskId}/comments/{commentId}")]
    public async Task<IActionResult> DeleteComment(int listId, int taskId, int commentId)
    {
        var userId = this.GetUserId();
        if (string.IsNullOrWhiteSpace(userId))
        {
            return this.Unauthorized();
        }

        if (!await this.access.CanEditTaskAsync(listId, taskId, userId))
        {
            return this.Forbid();
        }

        var result = await this.taskService.DeleteCommentAsync(listId, taskId, commentId);
        return result ? this.Ok() : this.NotFound();
    }

    [HttpGet("{taskId}/tags")]
    public async Task<IActionResult> GetTags(int listId, int taskId)
    {
        var userId = this.GetValidatedUserId();
        if (userId == null)
        {
            return this.Unauthorized();
        }

        if (!await this.HasListAccess(listId, userId))
        {
            return this.Forbid();
        }

        var tags = await this.taskService.GetTagsAsync(listId, taskId);
        return this.Ok(tags);
    }

    [HttpPost("{taskId}/tags")]
    public async Task<IActionResult> AddTag(int listId, int taskId, [FromBody] TagCreateDto dto)
    {
        ArgumentNullException.ThrowIfNull(dto);

        if (!this.ValidateModel())
        {
            return this.BadRequest(this.ModelState);
        }

        var userId = this.GetValidatedUserId();
        if (userId == null)
        {
            return this.Unauthorized();
        }

        if (!await this.HasTaskAccess(listId, taskId, userId))
        {
            return this.Forbid();
        }

        if (string.IsNullOrWhiteSpace(dto.Name))
        {
            return this.BadRequest("Tag cannot be empty.");
        }

        var result = await this.taskService.AddTagToTaskAsync(listId, taskId, dto.Name);
        return result ? this.Ok() : this.NotFound();
    }

    [HttpPut("{taskId}/tags")]
    public async Task<IActionResult> RenameTag(int listId, int taskId, [FromForm] TagRenameDto dto)
    {
        ArgumentNullException.ThrowIfNull(dto);

        if (!this.ValidateModel())
        {
            return this.BadRequest(this.ModelState);
        }

        var userId = this.GetValidatedUserId();
        if (userId == null)
        {
            return this.Unauthorized();
        }

        if (!await this.HasTaskAccess(listId, taskId, userId))
        {
            return this.Forbid();
        }

        var result = await this.taskService.RenameTagAsync(listId, taskId, dto.OldName, dto.NewName);
        return result ? this.Ok() : this.NotFound();
    }

    [HttpDelete("{taskId}/tags/{tag}")]
    public async Task<IActionResult> RemoveTag(int listId, int taskId, string tag)
    {
        if (string.IsNullOrWhiteSpace(tag))
        {
            return this.BadRequest("Tag cannot be empty.");
        }

        var userId = this.GetValidatedUserId();
        if (userId == null)
        {
            return this.Unauthorized();
        }

        if (!await this.HasTaskAccess(listId, taskId, userId))
        {
            return this.Forbid();
        }

        var result = await this.taskService.RemoveTagFromTaskAsync(listId, taskId, tag);
        return result ? this.Ok() : this.NotFound();
    }

    private string? GetUserId() => this.User.FindFirstValue(ClaimTypes.NameIdentifier);

    private string? GetValidatedUserId()
    {
        var userId = this.GetUserId();
        return string.IsNullOrWhiteSpace(userId) ? null : userId;
    }

    private async Task<bool> HasListAccess(int listId, string userId)
    {
        if (string.IsNullOrWhiteSpace(userId))
        {
            return false;
        }

        return await this.access.HasAccessToListAsync(listId, userId);
    }

    private async Task<bool> HasTaskAccess(int listId, int taskId, string userId)
    {
        if (string.IsNullOrWhiteSpace(userId))
        {
            return false;
        }

        return await this.access.CanEditTaskAsync(listId, taskId, userId);
    }

    private bool ValidateModel()
    {
        return this.ModelState.IsValid;
    }
}

Помилки в методах:
Line 70 -

[HttpPost]
    public async Task<IActionResult> CreateTask(int listId, [FromBody] TodoTaskCreateDto dto)
    {
        ArgumentNullException.ThrowIfNull(dto);

        if (!this.ValidateModel())
        {
            return this.BadRequest(this.ModelState);
        }

        var userId = this.GetValidatedUserId();
        if (userId == null)
        {
            return this.Unauthorized();
        }

        if (!await this.HasListAccess(listId, userId))
        {
            return this.Forbid();
        }

        var taskId = await this.taskService.CreateTaskAsync(listId, dto);
        return taskId.HasValue
            ? this.CreatedAtAction(nameof(this.GetTask), new { listId, taskId = taskId.Value }, new { taskId = taskId.Value })
            : this.BadRequest("Failed to create task.");
    }

Line 97 -

[HttpPut("{taskId}")]
    public async Task<IActionResult> UpdateTask(int listId, int taskId, [FromBody] TodoTaskUpdateDto dto)
    {
        ArgumentNullException.ThrowIfNull(dto);

        if (!this.ValidateModel())
        {
            return this.BadRequest(this.ModelState);
        }

        var userId = this.GetValidatedUserId();
        if (userId == null)
        {
            return this.Unauthorized();
        }

        if (!await this.HasTaskAccess(listId, taskId, userId))
        {
            return this.Forbid();
        }

        var result = await this.taskService.UpdateTaskAsync(listId, taskId, dto);
        return result ? this.Ok() : this.NotFound();
    }

Line 158 -

[HttpPost("{taskId}/comments")]
    public async Task<IActionResult> AddComment(int listId, int taskId, [FromForm] CommentCreateDto dto)
    {
        ArgumentNullException.ThrowIfNull(dto);

        if (!this.ValidateModel())
        {
            return this.BadRequest(this.ModelState);
        }

        var userId = this.GetValidatedUserId();
        if (userId == null)
        {
            return this.Unauthorized();
        }

        if (!await this.HasTaskAccess(listId, taskId, userId))
        {
            return this.Forbid();
        }

        try
        {
            var result = await this.taskService.AddCommentAsync(listId, taskId, dto.Text, userId);
            return result ? this.Ok() : this.NotFound();
        }
        catch (HttpRequestException ex)
        {
            LogAddCommentFailure(this.logger, taskId, listId, userId, ex);
            return this.StatusCode(500, "Internal server error");
        }
    }

Line 191 -

[HttpPut("{taskId}/comments/{commentId}")]
    public async Task<IActionResult> EditComment(int listId, int taskId, int commentId, [FromBody] CommentUpdateDto dto)
    {
        ArgumentNullException.ThrowIfNull(dto);

        var userId = this.GetUserId();
        if (string.IsNullOrWhiteSpace(userId))
        {
            return this.Forbid();
        }

        var result = await this.taskService.EditCommentAsync(listId, taskId, commentId, dto.Text, userId);
        return result ? this.Ok() : this.NotFound();
    }

Line 242 -

[HttpPost("{taskId}/tags")]
    public async Task<IActionResult> AddTag(int listId, int taskId, [FromBody] TagCreateDto dto)
    {
        ArgumentNullException.ThrowIfNull(dto);

        if (!this.ValidateModel())
        {
            return this.BadRequest(this.ModelState);
        }

        var userId = this.GetValidatedUserId();
        if (userId == null)
        {
            return this.Unauthorized();
        }

        if (!await this.HasTaskAccess(listId, taskId, userId))
        {
            return this.Forbid();
        }

        if (string.IsNullOrWhiteSpace(dto.Name))
        {
            return this.BadRequest("Tag cannot be empty.");
        }

        var result = await this.taskService.AddTagToTaskAsync(listId, taskId, dto.Name);
        return result ? this.Ok() : this.NotFound();
    }

Line 272 -

[HttpPut("{taskId}/tags")]
    public async Task<IActionResult> RenameTag(int listId, int taskId, [FromForm] TagRenameDto dto)
    {
        ArgumentNullException.ThrowIfNull(dto);

        if (!this.ValidateModel())
        {
            return this.BadRequest(this.ModelState);
        }

        var userId = this.GetValidatedUserId();
        if (userId == null)
        {
            return this.Unauthorized();
        }

        if (!await this.HasTaskAccess(listId, taskId, userId))
        {
            return this.Forbid();
        }

        var result = await this.taskService.RenameTagAsync(listId, taskId, dto.OldName, dto.NewName);
        return result ? this.Ok() : this.NotFound();
    }