Compare commits

...

4 Commits

Author SHA1 Message Date
serega404 1974f36b24 perf: отключил должности для экономии памяти
Create and publish a Docker image / Publish image (push) Successful in 1m30s
2026-05-04 17:20:50 +03:00
serega404 a75c952f45 docs: почистил документацию от остатков telegram
Create and publish a Docker image / Publish image (push) Successful in 28s
2026-05-04 13:45:27 +03:00
serega404 be1e2041ff chore: Remove Telegram logging
Create and publish a Docker image / Publish image (push) Successful in 1m19s
2026-05-04 12:27:38 +03:00
serega404 e237a248ca sync: MS Auth 2026-05-04 12:13:56 +03:00
9 changed files with 29 additions and 62 deletions
+3 -7
View File
@@ -23,10 +23,9 @@
- `employees.json` для локального индекса сотрудников; - `employees.json` для локального индекса сотрудников;
- `keys/` для ключей Data Protection; - `keys/` для ключей Data Protection;
- `Plugins/` для загружаемых плагинов. - `Plugins/` для загружаемых плагинов.
4. Настраивает логирование в консоль, а при наличии `TG_CHAT_ID` и `TG_TOKEN` ещё и отправку ошибок в Telegram. 4. Подключает Sentry, Swagger, Prometheus, rate limiter, API key auth и OpenID Connect через `Microsoft.Identity.Web`.
5. Подключает Sentry, Swagger, Prometheus, rate limiter, API key auth и OpenID Connect через `Microsoft.Identity.Web`. 5. Загружает все плагины `*.plugin.dll` из `data/Plugins` в отдельном `AssemblyLoadContext`.
6. Загружает все плагины `*.plugin.dll` из `data/Plugins` в отдельном `AssemblyLoadContext`. 6. Инициализирует Quartz-задачи:
7. Инициализирует Quartz-задачи:
- обновление JWT; - обновление JWT;
- обновление локального списка сотрудников; - обновление локального списка сотрудников;
- цепочку, при которой после успешного обновления JWT сразу запускается обновление сотрудников. - цепочку, при которой после успешного обновления JWT сразу запускается обновление сотрудников.
@@ -180,8 +179,6 @@ MVC-контроллеры из плагинов тоже подключаютс
| `PERMIT_LIMIT` | Нет | `40` | код | Лимит запросов в окне rate limiter | | `PERMIT_LIMIT` | Нет | `40` | код | Лимит запросов в окне rate limiter |
| `TIME_LIMIT` | Нет | `10` | код | Длина окна rate limiter в секундах | | `TIME_LIMIT` | Нет | `10` | код | Длина окна rate limiter в секундах |
| `TZ` | Нет | `Europe/Moscow` | код | Таймзона для запросов к`Modeus` и генерации `ICS` | | `TZ` | Нет | `Europe/Moscow` | код | Таймзона для запросов к`Modeus` и генерации `ICS` |
| `TG_CHAT_ID` | Нет | нет | код | Chat ID для Telegram-логирования |
| `TG_TOKEN` | Нет | нет | код | Bot token для Telegram-логирования |
| `Sentry:Dsn` | Нет | пустая строка | код | DSN для Sentry | | `Sentry:Dsn` | Нет | пустая строка | код | DSN для Sentry |
### Переменные для Microsoft / Azure AD ### Переменные для Microsoft / Azure AD
@@ -214,7 +211,6 @@ MVC-контроллеры из плагинов тоже подключаютс
- нужен `TOKEN` или рабочий `AUTH_URL`, чтобы ходить в `Modeus`; - нужен `TOKEN` или рабочий `AUTH_URL`, чтобы ходить в `Modeus`;
- нужен `API_KEY`, если вы хотите использовать `GET /api/schedule/getguid`; - нужен `API_KEY`, если вы хотите использовать `GET /api/schedule/getguid`;
- нужны `AzureAd:*`, если используется `GET /api/sfedu/guid`; - нужны `AzureAd:*`, если используется `GET /api/sfedu/guid`;
- нужны `TG_CHAT_ID` и `TG_TOKEN`, если хотите логирование в Telegram;
- нужен `Sentry:Dsn`, если хотите отправлять ошибки и трейсы в Sentry. - нужен `Sentry:Dsn`, если хотите отправлять ошибки и трейсы в Sentry.
## Пример `.env` ## Пример `.env`
-4
View File
@@ -11,10 +11,6 @@ public static class AppConsts
public const string ModeusUrlEnv = "MODEUS_URL"; public const string ModeusUrlEnv = "MODEUS_URL";
public const string ModeusDefaultUrl = "https://sfedu.modeus.org/"; public const string ModeusDefaultUrl = "https://sfedu.modeus.org/";
// Telegram
public const string TgChatIdEnv = "TG_CHAT_ID";
public const string TgTokenEnv = "TG_TOKEN";
// RateLimiter // RateLimiter
public const string PermitLimitEnv = "PERMIT_LIMIT"; public const string PermitLimitEnv = "PERMIT_LIMIT";
public const string TimeLimitEnv = "TIME_LIMIT"; public const string TimeLimitEnv = "TIME_LIMIT";
-21
View File
@@ -18,7 +18,6 @@ using SfeduSchedule.Jobs;
using SfeduSchedule.Logging; using SfeduSchedule.Logging;
using SfeduSchedule.Middleware; using SfeduSchedule.Middleware;
using SfeduSchedule.Services; using SfeduSchedule.Services;
using X.Extensions.Logging.Telegram.Extensions;
using IPNetwork = Microsoft.AspNetCore.HttpOverrides.IPNetwork; using IPNetwork = Microsoft.AspNetCore.HttpOverrides.IPNetwork;
var builder = WebApplication.CreateBuilder(args); var builder = WebApplication.CreateBuilder(args);
@@ -59,26 +58,6 @@ builder.Logging.AddConsole(options => options.FormatterName = "CustomConsoleForm
.AddConsoleFormatter<ConsoleFormatter, ConsoleFormatterOptions>(); .AddConsoleFormatter<ConsoleFormatter, ConsoleFormatterOptions>();
builder.Logging.AddFilter("Quartz", LogLevel.Warning); builder.Logging.AddFilter("Quartz", LogLevel.Warning);
if (!string.IsNullOrEmpty(configuration[AppConsts.TgChatIdEnv]) && !string.IsNullOrEmpty(configuration[AppConsts.TgTokenEnv]))
builder.Logging.AddTelegram(options =>
{
options.FormatterConfiguration = new X.Extensions.Logging.Telegram.Base.Configuration.FormatterConfiguration
{
IncludeException = true,
IncludeProperties = true,
};
options.ChatId = configuration[AppConsts.TgChatIdEnv]!;
options.AccessToken = configuration[AppConsts.TgTokenEnv]!;
options.FormatterConfiguration.UseEmoji = true;
options.FormatterConfiguration.ReadableApplicationName = "Modeus Schedule Proxy";
options.LogLevel = new Dictionary<string, LogLevel>
{
{ "Default", LogLevel.Error },
{ "SfeduSchedule.Jobs.UpdateJwtJob", LogLevel.Information },
{ "Program", LogLevel.Information },
{ "Quartz", LogLevel.Warning }
};
});
#endregion #endregion
builder.WebHost.UseSentry(options => builder.WebHost.UseSentry(options =>
@@ -3,7 +3,7 @@ using System.Text.Json;
namespace SfeduSchedule.Services; namespace SfeduSchedule.Services;
public class ModeusEmployeeService(ISchedulerFactory schedulerFactory) public class ModeusEmployeeService
: IHostedService : IHostedService
{ {
private Dictionary<string, (string, List<string>)> _employees = []; // ФИО (ИД, Список должностей) private Dictionary<string, (string, List<string>)> _employees = []; // ФИО (ИД, Список должностей)
+20 -19
View File
@@ -233,21 +233,22 @@ public class ModeusService(
} }
} }
var position = (e.GroupName ?? string.Empty).Trim(); // Отключено так как информация нигде не используется
// var position = (e.GroupName ?? string.Empty).Trim();
static string FormatDateRange(string? dateIn, string? dateOut) //
{ // static string FormatDateRange(string? dateIn, string? dateOut)
var start = (dateIn ?? string.Empty).Trim(); // {
if (string.IsNullOrEmpty(start)) start = "?"; // var start = (dateIn ?? string.Empty).Trim();
// if (string.IsNullOrEmpty(start)) start = "?";
var end = (dateOut ?? string.Empty).Trim(); //
if (string.IsNullOrEmpty(end)) end = "по наст.вр."; // var end = (dateOut ?? string.Empty).Trim();
// if (string.IsNullOrEmpty(end)) end = "по наст.вр.";
return $"{start}{end}"; //
} // return $"{start}{end}";
// }
var dateRange = FormatDateRange(e.DateIn, e.DateOut); //
var positionWithDates = string.IsNullOrEmpty(position) ? $"({dateRange})" : $"{position} ({dateRange})"; // var dateRange = FormatDateRange(e.DateIn, e.DateOut);
// var positionWithDates = string.IsNullOrEmpty(position) ? $"({dateRange})" : $"{position} ({dateRange})"; // Место работы с датой
if (!grouped.TryGetValue(fullName, out var entry)) if (!grouped.TryGetValue(fullName, out var entry))
{ {
@@ -261,10 +262,10 @@ public class ModeusService(
} }
} }
if (!entry.Positions.Contains(positionWithDates)) // if (!entry.Positions.Contains(positionWithDates))
{ // {
entry.Positions.Add(positionWithDates); // entry.Positions.Add(positionWithDates);
} // }
grouped[fullName] = entry; grouped[fullName] = entry;
} }
-1
View File
@@ -17,7 +17,6 @@
<PackageReference Include="Sentry.AspNetCore" Version="6.1.0"/> <PackageReference Include="Sentry.AspNetCore" Version="6.1.0"/>
<PackageReference Include="Sentry.Profiling" Version="6.1.0"/> <PackageReference Include="Sentry.Profiling" Version="6.1.0"/>
<PackageReference Include="Swashbuckle.AspNetCore" Version="9.0.6"/> <PackageReference Include="Swashbuckle.AspNetCore" Version="9.0.6"/>
<PackageReference Include="X.Extensions.Logging.Telegram" Version="2.0.2"/>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
-2
View File
@@ -11,8 +11,6 @@ services:
- AzureAd:ClientSecret= - AzureAd:ClientSecret=
- AzureAd:Domain=sfedu.onmicrosoft.com - AzureAd:Domain=sfedu.onmicrosoft.com
- AzureAd:CallbackPath=/signin-oidc - AzureAd:CallbackPath=/signin-oidc
- TG_CHAT_ID=${TG_CHAT_ID}
- TG_TOKEN=${TG_TOKEN}
- API_KEY=${API_KEY} - API_KEY=${API_KEY}
# - TOKEN=${TOKEN} # - TOKEN=${TOKEN}
- AUTH_URL=${AUTH_URL} - AUTH_URL=${AUTH_URL}
-2
View File
@@ -11,8 +11,6 @@ services:
- AzureAd:ClientSecret= - AzureAd:ClientSecret=
- AzureAd:Domain=sfedu.onmicrosoft.com - AzureAd:Domain=sfedu.onmicrosoft.com
- AzureAd:CallbackPath=/signin-oidc - AzureAd:CallbackPath=/signin-oidc
- TG_CHAT_ID=${TG_CHAT_ID}
- TG_TOKEN=${TG_TOKEN}
- API_KEY=${API_KEY} - API_KEY=${API_KEY}
# - TOKEN=${TOKEN} # - TOKEN=${TOKEN}
- AUTH_URL=${AUTH_URL} - AUTH_URL=${AUTH_URL}