feat/postit-acl-members #41
2 changed files with 68 additions and 71 deletions
commit
4956890236
|
|
@ -39,74 +39,13 @@ public sealed class BlogAclApiTests : IClassFixture<BlogsWebServerFixture>
|
||||||
{
|
{
|
||||||
private readonly BlogsWebServerFixture _fixture;
|
private readonly BlogsWebServerFixture _fixture;
|
||||||
|
|
||||||
public long CircleId { get; private set; }
|
|
||||||
public long PostId { get; private set; }
|
|
||||||
|
|
||||||
public BlogAclApiTests(BlogsWebServerFixture fixture)
|
public BlogAclApiTests(BlogsWebServerFixture fixture)
|
||||||
{
|
{
|
||||||
_fixture = fixture;
|
_fixture = fixture;
|
||||||
ResetDatabaseWithAlice();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// <summary>Reset the in-memory database and seed <c>alice</c>.
|
|
||||||
/// The shared SQLite <c>:memory:</c> store persists across
|
|
||||||
/// requests, so each test starts from a clean slate.</summary>
|
|
||||||
private void ResetDatabaseWithAlice()
|
|
||||||
{
|
|
||||||
using var scope = _fixture.Services.CreateScope();
|
|
||||||
var db = scope.ServiceProvider.GetRequiredService<ApplicationDbContext>();
|
|
||||||
db.Database.EnsureDeleted();
|
|
||||||
db.Database.EnsureCreated();
|
|
||||||
|
|
||||||
db.Users.Add(new ApplicationUser
|
|
||||||
{
|
|
||||||
Id = "alice",
|
|
||||||
UserName = "alice",
|
|
||||||
Email = "alice@example.com",
|
|
||||||
EmailConfirmed = true,
|
|
||||||
FullName = "Alice Dupont",
|
|
||||||
Avatar = "/avatars/alice.png",
|
|
||||||
});
|
|
||||||
db.SaveChanges();
|
|
||||||
CircleId = SeedCircle("alice", "test", isPublic: true);
|
|
||||||
PostId = SeedBlogPost("alice", "Billet ACL test");
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>Create a circle owned by <paramref name="ownerId"/>
|
|
||||||
/// directly in the SQLite store and return its server-assigned
|
|
||||||
/// id.</summary>
|
|
||||||
private long SeedCircle(string ownerId, string name, bool isPublic = false)
|
|
||||||
{
|
|
||||||
using var scope = _fixture.Services.CreateScope();
|
|
||||||
var db = scope.ServiceProvider.GetRequiredService<ApplicationDbContext>();
|
|
||||||
var circle = new Circle { OwnerId = ownerId, Name = name, Public = isPublic };
|
|
||||||
db.Circle.Add(circle);
|
|
||||||
db.SaveChanges();
|
|
||||||
return circle.Id;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>Create a blog post owned by <paramref name="authorId"/>
|
|
||||||
/// directly in the SQLite store and return its server-assigned
|
|
||||||
/// id.</summary>
|
|
||||||
private long SeedBlogPost(string authorId, string title)
|
|
||||||
{
|
|
||||||
using var scope = _fixture.Services.CreateScope();
|
|
||||||
var db = scope.ServiceProvider.GetRequiredService<ApplicationDbContext>();
|
|
||||||
var post = new BlogPost
|
|
||||||
{
|
|
||||||
AuthorId = authorId,
|
|
||||||
Title = title,
|
|
||||||
Article = "Test article body.",
|
|
||||||
DateCreated = DateTime.UtcNow,
|
|
||||||
DateModified = DateTime.UtcNow,
|
|
||||||
};
|
|
||||||
db.BlogSpot.Add(post);
|
|
||||||
db.SaveChanges();
|
|
||||||
return post.Id;
|
|
||||||
}
|
|
||||||
|
|
||||||
private string BlogAclUrl()
|
private string BlogAclUrl()
|
||||||
=> $"{_fixture.Addresses.First(a => a.StartsWith("https://"))}/{APIPrefix}/blogacl";
|
=> $"{_fixture.Addresses.First(a => a.StartsWith("https://"))}/{APIPrefix}/blogacl";
|
||||||
|
|
||||||
|
|
@ -152,8 +91,8 @@ public sealed class BlogAclApiTests : IClassFixture<BlogsWebServerFixture>
|
||||||
// Mirror PostIt's payload: scalar FK ids only, no nav props.
|
// Mirror PostIt's payload: scalar FK ids only, no nav props.
|
||||||
var payload = new CircleAuthorizationToBlogPost
|
var payload = new CircleAuthorizationToBlogPost
|
||||||
{
|
{
|
||||||
CircleId = CircleId,
|
CircleId = _fixture.CircleId,
|
||||||
BlogPostId = PostId,
|
BlogPostId = _fixture.PostId,
|
||||||
};
|
};
|
||||||
|
|
||||||
var response = await http.PostAsJsonAsync(BlogAclUrl(), payload,
|
var response = await http.PostAsJsonAsync(BlogAclUrl(), payload,
|
||||||
|
|
@ -187,15 +126,13 @@ public sealed class BlogAclApiTests : IClassFixture<BlogsWebServerFixture>
|
||||||
// The prod circle already exists with Name="test", Public=true,
|
// The prod circle already exists with Name="test", Public=true,
|
||||||
// owned by the caller. We seed the same shape pre-POST so the
|
// owned by the caller. We seed the same shape pre-POST so the
|
||||||
// test reproduces the prod scenario end-to-end.
|
// test reproduces the prod scenario end-to-end.
|
||||||
var circleId = SeedCircle("alice", "test", isPublic: true);
|
|
||||||
var postId = SeedBlogPost("alice", "Billet ACL test");
|
|
||||||
using var http = NewClient("alice");
|
using var http = NewClient("alice");
|
||||||
|
|
||||||
|
|
||||||
var payload = new PostAccessControlRulePayload
|
var payload = new PostAccessControlRulePayload
|
||||||
{
|
{
|
||||||
CircleId = circleId,
|
CircleId = _fixture.CircleId,
|
||||||
BlogPostId = postId
|
BlogPostId = _fixture.PostId
|
||||||
};
|
};
|
||||||
|
|
||||||
var response = await http.PostAsJsonAsync(BlogAclUrl(), payload,
|
var response = await http.PostAsJsonAsync(BlogAclUrl(), payload,
|
||||||
|
|
@ -268,10 +205,8 @@ public sealed class BlogAclApiTests : IClassFixture<BlogsWebServerFixture>
|
||||||
public async Task PostCircleAuthorization_never_returns_500(
|
public async Task PostCircleAuthorization_never_returns_500(
|
||||||
Dictionary<string, PostAccessControlRulePayload?> payload)
|
Dictionary<string, PostAccessControlRulePayload?> payload)
|
||||||
{
|
{
|
||||||
ResetDatabaseWithAlice();
|
|
||||||
using var http = NewClient("alice");
|
using var http = NewClient("alice");
|
||||||
|
|
||||||
|
|
||||||
var response = await http.PostAsJsonAsync(
|
var response = await http.PostAsJsonAsync(
|
||||||
BlogAclUrl(), payload,
|
BlogAclUrl(), payload,
|
||||||
TestContext.Current.CancellationToken);
|
TestContext.Current.CancellationToken);
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,3 @@
|
||||||
using System.Text;
|
|
||||||
using Microsoft.AspNetCore.Authentication.JwtBearer;
|
|
||||||
using Microsoft.AspNetCore.Authorization;
|
using Microsoft.AspNetCore.Authorization;
|
||||||
using Microsoft.AspNetCore.Builder;
|
using Microsoft.AspNetCore.Builder;
|
||||||
using Microsoft.Data.Sqlite;
|
using Microsoft.Data.Sqlite;
|
||||||
|
|
@ -8,6 +6,8 @@ using Microsoft.Extensions.DependencyInjection;
|
||||||
using Microsoft.IdentityModel.Tokens;
|
using Microsoft.IdentityModel.Tokens;
|
||||||
using Yavsc.Blogs.Controllers;
|
using Yavsc.Blogs.Controllers;
|
||||||
using Yavsc.Models;
|
using Yavsc.Models;
|
||||||
|
using Yavsc.Models.Blog;
|
||||||
|
using Yavsc.Models.Relationship;
|
||||||
using Yavsc.Services;
|
using Yavsc.Services;
|
||||||
using Yavsc.Tests.Shared;
|
using Yavsc.Tests.Shared;
|
||||||
|
|
||||||
|
|
@ -59,6 +59,9 @@ public sealed class BlogsWebServerFixture : WebHostFixture
|
||||||
{
|
{
|
||||||
protected override int HttpsPort => 5103;
|
protected override int HttpsPort => 5103;
|
||||||
|
|
||||||
|
public long CircleId { get; private set; }
|
||||||
|
public long PostId { get; private set; }
|
||||||
|
|
||||||
// A single SqliteConnection held open at the static level,
|
// A single SqliteConnection held open at the static level,
|
||||||
// mirroring how Yavsc.Org.Tests.WebServerFixture hoists its
|
// mirroring how Yavsc.Org.Tests.WebServerFixture hoists its
|
||||||
// shared configuration into static slots. Closing the
|
// shared configuration into static slots. Closing the
|
||||||
|
|
@ -282,4 +285,63 @@ public sealed class BlogsWebServerFixture : WebHostFixture
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>Reset the in-memory database and seed <c>alice</c>.
|
||||||
|
/// The shared SQLite <c>:memory:</c> store persists across
|
||||||
|
/// requests, so each test starts from a clean slate.</summary>
|
||||||
|
private void ResetDatabaseWithAlice()
|
||||||
|
{
|
||||||
|
using var scope = Services.CreateScope();
|
||||||
|
var db = scope.ServiceProvider.GetRequiredService<ApplicationDbContext>();
|
||||||
|
db.Database.EnsureDeleted();
|
||||||
|
db.Database.EnsureCreated();
|
||||||
|
|
||||||
|
db.Users.Add(new ApplicationUser
|
||||||
|
{
|
||||||
|
Id = "alice",
|
||||||
|
UserName = "alice",
|
||||||
|
Email = "alice@example.com",
|
||||||
|
EmailConfirmed = true,
|
||||||
|
FullName = "Alice Dupont",
|
||||||
|
Avatar = "/avatars/alice.png",
|
||||||
|
});
|
||||||
|
db.SaveChanges();
|
||||||
|
CircleId = SeedCircle("alice", "test", isPublic: true);
|
||||||
|
PostId = SeedBlogPost("alice", "Billet ACL test");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>Create a circle owned by <paramref name="ownerId"/>
|
||||||
|
/// directly in the SQLite store and return its server-assigned
|
||||||
|
/// id.</summary>
|
||||||
|
private long SeedCircle(string ownerId, string name, bool isPublic = false)
|
||||||
|
{
|
||||||
|
using var scope = Services.CreateScope();
|
||||||
|
var db = scope.ServiceProvider.GetRequiredService<ApplicationDbContext>();
|
||||||
|
var circle = new Circle { OwnerId = ownerId, Name = name, Public = isPublic };
|
||||||
|
db.Circle.Add(circle);
|
||||||
|
db.SaveChanges();
|
||||||
|
return circle.Id;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>Create a blog post owned by <paramref name="authorId"/>
|
||||||
|
/// directly in the SQLite store and return its server-assigned
|
||||||
|
/// id.</summary>
|
||||||
|
private long SeedBlogPost(string authorId, string title)
|
||||||
|
{
|
||||||
|
using var scope = Services.CreateScope();
|
||||||
|
var db = scope.ServiceProvider.GetRequiredService<ApplicationDbContext>();
|
||||||
|
var post = new BlogPost
|
||||||
|
{
|
||||||
|
AuthorId = authorId,
|
||||||
|
Title = title,
|
||||||
|
Article = "Test article body.",
|
||||||
|
DateCreated = DateTime.UtcNow,
|
||||||
|
DateModified = DateTime.UtcNow,
|
||||||
|
};
|
||||||
|
db.BlogSpot.Add(post);
|
||||||
|
db.SaveChanges();
|
||||||
|
return post.Id;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue