feat(): add postfixadmin-change-password plugin #3
This commit is contained in:
parent
7b8e9f7c5e
commit
fb32a710da
@ -13,6 +13,7 @@ Rainloop is a simple, modern & fast web-based client. More details on the [offic
|
|||||||
- Latest Rainloop **Community Edition** (stable)
|
- Latest Rainloop **Community Edition** (stable)
|
||||||
- Contacts (DB) : sqlite, or mysql (server not built-in)
|
- Contacts (DB) : sqlite, or mysql (server not built-in)
|
||||||
- With Nginx and PHP7
|
- With Nginx and PHP7
|
||||||
|
- Postfixadmin-change-password plugin
|
||||||
|
|
||||||
### Build-time variables
|
### Build-time variables
|
||||||
|
|
||||||
|
@ -3,6 +3,14 @@
|
|||||||
# Set attachment size limit
|
# Set attachment size limit
|
||||||
sed -i "s/<UPLOAD_MAX_SIZE>/$UPLOAD_MAX_SIZE/g" /etc/php7/php-fpm.conf /etc/nginx/nginx.conf
|
sed -i "s/<UPLOAD_MAX_SIZE>/$UPLOAD_MAX_SIZE/g" /etc/php7/php-fpm.conf /etc/nginx/nginx.conf
|
||||||
|
|
||||||
|
# Remove postfixadmin-change-password plugin if exist
|
||||||
|
if [ -d "/rainloop/data/_data_/_default_/plugins/postfixadmin-change-password" ]; then
|
||||||
|
rm -rf /rainloop/data/_data_/_default_/plugins/postfixadmin-change-password
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Add postfixadmin-change-password plugin
|
||||||
|
cp -r /usr/local/include/postfixadmin-change-password /rainloop/data/_data_/_default_/plugins/
|
||||||
|
|
||||||
# Fix permissions
|
# Fix permissions
|
||||||
chown -R $UID:$GID /rainloop/data /services /var/log /var/lib/nginx
|
chown -R $UID:$GID /rainloop/data /services /var/log /var/lib/nginx
|
||||||
|
|
||||||
|
@ -0,0 +1,301 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
class ChangePasswordPostfixAdminDriver implements \RainLoop\Providers\ChangePassword\ChangePasswordInterface
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private $sHost = '127.0.0.1';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var int
|
||||||
|
*/
|
||||||
|
private $iPort = 3306;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private $sDatabase = 'postfixadmin';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private $sTable = 'mailbox';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private $sUsercol = 'username';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private $sPasscol = 'password';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private $sUser = 'postfixadmin';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private $sPassword = '';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private $sEncrypt = '';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private $sAllowedEmails = '';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var \MailSo\Log\Logger
|
||||||
|
*/
|
||||||
|
private $oLogger = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $sHost
|
||||||
|
*
|
||||||
|
* @return \ChangePasswordPostfixAdminDriver
|
||||||
|
*/
|
||||||
|
public function SetHost($sHost)
|
||||||
|
{
|
||||||
|
$this->sHost = $sHost;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param int $iPort
|
||||||
|
*
|
||||||
|
* @return \ChangePasswordPostfixAdminDriver
|
||||||
|
*/
|
||||||
|
public function SetPort($iPort)
|
||||||
|
{
|
||||||
|
$this->iPort = (int) $iPort;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $sDatabase
|
||||||
|
*
|
||||||
|
* @return \ChangePasswordPostfixAdminDriver
|
||||||
|
*/
|
||||||
|
public function SetDatabase($sDatabase)
|
||||||
|
{
|
||||||
|
$this->sDatabase = $sDatabase;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $sTable
|
||||||
|
*
|
||||||
|
* @return \ChangePasswordPostfixAdminDriver
|
||||||
|
*/
|
||||||
|
public function SetTable($sTable)
|
||||||
|
{
|
||||||
|
$this->sTable = $sTable;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $sUsercol
|
||||||
|
*
|
||||||
|
* @return \ChangePasswordPostfixAdminDriver
|
||||||
|
*/
|
||||||
|
public function SetUserColumn($sUsercol)
|
||||||
|
{
|
||||||
|
$this->sUsercol = $sUsercol;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $sPasscol
|
||||||
|
*
|
||||||
|
* @return \ChangePasswordPostfixAdminDriver
|
||||||
|
*/
|
||||||
|
public function SetPasswordColumn($sPasscol)
|
||||||
|
{
|
||||||
|
$this->sPasscol = $sPasscol;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $sUser
|
||||||
|
*
|
||||||
|
* @return \ChangePasswordPostfixAdminDriver
|
||||||
|
*/
|
||||||
|
public function SetUser($sUser)
|
||||||
|
{
|
||||||
|
$this->sUser = $sUser;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $sPassword
|
||||||
|
*
|
||||||
|
* @return \ChangePasswordPostfixAdminDriver
|
||||||
|
*/
|
||||||
|
public function SetPassword($sPassword)
|
||||||
|
{
|
||||||
|
$this->sPassword = $sPassword;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $sEncrypt
|
||||||
|
*
|
||||||
|
* @return \ChangePasswordPostfixAdminDriver
|
||||||
|
*/
|
||||||
|
public function SetEncrypt($sEncrypt)
|
||||||
|
{
|
||||||
|
$this->sEncrypt = $sEncrypt;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $sAllowedEmails
|
||||||
|
*
|
||||||
|
* @return \ChangePasswordPostfixAdminDriver
|
||||||
|
*/
|
||||||
|
public function SetAllowedEmails($sAllowedEmails)
|
||||||
|
{
|
||||||
|
$this->sAllowedEmails = $sAllowedEmails;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param \MailSo\Log\Logger $oLogger
|
||||||
|
*
|
||||||
|
* @return \ChangePasswordPostfixAdminDriver
|
||||||
|
*/
|
||||||
|
public function SetLogger($oLogger)
|
||||||
|
{
|
||||||
|
if ($oLogger instanceof \MailSo\Log\Logger)
|
||||||
|
{
|
||||||
|
$this->oLogger = $oLogger;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param \RainLoop\Model\Account $oAccount
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function PasswordChangePossibility($oAccount)
|
||||||
|
{
|
||||||
|
return $oAccount && $oAccount->Email() &&
|
||||||
|
\RainLoop\Plugins\Helper::ValidateWildcardValues($oAccount->Email(), $this->sAllowedEmails);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param \RainLoop\Model\Account $oAccount
|
||||||
|
* @param string $sPrevPassword
|
||||||
|
* @param string $sNewPassword
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function ChangePassword(\RainLoop\Account $oAccount, $sPrevPassword, $sNewPassword)
|
||||||
|
{
|
||||||
|
if ($this->oLogger)
|
||||||
|
{
|
||||||
|
$this->oLogger->Write('Postfix: Try to change password for '.$oAccount->Email());
|
||||||
|
}
|
||||||
|
|
||||||
|
unset($sPrevPassword);
|
||||||
|
|
||||||
|
$bResult = false;
|
||||||
|
|
||||||
|
if (0 < \strlen($sNewPassword))
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
$sDsn = 'mysql:host='.$this->sHost.';port='.$this->iPort.';dbname='.$this->sDatabase;
|
||||||
|
|
||||||
|
$oPdo = new \PDO($sDsn, $this->sUser, $this->sPassword);
|
||||||
|
$oPdo->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION);
|
||||||
|
|
||||||
|
$sUpdatePassword = $this->cryptPassword($sNewPassword, $oPdo);
|
||||||
|
if (0 < \strlen($sUpdatePassword))
|
||||||
|
{
|
||||||
|
$oStmt = $oPdo->prepare("UPDATE {$this->sTable} SET {$this->sPasscol} = ? WHERE {$this->sUsercol} = ?");
|
||||||
|
$bResult = (bool) $oStmt->execute(array($sUpdatePassword, $oAccount->Email()));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if ($this->oLogger)
|
||||||
|
{
|
||||||
|
$this->oLogger->Write('Postfix: Encrypted password is empty',
|
||||||
|
\MailSo\Log\Enumerations\Type::ERROR);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$oPdo = null;
|
||||||
|
}
|
||||||
|
catch (\Exception $oException)
|
||||||
|
{
|
||||||
|
if ($this->oLogger)
|
||||||
|
{
|
||||||
|
$this->oLogger->WriteException($oException);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $bResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $sPassword
|
||||||
|
* @param \PDO $oPdo
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
private function cryptPassword($sPassword, $oPdo)
|
||||||
|
{
|
||||||
|
$sResult = '';
|
||||||
|
$sSalt = substr(str_shuffle('./ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'), 0, 16);
|
||||||
|
switch (strtolower($this->sEncrypt))
|
||||||
|
{
|
||||||
|
default:
|
||||||
|
case 'plain':
|
||||||
|
case 'cleartext':
|
||||||
|
$sResult = '{PLAIN}' . $sPassword;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'md5':
|
||||||
|
$sResult = '{PLAIN-MD5}' . md5($sPassword);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'system':
|
||||||
|
$sResult = '{CRYPT}' . crypt($sPassword);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'sha256-crypt':
|
||||||
|
$sResult = '{SHA256-CRYPT}' . crypt($sPassword,'$5$'.$sSalt);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'sha512-crypt':
|
||||||
|
$sResult = '{SHA512-CRYPT}' . crypt($sPassword,'$6$'.$sSalt);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'mysql_encrypt':
|
||||||
|
$oStmt = $oPdo->prepare('SELECT ENCRYPT(?) AS encpass');
|
||||||
|
if ($oStmt->execute(array($sPassword)))
|
||||||
|
{
|
||||||
|
$aFetchResult = $oStmt->fetchAll(\PDO::FETCH_ASSOC);
|
||||||
|
if (\is_array($aFetchResult) && isset($aFetchResult[0]['encpass']))
|
||||||
|
{
|
||||||
|
$sResult = $aFetchResult[0]['encpass'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $sResult;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,95 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
class PostfixadminChangePasswordPlugin extends \RainLoop\Plugins\AbstractPlugin
|
||||||
|
{
|
||||||
|
public function Init()
|
||||||
|
{
|
||||||
|
$this->addHook('main.fabrica', 'MainFabrica');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function Supported()
|
||||||
|
{
|
||||||
|
if (!extension_loaded('pdo') || !class_exists('PDO'))
|
||||||
|
{
|
||||||
|
return 'The PHP exention PDO (mysql) must be installed to use this plugin';
|
||||||
|
}
|
||||||
|
|
||||||
|
$aDrivers = \PDO::getAvailableDrivers();
|
||||||
|
if (!is_array($aDrivers) || !in_array('mysql', $aDrivers))
|
||||||
|
{
|
||||||
|
return 'The PHP exention PDO (mysql) must be installed to use this plugin';
|
||||||
|
}
|
||||||
|
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $sName
|
||||||
|
* @param mixed $oProvider
|
||||||
|
*/
|
||||||
|
public function MainFabrica($sName, &$oProvider)
|
||||||
|
{
|
||||||
|
switch ($sName)
|
||||||
|
{
|
||||||
|
case 'change-password':
|
||||||
|
|
||||||
|
include_once __DIR__.'/ChangePasswordPostfixAdminDriver.php';
|
||||||
|
|
||||||
|
$oProvider = new ChangePasswordPostfixAdminDriver();
|
||||||
|
|
||||||
|
$oProvider
|
||||||
|
->SetHost($this->Config()->Get('plugin', 'host', ''))
|
||||||
|
->SetPort((int) $this->Config()->Get('plugin', 'port', 3306))
|
||||||
|
->SetDatabase($this->Config()->Get('plugin', 'database', ''))
|
||||||
|
->SetTable($this->Config()->Get('plugin', 'table', ''))
|
||||||
|
->SetUserColumn($this->Config()->Get('plugin', 'usercol', ''))
|
||||||
|
->SetPasswordColumn($this->Config()->Get('plugin', 'passcol', ''))
|
||||||
|
->SetUser($this->Config()->Get('plugin', 'user', ''))
|
||||||
|
->SetPassword($this->Config()->Get('plugin', 'password', ''))
|
||||||
|
->SetEncrypt($this->Config()->Get('plugin', 'encrypt', ''))
|
||||||
|
->SetAllowedEmails(\strtolower(\trim($this->Config()->Get('plugin', 'allowed_emails', ''))))
|
||||||
|
->SetLogger($this->Manager()->Actions()->Logger())
|
||||||
|
;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function configMapping()
|
||||||
|
{
|
||||||
|
return array(
|
||||||
|
\RainLoop\Plugins\Property::NewInstance('host')->SetLabel('MySQL Host')
|
||||||
|
->SetDefaultValue('mariadb'),
|
||||||
|
\RainLoop\Plugins\Property::NewInstance('port')->SetLabel('MySQL Port')
|
||||||
|
->SetType(\RainLoop\Enumerations\PluginPropertyType::INT)
|
||||||
|
->SetDefaultValue(3306),
|
||||||
|
\RainLoop\Plugins\Property::NewInstance('database')->SetLabel('MySQL Database')
|
||||||
|
->SetDefaultValue('postfix'),
|
||||||
|
\RainLoop\Plugins\Property::NewInstance('table')->SetLabel('MySQL table')
|
||||||
|
->SetDefaultValue('mailbox'),
|
||||||
|
\RainLoop\Plugins\Property::NewInstance('usercol')->SetLabel('MySQL username column')
|
||||||
|
->SetDefaultValue('username'),
|
||||||
|
\RainLoop\Plugins\Property::NewInstance('passcol')->SetLabel('MySQL password column')
|
||||||
|
->SetDefaultValue('password'),
|
||||||
|
\RainLoop\Plugins\Property::NewInstance('user')->SetLabel('MySQL User')
|
||||||
|
->SetDefaultValue('postfix'),
|
||||||
|
\RainLoop\Plugins\Property::NewInstance('password')->SetLabel('MySQL Password')
|
||||||
|
->SetType(\RainLoop\Enumerations\PluginPropertyType::PASSWORD)
|
||||||
|
->SetDefaultValue(''),
|
||||||
|
\RainLoop\Plugins\Property::NewInstance('encrypt')->SetLabel('Encrypt')
|
||||||
|
->SetType(\RainLoop\Enumerations\PluginPropertyType::SELECTION)
|
||||||
|
->SetDefaultValue(array('SHA512-CRYPT','SHA256-CRYPT','md5', 'system', 'cleartext', 'mysql_encrypt'))
|
||||||
|
->SetDescription('In what way do you want the passwords to be crypted ?'),
|
||||||
|
\RainLoop\Plugins\Property::NewInstance('allowed_emails')->SetLabel('Allowed emails')
|
||||||
|
->SetType(\RainLoop\Enumerations\PluginPropertyType::STRING_TEXT)
|
||||||
|
->SetDescription('Allowed emails, space as delimiter, wildcard supported. Example: user1@domain1.net user2@domain1.net *@domain2.net')
|
||||||
|
->SetDefaultValue('*')
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user