Skip to content

Commit 5a21523

Browse files
committed
Cleaned up pagination in user and apikey controller. Extracted login start and start url generation to modular IOAuth2Provider interface. Improved login and register local oauth2 page
1 parent 6a29b53 commit 5a21523

File tree

10 files changed

+66
-80
lines changed

10 files changed

+66
-80
lines changed

Moonlight.ApiServer/Http/Controllers/Admin/ApiKeys/ApiKeysController.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,8 @@ public ApiKeysController(DatabaseRepository<ApiKey> apiKeyRepository, ApiKeyServ
2828
[HttpGet]
2929
[Authorize(Policy = "permissions:admin.apikeys.get")]
3030
public async Task<IPagedData<ApiKeyResponse>> Get(
31-
[FromQuery] int page,
32-
[FromQuery] [Range(1, 100)] int pageSize = 50
31+
[FromQuery] [Range(0, int.MaxValue)] int page,
32+
[FromQuery] [Range(1, 100)] int pageSize
3333
)
3434
{
3535
var count = await ApiKeyRepository.Get().CountAsync();

Moonlight.ApiServer/Http/Controllers/Admin/Users/UsersController.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ public UsersController(DatabaseRepository<User> userRepository)
2727
[Authorize(Policy = "permissions:admin.users.get")]
2828
public async Task<IPagedData<UserResponse>> Get(
2929
[FromQuery] [Range(0, int.MaxValue)] int page,
30-
[FromQuery] [Range(1, 100)] int pageSize = 50
30+
[FromQuery] [Range(1, 100)] int pageSize
3131
)
3232
{
3333
var count = await UserRepository.Get().CountAsync();

Moonlight.ApiServer/Http/Controllers/Auth/AuthController.cs

Lines changed: 9 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
using System.IdentityModel.Tokens.Jwt;
2+
using System.Security.Claims;
23
using System.Text;
34
using Microsoft.AspNetCore.Authorization;
45
using Microsoft.AspNetCore.Mvc;
56
using Microsoft.EntityFrameworkCore;
6-
using Microsoft.Extensions.Logging;
77
using Microsoft.IdentityModel.Tokens;
88
using MoonCore.Exceptions;
99
using MoonCore.Extended.Abstractions;
@@ -20,53 +20,37 @@ namespace Moonlight.ApiServer.Http.Controllers.Auth;
2020
public class AuthController : Controller
2121
{
2222
private readonly AppConfiguration Configuration;
23-
private readonly ILogger<AuthController> Logger;
2423
private readonly DatabaseRepository<User> UserRepository;
2524
private readonly IOAuth2Provider OAuth2Provider;
2625

27-
private readonly string RedirectUri;
28-
private readonly string EndpointUri;
29-
3026
public AuthController(
3127
AppConfiguration configuration,
32-
ILogger<AuthController> logger,
3328
DatabaseRepository<User> userRepository,
3429
IOAuth2Provider oAuth2Provider
3530
)
3631
{
3732
UserRepository = userRepository;
3833
OAuth2Provider = oAuth2Provider;
3934
Configuration = configuration;
40-
Logger = logger;
41-
42-
RedirectUri = string.IsNullOrEmpty(Configuration.Authentication.OAuth2.AuthorizationRedirect)
43-
? Configuration.PublicUrl
44-
: Configuration.Authentication.OAuth2.AuthorizationRedirect;
45-
46-
EndpointUri = string.IsNullOrEmpty(Configuration.Authentication.OAuth2.AuthorizationEndpoint)
47-
? Configuration.PublicUrl + "/oauth2/authorize"
48-
: Configuration.Authentication.OAuth2.AuthorizationEndpoint;
4935
}
5036

5137
[AllowAnonymous]
5238
[HttpGet("start")]
53-
public Task<LoginStartResponse> Start()
39+
public async Task<LoginStartResponse> Start()
5440
{
55-
var response = new LoginStartResponse()
41+
var url = await OAuth2Provider.Start();
42+
43+
return new LoginStartResponse()
5644
{
57-
ClientId = Configuration.Authentication.OAuth2.ClientId,
58-
RedirectUri = RedirectUri,
59-
Endpoint = EndpointUri
45+
Url = url
6046
};
61-
62-
return Task.FromResult(response);
6347
}
6448

6549
[AllowAnonymous]
6650
[HttpPost("complete")]
6751
public async Task<LoginCompleteResponse> Complete([FromBody] LoginCompleteRequest request)
6852
{
69-
var user = await OAuth2Provider.Sync(request.Code);
53+
var user = await OAuth2Provider.Complete(request.Code);
7054

7155
if (user == null)
7256
throw new HttpApiException("Unable to load user data", 500);
@@ -113,8 +97,8 @@ public async Task<LoginCompleteResponse> Complete([FromBody] LoginCompleteReques
11397
[HttpGet("check")]
11498
public async Task<CheckResponse> Check()
11599
{
116-
var userIdClaim = User.Claims.First(x => x.Type == "userId");
117-
var userId = int.Parse(userIdClaim.Value);
100+
var userIdStr = User.FindFirstValue("userId")!;
101+
var userId = int.Parse(userIdStr);
118102
var user = await UserRepository.Get().FirstAsync(x => x.Id == userId);
119103

120104
return new()

Moonlight.ApiServer/Http/Controllers/Frontend/FrontendPage.razor

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,10 @@
77
<head>
88
<meta charset="utf-8"/>
99
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
10-
<title>@Configuration.Title</title>
10+
<title>@Title</title>
1111
<base href="/"/>
1212

13-
@foreach (var style in Configuration.Styles)
13+
@foreach (var style in Styles)
1414
{
1515
<link rel="stylesheet" href="@style"/>
1616
}
@@ -86,7 +86,7 @@
8686

8787
</div>
8888

89-
@foreach (var script in Configuration.Scripts)
89+
@foreach (var script in Scripts)
9090
{
9191
<script src="@script"></script>
9292
}
@@ -99,6 +99,8 @@
9999

100100
@code
101101
{
102-
[Parameter] public FrontendConfiguration Configuration { get; set; }
102+
[Parameter] public string Title { get; set; }
103+
[Parameter] public string[] Scripts { get; set; }
104+
[Parameter] public string[] Styles { get; set; }
103105
[Parameter] public Theme? Theme { get; set; }
104106
}

Moonlight.ApiServer/Implementations/LocalOAuth2Provider.cs

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,27 @@ DatabaseRepository<User> userRepository
2727
Logger = logger;
2828
}
2929

30-
public async Task<User?> Sync(string code)
30+
public Task<string> Start()
31+
{
32+
var redirectUri = string.IsNullOrEmpty(Configuration.Authentication.OAuth2.AuthorizationRedirect)
33+
? Configuration.PublicUrl
34+
: Configuration.Authentication.OAuth2.AuthorizationRedirect;
35+
36+
var endpoint = string.IsNullOrEmpty(Configuration.Authentication.OAuth2.AuthorizationEndpoint)
37+
? Configuration.PublicUrl + "/oauth2/authorize"
38+
: Configuration.Authentication.OAuth2.AuthorizationEndpoint;
39+
40+
var clientId = Configuration.Authentication.OAuth2.ClientId;
41+
42+
var url = $"{endpoint}" +
43+
$"?client_id={clientId}" +
44+
$"&redirect_uri={redirectUri}" +
45+
$"&response_type=code";
46+
47+
return Task.FromResult(url);
48+
}
49+
50+
public async Task<User?> Complete(string code)
3151
{
3252
// Create http client to call the auth provider
3353
var httpClient = new HttpClient();
@@ -70,6 +90,10 @@ DatabaseRepository<User> userRepository
7090
throw new HttpApiException("Unable to request user data", 500);
7191
}
7292

93+
// Notice: We just look up the user id here
94+
// which works as our oauth2 provider is using the same db.
95+
// a real oauth2 provider would create a user here
96+
7397
// Handle the returned data
7498
var userId = handleData.UserId;
7599

Moonlight.ApiServer/Interfaces/IOAuth2Provider.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,7 @@ namespace Moonlight.ApiServer.Interfaces;
44

55
public interface IOAuth2Provider
66
{
7-
public Task<User?> Sync(string code);
7+
public Task<string> Start();
8+
9+
public Task<User?> Complete(string code);
810
}

Moonlight.ApiServer/Services/FrontendService.cs

Lines changed: 18 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -40,53 +40,44 @@ DatabaseRepository<Theme> themeRepository
4040
ThemeRepository = themeRepository;
4141
}
4242

43-
public async Task<FrontendConfiguration> GetConfiguration()
43+
public Task<FrontendConfiguration> GetConfiguration()
4444
{
4545
var configuration = new FrontendConfiguration()
4646
{
47-
Title = "Moonlight", // TODO: CONFIG
4847
ApiUrl = Configuration.PublicUrl,
4948
HostEnvironment = "ApiServer"
5049
};
5150

52-
// Load theme.json if it exists
53-
var themePath = Path.Combine("storage", "theme.json");
54-
55-
if (File.Exists(themePath))
56-
{
57-
var variablesJson = await File.ReadAllTextAsync(themePath);
58-
59-
configuration.Theme.Variables = JsonSerializer
60-
.Deserialize<Dictionary<string, string>>(variablesJson) ?? new();
61-
}
62-
63-
// Collect scripts to execute
64-
configuration.Scripts = ConfigurationOptions
65-
.SelectMany(x => x.Scripts)
66-
.ToArray();
67-
68-
// Collect styles
69-
configuration.Styles = ConfigurationOptions
70-
.SelectMany(x => x.Styles)
71-
.ToArray();
72-
73-
return configuration;
51+
return Task.FromResult(configuration);
7452
}
7553

7654
public async Task<string> GenerateIndexHtml() // TODO: Cache
7755
{
78-
var configuration = await GetConfiguration();
79-
56+
// Load requested theme
8057
var theme = await ThemeRepository
8158
.Get()
8259
.FirstOrDefaultAsync(x => x.IsEnabled);
60+
61+
// Load configured javascript files
62+
var scripts = ConfigurationOptions
63+
.SelectMany(x => x.Scripts)
64+
.Distinct()
65+
.ToArray();
66+
67+
// Load configured css files
68+
var styles = ConfigurationOptions
69+
.SelectMany(x => x.Styles)
70+
.Distinct()
71+
.ToArray();
8372

8473
return await ComponentHelper.RenderComponent<FrontendPage>(
8574
ServiceProvider,
8675
parameters =>
8776
{
88-
parameters["Configuration"] = configuration;
8977
parameters["Theme"] = theme!;
78+
parameters["Styles"] = styles;
79+
parameters["Scripts"] = scripts;
80+
parameters["Title"] = "Moonlight"; // TODO: Config
9081
}
9182
);
9283
}

Moonlight.Client/Services/RemoteAuthStateManager.cs

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -83,12 +83,7 @@ private async Task StartLogin()
8383
{
8484
var loginStartData = await HttpApiClient.GetJson<LoginStartResponse>("api/auth/start");
8585

86-
var url = $"{loginStartData.Endpoint}" +
87-
$"?client_id={loginStartData.ClientId}" +
88-
$"&redirect_uri={loginStartData.RedirectUri}" +
89-
$"&response_type=code";
90-
91-
NavigationManager.NavigateTo(url, true);
86+
NavigationManager.NavigateTo(loginStartData.Url, true);
9287
}
9388

9489
private async Task<AuthenticationState> LoadAuthState()

Moonlight.Shared/Http/Responses/Auth/LoginStartResponse.cs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,5 @@ namespace Moonlight.Shared.Http.Responses.Auth;
22

33
public class LoginStartResponse
44
{
5-
public string ClientId { get; set; }
6-
public string Endpoint { get; set; }
7-
public string RedirectUri { get; set; }
5+
public string Url { get; set; }
86
}

Moonlight.Shared/Misc/FrontendConfiguration.cs

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,6 @@ namespace Moonlight.Shared.Misc;
22

33
public class FrontendConfiguration
44
{
5-
public string Title { get; set; }
65
public string ApiUrl { get; set; }
76
public string HostEnvironment { get; set; }
8-
public ThemeData Theme { get; set; } = new();
9-
public string[] Scripts { get; set; }
10-
public string[] Styles { get; set; }
11-
public string[] Assemblies { get; set; }
12-
13-
public class ThemeData
14-
{
15-
public Dictionary<string, string> Variables { get; set; } = new();
16-
}
177
}

0 commit comments

Comments
 (0)