OneBot: Leantime 改造版源码(BOM/Univer 表格/AI 接管/品牌替换等)

This commit is contained in:
wangruiguo
2026-09-03 18:49:20 +08:00
commit d647428529
3501 changed files with 1988906 additions and 0 deletions

View File

@@ -0,0 +1,122 @@
<?php
namespace Leantime\Domain\Status\Controllers;
use Leantime\Core\Configuration\AppSettings;
use Leantime\Core\Configuration\Environment;
use Leantime\Core\Controller\Controller;
use Leantime\Core\Http\IncomingRequest;
use Leantime\Domain\Plugins\Services\Plugins;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Response;
/**
* Public, unauthenticated instance status / discovery endpoint — GET /status.
*
* The mobile app calls this at connect time to discover which login methods the
* instance offers (password / ldap / oidc), so it can show the right affordances
* — notably the OIDC "Sign in with SSO" redirect, which stays dormant in the app
* until a backend advertises it here. See the mobile client's
* connectionService::fetchPublicStatus and
* docs/backend-mobile-auth-bridge-plan.md for the contract.
*
* SECURITY — this endpoint is UNAUTHENTICATED, so it returns ONLY the safe,
* minimal tier: auth methods, the core version + instance name, provider labels,
* and the min app version. It deliberately does NOT list installed plugins,
* plugin versions, or the db version — an unauthenticated inventory of those is a
* recon gift (CVE matching). Those stay behind auth (the authenticated
* mobileStatus). Keep any `publicStatus` filter additions to this safe tier.
*
* Route 'status.index' is allow-listed public in AuthCheck.
*/
class Index extends Controller
{
/**
* Keys that must NEVER appear in the unauthenticated response, even if a
* publicStatus filter (or a future edit) adds them — a recon-risk inventory.
* Stripped after the filter runs, as defense in depth.
*/
private const SENSITIVE_KEYS = ['plugins', 'pluginVersions', 'installedPlugins', 'dbVersion', 'db_version'];
private Environment $config;
private AppSettings $appSettings;
private IncomingRequest $request;
private Plugins $plugins;
/**
* init - inject config, app settings, the incoming request, and the plugin
* service (used to gate mobile-auth advertising on AdvancedAuth).
*/
public function init(Environment $config, AppSettings $appSettings, IncomingRequest $request, Plugins $plugins): void
{
$this->config = $config;
$this->appSettings = $appSettings;
$this->request = $request;
$this->plugins = $plugins;
}
/**
* Return the public discovery payload: enabled auth methods, the OIDC login
* URL (when enabled), instance name, core version, and min app version — the
* safe unauthenticated tier only. Never plugin inventory / versions / db
* version (see the class-level security note).
*/
public function get(array $params): Response
{
$oidcEnabled = (bool) $this->config->oidcEnable;
$ldapEnabled = $this->config->useLdap === true && extension_loaded('ldap');
// Mobile auth is an AdvancedAuth capability — the mobile connection points
// (getToken, and the OIDC mint bridge) require the plugin. Only advertise
// mobile OIDC when AdvancedAuth is installed, so a core-only instance never
// offers a login the mint endpoint (Oidc\Controllers\Mobile) would refuse.
// NOTE: Cloud is assumed to ship AdvancedAuth, so this predicate covers it;
// confirm before release.
$mobileGate = $this->plugins->isEnabled('AdvancedAuth');
// password is always available; ldap/oidc only when configured.
$authMethods = ['password'];
if ($ldapEnabled) {
$authMethods[] = 'ldap';
}
if ($oidcEnabled && $mobileGate) {
$authMethods[] = 'oidc';
}
$payload = [
'mobileAuthEnabled' => $mobileGate,
'instanceName' => (string) ($this->config->sitename ?: 'Leantime'),
'version' => $this->appSettings->appVersion,
'minAppVersion' => null,
'authMethods' => $authMethods,
'ssoProviders' => [],
];
if ($oidcEnabled && $mobileGate) {
// Generic-OIDC login initiation URL — advertised for mobile only when
// AdvancedAuth is installed. The app opens this in the system auth
// browser; the mobile branch is triggered by its own query params
// (see Oidc\Controllers\Login).
$payload['oidcLoginUrl'] = $this->request->getSchemeAndHttpHost().'/oidc/login';
}
// AdvancedAuth (or other plugins) can append named SSO providers to the
// PUBLIC-safe payload (labels + login URLs only) via this filter, without
// core knowing about them. Filter handlers MUST preserve the public-safe
// contract — never add secrets, plugin inventory, or versions here.
$payload = self::dispatchFilter('publicStatus', $payload, ['request' => $this->request]);
// Defense in depth: this endpoint is unauthenticated, so strip any
// known-sensitive keys a misbehaving filter (or a future edit) might have
// added. The recon-risk inventory must NEVER reach an unauthenticated
// caller, even if a plugin gets the contract wrong.
foreach (self::SENSITIVE_KEYS as $sensitive) {
unset($payload[$sensitive]);
}
return new JsonResponse($payload);
}
}