Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merge develop #234

Merged
merged 22 commits into from
Dec 7, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
ec83cf1
add a patch endpoint to update a user group of an account
HubertWojcik10 Nov 11, 2023
db51706
a fix in xml comments
HubertWojcik10 Nov 11, 2023
1215be8
format code
HubertWojcik10 Nov 11, 2023
cbf89f3
Exposes setting product user groups to API
A-Guldborg Nov 12, 2023
4823479
Merge branch 'develop' into 217-new-admin-endpoints
jonasanker Nov 12, 2023
f4d2be6
Merge branch 'develop' into fix-set-product-user-groups
jonasanker Nov 12, 2023
cdf7bc1
fix Jonas comments
HubertWojcik10 Nov 16, 2023
66c9b98
authorize only board for the patch endpoint
HubertWojcik10 Nov 16, 2023
da5215a
uncomment the board authorization line
HubertWojcik10 Nov 16, 2023
45b4c45
format code
HubertWojcik10 Nov 16, 2023
b74fa82
Update documentation examples
A-Guldborg Nov 23, 2023
a018228
Remove obsolete call to get user groups of product
A-Guldborg Nov 23, 2023
613b776
change access to endpoint
HubertWojcik10 Nov 23, 2023
ae5239d
Test update product user groups
A-Guldborg Nov 24, 2023
636d6ae
Removes second call to DB to update user groups
A-Guldborg Nov 27, 2023
04b4419
Removes redundant database call
A-Guldborg Nov 27, 2023
071d3fa
Small fixes to decrease unnecessary code
A-Guldborg Nov 27, 2023
e9fb98b
Remove code smells
A-Guldborg Nov 28, 2023
abaa294
Fix last code smell
A-Guldborg Nov 28, 2023
bae327e
Merge pull request #223 from AnalogIO/fix-set-product-user-groups
A-Guldborg Nov 28, 2023
0789c28
Add productusergroups to get products (#231)
A-Guldborg Nov 30, 2023
7b48f72
Merge pull request #222 from AnalogIO/217-new-admin-endpoints
HubertWojcik10 Dec 7, 2023
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
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
Loading