111 lines
4.3 KiB
C#
111 lines
4.3 KiB
C#
using System;
|
|
using System.Linq;
|
|
using System.Net.Http.Json;
|
|
using FsTool;
|
|
using FsTool.Helpers;
|
|
|
|
namespace FsTool.Tasks
|
|
{
|
|
public static class UserTasks
|
|
{
|
|
/// <summary>
|
|
/// Performs a login request using configured credentials and optional two-factor authentication.
|
|
/// </summary>
|
|
/// <param name="httpClient">The HTTP client used to send the request.</param>
|
|
/// <returns>The CSRF token when login succeeds; otherwise, <c>null</c>.</returns>
|
|
public static async Task<string?> CallLoginEndpointAsync(HttpClient httpClient)
|
|
{
|
|
var credentials = SettingsProvider.Current.Credentials;
|
|
|
|
if (string.IsNullOrWhiteSpace(credentials.Email) || string.IsNullOrWhiteSpace(credentials.Password))
|
|
{
|
|
Console.WriteLine("Email and password must be configured in appsettings.json.");
|
|
return null;
|
|
}
|
|
|
|
string? authCode = null;
|
|
if (credentials.TwoFactorEnabled)
|
|
{
|
|
Console.Write("Enter 2FA code: ");
|
|
authCode = Console.ReadLine()?.Trim();
|
|
|
|
if (string.IsNullOrWhiteSpace(authCode))
|
|
{
|
|
Console.WriteLine("A valid 2FA code is required when two-factor authentication is enabled.");
|
|
return null;
|
|
}
|
|
}
|
|
|
|
string? csrfToken = null;
|
|
|
|
object payload = credentials.TwoFactorEnabled
|
|
? new
|
|
{
|
|
email = credentials.Email,
|
|
password = credentials.Password,
|
|
code = authCode,
|
|
remember_me = true
|
|
}
|
|
: new
|
|
{
|
|
email = credentials.Email,
|
|
password = credentials.Password,
|
|
remember_me = true
|
|
};
|
|
|
|
var response = await httpClient.PostAsJsonAsync(Endpoints.UserLogin, payload);
|
|
|
|
// handle unsuccessful response
|
|
if (!response.IsSuccessStatusCode)
|
|
{
|
|
var responseBody = await response.Content.ReadAsStringAsync();
|
|
await Console.Error.WriteLineAsync($"Login failed ({(int)response.StatusCode} {response.ReasonPhrase}): {responseBody}");
|
|
return null;
|
|
}
|
|
|
|
// Read headers as dictionary
|
|
var headers = response.Headers.ToDictionary(h => h.Key, h => string.Join(", ", h.Value));
|
|
if (headers.TryGetValue("Set-Cookie", out var setCookieHeader))
|
|
{
|
|
// Split cookies by comma and semicolon
|
|
var cookies = setCookieHeader.Split([";"], StringSplitOptions.RemoveEmptyEntries);
|
|
var csrfTokenEntry = cookies.FirstOrDefault(c => c.Trim().StartsWith("FS_CSRF_TOKEN="));
|
|
csrfToken = csrfTokenEntry?.Split('=')[1];
|
|
|
|
if (string.IsNullOrWhiteSpace(csrfToken)) return null;
|
|
|
|
var expiryEntry = cookies.FirstOrDefault(c => c.Trim().StartsWith("expires="));
|
|
var expireString = expiryEntry?.Split('=')[1];
|
|
if (DateTime.TryParse(expireString, out var expiration))
|
|
await AuthHelper.StoreCsrfTokenAsync(csrfToken, expiration);
|
|
}
|
|
|
|
return csrfToken;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Retrieves information about the current authenticated user.
|
|
/// </summary>
|
|
/// <param name="httpClient">The HTTP client used to send the request.</param>
|
|
/// <returns>A task that represents the asynchronous operation.</returns>
|
|
public static async Task GetCurrentUserAsync(HttpClient httpClient)
|
|
{
|
|
await AuthHelper.EnsureAuthenticationAsync(httpClient);
|
|
|
|
var response = await httpClient.GetAsync(Endpoints.UserCurrent);
|
|
|
|
// handle unsuccessful response
|
|
if (!response.IsSuccessStatusCode)
|
|
{
|
|
var responseBody = await response.Content.ReadAsStringAsync();
|
|
await Console.Error.WriteLineAsync($"Get current user failed ({(int)response.StatusCode} {response.ReasonPhrase}): {responseBody}");
|
|
return;
|
|
}
|
|
|
|
var content = await response.Content.ReadAsStringAsync();
|
|
Console.WriteLine("Current User Info:");
|
|
Console.WriteLine(content);
|
|
}
|
|
}
|
|
}
|