Implement add feedback operation in FeedbackReceiversController.cs.

This commit is contained in:
Denis-Cosmin Nutiu 2021-07-04 20:34:10 +03:00
parent eca110d669
commit 398f1c7e2f
20 changed files with 214 additions and 102 deletions

View file

@ -10,28 +10,23 @@ namespace Retroactiune.Core.Entities
/// </summary>
public class Feedback
{
private uint _rating;
public Feedback()
{
Id = ObjectId.GenerateNewId().ToString();
CreatedAt = DateTime.UtcNow;
}
[BsonId, JsonPropertyName("id")]
[BsonRepresentation(BsonType.ObjectId)]
public string Id { get; set; }
[JsonPropertyName("feedback_receiver_id")]
[BsonRepresentation(BsonType.ObjectId)]
public string FeedbackReceiverId { get; set; }
[JsonPropertyName("rating")]
public uint Rating
{
get => _rating;
set
{
if (value <= 5)
{
_rating = value;
}
else
{
throw new ArgumentException();
}
}
}
public uint Rating { get; set; }
[JsonPropertyName("description")] public string Description { get; set; }

View file

@ -11,6 +11,12 @@ namespace Retroactiune.Core.Entities
/// </summary>
public class FeedbackReceiver
{
public FeedbackReceiver()
{
Id = ObjectId.GenerateNewId().ToString();
CreatedAt = DateTime.UtcNow;
}
[BsonId, JsonPropertyName("id")]
[BsonRepresentation(BsonType.ObjectId)]
public string Id { get; set; }

View file

@ -1,6 +1,7 @@
using System;
using System.Runtime.CompilerServices;
using System.Text.Json.Serialization;
using Ardalis.GuardClauses;
using MongoDB.Bson;
using MongoDB.Bson.Serialization.Attributes;
@ -12,6 +13,13 @@ namespace Retroactiune.Core.Entities
/// </summary>
public class Token
{
public Token()
{
Id = ObjectId.GenerateNewId().ToString();
CreatedAt = DateTime.UtcNow;
}
[BsonId, JsonPropertyName("id")]
[BsonRepresentation(BsonType.ObjectId)]
public string Id { get; set; }
@ -41,5 +49,14 @@ namespace Retroactiune.Core.Entities
{
return RuntimeHelpers.GetHashCode(this);
}
public bool IsValid(FeedbackReceiver feedbackReceiver)
{
Guard.Against.Null(feedbackReceiver, nameof(feedbackReceiver));
var hasExpired = ExpiryTime != null && ExpiryTime <= DateTime.UtcNow;
var differentFeedbackReceiver = !FeedbackReceiverId.Equals(feedbackReceiver.Id);
var isUsed = TimeUsed != null;
return !(hasExpired || differentFeedbackReceiver || isUsed);
}
}
}

View file

@ -0,0 +1,17 @@
using System.Threading.Tasks;
using Retroactiune.Core.Entities;
namespace Retroactiune.Core.Interfaces
{
public interface IFeedbacksService
{
/// <summary>
/// Adds Feedback to a FeedbackReceiver.
/// </summary>
/// <param name="feedback">The feedback.</param>
/// <param name="receiver">The feedback receiver.</param>
/// <returns></returns>
public Task AddFeedbackAsync(Feedback feedback, FeedbackReceiver receiver);
}
}

View file

@ -23,14 +23,14 @@ namespace Retroactiune.Core.Interfaces
/// </summary>
/// <param name="tokenIds">A list of tokens to delete.</param>
/// <returns>The result of the delete operation.</returns>
public Task DeleteTokens(IEnumerable<string> tokenIds);
public Task DeleteTokensAsync(IEnumerable<string> tokenIds);
/// <summary>
/// List and filters tokens.
/// Finds and filters tokens.
/// </summary>
/// <param name="filters">Filters object for filtering results.</param>
/// <returns>A list of tokens matching the filters.</returns>
public Task<IEnumerable<Token>> ListTokens(TokenListFilters filters);
public Task<IEnumerable<Token>> FindAsync(TokenListFilters filters);
/// <summary>
/// Deletes tokens, by their associated FeedbackReceiverId.
@ -38,5 +38,11 @@ namespace Retroactiune.Core.Interfaces
/// <param name="feedbackReceiverIds">A list of FeedbackReceiverIDs.</param>
/// <returns>The result of the delete operation.</returns>
public Task DeleteManyByFeedbackReceiverIdAsync(IEnumerable<string> feedbackReceiverIds);
/// <summary>
/// Marks the token as being used.
/// </summary>
/// <param name="token">The token.</param>
public Task MarkTokenAsUsedAsync(Token token);
}
}

