471cfdd161
- 1 - Add: Gitea now creates timestamped database backup bundles under `[backup].PATH`, exposes the backup schedule in the installer, and surfaces the `database_backup` cron task in admin monitoring. - 2 - Add: installed instances now use `.gitea-installed` and `.gitea-recovery.ini` to enter email-gated recovery instead of falling back to public install mode when configuration or database access is broken. - 3 - Mod: the installer recovery flow now covers backup-bundle restore, bundled or manual `app.ini` reuse, uploaded SQL/GZ database restores, and repository-filesystem recovery with source-specific validation, confirmations, and preserved launcher state. - 4 - Fix: recovery now restores bundled `app.ini` snapshots when needed, discovers backup bundles from both the active backup path and persisted `.gitea-recovery.ini` path, and preserves SMTP and other rebuilt settings correctly when `app.ini` is missing or incomplete. - 5 - Fix: recovery validation and restore handling now accept either a selected backup bundle or an uploaded SQL/GZ dump, keep sensitive secrets and existing `LFS_JWT_SECRET` when appropriate, clear SQLite restore targets before import, and complete the post-install handoff without redirect loops. - 6 - Mod: fresh installs now default recovery email authorization to enabled with first-admin fallback, and the install/recovery UI, styling, and EN/RO wording were refined to match the final launcher behavior. Co-Authored-By: petru @ codex (GPT-5) <codex@openai.com> (cherry picked from commit 9879caf2292691b0cb521d12e6fee924b066bae2)
50 lines
2.3 KiB
Handlebars
50 lines
2.3 KiB
Handlebars
{{template "base/head" .}}
|
|
<div role="main" aria-label="{{.Title}}" class="page-content install post-install tw-h-full">
|
|
<div class="home tw-text-center tw-h-full tw-flex tw-flex-col tw-justify-center"><!-- the "home" class makes the links green -->
|
|
<div{{if eq .InstallProgressLogo "loading.png"}} class="tw-ml-[-30px]"{{end}}><img width="160" src="{{AssetUrlPrefix}}/img/{{.InstallProgressLogo}}" alt aria-hidden="true"></div>
|
|
<div class="tw-my-[2em] tw-text-[18px]">
|
|
<a
|
|
id="goto-after-install"
|
|
href="{{AppSubUrl}}{{if .InstallIsRecoveryRequest}}/{{else}}{{Iif .IsAccountCreated "/user/login" "/user/sign_up"}}{{end}}"
|
|
data-probe-url="{{if .InstallIsRecoveryRequest}}{{AppSubUrl}}/post-install{{else}}{{AppSubUrl}}{{Iif .IsAccountCreated "/user/login" "/user/sign_up"}}{{end}}"
|
|
data-probe-until-missing="{{if .InstallIsRecoveryRequest}}true{{else}}false{{end}}"
|
|
>{{ctx.Locale.Tr "install.installing_desc"}}</a>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<script>
|
|
// edit/add - by petru @ codex
|
|
if (window.location.search.includes('recovery=1')) {
|
|
window.history.replaceState(null, '', '{{AppSubUrl}}/');
|
|
}
|
|
{{if .InstallIsRecoveryRequest}}
|
|
window.__giteaRecoveryPostInstallHandled = true;
|
|
{
|
|
const gotoLink = document.getElementById('goto-after-install');
|
|
if (gotoLink instanceof HTMLAnchorElement) {
|
|
const targetUrl = gotoLink.getAttribute('href');
|
|
const probeUrl = gotoLink.dataset.probeUrl;
|
|
if (targetUrl && probeUrl) {
|
|
let recoveryPostInstallPoll = window.setInterval(async () => {
|
|
try {
|
|
const resp = await fetch(probeUrl, {cache: 'no-store', credentials: 'same-origin'});
|
|
if (resp.status === 404 || resp.redirected || !resp.url.endsWith('/post-install')) {
|
|
window.clearInterval(recoveryPostInstallPoll);
|
|
recoveryPostInstallPoll = 0;
|
|
const currentUrl = new URL(window.location.href); // edit/add - by petru @ codex
|
|
const nextUrl = new URL(targetUrl, window.location.href); // edit/add - by petru @ codex
|
|
if (currentUrl.pathname === nextUrl.pathname && currentUrl.search === nextUrl.search && currentUrl.hash === nextUrl.hash) {
|
|
window.location.reload(); // edit/add - by petru @ codex
|
|
} else {
|
|
window.location.replace(targetUrl);
|
|
}
|
|
}
|
|
} catch {}
|
|
}, 1000);
|
|
}
|
|
}
|
|
}
|
|
{{end}}
|
|
</script>
|
|
{{template "base/footer" .}}
|