Page MenuHomePhorge

D1069.1774814351.diff
No OneTemporary

Authored By
Unknown
Size
29 KB
Referenced Files
None
Subscribers
None

D1069.1774814351.diff

diff --git a/docker/kolab/kolab-init.sh b/docker/kolab/kolab-init.sh
--- a/docker/kolab/kolab-init.sh
+++ b/docker/kolab/kolab-init.sh
@@ -26,5 +26,6 @@
./18-adjust-kolab-conf.sh
./19-turn-on-vlv-in-roundcube.sh
./20-add-alias-attribute-index.sh
+./21-adjust-postfix-config.sh
touch /tmp/kolab-init.done
diff --git a/docker/kolab/utils/15-create-hosted-domain.sh b/docker/kolab/utils/15-create-hosted-domain.sh
--- a/docker/kolab/utils/15-create-hosted-domain.sh
+++ b/docker/kolab/utils/15-create-hosted-domain.sh
@@ -53,6 +53,18 @@
) | ldapadd -x -h ${ldap_host} -D "${ldap_binddn}" -w "${ldap_bindpw}"
(
+ for role in "2fa-user" "activesync-user" "imap-user"; do
+ echo "cn=${role},${hosted_domain_rootdn}"
+ echo "cn: ${role}"
+ echo "description: ${role} role"
+ echo "objectclass: top"
+ echo "objectclass: ldapsubentry"
+ echo "objectclass: nsmanagedroledefinition"
+ echo "objectclass: nsroledefinition"
+ echo "objectclass: nssimpleroledefinition"
+ echo ""
+ done
+
echo "dn: ou=Groups,${hosted_domain_rootdn}"
echo "ou: Groups"
echo "objectClass: top"
diff --git a/docker/kolab/utils/21-adjust-postfix-config.sh b/docker/kolab/utils/21-adjust-postfix-config.sh
new file mode 100755
--- /dev/null
+++ b/docker/kolab/utils/21-adjust-postfix-config.sh
@@ -0,0 +1,26 @@
+#!/bin/bash
+
+# new: (inetdomainstatus:1.2.840.113556.1.4.803:=1)
+# active: (inetdomainstatus:1.2.840.113556.1.4.803:=2)
+# suspended: (inetdomainstatus:1.2.840.113556.1.4.803:=4)
+# deleted: (inetdomainstatus:1.2.840.113556.1.4.803:=8)
+# confirmed: (inetdomainstatus:1.2.840.113556.1.4.803:=16)
+# verified: (inetdomainstatus:1.2.840.113556.1.4.803:=32)
+# ready: (inetdomainstatus:1.2.840.113556.1.4.803:=64)
+
+sed -i -r \
+ -e 's/^query_filter.*$/query_filter = (\&(associatedDomain=%s)(inetdomainstatus:1.2.840.113556.1.4.803:=18)(!(inetdomainstatus:1.2.840.113556.1.4.803:=4)))/g' \
+ /etc/postfix/ldap/mydestination.cf
+
+# new: (inetuserstatus:1.2.840.113556.1.4.803:=1)
+# active: (inetuserstatus:1.2.840.113556.1.4.803:=2)
+# suspended: (inetuserstatus:1.2.840.113556.1.4.803:=4)
+# deleted: (inetuserstatus:1.2.840.113556.1.4.803:=8)
+# ldapready: (inetuserstatus:1.2.840.113556.1.4.803:=16)
+# imapready: (inetuserstatus:1.2.840.113556.1.4.803:=32)
+
+sed -i -r \
+ -e 's/^query_filter.*$/query_filter = (\&(|(mail=%s)(alias=%s))(|(objectclass=kolabinetorgperson)(|(objectclass=kolabgroupofuniquenames)(objectclass=kolabgroupofurls))(|(|(objectclass=groupofuniquenames)(objectclass=groupofurls))(objectclass=kolabsharedfolder))(objectclass=kolabsharedfolder))(inetuserstatus:1.2.840.113556.1.4.803:=50)(!(inetuserstatus:1.2.840.113556.1.4.803:=4)))/g' \
+ /etc/postfix/ldap/local_recipient_maps.cf
+
+systemctl restart postfix
diff --git a/src/app/Backends/LDAP.php b/src/app/Backends/LDAP.php
--- a/src/app/Backends/LDAP.php
+++ b/src/app/Backends/LDAP.php
@@ -19,33 +19,33 @@
$config = self::getConfig('admin');
$ldap = self::initLDAP($config);
- $hosted_root_dn = \config('ldap.hosted.root_dn');
- $mgmt_root_dn = \config('ldap.admin.root_dn');
+ $hostedRootDN = \config('ldap.hosted.root_dn');
+ $mgmtRootDN = \config('ldap.admin.root_dn');
- $domain_base_dn = "ou={$domain->namespace},{$hosted_root_dn}";
+ $domainBaseDN = "ou={$domain->namespace},{$hostedRootDN}";
$aci = [
'(targetattr = "*")'
. '(version 3.0; acl "Deny Unauthorized"; deny (all)'
- . '(userdn != "ldap:///uid=kolab-service,ou=Special Users,' . $mgmt_root_dn
- . ' || ldap:///ou=People,' . $domain_base_dn . '??sub?(objectclass=inetorgperson)") '
- . 'AND NOT roledn = "ldap:///cn=kolab-admin,' . $mgmt_root_dn . '";)',
+ . '(userdn != "ldap:///uid=kolab-service,ou=Special Users,' . $mgmtRootDN
+ . ' || ldap:///ou=People,' . $domainBaseDN . '??sub?(objectclass=inetorgperson)") '
+ . 'AND NOT roledn = "ldap:///cn=kolab-admin,' . $mgmtRootDN . '";)',
'(targetattr != "userPassword")'
. '(version 3.0;acl "Search Access";allow (read,compare,search)'
- . '(userdn = "ldap:///uid=kolab-service,ou=Special Users,' . $mgmt_root_dn
- . ' || ldap:///ou=People,' . $domain_base_dn . '??sub?(objectclass=inetorgperson)");)',
+ . '(userdn = "ldap:///uid=kolab-service,ou=Special Users,' . $mgmtRootDN
+ . ' || ldap:///ou=People,' . $domainBaseDN . '??sub?(objectclass=inetorgperson)");)',
'(targetattr = "*")'
. '(version 3.0;acl "Kolab Administrators";allow (all)'
- . '(roledn = "ldap:///cn=kolab-admin,' . $domain_base_dn
- . ' || ldap:///cn=kolab-admin,' . $mgmt_root_dn . '");)'
+ . '(roledn = "ldap:///cn=kolab-admin,' . $domainBaseDN
+ . ' || ldap:///cn=kolab-admin,' . $mgmtRootDN . '");)'
];
$entry = [
'aci' => $aci,
'associateddomain' => $domain->namespace,
- 'inetdomainbasedn' => $domain_base_dn,
+ 'inetdomainbasedn' => $domainBaseDN,
'objectclass' => [
'top',
'domainrelatedobject',
@@ -72,42 +72,42 @@
$entry['aci'] = array(
'(targetattr = "*")'
. '(version 3.0;acl "Deny Unauthorized"; deny (all)'
- . '(userdn != "ldap:///uid=kolab-service,ou=Special Users,' . $mgmt_root_dn
- . ' || ldap:///ou=People,' . $domain_base_dn . '??sub?(objectclass=inetorgperson)") '
- . 'AND NOT roledn = "ldap:///cn=kolab-admin,' . $mgmt_root_dn . '";)',
+ . '(userdn != "ldap:///uid=kolab-service,ou=Special Users,' . $mgmtRootDN
+ . ' || ldap:///ou=People,' . $domainBaseDN . '??sub?(objectclass=inetorgperson)") '
+ . 'AND NOT roledn = "ldap:///cn=kolab-admin,' . $mgmtRootDN . '";)',
'(targetattr != "userPassword")'
. '(version 3.0;acl "Search Access";allow (read,compare,search,write)'
- . '(userdn = "ldap:///uid=kolab-service,ou=Special Users,' . $mgmt_root_dn
- . ' || ldap:///ou=People,' . $domain_base_dn . '??sub?(objectclass=inetorgperson)");)',
+ . '(userdn = "ldap:///uid=kolab-service,ou=Special Users,' . $mgmtRootDN
+ . ' || ldap:///ou=People,' . $domainBaseDN . '??sub?(objectclass=inetorgperson)");)',
'(targetattr = "*")'
. '(version 3.0;acl "Kolab Administrators";allow (all)'
- . '(roledn = "ldap:///cn=kolab-admin,' . $domain_base_dn
- . ' || ldap:///cn=kolab-admin,' . $mgmt_root_dn . '");)',
+ . '(roledn = "ldap:///cn=kolab-admin,' . $domainBaseDN
+ . ' || ldap:///cn=kolab-admin,' . $mgmtRootDN . '");)',
- '(target = "ldap:///ou=*,' . $domain_base_dn . '")'
+ '(target = "ldap:///ou=*,' . $domainBaseDN . '")'
. '(targetattr="objectclass || aci || ou")'
. '(version 3.0;acl "Allow Domain sub-OU Registration"; allow (add)'
- . '(userdn = "ldap:///uid=kolab-service,ou=Special Users,' . $mgmt_root_dn . '");)',
+ . '(userdn = "ldap:///uid=kolab-service,ou=Special Users,' . $mgmtRootDN . '");)',
- '(target = "ldap:///uid=*,ou=People,' . $domain_base_dn . '")(targetattr="*")'
+ '(target = "ldap:///uid=*,ou=People,' . $domainBaseDN . '")(targetattr="*")'
. '(version 3.0;acl "Allow Domain First User Registration"; allow (add)'
- . '(userdn = "ldap:///uid=kolab-service,ou=Special Users,' . $mgmt_root_dn . '");)',
+ . '(userdn = "ldap:///uid=kolab-service,ou=Special Users,' . $mgmtRootDN . '");)',
- '(target = "ldap:///cn=*,' . $domain_base_dn . '")(targetattr="objectclass || cn")'
+ '(target = "ldap:///cn=*,' . $domainBaseDN . '")(targetattr="objectclass || cn")'
. '(version 3.0;acl "Allow Domain Role Registration"; allow (add)'
- . '(userdn = "ldap:///uid=kolab-service,ou=Special Users,' . $mgmt_root_dn . '");)',
+ . '(userdn = "ldap:///uid=kolab-service,ou=Special Users,' . $mgmtRootDN . '");)',
);
- if (!$ldap->get_entry($domain_base_dn)) {
- $ldap->add_entry($domain_base_dn, $entry);
+ if (!$ldap->get_entry($domainBaseDN)) {
+ $ldap->add_entry($domainBaseDN, $entry);
}
foreach (['Groups', 'People', 'Resources', 'Shared Folders'] as $item) {
- if (!$ldap->get_entry("ou={$item},{$domain_base_dn}")) {
+ if (!$ldap->get_entry("ou={$item},{$domainBaseDN}")) {
$ldap->add_entry(
- "ou={$item},{$domain_base_dn}",
+ "ou={$item},{$domainBaseDN}",
[
'ou' => $item,
'description' => $item,
@@ -120,10 +120,10 @@
}
}
- foreach (['kolab-admin', 'imap-user', 'activesync-user', 'billing-user'] as $item) {
- if (!$ldap->get_entry("cn={$item},{$domain_base_dn}")) {
+ foreach (['kolab-admin', 'billing-user'] as $item) {
+ if (!$ldap->get_entry("cn={$item},{$domainBaseDN}")) {
$ldap->add_entry(
- "cn={$item},{$domain_base_dn}",
+ "cn={$item},{$domainBaseDN}",
[
'cn' => $item,
'description' => "{$item} role",
@@ -181,12 +181,14 @@
'objectclass' => [
'top',
'inetorgperson',
+ 'inetuser',
'kolabinetorgperson',
'mailrecipient',
'person'
],
'mail' => $user->email,
'uid' => $user->email,
+ 'nsroledn' => []
];
self::setUserAttributes($user, $entry);
@@ -210,7 +212,19 @@
*/
public static function updateDomain($domain)
{
- //
+ $config = self::getConfig('admin');
+ $ldap = self::initLDAP($config);
+
+ $ldapDomain = $ldap->find_domain($domain->namespace);
+
+ $oldEntry = $ldap->get_entry($ldapDomain['dn']);
+ $newEntry = $oldEntry;
+
+ self::setDomainAttributes($domain, $newEntry);
+
+ $ldap->modify_entry($ldapDomain['dn'], $oldEntry, $newEntry);
+
+ $ldap->close();
}
public static function deleteDomain($domain)
@@ -218,13 +232,13 @@
$config = self::getConfig('admin');
$ldap = self::initLDAP($config);
- $hosted_root_dn = \config('ldap.hosted.root_dn');
- $mgmt_root_dn = \config('ldap.admin.root_dn');
+ $hostedRootDN = \config('ldap.hosted.root_dn');
+ $mgmtRootDN = \config('ldap.admin.root_dn');
- $domain_base_dn = "ou={$domain->namespace},{$hosted_root_dn}";
+ $domainBaseDN = "ou={$domain->namespace},{$hostedRootDN}";
- if ($ldap->get_entry($domain_base_dn)) {
- $ldap->delete_entry_recursive($domain_base_dn);
+ if ($ldap->get_entry($domainBaseDN)) {
+ $ldap->delete_entry_recursive($domainBaseDN);
}
if ($ldap_domain = $ldap->find_domain($domain->namespace)) {
@@ -232,6 +246,8 @@
$ldap->delete_entry($ldap_domain['dn']);
}
}
+
+ $ldap->close();
}
public static function deleteUser($user)
@@ -244,6 +260,7 @@
$domain = $ldap->find_domain($_domain);
if (!$domain) {
+ $ldap->close();
return false;
}
@@ -251,10 +268,13 @@
$dn = "uid={$user->email},ou=People,{$base_dn}";
if (!$ldap->get_entry($dn)) {
+ $ldap->close();
return false;
}
$ldap->delete_entry($dn);
+
+ $ldap->close();
}
/**
@@ -274,18 +294,29 @@
$domain = $ldap->find_domain($_domain);
if (!$domain) {
+ $ldap->close();
return false;
}
$base_dn = $ldap->domain_root_dn($_domain);
$dn = "uid={$user->email},ou=People,{$base_dn}";
- $old_entry = $ldap->get_entry($dn);
- $new_entry = $old_entry;
+ $oldEntry = $ldap->get_entry($dn);
- self::setUserAttributes($user, $new_entry);
+ if (!$oldEntry) {
+ $ldap->close();
+ return false;
+ }
+
+ if (!array_key_exists('nsroledn', $oldEntry)) {
+ $oldEntry['nsroledn'] = (array)$ldap->get_entry_attributes($dn, ['nsroledn']);
+ }
+
+ $newEntry = $oldEntry;
+
+ self::setUserAttributes($user, $newEntry);
- $ldap->modify_entry($dn, $old_entry, $new_entry);
+ $ldap->modify_entry($dn, $oldEntry, $newEntry);
$ldap->close();
}
@@ -307,6 +338,14 @@
}
/**
+ * Set domain attributes
+ */
+ private static function setDomainAttributes(Domain $domain, array &$entry)
+ {
+ $entry['inetdomainstatus'] = $domain->status;
+ }
+
+ /**
* Set common user attributes
*/
private static function setUserAttributes(User $user, array &$entry)
@@ -341,6 +380,61 @@
$entry['givenname'] = $firstName;
$entry['sn'] = $lastName;
$entry['userpassword'] = $user->password_ldap;
+
+ $entry['inetuserstatus'] = $user->status;
+
+ $entry['mailquota'] = 0;
+
+ if (!array_key_exists('nsroledn', $entry)) {
+ $entry['nsroledn'] = [];
+ } else if (!is_array($entry['nsroledn'])) {
+ $entry['nsroledn'] = (array)$entry['nsroledn'];
+ }
+
+ $roles = [];
+
+ foreach ($user->entitlements as $entitlement) {
+ \Log::debug("Examining {$entitlement->sku->title}");
+
+ switch ($entitlement->sku->title) {
+ case "storage":
+ $entry['mailquota'] += 1048576;
+ break;
+ }
+
+ $roles[] = $entitlement->sku->title;
+ }
+
+ $hostedRootDN = \config('ldap.hosted.root_dn');
+
+ if (in_array("2fa", $roles)) {
+ $entry['nsroledn'][] = "cn=2fa-user,{$hostedRootDN}";
+ } else {
+ $key = array_search("cn=2fa-user,{$hostedRootDN}", $entry['nsroledn']);
+ if ($key !== false) {
+ unset($entry['nsroledn'][$key]);
+ }
+ }
+
+ if (in_array("activesync", $roles)) {
+ $entry['nsroledn'][] = "cn=activesync-user,{$hostedRootDN}";
+ } else {
+ $key = array_search("cn=activesync-user,{$hostedRootDN}", $entry['nsroledn']);
+ if ($key !== false) {
+ unset($entry['nsroledn'][$key]);
+ }
+ }
+
+ if (!in_array("groupware", $roles)) {
+ $entry['nsroledn'][] = "cn=imap-user,{$hostedRootDN}";
+ } else {
+ $key = array_search("cn=imap-user,{$hostedRootDN}", $entry['nsroledn']);
+ if ($key !== false) {
+ unset($entry['nsroledn'][$key]);
+ }
+ }
+
+ $entry['nsroledn'] = array_unique($entry['nsroledn']);
}
/**
@@ -367,7 +461,11 @@
public static function logHook($level, $msg): void
{
if (
- ($level == LOG_INFO || $level == LOG_DEBUG || $level == LOG_NOTICE)
+ (
+ $level == LOG_INFO
+ || $level == LOG_DEBUG
+ || $level == LOG_NOTICE
+ )
&& !\config('app.debug')
) {
return;
diff --git a/src/app/Console/Commands/DomainList.php b/src/app/Console/Commands/DomainList.php
new file mode 100644
--- /dev/null
+++ b/src/app/Console/Commands/DomainList.php
@@ -0,0 +1,47 @@
+<?php
+
+namespace App\Console\Commands;
+
+use App\Domain;
+use Illuminate\Console\Command;
+
+class DomainList extends Command
+{
+ /**
+ * The name and signature of the console command.
+ *
+ * @var string
+ */
+ protected $signature = 'domain:list';
+
+ /**
+ * The console command description.
+ *
+ * @var string
+ */
+ protected $description = 'List domains';
+
+ /**
+ * Create a new command instance.
+ *
+ * @return void
+ */
+ public function __construct()
+ {
+ parent::__construct();
+ }
+
+ /**
+ * Execute the console command.
+ *
+ * @return mixed
+ */
+ public function handle()
+ {
+ $domains = Domain::withTrashed()->orderBy('namespace')->each(
+ function ($domain) {
+ $this->info($domain->namespace);
+ }
+ );
+ }
+}
diff --git a/src/app/Console/Commands/DomainStatus.php b/src/app/Console/Commands/DomainStatus.php
new file mode 100644
--- /dev/null
+++ b/src/app/Console/Commands/DomainStatus.php
@@ -0,0 +1,51 @@
+<?php
+
+namespace App\Console\Commands;
+
+use App\Domain;
+use Illuminate\Console\Command;
+
+class DomainStatus extends Command
+{
+ /**
+ * The name and signature of the console command.
+ *
+ * @var string
+ */
+ protected $signature = 'domain:status {domain}';
+
+ /**
+ * The console command description.
+ *
+ * @var string
+ */
+ protected $description = 'Display the status of a domain';
+
+ /**
+ * Create a new command instance.
+ *
+ * @return void
+ */
+ public function __construct()
+ {
+ parent::__construct();
+ }
+
+ /**
+ * Execute the console command.
+ *
+ * @return mixed
+ */
+ public function handle()
+ {
+ $domain = Domain::where('namespace', $this->argument('domain'))->first();
+
+ if (!$domain) {
+ return 1;
+ }
+
+ $this->info("Found domain: {$domain->id}");
+
+ $this->info($domain->status);
+ }
+}
diff --git a/src/app/Console/Commands/DomainSuspend.php b/src/app/Console/Commands/DomainSuspend.php
new file mode 100644
--- /dev/null
+++ b/src/app/Console/Commands/DomainSuspend.php
@@ -0,0 +1,51 @@
+<?php
+
+namespace App\Console\Commands;
+
+use App\Domain;
+use Illuminate\Console\Command;
+
+class DomainSuspend extends Command
+{
+ /**
+ * The name and signature of the console command.
+ *
+ * @var string
+ */
+ protected $signature = 'domain:suspend {domain}';
+
+ /**
+ * The console command description.
+ *
+ * @var string
+ */
+ protected $description = 'Suspend a domain';
+
+ /**
+ * Create a new command instance.
+ *
+ * @return void
+ */
+ public function __construct()
+ {
+ parent::__construct();
+ }
+
+ /**
+ * Execute the console command.
+ *
+ * @return mixed
+ */
+ public function handle()
+ {
+ $domain = Domain::where('namespace', $this->argument('domain'))->first();
+
+ if (!$domain) {
+ return 1;
+ }
+
+ $this->info("Found domain: {$domain->id}");
+
+ $domain->suspend();
+ }
+}
diff --git a/src/app/Console/Commands/DomainUnsuspend.php b/src/app/Console/Commands/DomainUnsuspend.php
new file mode 100644
--- /dev/null
+++ b/src/app/Console/Commands/DomainUnsuspend.php
@@ -0,0 +1,51 @@
+<?php
+
+namespace App\Console\Commands;
+
+use App\Domain;
+use Illuminate\Console\Command;
+
+class DomainUnsuspend extends Command
+{
+ /**
+ * The name and signature of the console command.
+ *
+ * @var string
+ */
+ protected $signature = 'domain:unsuspend {domain}';
+
+ /**
+ * The console command description.
+ *
+ * @var string
+ */
+ protected $description = 'Remove a domain suspension';
+
+ /**
+ * Create a new command instance.
+ *
+ * @return void
+ */
+ public function __construct()
+ {
+ parent::__construct();
+ }
+
+ /**
+ * Execute the console command.
+ *
+ * @return mixed
+ */
+ public function handle()
+ {
+ $domain = Domain::where('namespace', $this->argument('domain'))->first();
+
+ if (!$domain) {
+ return 1;
+ }
+
+ $this->info("Found domain {$domain->id}");
+
+ $domain->unsuspend();
+ }
+}
diff --git a/src/app/Console/Commands/UserStatus.php b/src/app/Console/Commands/UserStatus.php
new file mode 100644
--- /dev/null
+++ b/src/app/Console/Commands/UserStatus.php
@@ -0,0 +1,51 @@
+<?php
+
+namespace App\Console\Commands;
+
+use App\User;
+use Illuminate\Console\Command;
+
+class UserStatus extends Command
+{
+ /**
+ * The name and signature of the console command.
+ *
+ * @var string
+ */
+ protected $signature = 'user:status {user}';
+
+ /**
+ * The console command description.
+ *
+ * @var string
+ */
+ protected $description = 'Display the status of a user';
+
+ /**
+ * Create a new command instance.
+ *
+ * @return void
+ */
+ public function __construct()
+ {
+ parent::__construct();
+ }
+
+ /**
+ * Execute the console command.
+ *
+ * @return mixed
+ */
+ public function handle()
+ {
+ $user = User::where('email', $this->argument('user'))->first();
+
+ if (!$user) {
+ return 1;
+ }
+
+ $this->info("Found user: {$user->id}");
+
+ $this->info($user->status);
+ }
+}
diff --git a/src/app/Console/Commands/UserSuspend.php b/src/app/Console/Commands/UserSuspend.php
new file mode 100644
--- /dev/null
+++ b/src/app/Console/Commands/UserSuspend.php
@@ -0,0 +1,51 @@
+<?php
+
+namespace App\Console\Commands;
+
+use App\User;
+use Illuminate\Console\Command;
+
+class UserSuspend extends Command
+{
+ /**
+ * The name and signature of the console command.
+ *
+ * @var string
+ */
+ protected $signature = 'user:suspend {user}';
+
+ /**
+ * The console command description.
+ *
+ * @var string
+ */
+ protected $description = 'Suspend a user';
+
+ /**
+ * Create a new command instance.
+ *
+ * @return void
+ */
+ public function __construct()
+ {
+ parent::__construct();
+ }
+
+ /**
+ * Execute the console command.
+ *
+ * @return mixed
+ */
+ public function handle()
+ {
+ $user = User::where('email', $this->argument('user'))->first();
+
+ if (!$user) {
+ return 1;
+ }
+
+ $this->info("Found user: {$user->id}");
+
+ $user->suspend();
+ }
+}
diff --git a/src/app/Console/Commands/UserUnsuspend.php b/src/app/Console/Commands/UserUnsuspend.php
new file mode 100644
--- /dev/null
+++ b/src/app/Console/Commands/UserUnsuspend.php
@@ -0,0 +1,51 @@
+<?php
+
+namespace App\Console\Commands;
+
+use App\User;
+use Illuminate\Console\Command;
+
+class UserUnsuspend extends Command
+{
+ /**
+ * The name and signature of the console command.
+ *
+ * @var string
+ */
+ protected $signature = 'user:unsuspend {user}';
+
+ /**
+ * The console command description.
+ *
+ * @var string
+ */
+ protected $description = 'Remove a user suspension';
+
+ /**
+ * Create a new command instance.
+ *
+ * @return void
+ */
+ public function __construct()
+ {
+ parent::__construct();
+ }
+
+ /**
+ * Execute the console command.
+ *
+ * @return mixed
+ */
+ public function handle()
+ {
+ $user = User::where('email', $this->argument('user'))->first();
+
+ if (!$user) {
+ return 1;
+ }
+
+ $this->info("Found user {$user->id}");
+
+ $user->unsuspend();
+ }
+}
diff --git a/src/app/Console/Commands/UserVerify.php b/src/app/Console/Commands/UserVerify.php
new file mode 100644
--- /dev/null
+++ b/src/app/Console/Commands/UserVerify.php
@@ -0,0 +1,51 @@
+<?php
+
+namespace App\Console\Commands;
+
+use Illuminate\Console\Command;
+
+class UserVerify extends Command
+{
+ /**
+ * The name and signature of the console command.
+ *
+ * @var string
+ */
+ protected $signature = 'user:verify {user}';
+
+ /**
+ * The console command description.
+ *
+ * @var string
+ */
+ protected $description = 'Verify the state of a user account';
+
+ /**
+ * Create a new command instance.
+ *
+ * @return void
+ */
+ public function __construct()
+ {
+ parent::__construct();
+ }
+
+ /**
+ * Execute the console command.
+ *
+ * @return mixed
+ */
+ public function handle()
+ {
+ $user = \App\User::where('email', $this->argument('user'))->first();
+
+ if (!$user) {
+ return 1;
+ }
+
+ $this->info("Found user: {$user->id}");
+
+ $job = new \App\Jobs\UserVerify($user);
+ $job->handle();
+ }
+}
diff --git a/src/app/Domain.php b/src/app/Domain.php
--- a/src/app/Domain.php
+++ b/src/app/Domain.php
@@ -309,6 +309,36 @@
}
/**
+ * Suspend this domain.
+ *
+ * @return void
+ */
+ public function suspend(): void
+ {
+ if ($this->isSuspended()) {
+ return;
+ }
+
+ $this->status |= Domain::STATUS_SUSPENDED;
+ $this->save();
+ }
+
+ /**
+ * Unsuspend this domain.
+ *
+ * @return void
+ */
+ public function unsuspend(): void
+ {
+ if (!$this->isSuspended()) {
+ return;
+ }
+
+ $this->status ^= Domain::STATUS_SUSPENDED;
+ $this->save();
+ }
+
+ /**
* Verify if a domain exists in DNS
*
* @return bool True if registered, False otherwise
diff --git a/src/app/Jobs/DomainUpdate.php b/src/app/Jobs/DomainUpdate.php
new file mode 100644
--- /dev/null
+++ b/src/app/Jobs/DomainUpdate.php
@@ -0,0 +1,44 @@
+<?php
+
+namespace App\Jobs;
+
+use App\Backends\LDAP;
+use Illuminate\Bus\Queueable;
+use Illuminate\Contracts\Queue\ShouldQueue;
+use Illuminate\Foundation\Bus\Dispatchable;
+use Illuminate\Queue\InteractsWithQueue;
+use Illuminate\Queue\SerializesModels;
+
+class DomainUpdate implements ShouldQueue
+{
+ use Dispatchable;
+ use InteractsWithQueue;
+ use Queueable;
+ use SerializesModels;
+
+ protected $domain_id;
+
+ /**
+ * Create a new job instance.
+ *
+ * @param int $domain_id
+ *
+ * @return void
+ */
+ public function __construct($domain_id)
+ {
+ $this->domain_id = $domain_id;
+ }
+
+ /**
+ * Execute the job.
+ *
+ * @return void
+ */
+ public function handle()
+ {
+ $domain = \App\Domain::find($this->domain_id);
+
+ LDAP::updateDomain($domain);
+ }
+}
diff --git a/src/app/Observers/DomainObserver.php b/src/app/Observers/DomainObserver.php
--- a/src/app/Observers/DomainObserver.php
+++ b/src/app/Observers/DomainObserver.php
@@ -77,10 +77,9 @@
*/
public function updated(Domain $domain)
{
- //
+ \App\Jobs\DomainUpdate::dispatch($domain->id);
}
-
/**
* Handle the domain "restored" event.
*
diff --git a/src/app/Observers/EntitlementObserver.php b/src/app/Observers/EntitlementObserver.php
--- a/src/app/Observers/EntitlementObserver.php
+++ b/src/app/Observers/EntitlementObserver.php
@@ -54,6 +54,12 @@
}
}
+ public function created(Entitlement $entitlement)
+ {
+ $entitlement->entitleable->updated_at = Carbon::now();
+ $entitlement->entitleable->save();
+ }
+
/**
* Handle the entitlement "deleted" event.
*
@@ -69,5 +75,8 @@
$sf = new \App\Auth\SecondFactor($entitlement->entitleable);
$sf->removeFactors();
}
+
+ $entitlement->entitleable->updated_at = Carbon::now();
+ $entitlement->entitleable->save();
}
}
diff --git a/src/app/User.php b/src/app/User.php
--- a/src/app/User.php
+++ b/src/app/User.php
@@ -453,6 +453,36 @@
}
/**
+ * Suspend this domain.
+ *
+ * @return void
+ */
+ public function suspend(): void
+ {
+ if ($this->isSuspended()) {
+ return;
+ }
+
+ $this->status |= User::STATUS_SUSPENDED;
+ $this->save();
+ }
+
+ /**
+ * Unsuspend this domain.
+ *
+ * @return void
+ */
+ public function unsuspend(): void
+ {
+ if (!$this->isSuspended()) {
+ return;
+ }
+
+ $this->status ^= User::STATUS_SUSPENDED;
+ $this->save();
+ }
+
+ /**
* Return users controlled by the current user.
*
* Users assigned to wallets the current user controls or owns.
diff --git a/src/database/seeds/UserSeeder.php b/src/database/seeds/UserSeeder.php
--- a/src/database/seeds/UserSeeder.php
+++ b/src/database/seeds/UserSeeder.php
@@ -57,6 +57,7 @@
$package_domain = \App\Package::where('title', 'domain-hosting')->first();
$package_kolab = \App\Package::where('title', 'kolab')->first();
+ $package_lite = \App\Package::where('title', 'lite')->first();
$domain->assignPackage($package_domain, $john);
$john->assignPackage($package_kolab);
@@ -109,6 +110,8 @@
$john->assignPackage($package_kolab, $ned);
+ $ned->assignSku(\App\Sku::where('title', 'activesync')->first(), 1);
+
// Ned is a controller on Jack's wallet
$john->wallets()->first()->addController($ned);
@@ -117,6 +120,17 @@
$ned->assignSku($sku2fa);
SecondFactor::seed('ned@kolab.org');
+ $joe = User::create(
+ [
+ 'name' => 'Joe Sixpack',
+ 'email' => 'joe@kolab.org',
+ 'password' => 'simple123',
+ 'email_verified_at' => now()
+ ]
+ );
+
+ $john->assignPackage($package_lite, $joe);
+
factory(User::class, 10)->create();
}
}

File Metadata

Mime Type
text/plain
Expires
Sun, Mar 29, 7:59 PM (1 w, 2 h ago)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
18774990
Default Alt Text
D1069.1774814351.diff (29 KB)

Event Timeline