diff options
-rw-r--r-- | Timeline.Tests/Helpers/Authentication/AuthenticationExtensions.cs | 19 | ||||
-rw-r--r-- | Timeline.Tests/IntegratedTests/IntegratedTestBase.cs | 27 | ||||
-rw-r--r-- | Timeline.Tests/IntegratedTests/PersonalTimelineTest.cs | 62 | ||||
-rw-r--r-- | Timeline/Controllers/PersonalTimelineController.cs | 8 | ||||
-rw-r--r-- | Timeline/Startup.cs | 2 | ||||
-rw-r--r-- | Timeline/Timeline.csproj | 10 |
6 files changed, 120 insertions, 8 deletions
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<HttpClient> CreateClientAs<T>(this WebApplicationFactory<T> 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<WebApplicationFactory<Startup>>, IDisposable + { + protected TestApplication TestApp { get; } + + protected WebApplicationFactory<Startup> Factory => TestApp.Factory; + + public IntegratedTestBase(WebApplicationFactory<Startup> 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<Startup> 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<string> { "admin" } }); + res.Should().HaveStatusCode(opMemberUser); + } + + { + var res = await client.PostAsJsonAsync("users/admin/timeline/op/member", + new TimelineMemberChangeRequest { Add = new List<string> { "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<ActionResult<TimelinePostCreateResponse>> 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<ActionResult> 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<IUserDetailService, UserDetailService>();
+ services.AddScoped<IPersonalTimelineService, PersonalTimelineService>();
+
var databaseConfig = Configuration.GetSection(nameof(DatabaseConfig)).Get<DatabaseConfig>();
services.AddDbContext<DatabaseContext>(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 @@ <LangVersion>8.0</LangVersion>
<Nullable>enable</Nullable>
</PropertyGroup>
+ <ItemGroup>
+ <Compile Remove="Resources\Filters\**" />
+ <Content Remove="Resources\Filters\**" />
+ <EmbeddedResource Remove="Resources\Filters\**" />
+ <None Remove="Resources\Filters\**" />
+ </ItemGroup>
<ItemGroup>
<Content Include="default-avatar.png">
@@ -174,8 +180,4 @@ <LastGenOutput>UserService.Designer.cs</LastGenOutput>
</EmbeddedResource>
</ItemGroup>
-
- <ItemGroup>
- <Folder Include="Resources\Filters\" />
- </ItemGroup>
</Project>
|