Merge branch 'cc-5709-airtime-analyzer-buy-now-saas' into saas
Conflicts: airtime_mvc/application/controllers/LoginController.php
This commit is contained in:
commit
35e98e468d
36 changed files with 2083 additions and 105 deletions
|
@ -7,13 +7,15 @@ $ccAcl = new Zend_Acl();
|
|||
$ccAcl->addRole(new Zend_Acl_Role('G'))
|
||||
->addRole(new Zend_Acl_Role('H'), 'G')
|
||||
->addRole(new Zend_Acl_Role('P'), 'H')
|
||||
->addRole(new Zend_Acl_Role('A'), 'P');
|
||||
->addRole(new Zend_Acl_Role('A'), 'P')
|
||||
->addRole(new Zend_Acl_Role('S'), 'A');
|
||||
|
||||
$ccAcl->add(new Zend_Acl_Resource('library'))
|
||||
->add(new Zend_Acl_Resource('index'))
|
||||
->add(new Zend_Acl_Resource('user'))
|
||||
->add(new Zend_Acl_Resource('error'))
|
||||
->add(new Zend_Acl_Resource('login'))
|
||||
->add(new Zend_Acl_Resource('whmcs-login'))
|
||||
->add(new Zend_Acl_Resource('playlist'))
|
||||
->add(new Zend_Acl_Resource('plupload'))
|
||||
->add(new Zend_Acl_Resource('schedule'))
|
||||
|
@ -29,11 +31,13 @@ $ccAcl->add(new Zend_Acl_Resource('library'))
|
|||
->add(new Zend_Acl_Resource('audiopreview'))
|
||||
->add(new Zend_Acl_Resource('webstream'))
|
||||
->add(new Zend_Acl_Resource('locale'))
|
||||
->add(new Zend_Acl_Resource('upgrade'));
|
||||
->add(new Zend_Acl_Resource('upgrade'))
|
||||
->add(new Zend_Acl_Resource('billing'));
|
||||
|
||||
/** Creating permissions */
|
||||
$ccAcl->allow('G', 'index')
|
||||
->allow('G', 'login')
|
||||
->allow('G', 'whmcs-login')
|
||||
->allow('G', 'error')
|
||||
->allow('G', 'user', 'edit-user')
|
||||
->allow('G', 'showbuilder')
|
||||
|
@ -54,7 +58,8 @@ $ccAcl->allow('G', 'index')
|
|||
->allow('A', 'listenerstat')
|
||||
->allow('A', 'user')
|
||||
->allow('A', 'systemstatus')
|
||||
->allow('A', 'preference');
|
||||
->allow('A', 'preference')
|
||||
->allow('S', 'billing');
|
||||
|
||||
|
||||
$aclPlugin = new Zend_Controller_Plugin_Acl($ccAcl);
|
||||
|
|
|
@ -41,6 +41,7 @@ define('UI_MDATA_VALUE_FORMAT_STREAM' , 'live stream');
|
|||
//User types
|
||||
define('UTYPE_HOST' , 'H');
|
||||
define('UTYPE_ADMIN' , 'A');
|
||||
define('UTYPE_SUPERADMIN' , 'S');
|
||||
define('UTYPE_GUEST' , 'G');
|
||||
define('UTYPE_PROGRAM_MANAGER' , 'P');
|
||||
|
||||
|
@ -63,3 +64,9 @@ define('UI_BLOCK_SESSNAME', 'BLOCK');*/
|
|||
define('SOUNDCLOUD_NOT_UPLOADED_YET' , -1);
|
||||
define('SOUNDCLOUD_PROGRESS' , -2);
|
||||
define('SOUNDCLOUD_ERROR' , -3);
|
||||
|
||||
|
||||
//WHMCS integration
|
||||
define("WHMCS_API_URL", "https://account.sourcefabric.com/includes/api.php");
|
||||
define("SUBDOMAIN_WHMCS_CUSTOM_FIELD_NAME", "Choose your domain");
|
||||
|
||||
|
|
|
@ -134,6 +134,34 @@ $pages = array(
|
|||
'resource' => 'dashboard'
|
||||
)
|
||||
)
|
||||
),
|
||||
array(
|
||||
'label' => _('Billing'),
|
||||
'uri' => '#',
|
||||
'resource' => 'billing',
|
||||
'pages' => array(
|
||||
array(
|
||||
'label' => _('Account Details'),
|
||||
'module' => 'default',
|
||||
'controller' => 'billing',
|
||||
'action' => 'client',
|
||||
'resource' => 'billing'
|
||||
),
|
||||
array(
|
||||
'label' => _('Account Plans'),
|
||||
'module' => 'default',
|
||||
'controller' => 'billing',
|
||||
'action' => 'upgrade',
|
||||
'resource' => 'billing'
|
||||
),
|
||||
array(
|
||||
'label' => _('View Invoices'),
|
||||
'module' => 'default',
|
||||
'controller' => 'billing',
|
||||
'action' => 'invoices',
|
||||
'resource' => 'billing'
|
||||
)
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
|
|
558
airtime_mvc/application/controllers/BillingController.php
Normal file
558
airtime_mvc/application/controllers/BillingController.php
Normal file
|
@ -0,0 +1,558 @@
|
|||
<?php
|
||||
|
||||
define('VAT_RATE', 19.00);
|
||||
|
||||
class BillingController extends Zend_Controller_Action {
|
||||
|
||||
public function init()
|
||||
{
|
||||
//Two of the actions in this controller return JSON because they're used for AJAX:
|
||||
$ajaxContext = $this->_helper->getHelper('AjaxContext');
|
||||
$ajaxContext->addActionContext('vat-validator', 'json')
|
||||
->addActionContext('is-country-in-eu', 'json')
|
||||
->initContext();
|
||||
}
|
||||
|
||||
public function indexAction()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public function upgradeAction()
|
||||
{
|
||||
$CC_CONFIG = Config::getConfig();
|
||||
$baseUrl = Application_Common_OsPath::getBaseDir();
|
||||
$this->view->headLink()->appendStylesheet($baseUrl.'css/billing.css?'.$CC_CONFIG['airtime_version']);
|
||||
BillingController::ensureClientIdIsValid();
|
||||
|
||||
$request = $this->getRequest();
|
||||
$form = new Application_Form_BillingUpgradeDowngrade();
|
||||
if ($request->isPost()) {
|
||||
|
||||
/*
|
||||
* TODO: determine if VAT shoould be charged on the invoice or not.
|
||||
* We'll need to check if a VAT number was supplied in the form and if so,
|
||||
* validate it somehow. We'll also need to make sure the country given is
|
||||
* in the EU
|
||||
*/
|
||||
|
||||
$formData = $request->getPost();
|
||||
if ($form->isValid($formData)) {
|
||||
$credentials = self::getAPICredentials();
|
||||
|
||||
if (in_array("7", $formData["customfields"])) {
|
||||
$apply_vat = BillingController::checkIfVatShouldBeApplied($formData["customfields"]["7"], $formData["country"]);
|
||||
} else {
|
||||
$apply_vat = false;
|
||||
}
|
||||
|
||||
$postfields = array();
|
||||
$postfields["username"] = $credentials["username"];
|
||||
$postfields["password"] = md5($credentials["password"]);
|
||||
$postfields["action"] = "upgradeproduct";
|
||||
$postfields["clientid"] = Application_Model_Preference::GetClientId();
|
||||
|
||||
$postfields["serviceid"] = self::getClientInstanceId();
|
||||
$postfields["type"] = "product";
|
||||
$postfields["newproductid"] = $formData["newproductid"];
|
||||
$postfields["newproductbillingcycle"] = $formData["newproductbillingcycle"];
|
||||
$postfields["paymentmethod"] = $formData["paymentmethod"];
|
||||
$postfields["responsetype"] = "json";
|
||||
|
||||
$upgrade_query_string = "";
|
||||
foreach ($postfields AS $k=>$v) $upgrade_query_string .= "$k=".urlencode($v)."&";
|
||||
|
||||
//update client info
|
||||
|
||||
$clientfields = array();
|
||||
$clientfields["username"] = $credentials["username"];
|
||||
$clientfields["password"] = md5($credentials["password"]);
|
||||
$clientfields["action"] = "updateclient";
|
||||
$clientfields["clientid"] = Application_Model_Preference::GetClientId();
|
||||
$clientfields["customfields"] = base64_encode(serialize($formData["customfields"]));
|
||||
unset($formData["customfields"]);
|
||||
$clientfields["responsetype"] = "json";
|
||||
unset($formData["newproductid"]);
|
||||
unset($formData["newproductbillingcycle"]);
|
||||
unset($formData["paymentmethod"]);
|
||||
unset($formData["action"]);
|
||||
$clientfields = array_merge($clientfields, $formData);
|
||||
unset($clientfields["password2verify"]);
|
||||
unset($clientfields["submit"]);
|
||||
$client_query_string = "";
|
||||
foreach ($clientfields AS $k=>$v) $client_query_string .= "$k=".urlencode($v)."&";
|
||||
|
||||
$result = $this->makeRequest($credentials["url"], $client_query_string);
|
||||
Logging::info($result);
|
||||
if ($result["result"] == "error") {
|
||||
$this->setErrorMessage();
|
||||
$this->view->form = $form;
|
||||
} else {
|
||||
$result = $this->makeRequest($credentials["url"], $upgrade_query_string);
|
||||
if ($result["result"] == "error") {
|
||||
Logging::info($_SERVER['HTTP_HOST']." - Account upgrade failed. - ".$result["message"]);
|
||||
$this->setErrorMessage();
|
||||
$this->view->form = $form;
|
||||
} else {
|
||||
if ($apply_vat) {
|
||||
$this->addVatToInvoice($result["invoiceid"]);
|
||||
}
|
||||
self::viewInvoice($result["invoiceid"]);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$this->view->form = $form;
|
||||
}
|
||||
} else {
|
||||
$this->view->form = $form;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public function isCountryInEuAction()
|
||||
{
|
||||
// Disable the view and the layout
|
||||
$this->view->layout()->disableLayout();
|
||||
$this->_helper->viewRenderer->setNoRender(true);
|
||||
|
||||
$request = $this->getRequest();
|
||||
if (!$request->isPost()) {
|
||||
throw new Exception("Must POST data to isCountryInEuAction.");
|
||||
}
|
||||
$formData = $request->getPost();
|
||||
|
||||
//Set the return JSON value
|
||||
$this->_helper->json(array("result"=>BillingController::isCountryInEU($formData["country"])));
|
||||
}
|
||||
|
||||
public function vatValidatorAction()
|
||||
{
|
||||
// Disable the view and the layout
|
||||
$this->view->layout()->disableLayout();
|
||||
$this->_helper->viewRenderer->setNoRender(true);
|
||||
|
||||
$request = $this->getRequest();
|
||||
if (!$request->isPost()) {
|
||||
throw new Exception("Must POST data to vatValidatorAction.");
|
||||
}
|
||||
$formData = $request->getPost();
|
||||
|
||||
$vatNumber = trim($formData["vatnumber"]);
|
||||
if (empty($vatNumber)) {
|
||||
$this->_helper->json(array("result"=>false));
|
||||
}
|
||||
|
||||
//Set the return JSON value
|
||||
$this->_helper->json(array("result"=>BillingController::checkIfVatShouldBeApplied($vatNumber, $formData["country"])));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return True if VAT should be applied to the order, false otherwise.
|
||||
*/
|
||||
private static function checkIfVatShouldBeApplied($vatNumber, $countryCode)
|
||||
{
|
||||
if ($countryCode === 'UK') {
|
||||
$countryCode = 'GB'; //VIES database has it as GB
|
||||
}
|
||||
//We don't charge you VAT if you're not in the EU
|
||||
if (!BillingController::isCountryInEU($countryCode))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
//So by here, we know you're in the EU.
|
||||
|
||||
//No VAT number? Then we charge you VAT.
|
||||
if (empty($vatNumber)) {
|
||||
return true;
|
||||
}
|
||||
//Check if VAT number is valid
|
||||
return BillingController::validateVATNumber($vatNumber, $countryCode);
|
||||
}
|
||||
|
||||
private static function isCountryInEU($countryCode)
|
||||
{
|
||||
$euCountryCodes = array('BE', 'BG', 'CZ', 'DK', 'DE', 'EE', 'IE', 'EL', 'ES', 'FR',
|
||||
'HR', 'IT', 'CY', 'LV', 'LT', 'LU', 'HU', 'MT', 'NL', 'AT',
|
||||
'PL', 'PT', 'RO', 'SI', 'SK', 'FI', 'SE', 'UK', 'GB');
|
||||
|
||||
if (!in_array($countryCode, $euCountryCodes)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if an EU VAT number is valid, using the EU VIES validation web API.
|
||||
*
|
||||
* @param string $vatNumber - A VAT identifier (number), with or without the two letter country code at the
|
||||
* start (either one works) .
|
||||
* @param string $countryCode - A two letter country code
|
||||
* @return boolean true if the VAT number is valid, false otherwise.
|
||||
*/
|
||||
private static function validateVATNumber($vatNumber, $countryCode)
|
||||
{
|
||||
$vatNumber = str_replace(array(' ', '.', '-', ',', ', '), '', trim($vatNumber));
|
||||
|
||||
//If the first two letters are a country code, use that as the country code and remove those letters.
|
||||
$firstTwoCharacters = substr($vatNumber, 0, 2);
|
||||
if (preg_match("/[a-zA-Z][a-zA-Z]/", $firstTwoCharacters) === 1) {
|
||||
$countryCode = strtoupper($firstTwoCharacters); //The country code from the VAT number overrides your country.
|
||||
$vatNumber = substr($vatNumber, 2);
|
||||
}
|
||||
$client = new SoapClient("http://ec.europa.eu/taxation_customs/vies/checkVatService.wsdl");
|
||||
|
||||
if($client){
|
||||
$params = array('countryCode' => $countryCode, 'vatNumber' => $vatNumber);
|
||||
try{
|
||||
$r = $client->checkVat($params);
|
||||
if($r->valid == true){
|
||||
// VAT-ID is valid
|
||||
return true;
|
||||
} else {
|
||||
// VAT-ID is NOT valid
|
||||
return false;
|
||||
}
|
||||
} catch(SoapFault $e) {
|
||||
Logging::error('VIES EU VAT validation error: '.$e->faultstring);
|
||||
if ($e->faultstring == "INVALID_INPUT") {
|
||||
return false;
|
||||
}
|
||||
//If there was another error with the VAT validation service, we allow
|
||||
//the VAT number to pass. (eg. SERVER_BUSY, MS_UNAVAILABLE, TIMEOUT, SERVICE_UNAVAILABLE)
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
// Connection to host not possible, europe.eu down?
|
||||
Logging::error('VIES EU VAT validation error: Host unreachable');
|
||||
//If there was an error with the VAT validation service, we allow
|
||||
//the VAT number to pass.
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
private function addVatToInvoice($invoice_id)
|
||||
{
|
||||
$credentials = self::getAPICredentials();
|
||||
|
||||
//First we need to get the invoice details: sub total, and total
|
||||
//so we can calcuate the amount of VAT to add
|
||||
$invoicefields = array();
|
||||
$invoicefields["username"] = $credentials["username"];
|
||||
$invoicefields["password"] = md5($credentials["password"]);
|
||||
$invoicefields["action"] = "getinvoice";
|
||||
$invoicefields["invoiceid"] = $invoice_id;
|
||||
$invoicefields["responsetype"] = "json";
|
||||
|
||||
$invoice_query_string = "";
|
||||
foreach ($invoicefields as $k=>$v) $invoice_query_string .= "$k=".urlencode($v)."&";
|
||||
|
||||
//TODO: error checking
|
||||
$result = $this->makeRequest($credentials["url"], $invoice_query_string);
|
||||
|
||||
$vat_amount = $result["subtotal"] * (VAT_RATE/100);
|
||||
$invoice_total = $result["total"] + $vat_amount;
|
||||
|
||||
//Second, update the invoice with the VAT amount and updated total
|
||||
$postfields = array();
|
||||
$postfields["username"] = $credentials["username"];
|
||||
$postfields["password"] = md5($credentials["password"]);
|
||||
$postfields["action"] = "updateinvoice";
|
||||
$postfields["invoiceid"] = $invoice_id;
|
||||
$postfields["tax"] = "$vat_amount";
|
||||
$postfields["taxrate"] = strval(VAT_RATE);
|
||||
$postfields["total"] = "$invoice_total";
|
||||
$postfields["responsetype"] = "json";
|
||||
|
||||
$query_string = "";
|
||||
foreach ($postfields as $k=>$v) $query_string .= "$k=".urlencode($v)."&";
|
||||
|
||||
//TODO: error checking
|
||||
$result = $this->makeRequest($credentials["url"], $query_string);
|
||||
}
|
||||
|
||||
private function setErrorMessage($msg=null)
|
||||
{
|
||||
if (!is_null($msg)) {
|
||||
$this->view->errorMessage = $msg;
|
||||
} else {
|
||||
$this->view->errorMessage = "An error occurred and we could not update your account. Please contact support for help.";
|
||||
}
|
||||
}
|
||||
|
||||
private function setSuccessMessage($msg=null)
|
||||
{
|
||||
if (!is_null($msg)) {
|
||||
$this->view->successMessage = $msg;
|
||||
} else {
|
||||
$this->view->successMessage = "Your account has been updated.";
|
||||
}
|
||||
}
|
||||
|
||||
private static function getAPICredentials()
|
||||
{
|
||||
return array(
|
||||
"username" => $_SERVER["WHMCS_USERNAME"],
|
||||
"password" => $_SERVER["WHMCS_PASSWORD"],
|
||||
"url" => "https://account.sourcefabric.com/includes/api.php?accesskey=".$_SERVER["WHMCS_ACCESS_KEY"],
|
||||
);
|
||||
}
|
||||
|
||||
private static function viewInvoice($invoice_id)
|
||||
{
|
||||
$whmcsurl = "https://account.sourcefabric.com/dologin.php";
|
||||
$autoauthkey = $_SERVER["WHMCS_AUTOAUTH_KEY"];
|
||||
$timestamp = time(); //whmcs timezone?
|
||||
$client = self::getClientDetails();
|
||||
$email = $client["email"];
|
||||
$hash = sha1($email.$timestamp.$autoauthkey);
|
||||
$goto = "viewinvoice.php?id=".$invoice_id;
|
||||
header("Location: ".$whmcsurl."?email=$email×tamp=$timestamp&hash=$hash&goto=$goto");
|
||||
}
|
||||
|
||||
public function clientAction()
|
||||
{
|
||||
$CC_CONFIG = Config::getConfig();
|
||||
$baseUrl = Application_Common_OsPath::getBaseDir();
|
||||
$this->view->headLink()->appendStylesheet($baseUrl.'css/billing.css?'.$CC_CONFIG['airtime_version']);
|
||||
|
||||
$request = $this->getRequest();
|
||||
$form = new Application_Form_BillingClient();
|
||||
BillingController::ensureClientIdIsValid();
|
||||
if ($request->isPost()) {
|
||||
$formData = $request->getPost();
|
||||
if ($form->isValid($formData)) {
|
||||
|
||||
$credentials = self::getAPICredentials();
|
||||
|
||||
$postfields = array();
|
||||
$postfields["username"] = $credentials["username"];
|
||||
$postfields["password"] = md5($credentials["password"]);
|
||||
$postfields["action"] = "updateclient";
|
||||
|
||||
$postfields["customfields"] = base64_encode(serialize($formData["customfields"]));
|
||||
unset($formData["customfields"]);
|
||||
|
||||
$postfields["clientid"] = Application_Model_Preference::GetClientId();
|
||||
$postfields["responsetype"] = "json";
|
||||
$postfields = array_merge($postfields, $formData);
|
||||
unset($postfields["password2verify"]);
|
||||
unset($postfields["submit"]);
|
||||
|
||||
$query_string = "";
|
||||
foreach ($postfields AS $k=>$v) $query_string .= "$k=".urlencode($v)."&";
|
||||
|
||||
$result = $this->makeRequest($credentials["url"], $query_string);
|
||||
|
||||
if ($result["result"] == "error") {
|
||||
$this->setErrorMessage();
|
||||
} else {
|
||||
$form = new Application_Form_BillingClient();
|
||||
$this->setSuccessMessage();
|
||||
}
|
||||
|
||||
$this->view->form = $form;
|
||||
} else {
|
||||
$this->view->form = $form;
|
||||
}
|
||||
} else {
|
||||
$this->view->form = $form;
|
||||
}
|
||||
}
|
||||
|
||||
public function invoicesAction()
|
||||
{
|
||||
$CC_CONFIG = Config::getConfig();
|
||||
$baseUrl = Application_Common_OsPath::getBaseDir();
|
||||
$this->view->headLink()->appendStylesheet($baseUrl.'css/billing.css?'.$CC_CONFIG['airtime_version']);
|
||||
|
||||
BillingController::ensureClientIdIsValid();
|
||||
$credentials = self::getAPICredentials();
|
||||
|
||||
$postfields = array();
|
||||
$postfields["username"] = $credentials["username"];
|
||||
$postfields["password"] = md5($credentials["password"]);
|
||||
$postfields["action"] = "getinvoices";
|
||||
$postfields["responsetype"] = "json";
|
||||
$postfields["userid"] = Application_Model_Preference::GetClientId();
|
||||
|
||||
$query_string = "";
|
||||
foreach ($postfields AS $k=>$v) $query_string .= "$k=".urlencode($v)."&";
|
||||
|
||||
$result = self::makeRequest($credentials["url"], $query_string);
|
||||
|
||||
$this->view->invoices = $result["invoices"]["invoice"];
|
||||
}
|
||||
|
||||
public function invoiceAction()
|
||||
{
|
||||
BillingController::ensureClientIdIsValid();
|
||||
$request = $this->getRequest();
|
||||
$invoice_id = $request->getParam('invoiceid');
|
||||
self::viewInvoice($invoice_id);
|
||||
}
|
||||
|
||||
/** Get the Airtime instance ID of the instance the customer is currently viewing. */
|
||||
private static function getClientInstanceId()
|
||||
{
|
||||
$currentProduct = BillingController::getClientCurrentAirtimeProduct();
|
||||
return $currentProduct["id"];
|
||||
}
|
||||
|
||||
public static function getProducts()
|
||||
{
|
||||
//Making this static to cache the products during a single HTTP request.
|
||||
//This saves us roundtrips to WHMCS if getProducts() is called multiple times.
|
||||
static $result = array();
|
||||
if (!empty($result))
|
||||
{
|
||||
return $result["products"]["product"];
|
||||
}
|
||||
|
||||
$credentials = self::getAPICredentials();
|
||||
|
||||
$postfields = array();
|
||||
$postfields["username"] = $credentials["username"];
|
||||
$postfields["password"] = md5($credentials["password"]);
|
||||
$postfields["action"] = "getproducts";
|
||||
$postfields["responsetype"] = "json";
|
||||
//gid is the Airtime product group id on whmcs
|
||||
$postfields["gid"] = "15";
|
||||
|
||||
$query_string = "";
|
||||
foreach ($postfields AS $k=>$v) $query_string .= "$k=".urlencode($v)."&";
|
||||
|
||||
$result = self::makeRequest($credentials["url"], $query_string);
|
||||
return $result["products"]["product"];
|
||||
}
|
||||
|
||||
public static function getProductPricesAndTypes()
|
||||
{
|
||||
$products = BillingController::getProducts();
|
||||
|
||||
foreach ($products as $k => $p) {
|
||||
$productPrices[$p["name"]] = array(
|
||||
"monthly" => $p["pricing"]["USD"]["monthly"],
|
||||
"annually" => $p["pricing"]["USD"]["annually"]
|
||||
);
|
||||
$productTypes[$p["pid"]] = $p["name"] . " ($" . $productPrices[$p['name']]['monthly'] . "/mo)";
|
||||
}
|
||||
return array($productPrices, $productTypes);
|
||||
}
|
||||
|
||||
/** Get the plan (or product in WHMCS lingo) that the customer is currently on.
|
||||
* @return An associative array containing the fields for the product
|
||||
* */
|
||||
public static function getClientCurrentAirtimeProduct()
|
||||
{
|
||||
static $airtimeProduct = null;
|
||||
//Ghetto caching to avoid multiple round trips to WHMCS
|
||||
if ($airtimeProduct) {
|
||||
return $airtimeProduct;
|
||||
}
|
||||
$credentials = self::getAPICredentials();
|
||||
|
||||
$postfields = array();
|
||||
$postfields["username"] = $credentials["username"];
|
||||
$postfields["password"] = md5($credentials["password"]);
|
||||
$postfields["action"] = "getclientsproducts";
|
||||
$postfields["responsetype"] = "json";
|
||||
$postfields["clientid"] = Application_Model_Preference::GetClientId();
|
||||
|
||||
$query_string = "";
|
||||
foreach ($postfields AS $k=>$v) $query_string .= "$k=".urlencode($v)."&";
|
||||
|
||||
$result = self::makeRequest($credentials["url"], $query_string);
|
||||
|
||||
//XXX: Debugging / local testing
|
||||
if ($_SERVER['SERVER_NAME'] == "airtime.localhost") {
|
||||
$_SERVER['SERVER_NAME'] = "bananas.airtime.pro";
|
||||
}
|
||||
|
||||
//This code must run on airtime.pro for it to work... it's trying to match
|
||||
//the server's hostname with the client subdomain. Once it finds a match
|
||||
//between the product and the server's hostname/subdomain, then it
|
||||
//returns the ID of that product (aka. the service ID of an Airtime instance)
|
||||
foreach ($result["products"] as $product)
|
||||
{
|
||||
if (strpos($product[0]["groupname"], "Airtime") === FALSE)
|
||||
{
|
||||
//Ignore non-Airtime products
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ($product[0]["status"] === "Active") {
|
||||
$airtimeProduct = $product[0];
|
||||
$subdomain = '';
|
||||
|
||||
foreach ($airtimeProduct['customfields']['customfield'] as $customField) {
|
||||
if ($customField['name'] === SUBDOMAIN_WHMCS_CUSTOM_FIELD_NAME) {
|
||||
$subdomain = $customField['value'];
|
||||
if (($subdomain . ".airtime.pro") === $_SERVER['SERVER_NAME']) {
|
||||
return $airtimeProduct;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
throw new Exception("Unable to match subdomain to a service ID");
|
||||
}
|
||||
|
||||
public static function getClientDetails()
|
||||
{
|
||||
try {
|
||||
$credentials = self::getAPICredentials();
|
||||
|
||||
$postfields = array();
|
||||
$postfields["username"] = $credentials["username"];
|
||||
$postfields["password"] = md5($credentials["password"]);
|
||||
$postfields["action"] = "getclientsdetails";
|
||||
$postfields["stats"] = true;
|
||||
$postfields["clientid"] = Application_Model_Preference::GetClientId();
|
||||
$postfields["responsetype"] = "json";
|
||||
|
||||
$query_string = "";
|
||||
foreach ($postfields AS $k=>$v) $query_string .= "$k=".urlencode($v)."&";
|
||||
|
||||
$arr = self::makeRequest($credentials["url"], $query_string);
|
||||
return $arr["client"];
|
||||
} catch (Exception $e) {
|
||||
Logging::info($e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private static function makeRequest($url, $query_string) {
|
||||
try {
|
||||
$ch = curl_init();
|
||||
curl_setopt($ch, CURLOPT_URL, $url);
|
||||
curl_setopt($ch, CURLOPT_POST, 1);
|
||||
curl_setopt($ch, CURLOPT_TIMEOUT, 5); //Aggressive 5 second timeout
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
|
||||
curl_setopt($ch, CURLOPT_POSTFIELDS, $query_string);
|
||||
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
|
||||
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
|
||||
$jsondata = curl_exec($ch);
|
||||
if (curl_error($ch)) {
|
||||
//die("Connection Error: ".curl_errno($ch).' - '.curl_error($ch));
|
||||
throw new Exception("WHMCS server down or invalid request.");
|
||||
}
|
||||
curl_close($ch);
|
||||
|
||||
return json_decode($jsondata, true);
|
||||
} catch (Exception $e) {
|
||||
Logging::info($e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private static function ensureClientIdIsValid()
|
||||
{
|
||||
if (Application_Model_Preference::GetClientId() == null)
|
||||
{
|
||||
throw new Exception("Invalid client ID: " . Application_Model_Preference::GetClientId());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -83,7 +83,7 @@ class LibraryController extends Zend_Controller_Action
|
|||
$obj = new $objInfo['className']($obj_sess->id);
|
||||
$userInfo = Zend_Auth::getInstance()->getStorage()->read();
|
||||
$user = new Application_Model_User($userInfo->id);
|
||||
$isAdminOrPM = $user->isUserType(array(UTYPE_ADMIN, UTYPE_PROGRAM_MANAGER));
|
||||
$isAdminOrPM = $user->isUserType(array(UTYPE_SUPERADMIN, UTYPE_ADMIN, UTYPE_PROGRAM_MANAGER));
|
||||
|
||||
if ($isAdminOrPM || $obj->getCreatorId() == $userInfo->id) {
|
||||
$this->view->obj = $obj;
|
||||
|
@ -186,7 +186,7 @@ class LibraryController extends Zend_Controller_Action
|
|||
//Open a jPlayer window and play the audio clip.
|
||||
$menu["play"] = array("name"=> _("Preview"), "icon" => "play", "disabled" => false);
|
||||
|
||||
$isAdminOrPM = $user->isUserType(array(UTYPE_ADMIN, UTYPE_PROGRAM_MANAGER));
|
||||
$isAdminOrPM = $user->isUserType(array(UTYPE_SUPERADMIN, UTYPE_ADMIN, UTYPE_PROGRAM_MANAGER));
|
||||
|
||||
$obj_sess = new Zend_Session_Namespace(UI_PLAYLISTCONTROLLER_OBJ_SESSNAME);
|
||||
|
||||
|
@ -302,7 +302,7 @@ class LibraryController extends Zend_Controller_Action
|
|||
$mediaItems = $this->_getParam('media', null);
|
||||
|
||||
$user = Application_Model_User::getCurrentUser();
|
||||
//$isAdminOrPM = $user->isUserType(array(UTYPE_ADMIN, UTYPE_PROGRAM_MANAGER));
|
||||
//$isAdminOrPM = $user->isUserType(array(UTYPE_SUPERADMIN, UTYPE_ADMIN, UTYPE_PROGRAM_MANAGER));
|
||||
|
||||
$files = array();
|
||||
$playlists = array();
|
||||
|
@ -418,7 +418,7 @@ class LibraryController extends Zend_Controller_Action
|
|||
public function editFileMdAction()
|
||||
{
|
||||
$user = Application_Model_User::getCurrentUser();
|
||||
$isAdminOrPM = $user->isUserType(array(UTYPE_ADMIN, UTYPE_PROGRAM_MANAGER));
|
||||
$isAdminOrPM = $user->isUserType(array(UTYPE_SUPERADMIN, UTYPE_ADMIN, UTYPE_PROGRAM_MANAGER));
|
||||
|
||||
$request = $this->getRequest();
|
||||
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
<?php
|
||||
|
||||
require_once('WhmcsLoginController.php');
|
||||
|
||||
class LoginController extends Zend_Controller_Action
|
||||
{
|
||||
|
||||
|
@ -13,6 +15,24 @@ class LoginController extends Zend_Controller_Action
|
|||
|
||||
$request = $this->getRequest();
|
||||
|
||||
//Allow AJAX requests from www.airtime.pro. We use this to automatically login users
|
||||
//after they sign up from the microsite.
|
||||
//Chrome sends the Origin header for all requests, so we whitelist the webserver's hostname as well.
|
||||
$response = $this->getResponse()->setHeader('Access-Control-Allow-Origin', '*');
|
||||
$origin = $request->getHeader('Origin');
|
||||
if (($origin != "") &&
|
||||
(!in_array($origin,
|
||||
array("http://www.airtime.pro",
|
||||
"https://www.airtime.pro",
|
||||
"http://" . $_SERVER['SERVER_NAME'],
|
||||
"https://" . $_SERVER['SERVER_NAME']
|
||||
))
|
||||
))
|
||||
{
|
||||
//Don't allow CORS from other domains to prevent XSS.
|
||||
throw new Zend_Controller_Action_Exception('Forbidden', 403);
|
||||
}
|
||||
|
||||
Application_Model_Locale::configureLocalization($request->getcookie('airtime_locale', 'en_CA'));
|
||||
$auth = Zend_Auth::getInstance();
|
||||
|
||||
|
@ -71,12 +91,23 @@ class LoginController extends Zend_Controller_Action
|
|||
|
||||
$this->_redirect('Showbuilder');
|
||||
} else {
|
||||
|
||||
$message = _("Wrong username or password provided. Please try again.");
|
||||
Application_Model_Subjects::increaseLoginAttempts($username);
|
||||
Application_Model_LoginAttempts::increaseAttempts($_SERVER['REMOTE_ADDR']);
|
||||
$form = new Application_Form_Login();
|
||||
$error = true;
|
||||
$email = $form->getValue('username');
|
||||
$authAdapter = new WHMCS_Auth_Adapter("admin", $email, $password);
|
||||
$auth = Zend_Auth::getInstance();
|
||||
$result = $auth->authenticate($authAdapter);
|
||||
if ($result->isValid()) {
|
||||
//set the user locale in case user changed it in when logging in
|
||||
Application_Model_Preference::SetUserLocale($locale);
|
||||
|
||||
$this->_redirect('Showbuilder');
|
||||
}
|
||||
else {
|
||||
$message = _("Wrong username or password provided. Please try again.");
|
||||
Application_Model_Subjects::increaseLoginAttempts($username);
|
||||
Application_Model_LoginAttempts::increaseAttempts($_SERVER['REMOTE_ADDR']);
|
||||
$form = new Application_Form_Login();
|
||||
$error = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -104,7 +104,7 @@ class ScheduleController extends Zend_Controller_Action
|
|||
$this->createShowFormAction(true);
|
||||
|
||||
$user = Application_Model_User::getCurrentUser();
|
||||
if ($user->isUserType(array(UTYPE_ADMIN, UTYPE_PROGRAM_MANAGER))) {
|
||||
if ($user->isUserType(array(UTYPE_SUPERADMIN, UTYPE_ADMIN, UTYPE_PROGRAM_MANAGER))) {
|
||||
$this->view->preloadShowForm = true;
|
||||
}
|
||||
|
||||
|
@ -133,7 +133,7 @@ class ScheduleController extends Zend_Controller_Action
|
|||
{
|
||||
$userInfo = Zend_Auth::getInstance()->getStorage()->read();
|
||||
$user = new Application_Model_User($userInfo->id);
|
||||
$editable = $user->isUserType(array(UTYPE_ADMIN, UTYPE_PROGRAM_MANAGER));
|
||||
$editable = $user->isUserType(array(UTYPE_SUPERADMIN, UTYPE_ADMIN, UTYPE_PROGRAM_MANAGER));
|
||||
|
||||
$calendar_interval = Application_Model_Preference::GetCalendarTimeScale();
|
||||
Logging::info($calendar_interval);
|
||||
|
@ -209,7 +209,7 @@ class ScheduleController extends Zend_Controller_Action
|
|||
$userInfo = Zend_Auth::getInstance()->getStorage()->read();
|
||||
$user = new Application_Model_User($userInfo->id);
|
||||
|
||||
if ($user->isUserType(array(UTYPE_ADMIN, UTYPE_PROGRAM_MANAGER))) {
|
||||
if ($user->isUserType(array(UTYPE_SUPERADMIN, UTYPE_ADMIN, UTYPE_PROGRAM_MANAGER))) {
|
||||
try {
|
||||
$show = new Application_Model_Show($showId);
|
||||
} catch (Exception $e) {
|
||||
|
@ -654,7 +654,7 @@ class ScheduleController extends Zend_Controller_Action
|
|||
|
||||
$user = Application_Model_User::getCurrentUser();
|
||||
|
||||
if ($user->isUserType(array(UTYPE_ADMIN, UTYPE_PROGRAM_MANAGER))) {
|
||||
if ($user->isUserType(array(UTYPE_SUPERADMIN, UTYPE_ADMIN, UTYPE_PROGRAM_MANAGER))) {
|
||||
$id = $this->_getParam('id');
|
||||
|
||||
try {
|
||||
|
|
|
@ -1,71 +1,51 @@
|
|||
<?php
|
||||
|
||||
require_once("Upgrades.php");
|
||||
|
||||
class UpgradeController extends Zend_Controller_Action
|
||||
{
|
||||
public function indexAction()
|
||||
{
|
||||
$airtime_upgrade_version = '2.5.3';
|
||||
|
||||
$this->view->layout()->disableLayout();
|
||||
$this->_helper->viewRenderer->setNoRender(true);
|
||||
|
||||
if (!$this->verifyAuth()) {
|
||||
return;
|
||||
}
|
||||
|
||||
$upgraders = array();
|
||||
array_push($upgraders, new AirtimeUpgrader253());
|
||||
array_push($upgraders, new AirtimeUpgrader254());
|
||||
|
||||
if (!$this->verifyAirtimeVersion()) {
|
||||
return;
|
||||
}
|
||||
|
||||
$con = Propel::getConnection();
|
||||
$con->beginTransaction();
|
||||
try {
|
||||
//Disable Airtime UI
|
||||
//create a temporary maintenance notification file
|
||||
//when this file is on the server, zend framework redirects all
|
||||
//requests to the maintenance page and sets a 503 response code
|
||||
|
||||
$maintenanceFile = isset($_SERVER['AIRTIME_BASE']) ? $_SERVER['AIRTIME_BASE']."maintenance.txt" : "/tmp/maintenance.txt";
|
||||
$file = fopen($maintenanceFile, 'w');
|
||||
fclose($file);
|
||||
|
||||
//Begin upgrade
|
||||
$didWePerformAnUpgrade = false;
|
||||
try
|
||||
{
|
||||
for ($i = 0; $i < count($upgraders); $i++)
|
||||
{
|
||||
$upgrader = $upgraders[$i];
|
||||
if ($upgrader->checkIfUpgradeSupported())
|
||||
{
|
||||
$upgrader->upgrade(); //This will throw an exception if the upgrade fails.
|
||||
$didWePerformAnUpgrade = true;
|
||||
$this->getResponse()
|
||||
->setHttpResponseCode(200)
|
||||
->appendBody("Upgrade to Airtime " . $upgrader->getNewVersion() . " OK<br>");
|
||||
$i = 0; //Start over, in case the upgrade handlers are not in ascending order.
|
||||
}
|
||||
}
|
||||
|
||||
//Update disk_usage value in cc_pref
|
||||
$storDir = isset($_SERVER['AIRTIME_BASE']) ? $_SERVER['AIRTIME_BASE']."srv/airtime/stor" : "/srv/airtime/stor";
|
||||
$diskUsage = shell_exec("du -sb $storDir | awk '{print $1}'");
|
||||
|
||||
Application_Model_Preference::setDiskUsage($diskUsage);
|
||||
|
||||
//TODO: clear out the cache
|
||||
|
||||
$con->commit();
|
||||
|
||||
//update system_version in cc_pref and change some columns in cc_files
|
||||
$airtimeConf = isset($_SERVER['AIRTIME_CONF']) ? $_SERVER['AIRTIME_CONF'] : "/etc/airtime/airtime.conf";
|
||||
$values = parse_ini_file($airtimeConf, true);
|
||||
|
||||
$username = $values['database']['dbuser'];
|
||||
$password = $values['database']['dbpass'];
|
||||
$host = $values['database']['host'];
|
||||
$database = $values['database']['dbname'];
|
||||
$dir = __DIR__;
|
||||
|
||||
passthru("export PGPASSWORD=$password && psql -h $host -U $username -q -f $dir/upgrade_sql/airtime_$airtime_upgrade_version/upgrade.sql $database 2>&1 | grep -v \"will create implicit index\"");
|
||||
|
||||
//delete maintenance.txt to give users access back to Airtime
|
||||
unlink($maintenanceFile);
|
||||
|
||||
$this->getResponse()
|
||||
if (!$didWePerformAnUpgrade)
|
||||
{
|
||||
$this->getResponse()
|
||||
->setHttpResponseCode(200)
|
||||
->appendBody("Upgrade to Airtime 2.5.3 OK");
|
||||
|
||||
} catch(Exception $e) {
|
||||
$con->rollback();
|
||||
unlink($maintenanceFile);
|
||||
->appendBody("No upgrade was performed. The current Airtime version is " . AirtimeUpgrader::getCurrentVersion() . ".<br>");
|
||||
}
|
||||
}
|
||||
catch (Exception $e)
|
||||
{
|
||||
$this->getResponse()
|
||||
->setHttpResponseCode(400)
|
||||
->appendBody($e->getMessage());
|
||||
->setHttpResponseCode(400)
|
||||
->appendBody($e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -86,25 +66,10 @@ class UpgradeController extends Zend_Controller_Action
|
|||
{
|
||||
$this->getResponse()
|
||||
->setHttpResponseCode(401)
|
||||
->appendBody("Error: Incorrect API key.");
|
||||
->appendBody("Error: Incorrect API key.<br>");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private function verifyAirtimeVersion()
|
||||
{
|
||||
$pref = CcPrefQuery::create()
|
||||
->filterByKeystr('system_version')
|
||||
->findOne();
|
||||
$airtime_version = $pref->getValStr();
|
||||
|
||||
if (!in_array($airtime_version, array('2.5.1', '2.5.2'))) {
|
||||
$this->getResponse()
|
||||
->setHttpResponseCode(400)
|
||||
->appendBody("Upgrade to Airtime 2.5.3 FAILED. You must be using Airtime 2.5.1 or 2.5.2 to upgrade.");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -62,7 +62,11 @@ class UserController extends Zend_Controller_Action
|
|||
if ($formData['password'] != "xxxxxx") {
|
||||
$user->setPassword($formData['password']);
|
||||
}
|
||||
$user->setType($formData['type']);
|
||||
if (array_key_exists('type', $formData)) {
|
||||
if ($formData['type'] != UTYPE_SUPERADMIN) { //Don't allow any other user to be promoted to Super Admin
|
||||
$user->setType($formData['type']);
|
||||
}
|
||||
}
|
||||
$user->setEmail($formData['email']);
|
||||
$user->setCellPhone($formData['cell_phone']);
|
||||
$user->setSkype($formData['skype']);
|
||||
|
@ -121,6 +125,10 @@ class UserController extends Zend_Controller_Action
|
|||
|
||||
public function editUserAction()
|
||||
{
|
||||
if (Application_Model_User::getCurrentUser()->isSuperAdmin()) {
|
||||
$this->_redirect('billing/client');
|
||||
}
|
||||
|
||||
$request = $this->getRequest();
|
||||
$form = new Application_Form_EditUser();
|
||||
if ($request->isPost()) {
|
||||
|
@ -187,6 +195,12 @@ class UserController extends Zend_Controller_Action
|
|||
}
|
||||
|
||||
$user = new Application_Model_User($delId);
|
||||
|
||||
// Don't allow super admins to be deleted.
|
||||
if ($user->isSuperAdmin())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
# Take care of the user's files by either assigning them to somebody
|
||||
# or deleting them all
|
||||
|
|
|
@ -88,7 +88,7 @@ class WebstreamController extends Zend_Controller_Action
|
|||
public function isAuthorized($webstream_id)
|
||||
{
|
||||
$user = Application_Model_User::getCurrentUser();
|
||||
if ($user->isUserType(array(UTYPE_ADMIN, UTYPE_PROGRAM_MANAGER))) {
|
||||
if ($user->isUserType(array(UTYPE_SUPERADMIN, UTYPE_ADMIN, UTYPE_PROGRAM_MANAGER))) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
258
airtime_mvc/application/controllers/WhmcsLoginController.php
Normal file
258
airtime_mvc/application/controllers/WhmcsLoginController.php
Normal file
|
@ -0,0 +1,258 @@
|
|||
<?php
|
||||
|
||||
class WhmcsLoginController extends Zend_Controller_Action
|
||||
{
|
||||
|
||||
public function init()
|
||||
{
|
||||
}
|
||||
|
||||
public function indexAction()
|
||||
{
|
||||
$CC_CONFIG = Config::getConfig();
|
||||
|
||||
$request = $this->getRequest();
|
||||
$this->view->layout()->disableLayout();
|
||||
$this->_helper->viewRenderer->setNoRender(true);
|
||||
|
||||
$username = "admin"; //This is just for appearance in your session. It shows up in the corner of the Airtime UI.
|
||||
$email = $_POST["email"];
|
||||
$password = $_POST["password"];
|
||||
|
||||
Application_Model_Locale::configureLocalization($request->getcookie('airtime_locale', 'en_CA'));
|
||||
if (Zend_Auth::getInstance()->hasIdentity())
|
||||
{
|
||||
$this->_redirect('Showbuilder');
|
||||
}
|
||||
|
||||
$authAdapter = new WHMCS_Auth_Adapter($username, $email, $password);
|
||||
|
||||
$auth = Zend_Auth::getInstance();
|
||||
$result = $auth->authenticate($authAdapter);
|
||||
if ($result->isValid()) {
|
||||
//all info about this user from the login table omit only the password
|
||||
//$userInfo = $authAdapter->getResultRowObject(null, 'password');
|
||||
|
||||
//the default storage is a session with namespace Zend_Auth
|
||||
/*
|
||||
[id] => 1
|
||||
[login] => admin
|
||||
[pass] => hashed password
|
||||
[type] => A
|
||||
[first_name] =>
|
||||
[last_name] =>
|
||||
[lastlogin] =>
|
||||
[lastfail] =>
|
||||
[skype_contact] =>
|
||||
[jabber_contact] =>
|
||||
[email] => asdfasdf@asdasdf.com
|
||||
[cell_phone] =>
|
||||
[login_attempts] => 0
|
||||
*/
|
||||
|
||||
//Zend_Auth already does this for us, it's not needed:
|
||||
//$authStorage = $auth->getStorage();
|
||||
//$authStorage->write($result->getIdentity()); //$userInfo);
|
||||
|
||||
//set the user locale in case user changed it in when logging in
|
||||
//$locale = $form->getValue('locale');
|
||||
//Application_Model_Preference::SetUserLocale($locale);
|
||||
|
||||
$this->_redirect('Showbuilder');
|
||||
}
|
||||
else {
|
||||
echo("Sorry, that username or password was incorrect.");
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
class WHMCS_Auth_Adapter implements Zend_Auth_Adapter_Interface {
|
||||
private $username;
|
||||
private $password;
|
||||
private $email;
|
||||
|
||||
function __construct($username, $email, $password) {
|
||||
$this->username = $username;
|
||||
$this->password = $password;
|
||||
$this->email = $email;
|
||||
$this->identity = null;
|
||||
}
|
||||
|
||||
function authenticate() {
|
||||
list($credentialsValid, $clientId) = $this->validateCredentialsWithWHMCS($this->email, $this->password);
|
||||
if (!$credentialsValid)
|
||||
{
|
||||
return new Zend_Auth_Result(Zend_Auth_Result::FAILURE_CREDENTIAL_INVALID, null);
|
||||
}
|
||||
if (!$this->verifyClientSubdomainOwnership($clientId))
|
||||
{
|
||||
return new Zend_Auth_Result(Zend_Auth_Result::FAILURE_CREDENTIAL_INVALID, null);
|
||||
}
|
||||
|
||||
$identity = array();
|
||||
|
||||
//TODO: Get identity of the first admin user!
|
||||
|
||||
/*
|
||||
$identity["id"] = 1;
|
||||
$identity["type"] = "S";
|
||||
$identity["login"] = $this->username; //admin";
|
||||
$identity["email"] = $this->email;*/
|
||||
$identity = $this->getSuperAdminIdentity();
|
||||
if (is_null($identity)) {
|
||||
Logging::error("No super admin user found");
|
||||
return new Zend_Auth_Result(Zend_Auth_Result::FAILURE, null);
|
||||
}
|
||||
$identity = (object)$identity; //Convert the array into an stdClass object
|
||||
|
||||
try {
|
||||
return new Zend_Auth_Result(Zend_Auth_Result::SUCCESS, $identity);
|
||||
} catch (Exception $e) {
|
||||
// exception occured
|
||||
return new Zend_Auth_Result(Zend_Auth_Result::FAILURE, null);
|
||||
}
|
||||
}
|
||||
|
||||
private function getSuperAdminIdentity()
|
||||
{
|
||||
$firstSuperAdminUser = CcSubjsQuery::create()
|
||||
->filterByDbType('S')
|
||||
->orderByDbId()
|
||||
->findOne();
|
||||
if (!$firstSuperAdminUser) {
|
||||
//If there's no super admin users, get the first regular admin user!
|
||||
$firstSuperAdminUser = CcSubjsQuery::create()
|
||||
->filterByDbType('A')
|
||||
->orderByDbId()
|
||||
->findOne();
|
||||
if (!$firstSuperAdminUser) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
$identity["id"] = $firstSuperAdminUser->getDbId();
|
||||
$identity["type"] = "S"; //Super Admin
|
||||
$identity["login"] = $firstSuperAdminUser->getDbLogin();
|
||||
$identity["email"] = $this->email;
|
||||
return $identity;
|
||||
}
|
||||
|
||||
//Returns an array! Read the code carefully:
|
||||
private function validateCredentialsWithWHMCS($email, $password)
|
||||
{
|
||||
$client_postfields = array();
|
||||
$client_postfields["username"] = $_SERVER['WHMCS_USERNAME']; //WHMCS API username
|
||||
$client_postfields["password"] = md5($_SERVER['WHMCS_PASSWORD']); //WHMCS API password
|
||||
$client_postfields["action"] ="validatelogin";
|
||||
$client_postfields["responsetype"] = "json";
|
||||
|
||||
$client_postfields["email"] = $email;
|
||||
$client_postfields["password2"] = $password;
|
||||
|
||||
$query_string = "";
|
||||
foreach ($client_postfields as $k => $v) $query_string .= "$k=".urlencode($v)."&";
|
||||
|
||||
$ch = curl_init();
|
||||
curl_setopt($ch, CURLOPT_URL, WHMCS_API_URL);
|
||||
curl_setopt($ch, CURLOPT_POST, 1);
|
||||
curl_setopt($ch, CURLOPT_TIMEOUT, 30);
|
||||
curl_setopt($ch, CURLOPT_FAILONERROR, 1);
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
|
||||
curl_setopt($ch, CURLOPT_POSTFIELDS, $query_string);
|
||||
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
|
||||
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
|
||||
$jsondata = curl_exec($ch);
|
||||
if (curl_error($ch)) {
|
||||
die(curl_getinfo($ch, CURLINFO_EFFECTIVE_URL));
|
||||
//die("Connection Error: ".curl_errno($ch).' - '.curl_error($ch));
|
||||
}
|
||||
curl_close($ch);
|
||||
|
||||
$arr = json_decode($jsondata, true); # Decode JSON String
|
||||
|
||||
if ($arr["result"] != "success") {
|
||||
return array(false, -1);
|
||||
}
|
||||
$clientId = $arr["userid"];
|
||||
|
||||
return array(true, $clientId);
|
||||
}
|
||||
|
||||
function verifyClientSubdomainOwnership($clientId)
|
||||
{
|
||||
//Do a quick safety check to ensure the client ID we're authenticating
|
||||
//matches up to the owner of this instance.
|
||||
if ($clientId != Application_Model_Preference::GetClientId())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
$client_postfields = array();
|
||||
$client_postfields["username"] = $_SERVER['WHMCS_USERNAME'];
|
||||
$client_postfields["password"] = md5($_SERVER['WHMCS_PASSWORD']);
|
||||
$client_postfields["action"] ="getclientsproducts";
|
||||
$client_postfields["responsetype"] = "json";
|
||||
|
||||
$client_postfields["clientid"] = $clientId;
|
||||
//$client_postfields["stats"] = "true";
|
||||
|
||||
$query_string = "";
|
||||
foreach ($client_postfields as $k => $v) $query_string .= "$k=".urlencode($v)."&";
|
||||
|
||||
$ch = curl_init();
|
||||
curl_setopt($ch, CURLOPT_URL, WHMCS_API_URL);
|
||||
curl_setopt($ch, CURLOPT_POST, 1);
|
||||
curl_setopt($ch, CURLOPT_TIMEOUT, 30);
|
||||
curl_setopt($ch, CURLOPT_FAILONERROR, 1);
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
|
||||
curl_setopt($ch, CURLOPT_POSTFIELDS, $query_string);
|
||||
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
|
||||
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
|
||||
$jsondata = curl_exec($ch);
|
||||
if (curl_error($ch)) {
|
||||
die(curl_getinfo($ch, CURLINFO_EFFECTIVE_URL));
|
||||
//die("Connection Error: ".curl_errno($ch).' - '.curl_error($ch));
|
||||
}
|
||||
curl_close($ch);
|
||||
|
||||
$arr = json_decode($jsondata, true); # Decode JSON String
|
||||
//$client_id = $arr["clientid"];
|
||||
//print_r($arr);
|
||||
if ($arr["result"] != "success") {
|
||||
die("Sorry, that email address or password was incorrect.");
|
||||
}
|
||||
|
||||
$doesAirtimeProductExist = false;
|
||||
$isAirtimeAccountSuspended = true;
|
||||
$airtimeProduct = null;
|
||||
|
||||
foreach ($arr["products"] as $product)
|
||||
{
|
||||
if (strpos($product[0]["groupname"], "Airtime") === FALSE)
|
||||
{
|
||||
//Ignore non-Airtime products
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ($product[0]["status"] === "Active") {
|
||||
$airtimeProduct = $product[0];
|
||||
$subdomain = '';
|
||||
|
||||
foreach ($airtimeProduct['customfields']['customfield'] as $customField)
|
||||
{
|
||||
if ($customField['name'] === SUBDOMAIN_WHMCS_CUSTOM_FIELD_NAME)
|
||||
{
|
||||
$subdomain = $customField['value'];
|
||||
if (($subdomain . ".airtime.pro") === $_SERVER['SERVER_NAME'])
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
|
@ -118,8 +118,7 @@ class Zend_Controller_Plugin_Acl extends Zend_Controller_Plugin_Abstract
|
|||
return;
|
||||
}
|
||||
|
||||
if (in_array($controller, array("api", "auth", "locale", "upgrade"))) {
|
||||
|
||||
if (in_array($controller, array("api", "auth", "locale", "upgrade", 'whmcs-login'))) {
|
||||
$this->setRoleName("G");
|
||||
} elseif (!Zend_Auth::getInstance()->hasIdentity()) {
|
||||
|
||||
|
|
|
@ -95,9 +95,9 @@ class Application_Form_AddUser extends Zend_Form
|
|||
"G" => _("Guest"),
|
||||
"H" => _("DJ"),
|
||||
"P" => _("Program Manager"),
|
||||
"A" => _("Admin")
|
||||
"A" => _("Admin"),
|
||||
));
|
||||
$select->setRequired(true);
|
||||
$select->setRequired(false);
|
||||
$this->addElement($select);
|
||||
|
||||
$saveBtn = new Zend_Form_Element_Button('save_user');
|
||||
|
|
196
airtime_mvc/application/forms/BillingClient.php
Normal file
196
airtime_mvc/application/forms/BillingClient.php
Normal file
|
@ -0,0 +1,196 @@
|
|||
<?php
|
||||
require_once 'Zend/Locale.php';
|
||||
|
||||
class Application_Form_BillingClient extends Zend_Form
|
||||
{
|
||||
public function init()
|
||||
{
|
||||
/*$this->setDecorators(array(
|
||||
array('ViewScript', array('viewScript' => 'form/billing-purchase.phtml'))));*/
|
||||
$client = BillingController::getClientDetails();
|
||||
$this->setAttrib("id", "clientdetails_form");
|
||||
|
||||
$notEmptyValidator = Application_Form_Helper_ValidationTypes::overrideNotEmptyValidator();
|
||||
$emailValidator = Application_Form_Helper_ValidationTypes::overrideEmailAddressValidator();
|
||||
|
||||
$firstname = new Zend_Form_Element_Text('firstname');
|
||||
$firstname->setLabel(_('First Name:'))
|
||||
->setValue($client["firstname"])
|
||||
->setAttrib('class', 'input_text')
|
||||
->setRequired(true)
|
||||
->addValidator($notEmptyValidator)
|
||||
->addFilter('StringTrim');
|
||||
$this->addElement($firstname);
|
||||
|
||||
$lastname = new Zend_Form_Element_Text('lastname');
|
||||
$lastname->setLabel(_('Last Name:'))
|
||||
->setValue($client["lastname"])
|
||||
->setAttrib('class', 'input_text')
|
||||
->setRequired(true)
|
||||
->addValidator($notEmptyValidator)
|
||||
->addFilter('StringTrim');
|
||||
$this->addElement($lastname);
|
||||
|
||||
$companyname = new Zend_Form_Element_Text('companyname');
|
||||
$companyname->setLabel(_('Company Name:'))
|
||||
->setValue($client["companyname"])
|
||||
->setAttrib('class', 'input_text')
|
||||
->setRequired(false)
|
||||
->addValidator($notEmptyValidator)
|
||||
->addFilter('StringTrim');
|
||||
$this->addElement($companyname);
|
||||
|
||||
$email = new Zend_Form_Element_Text('email');
|
||||
$email->setLabel(_('Email Address:'))
|
||||
->setValue($client["email"])
|
||||
->setAttrib('class', 'input_text')
|
||||
->setRequired(true)
|
||||
->setAttrib('readonly', 'readonly')
|
||||
->addValidator($emailValidator)
|
||||
->addFilter('StringTrim');
|
||||
$this->addElement($email);
|
||||
|
||||
$address1 = new Zend_Form_Element_Text('address1');
|
||||
$address1->setLabel(_('Address 1:'))
|
||||
->setValue($client["address1"])
|
||||
->setAttrib('class', 'input_text')
|
||||
->setRequired(true)
|
||||
->addValidator($notEmptyValidator)
|
||||
->addFilter('StringTrim');
|
||||
$this->addElement($address1);
|
||||
|
||||
$address2 = new Zend_Form_Element_Text('address2');
|
||||
$address2->setLabel(_('Address 2:'))
|
||||
->setValue($client["address2"])
|
||||
->setAttrib('class', 'input_text')
|
||||
->addFilter('StringTrim');
|
||||
$this->addElement($address2);
|
||||
|
||||
$city = new Zend_Form_Element_Text('city');
|
||||
$city->setLabel(_('City:'))
|
||||
->setValue($client["city"])
|
||||
->setAttrib('class', 'input_text')
|
||||
->setRequired(true)
|
||||
->addValidator($notEmptyValidator)
|
||||
->addFilter('StringTrim');
|
||||
$this->addElement($city);
|
||||
|
||||
//TODO: get list from whmcs?
|
||||
$state = new Zend_Form_Element_Text('state');
|
||||
$state->setLabel(_('State/Region:'))
|
||||
->setValue($client["state"])
|
||||
->setAttrib('class', 'input_text')
|
||||
->setRequired(true)
|
||||
->addValidator($notEmptyValidator)
|
||||
->addFilter('StringTrim');
|
||||
$this->addElement($state);
|
||||
|
||||
$postcode = new Zend_Form_Element_Text('postcode');
|
||||
$postcode->setLabel(_('Zip Code / Postal Code:'))
|
||||
->setValue($client["postcode"])
|
||||
->setAttrib('class', 'input_text')
|
||||
->setRequired(true)
|
||||
->addValidator($notEmptyValidator)
|
||||
->addFilter('StringTrim');
|
||||
$this->addElement($postcode);
|
||||
|
||||
$locale = new Zend_Locale('en_US');
|
||||
$countries = $locale->getTranslationList('Territory', 'en', 2);
|
||||
asort($countries, SORT_LOCALE_STRING);
|
||||
|
||||
$country = new Zend_Form_Element_Select('country');
|
||||
$country->setLabel(_('Country:'))
|
||||
->setValue($client["country"])
|
||||
->setAttrib('class', 'input_text')
|
||||
->setMultiOptions($countries)
|
||||
->setRequired(true)
|
||||
->addValidator($notEmptyValidator)
|
||||
->addFilter('StringTrim');
|
||||
$this->addElement($country);
|
||||
|
||||
$phonenumber = new Zend_Form_Element_Text('phonenumber');
|
||||
$phonenumber->setLabel(_('Phone Number:'))
|
||||
->setValue($client["phonenumber"])
|
||||
->setAttrib('class', 'input_text')
|
||||
->setRequired(true)
|
||||
->addValidator($notEmptyValidator)
|
||||
->addFilter('StringTrim');
|
||||
$this->addElement($phonenumber);
|
||||
|
||||
$securityqid = new Zend_Form_Element_Select('securityqid');
|
||||
$securityqid->setLabel(_('Please choose a security question:'))
|
||||
->setValue($client["securityqid"])
|
||||
->setAttrib('class', 'input_text')
|
||||
->setRequired(true)
|
||||
->setMultiOptions(array(
|
||||
"1" => _("What is the name of your favorite childhood friend?"),
|
||||
"3" => _("What school did you attend for sixth grade?"),
|
||||
"4" => _("In what city did you meet your spouse/significant other?"),
|
||||
"5" => _("What street did you live on in third grade?"),
|
||||
"6" => _("What is the first name of the boy or girl that you first kissed?"),
|
||||
"7" => _("In what city or town was your first job?")));
|
||||
$this->addElement($securityqid);
|
||||
|
||||
$securityqans = new Zend_Form_Element_Text('securityqans');
|
||||
$securityqans->setLabel(_('Please enter an answer:'))
|
||||
->setValue($client["securityqans"])
|
||||
->setAttrib('class', 'input_text')
|
||||
->setRequired(true)
|
||||
->addValidator($notEmptyValidator)
|
||||
->addFilter('StringTrim');
|
||||
$this->addElement($securityqans);
|
||||
|
||||
foreach ($client["customfields"] as $field) {
|
||||
if ($field["id"] == "7") {
|
||||
$vatvalue = $field["value"];
|
||||
} elseif ($field["id"] == "71") {
|
||||
$subscribevalue = $field["value"];
|
||||
}
|
||||
}
|
||||
|
||||
$vat = new Zend_Form_Element_Text("7");
|
||||
$vat->setLabel(_('VAT/Tax ID (EU only)'))
|
||||
->setBelongsTo('customfields')
|
||||
->setValue($vatvalue)
|
||||
->setAttrib('class', 'input_text')
|
||||
//->setRequired(true)
|
||||
//->addValidator($notEmptyValidator)
|
||||
->addFilter('StringTrim');
|
||||
$this->addElement($vat);
|
||||
|
||||
$subscribe = new Zend_Form_Element_Checkbox('71');
|
||||
$subscribe->setLabel(_('Subscribe to Sourcefabric newsletter'))
|
||||
->setValue($subscribevalue)
|
||||
->setBelongsTo('customfields')
|
||||
->setAttrib('class', 'input_text')
|
||||
->setRequired(true)
|
||||
->addValidator($notEmptyValidator)
|
||||
->addFilter('StringTrim');
|
||||
$this->addElement($subscribe);
|
||||
|
||||
$password = new Zend_Form_Element_Password('password2');
|
||||
$password->setLabel(_('Password:'));
|
||||
$password->setAttrib('class', 'input_text');
|
||||
$password->setValue("xxxxxx");
|
||||
$password->setRequired(true);
|
||||
$password->addFilter('StringTrim');
|
||||
$password->addValidator($notEmptyValidator);
|
||||
$this->addElement($password);
|
||||
|
||||
$passwordVerify = new Zend_Form_Element_Password('password2verify');
|
||||
$passwordVerify->setLabel(_('Verify Password:'));
|
||||
$passwordVerify->setAttrib('class', 'input_text');
|
||||
$passwordVerify->setValue("xxxxxx");
|
||||
$passwordVerify->setRequired(true);
|
||||
$passwordVerify->addFilter('StringTrim');
|
||||
//$passwordVerify->addValidator($notEmptyValidator);
|
||||
$passwordVerify->addValidator('Identical', false, array('token' => 'password2'));
|
||||
$passwordVerify->addValidator($notEmptyValidator);
|
||||
$this->addElement($passwordVerify);
|
||||
|
||||
$submit = new Zend_Form_Element_Submit("submit");
|
||||
$submit->setIgnore(true)
|
||||
->setLabel(_("Save"));
|
||||
$this->addElement($submit);
|
||||
}
|
||||
}
|
54
airtime_mvc/application/forms/BillingUpgradeDowngrade.php
Normal file
54
airtime_mvc/application/forms/BillingUpgradeDowngrade.php
Normal file
|
@ -0,0 +1,54 @@
|
|||
<?php
|
||||
class Application_Form_BillingUpgradeDowngrade extends Zend_Form
|
||||
{
|
||||
public function init()
|
||||
{
|
||||
$productPrices = array();
|
||||
$productTypes = array();
|
||||
list($productPrices, $productTypes) = BillingController::getProductPricesAndTypes();
|
||||
|
||||
//$currentPlanType = ucfirst(Application_Model_Preference::GetPlanLevel());
|
||||
$currentPlanType = "Hobbyist";
|
||||
if (($key = array_search($currentPlanType, $productTypes)) !== false) {
|
||||
//unset($productTypes[$key]);
|
||||
}
|
||||
|
||||
$currentPlanProduct = BillingController::getClientCurrentAirtimeProduct();
|
||||
$currentPlanProductId = $currentPlanProduct["pid"];
|
||||
$currentPlanProductBillingCycle = $currentPlanProduct["billingcycle"];
|
||||
$pid = new Zend_Form_Element_Radio('newproductid');
|
||||
$pid->setLabel(_('Plan type:'))
|
||||
->setMultiOptions($productTypes)
|
||||
->setRequired(true)
|
||||
->setValue($currentPlanProductId);
|
||||
$this->addElement($pid);
|
||||
|
||||
//Logging::info(BillingController::getClientCurrentAirtimeProduct());
|
||||
$billingcycle = new Zend_Form_Element_Radio('newproductbillingcycle');
|
||||
$billingcycle->setLabel(_('Billing cycle:'))
|
||||
->setMultiOptions(array('monthly' => 'Monthly', 'annually' => 'Annually'))
|
||||
->setRequired(true)
|
||||
->setValue($currentPlanProductBillingCycle);
|
||||
|
||||
$this->addElement($billingcycle);
|
||||
|
||||
$paymentmethod = new Zend_Form_Element_Radio('paymentmethod');
|
||||
$paymentmethod->setLabel(_('Payment method:'))
|
||||
->setRequired(true)
|
||||
->setMultiOptions(array(
|
||||
'paypal' => _('PayPal'),
|
||||
'tco' => _('Credit Card via 2Checkout')))
|
||||
->setValue('paypal');
|
||||
$this->addElement($paymentmethod);
|
||||
|
||||
/*$submit = new Zend_Form_Element_Submit("submit");
|
||||
$submit->setIgnore(true)
|
||||
->setLabel(_("Save"));
|
||||
$this->addElement($submit);*/
|
||||
|
||||
$client = new Application_Form_BillingClient();
|
||||
$client->removeElement("password2");
|
||||
$client->removeElement("password2verify");
|
||||
$this->addSubForm($client, 'billing_client_info');
|
||||
}
|
||||
}
|
|
@ -33,7 +33,9 @@ j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
|
|||
<div class="personal-block solo">
|
||||
<ul>
|
||||
<li>
|
||||
<a id="current-user" href=<?php echo $baseUrl . "User/edit-user"?>><span class="name"><?php echo $this->escape($this->loggedInAs()); ?></span></a> | <a href=<?php echo $baseUrl . "Login/logout"?>><?php echo _("Logout")?></a>
|
||||
<!-- <span class="trial-box-button"><a title="Billing" href=<?php echo $baseUrl . 'billing/upgrade'?>>Upgrade</a></span> -->
|
||||
<a id="current-user" href=<?php echo $baseUrl . "User/edit-user"?>><span class="name"><?php echo $this->escape($this->loggedInAs()); ?></span></a>
|
||||
| <a href=<?php echo $baseUrl . "Login/logout"?>><?php echo _("Logout")?></a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
|
|
@ -1038,7 +1038,7 @@ SQL;
|
|||
{
|
||||
$userInfo = Zend_Auth::getInstance()->getStorage()->read();
|
||||
$user = new Application_Model_User($userInfo->id);
|
||||
$isAdminOrPM = $user->isUserType(array(UTYPE_ADMIN, UTYPE_PROGRAM_MANAGER));
|
||||
$isAdminOrPM = $user->isUserType(array(UTYPE_SUPERADMIN, UTYPE_ADMIN, UTYPE_PROGRAM_MANAGER));
|
||||
|
||||
// get only the files from the blocks
|
||||
// we are about to delete
|
||||
|
|
|
@ -35,4 +35,11 @@ class Cache
|
|||
//return apc_fetch($cacheKey);
|
||||
return false;
|
||||
}
|
||||
|
||||
public static function clear()
|
||||
{
|
||||
// Disabled on SaaS
|
||||
// apc_clear_cache('user');
|
||||
// apc_clear_cache();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -987,7 +987,7 @@ SQL;
|
|||
{
|
||||
$userInfo = Zend_Auth::getInstance()->getStorage()->read();
|
||||
$user = new Application_Model_User($userInfo->id);
|
||||
$isAdminOrPM = $user->isUserType(array(UTYPE_ADMIN, UTYPE_PROGRAM_MANAGER));
|
||||
$isAdminOrPM = $user->isUserType(array(UTYPE_SUPERADMIN, UTYPE_ADMIN, UTYPE_PROGRAM_MANAGER));
|
||||
|
||||
// get only the files from the playlists
|
||||
// we are about to delete
|
||||
|
|
|
@ -6,7 +6,7 @@ class Application_Model_Preference
|
|||
{
|
||||
|
||||
private static function getUserId()
|
||||
{
|
||||
{
|
||||
//pass in true so the check is made with the autoloader
|
||||
//we need this check because saas calls this function from outside Zend
|
||||
if (!class_exists("Zend_Auth", true) || !Zend_Auth::getInstance()->hasIdentity()) {
|
||||
|
|
|
@ -379,7 +379,7 @@ SQL;
|
|||
|
||||
$userInfo = Zend_Auth::getInstance()->getStorage()->read();
|
||||
$user = new Application_Model_User($userInfo->id);
|
||||
$isAdminOrPM = $user->isUserType(array(UTYPE_ADMIN, UTYPE_PROGRAM_MANAGER));
|
||||
$isAdminOrPM = $user->isUserType(array(UTYPE_SUPERADMIN, UTYPE_ADMIN, UTYPE_PROGRAM_MANAGER));
|
||||
if (!$isAdminOrPM && $this->getFileOwnerId() != $user->getId()) {
|
||||
throw new FileNoPermissionException();
|
||||
}
|
||||
|
|
|
@ -49,14 +49,20 @@ class Application_Model_User
|
|||
{
|
||||
return $this->isUserType(UTYPE_ADMIN);
|
||||
}
|
||||
|
||||
|
||||
public function isSuperAdmin()
|
||||
{
|
||||
return $this->isUserType(UTYPE_SUPERADMIN);
|
||||
}
|
||||
|
||||
public function canSchedule($p_showId)
|
||||
{
|
||||
$type = $this->getType();
|
||||
$result = false;
|
||||
|
||||
if ($type === UTYPE_ADMIN ||
|
||||
$type === UTYPE_PROGRAM_MANAGER ||
|
||||
if ($this->isAdmin() ||
|
||||
$this->isSuperAdmin() ||
|
||||
$this->isPM() ||
|
||||
self::isHostOfShow($p_showId)) {
|
||||
$result = true;
|
||||
}
|
||||
|
|
|
@ -15,7 +15,7 @@ class CcSubjs extends BaseCcSubjs {
|
|||
|
||||
public function isAdminOrPM()
|
||||
{
|
||||
return $this->type === UTYPE_ADMIN || $this->type === UTYPE_PROGRAM_MANAGER;
|
||||
return $this->type === UTYPE_SUPERADMIN || $this->type === UTYPE_ADMIN || $this->type === UTYPE_PROGRAM_MANAGER;
|
||||
}
|
||||
|
||||
public function isHostOfShow($showId)
|
||||
|
|
197
airtime_mvc/application/upgrade/Upgrades.php
Normal file
197
airtime_mvc/application/upgrade/Upgrades.php
Normal file
|
@ -0,0 +1,197 @@
|
|||
<?php
|
||||
|
||||
abstract class AirtimeUpgrader
|
||||
{
|
||||
/** Versions that this upgrader class can upgrade from (an array of version strings). */
|
||||
abstract protected function getSupportedVersions();
|
||||
/** The version that this upgrader class will upgrade to. (returns a version string) */
|
||||
abstract public function getNewVersion();
|
||||
|
||||
public static function getCurrentVersion()
|
||||
{
|
||||
CcPrefPeer::clearInstancePool(); //Ensure we don't get a cached Propel object (cached DB results)
|
||||
//because we're updating this version number within this HTTP request as well.
|
||||
$pref = CcPrefQuery::create()
|
||||
->filterByKeystr('system_version')
|
||||
->findOne();
|
||||
$airtime_version = $pref->getValStr();
|
||||
return $airtime_version;
|
||||
}
|
||||
|
||||
/**
|
||||
* This function checks to see if this class can perform an upgrade of your version of Airtime
|
||||
* @return boolean True if we can upgrade your version of Airtime.
|
||||
*/
|
||||
public function checkIfUpgradeSupported()
|
||||
{
|
||||
if (!in_array(AirtimeUpgrader::getCurrentVersion(), $this->getSupportedVersions())) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
protected function toggleMaintenanceScreen($toggle)
|
||||
{
|
||||
if ($toggle)
|
||||
{
|
||||
//Disable Airtime UI
|
||||
//create a temporary maintenance notification file
|
||||
//when this file is on the server, zend framework redirects all
|
||||
//requests to the maintenance page and sets a 503 response code
|
||||
$this->maintenanceFile = isset($_SERVER['AIRTIME_BASE']) ? $_SERVER['AIRTIME_BASE']."maintenance.txt" : "/tmp/maintenance.txt";
|
||||
$file = fopen($this->maintenanceFile, 'w');
|
||||
fclose($file);
|
||||
} else {
|
||||
//delete maintenance.txt to give users access back to Airtime
|
||||
if ($this->maintenanceFile) {
|
||||
unlink($this->maintenanceFile);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Implement this for each new version of Airtime */
|
||||
abstract public function upgrade();
|
||||
}
|
||||
|
||||
class AirtimeUpgrader253 extends AirtimeUpgrader
|
||||
{
|
||||
protected function getSupportedVersions()
|
||||
{
|
||||
return array('2.5.1', '2.5.2');
|
||||
}
|
||||
public function getNewVersion()
|
||||
{
|
||||
return '2.5.3';
|
||||
}
|
||||
|
||||
public function upgrade()
|
||||
{
|
||||
Cache::clear();
|
||||
assert($this->checkIfUpgradeSupported());
|
||||
|
||||
$con = Propel::getConnection();
|
||||
$con->beginTransaction();
|
||||
try {
|
||||
|
||||
$this->toggleMaintenanceScreen(true);
|
||||
Cache::clear();
|
||||
|
||||
//Begin upgrade
|
||||
|
||||
//Update disk_usage value in cc_pref
|
||||
$musicDir = CcMusicDirsQuery::create()
|
||||
->filterByType('stor')
|
||||
->filterByExists(true)
|
||||
->findOne();
|
||||
$storPath = $musicDir->getDirectory();
|
||||
|
||||
//Update disk_usage value in cc_pref
|
||||
$storDir = isset($_SERVER['AIRTIME_BASE']) ? $_SERVER['AIRTIME_BASE']."srv/airtime/stor" : "/srv/airtime/stor";
|
||||
$diskUsage = shell_exec("du -sb $storDir | awk '{print $1}'");
|
||||
|
||||
Application_Model_Preference::setDiskUsage($diskUsage);
|
||||
|
||||
//clear out the cache
|
||||
Cache::clear();
|
||||
|
||||
$con->commit();
|
||||
|
||||
//update system_version in cc_pref and change some columns in cc_files
|
||||
$airtimeConf = isset($_SERVER['AIRTIME_CONF']) ? $_SERVER['AIRTIME_CONF'] : "/etc/airtime/airtime.conf";
|
||||
$values = parse_ini_file($airtimeConf, true);
|
||||
|
||||
$username = $values['database']['dbuser'];
|
||||
$password = $values['database']['dbpass'];
|
||||
$host = $values['database']['host'];
|
||||
$database = $values['database']['dbname'];
|
||||
$dir = __DIR__;
|
||||
|
||||
passthru("export PGPASSWORD=$password && psql -h $host -U $username -q -f $dir/upgrade_sql/airtime_$airtime_upgrade_version/upgrade.sql $database 2>&1 | grep -v \"will create implicit index\"");
|
||||
|
||||
Application_Model_Preference::SetAirtimeVersion($this->getNewVersion());
|
||||
//clear out the cache
|
||||
Cache::clear();
|
||||
|
||||
$this->toggleMaintenanceScreen(false);
|
||||
|
||||
} catch (Exception $e) {
|
||||
$con->rollback();
|
||||
$this->toggleMaintenanceScreen(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class AirtimeUpgrader254 extends AirtimeUpgrader
|
||||
{
|
||||
protected function getSupportedVersions()
|
||||
{
|
||||
return array('2.5.3');
|
||||
}
|
||||
public function getNewVersion()
|
||||
{
|
||||
return '2.5.4';
|
||||
}
|
||||
|
||||
public function upgrade()
|
||||
{
|
||||
Cache::clear();
|
||||
|
||||
assert($this->checkIfUpgradeSupported());
|
||||
|
||||
$newVersion = $this->getNewVersion();
|
||||
|
||||
$con = Propel::getConnection();
|
||||
//$con->beginTransaction();
|
||||
try {
|
||||
$this->toggleMaintenanceScreen(true);
|
||||
Cache::clear();
|
||||
|
||||
//Begin upgrade
|
||||
|
||||
//First, ensure there are no superadmins already.
|
||||
$numberOfSuperAdmins = CcSubjsQuery::create()
|
||||
->filterByDbType(UTYPE_SUPERADMIN)
|
||||
->count();
|
||||
|
||||
//Only create a super admin if there isn't one already.
|
||||
if ($numberOfSuperAdmins == 0)
|
||||
{
|
||||
//Find the "admin" user and promote them to superadmin.
|
||||
$adminUser = CcSubjsQuery::create()
|
||||
->filterByDbLogin('admin')
|
||||
->findOne();
|
||||
if (!$adminUser)
|
||||
{
|
||||
//TODO: Otherwise get the user with the lowest ID that is of type administrator:
|
||||
//
|
||||
$adminUser = CcSubjsQuery::create()
|
||||
->filterByDbType(UTYPE_ADMIN)
|
||||
->orderByDbId(Criteria::ASC)
|
||||
->findOne();
|
||||
|
||||
if (!$adminUser) {
|
||||
throw new Exception("Failed to find any users of type 'admin' ('A').");
|
||||
}
|
||||
}
|
||||
|
||||
$adminUser = new Application_Model_User($adminUser->getDbId());
|
||||
$adminUser->setType(UTYPE_SUPERADMIN);
|
||||
$adminUser->save();
|
||||
Logging::info($_SERVER['HTTP_HOST'] . ': ' . $newVersion . " Upgrade: Promoted user " . $adminUser->getLogin() . " to be a Super Admin.");
|
||||
}
|
||||
|
||||
//$con->commit();
|
||||
Application_Model_Preference::SetAirtimeVersion($newVersion);
|
||||
Cache::clear();
|
||||
|
||||
$this->toggleMaintenanceScreen(false);
|
||||
|
||||
return true;
|
||||
|
||||
} catch(Exception $e) {
|
||||
//$con->rollback();
|
||||
$this->toggleMaintenanceScreen(false);
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
}
|
15
airtime_mvc/application/views/scripts/billing/client.phtml
Normal file
15
airtime_mvc/application/views/scripts/billing/client.phtml
Normal file
|
@ -0,0 +1,15 @@
|
|||
<?php
|
||||
$this->form->getElement("submit")->setAttrib("class", "right-align");
|
||||
$this->form->getElement("country")->setAttrib("class", "right-align");
|
||||
$this->form->getElement("securityqid")->setAttrib("class", "right-align");
|
||||
?>
|
||||
<div class="ui-widget ui-widget-content block-shadow clearfix padded-strong billing-panel">
|
||||
<H2>Billing Account Details</H2>
|
||||
<?php if (isset($this->errorMessage)) {?>
|
||||
<div class="errors"><?php echo $this->errorMessage ?></div>
|
||||
<?php } else if (isset($this->successMessage)) {?>
|
||||
<div class="success"><?php echo $this->successMessage ?></div>
|
||||
<?php }?>
|
||||
|
||||
<?php echo $this->form ?>
|
||||
</div>
|
|
@ -0,0 +1 @@
|
|||
test
|
22
airtime_mvc/application/views/scripts/billing/invoices.phtml
Normal file
22
airtime_mvc/application/views/scripts/billing/invoices.phtml
Normal file
|
@ -0,0 +1,22 @@
|
|||
<div class="ui-widget ui-widget-content block-shadow clearfix padded-strong billing-panel">
|
||||
<H2>Invoices</H2>
|
||||
<p style="text-align: center;"><?=_("Tip: To pay an invoice, click \"View Invoice\"<br> and look for the \"Checkout\" button.")?></p>
|
||||
<table id="invoices_table">
|
||||
<tr class="header">
|
||||
<th>Date Issued</th>
|
||||
<th>Due Date</th>
|
||||
<th>Link</th>
|
||||
<th>Status</th>
|
||||
</tr>
|
||||
<?php
|
||||
foreach ($this->invoices as $invoice) {?>
|
||||
<tr>
|
||||
<td><?php echo $invoice["date"]?></td>
|
||||
<td><?php echo $invoice["duedate"]?></td>
|
||||
<td><a href="invoice?invoiceid=<?php echo $invoice["id"]?>">View Invoice</a></td>
|
||||
<td class="<?=$invoice["status"]==="Unpaid" ? "unpaid" : "";?>"><?php echo $invoice["status"]?></td>
|
||||
</tr>
|
||||
|
||||
<?php };?>
|
||||
</table>
|
||||
</div>
|
365
airtime_mvc/application/views/scripts/billing/upgrade.phtml
Normal file
365
airtime_mvc/application/views/scripts/billing/upgrade.phtml
Normal file
|
@ -0,0 +1,365 @@
|
|||
<?php
|
||||
$form = $this->form;
|
||||
$form->setAttrib('id', 'upgrade-downgrade');
|
||||
|
||||
?>
|
||||
<script type="text/javascript">
|
||||
<?php echo("var products = " . json_encode(BillingController::getProducts()) . ";\n");
|
||||
echo("var vatRate = " . json_encode(VAT_RATE) . ";");
|
||||
?>
|
||||
|
||||
var vatFieldId = "#customfields-7";
|
||||
var validVATNumber = false;
|
||||
var customerInEU = false;
|
||||
|
||||
//Disable annual billing for hobbyist plan
|
||||
function validatePlan()
|
||||
{
|
||||
if ($("#newproductid-25").is(":checked")) {
|
||||
$("#newproductbillingcycle-annually").prop("disabled", "true");
|
||||
$("label[for='newproductbillingcycle-annually']").addClass("disabled");
|
||||
$("#newproductbillingcycle-monthly").prop("checked", "true");
|
||||
} else {
|
||||
$("#newproductbillingcycle-annually").removeProp("disabled");
|
||||
$("label[for='newproductbillingcycle-annually']").removeClass("disabled");
|
||||
}
|
||||
}
|
||||
|
||||
function validateVATNumber()
|
||||
{
|
||||
$.post("/billing/vat-validator", { "vatnumber" : $(vatFieldId).val(), "country" : $("#country").val() })
|
||||
.success(function(data, textStatus, jqXHR) {
|
||||
if (data["result"]) {
|
||||
$("#vaterror").html("✓ Your VAT number is valid.");
|
||||
window.validVATNumber = true;
|
||||
} else {
|
||||
$("#vaterror").text("Error: Your VAT number is invalid.");
|
||||
window.validVATNumber = false;
|
||||
}
|
||||
recalculateTotals();
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
/* Recalculate subtotal and total */
|
||||
function recalculateTotals()
|
||||
{
|
||||
var newProductId = $("input[type='radio'][name='newproductid']:checked");
|
||||
if (newProductId.length > 0) {
|
||||
newProductId = newProductId.val();
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
var newProduct = null;
|
||||
for (var i = 0; i < products.length; i++)
|
||||
{
|
||||
if (products[i].pid == newProductId) {
|
||||
newProduct = products[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/** This calculation is all done on the server side too inside WHMCS so don't waste your time
|
||||
trying to hax0r it to get cheap Airtime Pro. */
|
||||
var subtotal = "0";
|
||||
var savings = "0";
|
||||
var subtotalNumber = "0";
|
||||
var billingPeriodString = "";
|
||||
if ($("#newproductbillingcycle-monthly").is(":checked")) {
|
||||
billingPeriodString = " per month";
|
||||
subtotalNumber = newProduct.pricing["USD"]["monthly"];
|
||||
subtotal = "$" + subtotalNumber + billingPeriodString;
|
||||
$("#savings").text("");
|
||||
|
||||
} else if ($("#newproductbillingcycle-annually").is(":checked")) {
|
||||
subtotalNumber = newProduct.pricing["USD"]["annually"];
|
||||
billingPeriodString = " per year";
|
||||
subtotal = "$" + subtotalNumber + billingPeriodString;
|
||||
savings = "$" + (newProduct.pricing["USD"]["monthly"]*12 - subtotalNumber).toFixed(2);
|
||||
$("#savings").html("You save: " + savings + " per year");
|
||||
}
|
||||
$("#subtotal").text(subtotal);
|
||||
|
||||
//Calculate total:
|
||||
var vatAmount = 0;
|
||||
if (window.customerInEU && !window.validVATNumber) {
|
||||
vatAmount = (parseFloat(subtotalNumber) * vatRate)/100.00;
|
||||
}
|
||||
var total = (vatAmount + parseFloat(subtotalNumber)).toFixed(2);
|
||||
$(".subtotal").text(subtotal);
|
||||
if (vatAmount > 0) {
|
||||
$("#tax").text("Plus VAT at " + parseInt(vatRate) + "%: $" + vatAmount.toFixed(2) + billingPeriodString);
|
||||
} else {
|
||||
$("#tax").text("");
|
||||
}
|
||||
$("#total").text("$" + total + billingPeriodString);
|
||||
}
|
||||
|
||||
function configureByCountry(countryCode)
|
||||
{
|
||||
//Disable the VAT tax field if the country is not in the EU.
|
||||
$.post("/billing/is-country-in-eu", { "country" : countryCode })
|
||||
.success(function(data, textStatus, jqXHR) {
|
||||
if (data["result"]) {
|
||||
$(vatFieldId).prop("disabled", false);
|
||||
$(vatFieldId).prop("readonly", false);
|
||||
$(vatFieldId + "-label").removeClass("disabled");
|
||||
$("#vat_disclaimer2").fadeIn(300);
|
||||
window.customerInEU = true;
|
||||
} else {
|
||||
$(vatFieldId).prop("disabled", true);
|
||||
$(vatFieldId).prop("readonly", true);
|
||||
$(vatFieldId).val("");
|
||||
$(vatFieldId + "-label").addClass("disabled");
|
||||
$("#vat_disclaimer2").fadeOut(0);
|
||||
window.customerInEU = false;
|
||||
}
|
||||
recalculateTotals();
|
||||
});
|
||||
}
|
||||
|
||||
$(document).ready(function() {
|
||||
|
||||
configureByCountry($("#country").val());
|
||||
recalculateTotals();
|
||||
|
||||
$("input[name='newproductid']").change(function() {
|
||||
validatePlan();
|
||||
recalculateTotals();
|
||||
});
|
||||
$("input[name='newproductbillingcycle']").change(function() {
|
||||
recalculateTotals();
|
||||
});
|
||||
|
||||
$("#country").change(function() {
|
||||
configureByCountry($(this).val());
|
||||
});
|
||||
|
||||
vatFieldChangeTimer = null;
|
||||
$(vatFieldId).change(function() {
|
||||
$("#vaterror").text("Please wait, checking VAT number...");
|
||||
|
||||
if (vatFieldChangeTimer) {
|
||||
clearTimeout(vatFieldChangeTimer);
|
||||
}
|
||||
|
||||
if ($(this).val() == "") {
|
||||
$("#vaterror").text("");
|
||||
window.validVATNumber = false;
|
||||
recalculateTotals();
|
||||
return;
|
||||
}
|
||||
vatFieldChangeTimer = setTimeout(function() {
|
||||
validateVATNumber(); //Validate and recalculate the totals
|
||||
}, 1500); //Wait 1.5 seconds before validating the VAT number
|
||||
});
|
||||
|
||||
$("#hobbyist_grid_price").text("$" + products[0].pricing["USD"]["monthly"] + " / month");
|
||||
$("#starter_grid_price").text("$" + products[1].pricing["USD"]["monthly"] + " / month");
|
||||
$("#plus_grid_price").text("$" + products[2].pricing["USD"]["monthly"] + " / month");
|
||||
$("#premium_grid_price").text("$" + products[3].pricing["USD"]["monthly"] + " / month");
|
||||
});
|
||||
</script>
|
||||
|
||||
<div class="ui-widget ui-widget-content block-shadow clearfix padded-strong billing-panel">
|
||||
<H2><?=_("Account Plans")?></H2>
|
||||
<H4><?=_("Upgrade today to get more listeners and storage space!")?></H4>
|
||||
<div class="pricing-grid">
|
||||
<table>
|
||||
<tr>
|
||||
<th>Hobbyist</th>
|
||||
<th>Starter</th>
|
||||
<th>Plus</th>
|
||||
<th>Premium</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>1 Stream
|
||||
</td>
|
||||
<td>2 Streams
|
||||
</td>
|
||||
<td>2 Streams
|
||||
</td>
|
||||
<td>3 Streams
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>64kbps Stream Quality
|
||||
</td>
|
||||
<td>64kbps and 128kbps Stream Quality
|
||||
</td>
|
||||
<td>64kbps and 196kbps Stream Quality
|
||||
</td>
|
||||
<td>64kbps, 128kbps, and 196kbps Stream Quality
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>5 Listeners
|
||||
</td>
|
||||
<td>40 Listeners per stream
|
||||
</td>
|
||||
<td>100 Listeners per stream
|
||||
</td>
|
||||
<td>500 Listeners per stream
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>2GB Storage
|
||||
</td>
|
||||
<td>5GB Storage
|
||||
</td>
|
||||
<td>30GB Storage
|
||||
</td>
|
||||
<td>150GB Storage
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Ticket, Email, Forum Support
|
||||
</td>
|
||||
<td>Live Chat, Ticket, Email, Forum Support
|
||||
</td>
|
||||
<td>Live Chat, Ticket, Email, Forum Support
|
||||
</td>
|
||||
<td>Live Chat, Ticket, Email, Forum Support
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
</td>
|
||||
<td>Save 15% if paid annually
|
||||
</td>
|
||||
<td>Save 15% if paid annually
|
||||
</td>
|
||||
<td>Save 15% if paid annually
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="price">
|
||||
<td id="hobbyist_grid_price">
|
||||
</td>
|
||||
<td id="starter_grid_price">
|
||||
</td>
|
||||
<td id="plus_grid_price">
|
||||
</td>
|
||||
<td id="premium_grid_price">
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<!--
|
||||
<p> <a target="_blank" href="https://www.airtime.pro/pricing"><?=_("View Plans")?></a> (Opens in a new window)</p>
|
||||
-->
|
||||
<p id="current_plan"><b>Current Plan:</b>
|
||||
<?php
|
||||
$currentProduct = BillingController::getClientCurrentAirtimeProduct();
|
||||
echo($currentProduct["name"]);
|
||||
//echo Application_Model_Preference::GetPlanLevel();
|
||||
?>
|
||||
</p>
|
||||
|
||||
<h3>Choose a plan:</h3>
|
||||
<form id="<?php echo $form->getId(); ?>" method="<?php echo $form->getMethod() ?>" action="<?php echo
|
||||
$form->getAction()?>" enctype="<?php echo $form->getEncType();?>">
|
||||
|
||||
<div id="plantype">
|
||||
<?php echo $form->newproductid ?>
|
||||
</div>
|
||||
<div id="billingcycle">
|
||||
<?php echo $form->newproductbillingcycle ?>
|
||||
</div>
|
||||
<div id="billingcycle_disclaimer">
|
||||
Save 15% on annual plans (Hobbyist plan excluded).
|
||||
</div>
|
||||
<div class="clearfix"></div>
|
||||
<div id="subtotal_box">
|
||||
<b>Subtotal:</b><br>
|
||||
<span class="subtotal"></span><br>
|
||||
<div id="savings"></div>
|
||||
</div>
|
||||
|
||||
<div id="vat_disclaimer">
|
||||
VAT will be added below if you are an EU resident without a valid VAT number.
|
||||
</div>
|
||||
|
||||
<h3>Enter your payment details:</h3>
|
||||
<?php if (isset($this->errorMessage)) {?>
|
||||
<div class="errors"><?php echo $this->errorMessage ?></div>
|
||||
<?php }?>
|
||||
<?php //echo $form ?>
|
||||
|
||||
<?php $billingForm = $form->getSubform("billing_client_info") ?>
|
||||
<div class="billing_col1">
|
||||
<?=$billingForm->firstname?>
|
||||
</div>
|
||||
<div class="billing_col2">
|
||||
<?=$billingForm->lastname?>
|
||||
</div>
|
||||
<div class="clearfix"></div>
|
||||
<div class="billing_col1">
|
||||
<?=$billingForm->companyname?>
|
||||
</div>
|
||||
<div class="billing_col2">
|
||||
<?=$billingForm->email?>
|
||||
</div>
|
||||
<div class="clearfix"></div>
|
||||
<div class="billing_col1">
|
||||
<?=$billingForm->address1?>
|
||||
</div>
|
||||
<div class="billing_col2">
|
||||
<?=$billingForm->address2?>
|
||||
</div>
|
||||
<div class="clearfix"></div>
|
||||
<div class="billing_col1">
|
||||
<?=$billingForm->city?>
|
||||
</div>
|
||||
<div class="billing_col2">
|
||||
<?=$billingForm->state?>
|
||||
</div>
|
||||
<div class="clearfix"></div>
|
||||
<div>
|
||||
<?=$billingForm->postcode?>
|
||||
</div>
|
||||
<div>
|
||||
<?=$billingForm->country?>
|
||||
</div>
|
||||
<div>
|
||||
<?=$billingForm->phonenumber?>
|
||||
</div>
|
||||
<div>
|
||||
<?=$billingForm->securityqid?>
|
||||
</div>
|
||||
<div>
|
||||
<?=$billingForm->securityqans?>
|
||||
</div>
|
||||
<div id="vat_disclaimer2"><p>VAT will be added to your invoice if you are an EU resident without a valid company VAT number.</p>
|
||||
</div>
|
||||
<div>
|
||||
<?=$billingForm->getElement("7"); ?>
|
||||
<div id="vaterror"></div>
|
||||
</div>
|
||||
<div class="clearfix"></div>
|
||||
|
||||
<div>
|
||||
<div class="billing_checkbox">
|
||||
<?=$billingForm->getElement("71")->renderViewHelper(); ?>
|
||||
</div>
|
||||
<?=$billingForm->getElement("71")->renderLabel(); ?>
|
||||
</div>
|
||||
<div class="clearfix"></div>
|
||||
|
||||
<div style="float:right; width: 200px;"><p>After submitting your order, you will be redirected to an invoice with payment buttons.</p>
|
||||
</div>
|
||||
<div id="paymentmethod">
|
||||
<?php echo $form->paymentmethod ?>
|
||||
</div>
|
||||
|
||||
<div class="clearfix"></div>
|
||||
<div id="total_box">
|
||||
<b>Subtotal:</b> <span class="subtotal"></span><br>
|
||||
<span id="tax"></span><br>
|
||||
<b>Total:</b> <span id="total"></span>
|
||||
</div>
|
||||
|
||||
<input type="submit" value="Submit Order"></input>
|
||||
<div class="clearfix"></div>
|
||||
</form>
|
||||
</div>
|
|
@ -157,7 +157,7 @@
|
|||
</ul>
|
||||
<?php endif; ?>
|
||||
</dd>
|
||||
<button type="submit" id="cu_save_user" class="btn btn-small right-floated"><?php echo _("Save")?></button>
|
||||
</dl>
|
||||
<button type="submit" id="cu_save_user" class="btn btn-small right-floated"><?php echo _("Save")?></button>
|
||||
</form>
|
||||
</div>
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
<div class="trial-box-calendar-gray"><?php echo _("days") ?></div>
|
||||
</div>
|
||||
<div class="trial-box-button">
|
||||
<a title="<?php echo _('Purchase your copy of Airtime')?>" href="https://account.sourcefabric.com/clientarea.php" target="_blank"><?php echo _("My Account") ?></a>
|
||||
<a title="<?php echo _("Purchase an Airtime Pro plan!")?>" href="/billing/upgrade" target="_blank"><?php echo _("My Account") ?></a>
|
||||
</div>
|
||||
</div>
|
||||
<?php }?>
|
||||
|
|
|
@ -26,6 +26,9 @@
|
|||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<div class="user-data" id="user_details_superadmin_message" style="display: none; margin-top: 105px; text-align: center;">
|
||||
<?=sprintf(_("Super Admin details can be changed in your <a href=\"%s\">Billing Settings</a>."), "/billing/client");?>
|
||||
</div>
|
||||
<div class="user-data simple-formblock" id="user_details">
|
||||
<?php echo $this->successMessage ?>
|
||||
<fieldset class="padded">
|
||||
|
|
226
airtime_mvc/public/css/billing.css
Normal file
226
airtime_mvc/public/css/billing.css
Normal file
|
@ -0,0 +1,226 @@
|
|||
@CHARSET "UTF-8";
|
||||
|
||||
.billing-panel
|
||||
{
|
||||
width: 400px;
|
||||
margin: 0 auto;
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
|
||||
.billing-panel h3
|
||||
{
|
||||
color: #222;
|
||||
}
|
||||
|
||||
.billing-panel h4
|
||||
{
|
||||
font-size: 1.25em;
|
||||
margin: 0px;
|
||||
color: #333;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
#upgrade-downgrade
|
||||
{
|
||||
border: 0px solid #000;
|
||||
margin: 0 auto;
|
||||
color: #000;
|
||||
}
|
||||
|
||||
#upgrade-downgrade label
|
||||
{
|
||||
color: rgb(28,28,28);
|
||||
}
|
||||
#upgrade-downgrade label.disabled
|
||||
{
|
||||
color: rgb(108,108,108);
|
||||
}
|
||||
|
||||
#upgrade-downgrade dl
|
||||
{
|
||||
width: 300px;
|
||||
}
|
||||
|
||||
#upgrade-downgrade dt, #upgrade-downgrade dd
|
||||
{
|
||||
margin: 0px;
|
||||
}
|
||||
|
||||
#upgrade-downgrade dd
|
||||
{
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.pricing-grid table
|
||||
{
|
||||
border-spacing: 0px;
|
||||
border-collapse: separate;
|
||||
border: 1px solid #777;
|
||||
width: 600px;
|
||||
margin-left: -100px;
|
||||
/*background-color: #555;*/
|
||||
table-layout: fixed;
|
||||
margin-top: 20px;
|
||||
margin-bottom: 20px;
|
||||
box-shadow: 0px 5px 5px rgba(0,0,0,0.5);
|
||||
}
|
||||
|
||||
.pricing-grid td, .pricing-grid th
|
||||
{
|
||||
border-bottom: 1px solid #999;
|
||||
border-right: 1px solid #bbb;
|
||||
background-color: #ccc;
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.pricing-grid th
|
||||
{
|
||||
border-top-left-radius: 5px;
|
||||
border-top-right-radius: 5px;
|
||||
border: 0px;
|
||||
}
|
||||
|
||||
|
||||
.pricing-grid tr.price td
|
||||
{
|
||||
text-align: right;
|
||||
background-color: #ddd;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
#current_plan
|
||||
{
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
#plantype
|
||||
{
|
||||
float: left;
|
||||
}
|
||||
|
||||
#billingcycle
|
||||
{
|
||||
float: left;
|
||||
margin-left: 30px;
|
||||
}
|
||||
|
||||
#billingcycle_disclaimer
|
||||
{
|
||||
float: left;
|
||||
margin-left: 30px;
|
||||
width: 200px;
|
||||
}
|
||||
|
||||
#vat_disclaimer
|
||||
{
|
||||
text-align: right;
|
||||
font-size: 0.9em;
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
|
||||
#vat_disclaimer2
|
||||
{
|
||||
float:right;
|
||||
width: 200px;
|
||||
}
|
||||
|
||||
#subtotal_box, #total_box
|
||||
{
|
||||
position: relative;
|
||||
text-align: right;
|
||||
margin-top: 30px;
|
||||
margin-bottom: 10px;
|
||||
border: 1px solid #777;
|
||||
background: #ccc;
|
||||
padding: 5px;
|
||||
}
|
||||
#total_box
|
||||
{
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
#total
|
||||
{
|
||||
border-bottom: 3px double;
|
||||
}
|
||||
|
||||
#savings
|
||||
{
|
||||
/*line-height: 30px;*/
|
||||
position: absolute;
|
||||
bottom: 5px;
|
||||
left: 5px;
|
||||
}
|
||||
|
||||
#paymentmethod
|
||||
{
|
||||
}
|
||||
|
||||
.billing_col1, .billing_col2
|
||||
{
|
||||
float: left;
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.billing_checkbox
|
||||
{
|
||||
float: left;
|
||||
margin-right: 5px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
#upgrade-downgrade input[type=submit]
|
||||
{
|
||||
float: right;
|
||||
}
|
||||
|
||||
#invoices_table
|
||||
{
|
||||
margin: 0 auto;
|
||||
border-spacing: 0px;
|
||||
border-collapse: separate;
|
||||
border: 1px solid #777;
|
||||
/*background-color: #555;*/
|
||||
table-layout: fixed;
|
||||
margin-top: 20px;
|
||||
margin-bottom: 35px;
|
||||
background: #ccc;
|
||||
}
|
||||
|
||||
#invoices_table tbody tr th
|
||||
{
|
||||
border: 0px;
|
||||
}
|
||||
|
||||
#invoices_table .header
|
||||
{
|
||||
box-shadow: 0px 2px 2px rgba(0,0,0,0.5);
|
||||
}
|
||||
|
||||
#invoices_table tr
|
||||
{
|
||||
border: 1px solid #555;
|
||||
}
|
||||
|
||||
#invoices_table .unpaid
|
||||
{
|
||||
color: #ff0000;
|
||||
}
|
||||
|
||||
/** This form is the separate one on the Billing Account Details page (BillingClient.php) */
|
||||
#clientdetails_form dt {
|
||||
float: left;
|
||||
clear: both;
|
||||
width: 50%;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
#clientdetails_form dd {
|
||||
float: left;
|
||||
margin-left: 0px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
#clientdetails_form .right-align
|
||||
{
|
||||
/*text-align: right;*/
|
||||
width: 100%;
|
||||
}
|
|
@ -43,6 +43,10 @@ if (file_exists('/usr/share/php/libzend-framework-php')) {
|
|||
set_include_path('/usr/share/php/libzend-framework-php' . PATH_SEPARATOR . get_include_path());
|
||||
}
|
||||
|
||||
//Upgrade directory
|
||||
set_include_path(APPLICATION_PATH . '/upgrade/' . PATH_SEPARATOR . get_include_path());
|
||||
|
||||
|
||||
/** Zend_Application */
|
||||
require_once 'Zend/Application.php';
|
||||
$application = new Zend_Application(
|
||||
|
|
|
@ -35,7 +35,7 @@ function makeTimeStamp(date){
|
|||
function dayClick(date, allDay, jsEvent, view){
|
||||
// The show from will be preloaded if the user is admin or program manager.
|
||||
// Hence, if the user if DJ then it won't open anything.
|
||||
if(userType == "A" || userType == "P"){
|
||||
if(userType == "S" || userType == "A" || userType == "P"){
|
||||
var now, today, selected, chosenDate, chosenTime;
|
||||
|
||||
now = adjustDateToServerDate(new Date(), serverTimezoneOffset);
|
||||
|
@ -163,7 +163,7 @@ function viewDisplay( view ) {
|
|||
if(($("#add-show-form").length == 1) && ($("#add-show-form").css('display')=='none') && ($('.fc-header-left > span').length == 5)) {
|
||||
|
||||
//userType is defined in bootstrap.php, and is derived from the currently logged in user.
|
||||
if(userType == "A" || userType == "P"){
|
||||
if(userType == "S" || userType == "A" || userType == "P"){
|
||||
makeAddShowButton();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,6 +4,17 @@ function populateForm(entries){
|
|||
$('.errors').remove();
|
||||
$('.success').remove();
|
||||
|
||||
if (entries.type === 'S')
|
||||
{
|
||||
$("#user_details").hide();
|
||||
$("#user_details_superadmin_message").show();
|
||||
$('#type').attr('disabled', '1');
|
||||
} else {
|
||||
$("#user_details").show();
|
||||
$("#user_details_superadmin_message").hide();
|
||||
$('#type').removeAttr('disabled');
|
||||
}
|
||||
|
||||
$('#user_id').val(entries.id);
|
||||
$('#login').val(entries.login);
|
||||
$('#first_name').val(entries.first_name);
|
||||
|
@ -57,6 +68,10 @@ function rowCallback( nRow, aData, iDisplayIndex ){
|
|||
} else if ( aData['type'] == "P" )
|
||||
{
|
||||
$('td:eq(3)', nRow).html( $.i18n._('Program Manager') );
|
||||
} else if ( aData['type'] == "S" )
|
||||
{
|
||||
$('td:eq(3)', nRow).html( $.i18n._('Super Admin') );
|
||||
$('td:eq(4)', nRow).html(""); //Disable deleting the super admin
|
||||
}
|
||||
|
||||
return nRow;
|
||||
|
@ -183,7 +198,7 @@ $(document).ready(function() {
|
|||
|
||||
var newUser = {login:"", first_name:"", last_name:"", type:"G", id:""};
|
||||
|
||||
$('#add_user_button').live('click', function(){populateForm(newUser)});
|
||||
$('#add_user_button').live('click', function(){populateForm(newUser);});
|
||||
|
||||
$('#save_user').live('click', function(){
|
||||
var data = $('#user_form').serialize();
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue