elfisa-pharmacy/src/Elfisa.Core/Session.cs
Exest 436bbb8bfb версия 2.0.3: запоминание входа, быстрая загрузка прайса, повтор при SSL
- Session: сохранение/восстановление сессии между запусками (JWT exp-проверка)
- LoadPrice: страница 20000 вместо 500 — прайс грузится одним запросом
- ApiClient: повтор запроса на транзиентных сбоях TLS (поиск/загрузка)
- download-страница: реальный размер, macOS помечен «скоро»

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-13 09:23:29 +03:00

71 lines
2.5 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using System;
using System.Text.Json;
namespace Elfisa.Core;
/// <summary>Текущая сессия пользователя (токен, роль, логин). Сохраняется между запусками.</summary>
public sealed class Session
{
public static Session Current { get; } = new();
public string? Token { get; set; }
public string? Role { get; set; }
public string? Username { get; set; }
public bool IsAuthenticated => !string.IsNullOrWhiteSpace(Token);
/// <summary>Сохранить сессию в настройки (чтобы не логиниться каждый раз).</summary>
public void Save()
{
SettingsStore.Current.Token = Token;
SettingsStore.Current.Role = Role;
SettingsStore.Current.Username = Username;
SettingsStore.Save();
}
/// <summary>Восстановить сессию из настроек, если токен есть и не истёк.</summary>
public static bool TryRestore()
{
var s = SettingsStore.Current;
if (string.IsNullOrWhiteSpace(s.Token) || IsJwtExpired(s.Token))
return false;
Current.Token = s.Token;
Current.Role = s.Role;
Current.Username = s.Username;
return true;
}
public void Clear()
{
Token = null;
Role = null;
Username = null;
SettingsStore.Current.Token = null;
SettingsStore.Current.Role = null;
SettingsStore.Current.Username = null;
SettingsStore.Save();
}
/// <summary>Проверяет, истёк ли JWT (по claim exp), с запасом в 1 минуту.</summary>
private static bool IsJwtExpired(string token)
{
try
{
var parts = token.Split('.');
if (parts.Length != 3) return true;
var payload = parts[1].Replace('-', '+').Replace('_', '/');
switch (payload.Length % 4)
{
case 2: payload += "=="; break;
case 3: payload += "="; break;
}
var json = System.Text.Encoding.UTF8.GetString(Convert.FromBase64String(payload));
using var doc = JsonDocument.Parse(json);
if (doc.RootElement.TryGetProperty("exp", out var exp) && exp.TryGetInt64(out var expUnix))
return DateTimeOffset.UtcNow.ToUnixTimeSeconds() >= expUnix - 60;
return false; // нет exp — считаем валидным
}
catch { return true; }
}
}