Changeset View
Changeset View
Standalone View
Standalone View
src/app/Domain.php
Show First 20 Lines • Show All 90 Lines • ▼ Show 20 Lines | public function assignPackage($package, $user) | ||||
] | ] | ||||
); | ); | ||||
} | } | ||||
} | } | ||||
return $this; | return $this; | ||||
} | } | ||||
/** | |||||
* Ownership verification by checking for a TXT (or CNAME) record | |||||
* in the domain's DNS (that matches the verification hash). | |||||
* | |||||
* @return bool True if verification was successful, false otherwise | |||||
* @throws \Exception Throws exception on DNS or DB errors | |||||
*/ | |||||
public function confirm(): bool | |||||
{ | |||||
if ($this->isConfirmed()) { | |||||
return true; | |||||
} | |||||
$hash = $this->hash(self::HASH_TEXT); | |||||
$confirmed = false; | |||||
// Get DNS records and find a matching TXT entry | |||||
$records = \dns_get_record($this->namespace, DNS_TXT); | |||||
if ($records === false) { | |||||
throw new \Exception("Failed to get DNS record for {$this->namespace}"); | |||||
} | |||||
foreach ($records as $record) { | |||||
if ($record['txt'] === $hash) { | |||||
$confirmed = true; | |||||
break; | |||||
} | |||||
} | |||||
// Get DNS records and find a matching CNAME entry | |||||
// Note: some servers resolve every non-existing name | |||||
// so we need to define left and right side of the CNAME record | |||||
// i.e.: kolab-verify IN CNAME <hash>.domain.tld. | |||||
if (!$confirmed) { | |||||
$cname = $this->hash(self::HASH_CODE) . '.' . $this->namespace; | |||||
$records = \dns_get_record('kolab-verify.' . $this->namespace, DNS_CNAME); | |||||
if ($records === false) { | |||||
throw new \Exception("Failed to get DNS record for {$this->namespace}"); | |||||
} | |||||
foreach ($records as $records) { | |||||
if ($records['target'] === $cname) { | |||||
$confirmed = true; | |||||
break; | |||||
} | |||||
} | |||||
} | |||||
if ($confirmed) { | |||||
$this->status |= Domain::STATUS_CONFIRMED; | |||||
$this->save(); | |||||
} | |||||
return $confirmed; | |||||
} | |||||
/** | |||||
* Return the entitlement for this domain. | |||||
* | |||||
* @return \App\Entitlement|null | |||||
*/ | |||||
public function entitlement() | public function entitlement() | ||||
{ | { | ||||
if ($this->isPublic()) { | |||||
return null; | |||||
} | |||||
return $this->morphOne('App\Entitlement', 'entitleable'); | return $this->morphOne('App\Entitlement', 'entitleable'); | ||||
} | } | ||||
/** | /** | ||||
* Return list of public+active domain names | * Return list of public+active domain names | ||||
*/ | */ | ||||
public static function getPublicDomains(): array | public static function getPublicDomains(): array | ||||
{ | { | ||||
$where = sprintf('(type & %s)', Domain::TYPE_PUBLIC); | $where = sprintf('(type & %s)', Domain::TYPE_PUBLIC); | ||||
return self::whereRaw($where)->get(['namespace'])->pluck('namespace')->toArray(); | return self::whereRaw($where)->get(['namespace'])->pluck('namespace')->toArray(); | ||||
} | } | ||||
/** | /** | ||||
* Generate a verification hash for this domain | |||||
* | |||||
* @param int $mod One of: HASH_CNAME, HASH_CODE (Default), HASH_TEXT | |||||
* | |||||
* @return string Verification hash | |||||
*/ | |||||
public function hash($mod = null): string | |||||
{ | |||||
$cname = 'kolab-verify'; | |||||
if ($mod === self::HASH_CNAME) { | |||||
return $cname; | |||||
} | |||||
$hash = \md5('hkccp-verify-' . $this->namespace); | |||||
return $mod === self::HASH_TEXT ? "$cname=$hash" : $hash; | |||||
} | |||||
/** | |||||
* Returns whether this domain is active. | * Returns whether this domain is active. | ||||
* | * | ||||
* @return bool | * @return bool | ||||
*/ | */ | ||||
public function isActive(): bool | public function isActive(): bool | ||||
{ | { | ||||
return ($this->status & self::STATUS_ACTIVE) > 0; | return ($this->status & self::STATUS_ACTIVE) > 0; | ||||
} | } | ||||
▲ Show 20 Lines • Show All 126 Lines • ▼ Show 20 Lines | public function setStatusAttribute($status) | ||||
if ($status > 0) { | if ($status > 0) { | ||||
throw new \Exception("Invalid domain status: {$status}"); | throw new \Exception("Invalid domain status: {$status}"); | ||||
} | } | ||||
$this->attributes['status'] = $new_status; | $this->attributes['status'] = $new_status; | ||||
} | } | ||||
/** | /** | ||||
* Ownership verification by checking for a TXT (or CNAME) record | |||||
* in the domain's DNS (that matches the verification hash). | |||||
* | |||||
* @return bool True if verification was successful, false otherwise | |||||
* @throws \Exception Throws exception on DNS or DB errors | |||||
*/ | |||||
public function confirm(): bool | |||||
{ | |||||
if ($this->isConfirmed()) { | |||||
return true; | |||||
} | |||||
$hash = $this->hash(self::HASH_TEXT); | |||||
$confirmed = false; | |||||
// Get DNS records and find a matching TXT entry | |||||
$records = \dns_get_record($this->namespace, DNS_TXT); | |||||
if ($records === false) { | |||||
throw new \Exception("Failed to get DNS record for {$this->namespace}"); | |||||
} | |||||
foreach ($records as $record) { | |||||
if ($record['txt'] === $hash) { | |||||
$confirmed = true; | |||||
break; | |||||
} | |||||
} | |||||
// Get DNS records and find a matching CNAME entry | |||||
// Note: some servers resolve every non-existing name | |||||
// so we need to define left and right side of the CNAME record | |||||
// i.e.: kolab-verify IN CNAME <hash>.domain.tld. | |||||
if (!$confirmed) { | |||||
$cname = $this->hash(self::HASH_CODE) . '.' . $this->namespace; | |||||
$records = \dns_get_record('kolab-verify.' . $this->namespace, DNS_CNAME); | |||||
if ($records === false) { | |||||
throw new \Exception("Failed to get DNS record for {$this->namespace}"); | |||||
} | |||||
foreach ($records as $records) { | |||||
if ($records['target'] === $cname) { | |||||
$confirmed = true; | |||||
break; | |||||
} | |||||
} | |||||
} | |||||
if ($confirmed) { | |||||
$this->status |= Domain::STATUS_CONFIRMED; | |||||
$this->save(); | |||||
} | |||||
return $confirmed; | |||||
} | |||||
/** | |||||
* Generate a verification hash for this domain | |||||
* | |||||
* @param int $mod One of: HASH_CNAME, HASH_CODE (Default), HASH_TEXT | |||||
* | |||||
* @return string Verification hash | |||||
*/ | |||||
public function hash($mod = null): string | |||||
{ | |||||
$cname = 'kolab-verify'; | |||||
if ($mod === self::HASH_CNAME) { | |||||
return $cname; | |||||
} | |||||
$hash = \md5('hkccp-verify-' . $this->namespace); | |||||
return $mod === self::HASH_TEXT ? "$cname=$hash" : $hash; | |||||
} | |||||
/** | |||||
* Suspend this domain. | * Suspend this domain. | ||||
* | * | ||||
* @return void | * @return void | ||||
*/ | */ | ||||
public function suspend(): void | public function suspend(): void | ||||
{ | { | ||||
if ($this->isSuspended()) { | if ($this->isSuspended()) { | ||||
return; | return; | ||||
Show All 14 Lines | public function unsuspend(): void | ||||
return; | return; | ||||
} | } | ||||
$this->status ^= Domain::STATUS_SUSPENDED; | $this->status ^= Domain::STATUS_SUSPENDED; | ||||
$this->save(); | $this->save(); | ||||
} | } | ||||
/** | /** | ||||
* List user accounts for this domain. | |||||
* | |||||
* @return \App\User[] A list of users. | |||||
*/ | |||||
public function users() | |||||
{ | |||||
if ($this->isPublic()) { | |||||
$this->error("This domain is a public registration domain."); | |||||
return 1; | |||||
} | |||||
// TODO: actually implement listing users | |||||
$wallet = $this->wallet(); | |||||
if (!$wallet) { | |||||
$this->error("This domain isn't billed to a wallet."); | |||||
return 1; | |||||
} | |||||
$mailboxSKU = \App\Sku::where('title', 'mailbox')->first(); | |||||
if (!$mailboxSKU) { | |||||
$this->error("No mailbox SKU available."); | |||||
machniak: I think $this->error() in here is not correct. Also the `TODO` above. | |||||
} | |||||
$entitlements = $wallet->entitlements() | |||||
->where('entitleable_type', \App\User::class) | |||||
->where('sku_id', $mailboxSKU->id)->get(); | |||||
$users = []; | |||||
foreach ($entitlements as $entitlement) { | |||||
$users[] = $entitlement->entitleable; | |||||
} | |||||
usort($users, function ($a, $b) { | |||||
return $a->email > $b->email; | |||||
}); | |||||
return $users; | |||||
} | |||||
/** | |||||
* Verify if a domain exists in DNS | * Verify if a domain exists in DNS | ||||
* | * | ||||
* @return bool True if registered, False otherwise | * @return bool True if registered, False otherwise | ||||
* @throws \Exception Throws exception on DNS or DB errors | * @throws \Exception Throws exception on DNS or DB errors | ||||
*/ | */ | ||||
public function verify(): bool | public function verify(): bool | ||||
{ | { | ||||
if ($this->isVerified()) { | if ($this->isVerified()) { | ||||
Show All 34 Lines |
I think $this->error() in here is not correct. Also the TODO above.