Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 52 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
name: CI

on:
push:
branches:
- main

paths:
- "Homeworks/06 Настройка CI/**"

workflow_dispatch:

env:
REGISTRY: ghcr.io
TAG: latest

jobs:
build-test-push:
runs-on: ubuntu-latest

permissions:
contents: read
packages: write

steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Log in to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: Convert repository name to lowercase
run: |
REPO_LOWER=$(echo "${{ github.repository }}" | tr '[:upper:]' '[:lower:]')
echo "IMAGE_NAME=${REPO_LOWER}/promocode-factory-api" >> $GITHUB_ENV

- name: build of test
uses: docker/build-push-action@v5
with:
context: "Homeworks/06 Настройка CI/src"
file: "Homeworks/06 Настройка CI/src/Dockerfile"
push: true
tags: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ env.TAG }}

- name: Print image name
run: |
echo "Образ успешно собран и запушен:"
echo "${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ env.TAG }}"
7 changes: 7 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
################################################################################
# This .gitignore file was automatically created by Microsoft(R) Visual Studio.
################################################################################

/.vs
/.gitignore
/.gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using PromoCodeFactory.Core.Abstractions.Repositories;
using PromoCodeFactory.Core.Domain;
using PromoCodeFactory.Core.Exceptions;
using System.Collections.Concurrent;

namespace PromoCodeFactory.DataAccess.Repositories;
Expand All @@ -13,27 +14,43 @@ public InMemoryRepository(IEnumerable<T> data)
_data = new ConcurrentDictionary<Guid, T>(data.Select(e => new KeyValuePair<Guid, T>(e.Id, e)));
}
public Task<IReadOnlyCollection<T>> GetAll(CancellationToken ct)
{
{
return Task.FromResult((IReadOnlyCollection<T>)_data.Values);
}

public Task<T?> GetById(Guid id, CancellationToken ct)
{
throw new NotImplementedException();
return _data.TryGetValue(id, out var result) ?
Task.FromResult((T?)result) :
Task.FromResult((T?)null);
}

public Task Add(T entity, CancellationToken ct)
{
throw new NotImplementedException();
if (_data.TryAdd(entity.Id, entity))
return Task.CompletedTask;

throw new InvalidOperationException($"Не удалось добавить элемент типа \"{typeof(T).Name}\" с Id {entity.Id}");
}

public Task Update(T entity, CancellationToken ct)
{
throw new NotImplementedException();
if (_data.ContainsKey(entity.Id))
{
if (_data.TryUpdate(entity.Id, entity, _data[entity.Id]))
return Task.CompletedTask;

throw new InvalidOperationException($"Не удалось обновить элемент типа \"{typeof(T).Name}\" с Id {entity.Id}");
}

throw new EntityNotFoundException(entity.GetType(), entity.Id);
}

public Task Delete(Guid id, CancellationToken ct)
{
throw new NotImplementedException();
{
if (_data.TryRemove(id, out _))
return Task.CompletedTask;

throw new EntityNotFoundException(typeof(T), id);
}
}
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using Microsoft.AspNetCore.Http.HttpResults;
using Microsoft.AspNetCore.Mvc;
using PromoCodeFactory.WebHost.Mapping;
using PromoCodeFactory.WebHost.Models;
Expand Down Expand Up @@ -34,7 +35,11 @@ public async Task<ActionResult<IEnumerable<EmployeeShortResponse>>> Get(Cancella
[ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status404NotFound)]
public async Task<ActionResult<EmployeeResponse>> GetById([FromRoute] Guid id, CancellationToken ct)
{
throw new NotImplementedException();
var employee = await employeeRepository.GetById(id, ct);

return employee is null ?
NotFound(new ProblemDetails { Title = "Ошибка получения", Detail = $"Сотрудник с таким id = \"{id}\" не найден." }) :
Ok( Mapper.ToEmployeeResponse(employee) );
}

/// <summary>
Expand All @@ -44,9 +49,23 @@ public async Task<ActionResult<EmployeeResponse>> GetById([FromRoute] Guid id, C
[ProducesResponseType(typeof(EmployeeResponse), StatusCodes.Status201Created)]
[ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status400BadRequest)]
public async Task<ActionResult<EmployeeResponse>> Create([FromBody] EmployeeCreateRequest request, CancellationToken ct)
{
throw new NotImplementedException();
}
{
var roles = await roleRepository.GetAll(ct);
var role = roles.FirstOrDefault(r => r.Id == request.RoleId);

if (role is null)
return BadRequest(new ProblemDetails { Title = "Ошибка создания", Detail = $"Роль с указанным id = \"{request.RoleId}\" не найдена." });
try
{
await employeeRepository.Add(Mapper.ToEmployee(request, role), ct);
}
catch (InvalidOperationException ex)
{
return BadRequest(new ProblemDetails { Title = "Ошибка создания", Detail = ex.Message } );
}

return Created();
}

/// <summary>
/// Обновить сотрудника
Expand All @@ -59,8 +78,36 @@ public async Task<ActionResult<EmployeeResponse>> Update(
[FromRoute] Guid id,
[FromBody] EmployeeUpdateRequest request,
CancellationToken ct)
{
throw new NotImplementedException();
{
var employee = await employeeRepository.GetById(id, ct);

if (employee is null)
return NotFound(new ProblemDetails { Title = "Ошибка обновления", Detail = $"Сотрудник с таким id = \"{id}\" не найден." } );

var roles = await roleRepository.GetAll(ct);
var role = roles.FirstOrDefault(r => r.Id == request.RoleId);
if (role is null)
return BadRequest(new ProblemDetails { Title = "Ошибка обновления", Detail = $"Некорректный id = \"{id}\" роли. Роль с таким id не найдена." } );

employee.FirstName = request.FirstName;
employee.LastName = request.LastName;
employee.Email = request.Email;
employee.Role = role;

try
{
await employeeRepository.Update(employee, ct);
}
catch (InvalidOperationException ex)
{
return BadRequest(new ProblemDetails { Title = "Ошибка обновления", Detail = ex.Message });
}
catch (EntityNotFoundException ex)
{
return NotFound(new ProblemDetails { Title = "Ошибка обновления", Detail = ex.Message });
}

return Ok(Mapper.ToEmployeeResponse(employee));
}

/// <summary>
Expand All @@ -73,6 +120,20 @@ public async Task<IActionResult> Delete(
[FromRoute] Guid id,
CancellationToken ct)
{
throw new NotImplementedException();
var employee = await employeeRepository.GetById(id, ct);

if (employee is null)
return NotFound(new ProblemDetails { Title = "Ошибка удаления", Detail = $"Сотрудник с таким id = \"{id}\" не найден." } );

try
{
await employeeRepository.Delete(employee.Id, ct);
}
catch (EntityNotFoundException ex)
{
return NotFound(new ProblemDetails { Title = "Ошибка удаления", Detail = ex.Message });
}

return NoContent();
}
}
Loading