Skip to content

Commit d54a65d

Browse files
committed
Adjust API routes
1 parent a672659 commit d54a65d

6 files changed

Lines changed: 157 additions & 24 deletions

File tree

Backend.Tests/Controllers/AuthControllerTests.cs

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@ namespace Backend.Tests.Controllers
1414
{
1515
internal sealed class AuthControllerTests : IDisposable
1616
{
17-
private PermissionServiceMock _permissionService = null!;
1817
private LexboxAuthServiceMock _lexboxAuthService = null!;
18+
private PermissionServiceMock _permissionService = null!;
1919
private AuthController _controller = null!;
2020

2121
public void Dispose()
@@ -27,16 +27,11 @@ public void Dispose()
2727
[SetUp]
2828
public void Setup()
2929
{
30-
_permissionService = new PermissionServiceMock();
3130
_lexboxAuthService = new LexboxAuthServiceMock();
32-
var configValues = new Dictionary<string, string?>
33-
{
34-
{ "LexboxAuth:PostLoginRedirect", "/" },
35-
};
36-
var configuration = new ConfigurationBuilder()
37-
.AddInMemoryCollection(configValues)
38-
.Build();
39-
_controller = new AuthController(_permissionService, _lexboxAuthService, configuration);
31+
_permissionService = new PermissionServiceMock();
32+
var configValues = new Dictionary<string, string?> { { "LexboxAuth:PostLoginRedirect", "/" } };
33+
var configuration = new ConfigurationBuilder().AddInMemoryCollection(configValues).Build();
34+
_controller = new AuthController(_lexboxAuthService, _permissionService, configuration);
4035
}
4136

4237
[Test]
@@ -90,7 +85,7 @@ private sealed class LexboxAuthServiceMock : ILexboxAuthService
9085

9186
public LexboxLoginUrl CreateLoginUrl(HttpRequest request, string sessionId, string? returnUrl)
9287
{
93-
return new LexboxLoginUrl { Url = "https://example.test/login" };
88+
return new LexboxLoginUrl { Url = "not-a-valid-url" };
9489
}
9590

9691
public Task<LexboxAuthResult?> CompleteLoginAsync(HttpRequest request, string code, string state)

Backend/Controllers/AuthController.cs

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using System;
22
using System.Threading.Tasks;
3+
using BackendFramework.Helper;
34
using BackendFramework.Interfaces;
45
using BackendFramework.Models;
56
using BackendFramework.Otel;
@@ -11,9 +12,7 @@ namespace BackendFramework.Controllers
1112
{
1213
[Produces("application/json")]
1314
[Route("v1/auth")]
14-
public class AuthController(
15-
IPermissionService permissionService,
16-
ILexboxAuthService lexboxAuthService,
15+
public class AuthController(ILexboxAuthService lexboxAuthService, IPermissionService permissionService,
1716
IConfiguration configuration) : Controller
1817
{
1918
private readonly IPermissionService _permissionService = permissionService;
@@ -27,6 +26,7 @@ public class AuthController(
2726
/// <summary> Gets authentication status for the current request. </summary>
2827
[HttpGet("status", Name = "GetAuthStatus")]
2928
[ProducesResponseType(StatusCodes.Status200OK, Type = typeof(AuthStatus))]
29+
[ProducesResponseType(StatusCodes.Status403Forbidden)]
3030
public IActionResult GetAuthStatus()
3131
{
3232
using var activity = OtelService.StartActivityWithTag(otelTagName, "getting auth status");
@@ -40,10 +40,11 @@ public IActionResult GetAuthStatus()
4040
}
4141

4242
/// <summary> Generates a Lexbox login URL for OIDC sign-in. </summary>
43-
[HttpGet("lexbox/login-url", Name = "GetLexboxLoginUrl")]
43+
[HttpGet("lexbox-login-url", Name = "GetLexboxLoginUrl")]
4444
[ProducesResponseType(StatusCodes.Status200OK, Type = typeof(LexboxLoginUrl))]
45+
[ProducesResponseType(StatusCodes.Status403Forbidden)]
4546
[ProducesResponseType(StatusCodes.Status500InternalServerError)]
46-
public IActionResult GetLexboxLoginUrl([FromQuery] string? returnUrl = null)
47+
public IActionResult GetLexboxLoginUrl()
4748
{
4849
using var activity = OtelService.StartActivityWithTag(otelTagName, "getting lexbox login url");
4950
if (!_permissionService.IsCurrentUserAuthenticated(HttpContext))
@@ -62,8 +63,8 @@ public IActionResult GetLexboxLoginUrl([FromQuery] string? returnUrl = null)
6263
IsEssential = true,
6364
Path = "/",
6465
});
65-
var normalizedReturnUrl = NormalizeReturnUrl(returnUrl) ??
66-
NormalizeReturnUrl(_configuration[PostLoginRedirectConfigKey]);
66+
var normalizedReturnUrl = NormalizeReturnUrl(_configuration[PostLoginRedirectConfigKey])
67+
?? NormalizeReturnUrl(Domain.FrontendDomain);
6768
var result = _lexboxAuthService.CreateLoginUrl(Request, sessionId, normalizedReturnUrl);
6869
return Ok(result);
6970
}
@@ -74,9 +75,10 @@ public IActionResult GetLexboxLoginUrl([FromQuery] string? returnUrl = null)
7475
}
7576

7677
/// <summary> Completes the Lexbox OAuth login and stores the login status. </summary>
77-
[HttpGet("/api/auth/oauth-callback", Name = "LexboxOauthCallback")]
78+
[HttpGet("oauth-callback", Name = "LexboxOauthCallback")]
7879
[ProducesResponseType(StatusCodes.Status200OK, Type = typeof(AuthStatus))]
7980
[ProducesResponseType(StatusCodes.Status400BadRequest)]
81+
[ProducesResponseType(StatusCodes.Status403Forbidden)]
8082
public async Task<IActionResult> CompleteLexboxLogin([FromQuery] string? code, [FromQuery] string? state)
8183
{
8284
using var activity = OtelService.StartActivityWithTag(otelTagName, "completing lexbox login");

Backend/Services/LexboxAuthService.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ public LexboxLoginUrl CreateLoginUrl(HttpRequest request, string sessionId, stri
6262
};
6363

6464
var loginReturnUrl = QueryHelpers.AddQueryString("/api/oauth/open-id-auth", query);
65+
Console.WriteLine($"Return URL: {loginReturnUrl}");
6566
var loginUrl = $"{settings.BaseUrl.TrimEnd('/')}/login?ReturnUrl={Uri.EscapeDataString(loginReturnUrl)}";
6667

6768
return new LexboxLoginUrl { Url = loginUrl };
@@ -110,7 +111,7 @@ public LexboxLoginUrl CreateLoginUrl(HttpRequest request, string sessionId, stri
110111
private static string BuildRedirectUri(HttpRequest request)
111112
{
112113
var pathBase = request.PathBase.HasValue ? request.PathBase.Value : string.Empty;
113-
return $"{request.Scheme}://{request.Host}{pathBase}/api/auth/oauth-callback";
114+
return $"{request.Scheme}://{request.Host}{pathBase}/v1/auth/oauth-callback";
114115
}
115116

116117
private LexboxAuthSettings GetSettings()

Backend/appsettings.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,11 @@
1212
"LexboxAuth": {
1313
"BaseUrl": "https://lexbox.org",
1414
"ClientId": "becf2856-0690-434b-b192-a4032b72067f",
15-
"Scope": "profile openid offline_access sendandreceive",
16-
"Prompt": "select_account",
15+
"ClientOs": "Microsoft Windows",
1716
"ClientSku": "TheCombine",
1817
"ClientVersion": "1.0",
19-
"ClientOs": "Microsoft Windows"
18+
"Prompt": "select_account",
19+
"Scope": "profile openid offline_access sendandreceive"
2020
},
2121
"AllowedHosts": "*"
2222
}

src/api/api/auth-api.ts

Lines changed: 135 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ export const AuthApiAxiosParamCreator = function (
9090
* @throws {RequiredError}
9191
*/
9292
getLexboxLoginUrl: async (options: any = {}): Promise<RequestArgs> => {
93-
const localVarPath = `/v1/auth/lexbox/login-url`;
93+
const localVarPath = `/v1/auth/lexbox-login-url`;
9494
// use dummy base URL string because the URL constructor only accepts absolute URLs.
9595
const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL);
9696
let baseOptions;
@@ -115,6 +115,56 @@ export const AuthApiAxiosParamCreator = function (
115115
...options.headers,
116116
};
117117

118+
return {
119+
url: toPathString(localVarUrlObj),
120+
options: localVarRequestOptions,
121+
};
122+
},
123+
/**
124+
*
125+
* @param {string} [code]
126+
* @param {string} [state]
127+
* @param {*} [options] Override http request option.
128+
* @throws {RequiredError}
129+
*/
130+
lexboxOauthCallback: async (
131+
code?: string,
132+
state?: string,
133+
options: any = {}
134+
): Promise<RequestArgs> => {
135+
const localVarPath = `/v1/auth/oauth-callback`;
136+
// use dummy base URL string because the URL constructor only accepts absolute URLs.
137+
const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL);
138+
let baseOptions;
139+
if (configuration) {
140+
baseOptions = configuration.baseOptions;
141+
}
142+
143+
const localVarRequestOptions = {
144+
method: "GET",
145+
...baseOptions,
146+
...options,
147+
};
148+
const localVarHeaderParameter = {} as any;
149+
const localVarQueryParameter = {} as any;
150+
151+
if (code !== undefined) {
152+
localVarQueryParameter["code"] = code;
153+
}
154+
155+
if (state !== undefined) {
156+
localVarQueryParameter["state"] = state;
157+
}
158+
159+
setSearchParams(localVarUrlObj, localVarQueryParameter, options.query);
160+
let headersFromBaseOptions =
161+
baseOptions && baseOptions.headers ? baseOptions.headers : {};
162+
localVarRequestOptions.headers = {
163+
...localVarHeaderParameter,
164+
...headersFromBaseOptions,
165+
...options.headers,
166+
};
167+
118168
return {
119169
url: toPathString(localVarUrlObj),
120170
options: localVarRequestOptions,
@@ -168,6 +218,33 @@ export const AuthApiFp = function (configuration?: Configuration) {
168218
configuration
169219
);
170220
},
221+
/**
222+
*
223+
* @param {string} [code]
224+
* @param {string} [state]
225+
* @param {*} [options] Override http request option.
226+
* @throws {RequiredError}
227+
*/
228+
async lexboxOauthCallback(
229+
code?: string,
230+
state?: string,
231+
options?: any
232+
): Promise<
233+
(axios?: AxiosInstance, basePath?: string) => AxiosPromise<AuthStatus>
234+
> {
235+
const localVarAxiosArgs =
236+
await localVarAxiosParamCreator.lexboxOauthCallback(
237+
code,
238+
state,
239+
options
240+
);
241+
return createRequestFunction(
242+
localVarAxiosArgs,
243+
globalAxios,
244+
BASE_PATH,
245+
configuration
246+
);
247+
},
171248
};
172249
};
173250

@@ -202,9 +279,46 @@ export const AuthApiFactory = function (
202279
.getLexboxLoginUrl(options)
203280
.then((request) => request(axios, basePath));
204281
},
282+
/**
283+
*
284+
* @param {string} [code]
285+
* @param {string} [state]
286+
* @param {*} [options] Override http request option.
287+
* @throws {RequiredError}
288+
*/
289+
lexboxOauthCallback(
290+
code?: string,
291+
state?: string,
292+
options?: any
293+
): AxiosPromise<AuthStatus> {
294+
return localVarFp
295+
.lexboxOauthCallback(code, state, options)
296+
.then((request) => request(axios, basePath));
297+
},
205298
};
206299
};
207300

