mirror of
https://github.com/opensupports/opensupports.git
synced 2025-07-27 07:44:29 +02:00
First working version of invite users feature
This commit is contained in:
parent
aa7cefc959
commit
5331c3363e
@ -4,6 +4,7 @@ $userControllers->setGroupPath('/user');
|
|||||||
|
|
||||||
$userControllers->addController(new LoginController);
|
$userControllers->addController(new LoginController);
|
||||||
$userControllers->addController(new SignUpController);
|
$userControllers->addController(new SignUpController);
|
||||||
|
$userControllers->addController(new InviteUserController);
|
||||||
$userControllers->addController(new LogoutController);
|
$userControllers->addController(new LogoutController);
|
||||||
$userControllers->addController(new CheckSessionController);
|
$userControllers->addController(new CheckSessionController);
|
||||||
$userControllers->addController(new SendRecoverPasswordController);
|
$userControllers->addController(new SendRecoverPasswordController);
|
||||||
|
148
server/controllers/user/invite.php
Executable file
148
server/controllers/user/invite.php
Executable file
@ -0,0 +1,148 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Respect\Validation\Validator as DataValidator;
|
||||||
|
DataValidator::with('CustomValidations', true);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @api {post} /user/invite Invite
|
||||||
|
* @apiVersion 4.5.0
|
||||||
|
*
|
||||||
|
* @apiName Invite
|
||||||
|
*
|
||||||
|
* @apiGroup User
|
||||||
|
*
|
||||||
|
* @apiDescription This path invites an user on the system.
|
||||||
|
*
|
||||||
|
* @apiPermission staff1
|
||||||
|
*
|
||||||
|
* @apiParam {String} name The name of the invited user.
|
||||||
|
* @apiParam {String} email The email of the invited user.
|
||||||
|
* @apiParam {String} customfield_ Custom field values for this user.
|
||||||
|
*
|
||||||
|
* @apiUse INVALID_NAME
|
||||||
|
* @apiUse INVALID_EMAIL
|
||||||
|
* @apiUse INVALID_CAPTCHA
|
||||||
|
* @apiUse USER_EXISTS
|
||||||
|
* @apiUse ALREADY_BANNED
|
||||||
|
* @apiUse NO_PERMISSION
|
||||||
|
* @apiUse INVALID_CUSTOM_FIELD_OPTION
|
||||||
|
* @apiUse MAIL_SENDER_NOT_CONNECTED
|
||||||
|
*
|
||||||
|
* @apiSuccess {Object} data Information about invited user
|
||||||
|
* @apiSuccess {Number} data.userId Id of the invited user
|
||||||
|
* @apiSuccess {String} data.userEmail Email of the invited user
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
class InviteUserController extends Controller {
|
||||||
|
const PATH = '/invite';
|
||||||
|
const METHOD = 'POST';
|
||||||
|
|
||||||
|
private $userEmail;
|
||||||
|
private $userName;
|
||||||
|
|
||||||
|
public function validations() {
|
||||||
|
$validations = [
|
||||||
|
'permission' => 'staff_1',
|
||||||
|
'requestData' => [
|
||||||
|
'name' => [
|
||||||
|
'validation' => DataValidator::length(2, 55),
|
||||||
|
'error' => ERRORS::INVALID_NAME
|
||||||
|
],
|
||||||
|
'email' => [
|
||||||
|
'validation' => DataValidator::email(),
|
||||||
|
'error' => ERRORS::INVALID_EMAIL
|
||||||
|
]
|
||||||
|
]
|
||||||
|
];
|
||||||
|
|
||||||
|
$validations['requestData']['captcha'] = [
|
||||||
|
'validation' => DataValidator::captcha(),
|
||||||
|
'error' => ERRORS::INVALID_CAPTCHA
|
||||||
|
];
|
||||||
|
|
||||||
|
return $validations;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function handler() {
|
||||||
|
if (!Controller::isUserSystemEnabled()) {
|
||||||
|
throw new RequestException(ERRORS::USER_SYSTEM_DISABLED);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Setting::getSetting('registration')->value) {
|
||||||
|
throw new RequestException(ERRORS::NO_PERMISSION);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->storeRequestData();
|
||||||
|
|
||||||
|
$existentUser = User::getUser($this->userEmail, 'email');
|
||||||
|
|
||||||
|
if (!$existentUser->isNull()) {
|
||||||
|
throw new RequestException(ERRORS::USER_EXISTS);
|
||||||
|
}
|
||||||
|
|
||||||
|
$banRow = Ban::getDataStore($this->userEmail, 'email');
|
||||||
|
|
||||||
|
if (!$banRow->isNull()) {
|
||||||
|
throw new RequestException(ERRORS::ALREADY_BANNED);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(MailSender::getInstance()->isConnected()) {
|
||||||
|
$userId = $this->createNewUserAndRetrieveId();
|
||||||
|
|
||||||
|
$this->token = Hashing::generateRandomToken();
|
||||||
|
|
||||||
|
$recoverPassword = new RecoverPassword();
|
||||||
|
$recoverPassword->setProperties(array(
|
||||||
|
'email' => $this->userEmail,
|
||||||
|
'token' => $this->token,
|
||||||
|
'staff' => false
|
||||||
|
));
|
||||||
|
$recoverPassword->store();
|
||||||
|
|
||||||
|
$this->sendInvitationMail();
|
||||||
|
|
||||||
|
Response::respondSuccess([
|
||||||
|
'userId' => $userId,
|
||||||
|
'userEmail' => $this->userEmail
|
||||||
|
]);
|
||||||
|
// TODO: Log::createLog('SIGN_UP', null, User::getDataStore($userId));
|
||||||
|
} else {
|
||||||
|
throw new RequestException(ERRORS::MAIL_SENDER_NOT_CONNECTED);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function storeRequestData() {
|
||||||
|
$this->userName = Controller::request('name');
|
||||||
|
$this->userEmail = Controller::request('email');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function createNewUserAndRetrieveId() {
|
||||||
|
$userInstance = new User();
|
||||||
|
|
||||||
|
$userInstance->setProperties([
|
||||||
|
'name' => $this->userName,
|
||||||
|
'signupDate' => Date::getCurrentDate(),
|
||||||
|
'tickets' => 0,
|
||||||
|
'email' => $this->userEmail,
|
||||||
|
'password' => Hashing::hashPassword(Hashing::generateRandomToken()),
|
||||||
|
'verificationToken' => null,
|
||||||
|
'xownCustomfieldvalueList' => $this->getCustomFieldValues()
|
||||||
|
]);
|
||||||
|
|
||||||
|
return $userInstance->store();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function sendInvitationMail() {
|
||||||
|
$mailSender = MailSender::getInstance();
|
||||||
|
|
||||||
|
$mailSender->setTemplate(MailTemplate::USER_INVITE, [
|
||||||
|
'to' => $this->userEmail,
|
||||||
|
'name' => $this->userName,
|
||||||
|
'url' => Setting::getSetting('url')->getValue(),
|
||||||
|
'token' => $this->token
|
||||||
|
]);
|
||||||
|
|
||||||
|
$mailSender->send();
|
||||||
|
}
|
||||||
|
}
|
@ -18,7 +18,7 @@ DataValidator::with('CustomValidations', true);
|
|||||||
* @apiParam {String} name The name of the new user.
|
* @apiParam {String} name The name of the new user.
|
||||||
* @apiParam {String} email The email of the new user.
|
* @apiParam {String} email The email of the new user.
|
||||||
* @apiParam {String} password The password of the new user.
|
* @apiParam {String} password The password of the new user.
|
||||||
* @apiParam {String} apiKey APIKey to sign up an user if the user system is disabled.
|
* @apiParam {String} apiKey APIKey to sign up an user if the registration system is disabled.
|
||||||
* @apiParam {String} customfield_ Custom field values for this user.
|
* @apiParam {String} customfield_ Custom field values for this user.
|
||||||
*
|
*
|
||||||
* @apiUse INVALID_NAME
|
* @apiUse INVALID_NAME
|
||||||
|
@ -251,6 +251,10 @@
|
|||||||
* @apiDefine INVALID_COLOR
|
* @apiDefine INVALID_COLOR
|
||||||
* @apiError {String} INVALID_COLOR The color should be in hexadecimal, preceded by a '#'
|
* @apiError {String} INVALID_COLOR The color should be in hexadecimal, preceded by a '#'
|
||||||
*/
|
*/
|
||||||
|
/**
|
||||||
|
* @apiDefine MAIL_SENDER_NOT_CONNECTED
|
||||||
|
* @apiError {String} MAIL_SENDER_NOT_CONNECTED The mail sender is not connected.
|
||||||
|
*/
|
||||||
|
|
||||||
class ERRORS {
|
class ERRORS {
|
||||||
const INVALID_CREDENTIALS = 'INVALID_CREDENTIALS';
|
const INVALID_CREDENTIALS = 'INVALID_CREDENTIALS';
|
||||||
@ -317,4 +321,5 @@ class ERRORS {
|
|||||||
const INVALID_CUSTOM_FIELD_OPTION = 'INVALID_CUSTOM_FIELD_OPTION';
|
const INVALID_CUSTOM_FIELD_OPTION = 'INVALID_CUSTOM_FIELD_OPTION';
|
||||||
const UNAVAILABLE_STATS = 'UNAVAILABLE_STATS';
|
const UNAVAILABLE_STATS = 'UNAVAILABLE_STATS';
|
||||||
const INVALID_COLOR = 'INVALID_COLOR';
|
const INVALID_COLOR = 'INVALID_COLOR';
|
||||||
|
const MAIL_SENDER_NOT_CONNECTED = 'MAIL_SENDER_NOT_CONNECTED';
|
||||||
}
|
}
|
||||||
|
@ -25,6 +25,12 @@ class MailTexts {
|
|||||||
'Hi, {{name}}. You have requested to recover your password.',
|
'Hi, {{name}}. You have requested to recover your password.',
|
||||||
'Use this code in {{url}}/recover-password?email={{to}}&token={{token}} or click the button below.',
|
'Use this code in {{url}}/recover-password?email={{to}}&token={{token}} or click the button below.',
|
||||||
],
|
],
|
||||||
|
'USER_INVITE' => [
|
||||||
|
'User invited - OpenSupports',
|
||||||
|
'User invited',
|
||||||
|
'Hi, {{name}}. You have been invited to join our support center.',
|
||||||
|
'Use this code in {{url}}/recover-password?email={{to}}&token={{token}}&invited=true or click the button below to set up your password.'
|
||||||
|
],
|
||||||
'USER_SYSTEM_DISABLED' => [
|
'USER_SYSTEM_DISABLED' => [
|
||||||
'Access system changed - OpenSupports',
|
'Access system changed - OpenSupports',
|
||||||
'Access system changed',
|
'Access system changed',
|
||||||
|
384
server/data/mail-templates/user-invite.html
Executable file
384
server/data/mail-templates/user-invite.html
Executable file
@ -0,0 +1,384 @@
|
|||||||
|
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||||
|
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||||
|
<head>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||||
|
<title>Support Center</title>
|
||||||
|
|
||||||
|
<style type="text/css">
|
||||||
|
/* Take care of image borders and formatting, client hacks */
|
||||||
|
img { max-width: 600px; outline: none; text-decoration: none; -ms-interpolation-mode: bicubic;}
|
||||||
|
a img { border: none; }
|
||||||
|
table { border-collapse: collapse !important;}
|
||||||
|
#outlook a { padding:0; }
|
||||||
|
.ReadMsgBody { width: 100%; }
|
||||||
|
.ExternalClass { width: 100%; }
|
||||||
|
.backgroundTable { margin: 0 auto; padding: 0; width: 100% !important; }
|
||||||
|
table td { border-collapse: collapse; }
|
||||||
|
.ExternalClass * { line-height: 115%; }
|
||||||
|
.container-for-gmail-android { min-width: 600px; }
|
||||||
|
|
||||||
|
|
||||||
|
/* General styling */
|
||||||
|
* {
|
||||||
|
font-family: Helvetica, Arial, sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
-webkit-font-smoothing: antialiased;
|
||||||
|
-webkit-text-size-adjust: none;
|
||||||
|
width: 100% !important;
|
||||||
|
margin: 0 !important;
|
||||||
|
height: 100%;
|
||||||
|
color: #676767;
|
||||||
|
}
|
||||||
|
|
||||||
|
td {
|
||||||
|
font-family: Helvetica, Arial, sans-serif;
|
||||||
|
font-size: 14px;
|
||||||
|
color: #777777;
|
||||||
|
text-align: center;
|
||||||
|
line-height: 21px;
|
||||||
|
}
|
||||||
|
|
||||||
|
a {
|
||||||
|
color: #676767;
|
||||||
|
text-decoration: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pull-left {
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pull-right {
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header-lg,
|
||||||
|
.header-md,
|
||||||
|
.header-sm {
|
||||||
|
font-size: 32px;
|
||||||
|
font-weight: 700;
|
||||||
|
line-height: normal;
|
||||||
|
padding: 35px 0 0;
|
||||||
|
color: #4d4d4d;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header-md {
|
||||||
|
font-size: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header-sm {
|
||||||
|
padding: 5px 0;
|
||||||
|
font-size: 18px;
|
||||||
|
line-height: 1.3;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content-padding {
|
||||||
|
padding: 20px 0 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mobile-header-padding-right {
|
||||||
|
width: 290px;
|
||||||
|
text-align: right;
|
||||||
|
padding-left: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mobile-header-padding-left {
|
||||||
|
width: 290px;
|
||||||
|
text-align: left;
|
||||||
|
padding-left: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.free-text {
|
||||||
|
width: 100% !important;
|
||||||
|
padding: 10px 60px 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.block-rounded {
|
||||||
|
border-radius: 5px;
|
||||||
|
border: 1px solid #e5e5e5;
|
||||||
|
vertical-align: top;
|
||||||
|
}
|
||||||
|
|
||||||
|
.button {
|
||||||
|
padding: 55px 0 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info-block {
|
||||||
|
padding: 0 20px;
|
||||||
|
width: 260px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mini-block-container {
|
||||||
|
padding: 30px 50px;
|
||||||
|
width: 500px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mini-block {
|
||||||
|
background-color: #ffffff;
|
||||||
|
width: 498px;
|
||||||
|
border: 1px solid #cccccc;
|
||||||
|
border-radius: 5px;
|
||||||
|
padding: 60px 75px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.block-rounded {
|
||||||
|
width: 260px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info-img {
|
||||||
|
width: 258px;
|
||||||
|
border-radius: 5px 5px 0 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.force-width-img {
|
||||||
|
width: 480px;
|
||||||
|
height: 1px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.force-width-full {
|
||||||
|
width: 600px;
|
||||||
|
height: 1px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.user-img img {
|
||||||
|
width: 82px;
|
||||||
|
border-radius: 5px;
|
||||||
|
border: 1px solid #cccccc;
|
||||||
|
}
|
||||||
|
|
||||||
|
.user-img {
|
||||||
|
width: 92px;
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.user-msg {
|
||||||
|
width: 236px;
|
||||||
|
font-size: 14px;
|
||||||
|
text-align: left;
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
|
||||||
|
.code-block {
|
||||||
|
padding: 10px 0;
|
||||||
|
border: 1px solid #cccccc;
|
||||||
|
color: #4d4d4d;
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 17px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.force-width-gmail {
|
||||||
|
min-width:600px;
|
||||||
|
height: 0px !important;
|
||||||
|
line-height: 1px !important;
|
||||||
|
font-size: 1px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.button-width {
|
||||||
|
width: 228px;
|
||||||
|
}
|
||||||
|
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<style type="text/css" media="screen">
|
||||||
|
@import url(http://fonts.googleapis.com/css?family=Oxygen:400,700);
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<style type="text/css" media="screen">
|
||||||
|
@media screen {
|
||||||
|
/* Thanks Outlook 2013! */
|
||||||
|
* {
|
||||||
|
font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<style type="text/css" media="only screen and (max-width: 480px)">
|
||||||
|
/* Mobile styles */
|
||||||
|
@media only screen and (max-width: 480px) {
|
||||||
|
|
||||||
|
table[class*="container-for-gmail-android"] {
|
||||||
|
min-width: 290px !important;
|
||||||
|
width: 100% !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
table[class="w320"] {
|
||||||
|
width: 320px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
img[class="force-width-gmail"] {
|
||||||
|
display: none !important;
|
||||||
|
width: 0 !important;
|
||||||
|
height: 0 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
a[class="button-width"],
|
||||||
|
a[class="button-mobile"] {
|
||||||
|
width: 248px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
td[class*="mobile-header-padding-left"] {
|
||||||
|
width: 160px !important;
|
||||||
|
padding-left: 0 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
td[class*="mobile-header-padding-right"] {
|
||||||
|
width: 160px !important;
|
||||||
|
padding-right: 0 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
td[class="header-lg"] {
|
||||||
|
font-size: 24px !important;
|
||||||
|
padding-bottom: 5px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
td[class="header-md"] {
|
||||||
|
font-size: 18px !important;
|
||||||
|
padding-bottom: 5px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
td[class="content-padding"] {
|
||||||
|
padding: 5px 0 30px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
td[class="button"] {
|
||||||
|
padding: 15px 0 5px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
td[class*="free-text"] {
|
||||||
|
padding: 10px 18px 30px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
img[class="force-width-img"],
|
||||||
|
img[class="force-width-full"] {
|
||||||
|
display: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
td[class="info-block"] {
|
||||||
|
display: block !important;
|
||||||
|
width: 280px !important;
|
||||||
|
padding-bottom: 40px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
td[class="info-img"],
|
||||||
|
img[class="info-img"] {
|
||||||
|
width: 278px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
td[class="mini-block-container"] {
|
||||||
|
padding: 8px 20px !important;
|
||||||
|
width: 280px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
td[class="mini-block"] {
|
||||||
|
padding: 20px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
td[class="user-img"] {
|
||||||
|
display: block !important;
|
||||||
|
text-align: center !important;
|
||||||
|
width: 100% !important;
|
||||||
|
padding-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
td[class="user-msg"] {
|
||||||
|
display: block !important;
|
||||||
|
padding-bottom: 20px !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body bgcolor="#f7f7f7">
|
||||||
|
<table align="center" cellpadding="0" cellspacing="0" class="container-for-gmail-android" width="100%">
|
||||||
|
<tr>
|
||||||
|
<td align="left" valign="top" width="100%" style="background-color: #ffffff;">
|
||||||
|
<center>
|
||||||
|
<table cellspacing="0" cellpadding="0" width="100%" bgcolor="#ffffff" style="border-bottom: 1px solid #cccccc">
|
||||||
|
<tr>
|
||||||
|
<td width="100%" height="80" valign="top" style="text-align: center; vertical-align:middle;">
|
||||||
|
<center>
|
||||||
|
<table cellpadding="0" cellspacing="0" width="600" class="w320">
|
||||||
|
<tr>
|
||||||
|
<td style="vertical-align: middle;padding: 15px 0;">
|
||||||
|
<img src="{{IMAGE_HEADER_URL}}" alt="logo">
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</center>
|
||||||
|
<!--[if gte mso 9]>
|
||||||
|
</v:textbox>
|
||||||
|
</v:rect>
|
||||||
|
<![endif]-->
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</center>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td align="center" valign="top" width="100%" style="background-color: #f7f7f7;" class="content-padding">
|
||||||
|
<center>
|
||||||
|
<table cellspacing="0" cellpadding="0" width="600" class="w320">
|
||||||
|
<tr>
|
||||||
|
<td class="header-lg">
|
||||||
|
{{USER_INVITE_MATCH_1}}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="free-text">
|
||||||
|
{{USER_INVITE_MATCH_2}}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="mini-block-container">
|
||||||
|
<table cellspacing="0" cellpadding="0" width="100%" style="border-collapse:separate !important;">
|
||||||
|
<tr>
|
||||||
|
<td class="mini-block">
|
||||||
|
<table cellpadding="0" cellspacing="0" width="100%">
|
||||||
|
<tr>
|
||||||
|
<td style="padding-bottom: 30px;">
|
||||||
|
{{USER_INVITE_MATCH_3}}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="code-block">
|
||||||
|
{{token}}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="button">
|
||||||
|
<div><a class="button-mobile" target="_blank" href="{{url}}/recover-password?email={{to}}&token={{token}}&invited=true"
|
||||||
|
style="background-color:#ff6f6f;border-radius:5px;color:#ffffff;display:inline-block;font-family:'Cabin', Helvetica, Arial, sans-serif;font-size:14px;font-weight:regular;line-height:45px;text-align:center;text-decoration:none;width:155px;-webkit-text-size-adjust:none;mso-hide:all;">Set up your password</a></div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</center>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td align="center" valign="top" width="100%" style="background-color: #ffffff; border-top: 1px solid #e5e5e5; border-bottom: 1px solid #e5e5e5; height: 100px;">
|
||||||
|
<center>
|
||||||
|
<table cellspacing="0" cellpadding="0" width="600" class="w320">
|
||||||
|
<tr>
|
||||||
|
<td style="padding: 25px 0 25px">
|
||||||
|
<strong>OpenSupports</strong><br />
|
||||||
|
Open source ticket system<br />
|
||||||
|
www.opensupports.com<br /><br />
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</center>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</body>
|
||||||
|
</html>
|
@ -19,6 +19,7 @@ class MailTemplate extends DataStore {
|
|||||||
const USER_SIGNUP = 'USER_SIGNUP';
|
const USER_SIGNUP = 'USER_SIGNUP';
|
||||||
const USER_PASSWORD = 'USER_PASSWORD';
|
const USER_PASSWORD = 'USER_PASSWORD';
|
||||||
const PASSWORD_FORGOT = 'PASSWORD_FORGOT';
|
const PASSWORD_FORGOT = 'PASSWORD_FORGOT';
|
||||||
|
const USER_INVITE = 'USER_INVITE';
|
||||||
const USER_SYSTEM_DISABLED = 'USER_SYSTEM_DISABLED';
|
const USER_SYSTEM_DISABLED = 'USER_SYSTEM_DISABLED';
|
||||||
const USER_SYSTEM_ENABLED = 'USER_SYSTEM_ENABLED';
|
const USER_SYSTEM_ENABLED = 'USER_SYSTEM_ENABLED';
|
||||||
const TICKET_CREATED = 'TICKET_CREATED';
|
const TICKET_CREATED = 'TICKET_CREATED';
|
||||||
@ -32,6 +33,7 @@ class MailTemplate extends DataStore {
|
|||||||
'USER_PASSWORD' => 'data/mail-templates/user-edit-password.html',
|
'USER_PASSWORD' => 'data/mail-templates/user-edit-password.html',
|
||||||
'USER_EMAIL' => 'data/mail-templates/user-edit-email.html',
|
'USER_EMAIL' => 'data/mail-templates/user-edit-email.html',
|
||||||
'PASSWORD_FORGOT' => 'data/mail-templates/user-password-forgot.html',
|
'PASSWORD_FORGOT' => 'data/mail-templates/user-password-forgot.html',
|
||||||
|
'USER_INVITE' => 'data/mail-templates/user-invite.html',
|
||||||
'USER_SYSTEM_DISABLED' => 'data/mail-templates/user-system-disabled.html',
|
'USER_SYSTEM_DISABLED' => 'data/mail-templates/user-system-disabled.html',
|
||||||
'USER_SYSTEM_ENABLED' => 'data/mail-templates/user-system-enabled.html',
|
'USER_SYSTEM_ENABLED' => 'data/mail-templates/user-system-enabled.html',
|
||||||
'TICKET_CREATED' => 'data/mail-templates/ticket-created.html',
|
'TICKET_CREATED' => 'data/mail-templates/ticket-created.html',
|
||||||
|
Loading…
x
Reference in New Issue
Block a user