View file

@ -5,6 +5,7 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Ardalis.GuardClauses" Version="3.2.0" />
<PackageReference Include="MongoDB.Driver" Version="2.12.3" />
</ItemGroup>

View file

@ -0,0 +1,29 @@
using System.Threading.Tasks;
using Ardalis.GuardClauses;
using MongoDB.Driver;
using Retroactiune.Core.Entities;
using Retroactiune.Core.Interfaces;
namespace Retroactiune.Core.Services
{
public class FeedbacksService : IFeedbacksService
{
private readonly IMongoCollection<Feedback> _collection;
public FeedbacksService(IMongoClient client, IDatabaseSettings settings)
{
var database = client.GetDatabase(settings.DatabaseName);
_collection = database.GetCollection<Feedback>(settings.FeedbackCollectionName);
}
public async Task AddFeedbackAsync(Feedback feedback, FeedbackReceiver receiver)
{
// TODO: Unit test.
Guard.Against.Null(feedback, nameof(feedback));
Guard.Against.Null(receiver, nameof(receiver));
feedback.FeedbackReceiverId = receiver.Id;
await _collection.InsertOneAsync(feedback);
}
}
}

View file

@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Ardalis.GuardClauses;
using MongoDB.Driver;
using Retroactiune.Core.Entities;
using Retroactiune.Core.Interfaces;
@ -21,10 +22,7 @@ namespace Retroactiune.Core.Services
public async Task GenerateTokensAsync(int numberOfTokens, string feedbackReceiverGuid,
DateTime? expiryTime = null)
{
if (numberOfTokens <= 0)
{
throw new ArgumentException("numberOfTokens must be positive");
}
Guard.Against.Negative(numberOfTokens, nameof(numberOfTokens));
var token = new List<Token>();
for (var i = 0; i < numberOfTokens; i++)
@ -41,7 +39,7 @@ namespace Retroactiune.Core.Services
await _collection.InsertManyAsync(token);
}
public async Task DeleteTokens(IEnumerable<string> tokenIds)
public async Task DeleteTokensAsync(IEnumerable<string> tokenIds)
{
try
{
@ -54,7 +52,7 @@ namespace Retroactiune.Core.Services
}
}
public async Task<IEnumerable<Token>> ListTokens(TokenListFilters filters)
public async Task<IEnumerable<Token>> FindAsync(TokenListFilters filters)
{
var filterBuilder = new FilterDefinitionBuilder<Token>();
var activeFilters = new List<FilterDefinition<Token>>();
@ -119,5 +117,14 @@ namespace Retroactiune.Core.Services
throw new GenericServiceException($"Operation failed: {e.Message} {e.StackTrace}");
}
}
public async Task MarkTokenAsUsedAsync(Token token)
{
// TODO: Unit test.
var filterBuilder = new FilterDefinitionBuilder<Token>();
var updateBuilder = new UpdateDefinitionBuilder<Token>();
await _collection.UpdateOneAsync(filterBuilder.Eq(i => i.Id, token.Id),
updateBuilder.Set(i => i.TimeUsed, DateTime.UtcNow));
}
}
}

View file

