From 2d9d7f383c6512cf6862c249d55d6ce5a01cbf4b Mon Sep 17 00:00:00 2001 From: Deon George Date: Fri, 8 Nov 2013 22:02:32 +1100 Subject: [PATCH] Status updates, SSL updates --- .../classes/Controller/Admin/Module.php | 4 +- .../classes/Controller/Reseller/Account.php | 2 +- .../classes/Controller/Reseller/Summary.php | 43 +++++ .../classes/Controller/Reseller/Welcome.php | 2 +- application/classes/Model/Account.php | 2 +- .../classes/Model/Auth/RoleDefault.php | 27 --- application/classes/Model/Group.php | 4 +- application/classes/Model/Module.php | 8 +- application/classes/ORM.php | 31 ++-- application/classes/StaticList/YesNo.php | 6 +- application/media/guide/css/kodoc.css | 142 +++++++++++++++ .../views/module/method/admin/edit.php | 2 +- application/views/userguide/template.php | 110 ++++++++++++ .../adsl/classes/Controller/Admin/Adsl.php | 2 +- modules/charge/classes/Model/Charge.php | 6 +- .../classes/Controller/Reseller/Export.php | 2 +- modules/invoice/classes/Model/Invoice.php | 3 + .../classes/Controller/Admin/Product.php | 4 +- .../classes/Controller/Reseller/Service.php | 2 +- .../classes/Controller/User/Service.php | 2 +- modules/service/classes/Model/Service.php | 10 +- modules/service/views/service/user/view.php | 6 +- modules/ssl/classes/Controller/Admin/Ssl.php | 109 ------------ .../ssl/classes/Controller/Reseller/Ssl.php | 162 ++++++++++++++++++ modules/ssl/classes/Model/SSL/CA.php | 80 +++++++-- .../ssl/classes/Model/Service/Plugin/Ssl.php | 58 ++++--- modules/ssl/classes/Task/Ssl/Renew.php | 4 +- .../product/plugin/ssl/feature_summary.php | 3 - .../views/service/user/plugin/ssl/view.php | 38 ++-- modules/ssl/views/ssl/admin/add_view.php | 55 ------ modules/ssl/views/ssl/reseller/add_edit.php | 58 +++++++ 31 files changed, 688 insertions(+), 299 deletions(-) create mode 100644 application/classes/Controller/Reseller/Summary.php delete mode 100644 application/classes/Model/Auth/RoleDefault.php create mode 100644 application/media/guide/css/kodoc.css create mode 100644 application/views/userguide/template.php delete mode 100644 modules/ssl/classes/Controller/Admin/Ssl.php create mode 100644 modules/ssl/classes/Controller/Reseller/Ssl.php delete mode 100644 modules/ssl/views/ssl/admin/add_view.php create mode 100644 modules/ssl/views/ssl/reseller/add_edit.php diff --git a/application/classes/Controller/Admin/Module.php b/application/classes/Controller/Admin/Module.php index ae032d1a..e57a9f81 100644 --- a/application/classes/Controller/Admin/Module.php +++ b/application/classes/Controller/Admin/Module.php @@ -183,8 +183,8 @@ class Controller_Admin_Module extends Controller_Module { 'id'=>'ID', 'name'=>'Name', 'notes'=>'Notes', - 'status(TRUE)'=>'Active', - 'external(TRUE)'=>'External', + 'status'=>'Active', + 'external'=>'External', )) ->prepend(array( 'id'=>array('url'=>URL::link('admin','module/edit/')), diff --git a/application/classes/Controller/Reseller/Account.php b/application/classes/Controller/Reseller/Account.php index bf2e8538..c1907709 100644 --- a/application/classes/Controller/Reseller/Account.php +++ b/application/classes/Controller/Reseller/Account.php @@ -28,7 +28,7 @@ class Controller_Reseller_Account extends Controller_Account { ->jssort('customer') ->columns(array( 'id'=>'ID', - 'status(TRUE)'=>'Active', + 'status'=>'Active', 'accnum()'=>'Num', 'name(TRUE)'=>'Account', 'email'=>'Email', diff --git a/application/classes/Controller/Reseller/Summary.php b/application/classes/Controller/Reseller/Summary.php new file mode 100644 index 00000000..e9d0ca33 --- /dev/null +++ b/application/classes/Controller/Reseller/Summary.php @@ -0,0 +1,43 @@ +TRUE, + ); + + /** + */ + public function action_index() { + $result = array(); + + // ADSL + $svs = ORM::factory('Service')->where_authorised()->list_active(); + foreach ($svs as $so) { + if (! isset($result[$so->product->prod_plugin_file][$so->product->supplier()])) { + $result[$so->product->prod_plugin_file][$so->product->supplier()]['count'] = 0; + $result[$so->product->prod_plugin_file][$so->product->supplier()]['cost'] = 0; + $result[$so->product->prod_plugin_file][$so->product->supplier()]['revenue'] = 0; + } + + $result[$so->product->prod_plugin_file][$so->product->supplier()]['count']++; + $result[$so->product->prod_plugin_file][$so->product->supplier()]['cost'] += $so->product->cost(TRUE); + $result[$so->product->prod_plugin_file][$so->product->supplier()]['revenue'] += $so->revenue(TRUE); + } + + Block::factory() + ->title('Revenue / Cost Analysis') + ->title_icon('icon-info-sign') + ->span(6) + ->body(View::factory('summary/reseller/index')->set('o',$result)); + } +} +?> diff --git a/application/classes/Controller/Reseller/Welcome.php b/application/classes/Controller/Reseller/Welcome.php index f544f4ad..15a5394e 100644 --- a/application/classes/Controller/Reseller/Welcome.php +++ b/application/classes/Controller/Reseller/Welcome.php @@ -94,7 +94,7 @@ class Controller_Reseller_Welcome extends Controller_Welcome { 'date_payment'=>'Pay Date', 'account->accnum()'=>'Num', 'account->name()'=>'Account', - 'account->status(TRUE)'=>'Active', + 'account->status'=>'Active', 'total(TRUE)'=>'Total', 'balance(TRUE)'=>'Balance', )) diff --git a/application/classes/Model/Account.php b/application/classes/Model/Account.php index 6909a8a2..69979717 100644 --- a/application/classes/Model/Account.php +++ b/application/classes/Model/Account.php @@ -36,7 +36,7 @@ class Model_Account extends Model_Auth_UserDefault { array('Config::date',array(':value')), ), 'status'=>array( - array('StaticList_YesNo::get',array(':value')), + array('StaticList_YesNo::get',array(':value',TRUE)), ), ); diff --git a/application/classes/Model/Auth/RoleDefault.php b/application/classes/Model/Auth/RoleDefault.php deleted file mode 100644 index 20297fec..00000000 --- a/application/classes/Model/Auth/RoleDefault.php +++ /dev/null @@ -1,27 +0,0 @@ -_table_columns[$column])) - return NULL; - - if (! $render) - return $this->display($column); - - return View::factory(Config::theme().'/label/bool') - ->set('label',$this->$column ? 'label-success' : '') - ->set('column',$this->display($column)); - } -} -?> diff --git a/application/classes/Model/Group.php b/application/classes/Model/Group.php index 7a8ff786..afa3f20e 100644 --- a/application/classes/Model/Group.php +++ b/application/classes/Model/Group.php @@ -8,7 +8,7 @@ * @copyright (c) 2009-2013 Open Source Billing * @license http://dev.osbill.net/license.html */ -class Model_Group extends Model_Auth_RoleDefault { +class Model_Group extends Model_Auth_Role { // Relationships protected $_has_many = array( 'account'=>array('through'=>'account_group'), @@ -20,7 +20,7 @@ class Model_Group extends Model_Auth_RoleDefault { protected $_display_filters = array( 'status'=>array( - array('StaticList_YesNo::get',array(':value')), + array('StaticList_YesNo::get',array(':value',TRUE)), ), ); diff --git a/application/classes/Model/Module.php b/application/classes/Model/Module.php index 97479f5b..dcae16b4 100644 --- a/application/classes/Model/Module.php +++ b/application/classes/Model/Module.php @@ -26,20 +26,16 @@ class Model_Module extends ORM_OSB { protected $_display_filters = array( 'external'=>array( - array('StaticList_YesNo::get',array(':value')), + array('StaticList_YesNo::get',array(':value',TRUE)), ), 'name'=>array( array('strtoupper',array(':value')), ), 'status'=>array( - array('StaticList_YesNo::get',array(':value')), + array('StaticList_YesNo::get',array(':value',TRUE)), ), ); - public function external($render=FALSE) { - return $this->label_bool('external',$render); - } - /** * Return an instance of this Module's Model * diff --git a/application/classes/ORM.php b/application/classes/ORM.php index 804953bc..e38e3696 100644 --- a/application/classes/ORM.php +++ b/application/classes/ORM.php @@ -65,6 +65,18 @@ abstract class ORM extends Kohana_ORM { return $this->where('status','=',TRUE); } + /** + * Determine if the account is authoised by the user + */ + public function authorised(Model $o=NULL,Model_Account $ao=NULL,$aid='account_id') { + if (is_null($o)) + $o = $this; + if (is_null($ao)) + $ao = Auth::instance()->get_user(); + + return in_array($o->{$aid},$ao->RTM->customers($ao->RTM)); + } + /** * Overrides Kohana cache so that it can be globally disabled. */ @@ -137,21 +149,6 @@ abstract class ORM extends Kohana_ORM { $this->_display_filters = Arr::merge($this->_display_filters,$filters); } - /** - * Show a bootstrap label button for a field with a boolean value - */ - public function label_bool($column,$render=FALSE) { - if (! isset($this->_table_columns[$column])) - return NULL; - - if (! $render) - return $this->display($column); - - return View::factory(Config::theme().'/label/bool') - ->set('label',$this->$column ? 'label-success' : '') - ->set('column',$this->display($column)); - } - /** * Function help to find records that are active */ @@ -218,10 +215,6 @@ abstract class ORM extends Kohana_ORM { return $x; } - public function status($render=FALSE) { - return $this->label_bool('status',$render); - } - public function where_active() { return $this->_where_active(); } diff --git a/application/classes/StaticList/YesNo.php b/application/classes/StaticList/YesNo.php index ff5b2c93..04f36dc3 100644 --- a/application/classes/StaticList/YesNo.php +++ b/application/classes/StaticList/YesNo.php @@ -17,11 +17,13 @@ class StaticList_YesNo extends StaticList { ); } - public static function get($value) { + public static function get($value,$format=FALSE) { if (! $value) $value = 0; - return static::factory()->_get($value); + return $format ? View::factory(Config::theme().'/label/bool') + ->set('label',$value ? 'label-success' : '') + ->set('column',static::factory()->_get($value)) : $value; } } ?> diff --git a/application/media/guide/css/kodoc.css b/application/media/guide/css/kodoc.css new file mode 100644 index 00000000..4ef5252d --- /dev/null +++ b/application/media/guide/css/kodoc.css @@ -0,0 +1,142 @@ +@import url('api.css'); + +html { background: #FFFFFF; font-size: 70%; } +body { margin: 0; } +ol ol, ol ul, ul ul, ul ol { margin-bottom: 0; } +a img { border: 0; } + +h1 small, +h2 small, +h3 small, +h4 small { font-weight: normal; font-size: 0.7em; } +h5 small, +h6 small { font-weight: normal; font-size: 0.8em; } + +dl dd { margin-left: 0; } + +code { + color:#6BAA3D; + font-family: Consolas, 'Bitstream Vera Sans Mono', 'Courier New', Courier, monospace; +} + +pre { + background:#fff; + border-radius:10px; + padding:1.5em; + font-size:0.9em; + margin-top:1.5em; + margin-bottom:1.5em; + overflow:auto; +} + +.highlighted div.line { + font-size:1em; + line-height:1.3 !important; +} + +table { + background:#eee; + border-left: 1px solid #CCC; + border-top: 1px solid #CCC; + margin-bottom:1.5em; + width: 100%; +} + +table td, table th { + padding:0.4em 0.8em; + line-height:1.4286; + border-right: 1px solid #CCC; + border-bottom: 1px solid #CCC; +} + +table th { + background: #ddd; +} + +table tr:nth-child(even) { + background: #fff; +} + +.caps { text-transform: uppercase; font-size: 0.8em; font-weight: normal; } +.status { text-transform: lowercase; font-variant: small-caps; font-weight: bold; color: #911; } +.container .colborder { border-color: #d3d8bc; } + +.note { + padding: 1.5em; + padding-left: 5em; + background: #e8efcf url('../img/lightbulb_48.png') no-repeat 1em center; + border-radius: 0.6em; + overflow: auto; +} + +h1 a.permalink, +h2 a.permalink, +h3 a.permalink, +h4 a.permalink, +h5 a.permalink, +h6 a.permalink { + font-size: 0.6em; + line-height: 100%; + vertical-align: middle; + margin-left: 1em; + padding: 0; + font-weight: normal; + display: none; + position: inherit; +} + +h1:hover a.permalink, +h2:hover a.permalink, +h3:hover a.permalink, +h4:hover a.permalink, +h5:hover a.permalink, +h6:hover a.permalink { + display: inline; +} + + +#kodoc-header, +#kodoc-content, +#kodoc-footer { float: left; clear: both; width: 100%; } + +#kodoc-header { padding: 20px 0 2em; background: #FAFAFC; } + #kodoc-logo { display: block; float: left; } + #kodoc-menu { float: right; margin-top: 12px; background: #050505; -moz-border-radius: 5px; -webkit-border-radius: 5px; } + #kodoc-menu ul { float: left; margin: 0; padding: 0 0.5em 0 0; } + #kodoc-menu li { display: block; float: left; margin: 0; padding: 0; } + #kodoc-menu li.first { padding-left: 0.5em; } + #kodoc-menu li a { display: block; height: 32px; line-height: 32px; padding: 0 0.8em; border-right: solid 1px #050505; border-left: solid 1px #050505; letter-spacing: 0.05em; text-decoration: none; text-transform: uppercase; color: #FCFCFE; font-size: 90%; } + #kodoc-menu li.first a { border-left: 0; } + #kodoc-menu li.last a { border-right: 0; } + #kodoc-menu li a:hover { background: #353535; color: #FCFCFE; text-shadow: #FFFFFF 0 0 1px; } + +#kodoc-content { background: #FCFCFE; } + #kodoc-content .wrapper { min-height: 390px; padding: 1em 0; } + #kodoc-content div.page-toc { float: right; margin: 1em; margin-top: 0; padding: 1em; background: #fff; border: solid 0.1em #e8efcf; border-radius: 0.6em; } + #kodoc-content p.intro { padding: 1em 20px; padding-left: 20px; margin: 0 -20px; font-size: 1.2em; } + #kodoc-content a { color: #004352; } + #kodoc-content a:hover { color: #00758f; } + #kodoc-content a:active { text-decoration: none; } + +#kodoc-breadcrumb { margin: 0 0 1em; padding: 0 0 0.5em; list-style: none; border-bottom: solid 1px #e8efcf; } + #kodoc-breadcrumb li { display: inline-block; margin: 0; padding: 0 0.4em 0 0; text-transform: uppercase; font-size: 11px; } + #kodoc-breadcrumb li:before { content: 'ยป'; padding-right: 0.4em; } + #kodoc-breadcrumb li a { color: #999; text-decoration: none; } + +#kodoc-topics { } + #kodoc-topics ul, + #kodoc-topics ol { list-style-type:none; margin: 0; padding: 0;} + #kodoc-topics ul li, + #kodoc-topics ol li { margin:0; padding: 0; margin-left: 1em; } + #kodoc-topics ul li a.current, + #kodoc-topics ol li a.current { font-weight: bold; } + #kodoc-topics span, + #kodoc-topics a { display: block; padding: 0; margin: 0; } + #kodoc-topics span { cursor: pointer; } + #kodoc-topics span.toggle { display: block; float: left; width: 1em; padding-right: 0.4em; margin-left: -1.4em; text-align: center; } + + #kodoc-topics li span { cursor:pointer; } + +#kodoc-footer { padding: 1em 0; background: #FAFAFC; color: #050505; text-shadow: #FFFFFF 0.1em 0.1em 1px; font-size: 0.9em; } + #kodoc-footer a { color: #809397; } + #kodoc-footer div.last { text-align: right; } diff --git a/application/views/module/method/admin/edit.php b/application/views/module/method/admin/edit.php index f3e6327c..e46137ca 100644 --- a/application/views/module/method/admin/edit.php +++ b/application/views/module/method/admin/edit.php @@ -28,7 +28,7 @@ id,TRUE),$go->display('name')); ?> display('notes'); ?> - label_bool('status',TRUE); ?> + display('status'); ?> id,$o->has('group',$go)); ?> diff --git a/application/views/userguide/template.php b/application/views/userguide/template.php new file mode 100644 index 00000000..454a31a7 --- /dev/null +++ b/application/views/userguide/template.php @@ -0,0 +1,110 @@ + + + + + +<?php echo $title ?> | Kohana <?php echo __('User Guide'); ?> + + $media) echo HTML::style($style, array('media' => $media), NULL, TRUE), "\n" ?> + + + + + + + +
+
+ +
+
    +
  • + +
  • + load('userguide.api_browser')): ?> +
  • + +
  • + +
+
+
+
+ +
+
+
+
+
    + $title): ?> + +
  • + +
  • + + +
+
+
+
+ +
+
+
+ + + +
+ + + Documentation comments powered by Disqus + +
+
+
+
+ + + + + + + + diff --git a/modules/adsl/classes/Controller/Admin/Adsl.php b/modules/adsl/classes/Controller/Admin/Adsl.php index b294c8d9..e852ed4d 100644 --- a/modules/adsl/classes/Controller/Admin/Adsl.php +++ b/modules/adsl/classes/Controller/Admin/Adsl.php @@ -53,7 +53,7 @@ class Controller_Admin_Adsl extends Controller_Adsl { 'service'=>'Service Login', 'plan->service->id'=>'Service', 'plan->service_number'=>'Service', - 'plan->service->status(TRUE)'=>'Active', + 'plan->service->status'=>'Active', 'up_peak'=>'Up Peak', 'down_peak'=>'Down Peak', 'up_offpeak'=>'Up OffPeak', diff --git a/modules/charge/classes/Model/Charge.php b/modules/charge/classes/Model/Charge.php index 45e50046..8098f6ff 100644 --- a/modules/charge/classes/Model/Charge.php +++ b/modules/charge/classes/Model/Charge.php @@ -36,7 +36,7 @@ class Model_Charge extends ORM_OSB { array('Config::date',array(':value')), ), 'processed'=>array( - array('StaticList_YesNo::get',array(':value')), + array('StaticList_YesNo::get',array(':value',TRUE)), ), 'sweep_type'=>array( array('StaticList_SweepType::get',array(':value')), @@ -59,10 +59,6 @@ class Model_Charge extends ORM_OSB { } } - public function processed($render=FALSE) { - return $this->label_bool('processed',$render); - } - public function total($format=FALSE) { $result = $this->quantity * $this->amount; diff --git a/modules/export/classes/Controller/Reseller/Export.php b/modules/export/classes/Controller/Reseller/Export.php index 91d36c15..d557426c 100644 --- a/modules/export/classes/Controller/Reseller/Export.php +++ b/modules/export/classes/Controller/Reseller/Export.php @@ -81,7 +81,7 @@ class Controller_Reseller_Export extends Controller_Export { 'id'=>'ID', 'account->name(TRUE)'=>'Account', 'date_orig'=>'Date', - 'status(TRUE)'=>'Active', + 'status'=>'Active', 'total(TRUE)'=>'Total', 'exported'=>'Exported', ),$emo->display ? $emo->display : array())) diff --git a/modules/invoice/classes/Model/Invoice.php b/modules/invoice/classes/Model/Invoice.php index cf26b47c..192e157d 100644 --- a/modules/invoice/classes/Model/Invoice.php +++ b/modules/invoice/classes/Model/Invoice.php @@ -125,6 +125,9 @@ class Model_Invoice extends ORM_OSB implements Cartable { * Returns the array of Email Template Objects */ public function reminders($key=NULL,$format=FALSE) { + if (is_null($key) AND ! $this->reminders) + return array(); + $prefix = 'task_invoice_'; if (is_null($key)) { diff --git a/modules/product/classes/Controller/Admin/Product.php b/modules/product/classes/Controller/Admin/Product.php index 4775957e..4317000b 100644 --- a/modules/product/classes/Controller/Admin/Product.php +++ b/modules/product/classes/Controller/Admin/Product.php @@ -167,7 +167,7 @@ $(document).ready(function() { array( 'id'=>array('label'=>'ID','url'=>URL::link('admin','product/view/')), 'title()'=>array('label'=>'Details'), - 'status(TRUE)'=>array('label'=>'Active'), + 'status'=>array('label'=>'Active'), 'prod_plugin_file'=>array('label'=>'Plugin Name'), 'prod_plugin_data'=>array('label'=>'Plugin Data'), 'price_type'=>array('label'=>'Price Type'), @@ -199,7 +199,7 @@ $(document).ready(function() { 'account->accnum()'=>array(), 'account->name()'=>array('label'=>'Account'), 'name()'=>array('label'=>'Details'), - 'status(TRUE)'=>array('label'=>'Active'), + 'status'=>array('label'=>'Active'), 'price(TRUE,TRUE)'=>array('label'=>'Price','align'=>'right'), ), array( diff --git a/modules/service/classes/Controller/Reseller/Service.php b/modules/service/classes/Controller/Reseller/Service.php index 2f885481..bee13ef7 100644 --- a/modules/service/classes/Controller/Reseller/Service.php +++ b/modules/service/classes/Controller/Reseller/Service.php @@ -32,7 +32,7 @@ class Controller_Reseller_Service extends Controller_Service { 'service_name()'=>'Service', 'recur_schedule'=>'Billing', 'price(TRUE,TRUE)'=>'Price', - 'status(TRUE)'=>'Active', + 'status'=>'Active', 'account->accnum()'=>'Cust ID', 'account->name()'=>'Customer', )) diff --git a/modules/service/classes/Controller/User/Service.php b/modules/service/classes/Controller/User/Service.php index de8d5204..9da5b38a 100644 --- a/modules/service/classes/Controller/User/Service.php +++ b/modules/service/classes/Controller/User/Service.php @@ -48,7 +48,7 @@ class Controller_User_Service extends Controller_Service { 'service_name()'=>'Service', 'recur_schedule'=>'Billing', 'price(TRUE,TRUE)'=>'Price', - 'status(TRUE)'=>'Active', + 'status'=>'Active', )) ->prepend(array( 'id'=>array('url'=>URL::link('user','service/view/')), diff --git a/modules/service/classes/Model/Service.php b/modules/service/classes/Model/Service.php index c3e4aa47..2ebed119 100644 --- a/modules/service/classes/Model/Service.php +++ b/modules/service/classes/Model/Service.php @@ -39,11 +39,14 @@ class Model_Service extends ORM_OSB { 'date_next_invoice'=>array( array('Config::date',array(':value')), ), + 'price_override'=>array( + array('Currency::display',array(':value')), + ), 'recur_schedule'=>array( array('StaticList_RecurSchedule::get',array(':value')), ), 'status'=>array( - array('StaticList_YesNo::get',array(':value')), + array('StaticList_YesNo::get',array(':value',TRUE)), ), ); @@ -226,12 +229,15 @@ class Model_Service extends ORM_OSB { /** * Return the service charge */ - public function price($tax=FALSE,$format=FALSE) { + public function price($tax=FALSE,$format=FALSE,$original=FALSE) { $x = $this->product->keyget('price_group',$this->recur_schedule); // @todo This index shouldnt be hard coded. $p = ! is_null($this->price) ? $this->price : $x[$this->price_group]['price_base']; + if (! $original AND ! is_null($this->price_override)) + $p = $this->price_override; + if ($tax) $p = Tax::add($p); diff --git a/modules/service/views/service/user/view.php b/modules/service/views/service/user/view.php index 5247798b..2cec255b 100644 --- a/modules/service/views/service/user/view.php +++ b/modules/service/views/service/user/view.php @@ -8,13 +8,13 @@
account->name(),$o->account->accnum()); ?>
Service Active
-
label_bool('status',TRUE); ?>
+
display('status'); ?>
Billing Period
display('recur_schedule');?>
Cost
-
price(TRUE,TRUE); if ($o->pending_change()) echo ' *'; ?>
+
price_override) ? sprintf('%s ',$o->price(TRUE,TRUE,TRUE)) : ''). $o->price(TRUE,TRUE); if ($o->pending_change()) echo ' *'; ?>
price) OR ($o->price<=$o->product->price($o->price_group,$o->recur_schedule,'price_base'))) : ?>
Service
@@ -28,7 +28,7 @@
paid_to(TRUE); ?>
Date Next Invoice
-
display('date_next_invoice'); ?>
+
suspend_billing ? '%s' : '%s',$o->display('date_next_invoice')); ?>
Current Invoices Due
due(TRUE); ?>
diff --git a/modules/ssl/classes/Controller/Admin/Ssl.php b/modules/ssl/classes/Controller/Admin/Ssl.php deleted file mode 100644 index 30cacaf4..00000000 --- a/modules/ssl/classes/Controller/Admin/Ssl.php +++ /dev/null @@ -1,109 +0,0 @@ -TRUE, - 'list'=>TRUE, - 'view'=>TRUE, - ); - - public function action_list() { - Block::add(array( - 'title'=>_('SSL CA Certificates'), - 'body'=>Table::display( - ORM::factory('SSL_CA')->find_all(), - 25, - array( - 'id'=>array('label'=>'ID','url'=>URL::link('admin','ssl/view/')), - 'sign_cert'=>array('label'=>'Cert'), - 'issuer()'=>array('label'=>'Issuer'), - 'valid_to(TRUE)'=>array('label'=>'Expires'), - ), - array( - 'page'=>TRUE, - 'type'=>'select', - 'form'=>URL::link('admin','ssl/view'), - )), - )); - } - - private function add_view($id=NULL,$output='') { - $so = ORM::factory('SSL_CA',$id); - - if ($_POST) { - if ($so->values($_POST)->changed()) { - try { - $so->save(); - SystemMessage::add(array( - 'title'=>'SSL Certificate Saved', - 'type'=>'info', - 'body'=>'SSL Certificate successfully recorded.', - )); - - } catch (ORM_Validation_Exception $e) { - $errors = $e->errors('models'); - - SystemMessage::add(array( - 'title'=>'SSL Certificate NOT saved', - 'type'=>'error', - 'body'=>join("\n",array_values($errors)), - )); - - $so->reload(); - } - } - } - - $output .= Form::open(); - $output .= View::factory('ssl/admin/add_view') - ->set('o',$so); - $output .= Form::submit('submit','submit',array('class'=>'form_button')); - $output .= Form::close(); - - return $output; - } - - public function action_add() { - Block::add(array( - 'title'=>_('Add SSL CA Certificate'), - 'body'=>$this->add_view(), - )); - } - - public function action_view() { - list($id,$output) = Table::page(__METHOD__); - - Block::add(array( - 'title'=>sprintf('%s: %s (%s)',_('View SSL CA Certificate'),$id,ORM::factory('SSL_CA',$id)->display('sign_cert')), - 'body'=>$this->add_view($id,$output), - )); - - Block::add(array( - 'title'=>_('Services using this Certificate'), - 'body'=>Table::display( - ORM::factory('SSL_CA',$id)->list_issued(), - 25, - array( - 'id'=>array('label'=>'ID','url'=>URL::link('admin','service/view/')), - 'plugin()->dn()'=>array('label'=>'Cert'), - 'plugin()->valid_to(TRUE)'=>array('label'=>'Expires'), - ), - array( - 'page'=>TRUE, - 'type'=>'select', - 'form'=>URL::link('admin','service/view'), - )), - )); - - } -} -?> diff --git a/modules/ssl/classes/Controller/Reseller/Ssl.php b/modules/ssl/classes/Controller/Reseller/Ssl.php new file mode 100644 index 00000000..c7f7b86d --- /dev/null +++ b/modules/ssl/classes/Controller/Reseller/Ssl.php @@ -0,0 +1,162 @@ +TRUE, + 'edit'=>TRUE, + 'list'=>TRUE, + 'renew'=>TRUE, + 'listchildca'=>TRUE, + 'listchildcrt'=>TRUE, + ); + + public function action_list() { + Block::factory() + ->title('SSL CA Certificates') + ->title_icon('icon-th-list') + ->body(Table::factory() + ->jssort('ca') + ->data(ORM::factory('SSL_CA')->where_authorised($this->ao)->find_all()) + ->columns(array( + 'id'=>'ID', + 'sign_cert'=>'Cert', + 'valid_to(TRUE)'=>'Expires', + 'validParent(TRUE)'=>'Valid', + 'childca(TRUE)'=>'cCA', + 'childcrt(TRUE)'=>'Crts', + 'issuer()'=>'Issuer', + )) + ->prepend(array( + 'id'=>array('url'=>URL::link('reseller','ssl/edit/')), + 'childca(TRUE)'=>array('url_resolve'=>URL::link('reseller','ssl/listchildca/%id%')), + 'childcrt(TRUE)'=>array('url_resolve'=>URL::link('reseller','ssl/listchildcrt/%id%')), + )) + ); + } + + public function action_listchildca() { + list($id,$output) = Table::page(__METHOD__); + $sco = ORM::factory('SSL_CA',$id); + + if ($sco->childca()) + Block::factory() + ->title(sprintf('SSL CA Certificates for CA: %s',$sco->dn())) + ->title_icon('icon-th-list') + ->body(Table::factory() + ->jssort('ca') + ->data($sco->where_authorised($this->ao)->list_childca()) + ->columns(array( + 'id'=>'ID', + 'sign_cert'=>'Cert', + 'ski()'=>'Identifier', + 'valid_to(TRUE)'=>'Expires', + 'validParent(TRUE)'=>'Valid', + 'childca()'=>'cCA', + 'childcrt()'=>'Crts', + )) + ->prepend(array( + 'id'=>array('url'=>URL::link('reseller','ssl/edit/')), + 'childca()'=>array('url_resolve'=>URL::link('reseller','ssl/listchildca/%id%')), + 'childcrt()'=>array('url_resolve'=>URL::link('reseller','ssl/listchildcrt/%id%')), + )) + ); + + if ($sco->childcrt()) + $this->action_listchildcrt(); + } + + public function action_listchildcrt() { + list($id,$output) = Table::page(__METHOD__); + $sco = ORM::factory('SSL_CA',$id); + + Block::factory() + ->title(sprintf('SSL Certificates for CA: %s',$sco->dn())) + ->title_icon('icon-th-list') + ->body(Table::factory() + ->jssort('crt') + ->data($sco->where_authorised($this->ao)->list_childcrt()) + ->columns(array( + 'id'=>'ID', + 'plugin()->dn()'=>'Cert', + 'plugin()->valid_to(TRUE)'=>'Expires', + )) + ->prepend(array( + 'id'=>array('url'=>URL::link('user','service/view/')), + )) + ); + } + + public function action_add() { + Block::factory() + ->type('form-horizontal') + ->title('Add/View SSL CA') + ->title_icon('icon-wrench') + ->body($this->add_edit()); + } + + public function action_edit() { + list($id,$output) = Table::page(__METHOD__); + + Block::factory() + ->type('form-horizontal') + ->title(sprintf('%s: %s',_('Add/View SSL CA'),$id)) + ->title_icon('icon-wrench') + ->body($this->add_edit($id,$output)); + } + + public function action_renew() { + $so = ORM::factory('Service',Request::current()->param('id')); + + if (! $so->loaded() OR ! Auth::instance()->authorised($so->account)) { + SystemMessage::factory() + ->title('SSL Certificate not updated') + ->type('error') + ->body('Either the Service doesnt exist, or you are not authorised to see it'); + + HTTP::redirect('welcome'); + } + + $so->plugin()->renew(); + HTTP::redirect(URL::link('user','service/view/'.$so->id)); + } + + private function add_edit($id=NULL,$output='') { + $sco = ORM::factory('SSL_CA',$id); + + if ($_POST) { + // Entry updated + if ($sco->values($_POST)->check()) { + try { + $sco->save(); + SystemMessage::factory() + ->title('Record updated') + ->type('success') + ->body(_('Your Charge record has been recorded/updated.')); + + } catch (ORM_Validation_Exception $e) { + $errors = $e->errors('models'); + + SystemMessage::factory() + ->title('Record NOT updated') + ->type('error') + ->body(join('
',array_values($errors))); + + $sco->reload(); + } + } + } + + return View::factory('ssl/reseller/add_edit') + ->set('o',$sco); + } +} +?> diff --git a/modules/ssl/classes/Model/SSL/CA.php b/modules/ssl/classes/Model/SSL/CA.php index 65e73821..d65f5480 100644 --- a/modules/ssl/classes/Model/SSL/CA.php +++ b/modules/ssl/classes/Model/SSL/CA.php @@ -13,7 +13,11 @@ class Model_SSL_CA extends ORM_OSB { protected $_updated_column = FALSE; // Relationships + protected $_belongs_to = array( + 'parent'=>array('model'=>'ssl_ca','foreign_key'=>'parent_ssl_ca_id'), + ); protected $_has_many = array( + 'children'=>array('model'=>'ssl_ca','far_key'=>'id','foreign_key'=>'parent_ssl_ca_id'), 'service'=>array('through'=>'service__ssl'), ); @@ -23,6 +27,14 @@ class Model_SSL_CA extends ORM_OSB { ), ); + public function filters() { + return array( + 'parent_ssl_ca_id'=>array( + array(array($this,'filter_getParent')), + ) + ); + } + public function rules() { return array( 'sign_cert'=>array( @@ -30,19 +42,11 @@ class Model_SSL_CA extends ORM_OSB { array(array($this,'isCA')), ), 'parent_ssl_ca_id'=>array( - array(array($this,'Rule_ParentExists')), + array(array($this,'rule_parentExist')), ), ); } - public function filters() { - return array( - 'parent_ssl_ca_id'=>array( - array(array($this,'Filter_GetParent')), - ) - ); - } - private $_so = NULL; /** @@ -51,10 +55,13 @@ class Model_SSL_CA extends ORM_OSB { public function __call($name,$args) { $m = 'get_'.$name; + if (is_null($this->_so)) + return NULL; + if (method_exists($this->_so,$m)) return $this->_so->{$m}($args); else - throw new Kohana_Exception('Unknown method :method',array(':method'=>$name)); + throw new Kohana_Exception('Unknown method :method for :class',array(':method'=>$m,':class'=>get_class($this->_so))); } // We want to inject the SSL object into this Model @@ -67,6 +74,42 @@ class Model_SSL_CA extends ORM_OSB { return $this; } + /** + * List the child CA certs + */ + public function childca($children=FALSE) { + $result = 0; + + if ($children) + foreach ($this->list_childca() as $cao) + $result += $cao->childca($children); + + return $result+$this->list_childca()->count(); + } + + public function childcrt($children=FALSE) { + $result = 0; + + if ($children) + foreach ($this->list_childca() as $cao) + $result += $cao->childcrt($children); + + return $result+$this->list_childcrt()->count(); + } + + /** + * Make sure we have our parent in the DB too + */ + public function validParent($format=FALSE) { + $result = NULL; + + // If we are a root cert, we are valid + if (is_null($this->parent_ssl_ca_id) AND $this->isRoot()) + return StaticList_YesNo::get(TRUE,$format); + + return StaticList_YesNo::get($this->aki_keyid() == $this->parent->ski(),$format); + } + // If we change the SSL certificate, we need to reload our SSL object public function values(array $values, array $expected = NULL) { parent::values($values,$expected); @@ -77,20 +120,23 @@ class Model_SSL_CA extends ORM_OSB { return $this; } - // @todo This could require some optimisation, by storing the keyid in the database and then getting the DB just to return that parent - public function Filter_GetParent() { + public function filter_getParent() { foreach (ORM::factory($this->_object_name)->find_all() as $sco) if ($sco->aki_keyid() == $this->aki_keyid()) return $sco->id; } - public function Rule_ParentExists() { - // Our parent_ssl_ca_id should have been populated by Filter_GetParent(). - return $this->parent_ssl_ca_id OR $this->isRoot(); + public function list_childca() { + return $this->children->find_all(); } - public function list_issued() { - return $this->service->find_all(); + public function list_childcrt() { + return $this->service->where_active()->find_all(); + } + + public function rule_parentExist() { + // Our parent_ssl_ca_id should have been populated by filter_GetParent(). + return $this->parent_ssl_ca_id OR $this->isRoot(); } } ?> diff --git a/modules/ssl/classes/Model/Service/Plugin/Ssl.php b/modules/ssl/classes/Model/Service/Plugin/Ssl.php index 329dba40..1c954dad 100644 --- a/modules/ssl/classes/Model/Service/Plugin/Ssl.php +++ b/modules/ssl/classes/Model/Service/Plugin/Ssl.php @@ -18,7 +18,7 @@ class Model_Service_Plugin_Ssl extends Model_Service_Plugin { 'service'=>array(), ); protected $_has_one = array( - 'SSL_CA'=>array('far_key'=>'ssl_ca_id','foreign_key'=>'id'), + 'ca'=>array('model'=>'SSL_CA','far_key'=>'ssl_ca_id','foreign_key'=>'id'), ); protected $_display_filters = array( @@ -31,9 +31,23 @@ class Model_Service_Plugin_Ssl extends Model_Service_Plugin { ); // Required abstract functions - public function username_value() {} // Not used + public function expire($format=FALSE) { + return $this->_so->get_valid_to($format); + } + + public function name() { + return ($this->cert AND $this->ca->loaded()) ? sprintf('%s:%s',$this->ca->subject(),$this->display('cert')) : $this->display('csr'); + } + public function password_value() {} // Not used + public function service_view() { + return View::factory('service/user/plugin/ssl/view') + ->set('o',$this); + } + + public function username_value() {} // Not used + private $_so = NULL; /** @@ -58,6 +72,10 @@ class Model_Service_Plugin_Ssl extends Model_Service_Plugin { return $this; } + public function validCA() { + return $this->ca->validParent(); + } + // If we change the SSL certificate, we need to reload our SSL object public function values(array $values, array $expected = NULL) { parent::values($values,$expected); @@ -68,19 +86,6 @@ class Model_Service_Plugin_Ssl extends Model_Service_Plugin { return $this; } - public function expire($format=FALSE) { - return $this->_so->get_valid_to($format); - } - - public function name() { - return ($this->cert AND $this->SSL_CA->loaded()) ? sprintf('%s:%s',$this->SSL_CA->subject(),$this->display('cert')) : $this->display('csr'); - } - - public function service_view() { - return View::factory('service/user/plugin/ssl/view') - ->set('o',$this); - } - /** * Get specific service details for use in other modules * For Example: Invoice @@ -103,7 +108,7 @@ class Model_Service_Plugin_Ssl extends Model_Service_Plugin { public function admin_update() { return View::factory('service/admin/plugin/ssl/update') ->set('mediapath',Route::get('default/media')) - ->set('so',$this); + ->set('o',$this); } public function download_button() { @@ -134,17 +139,21 @@ class Model_Service_Plugin_Ssl extends Model_Service_Plugin { return $result; } - public function renew() { - $d = SSL::instance($this->cert); + /** + * Renew an SSL Certificate + */ + public function renew($force=FALSE) { + $sslo = SSL::instance($this->cert); $ssl_conf = Kohana::$config->load('ssl'); - // @todo change this so an admin can force this. - $force = TRUE; // If our certificate is not old enough skip - if ($d->get_valid_to() > time()+$ssl_conf['min_renew_days']*86400 AND ! $force) + if ($sslo->get_valid_to() > time()+$ssl_conf['min_renew_days']*86400 AND ! $force) return FALSE; - $res = openssl_csr_sign($this->csr,$this->SSL_CA->sign_cert,$this->SSL_CA->sign_pk,$this->service->product->plugin()->days,array( + $today = mktime(0,0,0,date('n'),date('j'),date('Y')); + $days = (int)(($this->service->invoiced_to()-$today)/86400); + + $res = openssl_csr_sign($this->csr,$this->ca->sign_cert,$this->ca->sign_pk,$days,array( 'config'=>$ssl_conf['config'], 'x509_extensions'=>$this->service->product->plugin()->extensions, 'digest_alg'=>'sha1', @@ -155,11 +164,12 @@ class Model_Service_Plugin_Ssl extends Model_Service_Plugin { $this->save(); return TRUE; + } else { print_r(array( 'csr'=>$this->csr, - 'ca'=>$this->SSL_CA->sign_cert, - 'capk'=>$this->SSL_CA->sign_pk, + 'ca'=>$this->ca->sign_cert, + 'capk'=>$this->ca->sign_pk, 'days'=>$this->service->product->plugin()->days, 'ssl'=>$ssl_conf, 'x509e'=>$this->service->product->plugin()->extensions diff --git a/modules/ssl/classes/Task/Ssl/Renew.php b/modules/ssl/classes/Task/Ssl/Renew.php index 61a727d5..35627d17 100644 --- a/modules/ssl/classes/Task/Ssl/Renew.php +++ b/modules/ssl/classes/Task/Ssl/Renew.php @@ -12,14 +12,14 @@ class Task_SSL_Renew extends Minion_Task { protected $_options = array( 'id'=>NULL, + 'force'=>FALSE, ); /** * Renew a certificate */ protected function _execute(array $params) { - // @todo, Change this to be a SSL id, maybe list all the certs expiring - ORM::factory('Service',$params['id'])->plugin()->renew(); + ORM::factory('Service',$params['id'])->plugin()->renew($params['force']); } } ?> diff --git a/modules/ssl/views/product/plugin/ssl/feature_summary.php b/modules/ssl/views/product/plugin/ssl/feature_summary.php index a481b080..01300a8f 100644 --- a/modules/ssl/views/product/plugin/ssl/feature_summary.php +++ b/modules/ssl/views/product/plugin/ssl/feature_summary.php @@ -3,9 +3,6 @@
-
Validatity Days
-
display('days'); ?>
-
Type
display('extensions'); ?>
diff --git a/modules/ssl/views/service/user/plugin/ssl/view.php b/modules/ssl/views/service/user/plugin/ssl/view.php index e45cb007..75b947f9 100644 --- a/modules/ssl/views/service/user/plugin/ssl/view.php +++ b/modules/ssl/views/service/user/plugin/ssl/view.php @@ -3,14 +3,26 @@
-
Subject
+
DN
dn(); ?>
-
Issuer
-
issuerdn(); ?>
+
Serial Number
+
serial(); ?>
-
CA
-
SSL_CA->loaded() ? $o->SSL_CA->subject() : $o->issuer(); ?>
+
Subject Key Id
+
ski(); ?>
+ +
Issuer
+
+ validCA() AND $o->authorised($o->ca)) : ?> + ca->id,$o->issuer()); ?> + + issuer(); ?> + +
+ +
Issuer Serial
+
aki_keyid(), $o->aki_serial()); ?>
Valid From
valid_from(TRUE); ?>
@@ -18,15 +30,12 @@
Valid To
valid_to(TRUE); ?>
-
Serial Number
-
serial(); ?>
+
Hash
+
hash(); ?>
Version
version(); ?>
-
Hash
-
hash(); ?>
-
Algorithm
algorithm(); ?>
@@ -37,5 +46,12 @@ Certificate
cert; ?>
- download_button(); ?> + download_button(); + if ($ao=Auth::instance()->get_user() AND ($ao->isAdmin() OR $ao->isReseller()) AND $o->service->status AND ($o->valid_to()-(Kohana::$config->load('ssl.min_renew_days')*86400) <= time()) AND $o->service->paid_to() > time()) : + echo Form::open(URL::link('reseller','ssl/renew/'.$o->service->id)); + echo Form::button('submit','Renew',array('class'=>'btn btn-primary')); + endif + ?> + diff --git a/modules/ssl/views/ssl/admin/add_view.php b/modules/ssl/views/ssl/admin/add_view.php deleted file mode 100644 index 050ce37b..00000000 --- a/modules/ssl/views/ssl/admin/add_view.php +++ /dev/null @@ -1,55 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
DNdn(); ?>
Subjectsubject(),$o->serial()); ?>
Subject Key IDski(); ?>
Issuerissuer(),$o->aki_serial()); ?>
Issuer Key IDaki_keyid(); ?>
CAisCA()); ?>
Valid Fromvalid_from(TRUE); ?>
Valid Tovalid_to(TRUE); ?>
Hashhash(); ?>
Versionversion(); ?>
Key Algorithmalgorithm(); ?>
Private Keysign_pk,array('cols'=>64,'rows'=>13)); ?>
Certificatesign_cert,array('cols'=>64,'rows'=>13)); ?>
diff --git a/modules/ssl/views/ssl/reseller/add_edit.php b/modules/ssl/views/ssl/reseller/add_edit.php new file mode 100644 index 00000000..1168423d --- /dev/null +++ b/modules/ssl/views/ssl/reseller/add_edit.php @@ -0,0 +1,58 @@ +
+
+ +
+ +
Subject
+
subject(); ?>
+ +
DN
+
dn(); ?>
+ +
Serial
+
serial(); ?>
+ +
Subject Key Id
+
ski(); ?>
+ + isRoot()) : ?> +
Issuer
+
+ validParent()) : ?> + parent_ssl_ca_id,$o->issuer()); ?> + + issuer(); ?> + +
+ +
Issuer Serial
+
aki_keyid(), $o->aki_serial()); ?>
+ +
Issuer Valid
+
validParent(TRUE); ?>
+ + +
Valid From
+
valid_from(TRUE); ?>
+ +
Valid To
+
valid_to(TRUE); ?>
+ +
Hash
+
hash(); ?>
+ +
Version
+
version(); ?>
+ +
Key Algorithm
+
algorithm(); ?>
+ +
+
+ + sign_pk,array('class'=>'span6','label'=>'Private Key','placeholder'=>'Private Key','nowysihtml'=>TRUE,'style'=>'font-family: monospace;','rows'=>Form::textarea_rows($o->sign_pk))); ?> + sign_cert,array('class'=>'span6','label'=>'Public Certificate','placeholder'=>'Public Certificate','nowysihtml'=>TRUE,'style'=>'font-family: monospace;','rows'=>Form::textarea_rows($o->sign_cert))); ?> + + 'btn btn-primary')); ?> +
+