From 59c10650fc36e8c79c1def088240fd90a5151250 Mon Sep 17 00:00:00 2001 From: crupest Date: Sun, 17 Nov 2019 23:04:21 +0800 Subject: Fix typo in path of personal timeline controller actions. Add timeline permission test. --- .../Authentication/AuthenticationExtensions.cs | 19 +++++++ .../IntegratedTests/IntegratedTestBase.cs | 27 ++++++++++ .../IntegratedTests/PersonalTimelineTest.cs | 62 ++++++++++++++++++++++ Timeline/Controllers/PersonalTimelineController.cs | 8 +-- Timeline/Startup.cs | 2 + Timeline/Timeline.csproj | 10 ++-- 6 files changed, 120 insertions(+), 8 deletions(-) create mode 100644 Timeline.Tests/IntegratedTests/IntegratedTestBase.cs create mode 100644 Timeline.Tests/IntegratedTests/PersonalTimelineTest.cs diff --git a/Timeline.Tests/Helpers/Authentication/AuthenticationExtensions.cs b/Timeline.Tests/Helpers/Authentication/AuthenticationExtensions.cs index 34d7e460..6a78be7a 100644 --- a/Timeline.Tests/Helpers/Authentication/AuthenticationExtensions.cs +++ b/Timeline.Tests/Helpers/Authentication/AuthenticationExtensions.cs @@ -1,5 +1,6 @@ using Microsoft.AspNetCore.Mvc.Testing; using Newtonsoft.Json; +using System; using System.Net.Http; using System.Threading.Tasks; using Timeline.Models.Http; @@ -7,6 +8,13 @@ using Timeline.Tests.Mock.Data; namespace Timeline.Tests.Helpers.Authentication { + public enum AuthType + { + None, + User, + Admin + } + public static class AuthenticationExtensions { private const string CreateTokenUrl = "/token/create"; @@ -36,5 +44,16 @@ namespace Timeline.Tests.Helpers.Authentication { return factory.CreateClientWithCredential(MockUser.Admin.Username, MockUser.Admin.Password); } + + public static Task CreateClientAs(this WebApplicationFactory factory, AuthType authType) where T : class + { + return authType switch + { + AuthType.None => Task.FromResult(factory.CreateDefaultClient()), + AuthType.User => factory.CreateClientAsUser(), + AuthType.Admin => factory.CreateClientAsAdmin(), + _ => throw new InvalidOperationException("Unknown auth type.") + }; + } } } diff --git a/Timeline.Tests/IntegratedTests/IntegratedTestBase.cs b/Timeline.Tests/IntegratedTests/IntegratedTestBase.cs new file mode 100644 index 00000000..c4d72faf --- /dev/null +++ b/Timeline.Tests/IntegratedTests/IntegratedTestBase.cs @@ -0,0 +1,27 @@ +using Microsoft.AspNetCore.Mvc.Testing; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Timeline.Tests.Helpers; +using Xunit; + +namespace Timeline.Tests.IntegratedTests +{ + public abstract class IntegratedTestBase : IClassFixture>, IDisposable + { + protected TestApplication TestApp { get; } + + protected WebApplicationFactory Factory => TestApp.Factory; + + public IntegratedTestBase(WebApplicationFactory factory) + { + TestApp = new TestApplication(factory); + } + + public virtual void Dispose() + { + TestApp.Dispose(); + } + } +} diff --git a/Timeline.Tests/IntegratedTests/PersonalTimelineTest.cs b/Timeline.Tests/IntegratedTests/PersonalTimelineTest.cs new file mode 100644 index 00000000..9629fc0a --- /dev/null +++ b/Timeline.Tests/IntegratedTests/PersonalTimelineTest.cs @@ -0,0 +1,62 @@ +using FluentAssertions; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc.Testing; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Net.Http; +using System.Text.Json; +using System.Threading.Tasks; +using Timeline.Models.Http; +using Timeline.Tests.Helpers; +using Timeline.Tests.Helpers.Authentication; +using Xunit; + +namespace Timeline.Tests.IntegratedTests +{ + public class PersonalTimelineTest : IntegratedTestBase + { + public PersonalTimelineTest(WebApplicationFactory factory) + : base(factory) + { + + } + + [Theory] + [InlineData(AuthType.None, 200, 401, 401, 401, 401)] + [InlineData(AuthType.User, 200, 200, 403, 200, 403)] + [InlineData(AuthType.Admin, 200, 200, 200, 200, 200)] + public async Task Permission_Timeline(AuthType authType, int get, int opPropertyUser, int opPropertyAdmin, int opMemberUser, int opMemberAdmin) + { + using var client = await Factory.CreateClientAs(authType); + { + var res = await client.GetAsync("users/user/timeline"); + res.Should().HaveStatusCode(get); + } + + { + var res = await client.PostAsJsonAsync("users/user/timeline/op/property", + new TimelinePropertyChangeRequest { Description = "hahaha" }); + res.Should().HaveStatusCode(opPropertyUser); + } + + { + var res = await client.PostAsJsonAsync("users/admin/timeline/op/property", + new TimelinePropertyChangeRequest { Description = "hahaha" }); + res.Should().HaveStatusCode(opPropertyAdmin); + } + + { + var res = await client.PostAsJsonAsync("users/user/timeline/op/member", + new TimelineMemberChangeRequest { Add = new List { "admin" } }); + res.Should().HaveStatusCode(opMemberUser); + } + + { + var res = await client.PostAsJsonAsync("users/admin/timeline/op/member", + new TimelineMemberChangeRequest { Add = new List { "user" } }); + res.Should().HaveStatusCode(opMemberAdmin); + } + } + } +} diff --git a/Timeline/Controllers/PersonalTimelineController.cs b/Timeline/Controllers/PersonalTimelineController.cs index af6a70f8..88f5ba00 100644 --- a/Timeline/Controllers/PersonalTimelineController.cs +++ b/Timeline/Controllers/PersonalTimelineController.cs @@ -87,7 +87,7 @@ namespace Timeline.Controllers return await _service.GetPosts(username); } - [HttpPost("user/{username}/timeline/postop/create")] + [HttpPost("users/{username}/timeline/postop/create")] [Authorize] [CatchTimelineNotExistException] public async Task> PostOperationCreate([FromRoute][Username] string username, [FromBody] TimelinePostCreateRequest body) @@ -102,7 +102,7 @@ namespace Timeline.Controllers return res; } - [HttpPost("user/{username}/timeline/postop/delete")] + [HttpPost("users/{username}/timeline/postop/delete")] [Authorize] [CatchTimelineNotExistException] public async Task PostOperationDelete([FromRoute][Username] string username, [FromBody] TimelinePostDeleteRequest body) @@ -126,7 +126,7 @@ namespace Timeline.Controllers return Ok(); } - [HttpPost("user/{username}/timeline/op/property")] + [HttpPost("users/{username}/timeline/op/property")] [Authorize] [SelfOrAdmin] [CatchTimelineNotExistException] @@ -136,7 +136,7 @@ namespace Timeline.Controllers return Ok(); } - [HttpPost("user/{username}/timeline/op/member")] + [HttpPost("users/{username}/timeline/op/member")] [Authorize] [SelfOrAdmin] [CatchTimelineNotExistException] diff --git a/Timeline/Startup.cs b/Timeline/Startup.cs index f6abf36d..b2e958f9 100644 --- a/Timeline/Startup.cs +++ b/Timeline/Startup.cs @@ -71,6 +71,8 @@ namespace Timeline services.AddUserAvatarService(); services.AddScoped(); + services.AddScoped(); + var databaseConfig = Configuration.GetSection(nameof(DatabaseConfig)).Get(); services.AddDbContext(options => diff --git a/Timeline/Timeline.csproj b/Timeline/Timeline.csproj index 7e1dd4ef..6b4a2d6e 100644 --- a/Timeline/Timeline.csproj +++ b/Timeline/Timeline.csproj @@ -8,6 +8,12 @@ 8.0 enable + + + + + + @@ -174,8 +180,4 @@ UserService.Designer.cs - - - - -- cgit v1.2.3