@ -68,16 +68,8 @@ namespace Retroactiune.Tests.Retroactiune.Core.Services
await service.GenerateTokensAsync(3, "Hello", expiryTime);
// Assert
var item = new Token
{
Id = null,
ExpiryTime = expiryTime,
TimeUsed = null,
FeedbackReceiverId = "Hello",
CreatedAt = expiryTime
};
mongoCollectionMock.Verify(
i => i.InsertManyAsync(new[] {item, item, item},
i => i.InsertManyAsync(It.IsAny<IEnumerable<Token>>(),
It.IsAny<InsertManyOptions>(),
It.IsAny<CancellationToken>()), Times.Once);
}
@ -106,7 +98,7 @@ namespace Retroactiune.Tests.Retroactiune.Core.Services
// Test
var service = new TokensService(mongoClientMock.Object, mongoSettingsMock.Object);
await service.DeleteTokens(new[] {"test_id"});
await service.DeleteTokensAsync(new[] {"test_id"});
// Assert
mongoCollectionMock.Verify(
@ -145,7 +137,7 @@ namespace Retroactiune.Tests.Retroactiune.Core.Services
// Test
var service = new TokensService(mongoClientMock.Object, mongoSettingsMock.Object);
var result = await service.ListTokens(new TokenListFilters());
var result = await service.FindAsync(new TokenListFilters());
// Assert
Assert.IsType<List<Token>>(result);
@ -185,7 +177,7 @@ namespace Retroactiune.Tests.Retroactiune.Core.Services
// Test
var service = new TokensService(mongoClientMock.Object, mongoSettingsMock.Object);
var result = await service.ListTokens(new TokenListFilters
var result = await service.FindAsync(new TokenListFilters
{
Ids = new[] {"a", "b"},
FeedbackReceiverId = "abc",

View file

@ -23,10 +23,12 @@ namespace Retroactiune.Tests.Retroactiune.WebAPI.Controllers
var mapper = TestUtils.GetMapper();
var mockService = new Mock<IFeedbackReceiversService>();
var tokensService = new Mock<ITokensService>();
var feedbacksService = new Mock<IFeedbacksService>();
var logger = new Mock<ILogger<FeedbackReceiversController>>();
// Test
var controller = new FeedbackReceiversController(mockService.Object, tokensService.Object, mapper, null,
var controller = new FeedbackReceiversController(mockService.Object, tokensService.Object,
feedbacksService.Object, mapper, null,
logger.Object);
var result = await controller.Post(new List<FeedbackReceiverInDto>());
@ -42,10 +44,12 @@ namespace Retroactiune.Tests.Retroactiune.WebAPI.Controllers
var mapper = TestUtils.GetMapper();
var mockService = new Mock<IFeedbackReceiversService>();
var tokensService = new Mock<ITokensService>();
var feedbacksService = new Mock<IFeedbacksService>();
var logger = new Mock<ILogger<FeedbackReceiversController>>();
// Test
var controller = new FeedbackReceiversController(mockService.Object, tokensService.Object, mapper, null,
var controller = new FeedbackReceiversController(mockService.Object, tokensService.Object,
feedbacksService.Object, mapper, null,
logger.Object);
var result = await controller.Post(items);
@ -61,10 +65,12 @@ namespace Retroactiune.Tests.Retroactiune.WebAPI.Controllers
var mapper = TestUtils.GetMapper();
var mockService = new Mock<IFeedbackReceiversService>();
var tokensService = new Mock<ITokensService>();
var feedbacksService = new Mock<IFeedbacksService>();
var logger = new Mock<ILogger<FeedbackReceiversController>>();
// Test
var controller = new FeedbackReceiversController(mockService.Object, tokensService.Object, mapper, null,
var controller = new FeedbackReceiversController(mockService.Object, tokensService.Object,
feedbacksService.Object, mapper, null,
logger.Object);
var result = await controller.Delete("bad_guid_but_unit_test_works_cause_validation_doesnt");
@ -84,10 +90,12 @@ namespace Retroactiune.Tests.Retroactiune.WebAPI.Controllers
var mapper = TestUtils.GetMapper();
var mockService = new Mock<IFeedbackReceiversService>();
var tokensService = new Mock<ITokensService>();
var feedbacksService = new Mock<IFeedbacksService>();
var logger = new Mock<ILogger<FeedbackReceiversController>>();
// Test
var controller = new FeedbackReceiversController(mockService.Object, tokensService.Object, mapper, null,
var controller = new FeedbackReceiversController(mockService.Object, tokensService.Object,
feedbacksService.Object, mapper, null,
logger.Object);
var items = new[] {"bad_guid_but_unit_test_works_cause_validation_doesnt", "2", "3"};
var result = await controller.DeleteMany(items);
@ -106,12 +114,14 @@ namespace Retroactiune.Tests.Retroactiune.WebAPI.Controllers
var mapper = TestUtils.GetMapper();
var mockService = new Mock<IFeedbackReceiversService>();
var tokensService = new Mock<ITokensService>();
var feedbacksService = new Mock<IFeedbacksService>();
var logger = new Mock<ILogger<FeedbackReceiversController>>();
mockService.Setup(i => i.DeleteManyAsync(It.IsAny<IEnumerable<string>>()))
.ThrowsAsync(new GenericServiceException("op failed"));
// Test
var controller = new FeedbackReceiversController(mockService.Object, tokensService.Object, mapper, null,
var controller = new FeedbackReceiversController(mockService.Object, tokensService.Object,
feedbacksService.Object, mapper, null,
logger.Object);
var items = new[] {"bad_guid_but_unit_test_works_cause_validation_doesnt", "2", "3"};
var result = await controller.DeleteMany(items);
@ -129,12 +139,14 @@ namespace Retroactiune.Tests.Retroactiune.WebAPI.Controllers
var mapper = TestUtils.GetMapper();
var mockService = new Mock<IFeedbackReceiversService>();
var tokensService = new Mock<ITokensService>();
var feedbacksService = new Mock<IFeedbacksService>();
var logger = new Mock<ILogger<FeedbackReceiversController>>();
mockService.Setup(i => i.FindAsync(It.IsAny<IEnumerable<string>>(), null, null))
.ReturnsAsync(new[] {new FeedbackReceiver()});
// Test
var controller = new FeedbackReceiversController(mockService.Object, tokensService.Object, mapper, null,
var controller = new FeedbackReceiversController(mockService.Object, tokensService.Object,
feedbacksService.Object, mapper, null,
logger.Object);
var result = await controller.Get("bad_guid_but_unit_test_works_cause_validation_doesnt");
@ -152,10 +164,12 @@ namespace Retroactiune.Tests.Retroactiune.WebAPI.Controllers
var mapper = TestUtils.GetMapper();
var mockService = new Mock<IFeedbackReceiversService>();
var tokensService = new Mock<ITokensService>();
var feedbacksService = new Mock<IFeedbacksService>();
var logger = new Mock<ILogger<FeedbackReceiversController>>();
// Test
var controller = new FeedbackReceiversController(mockService.Object, tokensService.Object, mapper, null,
var controller = new FeedbackReceiversController(mockService.Object, tokensService.Object,
feedbacksService.Object, mapper, null,
logger.Object);
var result = await controller.Get("bad_guid_but_unit_test_works_cause_validation_doesnt");
@ -173,11 +187,13 @@ namespace Retroactiune.Tests.Retroactiune.WebAPI.Controllers
var mapper = TestUtils.GetMapper();
var mockService = new Mock<IFeedbackReceiversService>();
var tokensService = new Mock<ITokensService>();
var feedbacksService = new Mock<IFeedbacksService>();
var logger = new Mock<ILogger<FeedbackReceiversController>>();
var filterArr = filter as string[] ?? filter.ToArray();
// Test
var controller = new FeedbackReceiversController(mockService.Object, tokensService.Object, mapper, null,
var controller = new FeedbackReceiversController(mockService.Object, tokensService.Object,
feedbacksService.Object, mapper, null,
logger.Object);
var result = await controller.List(filterArr, offset, limit);

View file

@ -74,7 +74,7 @@ namespace Retroactiune.Tests.Retroactiune.WebAPI.Controllers
// Assert
Assert.IsType<NoContentResult>(result);
tokens.Verify(i => i.DeleteTokens(new[] {"my_guid"}), Times.Once);
tokens.Verify(i => i.DeleteTokensAsync(new[] {"my_guid"}), Times.Once);
}
[Fact]
@ -85,7 +85,7 @@ namespace Retroactiune.Tests.Retroactiune.WebAPI.Controllers
var feedbackService = new Mock<IFeedbackReceiversService>();
var tokens = new Mock<ITokensService>();
var logger = new Mock<ILogger<TokensController>>();
tokens.Setup(i => i.DeleteTokens(It.IsAny<IEnumerable<string>>()))
tokens.Setup(i => i.DeleteTokensAsync(It.IsAny<IEnumerable<string>>()))
.Throws(new GenericServiceException("op fail"));
// Test
@ -94,7 +94,7 @@ namespace Retroactiune.Tests.Retroactiune.WebAPI.Controllers
// Assert
Assert.IsType<BadRequestObjectResult>(result);
tokens.Verify(i => i.DeleteTokens(new[] {"my_guid"}), Times.Once);
tokens.Verify(i => i.DeleteTokensAsync(new[] {"my_guid"}), Times.Once);
}
[Fact]
@ -112,7 +112,7 @@ namespace Retroactiune.Tests.Retroactiune.WebAPI.Controllers
// Assert
Assert.IsType<NoContentResult>(result);
tokens.Verify(i => i.DeleteTokens(new[] {"my_guid", "b"}), Times.Once);
tokens.Verify(i => i.DeleteTokensAsync(new[] {"my_guid", "b"}), Times.Once);
}
[Fact]
@ -123,7 +123,7 @@ namespace Retroactiune.Tests.Retroactiune.WebAPI.Controllers
var feedbackService = new Mock<IFeedbackReceiversService>();
var tokens = new Mock<ITokensService>();
var logger = new Mock<ILogger<TokensController>>();
tokens.Setup(i => i.DeleteTokens(It.IsAny<IEnumerable<string>>()))
tokens.Setup(i => i.DeleteTokensAsync(It.IsAny<IEnumerable<string>>()))
.Throws(new GenericServiceException("op fail"));
// Test
@ -132,7 +132,7 @@ namespace Retroactiune.Tests.Retroactiune.WebAPI.Controllers
// Assert
Assert.IsType<BadRequestObjectResult>(result);
tokens.Verify(i => i.DeleteTokens(new[] {"my_guid", "b"}), Times.Once);
tokens.Verify(i => i.DeleteTokensAsync(new[] {"my_guid", "b"}), Times.Once);
}
[Fact]
@ -150,7 +150,7 @@ namespace Retroactiune.Tests.Retroactiune.WebAPI.Controllers
// Assert
Assert.IsType<OkObjectResult>(result);
tokens.Verify(i => i.ListTokens(It.IsAny<TokenListFilters>()), Times.Once);
tokens.Verify(i => i.FindAsync(It.IsAny<TokenListFilters>()), Times.Once);
}
[Fact]
@ -161,7 +161,7 @@ namespace Retroactiune.Tests.Retroactiune.WebAPI.Controllers
var feedbackService = new Mock<IFeedbackReceiversService>();
var tokens = new Mock<ITokensService>();
var logger = new Mock<ILogger<TokensController>>();
tokens.Setup(i => i.ListTokens(It.IsAny<TokenListFilters>()))
tokens.Setup(i => i.FindAsync(It.IsAny<TokenListFilters>()))
.Throws(new GenericServiceException("op fail"));
// Test
@ -170,7 +170,7 @@ namespace Retroactiune.Tests.Retroactiune.WebAPI.Controllers
// Assert
Assert.IsType<BadRequestObjectResult>(result);
tokens.Verify(i => i.ListTokens(It.IsAny<TokenListFilters>()), Times.Once);
tokens.Verify(i => i.FindAsync(It.IsAny<TokenListFilters>()), Times.Once);
}
}
}

View file

@ -1,9 +0,0 @@
using Microsoft.AspNetCore.Mvc;
namespace Retroactiune.Controllers
{
public class FeedbackController : ControllerBase
{
// TODO Add feedback, list feedback, delete feedback, ged feedback.
}
}

View file

@ -1,5 +1,4 @@
using System;
using System.Collections.Generic;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Threading.Tasks;
@ -24,15 +23,17 @@ namespace Retroactiune.Controllers
// Note: Probably refactor this to use an Aggregate object, need to learn more about aggregates..
private readonly IFeedbackReceiversService _feedbackReceiversService;
private readonly ITokensService _tokensService;
private readonly IFeedbacksService _feedbacksService;
private readonly IMapper _mapper;
private readonly ILogger _logger;
public FeedbackReceiversController(IFeedbackReceiversService feedbackReceiversService,
ITokensService tokensService, IMapper mapper,
ITokensService tokensService, IFeedbacksService feedbacksService, IMapper mapper,
IOptions<ApiBehaviorOptions> apiBehaviorOptions, ILogger<FeedbackReceiversController> logger)
{
_feedbackReceiversService = feedbackReceiversService;
_tokensService = tokensService;
_feedbacksService = feedbacksService;
_mapper = mapper;
_apiBehaviorOptions = apiBehaviorOptions;
_logger = logger;
@ -59,12 +60,7 @@ namespace Retroactiune.Controllers
return _apiBehaviorOptions?.Value.InvalidModelStateResponseFactory(ControllerContext);
}
var mappedItems = feedbackReceiversDto.Select(i =>
{
var result = _mapper.Map<FeedbackReceiver>(i);
result.CreatedAt = DateTime.UtcNow;
return result;
});
var mappedItems = feedbackReceiversDto.Select(i => _mapper.Map<FeedbackReceiver>(i));
await _feedbackReceiversService.CreateManyAsync(mappedItems);
@ -171,5 +167,57 @@ namespace Retroactiune.Controllers
});
}
}
/// <summary>
/// Add Feedback to a FeedbackReceiver.
/// </summary>
/// <param name="guid">The guid of the FeedbackReceiver to add feedback.</param>
/// <param name="feedbackInDto">The feedback dto.</param>
/// <response code="200">The feedback has been added.</response>
/// <response code="404">The request is invalid.</response>
/// <returns></returns>
[HttpPost("{guid}/feedbacks")]
[ProducesResponseType(typeof(NoContentResult), StatusCodes.Status204NoContent)]
[ProducesResponseType(typeof(BasicResponse), StatusCodes.Status400BadRequest)]
public async Task<IActionResult> AddFeedback(string guid, [FromBody] FeedbackInDto feedbackInDto)
{
// TODO: Unit & integration test.
var receivers = await _feedbackReceiversService.FindAsync(new[] {guid}, limit: 1);
var tokenEnum = await _tokensService.FindAsync(new TokenListFilters
{
Ids = new[] {feedbackInDto.TokenId}
});
var feedbackReceivers = receivers as FeedbackReceiver[] ?? receivers.ToArray();
var tokens = (tokenEnum as Token[] ?? tokenEnum.ToArray());
if (!feedbackReceivers.Any())
{
return BadRequest(new BasicResponse
{
Message = $"FeedbackReceiver with id {guid} not found."
});
}
if (tokens.Length == 0)
{
return BadRequest(new BasicResponse
{
Message = "Token not found."
});
}
var token = tokens[0];
if (!token.IsValid(feedbackReceivers[0]))
{
return BadRequest(new BasicResponse
{
Message = "Token is invalid."
});
}
var feedback = _mapper.Map<Feedback>(feedbackInDto);
await Task.WhenAll(_tokensService.MarkTokenAsUsedAsync(token),
_feedbacksService.AddFeedbackAsync(feedback, feedbackReceivers[0]));
return Ok();
}
}
}

