share tactic to team and user
continuous-integration/drone/push Build is passing Details

shareTactic
Vivien DUFOUR 1 year ago
parent 5e142f4604
commit f1b4f53cd4

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<ActiveDebugProfile>https</ActiveDebugProfile>
</PropertyGroup>
</Project>

@ -151,4 +151,5 @@ public class TacticController(ITacticService service, IContextAccessor accessor)
await service.SetTacticStepContent(tacticId, stepId, JsonSerializer.Serialize(req.Content)); await service.SetTacticStepContent(tacticId, stepId, JsonSerializer.Serialize(req.Content));
return Ok(); return Ok();
} }
} }

@ -1,6 +1,7 @@
using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations;
using API.Context; using API.Context;
using API.Validation; using API.Validation;
using AppContext.Entities;
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Model; using Model;
@ -10,7 +11,7 @@ namespace API.Controllers;
[ApiController] [ApiController]
[Authorize] [Authorize]
public class TeamsController(ITeamService service, IContextAccessor accessor) : ControllerBase public class TeamsController(ITeamService service, ITacticService tactics,IContextAccessor accessor) : ControllerBase
{ {
public record CreateTeamRequest( public record CreateTeamRequest(
[Name] string Name, [Name] string Name,
@ -74,4 +75,34 @@ public class TeamsController(ITeamService service, IContextAccessor accessor) :
var removed = await service.RemoveMember(teamId, userId); var removed = await service.RemoveMember(teamId, userId);
return removed ? Ok() : NotFound(); return removed ? Ok() : NotFound();
} }
public record ShareTacticToTeamRequest(
int TacticId,
int TeamId
);
[HttpPost("/team/share-tactic")]
[Authorize]
public async Task<IActionResult> ShareTactic([FromBody] ShareTacticToTeamRequest sharedTactic)
{
var userId = accessor.CurrentUserId(HttpContext);
var success = await tactics.ShareTactic(sharedTactic.TacticId, null, sharedTactic.TeamId);
return success ? Ok() : BadRequest();
}
[HttpGet("/tactics/shared/team/{teamId:int}")]
[Authorize]
public async Task<IActionResult> GetSharedTacticsToTeam(int teamId)
{
var currentUserId = accessor.CurrentUserId(HttpContext);
if (!await service.IsUserInTeam(currentUserId, teamId))
{
return Unauthorized();
}
var sharedTactics = await service.GetSharedTacticsToTeam(teamId);
return sharedTactics != null ? Ok(sharedTactics) : NotFound();
}
} }

@ -1,6 +1,7 @@
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using API.Context; using API.Context;
using API.DTO; using API.DTO;
using AppContext.Entities;
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Model; using Model;
@ -35,4 +36,45 @@ public class UsersController(IUserService users, ITeamService teams, ITacticServ
var userTactics = await tactics.ListTacticsOf(userId); var userTactics = await tactics.ListTacticsOf(userId);
return new GetUserDataResponse(userTeams.ToArray(), userTactics.Select(t => t.ToDto()).ToArray()); return new GetUserDataResponse(userTeams.ToArray(), userTactics.Select(t => t.ToDto()).ToArray());
} }
public record ShareTacticToUserRequest(
int TacticId,
int UserId
);
[HttpPost("/user/share-tactic")]
[Authorize]
public async Task<IActionResult> ShareTactic([FromBody] ShareTacticToUserRequest sharedTactic)
{
var currentUserId = accessor.CurrentUserId(HttpContext);
var tactic = await tactics.GetTactic(sharedTactic.TacticId);
if (tactic == null)
{
return NotFound();
}
if (currentUserId != tactic.OwnerId)
{
return Unauthorized();
}
var result = await tactics.ShareTactic(sharedTactic.TacticId, sharedTactic.UserId, null);
return result ? Ok() : NotFound();
}
[HttpGet("/tactics/shared/user/{userId:int}")]
[Authorize]
public async Task<IActionResult> GetSharedTacticsToUser(int userId)
{
var currentUserId = accessor.CurrentUserId(HttpContext);
if (currentUserId != userId)
{
return Unauthorized();
}
var sharedTactics = await users.GetSharedTacticsToUser(userId);
return sharedTactics != null ? Ok(sharedTactics) : NotFound();
}
} }

@ -13,6 +13,8 @@ public class AppContext : DbContext
public DbSet<TeamEntity> Teams { get; init; } public DbSet<TeamEntity> Teams { get; init; }
public DbSet<MemberEntity> Members { get; init; } public DbSet<MemberEntity> Members { get; init; }
public DbSet<TacticStepEntity> TacticSteps { get; set; } public DbSet<TacticStepEntity> TacticSteps { get; set; }
public DbSet<SharedTacticEntity> SharedTactics { get; set; }
public AppContext() public AppContext()
{ {

@ -0,0 +1,12 @@
using System.ComponentModel.DataAnnotations;
namespace AppContext.Entities
{
public class SharedTacticEntity
{
[Key] public int Id { get; set; }
public int TacticId { get; set; }
public int? SharedWithUserId { get; set; }
public int? SharedWithTeamId { get; set; }
}
}

@ -37,4 +37,9 @@ public static class EntitiesToModels
{ {
return new Member(entity.TeamId, entity.UserId, entity.Role); return new Member(entity.TeamId, entity.UserId, entity.Role);
} }
public static SharedTactic ToModel(this SharedTacticEntity entity)
{
return new SharedTactic(entity.Id, entity.TacticId, entity.SharedWithUserId, entity.SharedWithTeamId);
}
} }

