control.php 55 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370
  1. <?php
  2. /**
  3. * The control file of gitlab module of ZenTaoPMS.
  4. *
  5. * @copyright Copyright 2009-2023 禅道软件(青岛)有限公司(ZenTao Software (Qingdao) Co., Ltd. www.cnezsoft.com)
  6. * @license ZPL(http://zpl.pub/page/zplv12.html) or AGPL(https://www.gnu.org/licenses/agpl-3.0.en.html)
  7. * @author Chenqi <chenqi@cnezsoft.com>
  8. * @package product
  9. * @version $Id: ${FILE_NAME} 5144 2020/1/8 8:10 下午 chenqi@cnezsoft.com $
  10. * @link https://www.zentao.net
  11. */
  12. class gitlab extends control
  13. {
  14. /**
  15. * The gitlab constructor.
  16. * @param string $moduleName
  17. * @param string $methodName
  18. */
  19. public function __construct($moduleName = '', $methodName = '')
  20. {
  21. parent::__construct($moduleName, $methodName);
  22. if(stripos($this->methodName, 'ajax') === false)
  23. {
  24. if(!commonModel::hasPriv('space', 'browse')) $this->loadModel('common')->deny('space', 'browse', false);
  25. if(!in_array(strtolower(strtolower($this->methodName)), array('browseproject', 'browsegroup', 'browseuser', 'browsebranch', 'browsetag')))
  26. {
  27. if(!commonModel::hasPriv('instance', 'manage')) $this->loadModel('common')->deny('instance', 'manage', false);
  28. }
  29. }
  30. /* This is essential when changing tab(menu) from gitlab to repo. */
  31. /* Optional: common::setMenuVars('devops', $this->session->repoID); */
  32. $this->loadModel('ci')->setMenu();
  33. }
  34. /**
  35. * Gitlab列表。
  36. * Browse gitlab.
  37. *
  38. * @param string $orderBy
  39. * @param int $recTotal
  40. * @param int $recPerPage
  41. * @param int $pageID
  42. * @access public
  43. * @return void
  44. */
  45. public function browse($orderBy = 'id_desc', $recTotal = 0, $recPerPage = 20, $pageID = 1)
  46. {
  47. $this->app->loadClass('pager', true);
  48. $pager = new pager($recTotal, $recPerPage, $pageID);
  49. /* Admin user don't need bind. */
  50. $gitlabList = $this->gitlab->getList($orderBy, $pager);
  51. $this->view->title = $this->lang->gitlab->common . $this->lang->hyphen . $this->lang->gitlab->browse;
  52. $this->view->gitlabList = $gitlabList;
  53. $this->view->orderBy = $orderBy;
  54. $this->view->pager = $pager;
  55. $this->display();
  56. }
  57. /**
  58. * 创建一个gitlab。
  59. * Create a gitlab.
  60. *
  61. * @access public
  62. * @return void
  63. */
  64. public function create()
  65. {
  66. if($_POST)
  67. {
  68. $gitlab = form::data($this->config->gitlab->form->create)
  69. ->add('createdBy', $this->app->user->account)
  70. ->get();
  71. $this->checkToken($gitlab);
  72. $gitlabID = $this->loadModel('pipeline')->create($gitlab);
  73. if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
  74. $this->loadModel('action');
  75. $this->action->create('gitlab', $gitlabID, 'created');
  76. return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => $this->createLink('space', 'browse')));
  77. }
  78. $this->view->title = $this->lang->gitlab->common . $this->lang->hyphen . $this->lang->gitlab->lblCreate;
  79. $this->display();
  80. }
  81. /**
  82. * Gitlab详情页。
  83. * View a gitlab.
  84. * @param int $gitlabID
  85. * @access public
  86. * @return void
  87. */
  88. public function view($gitlabID)
  89. {
  90. $gitlab = $this->gitlab->getByID($gitlabID);
  91. $this->view->title = $this->lang->gitlab->common . $this->lang->hyphen . $this->lang->gitlab->view;
  92. $this->view->gitlab = $gitlab;
  93. $this->view->users = $this->loadModel('user')->getPairs('noclosed');
  94. $this->view->actions = $this->loadModel('action')->getList('gitlab', $gitlabID);
  95. $this->view->preAndNext = $this->loadModel('common')->getPreAndNextObject('pipeline', $gitlabID);
  96. $this->display();
  97. }
  98. /**
  99. * 编辑gitlab。
  100. * Edit a gitlab.
  101. *
  102. * @param int $gitlabID
  103. * @access public
  104. * @return void
  105. */
  106. public function edit($gitlabID)
  107. {
  108. $oldGitLab = $this->gitlab->getByID($gitlabID);
  109. if($_POST)
  110. {
  111. $gitlab = form::data($this->config->gitlab->form->edit)
  112. ->add('editedBy', $this->app->user->account)
  113. ->get();
  114. $this->checkToken($gitlab, $gitlabID);
  115. $this->loadModel('pipeline')->update($gitlabID, $gitlab);
  116. $gitLab = $this->gitlab->getByID($gitlabID);
  117. if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
  118. $this->loadModel('action');
  119. $actionID = $this->action->create('gitlab', $gitlabID, 'edited');
  120. $changes = common::createChanges($oldGitLab, $gitLab);
  121. $this->action->logHistory($actionID, $changes);
  122. return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'load' => true, 'closeModal' => true));
  123. }
  124. $this->view->title = $this->lang->gitlab->common . $this->lang->hyphen . $this->lang->gitlab->edit;
  125. $this->view->gitlab = $oldGitLab;
  126. $this->display();
  127. }
  128. /**
  129. * Bind gitlab user to zentao users.
  130. *
  131. * @param int $gitlabID
  132. * @param string $type
  133. * @access public
  134. * @return void
  135. */
  136. public function bindUser($gitlabID, $type = 'all')
  137. {
  138. $userPairs = $this->loadModel('user')->getPairs('noclosed|noletter');
  139. $gitlab = $this->gitlab->getByID($gitlabID);
  140. $user = $this->gitlab->apiGetCurrentUser($gitlab->url, $gitlab->token);
  141. if(empty($user->is_admin)) return $this->send(array('result' => 'fail', 'load' => array('alert' => $this->lang->gitlab->tokenLimit, 'modal' => $this->createLink('gitlab', 'edit', array('gitlabID' => $gitlabID)))));
  142. $zentaoUsers = $this->dao->select('account,email,realname')->from(TABLE_USER)->where('deleted')->eq('0')->fetchAll('account');
  143. if($_POST)
  144. {
  145. $users = $this->post->zentaoUsers;
  146. $gitlabNames = $this->post->gitlabUserNames;
  147. $result = $this->gitlabZen->checkUserRepeat($users, $userPairs);
  148. if($result['result'] != 'success') return $this->send($result);
  149. $this->gitlabZen->bindUsers($gitlabID, $users, $gitlabNames, $zentaoUsers);
  150. if(dao::isError()) return $this->sendError(dao::getError());
  151. return $this->sendSuccess(array('message' => $this->lang->saveSuccess, 'load' => helper::createLink('space', 'browse')));
  152. }
  153. $userList = array();
  154. $gitlabUsers = $this->gitlab->apiGetUsers($gitlabID);
  155. $bindedUsers = $this->loadModel('pipeline')->getUserBindedPairs($gitlabID, 'gitlab', 'account,openID');
  156. $matchedResult = $this->gitlab->getMatchedUsers($gitlabID, $gitlabUsers, $zentaoUsers);
  157. foreach($gitlabUsers as $gitlabUserID => $gitlabUser)
  158. {
  159. $user = new stdclass();
  160. $user->email = '';
  161. $user->status = 'notBind';
  162. $user->gitlabID = $gitlabUser->id;
  163. $user->gitlabEmail = $gitlabUser->email;
  164. $user->gitlabUser = $gitlabUser->realname . '@' . $gitlabUser->account;
  165. $user->gitlabUserAvatar = $gitlabUser->avatar;
  166. $user->zentaoUsers = isset($matchedResult[$gitlabUser->id]) ? $matchedResult[$gitlabUser->id]->zentaoAccount : '';
  167. if($user->zentaoUsers)
  168. {
  169. if(isset($zentaoUsers[$user->zentaoUsers])) $user->email = $zentaoUsers[$user->zentaoUsers]->email;
  170. if(isset($bindedUsers[$user->zentaoUsers]) && $bindedUsers[$user->zentaoUsers] == $gitlabUser->id)
  171. {
  172. $user->status = 'binded';
  173. if(!isset($bindedUsers[$user->zentaoUsers])) $user->status = 'bindedError';
  174. }
  175. }
  176. if($type != 'all' && $user->status != $type) continue;
  177. $userList[] = $user;
  178. }
  179. $this->view->title = $this->lang->gitlab->bindUser;
  180. $this->view->type = $type;
  181. $this->view->gitlabID = $gitlabID;
  182. $this->view->recTotal = count($userList);
  183. $this->view->userList = $userList;
  184. $this->view->userPairs = $userPairs;
  185. $this->view->zentaoUsers = $zentaoUsers;
  186. $this->display();
  187. }
  188. /**
  189. * 删除一条gitlab记录。
  190. * Delete a gitlab.
  191. *
  192. * @param int $gitlabID
  193. * @access public
  194. * @return void
  195. */
  196. public function delete($gitlabID)
  197. {
  198. $oldGitLab = $this->loadModel('pipeline')->getByID($gitlabID);
  199. $actionID = $this->pipeline->deleteByObject($gitlabID, 'gitlab');
  200. if(!$actionID)
  201. {
  202. $response['result'] = 'fail';
  203. $response['callback'] = sprintf('zui.Modal.alert("%s");', $this->lang->pipeline->delError);
  204. return $this->send($response);
  205. }
  206. $gitLab = $this->gitlab->getByID($gitlabID);
  207. $changes = common::createChanges($oldGitLab, $gitLab);
  208. $this->loadModel('action')->logHistory($actionID, $changes);
  209. $response['load'] = $this->createLink('space', 'browse');
  210. $response['result'] = 'success';
  211. return $this->send($response);
  212. }
  213. /**
  214. * 检查post的token是否有管理员权限。
  215. * Check post token has admin permissions.
  216. *
  217. * @param object $gitlab
  218. * @param int $gitlabID
  219. * @access protected
  220. * @return void
  221. */
  222. protected function checkToken($gitlab, $gitlabID = 0)
  223. {
  224. $this->dao->update('gitlab')->data($gitlab)->batchCheck($gitlabID ? $this->config->gitlab->edit->requiredFields : $this->config->gitlab->create->requiredFields, 'notempty');
  225. if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
  226. if(strpos($gitlab->url, 'http') !== 0) return $this->send(array('result' => 'fail', 'message' => array('url' => array(sprintf($this->lang->gitlab->hostError, $this->config->gitlab->minCompatibleVersion)))));
  227. if(!$gitlab->token) return $this->send(array('result' => 'fail', 'message' => array('token' => array($this->lang->gitlab->tokenError))));
  228. $user = $this->gitlab->checkTokenAccess($gitlab->url, $gitlab->token);
  229. if(is_bool($user)) return $this->send(array('result' => 'fail', 'message' => array('url' => array(sprintf($this->lang->gitlab->hostError, $this->config->gitlab->minCompatibleVersion)))));
  230. if(!isset($user->id)) return $this->send(array('result' => 'fail', 'message' => array('token' => array($this->lang->gitlab->tokenError))));
  231. /* Verify version compatibility. */
  232. $result = $this->gitlab->getVersion($gitlab->url, $gitlab->token);
  233. if(empty($result) or !isset($result->version) or (version_compare($result->version, $this->config->gitlab->minCompatibleVersion, '<'))) return $this->send(array('result' => 'fail', 'message' => array('url' => array($this->lang->gitlab->notCompatible))));
  234. }
  235. /**
  236. * Webhook api.
  237. *
  238. * @access public
  239. * @return void
  240. */
  241. public function webhook()
  242. {
  243. $this->gitlab->webhookCheckToken();
  244. $gitlab = $this->get->gitlab;
  245. $input = file_get_contents('php://input');
  246. $requestBody = json_decode($input);
  247. $result = $this->gitlabZen->webhookParseBody($requestBody, $gitlab);
  248. $this->gitlabZen->recordWebhookLogs($input, $result);
  249. if($result->action == 'updateissue' and isset($result->changes->assignees)) $this->gitlab->webhookAssignIssue($result);
  250. //if($result->action = 'reopenissue') $this->gitlab->webhookIssueReopen($gitlab, $result);
  251. if($result->action == 'closeissue') $this->gitlab->webhookCloseIssue($result);
  252. if($result->action == 'updateissue') $this->gitlab->webhookSyncIssue($result);
  253. $this->view->result = 'success';
  254. $this->view->status = 'ok';
  255. $this->view->data = $result->object;
  256. $this->display();
  257. }
  258. /**
  259. * Gitlab群组列表。
  260. * Browse gitlab group.
  261. *
  262. * @param int $gitlabID
  263. * @param string $orderBy
  264. * @access public
  265. * @return void
  266. */
  267. public function browseGroup($gitlabID, $orderBy = 'name_asc')
  268. {
  269. if(!$this->app->user->admin) $this->gitlabZen->checkBindedUser($gitlabID);
  270. $fixOrderBy = str_replace('fullName', 'name', $orderBy);
  271. $keyword = fixer::input('post')->setDefault('keyword', '')->get('keyword');
  272. $groups = $this->gitlab->apiGetGroups($gitlabID, $fixOrderBy, '', $keyword);
  273. $adminGroups = $this->gitlab->apiGetGroups($gitlabID, $fixOrderBy, 'owner', $keyword);
  274. $adminGroupIDList = array();
  275. foreach($adminGroups as $group) $adminGroupIDList[] = $group->id;
  276. $this->view->title = $this->lang->gitlab->common . $this->lang->hyphen . $this->lang->gitlab->browseGroup;
  277. $this->view->gitlabID = $gitlabID;
  278. $this->view->gitlab = $this->gitlab->getByID($gitlabID);
  279. $this->view->gitlabGroupList = $groups;
  280. $this->view->adminGroupIDList = $adminGroupIDList;
  281. $this->view->orderBy = $orderBy;
  282. $this->view->keyword = $keyword;
  283. $this->display();
  284. }
  285. /**
  286. * 创建一个gitlab群组。
  287. * Creat a gitlab group.
  288. *
  289. * @param int $gitlabID
  290. * @access public
  291. * @return void
  292. */
  293. public function createGroup($gitlabID)
  294. {
  295. if(!$this->app->user->admin) $this->gitlabZen->checkBindedUser($gitlabID);
  296. if($_POST)
  297. {
  298. $gitlabGroup = form::data($this->config->gitlab->form->group->create)->get();
  299. $this->gitlab->createGroup($gitlabID, $gitlabGroup);
  300. if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
  301. return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => inlink('browseGroup', "gitlabID=$gitlabID")));
  302. }
  303. $gitlab = $this->gitlab->getByID($gitlabID);
  304. $this->view->title = $this->lang->gitlab->common . $this->lang->hyphen . $this->lang->gitlab->group->create;
  305. $this->view->gitlab = $gitlab;
  306. $this->view->gitlabID = $gitlabID;
  307. $this->display();
  308. }
  309. /**
  310. * 编辑一个gitlab群组。
  311. * Edit a gitlab group.
  312. *
  313. * @param int $gitlabID
  314. * @param int $userID
  315. * @access public
  316. * @return void
  317. * @param int $groupID
  318. */
  319. public function editGroup($gitlabID, $groupID)
  320. {
  321. if(!$this->app->user->admin)
  322. {
  323. $this->gitlabZen->checkBindedUser($gitlabID);
  324. $members = $this->gitlab->apiGetGroupMembers($gitlabID, $groupID, 0);
  325. if(empty($members) or $members[0]->access_level < $this->config->gitlab->accessLevel['owner']) return print(js::alert($this->lang->gitlab->noAccess) . js::locate($this->createLink('space', 'browse')));
  326. }
  327. if($_POST)
  328. {
  329. $gitlabGroup = form::data($this->config->gitlab->form->group->edit)->get();
  330. $this->gitlab->editGroup($gitlabID, $gitlabGroup);
  331. if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
  332. return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => inlink('browseGroup', "gitlabID=$gitlabID")));
  333. }
  334. $gitlab = $this->gitlab->getByID($gitlabID);
  335. $group = $this->gitlab->apiGetSingleGroup($gitlabID, $groupID);
  336. $this->view->title = $this->lang->gitlab->common . $this->lang->hyphen . $this->lang->gitlab->group->edit;
  337. $this->view->gitlab = $gitlab;
  338. $this->view->group = $group;
  339. $this->view->gitlabID = $gitlabID;
  340. $this->display();
  341. }
  342. /**
  343. * 删除一个gitlab群组。
  344. * Delete a gitlab group.
  345. *
  346. * @param int $gitlabID
  347. * @param int $groupID
  348. * @param string $confirm
  349. * @access public
  350. * @return void
  351. */
  352. public function deleteGroup($gitlabID, $groupID, $confirm = 'no')
  353. {
  354. if($confirm != 'yes') return print(js::confirm($this->lang->gitlab->group->confirmDelete , inlink('deleteGroup', "gitlabID=$gitlabID&groupID=$groupID&confirm=yes")));
  355. $group = $this->gitlab->apiGetSingleGroup($gitlabID, $groupID);
  356. $response = $this->gitlab->apiDeleteGroup($gitlabID, $groupID);
  357. /* If the status code beginning with 20 is returned or empty is returned, it is successful. */
  358. if(!$response or substr($response->message, 0, 2) == '20')
  359. {
  360. $this->loadModel('action')->create('gitlabgroup', $groupID, 'deleted', '', $group->name);
  361. return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'reload' => true));
  362. }
  363. $errorKey = array_search($response->message, $this->lang->gitlab->apiError);
  364. $result = $errorKey === false ? $response->message : zget($this->lang->gitlab->errorLang, $errorKey);
  365. return $this->send(array('result' => 'fail', 'message' => $result));
  366. }
  367. /**
  368. * 管理gitlba群组成员。
  369. * Manage a gitlab group members.
  370. *
  371. * @param int $gitlabID
  372. * @param int $groupID
  373. * @access public
  374. * @return void
  375. */
  376. public function manageGroupMembers($gitlabID, $groupID)
  377. {
  378. if($_POST)
  379. {
  380. $data = fixer::input('post')->get();
  381. $ids = array_filter($data->id);
  382. if(count($ids) != count(array_unique($ids))) return $this->send(array('result' => 'fail', 'message' => $this->lang->gitlab->group->repeatError));
  383. $newMembers = array();
  384. foreach($ids as $key => $id)
  385. {
  386. /* Check whether each member has selected accesslevel. */
  387. if(empty($data->access_level[$key])) return $this->send(array('result' => 'fail', 'message' => $this->lang->gitlab->group->memberAccessLevel . $this->lang->gitlab->group->emptyError ));
  388. $newMembers[$id] = (object)array('access_level'=>$data->access_level[$key], 'expires_at'=>$data->expires_at[$key]);
  389. }
  390. $currentMembers = $this->gitlab->apiGetGroupMembers($gitlabID, $groupID);
  391. list($addedMembers, $deletedMembers, $updatedMembers) = $this->gitlabZen->getGroupMemberData($currentMembers, $newMembers);
  392. foreach($addedMembers as $addedMember)
  393. {
  394. $this->gitlab->apiCreateGroupMember($gitlabID, $groupID, $addedMember);
  395. }
  396. foreach($updatedMembers as $updatedMember)
  397. {
  398. $this->gitlab->apiUpdateGroupMember($gitlabID, $groupID, $updatedMember);
  399. }
  400. foreach($deletedMembers as $deletedMemberID)
  401. {
  402. $this->gitlab->apiDeleteGroupMember($gitlabID, $groupID, $deletedMemberID);
  403. }
  404. return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => inlink('browseGroup', "gitlabID=$gitlabID")));
  405. }
  406. /* Get gitlab users data. */
  407. $gitlabUserList = $this->gitlab->apiGetUsers($gitlabID, true);
  408. $gitlabUsers = array(''=>'');
  409. foreach($gitlabUserList as $gitlabUser)
  410. {
  411. $gitlabUsers[$gitlabUser->id] = $gitlabUser->realname;
  412. }
  413. $accessLevels = $this->lang->gitlab->accessLevels;
  414. $currentMembers = $this->gitlab->apiGetGroupMembers($gitlabID, $groupID);
  415. $this->view->title = $this->lang->gitlab->common . $this->lang->hyphen . $this->lang->gitlab->group->manageMembers;
  416. $this->view->currentMembers = $currentMembers;
  417. $this->view->gitlabUsers = $gitlabUsers;
  418. $this->view->gitlabID = $gitlabID;
  419. $this->display();
  420. }
  421. /**
  422. * Gitlab用户列表。
  423. * Browse gitlab user.
  424. *
  425. * @param int $gitlabID
  426. * @param string $orderBy
  427. * @access public
  428. * @return void
  429. */
  430. public function browseUser($gitlabID, $orderBy = 'id_desc')
  431. {
  432. $isAdmin = true;
  433. if(!$this->app->user->admin)
  434. {
  435. $userID = $this->loadModel('pipeline')->getOpenIdByAccount($gitlabID, 'gitlab', $this->app->user->account);
  436. $user = $this->gitlab->apiGetSingleUser($gitlabID, (int)$userID);
  437. if(!$user->is_admin) $isAdmin = false;
  438. }
  439. $keyword = fixer::input('post')->setDefault('keyword', '')->get('keyword');
  440. $users = $this->gitlab->apiGetUsers($gitlabID, false, $orderBy);
  441. if($keyword)
  442. {
  443. foreach($users as $key => $user)
  444. {
  445. if(strpos($user->realname, $keyword) === false) unset($users[$key]);
  446. }
  447. }
  448. $this->view->title = $this->lang->gitlab->common . $this->lang->hyphen . $this->lang->gitlab->browseUser;
  449. $this->view->gitlabID = $gitlabID;
  450. $this->view->gitlabUserList = $users;
  451. $this->view->orderBy = $orderBy;
  452. $this->view->isAdmin = $isAdmin;
  453. $this->view->keyword = $keyword;
  454. $this->display();
  455. }
  456. /**
  457. * 创建一个gitlab用户。
  458. * Creat a gitlab user.
  459. *
  460. * @param int $gitlabID
  461. * @access public
  462. * @return void
  463. */
  464. public function createUser($gitlabID)
  465. {
  466. if($_POST)
  467. {
  468. $gitlabUser = form::data($this->config->gitlab->form->user->create)->get();
  469. if(!empty($_FILES['avatar']['name'][0])) $gitlabUser->avatar = curl_file_create($_FILES['avatar']['tmp_name'][0], $_FILES['avatar']['type'][0], $_FILES['avatar']['name'][0]);
  470. $this->gitlab->createUser($gitlabID, $gitlabUser);
  471. if(dao::isError())
  472. {
  473. $message = dao::getError();
  474. foreach($message as &$msg) if(is_string($msg)) $msg = zget($this->lang->gitlab->errorResonse, $msg, $msg);
  475. return $this->sendError(is_numeric(key($message)) ? implode("\n", $message) : $message);
  476. }
  477. return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'load' => inlink('browseUser', "gitlabID=$gitlabID")));
  478. }
  479. $users = $this->loadModel('user')->getList();
  480. $bindedUsers = $this->loadModel('pipeline')->getUserBindedPairs($gitlabID, 'gitlab', 'account,openID');
  481. $userPairs = array();
  482. $userInfos = array();
  483. foreach($users as $user)
  484. {
  485. if(!isset($bindedUsers[$user->account]))
  486. {
  487. $userPairs[$user->account] = $user->realname;
  488. $userInfos[$user->account] = $user;
  489. }
  490. }
  491. $this->view->title = $this->lang->gitlab->common . $this->lang->hyphen . $this->lang->gitlab->user->create;
  492. $this->view->userPairs = $userPairs;
  493. $this->view->users = $userInfos;
  494. $this->view->gitlabID = $gitlabID;
  495. $this->display();
  496. }
  497. /**
  498. * 编辑一个gitlab用户。
  499. * Edit a gitlab user.
  500. *
  501. * @param int $gitlabID
  502. * @param int $userID
  503. * @access public
  504. * @return void
  505. */
  506. public function editUser($gitlabID, $userID)
  507. {
  508. if($_POST)
  509. {
  510. $gitlabUser = form::data($this->config->gitlab->form->user->edit)
  511. ->removeIF(!$this->post->password, 'password,password_repeat')
  512. ->get();
  513. if(!empty($_FILES['avatar']['name'][0])) $gitlabUser->avatar = curl_file_create($_FILES['avatar']['tmp_name'][0], $_FILES['avatar']['type'][0], $_FILES['avatar']['name'][0]);
  514. $this->gitlab->editUser($gitlabID, $gitlabUser);
  515. if(dao::isError())
  516. {
  517. $message = dao::getError();
  518. foreach($message as &$msg) if(is_string($msg)) $msg = zget($this->lang->gitlab->errorResonse, $msg, $msg);
  519. return $this->sendError(is_numeric(key($message)) ? implode("\n", $message) : $message);
  520. }
  521. return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'load' => inlink('browseUser', "gitlabID=$gitlabID")));
  522. }
  523. $gitlabUser = $this->gitlab->apiGetSingleUser($gitlabID, $userID);
  524. $zentaoBindAccount = $this->dao->select('account')->from(TABLE_OAUTH)->where('providerType')->eq('gitlab')->andWhere('providerID')->eq($gitlabID)->andWhere('openID')->eq($gitlabUser->id)->fetch('account');
  525. $users = $this->loadModel('user')->getList();
  526. $bindedUsers = $this->loadModel('pipeline')->getUserBindedPairs($gitlabID, 'gitlab', 'account,openID');
  527. $userPairs = array();
  528. foreach($users as $user)
  529. {
  530. if(!isset($bindedUsers[$user->account]) or $user->account == $zentaoBindAccount) $userPairs[$user->account] = $user->realname;
  531. }
  532. $this->view->title = $this->lang->gitlab->common . $this->lang->hyphen . $this->lang->gitlab->user->edit;
  533. $this->view->user = $gitlabUser;
  534. $this->view->userPairs = $userPairs;
  535. $this->view->zentaoBindAccount = $zentaoBindAccount;
  536. $this->view->gitlabID = $gitlabID;
  537. $this->display();
  538. }
  539. /**
  540. * 删除一个gitlab用户。
  541. * Delete a gitlab user.
  542. *
  543. * @param int $gitlabID
  544. * @param int $userID
  545. * @param string $confirm
  546. * @access public
  547. * @return void
  548. */
  549. public function deleteUser($gitlabID, $userID, $confirm = 'no')
  550. {
  551. if($confirm != 'yes') return print(js::confirm($this->lang->gitlab->user->confirmDelete , inlink('deleteUser', "gitlabID=$gitlabID&userID=$userID&confirm=yes")));
  552. $user = $this->gitlab->apiGetSingleUser($gitlabID, $userID);
  553. $reponse = $this->gitlab->apiDeleteUser($gitlabID, $userID);
  554. /* If the status code beginning with 20 is returned or empty is returned, it is successful. */
  555. if(!$reponse or substr($reponse->message, 0, 2) == '20')
  556. {
  557. $this->loadModel('action')->create('gitlabuser', $userID, 'deleted', '', $user->name);
  558. /* Delete user bind. */
  559. $this->dao->delete()->from(TABLE_OAUTH)->where('providerType')->eq('gitlab')->andWhere('providerID')->eq($gitlabID)->andWhere('openID')->eq($userID)->exec();
  560. return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'load' => true));
  561. }
  562. return $this->send(array('result' => 'fail', 'message' => $reponse->message));
  563. }
  564. /**
  565. * gitlab项目列表页。
  566. * Browse gitlab project.
  567. *
  568. * @param int $gitlabID
  569. * @param string $orderBy
  570. * @param int $recTotal
  571. * @param int $recPerPage
  572. * @param int $pageID
  573. * @access public
  574. * @return void
  575. */
  576. public function browseProject($gitlabID, $orderBy = 'id_desc', $recTotal = 0, $recPerPage = 15, $pageID = 1)
  577. {
  578. $openID = 0;
  579. if(!$this->app->user->admin) $this->gitlabZen->checkBindedUser($gitlabID);
  580. $this->app->loadClass('pager', true);
  581. $pager = new pager($recTotal, $recPerPage, $pageID);
  582. $keyword = fixer::input('post')->setDefault('keyword', '')->get('keyword'); // Fix bug#16741.
  583. $result = $this->gitlab->apiGetProjectsPager($gitlabID, $keyword, $orderBy, $pager);
  584. /* Get group id list by gitlab user that the user is maintainer. */
  585. $groupIDList = array(0 => 0);
  586. $groups = $this->gitlab->apiGetGroups($gitlabID, 'name_asc', 'maintainer');
  587. foreach($groups as $group) $groupIDList[] = $group->id;
  588. foreach($result['projects'] as $project)
  589. {
  590. $project->adminer = (bool)$this->app->user->admin;
  591. if(!$project->adminer and isset($project->owner) and $project->owner->id == $openID) $project->adminer = true;
  592. $project->isMaintainer = $this->gitlab->checkUserAccess($gitlabID, $project->id, $project, $groupIDList, 'maintainer');
  593. $project->isDeveloper = $this->gitlab->checkUserAccess($gitlabID, $project->id, $project, $groupIDList, 'developer');
  594. }
  595. $gitlab = $this->gitlab->getByID($gitlabID);
  596. $repos = $this->loadModel('repo')->getListByCondition("serviceHost = '{$gitlabID}'", 'Gitlab');
  597. $repoPairs = array();
  598. foreach($repos as $repo) $repoPairs[$repo->serviceProject] = $repo->id;
  599. $this->view->gitlab = $gitlab;
  600. $this->view->keyword = urldecode(urldecode($keyword));
  601. $this->view->pager = $result['pager'];
  602. $this->view->title = $this->lang->gitlab->common . $this->lang->hyphen . $this->lang->gitlab->browseProject;
  603. $this->view->gitlabID = $gitlabID;
  604. $this->view->gitlabProjectList = empty($result['projects']) ? array() : $result['projects'];
  605. $this->view->orderBy = $orderBy;
  606. $this->view->repoPairs = $repoPairs;
  607. $this->display();
  608. }
  609. /**
  610. * 创建一个gitlab项目。
  611. * Creat a gitlab project.
  612. *
  613. * @param int $gitlabID
  614. * @access public
  615. * @return void
  616. */
  617. public function createProject($gitlabID)
  618. {
  619. if($_POST)
  620. {
  621. $gitlabProject = form::data($this->config->gitlab->form->project->create)->get();
  622. $this->gitlab->createProject($gitlabID, $gitlabProject);
  623. if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
  624. return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => inlink('browseProject', "gitlabID=$gitlabID")));
  625. }
  626. $gitlab = $this->gitlab->getByID($gitlabID);
  627. $user = $this->gitlab->apiGetCurrentUser($gitlab->url, $gitlab->token);
  628. /* Get namespaces data */
  629. $namespacesList = $this->gitlab->apiGetNamespaces($gitlabID);
  630. $namespaces = array();
  631. foreach($namespacesList as $namespace)
  632. {
  633. if($namespace->kind == 'user' and $namespace->path == $user->username)
  634. {
  635. $namespaces[$namespace->id] = $namespace->path;
  636. $this->view->defaultSpace = $namespace->id;
  637. }
  638. if($namespace->kind == 'group') $namespaces[$namespace->id] = $namespace->path;
  639. }
  640. $this->view->title = $this->lang->gitlab->common . $this->lang->hyphen . $this->lang->gitlab->project->create;
  641. $this->view->gitlab = $gitlab;
  642. $this->view->user = $user;
  643. $this->view->namespaces = $namespaces;
  644. $this->view->gitlabID = $gitlabID;
  645. $this->display();
  646. }
  647. /**
  648. * 编辑一个gitlab项目。
  649. * Edit a gitlab project.
  650. *
  651. * @param int $gitlabID
  652. * @param int $projectID
  653. * @access public
  654. * @return void
  655. */
  656. public function editProject($gitlabID, $projectID)
  657. {
  658. if($_POST)
  659. {
  660. $gitlabProject = form::data($this->config->gitlab->form->project->edit)->get();
  661. $this->gitlab->editProject($gitlabID, $gitlabProject);
  662. if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
  663. return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => inlink('browseProject', "gitlabID=$gitlabID")));
  664. }
  665. $project = $this->gitlab->apiGetSingleProject($gitlabID, $projectID);
  666. $this->view->title = $this->lang->gitlab->common . $this->lang->hyphen . $this->lang->gitlab->project->edit;
  667. $this->view->project = $project;
  668. $this->view->gitlabID = $gitlabID;
  669. $this->display();
  670. }
  671. /**
  672. * 删除一个gitlab项目。
  673. * Delete a gitlab project.
  674. *
  675. * @param int $gitlabID
  676. * @param int $projectID
  677. * @param string $confirm
  678. * @access public
  679. * @return void
  680. */
  681. public function deleteProject($gitlabID, $projectID, $confirm = 'no')
  682. {
  683. if($confirm != 'yes') return print(js::confirm($this->lang->gitlab->project->confirmDelete , inlink('deleteProject', "gitlabID=$gitlabID&projectID=$projectID&confirm=yes")));
  684. $project = $this->gitlab->apiGetSingleProject($gitlabID, $projectID);
  685. $reponse = $this->gitlab->apiDeleteProject($gitlabID, $projectID);
  686. /* If the status code beginning with 20 is returned or empty is returned, it is successful. */
  687. if(!$reponse or substr($reponse->message, 0, 2) == '20')
  688. {
  689. $this->loadModel('action')->create('gitlabproject', $projectID, 'deleted', '', $project->name);
  690. return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'load' => true));
  691. }
  692. return $this->send(array('result' => 'fail', 'message' => $reponse->message));
  693. }
  694. /**
  695. * Gitlab分支列表。
  696. * Browse gitlab branch.
  697. *
  698. * @param int $gitlabID
  699. * @param int $projectID
  700. * @param string $orderBy
  701. * @param int $recTotal
  702. * @param int $recPerPage
  703. * @param int $pageID
  704. * @access public
  705. * @return void
  706. */
  707. public function browseBranch($gitlabID, $projectID, $orderBy = 'name_desc', $recTotal = 0, $recPerPage = 20, $pageID = 1)
  708. {
  709. $this->session->set('gitlabBranchList', $this->app->getURI(true));
  710. $branchList = array();
  711. $result = $this->gitlab->apiGetBranches($gitlabID, $projectID);
  712. foreach($result as $gitlabBranch)
  713. {
  714. $branch = new stdClass();
  715. $branch->name = $gitlabBranch->name;
  716. $branch->lastCommitter = $gitlabBranch->commit->committer_name;
  717. $branch->lastCommittedDate = date('Y-m-d H:i:s', strtotime($gitlabBranch->commit->committed_date));
  718. $branchList[] = $branch;
  719. }
  720. /* Data sort. */
  721. list($order, $sort) = explode('_', $orderBy);
  722. $orderList = array();
  723. foreach($branchList as $branch)
  724. {
  725. $orderList[] = $branch->$order;
  726. }
  727. array_multisort($orderList, $sort == 'desc' ? SORT_DESC : SORT_ASC, $branchList);
  728. /* Pager. */
  729. $this->app->loadClass('pager', true);
  730. $recTotal = count($branchList);
  731. $pager = new pager($recTotal, $recPerPage, $pageID);
  732. $branchList = array_chunk($branchList, (int)$pager->recPerPage);
  733. $this->view->gitlab = $this->gitlab->getByID($gitlabID);
  734. $this->view->pager = $pager;
  735. $this->view->title = $this->lang->gitlab->common . $this->lang->hyphen . $this->lang->gitlab->browseBranch;
  736. $this->view->gitlabID = $gitlabID;
  737. $this->view->projectID = $projectID;
  738. $this->view->gitlabBranchList = empty($branchList) ? $branchList: $branchList[$pageID - 1];
  739. $this->view->orderBy = $orderBy;
  740. $this->display();
  741. }
  742. /**
  743. * 创建一个gitlab分支。
  744. * Creat a gitlab branch.
  745. *
  746. * @param int $gitlabID
  747. * @param int $projectID
  748. * @access public
  749. * @return void
  750. */
  751. public function createBranch($gitlabID, $projectID)
  752. {
  753. if($_POST)
  754. {
  755. $gitlabBranch = form::data($this->config->gitlab->form->branch->create)->get();
  756. $this->gitlab->createBranch($gitlabID, $projectID, $gitlabBranch);
  757. if(dao::isError()) return $this->sendError(dao::getError());
  758. $locate = $this->session->gitlabBranchList ? $this->session->gitlabBranchList : inlink('browseBranch', "gitlibID=$gitlabID&projectID=$projectID");
  759. return $this->sendSuccess(array('message' => $this->lang->gitlab->createSuccess, 'load' => $locate));
  760. }
  761. /* Get branches by api. */
  762. $branches = $this->gitlab->apiGetBranches($gitlabID, $projectID);
  763. if(!is_array($branches)) $branches= array();
  764. $branchPairs = array();
  765. foreach($branches as $branch) $branchPairs[$branch->name] = $branch->name;
  766. $this->view->title = $this->lang->gitlab->common . $this->lang->hyphen . $this->lang->gitlab->createBranch;
  767. $this->view->gitlabID = $gitlabID;
  768. $this->view->projectID = $projectID;
  769. $this->view->branchPairs = $branchPairs;
  770. $this->display();
  771. }
  772. /**
  773. * Gitlab tag列表。
  774. * Browse gitlab tag.
  775. *
  776. * @param int $gitlabID
  777. * @param int $projectID
  778. * @param string $orderBy
  779. * @param int $recTotal
  780. * @param int $recPerPage
  781. * @param int $pageID
  782. * @access public
  783. * @return void
  784. */
  785. public function browseTag($gitlabID, $projectID, $orderBy = 'updated_desc', $recTotal = 0, $recPerPage = 20, $pageID = 1)
  786. {
  787. $project = $this->gitlab->apiGetSingleProject($gitlabID, $projectID);
  788. if(!$this->app->user->admin) $this->gitlabZen->checkBindedUser($gitlabID);
  789. $this->session->set('gitlabTagList', $this->app->getURI(true));
  790. $keyword = fixer::input('post')->setDefault('keyword', '')->get('keyword');
  791. /* Pager. */
  792. $this->app->loadClass('pager', true);
  793. $pager = new pager($recTotal, $recPerPage, $pageID);
  794. $tagList = array();
  795. $result = $this->gitlab->apiGetTags($gitlabID, $projectID, $orderBy, $keyword, $pager);
  796. foreach($result as $gitlabTag)
  797. {
  798. $tag = new stdClass();
  799. $tag->name = $gitlabTag->name;
  800. $tag->lastCommitter = $gitlabTag->commit->committer_name;
  801. $tag->updated = date('Y-m-d H:i:s', strtotime($gitlabTag->commit->committed_date));
  802. $tag->protected = $gitlabTag->protected;
  803. $tag->gitlabID = $gitlabID;
  804. $tag->projectID = $projectID;
  805. $tag->tagName = helper::safe64Encode(urlencode($tag->name));
  806. $tagList[] = $tag;
  807. }
  808. $this->view->gitlab = $this->gitlab->getByID($gitlabID);
  809. $this->view->pager = $pager;
  810. $this->view->title = $this->lang->gitlab->common . $this->lang->hyphen . $this->lang->gitlab->browseTag;
  811. $this->view->gitlabID = $gitlabID;
  812. $this->view->projectID = $projectID;
  813. $this->view->keyword = $keyword;
  814. $this->view->project = $project;
  815. $this->view->gitlabTagList = $tagList;
  816. $this->view->orderBy = $orderBy;
  817. $this->display();
  818. }
  819. /**
  820. * 导入gitlab issue 到禅道。
  821. * Import gitlab issue to zentaopms.
  822. *
  823. * @param int $gitlabID
  824. * @param int $projectID
  825. * @access public
  826. * @return void
  827. */
  828. public function importIssue($gitlabID, $projectID)
  829. {
  830. $gitlab = $this->gitlab->getByID($gitlabID);
  831. if($gitlab) $user = $this->gitlab->apiGetCurrentUser($gitlab->url, $gitlab->token);
  832. if(empty($user->is_admin)) return print(js::alert($this->lang->gitlab->tokenLimit) . js::locate($this->createLink('gitlab', 'edit', array('gitlabID' => $gitlabID))));
  833. if($_POST)
  834. {
  835. $executionList = $this->post->executionList;
  836. $objectTypeList = $this->post->objectTypeList;
  837. $productList = $this->post->productList;
  838. $failedIssues = array();
  839. foreach($executionList as $issueID => $executionID)
  840. {
  841. if(empty($executionID) and $productList[$issueID]) return $this->send(array('result' => 'fail', 'message' => $this->lang->gitlab->importIssueError));
  842. }
  843. foreach($executionList as $issueID => $executionID)
  844. {
  845. if(empty($executionID)) continue;
  846. $executionID = (int)$executionID;
  847. $objectType = $objectTypeList[$issueID];
  848. $issue = $this->gitlab->apiGetSingleIssue($gitlabID, $projectID, $issueID);
  849. $issue->objectType = $objectType;
  850. $issue->objectID = 0; // Meet the required parameters for issueToZentaoObject.
  851. if(isset($issue->assignee)) $issue->assignee_id = $issue->assignee->id;
  852. $issue->updated_by_id = $issue->author->id; // Here can be replaced by current zentao user.
  853. $object = $this->gitlabZen->issueToZentaoObject($issue, $gitlabID);
  854. $object->product = (int)$productList[$issueID];
  855. $object->execution = $executionID;
  856. $clonedObject = clone $object;
  857. if($objectType == 'task') $objectID = $this->loadModel('task')->createTaskFromGitlabIssue($clonedObject, $executionID);
  858. if($objectType == 'bug') $objectID = $this->loadModel('bug')->createBugFromGitlabIssue($clonedObject, $executionID);
  859. if($objectType == 'story') $objectID = $this->loadModel('story')->createStoryFromGitlabIssue($clonedObject, $executionID);
  860. if($objectID)
  861. {
  862. $this->loadModel('action')->create($objectType, $objectID, 'ImportFromGitlab', '', $issueID);
  863. $object->id = $objectID;
  864. $this->gitlab->saveImportedIssue($gitlabID, $projectID, $objectType, $objectID, $issue, $object);
  865. }
  866. else
  867. {
  868. $failedIssues[] = $issue->iid;
  869. }
  870. }
  871. if($failedIssues) return $this->send(array('result' => 'success', 'message' => $this->lang->gitlab->importIssueWarn));
  872. return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'reload' => true));
  873. }
  874. $savedIssueIDList = $this->dao->select('BID as issueID')->from(TABLE_RELATION)
  875. ->where('relation')->eq('gitlab')
  876. ->andWhere('BType')->eq('issue')
  877. ->andWhere('BVersion')->eq($projectID)
  878. ->andWhere('extra')->eq($gitlabID)
  879. ->fetchAll('issueID');
  880. /* 'not[iids]' option in gitlab API has a issue when iids is too long. */
  881. $gitlabIssues = $this->gitlab->apiGetIssues($gitlabID, $projectID, '&state=opened');
  882. if(!is_array($gitlabIssues)) $gitlabIssues = array();
  883. foreach($gitlabIssues as $index => $issue)
  884. {
  885. foreach($savedIssueIDList as $savedIssueID)
  886. {
  887. if($issue->iid == $savedIssueID->issueID)
  888. {
  889. unset($gitlabIssues[$index]);
  890. break;
  891. }
  892. }
  893. }
  894. $this->view->title = $this->lang->gitlab->common . $this->lang->hyphen . $this->lang->gitlab->importIssue;
  895. $this->view->importable = empty($gitlabIssues) ? false : true;
  896. $this->view->products = $this->loadModel('product')->getPairs('', 0, '', 'all');
  897. $this->view->gitlabID = $gitlabID;
  898. $this->view->gitlabProjectID = $projectID;
  899. $this->view->objectTypes = $this->config->gitlab->objectTypes;
  900. $this->view->gitlabIssues = array_values($gitlabIssues);
  901. $this->display();
  902. }
  903. /**
  904. * 根据版本库创建webhook。
  905. * Create Webhook by repoID.
  906. *
  907. * @param int $repoID
  908. * @param string $confirm
  909. * @access public
  910. * @return void
  911. */
  912. public function createWebhook($repoID, $confirm = 'no')
  913. {
  914. if($confirm == 'no')
  915. {
  916. return print(js::confirm($this->lang->gitlab->confirmAddWebhook, $this->createLink('gitlab', 'createWebhook', "repoID=$repoID&confirm=yes")));
  917. }
  918. else
  919. {
  920. $repo = $this->loadModel('repo')->getByID($repoID);
  921. $res = $this->gitlab->addPushWebhook($repo);
  922. if($res)
  923. {
  924. return $this->send(array('result' => 'success', 'message' => $this->lang->gitlab->addWebhookSuccess));
  925. }
  926. else
  927. {
  928. return $this->send(array('result' => 'fail', 'message' => $this->lang->gitlab->failCreateWebhook));
  929. }
  930. }
  931. }
  932. /**
  933. * 管理gitlab项目成员。
  934. * Manage a gitlab project members.
  935. *
  936. * @param int $repoID
  937. * @access public
  938. * @return void
  939. */
  940. public function manageProjectMembers($repoID)
  941. {
  942. if($_POST)
  943. {
  944. $data = fixer::input('post')->get();
  945. $accounts = array_filter($data->account);
  946. if(count($accounts) != count(array_unique($accounts))) return $this->send(array('result' => 'fail', 'message' => $this->lang->gitlab->group->repeatError));
  947. $repo = $this->loadModel('repo')->getByID($repoID);
  948. $users = $this->loadModel('user')->getPairs('noletter|noempty|nodeleted');
  949. $bindedUsers = $this->loadModel('pipeline')->getUserBindedPairs($repo->gitService, 'gitlab', 'account,openID');
  950. if(empty($repo->acl))
  951. {
  952. $repo->acl = new stdClass();
  953. $repo->acl->users = array();
  954. }
  955. $newGitlabMembers = array();
  956. foreach($accounts as $key => $account)
  957. {
  958. /* If the user has set permissions, check whether they are bound. */
  959. if(!empty($data->access_level[$key]))
  960. {
  961. if(!isset($bindedUsers[$account])) return $this->send(array('result' => 'fail', 'message' => $users[$account] . ' ' . $this->lang->gitlab->project->notbindedError));
  962. $newGitlabMembers[$bindedUsers[$account]] = (object) array('access_level' => $data->access_level[$key], 'expires_at' => $data->expires_at[$key]);
  963. }
  964. }
  965. $gitlabCurrentMembers = $this->gitlab->apiGetProjectMembers($repo->gitService, (int)$repo->serviceProject);
  966. list($addedMembers, $deletedMembers, $updatedMembers) = $this->gitlabZen->getProjectMemberData($gitlabCurrentMembers, $newGitlabMembers, $bindedUsers, $accounts, !empty($repo->acl->users) ? $repo->acl->users : array());
  967. foreach($addedMembers as $addedMember)
  968. {
  969. $this->gitlab->apiCreateProjectMember($repo->gitService, (int)$repo->serviceProject, $addedMember);
  970. }
  971. foreach($updatedMembers as $updatedMember)
  972. {
  973. $this->gitlab->apiUpdateProjectMember($repo->gitService, (int)$repo->serviceProject, $updatedMember);
  974. }
  975. foreach($deletedMembers as $deletedMemberID)
  976. {
  977. $this->gitlab->apiDeleteProjectMember($repo->gitService, (int)$repo->serviceProject, (int)$deletedMemberID);
  978. }
  979. $repo->acl->users = array_values($accounts);
  980. $this->dao->update(TABLE_REPO)->data(array('acl' => json_encode($repo->acl)))->where('id')->eq($repoID)->exec();
  981. return $this->sendSuccess(array('load' => helper::createLink('gitlab', 'browseProject', "gitlabID={$repo->gitService}")));
  982. }
  983. $repo = $this->loadModel('repo')->getByID($repoID);
  984. $users = $this->loadModel('user')->getPairs('noletter|noempty|nodeleted|noclosed');
  985. $projectMembers = $this->gitlab->apiGetProjectMembers($repo->gitService, (int)$repo->serviceProject);
  986. if(!is_array($projectMembers)) $projectMembers = array();
  987. /* Get users accesslevel. */
  988. $userAccessData = array();
  989. $bindedUsers = $this->loadModel('pipeline')->getUserBindedPairs($repo->gitService, 'gitlab', 'openID,account');
  990. foreach($projectMembers as $projectMember)
  991. {
  992. if(isset($projectMember->id) and isset($bindedUsers[$projectMember->id]))
  993. {
  994. $account = $bindedUsers[$projectMember->id];
  995. $projectMember->account = $account;
  996. $userAccessData[$account] = $projectMember;
  997. }
  998. }
  999. $this->view->title = $this->lang->gitlab->common . $this->lang->hyphen . $this->lang->gitlab->manageProjectMembers;
  1000. $this->view->userAccessData = $userAccessData;
  1001. $this->view->users = $users;
  1002. $this->view->repo = $repo;
  1003. $this->display();
  1004. }
  1005. /**
  1006. * Ajax方式获取执行根据产品id。
  1007. * AJAX: Get executions by productID.
  1008. *
  1009. * @param int $productID
  1010. * @access public
  1011. * @return string
  1012. */
  1013. public function ajaxGetExecutionsByProduct($productID)
  1014. {
  1015. if(!$productID) return $this->send(array('message' => array()));
  1016. $executions = $this->loadModel('product')->getExecutionPairsByProduct($productID);
  1017. $options = array();
  1018. $options[] = array('text' => '', 'value' => '');;
  1019. foreach($executions as $index => $execution)
  1020. {
  1021. $options[] = array('text' => $execution, 'value' => $index);
  1022. }
  1023. return print(json_encode($options));
  1024. }
  1025. /**
  1026. * Ajax方式获取项目分支。
  1027. * AJAX: Get project branches.
  1028. *
  1029. * @param int $gitlabID
  1030. * @param int $projectID
  1031. * @access public
  1032. * @return void
  1033. */
  1034. public function ajaxGetProjectBranches($gitlabID, $projectID)
  1035. {
  1036. if(!$gitlabID or !$projectID) return $this->send(array('message' => array()));
  1037. $branches = $this->gitlab->apiGetBranches($gitlabID, $projectID);
  1038. $options = array();
  1039. $options[] = array('text' => '', 'value' => '');;
  1040. foreach($branches as $branch)
  1041. {
  1042. $options[] = array('text' => $branch->name, 'value' => $branch->name);
  1043. }
  1044. return print(json_encode($options));
  1045. }
  1046. /**
  1047. * 创建一个gitlab标签。
  1048. * Create a gitlab tag.
  1049. *
  1050. * @param int $gitlabID
  1051. * @param int $projectID
  1052. * @access public
  1053. * @return void
  1054. */
  1055. public function createTag($gitlabID, $projectID)
  1056. {
  1057. if($_POST)
  1058. {
  1059. $gitlabTag = form::data($this->config->gitlab->form->tag->create)->get();
  1060. $this->gitlab->createTag($gitlabID, $projectID, $gitlabTag);
  1061. if(dao::isError()) return $this->sendError(dao::getError());
  1062. return $this->sendSuccess(array('load' => inlink('browseTag', "gitlabID=$gitlabID&projectID=$projectID")));
  1063. }
  1064. $gitlabBranches = $this->gitlab->apiGetBranches($gitlabID, $projectID);
  1065. $branches = array();
  1066. foreach($gitlabBranches as $branch)
  1067. {
  1068. $branches[$branch->name] = $branch->name;
  1069. }
  1070. $this->view->title = $this->lang->gitlab->common . $this->lang->hyphen . $this->lang->gitlab->createTag;
  1071. $this->view->gitlabID = $gitlabID;
  1072. $this->view->projectID = $projectID;
  1073. $this->view->branches = $branches;
  1074. $this->display();
  1075. }
  1076. /**
  1077. * 删除一个gitlab标签。
  1078. * Delete a gitlab tag.
  1079. *
  1080. * @param int $gitlabID
  1081. * @param int $projectID
  1082. * @param string $tagName
  1083. * @access public
  1084. * @return void
  1085. */
  1086. public function deleteTag($gitlabID, $projectID, $tagName = '')
  1087. {
  1088. /* Fix error when request type is PATH_INFO and the tag name contains '-'.*/
  1089. $tagName = urldecode(helper::safe64Decode($tagName));
  1090. $reponse = $this->gitlab->apiDeleteTag($gitlabID, $projectID, $tagName);
  1091. /* If the status code beginning with 20 is returned or empty is returned, it is successful. */
  1092. if(!$reponse or substr($reponse->message, 0, 2) == '20')
  1093. {
  1094. $this->loadModel('action')->create('gitlabtag', $projectID, 'deleted', '', $projectID);
  1095. return $this->sendSuccess(array('load' => true));
  1096. }
  1097. return $this->sendError($reponse->message);
  1098. }
  1099. /**
  1100. * 管理gitlab分支保护策略。
  1101. * Manage a gitlab branch protected.
  1102. *
  1103. * @param int $repoID
  1104. * @param int $projectID
  1105. * @access public
  1106. * @return void
  1107. * @param int $gitlabID
  1108. */
  1109. public function manageBranchPriv($gitlabID, $projectID)
  1110. {
  1111. if(!$this->app->user->admin)
  1112. {
  1113. $this->gitlabZen->checkBindedUser($gitlabID);
  1114. $project = $this->gitlab->apiGetSingleProject($gitlabID, $projectID);
  1115. if(!$this->gitlab->checkUserAccess($gitlabID, $projectID, $project)) return print(js::alert($this->lang->gitlab->noAccess) . js::locate($this->createLink('gitlab', 'browse')));
  1116. }
  1117. $hasAccessBranches = $this->gitlab->apiGetBranchPrivs($gitlabID, $projectID, '', 'name_asc');
  1118. foreach($hasAccessBranches as $branch)
  1119. {
  1120. $branch->pushAccess = (string)$this->gitlab->checkAccessLevel($branch->push_access_levels);
  1121. $branch->mergeAccess = (string)$this->gitlab->checkAccessLevel($branch->merge_access_levels);
  1122. }
  1123. if(!empty($_POST))
  1124. {
  1125. $result = $this->gitlab->manageBranchPrivs($gitlabID, $projectID, $hasAccessBranches);
  1126. if(!empty($result)) return $this->send(array('result' => 'fail', 'message' => sprintf($this->lang->gitlab->saveFailed, implode(', ', $result))));
  1127. return $this->send(array('message' => $this->lang->saveSuccess, 'result' => 'success', 'locate' => inlink('browseProject', "gitlabID=$gitlabID")));
  1128. }
  1129. $allBranches = $this->gitlab->apiGetBranches($gitlabID, $projectID);
  1130. $branchPairs = array();
  1131. foreach($allBranches as $branch) $branchPairs[$branch->name] = $branch->name;
  1132. $this->view->title = $this->lang->gitlab->common . $this->lang->hyphen . $this->lang->gitlab->browseBranchPriv;
  1133. $this->view->gitlabID = $gitlabID;
  1134. $this->view->projectID = $projectID;
  1135. $this->view->branchPairs = $branchPairs;
  1136. $this->view->hasAccessBranches = $hasAccessBranches;
  1137. $this->display();
  1138. }
  1139. /**
  1140. * 管理gitlab 标签保护策略。
  1141. * Manage a gitlab tag protected.
  1142. *
  1143. * @param int $repoID
  1144. * @param int $projectID
  1145. * @access public
  1146. * @return void
  1147. * @param int $gitlabID
  1148. */
  1149. public function manageTagPriv($gitlabID, $projectID)
  1150. {
  1151. if(!$this->app->user->admin)
  1152. {
  1153. $this->gitlabZen->checkBindedUser($gitlabID);
  1154. $project = $this->gitlab->apiGetSingleProject($gitlabID, $projectID);
  1155. if(!$this->gitlab->checkUserAccess($gitlabID, $projectID, $project)) return print(js::alert($this->lang->gitlab->noAccess) . js::locate($this->createLink('gitlab', 'browse')));
  1156. }
  1157. $hasAccessTags = $this->gitlab->apiGetTagPrivs($gitlabID, $projectID, '', 'name_asc');
  1158. foreach($hasAccessTags as $tag) $tag->createAccess = (string)$this->gitlab->checkAccessLevel($tag->create_access_levels);
  1159. if(!empty($_POST))
  1160. {
  1161. $result = $this->gitlab->manageTagPrivs($gitlabID, $projectID, $hasAccessTags);
  1162. if(!empty($result)) return $this->send(array('result' => 'fail', 'message' => sprintf($this->lang->gitlab->saveFailed, implode(', ', $result))));
  1163. return $this->send(array('message' => $this->lang->saveSuccess, 'result' => 'success', 'locate' => inlink('browseProject', "gitlabID=$gitlabID")));
  1164. }
  1165. $allTags = $this->gitlab->apiGetTags($gitlabID, $projectID);
  1166. $tagPairs = array();
  1167. foreach($allTags as $tag) $tagPairs[$tag->name] = $tag->name;
  1168. $this->view->title = $this->lang->gitlab->common . $this->lang->hyphen . $this->lang->gitlab->browseTagPriv;
  1169. $this->view->gitlabID = $gitlabID;
  1170. $this->view->projectID = $projectID;
  1171. $this->view->hasAccessTags = $hasAccessTags;
  1172. $this->view->tagPairs = $tagPairs;
  1173. $this->display();
  1174. }
  1175. }