View file

@ -45,7 +45,7 @@ namespace Retroactiune.Controllers
try
{
var tokenFilters = _mapper.Map<TokenListFilters>(filtersDto);
var response = await _tokensService.ListTokens(tokenFilters);
var response = await _tokensService.FindAsync(tokenFilters);
return Ok(response);
}
catch (GenericServiceException e)
@ -104,7 +104,7 @@ namespace Retroactiune.Controllers
{
try
{
await _tokensService.DeleteTokens(tokenIds);
await _tokensService.DeleteTokensAsync(tokenIds);
return NoContent();
}
catch (GenericServiceException e)
@ -133,7 +133,7 @@ namespace Retroactiune.Controllers
{
try
{
await _tokensService.DeleteTokens(new[] {guid});
await _tokensService.DeleteTokensAsync(new[] {guid});
return NoContent();
}
catch (GenericServiceException e)

View file

@ -1,5 +1,4 @@
using System;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations;
namespace Retroactiune.DataTransferObjects
{
@ -8,27 +7,12 @@ namespace Retroactiune.DataTransferObjects
/// </summary>
public class FeedbackInDto
{
private uint _rating;
[Required, StringLength(24, ErrorMessage = "invalid guid, must be 24 characters", MinimumLength = 24)]
public string FeedbackReceiverId { get; set; }
[Required]
public uint Rating
{
get => _rating;
set
{
if (value <= 5)
{
_rating = value;
}
else
{
throw new ArgumentException();
}
}
}
[Required, StringLength(24, ErrorMessage = "invalid guid, must be 24 characters", MinimumLength = 24)]
public string TokenId { get; set; }
[Required, Range(0, 5, ErrorMessage = "The rating is out of range. [0-5]")]
public uint Rating { get; set; }
[Required] public string Description { get; set; }
}

View file

@ -12,6 +12,7 @@ namespace Retroactiune
CreateMap<ListTokensFiltersDto, TokenListFilters>();
CreateMap<FeedbackReceiver, FeedbackReceiverInDto>().ReverseMap();
CreateMap<FeedbackReceiver, FeedbackReceiverOutDto>();
CreateMap<FeedbackInDto, Feedback>();
}
}
}

