Merge branch 'cc-5709-airtime-analyzer-buy-now-saas' into saas

Conflicts:
	airtime_mvc/application/controllers/LoginController.php
This commit is contained in:
Albert Santoni 2014-07-02 13:43:09 -04:00
commit 35e98e468d
36 changed files with 2083 additions and 105 deletions

View file

@ -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);

View file

@ -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");

View file

@ -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'
)
)
)
);

View 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&timestamp=$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());
}
}
}

View file

@ -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();

View file

@ -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,7 +91,17 @@ class LoginController extends Zend_Controller_Action
$this->_redirect('Showbuilder');
} else {
$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']);
@ -81,6 +111,7 @@ class LoginController extends Zend_Controller_Action
}
}
}
}
$this->view->message = $message;
$this->view->error = $error;

View file

@ -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 {

View file

@ -1,11 +1,11 @@
<?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);
@ -13,56 +13,36 @@ class UpgradeController extends Zend_Controller_Action
return;
}
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
//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);
$upgraders = array();
array_push($upgraders, new AirtimeUpgrader253());
array_push($upgraders, new AirtimeUpgrader254());
$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 2.5.3 OK");
->appendBody("Upgrade to Airtime " . $upgrader->getNewVersion() . " OK<br>");
$i = 0; //Start over, in case the upgrade handlers are not in ascending order.
}
}
} catch(Exception $e) {
$con->rollback();
unlink($maintenanceFile);
if (!$didWePerformAnUpgrade)
{
$this->getResponse()
->setHttpResponseCode(200)
->appendBody("No upgrade was performed. The current Airtime version is " . AirtimeUpgrader::getCurrentVersion() . ".<br>");
}
}
catch (Exception $e)
{
$this->getResponse()
->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;
}
}

View file

@ -62,7 +62,11 @@ class UserController extends Zend_Controller_Action
if ($formData['password'] != "xxxxxx") {
$user->setPassword($formData['password']);
}
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()) {
@ -188,6 +196,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
if ($files_action == "delete_cascade") {

View file

@ -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;
}

View 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;
}
}

View file

@ -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()) {

View file

@ -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');

View 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);
}
}

View 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');
}
}

View file

@ -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>&nbsp;-->
<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>

View file

@ -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

View file

@ -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();
}
}

View file

@ -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

View file

@ -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();
}

View file

@ -50,13 +50,19 @@ 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;
}

View file

@ -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)

View 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;
}
}
}

View 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>

View file

@ -0,0 +1 @@
test

View 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>

View 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("&#10003; 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>

View file

@ -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>

View file

@ -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 }?>

View file

@ -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">

View 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%;
}

View file

@ -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(

View file

@ -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();
}
}

View file

@ -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();