@ -152,4 +152,31 @@ public class DbTacticService(AppContext.AppContext context) : ITacticService
return await context.SaveChangesAsync() > 0; return await context.SaveChangesAsync() > 0;
} }
public async Task<bool> ShareTactic(int tacticId, int? userId, int? teamId)
{
var sharedTactic = new SharedTacticEntity
{
TacticId = tacticId,
SharedWithUserId = userId,
SharedWithTeamId = teamId
};
await context.SharedTactics.AddAsync(sharedTactic);
return await context.SaveChangesAsync() > 0;
}
public async Task<bool> UnshareTactic(int tacticId, int? userId, int? teamId)
{
var sharedTactic = await context.SharedTactics
.FirstOrDefaultAsync(st => st.TacticId == tacticId && st.SharedWithUserId == userId && st.SharedWithTeamId == teamId);
if (sharedTactic == null)
{
return false;
}
context.SharedTactics.Remove(sharedTactic);
return await context.SaveChangesAsync() > 0;
}
} }

@ -83,6 +83,29 @@ public class DbTeamService(AppContext.AppContext context) : ITeamService
return await context.SaveChangesAsync() > 0; return await context.SaveChangesAsync() > 0;
} }
public async Task<IEnumerable<Tactic>> GetSharedTacticsToTeam(int teamId)
{
var sharedTactics = await context.SharedTactics
.Where(st => st.SharedWithTeamId == teamId)
.ToListAsync();
var tactics = new List<Tactic>();
foreach (var sharedTactic in sharedTactics)
{
var tactic = await context.Tactics
.Where(t => t.Id == sharedTactic.TacticId)
.Select(t => t.ToModel())
.FirstOrDefaultAsync();
if (tactic != null)
{
tactics.Add(tactic);
}
}
return tactics;
}
public IEnumerable<Member> GetMembersOf(int teamId) public IEnumerable<Member> GetMembersOf(int teamId)
{ {
@ -121,4 +144,10 @@ public class DbTeamService(AppContext.AppContext context) : ITeamService
.ExecuteDeleteAsync(); .ExecuteDeleteAsync();
return await context.SaveChangesAsync() > 0; return await context.SaveChangesAsync() > 0;
} }
public async Task<bool> IsUserInTeam(int userId, int teamId)
{
return await context.Members
.AnyAsync(m => m.TeamId == teamId && m.UserId == userId);
}
} }

@ -94,4 +94,27 @@ public class DbUserService(AppContext.AppContext context) : IUserService
.FirstOrDefaultAsync(u => u.Email == email)) .FirstOrDefaultAsync(u => u.Email == email))
?.ToModel(); ?.ToModel();
} }
public async Task<IEnumerable<Tactic>> GetSharedTacticsToUser(int userId)
{
var sharedTactics = await context.SharedTactics
.Where(st => st.SharedWithUserId == userId)
.ToListAsync();
var tactics = new List<Tactic>();
foreach (var sharedTactic in sharedTactics)
{
var tactic = await context.Tactics
.Where(t => t.Id == sharedTactic.TacticId)
.Select(t => t.ToModel())
.FirstOrDefaultAsync();
if (tactic != null)
{
tactics.Add(tactic);
}
}
return tactics;
}
} }

@ -0,0 +1,3 @@
namespace Model;
public record SharedTactic(int Id, int TacticId, int? SharedWithUserId, int? SharedWithTeamId);

@ -23,4 +23,7 @@ public interface ITacticService
public Task<IEnumerable<Tactic>> ListUserTactics(int userId); public Task<IEnumerable<Tactic>> ListUserTactics(int userId);
public Task<int?> AddTacticStep(int tacticId, int parentStepId, string initialJson); public Task<int?> AddTacticStep(int tacticId, int parentStepId, string initialJson);
public Task<bool> RemoveTacticStep(int tacticId, int stepId); public Task<bool> RemoveTacticStep(int tacticId, int stepId);
public Task<bool> ShareTactic(int tacticId, int? userId, int? teamId);
public Task<bool> UnshareTactic(int tacticId, int? userId, int? teamId);
} }

@ -23,4 +23,8 @@ public interface ITeamService
public Task<bool> UpdateTeam(Team team); public Task<bool> UpdateTeam(Team team);
public Task<IEnumerable<Tactic>> GetSharedTacticsToTeam(int teamId);
public Task<bool> IsUserInTeam(int userId, int teamId);
} }

@ -22,4 +22,7 @@ public interface IUserService
public Task<User?> Authorize(string email, string password); public Task<User?> Authorize(string email, string password);
public Task<IEnumerable<Tactic>> GetSharedTacticsToUser(int userId);
} }

@ -1,6 +1,8 @@
using API.Controllers; using API.Controllers;
using AppContext.Entities;
using DbServices; using DbServices;
using FluentAssertions; using FluentAssertions;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Data.Sqlite; using Microsoft.Data.Sqlite;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using Model; using Model;
@ -46,4 +48,12 @@ public class UsersControllerTest
var result = await controller.GetUserData(); var result = await controller.GetUserData();
result.Should().BeEquivalentTo(new UsersController.GetUserDataResponse([], [])); result.Should().BeEquivalentTo(new UsersController.GetUserDataResponse([], []));
} }
[Fact]
public async Task ShareTacticTest()
{
var controller = GetUserController(1);
var result = await controller.ShareTactic(new UsersController.ShareTacticToUserRequest(1, 2));
result.Should().BeOfType<OkResult>();
}
} }
Loading…
Cancel
Save