diff --git a/.docker-compose.yml.swp b/.docker-compose.yml.swp new file mode 100644 index 0000000..fb3bdea Binary files /dev/null and b/.docker-compose.yml.swp differ diff --git a/GrpcTodo.CLI/ActionRunner.cs b/GrpcTodo.CLI/ActionRunner.cs index 50140ff..43dd588 100644 --- a/GrpcTodo.CLI/ActionRunner.cs +++ b/GrpcTodo.CLI/ActionRunner.cs @@ -8,6 +8,7 @@ using GrpcTodo.CLI.UseCases.AliasList; using GrpcTodo.CLI.UseCases.AliasRemove; using GrpcTodo.CLI.UseCases.TaskCreate; +using GrpcTodo.CLI.UseCases.TaskDelete; using GrpcTodo.CLI.UseCases.TaskList; namespace GrpcTodo.CLI; @@ -23,6 +24,7 @@ internal class ActionRunner private readonly AliasRemoveUseCase _aliasRemoveUseCase; private readonly TaskCreateUseCase _taskCreateUseCase; private readonly TaskListUseCase _taskListUseCase; + private readonly TaskDeleteUseCase _taskDeleteUseCase; private readonly CommandReader _commandReader; @@ -39,6 +41,7 @@ public ActionRunner(ConfigsManager configsManager, CommandReader commandReader, _aliasRemoveUseCase = new AliasRemoveUseCase(configsManager, commandReader); _taskCreateUseCase = new TaskCreateUseCase(configsManager); _taskListUseCase = new TaskListUseCase(configsManager, parameters); + _taskDeleteUseCase = new TaskDeleteUseCase(configsManager); } public Task Run(Command? action) @@ -65,15 +68,14 @@ public Task Run(Command? action) return _taskCreateUseCase.ExecuteAsync(); case Command.ListAllTasks: return _taskListUseCase.ExecuteAsync(); + case Command.DeleteTask: + return _taskDeleteUseCase.ExecuteAsync(); case Command.CompleteTask: Console.WriteLine("no implemented yet: complete task"); break; case Command.UncompleteTask: Console.WriteLine("no implemented yet: uncomplete task"); break; - case Command.DeleteTask: - Console.WriteLine("no implemented yet: delete task"); - break; } return Task.CompletedTask; diff --git a/GrpcTodo.CLI/CLI.cs b/GrpcTodo.CLI/CLI.cs index f9f2ce2..87bf988 100644 --- a/GrpcTodo.CLI/CLI.cs +++ b/GrpcTodo.CLI/CLI.cs @@ -1,3 +1,5 @@ +using Grpc.Core; + using GrpcTodo.CLI.Lib; using GrpcTodo.CLI.Models; using GrpcTodo.CLI.Services; @@ -48,6 +50,14 @@ public async Task Run() Menu.ShowAvailableOptions(parameters); } } + catch (RpcException e) + { + ConsoleWritter.WriteError(e.Status.Detail ?? e.Message); + } + catch (ArgumentNullException e) + { + ConsoleWritter.WriteError(e.Message); + } catch (ShowErrorMessageException e) { ConsoleWritter.WriteError(e.Message); diff --git a/GrpcTodo.CLI/Menu.cs b/GrpcTodo.CLI/Menu.cs index 13ca5ba..dcf9622 100644 --- a/GrpcTodo.CLI/Menu.cs +++ b/GrpcTodo.CLI/Menu.cs @@ -99,8 +99,9 @@ public sealed class Menu }, new MenuOption { Path = "delete", + IsImplemented = true, Command = Command.DeleteTask, - Description = "delete a task" + Description = "delete a task. example: gl delete task " }, } } diff --git a/GrpcTodo.CLI/UseCases/AccountCreate/AccountCreateUseCase.cs b/GrpcTodo.CLI/UseCases/AccountCreate/AccountCreateUseCase.cs index cadc273..9affe7f 100644 --- a/GrpcTodo.CLI/UseCases/AccountCreate/AccountCreateUseCase.cs +++ b/GrpcTodo.CLI/UseCases/AccountCreate/AccountCreateUseCase.cs @@ -1,6 +1,5 @@ using GrpcTodo.CLI.Utils; using Grpc.Core; -using Grpc.Net.Client; using GrpcTodo.SharedKernel.Protos.User; using GrpcTodo.SharedKernel.Protos.User.Requests; using GrpcTodo.CLI.Lib; @@ -34,7 +33,7 @@ public override async Task ExecuteAsync() try { - using var channel = GrpcChannel.ForAddress(Settings.ServerAddress); + using var channel = GrpcConnection.CreateChannel(); var client = new User.UserClient(channel); diff --git a/GrpcTodo.CLI/UseCases/AccountLogin/AccountLoginUseCase.cs b/GrpcTodo.CLI/UseCases/AccountLogin/AccountLoginUseCase.cs index 03a8317..3bbf30f 100644 --- a/GrpcTodo.CLI/UseCases/AccountLogin/AccountLoginUseCase.cs +++ b/GrpcTodo.CLI/UseCases/AccountLogin/AccountLoginUseCase.cs @@ -1,6 +1,5 @@ using GrpcTodo.CLI.Utils; using Grpc.Core; -using Grpc.Net.Client; using GrpcTodo.SharedKernel.Protos.User; using GrpcTodo.SharedKernel.Protos.User.Requests; using GrpcTodo.CLI.Lib; @@ -34,7 +33,7 @@ public override async Task ExecuteAsync() try { - using var channel = GrpcChannel.ForAddress(Settings.ServerAddress); + using var channel = GrpcConnection.CreateChannel(); var client = new User.UserClient(channel); diff --git a/GrpcTodo.CLI/UseCases/AccountTokenUpdate/AccountTokenUpdateUseCase.cs b/GrpcTodo.CLI/UseCases/AccountTokenUpdate/AccountTokenUpdateUseCase.cs index 730742c..e985de9 100644 --- a/GrpcTodo.CLI/UseCases/AccountTokenUpdate/AccountTokenUpdateUseCase.cs +++ b/GrpcTodo.CLI/UseCases/AccountTokenUpdate/AccountTokenUpdateUseCase.cs @@ -1,5 +1,4 @@ using Grpc.Core; -using Grpc.Net.Client; using GrpcTodo.SharedKernel.Protos.User; using GrpcTodo.SharedKernel.Protos.User.Requests; using GrpcTodo.CLI.UseCases.Common; @@ -34,7 +33,7 @@ public override async Task ExecuteAsync() try { - using var channel = GrpcChannel.ForAddress(Settings.ServerAddress); + using var channel = GrpcConnection.CreateChannel(); var client = new User.UserClient(channel); diff --git a/GrpcTodo.CLI/UseCases/Common/Prompt.cs b/GrpcTodo.CLI/UseCases/Common/Prompt.cs index d7b548f..2a6034b 100644 --- a/GrpcTodo.CLI/UseCases/Common/Prompt.cs +++ b/GrpcTodo.CLI/UseCases/Common/Prompt.cs @@ -10,6 +10,9 @@ private protected record PromptOptions public bool RemoveWhitespaces { get; init; } = false; public bool ShouldBeNumber { get; init; } = false; public bool ShouldBeSingleWord { get; init; } = false; + /// + /// returns true when should show the error, false when not + /// public Func? Custom { get; init; } public string? CustomMessage { get; init; } public bool ShouldBeHidden { get; init; } = false; diff --git a/GrpcTodo.CLI/UseCases/TaskCreate/TaskCreateUseCase.cs b/GrpcTodo.CLI/UseCases/TaskCreate/TaskCreateUseCase.cs index a3834b6..52044c7 100644 --- a/GrpcTodo.CLI/UseCases/TaskCreate/TaskCreateUseCase.cs +++ b/GrpcTodo.CLI/UseCases/TaskCreate/TaskCreateUseCase.cs @@ -1,5 +1,4 @@ using Grpc.Core; -using Grpc.Net.Client; using GrpcTodo.CLI.Lib; using GrpcTodo.CLI.UseCases.Common; using GrpcTodo.CLI.Utils; @@ -27,7 +26,7 @@ public override async Task ExecuteAsync() var prompt = createTaskPrompt.PromptName(); var name = prompt.Name; - using var channel = GrpcChannel.ForAddress(Settings.ServerAddress); + using var channel = GrpcConnection.CreateChannel(); var client = new TaskItem.TaskItemClient(channel); diff --git a/GrpcTodo.CLI/UseCases/TaskDelete/TaskDeletePrompt.cs b/GrpcTodo.CLI/UseCases/TaskDelete/TaskDeletePrompt.cs new file mode 100644 index 0000000..e8badc8 --- /dev/null +++ b/GrpcTodo.CLI/UseCases/TaskDelete/TaskDeletePrompt.cs @@ -0,0 +1,56 @@ +using System.Text; + +using GrpcTodo.CLI.UseCases.Common; +using GrpcTodo.CLI.Utils; +using GrpcTodo.SharedKernel.Protos.Tasks.Responses; + +namespace GrpcTodo.CLI.UseCases.TaskDelete; + +public sealed class TaskDeletePrompt : Prompt +{ + public string PromptTask(IOrderedEnumerable tasks) + { + Dictionary tasksId = new(); + + foreach (var task in tasks) + tasksId.Add(task.Id[0..4], true); + + ConsoleWritter.WriteInfo("Choose a task id to delete\n"); + + ConsoleWritter.WriteWithColor("+ completed", ConsoleColor.Green); + ConsoleWritter.WriteWithColor("- uncompleted", ConsoleColor.White); + Console.WriteLine(); + + StringBuilder sb = new(); + + foreach (var task in tasks) + { + var id = task.Id[0..4]; + + sb.Append(task.Completed ? "+" : "- "); + + var createdAt = new DateTime(task.CreatedAt); + + sb.Append($"[{id}] [{createdAt:MM/dd HH:mm}] {task.Name}"); + + if (task.Completed) + ConsoleWritter.WriteWithColor(sb.ToString(), ConsoleColor.Green); + else + ConsoleWritter.WriteWithColor(sb.ToString(), ConsoleColor.White); + + sb.Clear(); + } + + Console.WriteLine(); + + var taskId = Read("task id: ", new PromptOptions + { + RemoveWhitespaces = true, + ShouldBeSingleWord = true, + CustomMessage = "This task id does not exists", + Custom = id => !tasksId.ContainsKey(id) + }); + + return taskId; + } +} diff --git a/GrpcTodo.CLI/UseCases/TaskDelete/TaskDeleteUseCase.cs b/GrpcTodo.CLI/UseCases/TaskDelete/TaskDeleteUseCase.cs new file mode 100644 index 0000000..b9f8a71 --- /dev/null +++ b/GrpcTodo.CLI/UseCases/TaskDelete/TaskDeleteUseCase.cs @@ -0,0 +1,45 @@ +using GrpcTodo.CLI.Lib; +using GrpcTodo.CLI.UseCases.Common; +using GrpcTodo.CLI.Utils; +using GrpcTodo.SharedKernel.Protos.Tasks; +using GrpcTodo.SharedKernel.Protos.Tasks.Requests; + +namespace GrpcTodo.CLI.UseCases.TaskDelete; +public class TaskDeleteUseCase : UseCase +{ + public TaskDeleteUseCase(ConfigsManager configsManager) : base(configsManager) + { + } + + public override async Task ExecuteAsync() + { + var accessToken = _configsManager.GetItem(ConfigKey.Item, Settings.AuthTokenKey); + + if (accessToken is null) + throw new ArgumentNullException(nameof(accessToken), "you are not authenticated"); + + using var channel = GrpcConnection.CreateChannel(); + + var client = new TaskItem.TaskItemClient(channel); + + var request = new TaskListRequest + { + AccessToken = accessToken + }; + + var response = await client.ListAllAsync(request); + + var tasks = response.Items.OrderByDescending(x => x.CreatedAt); + + var taskDeletePrompt = new TaskDeletePrompt(); + + var taskIdToDelete = taskDeletePrompt.PromptTask(tasks); + + await client.DeleteAsync(new TaskDeleteRequest { + TaskId = taskIdToDelete, + AccessToken = accessToken + }); + + ConsoleWritter.WriteSuccess($"task [{taskIdToDelete}] deleted successfully"); + } +} diff --git a/GrpcTodo.CLI/UseCases/TaskList/TaskListUseCase.cs b/GrpcTodo.CLI/UseCases/TaskList/TaskListUseCase.cs index 83c2f02..078b6a9 100644 --- a/GrpcTodo.CLI/UseCases/TaskList/TaskListUseCase.cs +++ b/GrpcTodo.CLI/UseCases/TaskList/TaskListUseCase.cs @@ -1,8 +1,5 @@ using System.Text; -using Grpc.Core; -using Grpc.Net.Client; - using GrpcTodo.CLI.Lib; using GrpcTodo.CLI.UseCases.Common; using GrpcTodo.CLI.Utils; @@ -22,66 +19,55 @@ public TaskListUseCase(ConfigsManager configsManager, Parameters parameters) : b public override async Task ExecuteAsync() { - try - { - var accessToken = _configsManager.GetItem(ConfigKey.Item, Settings.AuthTokenKey); + var accessToken = _configsManager.GetItem(ConfigKey.Item, Settings.AuthTokenKey); - if (accessToken is null) - throw new ArgumentNullException(nameof(accessToken), "you are not authenticated"); + if (accessToken is null) + throw new ArgumentNullException(nameof(accessToken), "you are not authenticated"); - using var channel = GrpcChannel.ForAddress(Settings.ServerAddress); + using var channel = GrpcConnection.CreateChannel(); - var client = new TaskItem.TaskItemClient(channel); - - var request = new TaskListRequest - { - AccessToken = accessToken - }; + var client = new TaskItem.TaskItemClient(channel); - var response = await client.ListAllAsync(request); + var request = new TaskListRequest + { + AccessToken = accessToken + }; - var tasks = response.Items.OrderByDescending(x => x.CreatedAt); + var response = await client.ListAllAsync(request); - ConsoleWritter.WriteInfo("==== ALL TASKS ===\n"); - ConsoleWritter.WriteWithColor("+ completed", ConsoleColor.Green); - ConsoleWritter.WriteWithColor("- uncompleted", ConsoleColor.White); - Console.WriteLine(); + var tasks = response.Items.OrderByDescending(x => x.CreatedAt); - StringBuilder sb = new(); + ConsoleWritter.WriteInfo("==== ALL TASKS ===\n"); + ConsoleWritter.WriteWithColor("+ completed", ConsoleColor.Green); + ConsoleWritter.WriteWithColor("- uncompleted", ConsoleColor.White); + Console.WriteLine(); - foreach (var task in tasks) - { - var id = task.Id[0..4]; + StringBuilder sb = new(); - sb.Append(task.Completed ? "+" : "- "); + foreach (var task in tasks) + { + var id = task.Id[0..4]; - if (_parameters.Has("--full")) - { - var createdAt = new DateTime(task.CreatedAt); + sb.Append(task.Completed ? "+" : "- "); - sb.Append($"[{id}] "); - sb.Append($"[{createdAt:MM/dd HH:mm}] "); - } + if (_parameters.Has("--full")) + { + var createdAt = new DateTime(task.CreatedAt); - sb.Append(task.Name); + sb.Append($"[{id}] "); + sb.Append($"[{createdAt:MM/dd HH:mm}] "); + } - if (task.Completed) - ConsoleWritter.WriteWithColor(sb.ToString(), ConsoleColor.Green); - else - ConsoleWritter.WriteWithColor(sb.ToString(), ConsoleColor.White); + sb.Append(task.Name); - sb.Clear(); - } + if (task.Completed) + ConsoleWritter.WriteWithColor(sb.ToString(), ConsoleColor.Green); + else + ConsoleWritter.WriteWithColor(sb.ToString(), ConsoleColor.White); - Console.WriteLine(); - } - catch (RpcException e) - { - ConsoleWritter.WriteError(e.Status.Detail ?? e.Message); - } - catch (ArgumentNullException e) - { - ConsoleWritter.WriteError(e.Message); + sb.Clear(); } + + Console.WriteLine(); } } diff --git a/GrpcTodo.CLI/Utils/GrpcConnection.cs b/GrpcTodo.CLI/Utils/GrpcConnection.cs new file mode 100644 index 0000000..ea6acc9 --- /dev/null +++ b/GrpcTodo.CLI/Utils/GrpcConnection.cs @@ -0,0 +1,21 @@ +using Grpc.Net.Client; + +namespace GrpcTodo.CLI.Utils; + +public static class GrpcConnection +{ + public static GrpcChannel CreateChannel() + { + var httpHandler = new HttpClientHandler + { + ServerCertificateCustomValidationCallback = HttpClientHandler.DangerousAcceptAnyServerCertificateValidator + }; + + var configurations = new GrpcChannelOptions + { + HttpHandler = httpHandler + }; + + return GrpcChannel.ForAddress(Settings.ServerAddress, configurations); + } +} \ No newline at end of file diff --git a/GrpcTodo.Server/Application/Repositories/TaskRepository.cs b/GrpcTodo.Server/Application/Repositories/TaskRepository.cs index b2f6bda..5e59751 100644 --- a/GrpcTodo.Server/Application/Repositories/TaskRepository.cs +++ b/GrpcTodo.Server/Application/Repositories/TaskRepository.cs @@ -34,6 +34,23 @@ public async Task CreateAsync(Guid id, string name, Guid userId) }); } + public async Task DeleteAsync(Guid id) + { + using var connection = _context.CreateConnection(); + + await connection.ExecuteAsync(TaskQueries.Delete, new + { + id + }); + } + + public async Task FindByShortIdAsync(string id) + { + using var connection = _context.CreateConnection(); + + return await connection.QueryFirstOrDefaultAsync(TaskQueries.FindByShortId, new { id = id + '%' }); + } + public async Task FindByNameAsync(string name) { using var connection = _context.CreateConnection(); diff --git a/GrpcTodo.Server/Domain/Repositories/ITaskRepository.cs b/GrpcTodo.Server/Domain/Repositories/ITaskRepository.cs index a8f39eb..07950ac 100644 --- a/GrpcTodo.Server/Domain/Repositories/ITaskRepository.cs +++ b/GrpcTodo.Server/Domain/Repositories/ITaskRepository.cs @@ -6,8 +6,10 @@ public interface ITaskRepository { public Task CreateAsync(Guid id, string name, Guid userId); public Task FindByNameAsync(string name); + public Task FindByShortIdAsync(string id); public Task UpdateTaskNameAsync(Guid id, string name); public Task CompleteAsync(Guid id); public Task UncompleteAsync(Guid id); public Task> ListAsync(Guid userId); + public Task DeleteAsync(Guid id); } diff --git a/GrpcTodo.Server/Domain/UseCases/Tasks/DeleteTaskUseCase.cs b/GrpcTodo.Server/Domain/UseCases/Tasks/DeleteTaskUseCase.cs new file mode 100644 index 0000000..f6cd003 --- /dev/null +++ b/GrpcTodo.Server/Domain/UseCases/Tasks/DeleteTaskUseCase.cs @@ -0,0 +1,28 @@ +using GrpcTodo.Server.Domain.Repositories; + +namespace GrpcTodo.Server.Domain.UseCases.Tasks; + +public sealed class DeleteTaskUseCase +{ + private readonly ITaskRepository _taskRepository; + + public DeleteTaskUseCase(ITaskRepository taskRepository) + { + _taskRepository = taskRepository; + } + + public async Task ExecuteAsync(Guid userId, DeleteTaskUseCaseInput request) + { + var task = await _taskRepository.FindByShortIdAsync(request.Id); + + if (task is null) + throw new NotFoundException("this task does not exists"); + + if (task.UserId != userId) + throw new DeniedException("this task does not belongs to you"); + + await _taskRepository.DeleteAsync(task.Id); + } +} + +public sealed record DeleteTaskUseCaseInput(string Id); \ No newline at end of file diff --git a/GrpcTodo.Server/GrpcServices/TaskGrpcService.cs b/GrpcTodo.Server/GrpcServices/TaskGrpcService.cs index a5147c5..ad5c747 100644 --- a/GrpcTodo.Server/GrpcServices/TaskGrpcService.cs +++ b/GrpcTodo.Server/GrpcServices/TaskGrpcService.cs @@ -14,15 +14,18 @@ public sealed class TaskGrpcService : TaskItem.TaskItemBase private readonly IAuthMiddleware _authMiddleware; private readonly CreateTaskUseCase _createTaskUseCase; private readonly ListAllTasksUseCase _listAllTasksUseCase; + private readonly DeleteTaskUseCase _deleteTaskUseCase; public TaskGrpcService( CreateTaskUseCase createTaskUseCase, ListAllTasksUseCase listAllTasksUseCase, + DeleteTaskUseCase deleteTaskUseCase, IAuthMiddleware authMiddleware) { _createTaskUseCase = createTaskUseCase; _listAllTasksUseCase = listAllTasksUseCase; _authMiddleware = authMiddleware; + _deleteTaskUseCase = deleteTaskUseCase; } public override async Task Create(TaskCreateRequest request, ServerCallContext context) @@ -60,4 +63,15 @@ public override async Task ListAll(TaskListRequest request, Se return tasks; } + + public override async Task Delete(TaskDeleteRequest request, ServerCallContext context) + { + var credentials = new Credentials(request.AccessToken); + + var input = new DeleteTaskUseCaseInput(request.TaskId); + + await _authMiddleware.Authenticate(credentials, input, _deleteTaskUseCase.ExecuteAsync); + + return new TaskDeleteResponse(); + } } diff --git a/GrpcTodo.Server/Infra/Queries/TaskQueries.cs b/GrpcTodo.Server/Infra/Queries/TaskQueries.cs index 59c8ac3..e1f5061 100644 --- a/GrpcTodo.Server/Infra/Queries/TaskQueries.cs +++ b/GrpcTodo.Server/Infra/Queries/TaskQueries.cs @@ -2,9 +2,11 @@ namespace GrpcTodo.Server.Infra.Queries; public static class TaskQueries { + public const string Delete = @"DELETE FROM ""task"" WHERE id = @id"; public const string Complete = ""; public const string Create = """INSERT INTO "task" (id, user_id, name, created_at) VALUES (@id, @userId, @name, @createdAt)"""; public const string FindByName = @"SELECT id, user_id as userId, name, completed, created_at as CreatedAt FROM ""task"" WHERE LOWER(name) = @name;"; + public const string FindByShortId = @"SELECT id, user_id as userId, name, completed, created_at as CreatedAt FROM ""task"" WHERE id::text LIKE @id;"; public const string List = """SELECT id, user_id as UserId, name, completed, created_at as CreatedAt FROM "task" WHERE user_id = @userId;"""; public const string Uncomplete = ""; public const string UpdateTaskName = ""; diff --git a/GrpcTodo.Server/IoC/DependencyInjection.cs b/GrpcTodo.Server/IoC/DependencyInjection.cs index e4ccb4f..1bf2544 100644 --- a/GrpcTodo.Server/IoC/DependencyInjection.cs +++ b/GrpcTodo.Server/IoC/DependencyInjection.cs @@ -27,6 +27,7 @@ public static IServiceCollection AddIoC(this IServiceCollection services) services.AddSingleton(); // use cases + services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); diff --git a/GrpcTodo.SharedKernel/Exceptions/DeniedException.cs b/GrpcTodo.SharedKernel/Exceptions/DeniedException.cs new file mode 100644 index 0000000..0791ef1 --- /dev/null +++ b/GrpcTodo.SharedKernel/Exceptions/DeniedException.cs @@ -0,0 +1,12 @@ +using Grpc.Core; + +namespace GrpcTodo.SharedKernel.Exceptions; + +public sealed class DeniedException : RpcException +{ + public DeniedException(string message) : base(new Status( + StatusCode.PermissionDenied, + message + ), message) + { } +} \ No newline at end of file diff --git a/GrpcTodo.SharedKernel/Protos/task/requests.proto b/GrpcTodo.SharedKernel/Protos/task/requests.proto index dd29d8b..4628aad 100644 --- a/GrpcTodo.SharedKernel/Protos/task/requests.proto +++ b/GrpcTodo.SharedKernel/Protos/task/requests.proto @@ -10,3 +10,8 @@ message TaskCreateRequest { message TaskListRequest { string accessToken = 1; } + +message TaskDeleteRequest { + string accessToken = 1; + string taskId = 2; +} \ No newline at end of file diff --git a/GrpcTodo.SharedKernel/Protos/task/responses.proto b/GrpcTodo.SharedKernel/Protos/task/responses.proto index a3b3560..56eb9e1 100644 --- a/GrpcTodo.SharedKernel/Protos/task/responses.proto +++ b/GrpcTodo.SharedKernel/Protos/task/responses.proto @@ -6,6 +6,9 @@ message TaskCreateResponse { string id = 1; } +message TaskDeleteResponse { +} + message TaskListResponseItem { string id = 1; string name = 2; diff --git a/GrpcTodo.SharedKernel/Protos/task/service.proto b/GrpcTodo.SharedKernel/Protos/task/service.proto index 405214a..4d2ef99 100644 --- a/GrpcTodo.SharedKernel/Protos/task/service.proto +++ b/GrpcTodo.SharedKernel/Protos/task/service.proto @@ -8,5 +8,6 @@ package grpc_todo.shared_kernel.protos.tasks; service TaskItem { rpc Create(requests.TaskCreateRequest) returns (responses.TaskCreateResponse); + rpc Delete(requests.TaskDeleteRequest) returns (responses.TaskDeleteResponse); rpc ListAll(requests.TaskListRequest) returns (responses.TaskListResponse); }