[Web][Dovecot][SOGo][DockerApi] Add mailbox groups, shared mailboxes and identity provider sync

This commit is contained in:
FreddleSpl0it committed 2026-10-27 10:01:33 +01:00
1 parent 8bc8fbdd2c
commit 2c5718c9c9
82 files changed
+6488 -1027

No files matched your search

@@ -0,0 +1,36 @@
<?php
declare(strict_types=1);
namespace Mailcow\Auth;
use Mailcow\Auth\Service\IdpLoginService;
use Mailcow\Core\Context;
use Mailcow\Identity\IdentityModule;
use Mailcow\MailboxGroup\MailboxGroupModule;
use PDO;
/**
* Logins. For now the IdP login steps of the legacy flows (keycloak_mbox_login_rest(), ldap_mbox_login(),
* identity_provider('verify-sso')); the auth logic of the function files moves here step by step.
*/
class AuthModule
{
public function __construct(public readonly IdpLoginService $idp)
{
}
/** @param array $iamSettings identity provider settings as identity_provider('get') returns them */
public static function create(PDO $pdo, Context $context, array $iamSettings): self
{
$identity = IdentityModule::create($pdo, $context, $iamSettings);
return new self(new IdpLoginService($identity->settings, $identity->links, MailboxGroupModule::create($pdo, $context)->templates));
}
/** Logins run before a session exists, so the default context is the system */
public static function fromGlobals(?Context $context = null): self
{
$settings = $GLOBALS['iam_settings'] ?? null;
return self::create($GLOBALS['pdo'], $context ?? Context::system(), is_array($settings) ? $settings : identity_provider('get'));
}
}
@@ -0,0 +1,70 @@
<?php
declare(strict_types=1);
namespace Mailcow\Auth\Service;
use Mailcow\Identity\Model\Settings;
use Mailcow\Identity\Service\LinkService;
use Mailcow\MailboxGroup\Service\TemplateService;
use Throwable;
/**
* Steps of an IdP login (Keycloak REST, LDAP bind, OIDC) the legacy login flows call. The link checks fail
* closed: an error denies the login.
*/
class IdpLoginService
{
public function __construct(private Settings $settings, private LinkService $links, private TemplateService $templates)
{
}
/** Template of the first attribute mapping matching one of the IdP attribute values, null if none */
public function mappedTemplate(mixed $values): ?string
{
return $this->settings->mappedTemplate((array)$values);
}
/** Template for the login of an existing mailbox: its effective group template, else the mapped one */
public function templateFor(string $username, ?string $mapped): ?string
{
try {
return $this->templates->templateForLogin($username, $mapped);
} catch (Throwable $e) {
error_log('mailcow: group template lookup failed for ' . $username . ': ' . $e->getMessage());
return $mapped;
}
}
/** The IdP user may open the mailbox, an unlinked mailbox gets linked */
public function verifyLink(string $provider, string $username, string $externalId): bool
{
try {
return $this->links->verify($provider, $username, $externalId);
} catch (Throwable $e) {
error_log('mailcow: IdP link check failed for ' . $username . ': ' . $e->getMessage());
return false;
}
}
/** Before a mailbox is created on login: the IdP user must not own another mailbox */
public function mayCreate(string $provider, string $username, string $externalId): bool
{
try {
return $this->links->mayCreate($provider, $username, $externalId);
} catch (Throwable $e) {
error_log('mailcow: IdP link check failed for ' . $username . ': ' . $e->getMessage());
return false;
}
}
/** Links a mailbox created on login */
public function storeLink(string $provider, string $username, string $externalId): void
{
try {
$this->links->link($provider, $username, $externalId);
} catch (Throwable $e) {
error_log('mailcow: IdP link could not be stored for ' . $username . ': ' . $e->getMessage());
}
}
}