301+
/**
302+
* Request parameters for lexboxOauthCallback operation in AuthApi.
303+
* @export
304+
* @interface AuthApiLexboxOauthCallbackRequest
305+
*/
306+
export interface AuthApiLexboxOauthCallbackRequest {
307+
/**
308+
*
309+
* @type {string}
310+
* @memberof AuthApiLexboxOauthCallback
311+
*/
312+
readonly code?: string;
313+
314+
/**
315+
*
316+
* @type {string}
317+
* @memberof AuthApiLexboxOauthCallback
318+
*/
319+
readonly state?: string;
320+
}
321+
208322
/**
209323
* AuthApi - object-oriented interface
210324
* @export
@@ -235,4 +349,24 @@ export class AuthApi extends BaseAPI {
235349
.getLexboxLoginUrl(options)
236350
.then((request) => request(this.axios, this.basePath));
237351
}
352+
353+
/**
354+
*
355+
* @param {AuthApiLexboxOauthCallbackRequest} requestParameters Request parameters.
356+
* @param {*} [options] Override http request option.
357+
* @throws {RequiredError}
358+
* @memberof AuthApi
359+
*/
360+
public lexboxOauthCallback(
361+
requestParameters: AuthApiLexboxOauthCallbackRequest = {},
362+
options?: any
363+
) {
364+
return AuthApiFp(this.configuration)
365+
.lexboxOauthCallback(
366+
requestParameters.code,
367+
requestParameters.state,
368+
options
369+
)
370+
.then((request) => request(this.axios, this.basePath));
371+
}
238372
}

src/components/Lexbox/LexboxLogin.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ export default function LexboxLogin(props: LexboxLoginProps): ReactElement {
4646
setActionLoading(true);
4747
try {
4848
const url = await getExternalLoginUrl();
49+
console.info("Opening Lexbox login URL:", url);
4950
if (url) {
5051
window.open(url);
5152
} else {

0 commit comments

Comments
 (0)