diff --git a/routes/admin.php b/routes/admin.php index b0e5e43..34fdf42 100644 --- a/routes/admin.php +++ b/routes/admin.php @@ -4,7 +4,7 @@ $app->get('', 'UserFrosting\Sprinkle\Dnsadmin\Controller\AdminController:pageZonesAdmin'); $app->get('/zones/z/{id}', 'UserFrosting\Sprinkle\Dnsadmin\Controller\AdminController:pageZoneEntriesAdmin'); -}); +})->add('authGuard'); $app->group('/modals/dnsadmin', function () use ($app) { $app->get('/create-zone', 'UserFrosting\Sprinkle\Dnsadmin\Controller\AdminController:modalCreateZone'); @@ -19,4 +19,4 @@ -}); +})->add('authGuard'); diff --git a/routes/api.php b/routes/api.php index 7d66af1..56770a5 100644 --- a/routes/api.php +++ b/routes/api.php @@ -17,4 +17,4 @@ -}); +})->add('authGuard'); diff --git a/src/Controller/AdminController.php b/src/Controller/AdminController.php index 8fbf5d6..c0e9d94 100644 --- a/src/Controller/AdminController.php +++ b/src/Controller/AdminController.php @@ -14,7 +14,8 @@ use UserFrosting\Fortress\Adapter\JqueryValidationAdapter; use UserFrosting\Sprinkle\Dnsadmin\Database\Models\Zone; use UserFrosting\Sprinkle\Dnsadmin\Database\Models\ZoneEntry; - +use Badcow\DNS\Rdata\RdataException; +use UserFrosting\Support\Exception\ForbiddenException; /** * Controller class that manages all of the DNS Admin front end UI @@ -34,6 +35,16 @@ class AdminController extends SimpleController */ public function pageZonesAdmin(Request $request, Response $response, $args) { + /** @var UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager */ + $authorizer = $this->ci->authorizer; + + /** @var UserFrosting\Sprinkle\Account\Model\User $currentUser */ + $currentUser = $this->ci->currentUser; + + if (!$authorizer->checkAccess($currentUser, 'uri_dnsadmin')) { + throw new ForbiddenException(); + } + // Get the zone create validation rules $schema_create = new RequestSchema('schema://requests/zone-create.yaml'); $validator_create = new JqueryValidationAdapter($schema_create, $this->ci->translator); @@ -62,6 +73,16 @@ public function pageZonesAdmin(Request $request, Response $response, $args) */ public function pageZoneEntriesAdmin(Request $request, Response $response, $args) { + /** @var UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager */ + $authorizer = $this->ci->authorizer; + + /** @var UserFrosting\Sprinkle\Account\Model\User $currentUser */ + $currentUser = $this->ci->currentUser; + + if (!$authorizer->checkAccess($currentUser, 'uri_dnsadmin')) { + throw new ForbiddenException(); + } + $zone = Zone::find($args['id']); if(!$zone) { @@ -98,6 +119,16 @@ public function pageZoneEntriesAdmin(Request $request, Response $response, $args */ public function modalCreateZone(Request $request, Response $response, $args) { + /** @var UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager */ + $authorizer = $this->ci->authorizer; + + /** @var UserFrosting\Sprinkle\Account\Model\User $currentUser */ + $currentUser = $this->ci->currentUser; + + if (!$authorizer->checkAccess($currentUser, 'uri_dnsadmin')) { + throw new ForbiddenException(); + } + return $this->ci->view->render($response, 'modals/zone.html.twig', [ "form" => [ "id" => "form-zone-create", @@ -118,6 +149,16 @@ public function modalCreateZone(Request $request, Response $response, $args) */ public function modalEditZone(Request $request, Response $response, $args) { + /** @var UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager */ + $authorizer = $this->ci->authorizer; + + /** @var UserFrosting\Sprinkle\Account\Model\User $currentUser */ + $currentUser = $this->ci->currentUser; + + if (!$authorizer->checkAccess($currentUser, 'uri_dnsadmin')) { + throw new ForbiddenException(); + } + $ms = $this->ci->alerts; $zone_id = $request->getQueryParam('id'); @@ -155,6 +196,16 @@ public function modalEditZone(Request $request, Response $response, $args) */ public function modalDeleteZone(Request $request, Response $response, $args) { + /** @var UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager */ + $authorizer = $this->ci->authorizer; + + /** @var UserFrosting\Sprinkle\Account\Model\User $currentUser */ + $currentUser = $this->ci->currentUser; + + if (!$authorizer->checkAccess($currentUser, 'uri_dnsadmin')) { + throw new ForbiddenException(); + } + $ms = $this->ci->alerts; $zone_id = $request->getQueryParam('id'); @@ -189,6 +240,16 @@ public function modalDeleteZone(Request $request, Response $response, $args) */ public function modalCreateZoneEntry(Request $request, Response $response, $args) { + /** @var UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager */ + $authorizer = $this->ci->authorizer; + + /** @var UserFrosting\Sprinkle\Account\Model\User $currentUser */ + $currentUser = $this->ci->currentUser; + + if (!$authorizer->checkAccess($currentUser, 'uri_dnsadmin')) { + throw new ForbiddenException(); + } + $ms = $this->ci->alerts; $zone_id = $request->getQueryParam('id'); @@ -223,6 +284,16 @@ public function modalCreateZoneEntry(Request $request, Response $response, $args */ public function modalEditZoneEntry(Request $request, Response $response, $args) { + /** @var UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager */ + $authorizer = $this->ci->authorizer; + + /** @var UserFrosting\Sprinkle\Account\Model\User $currentUser */ + $currentUser = $this->ci->currentUser; + + if (!$authorizer->checkAccess($currentUser, 'uri_dnsadmin')) { + throw new ForbiddenException(); + } + $ms = $this->ci->alerts; $zone_entry_id = $request->getQueryParam('id'); @@ -258,6 +329,16 @@ public function modalEditZoneEntry(Request $request, Response $response, $args) */ public function modalDeleteZoneEntry(Request $request, Response $response, $args) { + /** @var UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager */ + $authorizer = $this->ci->authorizer; + + /** @var UserFrosting\Sprinkle\Account\Model\User $currentUser */ + $currentUser = $this->ci->currentUser; + + if (!$authorizer->checkAccess($currentUser, 'uri_dnsadmin')) { + throw new ForbiddenException(); + } + $ms = $this->ci->alerts; $zone_entry_id = $request->getQueryParam('id'); @@ -307,6 +388,16 @@ public function getEntryTypes($zone_type) */ public function modalExportZoneEntry(Request $request, Response $response, $args) { + /** @var UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager */ + $authorizer = $this->ci->authorizer; + + /** @var UserFrosting\Sprinkle\Account\Model\User $currentUser */ + $currentUser = $this->ci->currentUser; + + if (!$authorizer->checkAccess($currentUser, 'uri_dnsadmin')) { + throw new ForbiddenException(); + } + $ms = $this->ci->alerts; $zone_id = $request->getQueryParam('id'); @@ -316,11 +407,14 @@ public function modalExportZoneEntry(Request $request, Response $response, $args $ms->addMessage('danger', 'Invalid Zone ID.'); return $response->withStatus(400); } + try { + $dnsConfigGenerator = $this->ci->dnsConfigGenerator; - $dnsConfigGenerator = $this->ci->dnsConfigGenerator; - - $config = $dnsConfigGenerator->getZoneConfig($zone); - + $config = $dnsConfigGenerator->getZoneConfig($zone); + } catch (RdataException $e) { + $ms->addMessage('danger', 'Error Generating Zone: '. $e->getMessage()); + return $response->withStatus(400); + } $zone = $zone->toArray(); $zone['config'] = $config; diff --git a/src/Controller/ApiController.php b/src/Controller/ApiController.php index be8e08d..e418e4b 100644 --- a/src/Controller/ApiController.php +++ b/src/Controller/ApiController.php @@ -18,6 +18,8 @@ use UserFrosting\Sprinkle\Dnsadmin\Database\Models\Zone; use UserFrosting\Sprinkle\Dnsadmin\Database\Models\ZoneEntry; use Illuminate\Database\Capsule\Manager as Capsule; +use Badcow\DNS\Rdata\RdataException; +use UserFrosting\Support\Exception\ForbiddenException; /** @@ -47,6 +49,15 @@ public function domainTransformer($domain) */ public function getZones(Request $request, Response $response, $args) { + /** @var UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager */ + $authorizer = $this->ci->authorizer; + + /** @var UserFrosting\Sprinkle\Account\Model\User $currentUser */ + $currentUser = $this->ci->currentUser; + + if (!$authorizer->checkAccess($currentUser, 'uri_dnsadmin')) { + throw new ForbiddenException(); + } // Get the GET parameters $params = $request->getQueryParams(); @@ -68,58 +79,68 @@ public function getZones(Request $request, Response $response, $args) */ public function createZone(Request $request, Response $response, $args) { - $params = $request->getParsedBody(); + /** @var UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager */ + $authorizer = $this->ci->authorizer; - // Start off by checking to make sure that the zone type is correct - $schema = new RequestSchema('schema://requests/zone-create.yaml'); + /** @var UserFrosting\Sprinkle\Account\Model\User $currentUser */ + $currentUser = $this->ci->currentUser; - $transformer = new RequestDataTransformer($schema); - $data = $transformer->transform($params); + if (!$authorizer->checkAccess($currentUser, 'uri_dnsadmin')) { + throw new ForbiddenException(); + } + + $params = $request->getParsedBody(); - $ms = $this->ci->alerts; + // Start off by checking to make sure that the zone type is correct + $schema = new RequestSchema('schema://requests/zone-create.yaml'); + + $transformer = new RequestDataTransformer($schema); + $data = $transformer->transform($params); + + $ms = $this->ci->alerts; - $validator = new ServerSideValidator($schema, $this->ci->translator); + $validator = new ServerSideValidator($schema, $this->ci->translator); - if(!$validator->validate($data)) { - $ms->addValidationErrors($validator); - return $response->withStatus(400); - } + if(!$validator->validate($data)) { + $ms->addValidationErrors($validator); + return $response->withStatus(400); + } - if($data['type'] == "normal") { - $data['name'] = $this->domainTransformer($data['name']); - } + if($data['type'] == "normal") { + $data['name'] = $this->domainTransformer($data['name']); + } - // Make sure that this zone doesn't already exist - $zone = Zone::where('name', $data['name'])->first(); + // Make sure that this zone doesn't already exist + $zone = Zone::where('name', $data['name'])->first(); - if($zone) { - $ms->addMessage('danger', 'A zone with that name already exists.'); - return $response->withStatus(400); - } + if($zone) { + $ms->addMessage('danger', 'A zone with that name already exists.'); + return $response->withStatus(400); + } - // Then add the zone to the Database + // Then add the zone to the Database - Capsule::transaction(function() use($data) { - $zone = new Zone(); + Capsule::transaction(function() use($data) { + $zone = new Zone(); - $zone->name = $data['name']; - $zone->type = $data['type']; - $zone->ttl = $data['ttl']; + $zone->name = $data['name']; + $zone->type = $data['type']; + $zone->ttl = $data['ttl']; - $zone->primary_dns = $this->domainTransformer($data['primary_dns']); - $zone->admin_domain = $this->domainTransformer($data['admin_domain']); + $zone->primary_dns = $this->domainTransformer($data['primary_dns']); + $zone->admin_domain = $this->domainTransformer($data['admin_domain']); - $zone->serial_number_mode = $data['serial_number_mode']; - $zone->serial_number = $data['serial_number']; + $zone->serial_number_mode = $data['serial_number_mode']; + $zone->serial_number = $data['serial_number']; - $zone->refresh = $data['refresh']; - $zone->retry = $data['retry']; - $zone->expiry = $data['expire']; - $zone->minimum = $data['minimum']; - $zone->save(); - }); + $zone->refresh = $data['refresh']; + $zone->retry = $data['retry']; + $zone->expiry = $data['expire']; + $zone->minimum = $data['minimum']; + $zone->save(); + }); - $ms->addMessage('success', "Successfully added zone '{$data['name']}'"); + $ms->addMessage('success', "Successfully added zone '{$data['name']}'"); } @@ -133,60 +154,70 @@ public function createZone(Request $request, Response $response, $args) */ public function editZone(Request $request, Response $response, $args) { - if(!isset($args['id'])) { - $ms->addMessage('danger', 'Zone Not Found.'); - return $response->withStatus(404); - } + /** @var UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager */ + $authorizer = $this->ci->authorizer; - $zone = Zone::find($args['id']); + /** @var UserFrosting\Sprinkle\Account\Model\User $currentUser */ + $currentUser = $this->ci->currentUser; - if(!$zone) { - $ms->addMessage('danger', 'Zone Not Found.'); - return $response->withStatus(404); - } + if (!$authorizer->checkAccess($currentUser, 'uri_dnsadmin')) { + throw new ForbiddenException(); + } - $params = $request->getParsedBody(); + if(!isset($args['id'])) { + $ms->addMessage('danger', 'Zone Not Found.'); + return $response->withStatus(404); + } - // Start off by checking to make sure that the zone type is correct - $schema = new RequestSchema('schema://requests/zone-edit.yaml'); + $zone = Zone::find($args['id']); - $transformer = new RequestDataTransformer($schema); - $data = $transformer->transform($params); + if(!$zone) { + $ms->addMessage('danger', 'Zone Not Found.'); + return $response->withStatus(404); + } - $ms = $this->ci->alerts; + $params = $request->getParsedBody(); - $validator = new ServerSideValidator($schema, $this->ci->translator); + // Start off by checking to make sure that the zone type is correct + $schema = new RequestSchema('schema://requests/zone-edit.yaml'); - if(!$validator->validate($data)) { - $ms->addValidationErrors($validator); - return $response->withStatus(400); - } + $transformer = new RequestDataTransformer($schema); + $data = $transformer->transform($params); - if($zone->type == "normal") { - $data['name'] = $this->domainTransformer($data['name']); - } + $ms = $this->ci->alerts; + + $validator = new ServerSideValidator($schema, $this->ci->translator); - Capsule::transaction(function() use($data, $zone) { + if(!$validator->validate($data)) { + $ms->addValidationErrors($validator); + return $response->withStatus(400); + } - $zone->name = $data['name']; + if($zone->type == "normal") { + $data['name'] = $this->domainTransformer($data['name']); + } - $zone->ttl = $data['ttl']; + Capsule::transaction(function() use($data, $zone) { - $zone->primary_dns = $this->domainTransformer($data['primary_dns']); - $zone->admin_domain = $this->domainTransformer($data['admin_domain']); + $zone->name = $data['name']; - $zone->serial_number_mode = $data['serial_number_mode']; - $zone->serial_number = $data['serial_number']; + $zone->ttl = $data['ttl']; - $zone->refresh = $data['refresh']; - $zone->retry = $data['retry']; - $zone->expiry = $data['expire']; - $zone->minimum = $data['minimum']; + $zone->primary_dns = $this->domainTransformer($data['primary_dns']); + $zone->admin_domain = $this->domainTransformer($data['admin_domain']); - $zone->save(); - }); + $zone->serial_number_mode = $data['serial_number_mode']; + $zone->serial_number = $data['serial_number']; - $ms->addMessage('success', "Successfully modified zone '{$data['name']}'"); + $zone->refresh = $data['refresh']; + $zone->retry = $data['retry']; + $zone->expiry = $data['expire']; + $zone->minimum = $data['minimum']; + + $zone->save(); + }); + + $ms->addMessage('success', "Successfully modified zone '{$data['name']}'"); } @@ -200,24 +231,34 @@ public function editZone(Request $request, Response $response, $args) */ public function deleteZone(Request $request, Response $response, $args) { - $ms = $this->ci->alerts; + /** @var UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager */ + $authorizer = $this->ci->authorizer; - $zone = Zone::find($args['id']); + /** @var UserFrosting\Sprinkle\Account\Model\User $currentUser */ + $currentUser = $this->ci->currentUser; - if(!$zone) { - $ms->addMessage('danger', 'Zone Not Found.'); - return $response->withStatus(404); - } + if (!$authorizer->checkAccess($currentUser, 'uri_dnsadmin')) { + throw new ForbiddenException(); + } - $zone_name = $zone->name; + $ms = $this->ci->alerts; - Capsule::transaction(function() use($zone) { - $zone->entries()->delete(); - $zone->delete(); + $zone = Zone::find($args['id']); - }); + if(!$zone) { + $ms->addMessage('danger', 'Zone Not Found.'); + return $response->withStatus(404); + } - $ms->addMessage('success', "Zone '$zone_name' has been deleted."); + $zone_name = $zone->name; + + Capsule::transaction(function() use($zone) { + $zone->entries()->delete(); + $zone->delete(); + + }); + + $ms->addMessage('success', "Zone '$zone_name' has been deleted."); } @@ -232,6 +273,16 @@ public function deleteZone(Request $request, Response $response, $args) */ public function getZoneEntries(Request $request, Response $response, $args) { + /** @var UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager */ + $authorizer = $this->ci->authorizer; + + /** @var UserFrosting\Sprinkle\Account\Model\User $currentUser */ + $currentUser = $this->ci->currentUser; + + if (!$authorizer->checkAccess($currentUser, 'uri_dnsadmin')) { + throw new ForbiddenException(); + } + $ms = $this->ci->alerts; $zone = Zone::find($args['id']); @@ -263,6 +314,16 @@ public function getZoneEntries(Request $request, Response $response, $args) */ public function createZoneEntry(Request $request, Response $response, $args) { + /** @var UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager */ + $authorizer = $this->ci->authorizer; + + /** @var UserFrosting\Sprinkle\Account\Model\User $currentUser */ + $currentUser = $this->ci->currentUser; + + if (!$authorizer->checkAccess($currentUser, 'uri_dnsadmin')) { + throw new ForbiddenException(); + } + $ms = $this->ci->alerts; $zone = Zone::find($args['id']); @@ -312,6 +373,16 @@ public function createZoneEntry(Request $request, Response $response, $args) */ public function editZoneEntry(Request $request, Response $response, $args) { + /** @var UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager */ + $authorizer = $this->ci->authorizer; + + /** @var UserFrosting\Sprinkle\Account\Model\User $currentUser */ + $currentUser = $this->ci->currentUser; + + if (!$authorizer->checkAccess($currentUser, 'uri_dnsadmin')) { + throw new ForbiddenException(); + } + $ms = $this->ci->alerts; $zone = Zone::find($args['zone_id']); @@ -368,6 +439,16 @@ public function editZoneEntry(Request $request, Response $response, $args) */ public function deleteZoneEntry(Request $request, Response $response, $args) { + /** @var UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager */ + $authorizer = $this->ci->authorizer; + + /** @var UserFrosting\Sprinkle\Account\Model\User $currentUser */ + $currentUser = $this->ci->currentUser; + + if (!$authorizer->checkAccess($currentUser, 'uri_dnsadmin')) { + throw new ForbiddenException(); + } + $ms = $this->ci->alerts; $zone = Zone::find($args['zone_id']); @@ -402,6 +483,16 @@ public function deleteZoneEntry(Request $request, Response $response, $args) */ public function saveConfiguration(Request $request, Response $response, $args) { + /** @var UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager */ + $authorizer = $this->ci->authorizer; + + /** @var UserFrosting\Sprinkle\Account\Model\User $currentUser */ + $currentUser = $this->ci->currentUser; + + if (!$authorizer->checkAccess($currentUser, 'uri_dnsadmin')) { + throw new ForbiddenException(); + } + $ms = $this->ci->alerts; $zone = Zone::find($args['id']); @@ -410,11 +501,14 @@ public function saveConfiguration(Request $request, Response $response, $args) $ms->addMessage('danger', 'Zone Not Found.'); return $response->withStatus(404); } + try { + $dnsConfigGenerator = $this->ci->dnsConfigGenerator; - $dnsConfigGenerator = $this->ci->dnsConfigGenerator; - - $dnsConfigGenerator->saveZone($zone); - + $dnsConfigGenerator->saveZone($zone); + } catch (RdataException $e) { + $ms->addMessage('danger', 'Error Generating Zone: '. $e->getMessage()); + return $response->withStatus(400); + } $ms->addMessage('Success', "Zone file was successfully saved"); } @@ -429,6 +523,16 @@ public function saveConfiguration(Request $request, Response $response, $args) */ public function setStatus(Request $request, Response $response, $args) { + /** @var UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager */ + $authorizer = $this->ci->authorizer; + + /** @var UserFrosting\Sprinkle\Account\Model\User $currentUser */ + $currentUser = $this->ci->currentUser; + + if (!$authorizer->checkAccess($currentUser, 'uri_dnsadmin')) { + throw new ForbiddenException(); + } + $ms = $this->ci->alerts; $zone = Zone::find($args['id']); diff --git a/src/Database/Migrations/v010/Permissions.php b/src/Database/Migrations/v010/Permissions.php new file mode 100644 index 0000000..1069678 --- /dev/null +++ b/src/Database/Migrations/v010/Permissions.php @@ -0,0 +1,44 @@ + new Permission([ + 'slug' => 'uri_dnsadmin', + 'name' => 'DNS Admin', + 'conditions' => 'always()', + 'description' => 'Gains access to the DNS Admin pages' + ]) + ]; + + foreach ($permissions as $id => $permission) { + $slug = $permission->slug; + $conditions = $permission->conditions; + // Skip if a permission with the same slug and conditions has already been added + if (!Permission::where('slug', $slug)->where('conditions', $conditions)->first()) { + $permission->save(); + } + } + + // Automatically add permissions to particular roles + $roleAdmin = Role::where('slug', 'site-admin')->first(); + if ($roleAdmin) { + $roleAdmin->permissions()->syncWithoutDetaching([ + $permissions['uri_dnsadmin']->id, + ]); + } + } +} diff --git a/templates/navigation/sidebar-menu.html.twig b/templates/navigation/sidebar-menu.html.twig index c52b8ac..adc9366 100644 --- a/templates/navigation/sidebar-menu.html.twig +++ b/templates/navigation/sidebar-menu.html.twig @@ -2,7 +2,9 @@ {% block navigation %} {{ parent() }} + {% if checkAccess('uri_dnsadmin') %}