api.universalqinq.php 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682
  1. <?php
  2. /**
  3. * Yet another QinQ implementation.
  4. */
  5. class UniversalQINQ {
  6. CONST MODULE = '?module=universalqinq';
  7. CONST MODULE_VLANMANAGEMENT = '?module=vlanmanagement';
  8. /**
  9. * Placeholder for nyan orm (`qinq` table)
  10. *
  11. * @var object
  12. */
  13. protected $qinqdb;
  14. /**
  15. * contains erros if any
  16. *
  17. * @var array
  18. */
  19. public $error = array();
  20. /**
  21. * Contains all the cathable exceptions
  22. *
  23. * @var array
  24. */
  25. public $exceptions = array();
  26. /**
  27. * Contains all
  28. *
  29. * @var array
  30. */
  31. protected $allData;
  32. /**
  33. * Containts all C-vlans
  34. *
  35. * @var array
  36. */
  37. protected $allCvlans = array();
  38. /**
  39. * Contains all realms
  40. *
  41. * @var array
  42. */
  43. protected $allRealms = array();
  44. /**
  45. * Contains all S-vlans
  46. *
  47. * @var array
  48. */
  49. protected $allSvlan = array();
  50. /**
  51. * Placeholder for nyan_orm instance for switches_qinq table.
  52. *
  53. * @var object
  54. */
  55. protected $switchesqinqDb;
  56. /**
  57. * Placeholder for nyan_orm isntance for switches table.
  58. *
  59. * @var object
  60. */
  61. protected $switchesDb;
  62. /**
  63. * Placeholder for nyan_orm instance for switchmodels table.
  64. *
  65. * @var object
  66. */
  67. protected $switchModelsDb;
  68. /**
  69. * Contains all switches
  70. *
  71. * @var array
  72. */
  73. protected $allSwitches = array();
  74. /**
  75. * Contains all switch models.
  76. *
  77. * @var array
  78. */
  79. protected $allSwitchModels = array();
  80. /**
  81. * Contains all c-vlans occupied by switches.
  82. *
  83. * @var array
  84. */
  85. protected $occupiedSwitches = array();
  86. /**
  87. * Contains system alter config as key=>value
  88. *
  89. * @var array
  90. */
  91. protected $altCfg;
  92. /**
  93. * Placeholder for nyan_orm instance for realms table.
  94. *
  95. * @var object
  96. */
  97. protected $realmsdb;
  98. /**
  99. * Placeholder for nyan_orm instance for svlan_qinq table.
  100. *
  101. * @var object
  102. */
  103. protected $svlandb;
  104. /**
  105. * Default realm selector
  106. *
  107. * @var string
  108. */
  109. protected $defaultRealm;
  110. /**
  111. * Placeholder for ubilling messages instance.
  112. *
  113. * @var object
  114. */
  115. protected $messages;
  116. /**
  117. * Placeholder for ubRouting object
  118. *
  119. * @var object
  120. */
  121. public $routing;
  122. public function __construct() {
  123. $this->qinqdb = new nya_qinq_bindings;
  124. $this->realmsdb = new nya_realms();
  125. $this->svlandb = new nya_qinq_svlan();
  126. $this->switchesqinqDb = new nya_switches_qinq();
  127. $this->switchesDb = new nya_switches();
  128. $this->switchModelsDb = new nya_switchmodels();
  129. $this->loadAlter();
  130. $this->initRouting();
  131. $this->loadData();
  132. $this->messages = new UbillingMessageHelper();
  133. }
  134. /**
  135. * Loads system alter.ini config for further usage
  136. *
  137. * @global object $ubillingConfig
  138. *
  139. * @return void
  140. */
  141. protected function loadAlter() {
  142. global $ubillingConfig;
  143. $this->altCfg = $ubillingConfig->getAlter();
  144. }
  145. /**
  146. * Creates new protected routing object instance for further usage
  147. *
  148. * @return void
  149. */
  150. protected function initRouting() {
  151. $this->routing = new ubRouting();
  152. }
  153. /**
  154. * Function to preload data from qinq_bindings, realms and qinq_svlan tables.
  155. *
  156. * @return void
  157. */
  158. protected function loadData() {
  159. $this->allData = $this->qinqdb->getAll('id');
  160. $this->allRealms = $this->realmsdb->getAll('id');
  161. $this->allSvlan = $this->svlandb->getAll('id');
  162. }
  163. /**
  164. * Redirects user back and show error if any
  165. *
  166. * @return void
  167. */
  168. protected function goToStartOrError() {
  169. if (empty($this->error) and empty($this->exceptions)) {
  170. if ($this->routing->checkGet('type')) {
  171. rcms_redirect(VlanManagement::MODULE . '&realm_id=' . $this->routing->get('realm_id', 'int') . '&svlan_id=' . $this->routing->get('svlan_id', 'int'));
  172. } else {
  173. rcms_redirect(self::MODULE);
  174. }
  175. }
  176. if (!$this->routing->checkGet('type')) {
  177. if (!empty($this->error)) {
  178. $this->showError();
  179. }
  180. if (!empty($this->exceptions)) {
  181. $this->showExceptions();
  182. }
  183. }
  184. }
  185. /**
  186. * Generate dynamic selector for realms.
  187. *
  188. * @param string $container
  189. * @param int $realm
  190. * @param int $svlan
  191. *
  192. * @return string
  193. */
  194. protected function realmsSelector($container = '', $realm = '', $svlan = '') {
  195. $this->realmSelector[self::MODULE . '&action=realm_id_select&ajrealmid=0'] = '---';
  196. if (!empty($this->allRealms)) {
  197. foreach ($this->allRealms as $id => $each) {
  198. $this->realmSelector[self::MODULE . '&action=realm_id_select&ajrealmid=' . $id . '&svlan_id=' . $svlan] = $each['realm'] . ' | ' . $each['description'];
  199. }
  200. $this->defaultRealm = self::MODULE . '&action=realm_id_select&ajrealmid=' . $realm . '&svlan_id=' . $svlan;
  201. }
  202. return(wf_AjaxSelectorAC($container, $this->realmSelector, __('Select realm'), $this->defaultRealm, false));
  203. }
  204. /**
  205. * Generates dynamic svlan selector.
  206. *
  207. * @param int $altRealm
  208. * @param int $altSvlan
  209. *
  210. * @return string
  211. */
  212. public function svlanSelector($altRealm = '', $altSvlan = '') {
  213. if ($this->routing->get('ajrealmid', 'int')) {
  214. $realm = $this->routing->get('ajrealmid', 'int');
  215. } else {
  216. $realm = $altRealm;
  217. }
  218. if ($this->routing->get('svlan_id')) {
  219. $svlan = $this->routing->get('svlan_id');
  220. } else {
  221. $svlan = $altSvlan;
  222. }
  223. $this->svlandb->where('realm_id', '=', $realm);
  224. $allSvlan = $this->svlandb->getAll('id');
  225. $allSvlanSelector = array('' => '---');
  226. if (!empty($allSvlan)) {
  227. foreach ($allSvlan as $id => $each) {
  228. $allSvlanSelector[$id] = $each['svlan'] . ' | ' . $each['description'];
  229. }
  230. }
  231. $result = wf_HiddenInput('module', 'universalqinq');
  232. $result .= wf_HiddenInput('realm_id', $realm);
  233. $result .= wf_Selector('svlan_id', $allSvlanSelector, 'SVLAN', $svlan, false);
  234. return ($result);
  235. }
  236. /**
  237. * Check if cvlan is int and has value from 1 to 4096
  238. *
  239. * @return bool
  240. */
  241. protected function validateCvlan() {
  242. if (($this->routing->get('cvlan_num', 'int') >= 1) and ( $this->routing->get('cvlan_num', 'int') <= 4096)) {
  243. return(true);
  244. } else {
  245. return(false);
  246. }
  247. }
  248. /**
  249. * Check if svlan_id greated than zero
  250. *
  251. * @return bool
  252. */
  253. protected function validateSvlan() {
  254. if ($this->routing->get('svlan_id', 'int') >= 1) {
  255. return(true);
  256. } else {
  257. return(false);
  258. }
  259. }
  260. /**
  261. * Check if qinq pair is not occupied by switch.
  262. *
  263. * @return bool
  264. */
  265. protected function isSwitchCvlanUnique() {
  266. if (isset($this->occupiedSwitches[$this->routing->get('cvlan_num', 'int')])) {
  267. return(false);
  268. }
  269. return(true);
  270. }
  271. /**
  272. * Check if qinq pair is not occupied by customer.
  273. *
  274. * @return bool
  275. */
  276. protected function isUniversalCvlanUnique() {
  277. if (isset($this->allCvlans[$this->routing->get('cvlan_num', 'int')])) {
  278. return(false);
  279. }
  280. return(true);
  281. }
  282. /**
  283. * Should we give a chance to assign vlan to non existing user?
  284. *
  285. * @return bool
  286. */
  287. public function isUserExists() {
  288. if ($this->altCfg['UNIVERSAL_QINQ_USER_EXIST']) {
  289. $allUsers = array_flip(zb_UserGetAllStargazerLogins());
  290. if ($this->routing->checkGet('username')) {
  291. $getLogin = 'username';
  292. } else {
  293. $getLogin = 'login';
  294. }
  295. if (isset($allUsers[$this->routing->get($getLogin, 'mres')])) {
  296. return(true);
  297. } else {
  298. return(false);
  299. }
  300. } else {
  301. return(true);
  302. }
  303. }
  304. /**
  305. * User might have only one entry
  306. *
  307. * @return bool
  308. */
  309. protected function isUserUnique() {
  310. if ($this->routing->get('action') == 'edit') {
  311. $this->qinqdb->where('login', '<>', $this->routing->get('login', 'mres'));
  312. }
  313. $data = $this->qinqdb->getAll('login');
  314. if (isset($data[$this->routing->get('login', 'mres')])) {
  315. return(false);
  316. } else {
  317. return(true);
  318. }
  319. }
  320. /**
  321. * Get all occupied c-vlans in current svlan.
  322. *
  323. * @return void
  324. */
  325. protected function occupiedUniversal() {
  326. $this->qinqdb->where('svlan_id', '=', $this->routing->get('svlan_id', 'int'));
  327. $this->allCvlans = $this->qinqdb->getAll('cvlan');
  328. }
  329. /**
  330. * Get all c-vlans occupied by switches.
  331. *
  332. * @return void
  333. */
  334. protected function occupiedSwitches() {
  335. $this->allSwitches = $this->switchesDb->getAll('id');
  336. $this->allSwitchModels = $this->switchModelsDb->getAll('id');
  337. $this->switchesqinqDb->where('svlan_id', '=', $this->routing->get('svlan_id', 'int'));
  338. foreach ($this->switchesqinqDb->getAll('switchid') as $io => $each) {
  339. if (isset($this->allSwitches[$each['switchid']])) {
  340. $modelid = $this->allSwitches[$each['switchid']]['modelid'];
  341. $port_number = $this->allSwitchModels[$modelid]['ports'];
  342. for ($i = $each['cvlan']; $i <= ($each['cvlan'] + $port_number - 1); $i++) {
  343. $this->occupiedSwitches[$i] = $this->allSwitches[$each['switchid']]['ip'] . ' | ' . $this->allSwitches[$each['switchid']]['location'];
  344. $this->switchVlans[$i] = $each['switchid'];
  345. }
  346. }
  347. }
  348. }
  349. /**
  350. * Check all validation function and return error if something didn't pass
  351. *
  352. * @return bool
  353. */
  354. protected function validator() {
  355. if (!$this->validateCvlan()) {
  356. $this->error[] = __('Wrong value') . ' CVLAN ' . $this->routing->get('cvlan_num', 'int');
  357. }
  358. if (!$this->validateSvlan()) {
  359. $this->error[] = __('Wrong value') . ' SVLAN ID ' . $this->routing->get('svlan_id', 'int');
  360. }
  361. if (!$this->isUniversalCvlanUnique()) {
  362. $this->error[] = "CVLAN " . $this->routing->get('cvlan_num', 'int')
  363. . ' ' . __('occcupied by login') . ': '
  364. . wf_link("?module=userprofile&username="
  365. . $this->occupiedUniversal[$this->routing->get('cvlan_num', 'int')]['login'], $this->occupiedUniversal[$this->routing->get('cvlan_num', 'int')]['login']
  366. );
  367. }
  368. if (!$this->isSwitchCvlanUnique()) {
  369. $this->error[] = "CVLAN " . $this->routing->get('cvlan_num', 'int')
  370. . ' ' . __('occcupied by switch') . ': '
  371. . $this->occupiedSwitches[$this->routing->get('cvlan_num', 'int')];
  372. }
  373. if (!$this->routing->get('login')) {
  374. $this->error[] = __('Login cannot be empty');
  375. } else if (!$this->isUserExists()) {
  376. $this->error[] = __('User does not exist') . ' : ' . $this->routing->get('login', 'mres');
  377. }
  378. if (!$this->isUserUnique()) {
  379. $this->error[] = __('There is entry for this login') . ' : ' . $this->routing->get('login', 'mres');
  380. }
  381. if (!empty($this->error)) {
  382. return(false);
  383. }
  384. return(true);
  385. }
  386. /**
  387. * Adding new entry
  388. *
  389. * @return void
  390. */
  391. public function add() {
  392. try {
  393. if ($this->validator()) {
  394. $this->qinqdb->data('login', trim($this->routing->get('login', 'mres')));
  395. $this->qinqdb->data('svlan_id', trim($this->routing->get('svlan_id', 'int')));
  396. $this->qinqdb->data('cvlan', trim($this->routing->get('cvlan_num', 'int')));
  397. $this->qinqdb->create();
  398. $this->logAdd();
  399. }
  400. $this->goToStartOrError();
  401. return($this->error);
  402. } catch (Exception $ex) {
  403. $this->exceptions[] = $ex;
  404. $this->goToStartOrError();
  405. }
  406. }
  407. /**
  408. * Delete entry
  409. *
  410. * @return void
  411. */
  412. public function delete() {
  413. try {
  414. $this->qinqdb->where('id', '=', trim($this->routing->get('id', 'int')));
  415. $this->qinqdb->delete();
  416. $this->logDelete();
  417. $this->goToStartOrError();
  418. } catch (Exception $ex) {
  419. $this->exceptions[] = $ex;
  420. $this->goToStartOrError();
  421. }
  422. }
  423. /**
  424. * Edit entry
  425. *
  426. * @return void
  427. */
  428. public function edit() {
  429. try {
  430. if ($this->validator()) {
  431. $this->qinqdb->where('id', '=', trim($this->routing->get('id', 'int')));
  432. $this->qinqdb->data('login', trim($this->routing->get('login', 'mres')));
  433. $this->qinqdb->data('svlan_id', trim($this->routing->get('svlan_id', 'int')));
  434. $this->qinqdb->data('cvlan', trim($this->routing->get('cvlan_num', 'int')));
  435. $this->qinqdb->save();
  436. $this->logEdit();
  437. }
  438. $this->goToStartOrError();
  439. } catch (Exception $ex) {
  440. $this->exceptions[] = $ex;
  441. $this->goToStartOrError();
  442. }
  443. }
  444. /**
  445. * Show all the entries
  446. *
  447. * @return string
  448. */
  449. public function showAll() {
  450. $modal = '<link rel="stylesheet" href="./skins/vlanmanagement.css" type="text/css" media="screen" />';
  451. $modal .= wf_tag('div', false, 'cvmodal', 'id="dialog-modal_cvmodal" title="' . __('Choose') . '" style="display:none; width:1px; height:1px;"');
  452. $modal .= wf_tag('p', false, '', 'id="content-cvmodal"');
  453. $modal .= wf_tag('p', true);
  454. $modal .= wf_tag('div', true);
  455. $modal .= '<script src="./modules/jsc/vlanmanagement.js" type="text/javascript"></script>';
  456. $columns = array(__('ID'), 'Realm', 'S-VLAN', 'C-VLAN', 'Address', 'Real Name', 'Actions');
  457. $opts = '"order": [[ 0, "desc" ]]';
  458. $result = '';
  459. $ajaxURL = '' . self::MODULE . '&ajax=true';
  460. $result .= show_window('', $modal . wf_JqDtLoader($columns, $ajaxURL, false, 'UniversalQINQ', 100, $opts));
  461. return ($result);
  462. }
  463. public function links() {
  464. $urls = wf_BackLink(UniversalQINQ::MODULE_VLANMANAGEMENT, __('Back'), false, 'ubButton');
  465. show_window('', $urls . $this->addForm());
  466. }
  467. /**
  468. * Form to create new entry
  469. *
  470. * @return void
  471. */
  472. protected function addForm() {
  473. $result = wf_AjaxLoader();
  474. $inputs2 = wf_HiddenInput('module', 'universalqinq');
  475. $inputs2 .= wf_HiddenInput('action', 'add');
  476. $inputs2 .= $this->realmsSelector('ajcontainer');
  477. $inputs2 .= wf_AjaxContainer('ajcontainer', '', $this->svlanSelector());
  478. $inputs2 .= wf_TextInput('cvlan_num', 'C-VLAN', '', true, '', 'digits');
  479. $inputs2 .= wf_TextInput('login', __('Login'), '', true, '', '');
  480. $inputs2 .= wf_Submit('Save');
  481. $result .= wf_Form('', 'GET', $inputs2, 'glamour');
  482. return(wf_modalAuto(web_icon_create() . ' ' . __('Create new entry'), __('Create new entry'), $result, 'ubButton'));
  483. }
  484. /**
  485. * Forming edit form
  486. *
  487. * @param array $each
  488. *
  489. * @return string
  490. */
  491. public function editFormGenerator($encode) {
  492. $decode = unserialize(base64_decode($encode));
  493. $result = wf_AjaxLoader();
  494. $addControls = wf_HiddenInput('module', 'universalqinq');
  495. $addControls .= wf_HiddenInput('action', 'edit');
  496. $addControls .= wf_HiddenInput('id', $decode['id']);
  497. $addControls .= $this->realmsSelector('ajcontainer2', $this->allSvlan[$decode['svlan_id']]['realm_id'], $decode['svlan_id']);
  498. $addControls .= wf_AjaxContainer('ajcontainer2', '', $this->svlanSelector($this->allSvlan[$decode['svlan_id']]['realm_id'], $decode['svlan_id']));
  499. $addControls .= wf_TextInput('cvlan_num', 'C-VLAN', $decode['cvlan'], true, '', 'digits');
  500. $addControls .= wf_TextInput('login', __('Login'), $decode['login'], true, '');
  501. $addControls .= wf_HiddenInput('old_login', $decode['login']);
  502. $addControls .= wf_HiddenInput('old_svlan', $decode['svlan_id']);
  503. $addControls .= wf_HiddenInput('old_cvlan', $decode['cvlan']);
  504. $addControls .= wf_Submit('Save');
  505. $result .= wf_Form('', 'GET', $addControls, 'glamour');
  506. return($result);
  507. }
  508. /**
  509. * If we have any errors show all of them
  510. *
  511. * @return void
  512. */
  513. protected function showError() {
  514. foreach ($this->error as $io => $each) {
  515. show_error($each);
  516. }
  517. }
  518. protected function showExceptions() {
  519. foreach ($this->exceptions as $io => $each) {
  520. show_error($each);
  521. }
  522. }
  523. public function getAll() {
  524. return($this->qinqdb->getAll('login'));
  525. }
  526. /**
  527. * Form all the entries to ajax array
  528. *
  529. * @return void
  530. */
  531. public function ajaxData() {
  532. $json = new wf_JqDtHelper();
  533. if (!empty($this->allData)) {
  534. $allRealnames = zb_UserGetAllRealnames();
  535. $allAddress = zb_AddressGetFulladdresslistCached();
  536. foreach ($this->allData as $io => $each) {
  537. if(!isset($this->allSvlan[$each['svlan_id']])) {
  538. continue;
  539. }
  540. $eachId = base64_encode(serialize(array(
  541. 'id' => $each['id'],
  542. 'svlan_id' => $each['svlan_id'],
  543. 'cvlan' => $each['cvlan'],
  544. 'login' => $each['login']
  545. )));
  546. $userLink = wf_Link('?module=userprofile&username=' . $each['login'], web_profile_icon() . ' ' . @$allAddress[$each['login']], false);
  547. $actLinks = wf_tag('div', false, '', 'id="' . $eachId . '" onclick="qinqEdit(this)" style="display:inline-block;"') . web_edit_icon() . wf_tag('div', true);
  548. $actLinks .= wf_JSAlert(self::MODULE . '&action=delete&id=' . $each['id'], web_delete_icon(), $this->messages->getDeleteAlert());
  549. $data[] = $each['id'];
  550. $data[] = $this->allRealms[$this->allSvlan[$each['svlan_id']]['realm_id']]['description'];
  551. $data[] = $this->allSvlan[$each['svlan_id']]['svlan'];
  552. $data[] = $each['cvlan'];
  553. $data[] = $userLink;
  554. $data[] = @$allRealnames[$each['login']];
  555. $data[] = $actLinks;
  556. $json->addRow($data);
  557. unset($data);
  558. }
  559. }
  560. $json->getJson();
  561. }
  562. /**
  563. * Log add action
  564. *
  565. * @return void
  566. */
  567. public function logAdd($login = '', $svlan = '', $cvlan = '') {
  568. if (empty($login)) {
  569. $login = $this->routing->get('login', 'mres');
  570. }
  571. if (empty($svlan)) {
  572. $svlan = $this->routing->get('svlan', 'int');
  573. }
  574. if (empty($cvlan)) {
  575. $cvlan = $this->routing->get('cvlan_num', 'int');
  576. }
  577. log_register('CREATE universalqinq ('
  578. . trim($login)
  579. . ') s'
  580. . trim($svlan)
  581. . '/c'
  582. . trim($cvlan)
  583. );
  584. }
  585. /**
  586. * Log delete action
  587. *
  588. * @return void
  589. */
  590. protected function logDelete() {
  591. log_register('DELETE universalqinq (' .
  592. trim($this->routing->get('login', 'mres')) .
  593. ') s' .
  594. trim($this->routing->get('svlan', 'int')) .
  595. '/c' .
  596. trim($this->routing->get('cvlan_num', 'int'))
  597. );
  598. }
  599. /**
  600. * Log edit action
  601. *
  602. * @return void
  603. */
  604. protected function logEdit() {
  605. log_register('EDIT universalqinq ('
  606. . trim($this->routing->get('old_login', 'mres'))
  607. . ') FROM s'
  608. . trim($this->routing->get('old_svlan', 'int'))
  609. . '/c'
  610. . trim($this->routing->get('old_cvlan', 'int'))
  611. . 'ON ('
  612. . trim($this->routing->get('login', 'mres'))
  613. . ') s'
  614. . trim($this->routing->get('svlan', 'int'))
  615. . '/c'
  616. . trim($this->routing->get('cvlan_num', 'int'))
  617. );
  618. }
  619. }