<?php
namespace App\Model;
use phpDocumentor\Reflection\Types\Boolean;
use Symfony\Component\Validator\Constraints as Assert;
use phpDocumentor\Reflection\Types\Array_;
use App\Util\Api;
class Account implements \JsonSerializable
{
const NUMBER_OF_ITEMS = 30;
const NUMBER_OF_ITEMS_MAX= 5000;
const NUMBER_OF_LOGINS = 10; // number of login attempts shown at once
const NUMBER_OF_OPERATIONS = 50; // number of login attempts shown at once
const PASS_COMPLEXITY_BASIC = 1;
const PASS_COMPLEXITY_STRICT = 2;
const PASS_COMPLEXITY_VERY_STRICT = 3;
const PASS_COMPLEXITY_VERY_STRICT_16 = 4; // very strict with 16 characters
const QUOTA_NO_QUOTA = 0;
const QUOTA_INFINITE = -1;
const QUOTA_NOT_AVAILABLE = -100;
const MAX_USERNAME_LENGTH = 32;
const MAX_FORWARDS_LIMIT = 1000;
// for admin charts
const LOAD_AVG_DEFAULT_RANGE = 5;
private $uid=0;
private $gid=0;
/**
* @Assert\NotBlank()
* @Assert\Regex(
pattern = "/^[a-z0-9]+[a-z0-9-@_.,]*$/",
message = "account.username.invalid"
)
* @Assert\Length(
min = 2,
minMessage = "account.username.minLength"
)
*/
private $userName;
/* /^[a-z0-9]+[a-z0-9-_.]*$/", */
/**
* @Assert\NotBlank()
* @Assert\Regex(
pattern = "/^[a-zA-Z0-9][a-zA-Z0-9.-]{0,61}\.[a-zA-Z]{2,}$/",
message = "account.userdomain.invalid"
)
* @Assert\Length(
min = 2,
minMessage = "account.userdomain.minLength"
)
*/
private $userDomain;
private $usedSpace;
/**
* TODO kalma sprawdzić jakie są asserty i ustawić, że ma być int, bo Integer nie działa
*/
private $description;
private $password;
private $clearPassword;
private $directory="";
private $shell="";
private $allowedServices;
private $allowedModules;
private $passComplexity;
private $role;
// options
private $sOptions;
private $inProgress;
private $aliases;
// int options
//private $iOptions;
const TOKEN_SALT = 'MMROn4nCRIY5c7no8x0Jtmxtq4aCKS3y';
const EMPTY_PASSWORD = 'j3DACJttjuG3cxxmhP5YfhVwpUNq2LFa';
public static function getConstQuotaNoQuota()
{
return Account::QUOTA_NO_QUOTA;
}
public static function getConstQuotaNotAvailable()
{
return Account::QUOTA_NOT_AVAILABLE;
}
public static function getConstQuotaInfinite()
{
return Account::QUOTA_INFINITE;
}
public static function getConstSAMaxScoreLimit()
{
return UserPref::SA_MAX_SCORE_LIMIT;
}
public static function getConstItemsMax()
{
return Account::NUMBER_OF_ITEMS_MAX;
}
public static function getConstOperations()
{
return Account::NUMBER_OF_OPERATIONS;
}
public static function getConstMaxForwardsLimit()
{
return Account::MAX_FORWARDS_LIMIT;
}
public function getGid(): ?int
{
return $this->gid;
}
public function setGid(int $id): self
{
$this->gid = $id;
return $this;
}
public function getUid(): ?int
{
return $this->uid;
}
public function setUid(int $id): self
{
$this->uid = $id;
return $this;
}
public function getUserName(): ?string
{
return $this->userName;
}
public function setUserName(string $username): self
{
$this->userName = $username;
return $this;
}
public function getUserDomain(): ?string
{
return $this->userDomain;
}
public function setUserDomain(string $userDomain): self
{
$this->userDomain = $userDomain;
return $this;
}
public function getUsedSpace(): ?int
{
return $this->usedSpace;
}
public function setUsedSpace(?int $usedSpace): self
{
$this->usedSpace = $usedSpace;
return $this;
}
public function getQuota(): ?int
{
return (int)$this->quota;
}
public function setQuota(?int $quota): self
{
$this->quota = $quota;
return $this;
}
public function getDescription(): ?string
{
return $this->description;
}
public function setDescription(string $description): self
{
$this->description = $description;
return $this;
}
public function getRole(): ?string
{
return $this->role;
}
public function setRole(string $role): self
{
if($role == '') {
$this->role = null;
}
else {
$this->role = $role;
}
return $this;
}
public function getSOptions(): ?array
{
return $this->sOptions;
}
public function setSOptions(array $options): self
{
$this->sOptions = $options;
return $this;
}
/**
* @return mixed
*/
public function getAliases()
{
return $this->aliases;
}
/**
* @param mixed $aliases
*/
public function setAliases($aliases)
{
$this->aliases = $aliases;
}
/*public function getIOptions(): ?array
{
return $this->iOptions;
}
public function setIOptions(array $options): self
{
$this->iOptions = $options;
return $this;
}*/
public function getPassword(): ?string
{
return $this->password;
}
public function setPassword(string $password): self
{
$this->password = $password;
return $this;
}
public function getClearPassword(): ?string
{
return $this->clearPassword;
}
public function setClearPassword(string $password): self
{
$this->clearPassword = $password;
return $this;
}
public function getDirectory(): ?string
{
return $this->directory;
}
public function setDirectory(string $directory): self
{
$this->directory = $directory;
return $this;
}
public function getShell(): ?string
{
return $this->shell;
}
public function setShell(string $shell): self
{
$this->shell = $shell;
return $this;
}
public function getPassComplexity(): ?int
{
if($this->passComplexity != 0) {
return $this->passComplexity;
}
else {
return Account::PASS_COMPLEXITY_STRICT;
}
}
public function setPassComplexity(int $passComplexity): self
{
$this->passComplexity = $passComplexity;
return $this;
}
public function getAllowedServices(): Array
{
return $this->allowedServices;
}
/**
*
* @param array $services - what services are allowed for this user
* @return self
*/
public function setAllowedServices(Array $services) : self
{
$this->allowedServices = $services;
return $this;
}
/**
* what kind of system services can be set as allowed / not allowed
* remember to change it in qpanel-server as well
* @return array
*/
public static function getAllowableServices() : Array
{
return ['Pop3', 'Imap4', 'Smtp', 'Webmail'];
}
public function getAllowedModules(): Array
{
return $this->allowedModules;
}
/**
*
* @param array $modules - what modules are allowed for this user
* @return self
*/
public function setAllowedModules(Array $modules): self
{
$this->allowedModules = $modules;
return $this;
}
/**
* what kind of modules for user can be set as allowed / not allowed
* remember to change it in qpanel-server as well
* @return array
*/
public static function getAllowableModules() : Array
{
return ['PasswordChange', 'Forward', 'Autoresponder', 'SpamAssassin', 'ImapDirs', 'ProcMail', 'NoticeSms'];
}
public function jsonSerialize()
{
$vars = get_object_vars($this);
return $vars;
}
/**
* return address of the account in format userName@userDomain
* @return string - user address
*/
public function userAddress() : string
{
return $this->userName . '@' . $this->userDomain;
}
public function setUserAddress($userAddress) : bool
{
$arr = explode('@', $userAddress);
if(count($arr) != 2) {
return false;
}
$this->userName = $arr[0];
$this->userDomain = $arr[1];
return true;
}
/**
* token crated from fields userName and userDomain to prevent URL manipulations
* @return string token
*/
public function token() :string
{
return md5($this->userName . Account::TOKEN_SALT . $this->userDomain);
}
/**
* lock account
* @return TRUE - success, FALSE - failure
*/
public function lock() : bool
{
return Api::lockAccount($this);
}
/**
* unlock account
* @return TRUE - success, FALSE - failure
*/
public function unlock() : bool
{
return Api::unlockAccount($this);
}
/**
* if account is locked
* @return bool
*/
public function isLocked() : bool
{
$ret_val = preg_match('/^\$A\$/', $this->getPassword());
if ($ret_val == 0)
$ret_val = preg_match('/^\$B\$/', $this->getPassword());
if ($ret_val == 0)
$ret_val = preg_match('/^\$C\$/', $this->getPassword());
return $ret_val;
}
/**
* delete account
* @return TRUE - success, FALSE - failure
*/
public function delete() : bool
{
return Api::deleteAccount($this);
}
public function md5() : String
{
return md5($this->userName . '@' . $this->userDomain);
}
/**
* returns domains accessible for this account (makes sens for roles POSTMASTER_MANY, POSTMASTER and GROUPMASTER)
* @return array
*/
public function roleDomains() : array
{
if($this->getRole() == 'ROLE_ADMIN') {
try {
$domains = Api::listDomains();
if(count($domains) == 0) {
return [$this->getuserDomain()];
}
else {
return $domains;
}
}
catch(\Exception $e) {
return [];
}
}
else {
try {
$domains = Api::getRoleDomains($this->getUserName(), $this->getuserDomain());
if(count($domains) == 0) {
return [$this->getuserDomain()];
}
else {
return $domains;
}
}
catch(\Exception $e) {
return [];
}
}
}
/**
* returns value of the option or throws exception if option not present
* @param string $name
* @throws \Exception
*/
/*public function findIOption(string $name) : int
{
if(array_key_exists($name, $this->iOptions)) {
return $this->iOptions[$name];
}
else {
throw new \Exception('option not found');
}
}*/
/**
* returns value of the option or return null if not found
* @param string $name or null
*/
public function findSOption(string $name)
{
if(array_key_exists($name, $this->sOptions)) {
return $this->sOptions[$name];
}
else {
return null;
}
}
/**
* is option 'name' set to true / yes 1
* mainly useful in twig templates
* @return boolean
*/
public function isOptionSet($name)
{
$val = $this->findSOption($name);
if($val == null) {
return false;
}
if($val == 1 || $val == 'yes' || $val == 'true') {
return true;
}
return false;
}
public function deleteOption(string $name)
{
/*if(array_key_exists($name, $this->iOptions)) {
unset($this->iOptions[$name]);
}*/
if(array_key_exists($name, $this->sOptions)) {
unset($this->sOptions[$name]);
}
}
/*public function setIOption(string $name, int $val)
{
$this->iOptions[$name] = $val;
return $this;
}*/
public function setSOption(string $name, string $val)
{
$this->sOptions[$name] = $val;
return $this;
}
// get state of the infoboxes
public function getInfoBoxCollapsed() : array
{
$ibc = $this->findSOption('infoBoxCollapsed') == null ? '[]' : $this->findSOption('infoBoxCollapsed');
return json_decode($ibc, true);
}
/**
* @return bool
*/
public function getInProgress() : bool
{
return $this->inProgress;
}
/**
* @param bool $inProgress
*/
public function setInProgress($inProgress)
{
$this->inProgress = $inProgress;
}
// if this account is in progress of adding / deleting
public function isInProgress() : bool
{
// always get fresh, current state
if($this->userAddress() != '') {
return Api::isAccountInProgress($this);
}
else {
return false;
}
}
}