View file

@ -40,6 +40,7 @@ namespace Retroactiune
// Services
services.AddSingleton<IFeedbackReceiversService, FeedbackReceiversService>();
services.AddSingleton<ITokensService, TokensService>();
services.AddSingleton<IFeedbacksService, FeedbacksService>();
services.AddSingleton<IMongoClient, MongoClient>(i =>
{
var settings = i.GetService<IOptions<DatabaseSettings>>();

View file

@ -36,6 +36,7 @@ namespace Retroactiune
// Services
services.AddSingleton<IFeedbackReceiversService, FeedbackReceiversService>();
services.AddSingleton<ITokensService, TokensService>();
services.AddSingleton<IFeedbacksService, FeedbacksService>();
services.AddSingleton<IMongoClient, MongoClient>(i =>
{
var settings = i.GetService<IOptions<DatabaseSettings>>();

View file

@ -1,8 +1,8 @@
{
"DatabaseSettings": {
"FeedbackCollectionName": "feedback",
"FeedbackCollectionName": "feedbacks",
"TokensCollectionName": "tokens",
"FeedbackReceiverCollectionName": "feedback_receiver",
"FeedbackReceiverCollectionName": "feedback_receivers",
"ConnectionString": "mongodb://localhost:27017",
"DatabaseName": "RetroactiuneTesting"
}

View file

@ -1,8 +1,8 @@
{
"DatabaseSettings": {
"FeedbackCollectionName": "feedback",
"FeedbackCollectionName": "feedbacks",
"TokensCollectionName": "tokens",
"FeedbackReceiverCollectionName": "feedback_receiver",
"FeedbackReceiverCollectionName": "feedback_receivers",
"ConnectionString": "mongodb://localhost:27017",
"DatabaseName": "Retroactiune"
},