Update configuration and access control for Telegram miniapp
- Added ALLOWED_USERNAMES and ADMIN_USERNAMES to .env.example for user access control. - Implemented validation of Telegram Web App initData in a new telegram_auth.py module. - Enhanced API to check user access before fetching duties. - Updated README with instructions for configuring miniapp access. - Modified .dockerignore and .gitignore to include data directory and database files.
This commit is contained in:
@@ -10,6 +10,9 @@
|
||||
const dutyListEl = document.getElementById("dutyList");
|
||||
const loadingEl = document.getElementById("loading");
|
||||
const errorEl = document.getElementById("error");
|
||||
const accessDeniedEl = document.getElementById("accessDenied");
|
||||
const headerEl = document.querySelector(".header");
|
||||
const weekdaysEl = document.querySelector(".weekdays");
|
||||
|
||||
function isoDate(d) {
|
||||
return d.toISOString().slice(0, 10);
|
||||
@@ -29,10 +32,38 @@
|
||||
return new Date(d.getFullYear(), d.getMonth(), diff);
|
||||
}
|
||||
|
||||
function getInitData() {
|
||||
return (window.Telegram && window.Telegram.WebApp && window.Telegram.WebApp.initData) || "";
|
||||
}
|
||||
|
||||
function showAccessDenied() {
|
||||
if (headerEl) headerEl.hidden = true;
|
||||
if (weekdaysEl) weekdaysEl.hidden = true;
|
||||
calendarEl.hidden = true;
|
||||
dutyListEl.hidden = true;
|
||||
loadingEl.classList.add("hidden");
|
||||
errorEl.hidden = true;
|
||||
accessDeniedEl.hidden = false;
|
||||
}
|
||||
|
||||
function hideAccessDenied() {
|
||||
accessDeniedEl.hidden = true;
|
||||
if (headerEl) headerEl.hidden = false;
|
||||
if (weekdaysEl) weekdaysEl.hidden = false;
|
||||
calendarEl.hidden = false;
|
||||
dutyListEl.hidden = false;
|
||||
}
|
||||
|
||||
async function fetchDuties(from, to) {
|
||||
const base = window.location.origin;
|
||||
const url = base + "/api/duties?from=" + encodeURIComponent(from) + "&to=" + encodeURIComponent(to);
|
||||
const res = await fetch(url);
|
||||
const initData = getInitData();
|
||||
const headers = {};
|
||||
if (initData) headers["X-Telegram-Init-Data"] = initData;
|
||||
const res = await fetch(url, { headers: headers });
|
||||
if (res.status === 403) {
|
||||
throw new Error("ACCESS_DENIED");
|
||||
}
|
||||
if (!res.ok) throw new Error("Ошибка загрузки");
|
||||
return res.json();
|
||||
}
|
||||
@@ -116,6 +147,11 @@
|
||||
}
|
||||
|
||||
async function loadMonth() {
|
||||
if (!getInitData()) {
|
||||
showAccessDenied();
|
||||
return;
|
||||
}
|
||||
hideAccessDenied();
|
||||
loadingEl.classList.remove("hidden");
|
||||
errorEl.hidden = true;
|
||||
const from = isoDate(firstDayOfMonth(current));
|
||||
@@ -126,6 +162,10 @@
|
||||
renderCalendar(current.getFullYear(), current.getMonth(), byDate);
|
||||
renderDutyList(duties);
|
||||
} catch (e) {
|
||||
if (e.message === "ACCESS_DENIED") {
|
||||
showAccessDenied();
|
||||
return;
|
||||
}
|
||||
showError(e.message || "Не удалось загрузить данные.");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -20,7 +20,12 @@
|
||||
<div class="duty-list" id="dutyList"></div>
|
||||
<div class="loading" id="loading">Загрузка…</div>
|
||||
<div class="error" id="error" hidden></div>
|
||||
<div class="access-denied" id="accessDenied" hidden>
|
||||
<p>Доступ запрещён.</p>
|
||||
<p class="muted">Откройте календарь из Telegram.</p>
|
||||
</div>
|
||||
</div>
|
||||
<script src="https://telegram.org/js/telegram-web-app.js"></script>
|
||||
<script src="app.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -150,3 +150,22 @@ body {
|
||||
.error[hidden], .loading.hidden {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
.access-denied {
|
||||
text-align: center;
|
||||
padding: 24px 12px;
|
||||
color: var(--muted);
|
||||
}
|
||||
|
||||
.access-denied p {
|
||||
margin: 0 0 8px 0;
|
||||
}
|
||||
|
||||
.access-denied p:first-child {
|
||||
color: #f7768e;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.access-denied[hidden] {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user