Skip to content

Commit

Permalink
Merge develop (#234)
Browse files Browse the repository at this point in the history
* add a patch endpoint to update a user group of an account

* a fix in xml comments

* format code

* Exposes setting product user groups to API

* fix Jonas comments

* authorize only board for the patch endpoint

* uncomment the board authorization line

* format code

* Update documentation examples

* Remove obsolete call to get user groups of product

* change access to endpoint

* Test update product user groups

* Removes second call to DB to update user groups

* Removes redundant database call

* Small fixes to decrease unnecessary code

* Remove code smells

* Fix last code smell

* Add productusergroups to get products (#231)

---------

Co-authored-by: Hubert <[email protected]>
Co-authored-by: A-Guldborg <[email protected]>
Co-authored-by: Jonas Anker Rasmussen <[email protected]>
Co-authored-by: A-Guldborg <[email protected]>
Co-authored-by: Hubert Wójcik <[email protected]>
  • Loading branch information
6 people authored Dec 7, 2023
1 parent fe59ee6 commit baab556
Show file tree
Hide file tree
Showing 11 changed files with 267 additions and 23 deletions.
26 changes: 26 additions & 0 deletions coffeecard/CoffeeCard.Library/Services/v2/AccountService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
using CoffeeCard.Models.DataTransferObjects.v2.User;
using CoffeeCard.Models.Entities;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Serilog;

Expand Down Expand Up @@ -200,6 +201,31 @@ private async Task<User> GetAccountByEmailAsync(string email)
return user;
}

public async Task UpdateUserGroup(UserGroup userGroup, int userId)
{
User user = await GetUserByIdAsync(userId);

user.UserGroup = userGroup;

await _context.SaveChangesAsync();
}

private async Task<User> GetUserByIdAsync(int id)
{
var user = await _context.Users
.Where(u => u.Id == id)
.FirstOrDefaultAsync();

if (user == null)
{
Log.Error("No user was found by user id: {id}", id);
throw new EntityNotFoundException($"No user was found by user id: {id}");
}

return user;
}


private static string EscapeName(string name)
{
return name.Trim('<', '>', '{', '}');
Expand Down
9 changes: 8 additions & 1 deletion coffeecard/CoffeeCard.Library/Services/v2/IAccountService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using CoffeeCard.Common.Errors;
using CoffeeCard.Models.DataTransferObjects.v2.User;
using CoffeeCard.Models.Entities;
using Microsoft.AspNetCore.Mvc;

namespace CoffeeCard.Library.Services.v2
{
Expand Down Expand Up @@ -53,8 +54,14 @@ public interface IAccountService
/// Resend invite e-mail if user account is not already verified
/// </summary>
/// <param name="request">Email request</param>
/// <exception cref="ConflictException">User account is already verified</exception>
/// <exception cref="EntityNotFoundException">Email account not found</exception>
Task ResendAccountVerificationEmail(ResendAccountVerificationEmailRequest request);

/// <summary>
/// Update a userGroup of a user with a provided id
/// </summary>
/// <param name="userGroup"> The user group that will be updated </param>
/// <param name="id"> id of the user </param>
Task UpdateUserGroup(UserGroup userGroup, int id);
}
}
29 changes: 14 additions & 15 deletions coffeecard/CoffeeCard.Library/Services/v2/ProductService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -78,31 +78,24 @@ public async Task<ChangedProductResponse> AddProduct(AddProductRequest newProduc
Name = newProduct.Name,
NumberOfTickets = newProduct.NumberOfTickets,
ExperienceWorth = 0,
Visible = newProduct.Visible
Visible = newProduct.Visible,
ProductUserGroup = newProduct.AllowedUserGroups.Select(userGroup => new ProductUserGroup
{
UserGroup = userGroup
}).ToList()
};

_context.Products.Add(product);
await _context.SaveChangesAsync();

var productUserGroups = newProduct.AllowedUserGroups.Select(userGroup => new ProductUserGroup
{
ProductId = product.Id,
UserGroup = userGroup
}).ToList();

_context.ProductUserGroups.AddRange(productUserGroups);


await _context.SaveChangesAsync();


var result = new ChangedProductResponse
{
Price = product.Price,
Description = product.Description,
Name = product.Name,
NumberOfTickets = product.NumberOfTickets,
Visible = product.Visible
Visible = product.Visible,
AllowedUserGroups = newProduct.AllowedUserGroups
};

return result;
Expand All @@ -116,6 +109,11 @@ public async Task<ChangedProductResponse> UpdateProduct(UpdateProductRequest cha
product.NumberOfTickets = changedProduct.NumberOfTickets;
product.Name = changedProduct.Name;
product.Visible = changedProduct.Visible;
product.ProductUserGroup = changedProduct.AllowedUserGroups.Select(userGroup => new ProductUserGroup
{
ProductId = changedProduct.Id,
UserGroup = userGroup
}).ToList();

await _context.SaveChangesAsync();

Expand All @@ -125,7 +123,8 @@ public async Task<ChangedProductResponse> UpdateProduct(UpdateProductRequest cha
Description = product.Description,
Name = product.Name,
NumberOfTickets = product.NumberOfTickets,
Visible = product.Visible
Visible = product.Visible,
AllowedUserGroups = changedProduct.AllowedUserGroups
};

return result;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ namespace CoffeeCard.Models.DataTransferObjects.v2.Product
/// "Price": 25,
/// "NumberOfTickets": 10,
/// "Description": "xxx",
/// "Visible": true
/// "Visible": true,
/// "AllowedUserGroups": ["Manager", "Board"]
/// }
/// </example>
public class AddProductRequest
Expand Down Expand Up @@ -63,8 +64,13 @@ public class AddProductRequest
[DefaultValue(true)]
public bool Visible { get; set; } = true;

/// <summary>
/// Gets or sets the user groups that can access the product.
/// </summary>
/// <value> Product User Groups </value>
/// <example> Manager, Board </example>
[Required]
public IEnumerable<UserGroup> AllowedUserGroups { get; set; }
public IEnumerable<UserGroup> AllowedUserGroups { get; set; } = new List<UserGroup>();

}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using CoffeeCard.Models.Entities;

namespace CoffeeCard.Models.DataTransferObjects.v2.Product
{
Expand Down Expand Up @@ -51,5 +52,13 @@ public class ChangedProductResponse
/// <example> true </example>
[Required]
public bool Visible { get; set; }

/// <summary>
/// Gets or sets the user groups that can access the product.
/// </summary>
/// <value> Product User Groups </value>
/// <example> Manager, Board </example>
[Required]
public IEnumerable<UserGroup> AllowedUserGroups { get; set; } = new List<UserGroup>();
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using CoffeeCard.Models.Entities;

namespace CoffeeCard.Models.DataTransferObjects.v2.Product
{
Expand All @@ -13,7 +15,8 @@ namespace CoffeeCard.Models.DataTransferObjects.v2.Product
/// "NumberOfTickets": 10,
/// "Name": "Espresso",
/// "Description": "A coffee made by forcing steam through ground coffee beans.",
/// "Visible": false
/// "Visible": false,
/// "AllowedUserGroups": ["Manager", "Board"]
/// }
/// </example>
public class UpdateProductRequest
Expand Down Expand Up @@ -69,5 +72,13 @@ public class UpdateProductRequest
/// <example> true </example>
[DefaultValue(true)]
public bool Visible { get; set; } = true;

/// <summary>
/// Gets or sets the user groups that can access the product.
/// </summary>
/// <value> Product User Groups </value>
/// <example> Manager, Board </example>
[Required]
public IEnumerable<UserGroup> AllowedUserGroups { get; set; } = new List<UserGroup>();
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
using System.ComponentModel.DataAnnotations;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using CoffeeCard.Models.Entities;

namespace CoffeeCard.Models.DataTransferObjects.v2.Products
{
Expand All @@ -12,7 +14,8 @@ namespace CoffeeCard.Models.DataTransferObjects.v2.Products
/// "numberOfTickets": 10,
/// "name": "Coffee clip card",
/// "description": "Coffee clip card of 10 clips",
/// "isPerk": true
/// "isPerk": true,
/// "AllowedUserGroups": ["Manager", "Board"]
/// }
/// </example>
public class ProductResponse
Expand Down Expand Up @@ -64,5 +67,13 @@ public class ProductResponse
/// <example>true</example>
[Required]
public bool IsPerk { get; set; }

/// <summary>
/// Decides the user groups that can access the product.
/// </summary>
/// <value> Product User Groups </value>
/// <example> Manager, Board </example>
[Required]
public IEnumerable<UserGroup> AllowedUserGroups { get; set; } = new List<UserGroup>();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
using System.ComponentModel.DataAnnotations;
using CoffeeCard.Models.Entities;

namespace CoffeeCard.Models.DataTransferObjects.v2.User
{
/// <summary>
/// Update the UserGroup property of a user
/// </summary>
/// <example>
/// {
/// "UserGroup": "Barista"
/// }
/// </example>
public class UpdateUserGroupRequest
{
/// <summary>
/// The UserGroup of a user
/// </summary>
/// <value> UserGroup object </value>
/// <example> UserGroup.Barista </example>
[Required]
public UserGroup UserGroup { get; set; }
}
}
128 changes: 128 additions & 0 deletions coffeecard/CoffeeCard.Tests.Unit/Services/v2/ProductServiceTest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Threading.Tasks;
using CoffeeCard.Common.Configuration;
using CoffeeCard.Library.Persistence;
using CoffeeCard.Library.Services.v2;
using CoffeeCard.Models.DataTransferObjects.v2.Product;
using CoffeeCard.Models.Entities;
using Microsoft.EntityFrameworkCore;
using Xunit;

namespace CoffeeCard.Tests.Unit.Services.v2
{
public class ProductServiceTest
{
[Fact(DisplayName = "UpdateProduct removes ommitted user groups and only adds selected user groups")]
public async Task UpdateProduct_Removes_Omitted_UserGroups()
{
var builder = new DbContextOptionsBuilder<CoffeeCardContext>()
.UseInMemoryDatabase(nameof(UpdateProduct_Removes_Omitted_UserGroups));

var databaseSettings = new DatabaseSettings
{
SchemaName = "test"
};
var environmentSettings = new EnvironmentSettings()
{
EnvironmentType = EnvironmentType.Test
};

await using var context = new CoffeeCardContext(builder.Options, databaseSettings, environmentSettings);
var p = new Product
{
Id = 1,
Name = "Coffee",
Description = "Coffee Clip card",
NumberOfTickets = 10,
Price = 10,
ExperienceWorth = 10,
Visible = true
};
await context.AddAsync(p);
await context.SaveChangesAsync();

await context.AddAsync(new ProductUserGroup
{
Product = p,
UserGroup = UserGroup.Barista
});

await context.AddAsync(new ProductUserGroup
{
Product = p,
UserGroup = UserGroup.Manager
});

await context.SaveChangesAsync();

using var productService = new ProductService(context);

await productService.UpdateProduct(new UpdateProductRequest()
{
Id = 1,
Visible = true,
Price = 10,
NumberOfTickets = 10,
Name = "Coffee",
Description = "Coffee Clip card",
AllowedUserGroups = new List<UserGroup>() { UserGroup.Customer, UserGroup.Board }
});

var expected = new List<UserGroup>
{
UserGroup.Customer, UserGroup.Board
};

var result = await productService.GetProductAsync(1);

Assert.Collection<UserGroup>(expected,
e => e.Equals(UserGroup.Customer),
e => e.Equals(UserGroup.Board));
}

[Fact(DisplayName = "AddProduct adds only selected user groups")]
public async Task AddProduct_Sets_Correct_UserGroups()
{
var builder = new DbContextOptionsBuilder<CoffeeCardContext>()
.UseInMemoryDatabase(nameof(AddProduct_Sets_Correct_UserGroups));

var databaseSettings = new DatabaseSettings
{
SchemaName = "test"
};
var environmentSettings = new EnvironmentSettings()
{
EnvironmentType = EnvironmentType.Test
};

await using var context = new CoffeeCardContext(builder.Options, databaseSettings, environmentSettings);

using var productService = new ProductService(context);

var p = new AddProductRequest
{
Name = "Coffee",
Description = "Coffee Clip card",
NumberOfTickets = 10,
Price = 10,
Visible = true,
AllowedUserGroups = new List<UserGroup> { UserGroup.Manager, UserGroup.Board }
};

await productService.AddProduct(p);

var expected = new List<UserGroup>
{
UserGroup.Manager, UserGroup.Board
};

var result = await productService.GetProductAsync(1);

Assert.Collection<UserGroup>(expected,
e => e.Equals(UserGroup.Customer),
e => e.Equals(UserGroup.Board));
}
}
}
Loading

0 comments on commit baab556

Please sign in to comment.