diff --git a/.editorconfig b/.editorconfig
index a914522..bc20077 100644
--- a/.editorconfig
+++ b/.editorconfig
@@ -22,6 +22,11 @@ end_of_line = crlf
insert_final_newline = true
#### Custom StyleCop Rules ####
+# https://rules.sonarsource.com/csharp/RSPEC-6608/
+dotnet_diagnostic.S6608.severity = None
+
+# https://rules.sonarsource.com/csharp/RSPEC-3925/
+dotnet_diagnostic.S3925.severity = None
# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA0001.md
dotnet_diagnostic.SA0001.severity = None
diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml
index ee21b2e..1a6c7c6 100644
--- a/.github/workflows/codeql.yml
+++ b/.github/workflows/codeql.yml
@@ -28,7 +28,7 @@ jobs:
- name: Setup .NET
uses: actions/setup-dotnet@v3
with:
- dotnet-version: 7.x
+ dotnet-version: 8.x
- name: Build
run: dotnet build --configuration Release
diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
index 6bb2656..b017eea 100644
--- a/.github/workflows/test.yml
+++ b/.github/workflows/test.yml
@@ -19,7 +19,7 @@ jobs:
- name: Setup .NET
uses: actions/setup-dotnet@v3
with:
- dotnet-version: 7.x
+ dotnet-version: 8.x
- name: Linting
run: dotnet format --verify-no-changes
@@ -42,7 +42,7 @@ jobs:
- name: Setup .NET
uses: actions/setup-dotnet@v3
with:
- dotnet-version: 7.x
+ dotnet-version: 8.x
- name: Tools
run: dotnet tool restore
diff --git a/Directory.Build.props b/Directory.Build.props
index 4a227ac..faf2029 100644
--- a/Directory.Build.props
+++ b/Directory.Build.props
@@ -7,14 +7,15 @@
+ Condition="$(MSBuildProjectExtension) == '.csproj'" />
+ Condition="$(MSBuildProjectExtension) == '.csproj'" />
+
diff --git a/Dockerfile b/Dockerfile
index 3cdb953..c73f44a 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -1,5 +1,5 @@
### Build
-FROM mcr.microsoft.com/dotnet/sdk:7.0 AS build
+FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build
WORKDIR /app
@@ -17,7 +17,7 @@ RUN dotnet publish \
MumbleApi
### Deploy
-FROM mcr.microsoft.com/dotnet/aspnet:7.0 AS final
+FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS final
ARG BUILD_VERSION=unknown
ARG COMMIT_SHA=unknown
diff --git a/MumbleApi.Test/Controller/PostControllerTest.cs b/MumbleApi.Test/Controller/PostControllerTest.cs
index cef5602..5a87ff9 100644
--- a/MumbleApi.Test/Controller/PostControllerTest.cs
+++ b/MumbleApi.Test/Controller/PostControllerTest.cs
@@ -9,16 +9,9 @@
namespace MumbleApi.Test.Controller;
-public class PostControllerTest : IClassFixture
+public class PostControllerTest(WebAppFactory factory) : IClassFixture
{
- private readonly WebAppFactory _factory;
-
- public PostControllerTest(WebAppFactory factory)
- {
- _factory = factory;
- }
-
- public static TheoryData> CreatePostData =>
+ public static TheoryData> CreatePostData =>
new()
{
// Create a post with text only.
@@ -29,7 +22,7 @@ public PostControllerTest(WebAppFactory factory)
new StringContent("new post text"), "text"
},
},
- result => { result.Text.Should().Be("new post text"); }
+ result => result.Text.Should().Be("new post text")
},
// Create post with media only.
@@ -536,7 +529,7 @@ public PostControllerTest(WebAppFactory factory)
},
};
- public static TheoryData> ReplacePostData =>
+ public static TheoryData> ReplacePostData =>
new()
{
// Create a post with text only.
@@ -606,7 +599,7 @@ public PostControllerTest(WebAppFactory factory)
[InlineData("DELETE", "/posts/id/likes")]
public async Task ReturnsUnauthorizedOnProtectedRoute(string method, string uri)
{
- var client = _factory.CreateUnauthorizedClient();
+ var client = factory.CreateUnauthorizedClient();
var result = await client.SendAsync(new HttpRequestMessage(new HttpMethod(method), uri));
result.StatusCode.Should().Be(HttpStatusCode.Unauthorized);
}
@@ -614,8 +607,8 @@ public async Task ReturnsUnauthorizedOnProtectedRoute(string method, string uri)
[Fact]
public async Task FetchEmptyPosts()
{
- await _factory.PrepareTestData(TestData.Empty);
- var client = _factory.CreateClient();
+ await factory.PrepareTestData(TestData.Empty);
+ var client = factory.CreateClient();
var result = await client.GetFromJsonAsync>("/posts");
if (result is null)
@@ -638,8 +631,8 @@ public async Task FetchEmptyPosts()
[InlineData("/posts/00000000000000000000000002/replies?offset=2&limit=1", true, false)]
public async Task PaginateCorrectly(string url, bool nextIsNull, bool prevIsNull)
{
- await _factory.PrepareTestData(TestData.PostsWithoutLikes);
- var client = _factory.CreateClient();
+ await factory.PrepareTestData(TestData.PostsWithoutLikes);
+ var client = factory.CreateClient();
var result = await client.GetFromJsonAsync>(url);
if (result is null)
@@ -656,8 +649,8 @@ public async Task PaginateCorrectly(string url, bool nextIsNull, bool prevIsNull
[InlineData("/posts/00000000000000000000000002/replies")]
public async Task NoInfoAboutLikeWithoutAuth(string url)
{
- await _factory.PrepareTestData(TestData.PostsWithoutLikes);
- var client = _factory.CreateUnauthorizedClient();
+ await factory.PrepareTestData(TestData.PostsWithoutLikes);
+ var client = factory.CreateUnauthorizedClient();
var result = await client.GetFromJsonAsync>(url);
if (result is null)
@@ -673,8 +666,8 @@ public async Task NoInfoAboutLikeWithoutAuth(string url)
[InlineData("/posts/00000000000000000000000002/replies")]
public async Task ContainInfoAboutLikeWithAuth(string url)
{
- await _factory.PrepareTestData(TestData.PostsWithoutLikes);
- var client = _factory.CreateClient();
+ await factory.PrepareTestData(TestData.PostsWithoutLikes);
+ var client = factory.CreateClient();
var result = await client.GetFromJsonAsync>(url);
if (result is null)
@@ -689,12 +682,10 @@ public async Task ContainInfoAboutLikeWithAuth(string url)
[MemberData(nameof(CreatePostData))]
public async Task CreatePost(string url, MultipartFormDataContent content, Action verify)
{
- await _factory.PrepareTestData(TestData.PostsWithoutLikes);
- var client = _factory.CreateClient();
- using var request = new HttpRequestMessage(HttpMethod.Post, url)
- {
- Content = content,
- };
+ await factory.PrepareTestData(TestData.PostsWithoutLikes);
+ var client = factory.CreateClient();
+ using var request = new HttpRequestMessage(HttpMethod.Post, url);
+ request.Content = content;
var response = await client.SendAsync(request);
var result = await response.EnsureSuccessStatusCode().Content.ReadFromJsonAsync();
@@ -713,12 +704,10 @@ public async Task CreatePost(string url, MultipartFormDataContent content, Actio
[MemberData(nameof(ErroneousResultData))]
public async Task ErroneousResult(HttpMethod method, string url, HttpContent? content, HttpStatusCode result)
{
- await _factory.PrepareTestData(TestData.PostsWithoutLikes);
- var client = _factory.CreateClient();
- using var request = new HttpRequestMessage(method, url)
- {
- Content = content,
- };
+ await factory.PrepareTestData(TestData.PostsWithoutLikes);
+ var client = factory.CreateClient();
+ using var request = new HttpRequestMessage(method, url);
+ request.Content = content;
var response = await client.SendAsync(request);
response.StatusCode.Should().Be(result);
@@ -727,8 +716,8 @@ public async Task ErroneousResult(HttpMethod method, string url, HttpContent? co
[Fact]
public async Task FetchPostById()
{
- await _factory.PrepareTestData(TestData.PostsWithoutLikes);
- var client = _factory.CreateUnauthorizedClient();
+ await factory.PrepareTestData(TestData.PostsWithoutLikes);
+ var client = factory.CreateUnauthorizedClient();
var result = await client.GetFromJsonAsync("/posts/00000000000000000000000001");
if (result is null)
@@ -743,8 +732,8 @@ public async Task FetchPostById()
[Fact]
public async Task FetchPostByIdWithLikeInfo()
{
- await _factory.PrepareTestData(TestData.PostsWithoutLikes);
- var client = _factory.CreateClient();
+ await factory.PrepareTestData(TestData.PostsWithoutLikes);
+ var client = factory.CreateClient();
var result = await client.GetFromJsonAsync("/posts/00000000000000000000000001");
if (result is null)
@@ -760,12 +749,10 @@ public async Task FetchPostByIdWithLikeInfo()
[MemberData(nameof(ReplacePostData))]
public async Task ReplacePost(MultipartFormDataContent content, Action verify)
{
- await _factory.PrepareTestData(TestData.PostsWithoutLikes);
- var client = _factory.CreateClient();
- using var request = new HttpRequestMessage(HttpMethod.Put, "/posts/00000000000000000000000001")
- {
- Content = content,
- };
+ await factory.PrepareTestData(TestData.PostsWithoutLikes);
+ var client = factory.CreateClient();
+ using var request = new HttpRequestMessage(HttpMethod.Put, "/posts/00000000000000000000000001");
+ request.Content = content;
var response = await client.SendAsync(request);
var result = await response.EnsureSuccessStatusCode().Content.ReadFromJsonAsync();
@@ -782,12 +769,10 @@ public async Task ReplacePost(MultipartFormDataContent content, Action
[Fact]
public async Task PatchPostWithText()
{
- await _factory.PrepareTestData(TestData.PostsWithoutLikes);
- var client = _factory.CreateClient();
- using var request = new HttpRequestMessage(HttpMethod.Patch, "/posts/00000000000000000000000001")
- {
- Content = new StringContent(@"{""text"": ""new post text""}", new MediaTypeHeaderValue("application/json")),
- };
+ await factory.PrepareTestData(TestData.PostsWithoutLikes);
+ var client = factory.CreateClient();
+ using var request = new HttpRequestMessage(HttpMethod.Patch, "/posts/00000000000000000000000001");
+ request.Content = new StringContent("""{"text": "new post text"}""", new MediaTypeHeaderValue("application/json"));
var response = await client.SendAsync(request);
response.StatusCode.Should().Be(HttpStatusCode.NoContent);
@@ -799,8 +784,8 @@ public async Task PatchPostWithText()
[Fact]
public async Task DeleteAPost()
{
- await _factory.PrepareTestData(TestData.PostsWithoutLikes);
- var client = _factory.CreateClient();
+ await factory.PrepareTestData(TestData.PostsWithoutLikes);
+ var client = factory.CreateClient();
var response = await client.DeleteAsync("/posts/00000000000000000000000001");
response.StatusCode.Should().Be(HttpStatusCode.NoContent);
@@ -811,8 +796,8 @@ public async Task DeleteAPost()
[Fact]
public async Task AttachMediaOnPost()
{
- await _factory.PrepareTestData(TestData.PostsWithoutLikes);
- var client = _factory.CreateClient();
+ await factory.PrepareTestData(TestData.PostsWithoutLikes);
+ var client = factory.CreateClient();
var response = await client.PutAsync("/posts/00000000000000000000000001/media", new MultipartFormDataContent
{
{
@@ -835,8 +820,8 @@ public async Task AttachMediaOnPost()
[Fact]
public async Task ReplaceMediaOnPost()
{
- await _factory.PrepareTestData(TestData.PostsWithoutLikes);
- var client = _factory.CreateClient();
+ await factory.PrepareTestData(TestData.PostsWithoutLikes);
+ var client = factory.CreateClient();
var response = await client.PutAsync("/posts/00000000000000000000000002/media", new MultipartFormDataContent
{
{
@@ -859,8 +844,8 @@ public async Task ReplaceMediaOnPost()
[Fact]
public async Task DeleteMediaFromPost()
{
- await _factory.PrepareTestData(TestData.PostsWithoutLikes);
- var client = _factory.CreateClient();
+ await factory.PrepareTestData(TestData.PostsWithoutLikes);
+ var client = factory.CreateClient();
var response = await client.DeleteAsync("/posts/00000000000000000000000003/media");
response.StatusCode.Should().Be(HttpStatusCode.NoContent);
@@ -871,8 +856,8 @@ public async Task DeleteMediaFromPost()
[Fact]
public async Task LikePost()
{
- await _factory.PrepareTestData(TestData.PostsWithoutLikes);
- var client = _factory.CreateClient();
+ await factory.PrepareTestData(TestData.PostsWithoutLikes);
+ var client = factory.CreateClient();
// Perform the put twice to see if it's idempotent.
var response = await client.PutAsync("/posts/00000000000000000000000001/likes", null);
@@ -887,8 +872,8 @@ public async Task LikePost()
[Fact]
public async Task UnlikePost()
{
- await _factory.PrepareTestData(TestData.PostsWithLikes);
- var client = _factory.CreateClient();
+ await factory.PrepareTestData(TestData.PostsWithLikes);
+ var client = factory.CreateClient();
var result = await client.GetFromJsonAsync("/posts/00000000000000000000000001");
result?.LikedBySelf.Should().BeTrue();
diff --git a/MumbleApi.Test/Controller/UserControllerTest.cs b/MumbleApi.Test/Controller/UserControllerTest.cs
index 3db1233..e83b4f4 100644
--- a/MumbleApi.Test/Controller/UserControllerTest.cs
+++ b/MumbleApi.Test/Controller/UserControllerTest.cs
@@ -7,15 +7,8 @@
namespace MumbleApi.Test.Controller;
-public class UserControllerTest : IClassFixture
+public class UserControllerTest(WebAppFactory factory) : IClassFixture
{
- private readonly WebAppFactory _factory;
-
- public UserControllerTest(WebAppFactory factory)
- {
- _factory = factory;
- }
-
public static TheoryData ErroneousResultData =>
new()
{
@@ -111,7 +104,7 @@ public UserControllerTest(WebAppFactory factory)
[InlineData("DELETE", "/users/id/followers")]
public async Task ReturnsUnauthorizedOnProtectedRoute(string method, string uri)
{
- var client = _factory.CreateUnauthorizedClient();
+ var client = factory.CreateUnauthorizedClient();
var result = await client.SendAsync(new HttpRequestMessage(new HttpMethod(method), uri));
result.StatusCode.Should().Be(HttpStatusCode.Unauthorized);
}
@@ -119,8 +112,8 @@ public async Task ReturnsUnauthorizedOnProtectedRoute(string method, string uri)
[Fact]
public async Task GetEmptyUsers()
{
- await _factory.PrepareTestData(TestData.Empty);
- var client = _factory.CreateClient();
+ await factory.PrepareTestData(TestData.Empty);
+ var client = factory.CreateClient();
var result = await client.GetFromJsonAsync>("/users");
if (result is null)
@@ -143,8 +136,8 @@ public async Task GetCorrectInformationForAuthStatus(string url)
{
async Task Unauthed()
{
- await _factory.PrepareTestData(TestData.UsersWithFollowers);
- var client = _factory.CreateUnauthorizedClient();
+ await factory.PrepareTestData(TestData.UsersWithFollowers);
+ var client = factory.CreateUnauthorizedClient();
var result = await client.GetStringAsync(url);
result.Should().NotContain("firstname");
@@ -152,8 +145,8 @@ async Task Unauthed()
async Task Authed()
{
- await _factory.PrepareTestData(TestData.UsersWithFollowers);
- var client = _factory.CreateClient();
+ await factory.PrepareTestData(TestData.UsersWithFollowers);
+ var client = factory.CreateClient();
var result = await client.GetStringAsync(url);
result.Should().Contain("firstname");
@@ -172,8 +165,8 @@ async Task Authed()
[InlineData("/users/1337/followees?offset=0&limit=1", true, true)]
public async Task PaginateCorrectly(string url, bool nextIsNull, bool prevIsNull)
{
- await _factory.PrepareTestData(TestData.UsersWithFollowers);
- var client = _factory.CreateClient();
+ await factory.PrepareTestData(TestData.UsersWithFollowers);
+ var client = factory.CreateClient();
var result = await client.GetFromJsonAsync>(url);
if (result is null)
@@ -188,8 +181,8 @@ public async Task PaginateCorrectly(string url, bool nextIsNull, bool prevIsNull
[Fact]
public async Task UploadAvatar()
{
- await _factory.PrepareTestData(TestData.UsersWithFollowers);
- var client = _factory.CreateClient();
+ await factory.PrepareTestData(TestData.UsersWithFollowers);
+ var client = factory.CreateClient();
var request = new HttpRequestMessage(HttpMethod.Put, "/users/avatar")
{
Content = new MultipartFormDataContent
@@ -215,8 +208,8 @@ public async Task UploadAvatar()
[Fact]
public async Task DeleteAvatar()
{
- await _factory.PrepareTestData(TestData.UsersWithFollowers);
- var client = _factory.CreateUserClient(TestData.UserTestyTester.Id);
+ await factory.PrepareTestData(TestData.UsersWithFollowers);
+ var client = factory.CreateUserClient(TestData.UserTestyTester.Id);
var result = await client.DeleteAsync("/users/avatar");
result.StatusCode.Should().Be(HttpStatusCode.NoContent);
@@ -227,8 +220,8 @@ public async Task DeleteAvatar()
[Fact]
public async Task UpdateProfile()
{
- await _factory.PrepareTestData(TestData.UsersWithFollowers);
- var client = _factory.CreateClient();
+ await factory.PrepareTestData(TestData.UsersWithFollowers);
+ var client = factory.CreateClient();
var request = new HttpRequestMessage(HttpMethod.Patch, "/users")
{
Content = JsonContent.Create(new
@@ -251,8 +244,8 @@ public async Task UpdateProfile()
[Fact]
public async Task FollowUser()
{
- await _factory.PrepareTestData(TestData.UsersWithFollowers);
- var client = _factory.CreateClient();
+ await factory.PrepareTestData(TestData.UsersWithFollowers);
+ var client = factory.CreateClient();
var result = await client.PutAsync($"/users/{TestData.UserJackJohnson.Id}/followers", null);
result.StatusCode.Should().Be(HttpStatusCode.NoContent);
result = await client.PutAsync($"/users/{TestData.UserJackJohnson.Id}/followers", null);
@@ -265,8 +258,8 @@ public async Task FollowUser()
[Fact]
public async Task UnfollowUser()
{
- await _factory.PrepareTestData(TestData.UsersWithFollowers);
- var client = _factory.CreateClient();
+ await factory.PrepareTestData(TestData.UsersWithFollowers);
+ var client = factory.CreateClient();
var result = await client.DeleteAsync($"/users/{TestData.UserTestyTester.Id}/followers");
result.StatusCode.Should().Be(HttpStatusCode.NoContent);
result = await client.DeleteAsync($"/users/{TestData.UserTestyTester.Id}/followers");
@@ -280,12 +273,10 @@ public async Task UnfollowUser()
[MemberData(nameof(ErroneousResultData))]
public async Task ErroneousResult(HttpMethod method, string url, HttpContent? content, HttpStatusCode result)
{
- await _factory.PrepareTestData(TestData.UsersWithFollowers);
- var client = _factory.CreateClient();
- using var request = new HttpRequestMessage(method, url)
- {
- Content = content,
- };
+ await factory.PrepareTestData(TestData.UsersWithFollowers);
+ var client = factory.CreateClient();
+ using var request = new HttpRequestMessage(method, url);
+ request.Content = content;
var response = await client.SendAsync(request);
response.StatusCode.Should().Be(result);
diff --git a/MumbleApi.Test/MumbleApi.Test.csproj b/MumbleApi.Test/MumbleApi.Test.csproj
index 3e16c3b..3c3c58e 100644
--- a/MumbleApi.Test/MumbleApi.Test.csproj
+++ b/MumbleApi.Test/MumbleApi.Test.csproj
@@ -1,7 +1,8 @@
- net7.0
+ net8.0
+ 12
enable
enable
false
@@ -9,15 +10,15 @@
-
-
-
-
-
+
+
+
+
+
runtime; build; native; contentfiles; analyzers; buildtransitive
all
-
+
runtime; build; native; contentfiles; analyzers; buildtransitive
all
diff --git a/MumbleApi.Test/Services/PostUpdatesTest.cs b/MumbleApi.Test/Services/PostUpdatesTest.cs
index 1c69ce4..d63e5d4 100644
--- a/MumbleApi.Test/Services/PostUpdatesTest.cs
+++ b/MumbleApi.Test/Services/PostUpdatesTest.cs
@@ -5,7 +5,7 @@
namespace MumbleApi.Test.Services;
-public class PostUpdatesTest : IClassFixture
+public class PostUpdatesTest(WebAppFactory factory) : IClassFixture
{
private static readonly JsonSerializerOptions Json = new()
{
@@ -13,13 +13,6 @@ public class PostUpdatesTest : IClassFixture
DictionaryKeyPolicy = JsonNamingPolicy.CamelCase,
};
- private readonly WebAppFactory _factory;
-
- public PostUpdatesTest(WebAppFactory factory)
- {
- _factory = factory;
- }
-
public static TheoryData?, bool>>
ReceiveCorrectPostEventData => new()
{
@@ -101,15 +94,15 @@ public async Task ReceiveCorrectPostEvent(
HttpContent? content,
Func?, bool> verify)
{
- await _factory.PrepareTestData(TestData.PostsWithLikes);
- var client = _factory.CreateClient();
+ await factory.PrepareTestData(TestData.PostsWithLikes);
+ var client = factory.CreateClient();
await using var eventStream = await client.GetStreamAsync("/posts/_sse");
using var request = new HttpRequestMessage(
method,
- url)
- { Content = content, };
+ url);
+ request.Content = content;
await client.SendAsync(request);
var result = await GetServerEvent(eventStream);
@@ -125,15 +118,15 @@ public async Task ReceiveCorrectPostLikeEvent(
HttpContent? content,
Func?, bool> verify)
{
- await _factory.PrepareTestData(TestData.PostsWithLikes);
- var client = _factory.CreateClient();
+ await factory.PrepareTestData(TestData.PostsWithLikes);
+ var client = factory.CreateClient();
await using var eventStream = await client.GetStreamAsync("/posts/_sse");
using var request = new HttpRequestMessage(
method,
- url)
- { Content = content, };
+ url);
+ request.Content = content;
await client.SendAsync(request);
var result = await GetServerEvent(eventStream);
@@ -144,8 +137,8 @@ public async Task ReceiveCorrectPostLikeEvent(
[Fact]
public async Task ReceiveCorrectPostDeletedEvent()
{
- await _factory.PrepareTestData(TestData.PostsWithLikes);
- var client = _factory.CreateClient();
+ await factory.PrepareTestData(TestData.PostsWithLikes);
+ var client = factory.CreateClient();
await using var eventStream = await client.GetStreamAsync("/posts/_sse");
@@ -172,7 +165,7 @@ public async Task ReceiveCorrectPostDeletedEvent()
var ev = new ServerEvent();
while (!sr.EndOfStream)
{
- var cts = new CancellationTokenSource(1000);
+ using var cts = new CancellationTokenSource(1000);
switch (await sr.ReadLineAsync(cts.Token))
{
case "":
diff --git a/MumbleApi/Application/HttpContextExtensions.cs b/MumbleApi/Application/HttpContextExtensions.cs
index 22237eb..34aaa62 100644
--- a/MumbleApi/Application/HttpContextExtensions.cs
+++ b/MumbleApi/Application/HttpContextExtensions.cs
@@ -1,5 +1,7 @@
using System.Security.Claims;
+using MumbleApi.Errors;
+
using Zitadel.Authentication;
namespace MumbleApi.Application;
@@ -10,5 +12,5 @@ public static class HttpContextExtensions
context.User.FindFirstValue(OidcClaimTypes.Subject);
public static string UserId(this HttpContext context) => context.User.FindFirstValue(OidcClaimTypes.Subject) ??
- throw new Exception("No UserID Found.");
+ throw new UserNotFoundException("No UserID Found.");
}
diff --git a/MumbleApi/Authentication/ZitadelAuthorizeAttribute.cs b/MumbleApi/Authentication/ZitadelAuthorizeAttribute.cs
index 01ad7e4..89f2fb4 100644
--- a/MumbleApi/Authentication/ZitadelAuthorizeAttribute.cs
+++ b/MumbleApi/Authentication/ZitadelAuthorizeAttribute.cs
@@ -4,6 +4,4 @@
namespace MumbleApi.Authentication;
-public class ZitadelAuthorizeAttribute : AuthorizeAttribute
-{
-}
+public class ZitadelAuthorizeAttribute : AuthorizeAttribute;
diff --git a/MumbleApi/Controller/PostController.cs b/MumbleApi/Controller/PostController.cs
index d52868d..52c1fca 100644
--- a/MumbleApi/Controller/PostController.cs
+++ b/MumbleApi/Controller/PostController.cs
@@ -17,17 +17,8 @@ namespace MumbleApi.Controller;
[Produces("application/json")]
[SwaggerTag("Manage posts in the Mumble system.")]
[OptionalZitadelAuthorize]
-public class PostController : ControllerBase
+public class PostController(IPosts posts, IPostUpdates updates) : ControllerBase
{
- private readonly IPosts _posts;
- private readonly IPostUpdates _updates;
-
- public PostController(IPosts posts, IPostUpdates updates)
- {
- _posts = posts;
- _updates = updates;
- }
-
///
/// Fetch/Search a paginated list of posts.
///
@@ -37,12 +28,12 @@ public PostController(IPosts posts, IPostUpdates updates)
[SwaggerResponse(200, "Success", typeof(PaginatedResult))]
public async Task Search([FromQuery] PostSearchParameters search)
{
- var (posts, total) = await _posts.GetPaginatedPostsWithLikes(search);
+ var (dbPosts, total) = await posts.GetPaginatedPostsWithLikes(search);
return Ok(new PaginatedResult
{
Count = Convert.ToUInt32(total),
- Data = posts.Select(Post.FromEntity(HttpContext.OptionalUserId())).ToList(),
+ Data = dbPosts.Select(Post.FromEntity(HttpContext.OptionalUserId())).ToList(),
Next = total > search.Offset + search.Limit
? $"{Url.ActionLink()}{(search with { Offset = search.Offset + search.Limit }).ToQueryString()}"
: null,
@@ -80,19 +71,19 @@ public async Task Create([FromForm][SwaggerRequestBody(Required =
if (data.Media is not null)
{
await using var file = data.Media.OpenReadStream();
- postEntity = await _posts.CreatePost(
+ postEntity = await posts.CreatePost(
userId,
text: data.Text,
media: (file, data.Media.ContentType));
}
else
{
- postEntity = await _posts.CreatePost(
+ postEntity = await posts.CreatePost(
userId,
text: data.Text);
}
- await _updates.NewPost(Post.FromEntity(postEntity));
+ await updates.NewPost(Post.FromEntity(postEntity));
return Ok(Post.FromEntity(postEntity, userId));
}
@@ -110,7 +101,7 @@ public async Task Create([FromForm][SwaggerRequestBody(Required =
[SwaggerResponse(404, "Not Found")]
public async Task GetById(Ulid id)
{
- var post = await _posts.GetPostById(id);
+ var post = await posts.GetPostById(id);
if (post is null)
{
return NotFound();
@@ -151,7 +142,7 @@ [FromForm] [SwaggerRequestBody(Required = true)]
if (data.Media is not null)
{
await using var file = data.Media.OpenReadStream();
- postEntity = await _posts.ReplacePost(
+ postEntity = await posts.ReplacePost(
userId,
id,
data.Text,
@@ -159,13 +150,13 @@ [FromForm] [SwaggerRequestBody(Required = true)]
}
else
{
- postEntity = await _posts.ReplacePost(
+ postEntity = await posts.ReplacePost(
userId,
id,
data.Text);
}
- await _updates.PostUpdated(Post.FromEntity(postEntity));
+ await updates.PostUpdated(Post.FromEntity(postEntity));
return Ok(Post.FromEntity(postEntity, userId));
}
@@ -207,8 +198,8 @@ [FromBody] [SwaggerRequestBody(Required = true)]
if (data.Text is not null)
{
var userId = HttpContext.UserId();
- var post = await _posts.UpdatePost(userId, id, data.Text);
- await _updates.PostUpdated(Post.FromEntity(post));
+ var post = await posts.UpdatePost(userId, id, data.Text);
+ await updates.PostUpdated(Post.FromEntity(post));
}
}
catch (PostNotFoundException)
@@ -242,8 +233,8 @@ public async Task Delete(Ulid id)
try
{
var userId = HttpContext.UserId();
- await _posts.DeletePost(userId, id);
- await _updates.PostDeleted(id);
+ await posts.DeletePost(userId, id);
+ await updates.PostDeleted(id);
}
catch (PostNotFoundException)
{
@@ -284,8 +275,8 @@ [FromForm] [SwaggerRequestBody(Required = true)]
{
await using var file = uploadData.Media.OpenReadStream();
var userId = HttpContext.UserId();
- var post = await _posts.UpdatePostMedia(userId, id, (file, uploadData.Media.ContentType));
- await _updates.PostUpdated(Post.FromEntity(post));
+ var post = await posts.UpdatePostMedia(userId, id, (file, uploadData.Media.ContentType));
+ await updates.PostUpdated(Post.FromEntity(post));
return Ok(post.MediaUrl);
}
@@ -316,8 +307,8 @@ public async Task DeleteMedia(Ulid id)
try
{
var userId = HttpContext.UserId();
- var post = await _posts.UpdatePostMedia(userId, id);
- await _updates.PostUpdated(Post.FromEntity(post));
+ var post = await posts.UpdatePostMedia(userId, id);
+ await updates.PostUpdated(Post.FromEntity(post));
}
catch (PostInvalidException)
{
@@ -350,7 +341,7 @@ public async Task GetReplies(Ulid id, [FromQuery] PaginationParam
{
try
{
- var (replies, total) = await _posts.GetPaginatedReplies(id, pagination);
+ var (replies, total) = await posts.GetPaginatedReplies(id, pagination);
return Ok(new PaginatedResult
{
Count = Convert.ToUInt32(total),
@@ -404,7 +395,7 @@ [FromForm] [SwaggerRequestBody(Required = true)]
if (data.Media is not null)
{
await using var file = data.Media.OpenReadStream();
- postEntity = await _posts.CreatePost(
+ postEntity = await posts.CreatePost(
userId,
id,
data.Text,
@@ -412,13 +403,13 @@ [FromForm] [SwaggerRequestBody(Required = true)]
}
else
{
- postEntity = await _posts.CreatePost(
+ postEntity = await posts.CreatePost(
userId,
id,
data.Text);
}
- await _updates.NewPost(Reply.FromEntity(postEntity));
+ await updates.NewPost(Reply.FromEntity(postEntity));
return Ok(Reply.FromEntity(postEntity, userId));
}
@@ -452,9 +443,9 @@ public async Task Like(Ulid id)
try
{
var userId = HttpContext.UserId();
- if (await _posts.LikePost(userId, id))
+ if (await posts.LikePost(userId, id))
{
- await _updates.PostLiked(userId, id);
+ await updates.PostLiked(userId, id);
}
return NoContent();
@@ -480,9 +471,9 @@ public async Task Unlike(Ulid id)
try
{
var userId = HttpContext.UserId();
- if (await _posts.UnlikePost(userId, id))
+ if (await posts.UnlikePost(userId, id))
{
- await _updates.PostUnliked(userId, id);
+ await updates.PostUnliked(userId, id);
}
return NoContent();
diff --git a/MumbleApi/Controller/UserController.cs b/MumbleApi/Controller/UserController.cs
index 363d85b..6df8242 100644
--- a/MumbleApi/Controller/UserController.cs
+++ b/MumbleApi/Controller/UserController.cs
@@ -15,15 +15,8 @@ namespace MumbleApi.Controller;
[OptionalZitadelAuthorize]
[Produces("application/json")]
[SwaggerTag("Users in the Mumble System.")]
-public class UserController : ControllerBase
+public class UserController(IUsers users) : ControllerBase
{
- private readonly IUsers _users;
-
- public UserController(IUsers users)
- {
- _users = users;
- }
-
///
/// Fetch a paginated list of users.
///
@@ -34,7 +27,7 @@ public UserController(IUsers users)
[SwaggerResponse(200, "Success", typeof(PaginatedResult))]
public async Task Get([FromQuery] PaginationParameters pagination)
{
- var (users, total) = await _users.GetPaginatedUsers(pagination);
+ var (dbUsers, total) = await users.GetPaginatedUsers(pagination);
var loggedIn = HttpContext.User.Identity?.IsAuthenticated == true;
var next = total > pagination.Offset + pagination.Limit
@@ -48,14 +41,14 @@ public async Task Get([FromQuery] PaginationParameters pagination
? Ok(new PaginatedResult
{
Count = Convert.ToUInt32(total),
- Data = users.Select(Models.User.FromEntity).ToList(),
+ Data = dbUsers.Select(Models.User.FromEntity).ToList(),
Next = next,
Previous = prev,
})
: Ok(new PaginatedResult
{
Count = Convert.ToUInt32(total),
- Data = users.Select(PublicUser.FromEntity).ToList(),
+ Data = dbUsers.Select(PublicUser.FromEntity).ToList(),
Next = next,
Previous = prev,
});
@@ -72,7 +65,7 @@ public async Task Get([FromQuery] PaginationParameters pagination
[SwaggerResponse(404, "Not Found")]
public async Task GetById(string id)
{
- var user = await _users.GetUserById(id);
+ var user = await users.GetUserById(id);
if (user is null)
{
return NotFound();
@@ -114,7 +107,7 @@ public async Task UpdateProfile([FromBody] UpdateUserData data)
try
{
- await _users.UpdateUser(HttpContext.UserId(), data.Firstname, data.Lastname, data.Username);
+ await users.UpdateUser(HttpContext.UserId(), data.Firstname, data.Lastname, data.Username);
return NoContent();
}
catch (UserNotFoundException)
@@ -145,7 +138,7 @@ public async Task UploadAvatar([FromForm][SwaggerRequestBody(Requ
}
await using var file = data.Media.OpenReadStream();
- var newUrl = await _users.UpdateUserAvatar(HttpContext.UserId(), (file, data.Media.ContentType));
+ var newUrl = await users.UpdateUserAvatar(HttpContext.UserId(), (file, data.Media.ContentType));
return Ok(newUrl);
}
@@ -160,7 +153,7 @@ public async Task UploadAvatar([FromForm][SwaggerRequestBody(Requ
[SwaggerResponse(204, "Success - No Content")]
public async Task DeleteAvatar()
{
- await _users.UpdateUserAvatar(HttpContext.UserId());
+ await users.UpdateUserAvatar(HttpContext.UserId());
return NoContent();
}
@@ -175,7 +168,7 @@ public async Task DeleteAvatar()
[SwaggerResponse(200, "Success", typeof(PaginatedResult))]
public async Task GetFollowers(string id, [FromQuery] PaginationParameters pagination)
{
- var (followers, total) = await _users.GetPaginatedFollowers(id, pagination);
+ var (followers, total) = await users.GetPaginatedFollowers(id, pagination);
var loggedIn = User.Identity?.IsAuthenticated == true;
var next = total > pagination.Offset + pagination.Limit
@@ -213,7 +206,7 @@ public async Task GetFollowers(string id, [FromQuery] PaginationP
[SwaggerResponse(200, "Success", typeof(PaginatedResult))]
public async Task GetFollowees(string id, [FromQuery] PaginationParameters pagination)
{
- var (followees, total) = await _users.GetPaginatedFollowees(id, pagination);
+ var (followees, total) = await users.GetPaginatedFollowees(id, pagination);
var loggedIn = User.Identity?.IsAuthenticated == true;
var next = total > pagination.Offset + pagination.Limit
@@ -254,7 +247,7 @@ public async Task FollowUser(string id)
{
try
{
- await _users.FollowUser(HttpContext.UserId(), id);
+ await users.FollowUser(HttpContext.UserId(), id);
return NoContent();
}
catch (UserNotFoundException)
@@ -276,7 +269,7 @@ public async Task UnfollowUser(string id)
{
try
{
- await _users.UnfollowUser(HttpContext.UserId(), id);
+ await users.UnfollowUser(HttpContext.UserId(), id);
return NoContent();
}
catch (UserNotFoundException)
diff --git a/MumbleApi/Database/DataContext.cs b/MumbleApi/Database/DataContext.cs
index 48e7ae2..c707e38 100644
--- a/MumbleApi/Database/DataContext.cs
+++ b/MumbleApi/Database/DataContext.cs
@@ -4,13 +4,8 @@
namespace MumbleApi.Database;
-public class DataContext : DbContext
+public class DataContext(DbContextOptions options) : DbContext(options)
{
- public DataContext(DbContextOptions options)
- : base(options)
- {
- }
-
#nullable disable
public DbSet Posts { get; set; }
diff --git a/MumbleApi/Database/UlidConverter.cs b/MumbleApi/Database/UlidConverter.cs
index 4f649c6..1557b59 100644
--- a/MumbleApi/Database/UlidConverter.cs
+++ b/MumbleApi/Database/UlidConverter.cs
@@ -2,10 +2,5 @@
namespace MumbleApi.Database;
-public class UlidConverter : ValueConverter
-{
- public UlidConverter()
- : base(ulid => ulid.ToString(), @string => Ulid.Parse(@string))
- {
- }
-}
+public class UlidConverter() : ValueConverter(ulid => ulid.ToString() ?? string.Empty,
+ @string => Ulid.Parse(@string));
diff --git a/MumbleApi/Errors/ForbiddenException.cs b/MumbleApi/Errors/ForbiddenException.cs
index 8ad5b1d..61e25a2 100644
--- a/MumbleApi/Errors/ForbiddenException.cs
+++ b/MumbleApi/Errors/ForbiddenException.cs
@@ -1,16 +1,18 @@
-using System.Runtime.Serialization;
+namespace MumbleApi.Errors;
-namespace MumbleApi.Errors;
-
-[Serializable]
public class ForbiddenException : Exception
{
public ForbiddenException()
{
}
- protected ForbiddenException(SerializationInfo info, StreamingContext context)
- : base(info, context)
+ public ForbiddenException(string? message)
+ : base(message)
+ {
+ }
+
+ public ForbiddenException(string? message, Exception? innerException)
+ : base(message, innerException)
{
}
}
diff --git a/MumbleApi/Errors/PostInvalidException.cs b/MumbleApi/Errors/PostInvalidException.cs
index a69340c..3e57e2f 100644
--- a/MumbleApi/Errors/PostInvalidException.cs
+++ b/MumbleApi/Errors/PostInvalidException.cs
@@ -1,16 +1,18 @@
-using System.Runtime.Serialization;
+namespace MumbleApi.Errors;
-namespace MumbleApi.Errors;
-
-[Serializable]
public class PostInvalidException : Exception
{
public PostInvalidException()
{
}
- protected PostInvalidException(SerializationInfo info, StreamingContext context)
- : base(info, context)
+ public PostInvalidException(string? message)
+ : base(message)
+ {
+ }
+
+ public PostInvalidException(string? message, Exception? innerException)
+ : base(message, innerException)
{
}
}
diff --git a/MumbleApi/Errors/PostIsAReplyException.cs b/MumbleApi/Errors/PostIsAReplyException.cs
index c05cf3c..8d4bf9f 100644
--- a/MumbleApi/Errors/PostIsAReplyException.cs
+++ b/MumbleApi/Errors/PostIsAReplyException.cs
@@ -1,16 +1,18 @@
-using System.Runtime.Serialization;
+namespace MumbleApi.Errors;
-namespace MumbleApi.Errors;
-
-[Serializable]
public class PostIsAReplyException : Exception
{
public PostIsAReplyException()
{
}
- protected PostIsAReplyException(SerializationInfo info, StreamingContext context)
- : base(info, context)
+ public PostIsAReplyException(string? message)
+ : base(message)
+ {
+ }
+
+ public PostIsAReplyException(string? message, Exception? innerException)
+ : base(message, innerException)
{
}
}
diff --git a/MumbleApi/Errors/PostNotFoundException.cs b/MumbleApi/Errors/PostNotFoundException.cs
index c193ea2..ed83ea1 100644
--- a/MumbleApi/Errors/PostNotFoundException.cs
+++ b/MumbleApi/Errors/PostNotFoundException.cs
@@ -1,16 +1,18 @@
-using System.Runtime.Serialization;
+namespace MumbleApi.Errors;
-namespace MumbleApi.Errors;
-
-[Serializable]
public class PostNotFoundException : Exception
{
public PostNotFoundException()
{
}
- protected PostNotFoundException(SerializationInfo info, StreamingContext context)
- : base(info, context)
+ public PostNotFoundException(string? message)
+ : base(message)
+ {
+ }
+
+ public PostNotFoundException(string? message, Exception? innerException)
+ : base(message, innerException)
{
}
}
diff --git a/MumbleApi/Errors/StorageException.cs b/MumbleApi/Errors/StorageException.cs
index 84e29d3..fa809eb 100644
--- a/MumbleApi/Errors/StorageException.cs
+++ b/MumbleApi/Errors/StorageException.cs
@@ -1,8 +1,5 @@
-using System.Runtime.Serialization;
+namespace MumbleApi.Errors;
-namespace MumbleApi.Errors;
-
-[Serializable]
public class StorageException : Exception
{
public StorageException()
@@ -14,8 +11,8 @@ public StorageException(string message)
{
}
- protected StorageException(SerializationInfo info, StreamingContext context)
- : base(info, context)
+ public StorageException(string? message, Exception? innerException)
+ : base(message, innerException)
{
}
}
diff --git a/MumbleApi/Errors/UserNotFoundException.cs b/MumbleApi/Errors/UserNotFoundException.cs
index 763199e..5befdc6 100644
--- a/MumbleApi/Errors/UserNotFoundException.cs
+++ b/MumbleApi/Errors/UserNotFoundException.cs
@@ -1,16 +1,18 @@
-using System.Runtime.Serialization;
+namespace MumbleApi.Errors;
-namespace MumbleApi.Errors;
-
-[Serializable]
public class UserNotFoundException : Exception
{
public UserNotFoundException()
{
}
- protected UserNotFoundException(SerializationInfo info, StreamingContext context)
- : base(info, context)
+ public UserNotFoundException(string? message)
+ : base(message)
+ {
+ }
+
+ public UserNotFoundException(string? message, Exception? innerException)
+ : base(message, innerException)
{
}
}
diff --git a/MumbleApi/MumbleApi.csproj b/MumbleApi/MumbleApi.csproj
index 14527f5..a6cf221 100644
--- a/MumbleApi/MumbleApi.csproj
+++ b/MumbleApi/MumbleApi.csproj
@@ -1,25 +1,26 @@
- net7.0
+ net8.0
+ 12
enable
enable
true
true
-
+
-
-
-
-
-
-
-
+
+
+
+
+
+
+
-
-
+
+
diff --git a/MumbleApi/OpenApi/ServerSentEventFilter.cs b/MumbleApi/OpenApi/ServerSentEventFilter.cs
index e84c210..83f3279 100644
--- a/MumbleApi/OpenApi/ServerSentEventFilter.cs
+++ b/MumbleApi/OpenApi/ServerSentEventFilter.cs
@@ -268,6 +268,9 @@ private sealed class LikeInfo
{
public Ulid PostId { get; set; }
+ ///
+ /// The userid of the user that liked the post.
+ ///
/// 179944860378202369
public string UserId { get; set; } = string.Empty;
}
diff --git a/MumbleApi/Program.cs b/MumbleApi/Program.cs
index 1ac8a77..8eacf25 100644
--- a/MumbleApi/Program.cs
+++ b/MumbleApi/Program.cs
@@ -1,3 +1,4 @@
+using System.Configuration;
using System.Net;
using System.Reflection;
using System.Security.Claims;
@@ -21,6 +22,8 @@
using Zitadel.Authentication;
using Zitadel.Extensions;
+using IPNetwork = Microsoft.AspNetCore.HttpOverrides.IPNetwork;
+
var builder = WebApplication.CreateBuilder(args);
var config = builder.Configuration
@@ -28,7 +31,7 @@
.AddJsonFile("appsettings.Secrets.json", true)
.Build()
#endif
- .Get() ?? throw new("Could not read config.");
+ .Get() ?? new();
builder.Services.AddSingleton(config);
builder.Services.AddLogging(
diff --git a/MumbleApi/Services/PostUpdates.cs b/MumbleApi/Services/PostUpdates.cs
index b2e75a2..d8d3be9 100644
--- a/MumbleApi/Services/PostUpdates.cs
+++ b/MumbleApi/Services/PostUpdates.cs
@@ -8,7 +8,8 @@
namespace MumbleApi.Services;
-internal class PostUpdates : ServerSentEventsService, IPostUpdates
+internal class PostUpdates(IOptions> options)
+ : ServerSentEventsService(options), IPostUpdates
{
private static readonly JsonSerializerOptions Json = new()
{
@@ -16,11 +17,6 @@ internal class PostUpdates : ServerSentEventsService, IPostUpdates
DictionaryKeyPolicy = JsonNamingPolicy.CamelCase,
};
- public PostUpdates(IOptions> options)
- : base(options)
- {
- }
-
public Task NewPost(PostBase post)
=> SendEventAsync(new ServerSentEvent
{
diff --git a/MumbleApi/Services/Posts.cs b/MumbleApi/Services/Posts.cs
index ad63653..8535d38 100644
--- a/MumbleApi/Services/Posts.cs
+++ b/MumbleApi/Services/Posts.cs
@@ -10,21 +10,12 @@
namespace MumbleApi.Services;
-internal class Posts : IPosts
+internal class Posts(IDbContextFactory factory, IStorage storage) : IPosts
{
- private readonly IDbContextFactory _factory;
- private readonly IStorage _storage;
-
- public Posts(IDbContextFactory factory, IStorage storage)
- {
- _factory = factory;
- _storage = storage;
- }
-
public async Task<(IEnumerable Posts, int TotalCount)> GetPaginatedPostsWithLikes(
PostSearchParameters parameters)
{
- await using var db = await _factory.CreateDbContextAsync();
+ await using var db = await factory.CreateDbContextAsync();
var query = db.Posts
.Include(p => p.Replies)
@@ -80,7 +71,7 @@ await query
public async Task GetPostById(Ulid id)
{
- await using var db = await _factory.CreateDbContextAsync();
+ await using var db = await factory.CreateDbContextAsync();
var query = db.Posts
.Include(p => p.Replies)
@@ -104,7 +95,7 @@ public async Task CreatePost(
throw new PostInvalidException();
}
- await using var db = await _factory.CreateDbContextAsync();
+ await using var db = await factory.CreateDbContextAsync();
if (parentId is not null)
{
@@ -133,7 +124,7 @@ public async Task CreatePost(
{
post.MediaType = media.Value.MediaType;
post.MediaUrl =
- await _storage.UploadFile(Guid.NewGuid().ToString(), media.Value.MediaType, media.Value.File);
+ await storage.UploadFile(Guid.NewGuid().ToString(), media.Value.MediaType, media.Value.File);
}
await db.Posts.AddAsync(post);
@@ -153,7 +144,7 @@ public async Task ReplacePost(
throw new PostInvalidException();
}
- await using var db = await _factory.CreateDbContextAsync();
+ await using var db = await factory.CreateDbContextAsync();
var post = await db.Posts
.Include(p => p.Replies)
@@ -176,7 +167,7 @@ public async Task ReplacePost(
post.Text = text;
if (post.MediaId is not null)
{
- await _storage.DeleteFileIfPossible(post.MediaId);
+ await storage.DeleteFileIfPossible(post.MediaId);
}
post.MediaType = post.MediaUrl = null;
@@ -185,7 +176,7 @@ public async Task ReplacePost(
{
post.MediaType = media.Value.MediaType;
post.MediaUrl =
- await _storage.UploadFile(Guid.NewGuid().ToString(), media.Value.MediaType, media.Value.File);
+ await storage.UploadFile(Guid.NewGuid().ToString(), media.Value.MediaType, media.Value.File);
}
await db.SaveChangesAsync();
@@ -194,7 +185,7 @@ public async Task ReplacePost(
public async Task UpdatePost(string userId, Ulid postId, string text)
{
- await using var db = await _factory.CreateDbContextAsync();
+ await using var db = await factory.CreateDbContextAsync();
var post = await db.Posts
.Include(p => p.Replies)
@@ -227,7 +218,7 @@ public async Task UpdatePost(string userId, Ulid postId, string text)
public async Task UpdatePostMedia(string userId, Ulid postId, (Stream File, string MediaType)? media = null)
{
- await using var db = await _factory.CreateDbContextAsync();
+ await using var db = await factory.CreateDbContextAsync();
var post = await db.Posts
.Include(p => p.Replies)
@@ -254,7 +245,7 @@ public async Task UpdatePostMedia(string userId, Ulid postId, (Stream File
if (post.MediaId is not null)
{
- await _storage.DeleteFileIfPossible(post.MediaId);
+ await storage.DeleteFileIfPossible(post.MediaId);
}
post.MediaType = post.MediaUrl = null;
@@ -262,7 +253,7 @@ public async Task UpdatePostMedia(string userId, Ulid postId, (Stream File
{
post.MediaType = media.Value.MediaType;
post.MediaUrl =
- await _storage.UploadFile(Guid.NewGuid().ToString(), media.Value.MediaType, media.Value.File);
+ await storage.UploadFile(Guid.NewGuid().ToString(), media.Value.MediaType, media.Value.File);
}
await db.SaveChangesAsync();
@@ -271,7 +262,7 @@ public async Task UpdatePostMedia(string userId, Ulid postId, (Stream File
public async Task DeletePost(string userId, Ulid postId)
{
- await using var db = await _factory.CreateDbContextAsync();
+ await using var db = await factory.CreateDbContextAsync();
var post = await db.Posts
.Where(p => p.Id == postId)
@@ -295,7 +286,7 @@ public async Task DeletePost(string userId, Ulid postId)
public async Task LikePost(string userId, Ulid postId)
{
- await using var db = await _factory.CreateDbContextAsync();
+ await using var db = await factory.CreateDbContextAsync();
if (await db.Posts.SingleOrDefaultAsync(p => p.Id == postId && p.Deleted == null) is null)
{
@@ -312,7 +303,7 @@ insert into likes(post_id, user_id)
public async Task UnlikePost(string userId, Ulid postId)
{
- await using var db = await _factory.CreateDbContextAsync();
+ await using var db = await factory.CreateDbContextAsync();
if (await db.Posts.SingleOrDefaultAsync(p => p.Id == postId && p.Deleted == null) is null)
{
@@ -330,7 +321,7 @@ delete from likes
Ulid postId,
PaginationParameters pagination)
{
- await using var db = await _factory.CreateDbContextAsync();
+ await using var db = await factory.CreateDbContextAsync();
var parent = await db.Posts.SingleOrDefaultAsync(p => p.Id == postId);
diff --git a/MumbleApi/Services/Storage.cs b/MumbleApi/Services/Storage.cs
index 24bc888..5c26675 100644
--- a/MumbleApi/Services/Storage.cs
+++ b/MumbleApi/Services/Storage.cs
@@ -9,16 +9,10 @@
namespace MumbleApi.Services;
-internal class Storage : IStorage
+internal class Storage(AppConfig config) : IStorage
{
- private readonly string _bucketName;
- private readonly StorageClient _gcs;
-
- public Storage(AppConfig config)
- {
- _bucketName = config.Storage.Bucket;
- _gcs = StorageClient.Create(GoogleCredential.FromJson(config.Storage.ServiceAccountKey));
- }
+ private readonly string _bucketName = config.Storage.Bucket;
+ private readonly StorageClient _gcs = StorageClient.Create(GoogleCredential.FromJson(config.Storage.ServiceAccountKey));
public async Task UploadFile(string filename, string contentType, Stream file)
{
diff --git a/MumbleApi/Services/Users.cs b/MumbleApi/Services/Users.cs
index c64b700..c176be7 100644
--- a/MumbleApi/Services/Users.cs
+++ b/MumbleApi/Services/Users.cs
@@ -10,20 +10,11 @@
namespace MumbleApi.Services;
-internal class Users : IUsers
+internal class Users(IDbContextFactory factory, IStorage storage) : IUsers
{
- private readonly IDbContextFactory _factory;
- private readonly IStorage _storage;
-
- public Users(IDbContextFactory factory, IStorage storage)
- {
- _factory = factory;
- _storage = storage;
- }
-
public async Task<(IEnumerable Users, int TotalCount)> GetPaginatedUsers(PaginationParameters pagination)
{
- await using var db = await _factory.CreateDbContextAsync();
+ await using var db = await factory.CreateDbContextAsync();
var query = db.Users
.OrderBy(u => u.Id);
@@ -39,13 +30,13 @@ public Users(IDbContextFactory factory, IStorage storage)
public async Task GetUserById(string id)
{
- await using var db = await _factory.CreateDbContextAsync();
+ await using var db = await factory.CreateDbContextAsync();
return await db.Users.SingleOrDefaultAsync(u => u.Id == id);
}
public async Task UpdateUser(string id, string? firstname, string? lastname, string? username)
{
- await using var db = await _factory.CreateDbContextAsync();
+ await using var db = await factory.CreateDbContextAsync();
var user = await db.Users.SingleOrDefaultAsync(u => u.Id == id);
if (user is null)
@@ -62,12 +53,12 @@ public async Task UpdateUser(string id, string? firstname, string? lastname, str
public async Task UpdateUserAvatar(string id, (Stream File, string MediaType)? avatar = null)
{
- await using var db = await _factory.CreateDbContextAsync();
+ await using var db = await factory.CreateDbContextAsync();
var user = await db.Users.SingleAsync(u => u.Id == id);
if (user.AvatarId is not null)
{
- await _storage.DeleteFileIfPossible(user.AvatarId);
+ await storage.DeleteFileIfPossible(user.AvatarId);
}
user.AvatarUrl = user.AvatarMediaType = null;
@@ -75,7 +66,7 @@ public async Task UpdateUser(string id, string? firstname, string? lastname, str
{
user.AvatarMediaType = avatar.Value.MediaType;
user.AvatarUrl =
- await _storage.UploadFile(Guid.NewGuid().ToString(), avatar.Value.MediaType, avatar.Value.File);
+ await storage.UploadFile(Guid.NewGuid().ToString(), avatar.Value.MediaType, avatar.Value.File);
}
await db.SaveChangesAsync();
@@ -86,7 +77,7 @@ public async Task UpdateUser(string id, string? firstname, string? lastname, str
string id,
PaginationParameters pagination)
{
- await using var db = await _factory.CreateDbContextAsync();
+ await using var db = await factory.CreateDbContextAsync();
var query = db.Follows
.Where(f => f.FolloweeId == id)
@@ -105,7 +96,7 @@ public async Task UpdateUser(string id, string? firstname, string? lastname, str
string id,
PaginationParameters pagination)
{
- await using var db = await _factory.CreateDbContextAsync();
+ await using var db = await factory.CreateDbContextAsync();
var query = db.Follows
.Where(f => f.FollowerId == id)
@@ -122,7 +113,7 @@ public async Task UpdateUser(string id, string? firstname, string? lastname, str
public async Task FollowUser(string userId, string followeeId)
{
- await using var db = await _factory.CreateDbContextAsync();
+ await using var db = await factory.CreateDbContextAsync();
try
{
await db.Database.ExecuteSqlInterpolatedAsync($@"
@@ -138,7 +129,7 @@ insert into follows(follower_id, followee_id)
public async Task UnfollowUser(string userId, string followeeId)
{
- await using var db = await _factory.CreateDbContextAsync();
+ await using var db = await factory.CreateDbContextAsync();
if (!await db.Users.AnyAsync(u => u.Id == followeeId))
{