mirror of
https://github.com/projectsend/projectsend.git
synced 2026-10-08 14:21:15 +00:00
9c43f9cb9a
LDAP sign-in only took an email address. The LDAP settings now have an optional username attribute (cn, uid, sAMAccountName and so on). Once it is set, the login field also takes a username. The service account looks the username up, and the login carries on with the address the directory holds for it, through the same checks, single user bind, provisioning and rate limiting as an email login. Whether the input is an address is decided by the same email rule that accepted every stored address, so an address such as someone@localhost is never taken for a username. The username goes through the query builder, so it is escaped, and it has to match exactly one entry. The directory is client-only, so a username never signs in a staff account. With the attribute left empty, nothing changes. This ports feat/ldap_signin_by_username, which was written against v1 and has no history in common with this codebase.
96 lines
2.8 KiB
PHP
96 lines
2.8 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace App\Modules\Identity\Ldap;
|
|
|
|
use Illuminate\Database\Eloquent\Model;
|
|
|
|
/**
|
|
* The single row describing this installation's directory.
|
|
*
|
|
* Shaped after MailProviderSettings, including the part that matters most:
|
|
* `bind_password` carries an `'encrypted'` cast, so a database dump does
|
|
* not hand over a service-account credential. v1 stored this one in plain
|
|
* text and then echoed it into the settings form's HTML `value=`.
|
|
*
|
|
* @property bool $active
|
|
* @property string|null $host
|
|
* @property int $port
|
|
* @property LdapEncryption $encryption
|
|
* @property string|null $ca_cert_path
|
|
* @property string|null $bind_dn
|
|
* @property string|null $bind_password
|
|
* @property string|null $base_dn
|
|
* @property string|null $user_filter
|
|
* @property string $email_attribute
|
|
* @property string $name_attribute
|
|
* @property string|null $username_attribute
|
|
* @property bool $auto_provision
|
|
* @property bool $auto_approve
|
|
*/
|
|
class LdapSettings extends Model
|
|
{
|
|
protected $table = 'ldap_settings';
|
|
|
|
protected $guarded = [];
|
|
|
|
/**
|
|
* Column defaults only apply on INSERT, so they never reach the unsaved
|
|
* instance `current()` hands back on a fresh install — these do.
|
|
*/
|
|
protected $attributes = [
|
|
'active' => false,
|
|
'port' => 389,
|
|
'encryption' => 'tls',
|
|
'email_attribute' => 'mail',
|
|
'name_attribute' => 'cn',
|
|
'auto_provision' => false,
|
|
'auto_approve' => false,
|
|
];
|
|
|
|
protected function casts(): array
|
|
{
|
|
return [
|
|
'active' => 'boolean',
|
|
'port' => 'integer',
|
|
'encryption' => LdapEncryption::class,
|
|
'bind_password' => 'encrypted',
|
|
'auto_provision' => 'boolean',
|
|
'auto_approve' => 'boolean',
|
|
];
|
|
}
|
|
|
|
public static function current(): self
|
|
{
|
|
return static::query()->firstOrNew([]);
|
|
}
|
|
|
|
/**
|
|
* Whether a login may consult the directory at all.
|
|
*
|
|
* The extension check is part of the answer rather than a separate
|
|
* question: an administrator can save settings on a server that cannot
|
|
* talk LDAP, and every login must then behave exactly as if the
|
|
* feature were switched off rather than throwing.
|
|
*/
|
|
public function usable(): bool
|
|
{
|
|
return $this->active
|
|
&& extension_loaded('ldap')
|
|
&& is_string($this->host) && $this->host !== ''
|
|
&& is_string($this->base_dn) && $this->base_dn !== '';
|
|
}
|
|
|
|
/**
|
|
* Whether people may sign in with a directory username as well as an
|
|
* address: only once an administrator has named the attribute that
|
|
* holds it.
|
|
*/
|
|
public function allowsUsernameSignIn(): bool
|
|
{
|
|
return $this->usable()
|
|
&& is_string($this->username_attribute) && $this->username_attribute !== '';
|
|
}
|
|
}
|