PageRenderTime 25ms CodeModel.GetById 11ms RepoModel.GetById 0ms app.codeStats 0ms

/application/modules/default/controllers/OrganizationReportController.php

https://bitbucket.org/areeves42/openfisma
PHP | 332 lines | 238 code | 40 blank | 54 comment | 21 complexity | 3885074335c7f23ce2f453b5ca92ef50 MD5 | raw file
  1. <?php
  2. /**
  3. * Copyright (c) 2008 Endeavor Systems, Inc.
  4. *
  5. * This file is part of OpenFISMA.
  6. *
  7. * OpenFISMA is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
  8. * License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later
  9. * version.
  10. *
  11. * OpenFISMA is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
  12. * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
  13. * details.
  14. *
  15. * You should have received a copy of the GNU General Public License along with OpenFISMA. If not, see
  16. * {@link http://www.gnu.org/licenses/}.
  17. */
  18. /**
  19. * Reports for organizations (in the system inventory module)
  20. *
  21. * @author Mark E. Haase
  22. * @copyright (c) Endeavor Systems, Inc. 2009 {@link http://www.endeavorsystems.com}
  23. * @license http://www.openfisma.org/content/license GPLv3
  24. * @package Controllers
  25. */
  26. class OrganizationReportController extends Fisma_Zend_Controller_Action_Security
  27. {
  28. public function init()
  29. {
  30. parent::init();
  31. $this->_helper->reportContextSwitch()
  32. ->addActionContext('personnel', array('html', 'pdf', 'xls'))
  33. ->addActionContext('privacy', array('html', 'pdf', 'xls'))
  34. ->addActionContext('security-authorization', array('html', 'pdf', 'xls'))
  35. ->addActionContext('documentation-compliance', array('html', 'pdf', 'xls'))
  36. ->initContext();
  37. }
  38. /**
  39. * Check that the user has the privilege to run reports
  40. */
  41. public function preDispatch()
  42. {
  43. parent::preDispatch();
  44. $this->_acl->requireArea('system_inventory_report');
  45. }
  46. /**
  47. * List ISO and ISSO personnel for each organization and system
  48. *
  49. * This is the one report which is not constrained by the organizations which a user is allowed to view. This report
  50. * is kind of like a phone book for security personnel, so all users are allowed to view all entries in it.
  51. *
  52. * @GETAllowed
  53. */
  54. public function personnelAction()
  55. {
  56. $personnelQuery = Doctrine_Query::create()
  57. ->select('r.nickname, o.nickname, u.nameLast, u.nameFirst, u.phoneOffice, u.email')
  58. ->from('Organization o')
  59. ->leftJoin('o.System s')
  60. ->leftJoin('o.OrganizationType orgType')
  61. ->leftJoin('o.UserRole ur')
  62. ->leftJoin('ur.Role r')
  63. ->leftJoin('ur.User u')
  64. ->andWhere('orgType.nickname = ?', array('system'))
  65. ->andWhere('s.sdlcPhase <> ?', 'disposal')
  66. ->andWhere('r.nickname LIKE ? OR r.nickname LIKE ?', array('ISO', 'ISSO'))
  67. ->andWhere("u.locktype IS NULL OR u.locktype<>'manual'")
  68. ->orderBy('o.lft, o.rgt, u.nameLast, u.nameFirst')
  69. ->setHydrationMode(Doctrine::HYDRATE_SCALAR);
  70. $personnel = $personnelQuery->execute();
  71. $report = new Fisma_Report();
  72. $report->setTitle('Personnel Report')
  73. ->addColumn(new Fisma_Report_Column('System', true))
  74. ->addColumn(new Fisma_Report_Column('Role', true))
  75. ->addColumn(new Fisma_Report_Column('Last Name', true))
  76. ->addColumn(new Fisma_Report_Column('First Name', true))
  77. ->addColumn(new Fisma_Report_Column('Office Phone', true))
  78. ->addColumn(new Fisma_Report_Column('E-mail', true))
  79. ->setData($personnel);
  80. $this->_helper->reportContextSwitch()->setReport($report);
  81. }
  82. /**
  83. * List privacy status for all systems
  84. *
  85. * @GETAllowed
  86. */
  87. public function privacyAction()
  88. {
  89. $storageNamespace = 'Organization.Privacy.Report';
  90. $orgTypeId = $this->_helper->OrganizationType
  91. ->getOrganizationTypeIdByStorageOrRequest($this->_me->id, $storageNamespace);
  92. $filterForm = $this->_helper->OrganizationType->getFilterForm($orgTypeId);
  93. $this->view->orgTypeId = $orgTypeId;
  94. $this->view->organizationTypeForm = $filterForm;
  95. $this->view->namespace = $storageNamespace;
  96. $this->view->url = "/organization-report/privacy/format/html";
  97. $baseQuery = CurrentUser::getInstance()->getOrganizationsByPrivilegeQuery('organization', 'read');
  98. if ('none' != $orgTypeId) {
  99. $systemQuery = $baseQuery->select('bureau.nickname AS name')
  100. ->addSelect('o.nickname AS name');
  101. } else {
  102. $systemQuery = $baseQuery->select('o.nickname AS name');
  103. }
  104. $systemQuery
  105. ->addSelect('systemData.hasPii AS has_pii')
  106. ->addSelect('systemData.piaRequired AS pia_required')
  107. ->addSelect(
  108. 'IF(\'YES\' = systemData.piaRequired,
  109. IF(systemData.piaUrl IS NULL, \'NO\', \'YES\'),
  110. \'N/A\') AS pia_url'
  111. )
  112. ->addSelect('systemData.sornRequired AS sorn_required')
  113. ->addSelect(
  114. 'IF(\'YES\' = systemData.sornRequired,
  115. IF(systemData.sornUrl IS NULL, \'NO\', \'YES\'),
  116. \'N/A\') AS sorn_url'
  117. )
  118. ->innerJoin('o.System systemData')
  119. ->innerJoin('o.OrganizationType orgType')
  120. ->leftJoin('Organization bureau')
  121. ->andWhere('orgType.nickname = ?', array('system'))
  122. ->andWhere('systemData.sdlcPhase <> ?', 'disposal')
  123. ->andWhere('o.lft BETWEEN bureau.lft and bureau.rgt')
  124. ->orderBy('bureau.nickname, o.nickname')
  125. ->setHydrationMode(Doctrine::HYDRATE_SCALAR);
  126. if ('none' != $orgTypeId) {
  127. $systemQuery->andWhere('bureau.orgTypeId = ?', $orgTypeId);
  128. }
  129. $systems = $systemQuery->execute();
  130. $report = new Fisma_Report();
  131. $report->setTitle('Privacy Report');
  132. $orgType = Doctrine::getTable('OrganizationType')->find($orgTypeId);
  133. if ('none' != $orgTypeId) {
  134. $report->addColumn(new Fisma_Report_Column(ucwords($orgType->nickname), true))
  135. ->addColumn(new Fisma_Report_Column('System', true));
  136. } else {
  137. $report->addColumn(new Fisma_Report_Column('System', true));
  138. }
  139. $report->addColumn(new Fisma_Report_Column('Contains PII', true))
  140. ->addColumn(new Fisma_Report_Column('PIA Required', true))
  141. ->addColumn(new Fisma_Report_Column('PIA Completed', true, 'Fisma.TableFormat.yesNo'))
  142. ->addColumn(new Fisma_Report_Column('SORN Required', true))
  143. ->addColumn(new Fisma_Report_Column('SORN Completed', true, 'Fisma.TableFormat.yesNo'))
  144. ->setData($systems);
  145. $this->_helper->reportContextSwitch()->setReport($report);
  146. }
  147. /**
  148. * List security authorization status for all systems
  149. *
  150. * @GETAllowed
  151. */
  152. public function securityAuthorizationAction()
  153. {
  154. $storageNamespace = 'Organization.SecurityAuth.Report';
  155. $orgTypeId = $this->_helper->OrganizationType
  156. ->getOrganizationTypeIdByStorageOrRequest($this->_me->id, $storageNamespace);
  157. $filterForm = $this->_helper->OrganizationType->getFilterForm($orgTypeId);
  158. $this->view->orgTypeId = $orgTypeId;
  159. $this->view->organizationTypeForm = $filterForm;
  160. $this->view->namespace = $storageNamespace;
  161. $this->view->url = "/organization-report/security-authorization/format/html";
  162. $systemQuery = CurrentUser::getInstance()->getOrganizationsByPrivilegeQuery('organization', 'read');
  163. $systemQuery->select('o.nickname AS name');
  164. if ('none' != $orgTypeId) {
  165. $systemQuery->addSelect('\'\' AS parent');
  166. }
  167. $systemQuery->addSelect('IFNULL(systemData.fipsCategory, \'NONE\') AS fips_category')
  168. ->addSelect('IFNULL(systemData.controlledBy, \'N/A\') AS operated_by')
  169. ->addSelect('IFNULL(systemData.securityAuthorizationDt, \'N/A\') AS security_auth_dt')
  170. ->addSelect('IFNULL(systemData.controlAssessmentDt, \'N/A\') AS self_assessment_dt')
  171. ->addSelect('IFNULL(systemData.contingencyPlanTestDt, \'N/A\') AS cplan_test_dt')
  172. ->addSelect("IF(systemData.fismaReportable,'Yes','No') AS fisma_reportable")
  173. ->innerJoin('o.System systemData')
  174. ->innerJoin('o.OrganizationType orgType')
  175. ->andWhere('orgType.nickname = ?', array('system'))
  176. ->andWhere('systemData.sdlcPhase <> ?', 'disposal')
  177. ->orderBy('o.nickname')
  178. ->setHydrationMode(Doctrine::HYDRATE_SCALAR);
  179. $systems = $systemQuery->execute();
  180. if ('none' != $orgTypeId) {
  181. $baseQuery = CurrentUser::getInstance()->getOrganizationsByPrivilegeQuery('organization', 'read')
  182. ->select('o.nickname as id, bureau.nickname as name')
  183. ->leftJoin('Organization bureau')
  184. ->andWhere('o.lft BETWEEN bureau.lft and bureau.rgt')
  185. ->andWhere('bureau.orgTypeId = ?', $orgTypeId)
  186. ->setHydrationMode(Doctrine::HYDRATE_SCALAR);
  187. $parents = $baseQuery->execute();
  188. foreach ($parents as $key => $value) {
  189. $parents[$value['o_id']] = $value['bureau_name'];
  190. unset($parents[$key]);
  191. }
  192. foreach ($systems as &$system) {
  193. if (isset($parents[$system['o_name']])) {
  194. $system['o_parent'] = $parents[$system['o_name']];
  195. }
  196. }
  197. }
  198. $report = new Fisma_Report();
  199. $report->setTitle('Security Authorizations Report');
  200. $orgType = Doctrine::getTable('OrganizationType')->find($orgTypeId);
  201. $report->addColumn(new Fisma_Report_Column('System', true));
  202. if ('none' != $orgTypeId) {
  203. $report->addColumn(new Fisma_Report_Column(ucwords($orgType->nickname), true));
  204. }
  205. $report->addColumn(new Fisma_Report_Column('FIPS 199', true))
  206. ->addColumn(new Fisma_Report_Column('Operated By', true))
  207. ->addColumn(
  208. new Fisma_Report_Column(
  209. 'Security Authorization',
  210. true,
  211. 'Fisma.TableFormat.securityAuthorization'
  212. )
  213. )
  214. ->addColumn(
  215. new Fisma_Report_Column(
  216. 'Self-Assessment',
  217. true,
  218. 'Fisma.TableFormat.selfAssessment'
  219. )
  220. )
  221. ->addColumn(
  222. new Fisma_Report_Column(
  223. 'Contingency Plan Test',
  224. true,
  225. 'Fisma.TableFormat.contingencyPlanTest'
  226. )
  227. )
  228. ->addColumn(new Fisma_Report_Column('FISMA Reportable', true))
  229. ->setData($systems);
  230. $this->_helper->reportContextSwitch()->setReport($report);
  231. }
  232. /**
  233. * Generate documentation compliance report
  234. *
  235. * @GETAllowed
  236. */
  237. public function documentationComplianceAction()
  238. {
  239. $systemDocuments = Doctrine::getTable('SystemDocument')->getSystemDocumentReportDataQuery()->execute();
  240. $allRequiredDocumentTypeName = Doctrine::getTable('DocumentType')
  241. ->getAllRequiredDocumentTypeQuery()
  242. ->execute()
  243. ->toKeyValueArray('id', 'name');
  244. $systemData = array();
  245. foreach ($systemDocuments as $systemDocument) {
  246. $systemData[] = array(
  247. $systemDocument['o_name'],
  248. $systemDocument['dt_percentage'],
  249. $this->_getMissingDocumentTypeName($allRequiredDocumentTypeName,
  250. $systemDocument['dt_uploadedRequiredDocument'])
  251. );
  252. }
  253. $report = new Fisma_Report();
  254. $report->setTitle('Documentation Compliance Report')
  255. ->addColumn(new Fisma_Report_Column('System', true))
  256. ->addColumn(
  257. new Fisma_Report_Column(
  258. 'Percentage',
  259. true,
  260. 'Fisma.TableFormat.completeDocTypePercentage',
  261. null,
  262. false,
  263. 'number'
  264. )
  265. )
  266. ->addColumn(
  267. new Fisma_Report_Column(
  268. 'Incomplete',
  269. true,
  270. 'Fisma.TableFormat.incompleteDocumentType'
  271. )
  272. )
  273. ->setData($systemData);
  274. $this->_helper->reportContextSwitch()->setReport($report);
  275. }
  276. /**
  277. * Get the missing document type name(s) by comparing $allRequiredDocumentType
  278. * and $uploadedRequiredDocumentType
  279. */
  280. private function _getMissingDocumentTypeName($allRequiredDocumentType, $uploadedRequiredDocumentType)
  281. {
  282. if ('N/A' != $uploadedRequiredDocumentType && count($allRequiredDocumentType) > 0) {
  283. $uploadedRequiredDocumentTypeArray = explode(',', $uploadedRequiredDocumentType);
  284. $missingDocumentTypeNames = array_diff($allRequiredDocumentType, $uploadedRequiredDocumentTypeArray);
  285. return count($missingDocumentTypeNames) > 0 ? join(',', $missingDocumentTypeNames) : 'N/A';
  286. } else if (count($allRequiredDocumentType) > 0) {
  287. return join(',', $allRequiredDocumentType);
  288. } else {
  289. return 'N/A';
  290. }
  291. }
  292. }