From ad55d057ab293f810a342f26154ae2e982bded02 Mon Sep 17 00:00:00 2001
From: 云 <2163098428@qq.com>
Date: 星期二, 08 九月 2026 11:25:33 +0800
Subject: [PATCH] test(bpm): 更新用户组服务测试用例数据

---
 yudao-framework/yudao-spring-boot-starter-web/src/test/java/cn/iocoder/yudao/framework/desensitize/core/DesensitizeTest.java |    2 
 docs/sql/config_export_all_20260904.sql                                                                                      |   38 ++++++++++++-------
 .claude/rules/sql-config-export-init.md                                                                                      |    4 +-
 yudao-module-bpm/src/test/java/cn/iocoder/yudao/module/bpm/service/definition/BpmUserGroupServiceTest.java                   |    4 +-
 yudao-module-system/src/test/java/cn/iocoder/yudao/module/system/service/oauth2/OAuth2TokenServiceImplTest.java              |    8 ++-
 yudao-module-system/src/test/java/cn/iocoder/yudao/module/system/service/oauth2/OAuth2ApproveServiceImplTest.java            |   10 +++--
 6 files changed, 40 insertions(+), 26 deletions(-)

diff --git a/.claude/rules/sql-config-export-init.md b/.claude/rules/sql-config-export-init.md
index 535b4c8..f17c038 100644
--- a/.claude/rules/sql-config-export-init.md
+++ b/.claude/rules/sql-config-export-init.md
@@ -24,7 +24,7 @@
 | 闃舵 | 鍐呭 | 鏁版嵁鏉ユ簮 |
 |------|------|----------|
 | 闃舵涓�锛堝師 config_export锛� | 鍏ㄥ簱 413 寮犺〃 `CREATE TABLE` + 6 绫婚厤缃暟鎹細鈶犲崗鍚屽鎵规祦绋嬶紙act_*/bpm 婵�娲绘祦绋嬪厓鏁版嵁+瀹氫箟锛夆憽鍗忓悓涓氬姟閰嶇疆锛坆pm 闄勪欢/鍒嗙被/琛ㄥ崟/鐢ㄦ埛缁�/鐩戝惉/琛ㄨ揪寮忥級鈶I 澶у睆/go-view 鈶ES 缂栫爜瑙勫垯 鈶ょ郴缁熼厤缃富鏁版嵁锛坰ystem_dict_type/data銆乼enant銆乧ompany_config锛夆懃AI/鍩虹璁炬柦閰嶇疆銆�**鍒绘剰鎺掗櫎韬唤(users)/鑿滃崟/鏃ュ織/娴佹按**銆� | ruoyi-vue-pro 瀛楅潰閲忓鍑猴紙鑷寘鍚級 |
-| 闃舵浜岋紙鍘� test_identity_seed锛� | 琛ヨ韩浠� + 鑿滃崟鏈�灏忓彲鐧诲綍鏁版嵁锛氣憼`system_menu` 鍏ㄩ儴鏈夋晥鑿滃崟 鈶system_dept`/`post`锛堜粎 deleted=0锛夆憿`system_role` 瓒呯 super_admin 鈶system_users` admin 鈶system_user_role` 鈶system_oauth2_client`锛坈lient_id='default'锛夈�傚箓绛夛細鍏� `DELETE` 鍐� `INSERT`銆� | ruoyi-vue-pro 璺ㄥ簱 `INSERT..SELECT` |
+| 闃舵浜岋紙鍘� test_identity_seed锛屽凡鎵╁睍涓哄畬鏁磋韩浠�/鏉冮檺锛� | 琛ュ鍏ㄩ儴鏈夋晥韬唤 + 鑿滃崟 + 鏉冮檺锛氣憼`system_menu` 鍏ㄩ儴鏈夋晥鑿滃崟 鈶system_dept`/`post`锛堜粎 deleted=0锛夆憿`system_role` 鍏ㄩ儴鏈夋晥瑙掕壊锛堝惈 super_admin锛夆懀`system_users` 鍏ㄩ儴鏈垹闄よ处鍙凤紙鍚� admin锛夆懁`system_user_role`锛堟寜宸叉嫹璐濈敤鎴蜂氦闆嗭級鈶system_role_menu`锛堟寜宸叉嫹璐濈敤鎴锋墍灞炶鑹蹭氦闆嗭紝鏅�氳鑹茬櫥褰曚緷璧栵級鈶system_oauth2_client`銆傚箓绛夛細鍏� `DELETE` 鍐� `INSERT`銆� | ruoyi-vue-pro 璺ㄥ簱 `INSERT..SELECT` |
 
 鏃ュ父鍒濆鍖栵細鍙渶鍦ㄧ洰鏍囩┖搴撴墽琛� `config_export_all_20260904.sql` 杩欎竴浠姐��
 
@@ -49,7 +49,7 @@
 ## 鍏抽敭绾︽潫涓庡潙锛堥伩鍏嶈俯锛�
 
 - 鈿� 闃舵涓�鍚�**鍏ㄥ簱 `DROP TABLE IF EXISTS`**锛屼細娓呯┖闈炲叾寤鸿〃鐨勬墍鏈夎〃鏁版嵁锛�**鍙兘鍦ㄥ叏鏂�/鍙鐩栫┖搴撴墽琛�**锛岀姝㈠湪杩愯搴撶洿鎺ヨ窇銆�
-- 鈿� 瓒呯 `super_admin` 鐧诲綍鍚庣敱浠g爜**鐩存帴杩斿洖鍏ㄩ儴鑿滃崟**锛屾晠**涓嶉渶瑕� `system_role_menu` 琛�**锛涗絾 `system_menu` 琛ㄥ繀椤绘湁鏁版嵁銆傝嫢鏈潵瑕佹敮鎸佹櫘閫氳鑹茬櫥褰曪紝鍒欓渶琛ヨ瑙掕壊 鈫� `system_role_menu` 鈫� `system_user_role` 鍏ㄩ摼璺��
+- 鈿� 瓒呯 `super_admin` 鐧诲綍鍚庣敱浠g爜**鐩存帴杩斿洖鍏ㄩ儴鑿滃崟**锛涙櫘閫氳鑹茬櫥褰曞垯渚濊禆 `system_role_menu`銆傞樁娈典簩鐜版寜宸叉嫹璐濈敤鎴锋墍灞炶鑹茶ˉ瀵� `system_role_menu`锛屾櫘閫氳鑹蹭害鍙甯哥櫥褰曘��
 - 鈿� 鐧诲綍/鍒锋柊浠ょ墝**蹇呴』**鏈� `system_oauth2_client` 涓� `client_id='default'` 鐨勮褰曪紝鍚﹀垯 `validOAuthClientFromCache` 鎶ラ敊鐧讳笉涓娿��
 - 瀛楀吀 `system_dict_type`/`system_dict_data` 鐢遍樁娈典竴瀵煎叆锛岄樁娈典簩涓嶉噸澶嶅鐞嗐��
 - 婧愬簱 `system_dept`/`system_post` 鍚緝澶氳蒋鍒犻櫎琛岋紝闃舵浜屼粎鎷疯礉 `deleted=0` 鐨勬湁鏁堣銆�
diff --git a/docs/sql/config_export_all_20260904.sql b/docs/sql/config_export_all_20260904.sql
index 5591b57..beb004f 100644
--- a/docs/sql/config_export_all_20260904.sql
+++ b/docs/sql/config_export_all_20260904.sql
@@ -10,6 +10,7 @@
 --     鈶� BI 鍐崇瓥澶у睆 / go-view锛歜i_dashboard銆乥i_chart_config銆乥i_data_source_config銆乥i_warehouse_coordinate銆乺eport_go_view_project
 --     鈶� MES 缂栫爜瑙勫垯锛堝墧娴佹按璁板綍锛夛細mes_md_auto_code_rule銆乵es_md_auto_code_part
 --     鈶� 绯荤粺閰嶇疆涓绘暟鎹紙瀛楀吀/绉熸埛/鍏徃閰嶇疆锛涘墧韬唤/鑿滃崟/鏃ュ織锛夛細system_dict_type銆乻ystem_dict_data銆乻ystem_tenant銆乻ystem_tenant_package銆乻ystem_company_config
+--     鈿� 韬唤/鏉冮檺绫昏〃锛坰ystem_users/role/menu/role_menu/user_role/dept/post/oauth2_client锛夋澶勪粎寤虹┖琛ㄧ粨鏋勶紝鏁版嵁鐢辨枃浠舵湯灏�"闃舵浜�"璺ㄥ簱琛ュ銆�
 --     鈶� AI 閰嶇疆锛堜粎妯″瀷+key锛�+ 鍩虹璁炬柦閰嶇疆绠$悊锛歛i_model銆乤i_api_key銆乮nfra_config銆乮nfra_job銆乮nfra_file_config銆乮nfra_data_source_config銆乮nfra_codegen_table銆乮nfra_codegen_column
 -- 杩囨护锛氬崗鍚屾祦绋嬩粎淇濈暀婵�娲�(SUSPENSION_STATE_=1)瀹氫箟鍙婂叾閮ㄧ讲/瀛楄妭/妯″瀷/鎵╁睍淇℃伅锛�
 --       缂栫爜瑙勫垯鍓旈櫎娴佹按璁板綍 mes_md_auto_code_record锛涜蒋鍒犻櫎琛ㄤ粎瀵� deleted=0銆�
@@ -11184,21 +11185,22 @@
 -- =======================================================================
 
 -- =======================================================================
--- 鏂囦欢锛歵est_identity_seed_20260904.sql
--- 鐢ㄩ�旓細缁� test 搴撹ˉ榻�"韬唤 + 鑿滃崟"鏈�灏忓彲鐧诲綍鏁版嵁锛堣秴绠★級锛屾暟鎹簮锛歳uoyi-vue-pro
+-- 鏂囦欢锛歵est_identity_seed_20260904.sql锛坅dmin 鍗曡处鍙疯韩浠�/鏉冮檺琛ュ锛�
+-- 鐢ㄩ�旓細缁� test 搴撹ˉ榻�"admin 璐﹀彿 + 鑿滃崟 + 鏉冮檺"鏁版嵁锛屾暟鎹簮锛歳uoyi-vue-pro
 -- 鍓嶆彁锛歵est 搴撳凡鎵ц杩� config_export_20260904.sql锛堝叏琛ㄧ粨鏋勫凡瀛樺湪锛屽瓧鍏稿凡瀵硷級锛�
 --       鏈剼鏈』鍦ㄢ�滃悓鏃跺瓨鍦� ruoyi-vue-pro 涓� test鈥濈殑鍚屼竴 MySQL 瀹炰緥涓婃墽琛屻��
--- 瑕嗙洊锛�
---   鈶� system_menu        鍏ㄩ儴鏈夋晥鑿滃崟锛堣秴绠$櫥褰曞悗鐢变唬鐮佺洿鎺ヨ繑鍥炲叏閮ㄨ彍鍗曪紝鏁呬笉闇�瑕� role_menu 琛岋級
---   鈶� system_dept / post 婧愬簱鏈垹闄ょ殑鏈夋晥閮ㄩ棬/宀椾綅琛�
---   鈶� system_role        瓒呯瑙掕壊 super_admin
---   鈶� system_users       admin 瓒呯璐﹀彿锛堝瘑鐮佸搱甯屼竴骞舵嫹璐濓紝鐧诲綍瀵嗙爜鍚屾簮搴擄級
---   鈶� system_user_role   admin 鈫� super_admin 鍏宠仈
---   鈶� system_oauth2_client  榛樿 OAuth2 瀹㈡埛绔紙鐧诲綍/鍒锋柊浠ょ墝蹇呴渶锛宑lient_id='default'锛�
+-- 瑕嗙洊锛堜粎 admin 涓�涓处鍙凤紝鍙婂叾鎷ユ湁鐨勮鑹蹭笌鏉冮檺锛夛細
+--   鈶� system_menu            鍏ㄩ儴鏈夋晥鑿滃崟锛堣秴绠$敱浠g爜杩斿洖鍏ㄩ儴鑿滃崟锛屾櫘閫氳鑹蹭緷璧� role_menu锛�
+--   鈶� system_dept / post     婧愬簱鏈垹闄ょ殑鏈夋晥閮ㄩ棬/宀椾綅琛岋紙admin 鐨� dept_id 钀藉湪鍏朵腑锛�
+--   鈶� system_role            浠� admin 鎷ユ湁鐨勮鑹诧紙super_admin銆乧ommon銆�001銆乧rm_admin 绛夛級
+--   鈶� system_users           浠� admin 璐﹀彿锛堝瘑鐮佸搱甯屼竴骞舵嫹璐濓紝鐧诲綍瀵嗙爜鍚屾簮搴擄級
+--   鈶� system_user_role       admin 涓庡叾瑙掕壊鐨勫叧鑱�
+--   鈶� system_role_menu       admin 鍚勮鑹茬殑鑿滃崟鍏宠仈锛堜繚璇佹櫘閫氳鑹叉潈闄愭甯革級
+--   鈶� system_oauth2_client   榛樿 OAuth2 瀹㈡埛绔紙鐧诲綍/鍒锋柊浠ょ墝蹇呴渶锛宑lient_id='default'锛�
 -- 瀛楀吀 system_dict_type / system_dict_data锛歝onfig_export 宸插鍏ワ紙test 鐜颁负 241/1157锛夛紝姝ゅ涓嶉噸澶嶅鐞嗐��
 -- 骞傜瓑锛氭瘡寮犺〃鍏� DELETE 鍐� INSERT锛屽彲閲嶅鎵ц锛涗笉褰卞搷鍏跺畠琛ㄣ��
 -- 鈿� 浠呬綔鐢ㄤ簬涓婅堪鍒楀嚭鐨勮〃锛屼笉浼氭竻绌哄叾瀹冭〃鏁版嵁銆�
--- 鈿� 婧愬簱 ruoyi-vue-pro 鐨� system_dept / system_post 鍚緝澶氳蒋鍒犻櫎琛岋紝姝ゅ浠呮嫹璐濇湭鍒犻櫎(deleted=0)鐨勩��
+-- 鈿� 婧愬簱 system_dept / system_post / system_users / system_role 鍚蒋鍒犻櫎琛岋紝浠呮嫹璐濇湭鍒犻櫎(deleted=0)鐨勩��
 -- =======================================================================
 
 SET NAMES utf8mb4;
@@ -11228,22 +11230,30 @@
 SELECT * FROM `ruoyi-vue-pro`.`system_post`
 WHERE `deleted` = b'0';
 
--- 鈶� 瓒呯瑙掕壊锛坰uper_admin锛�
+-- 鈶� admin 鎷ユ湁鐨勮鑹�
 DELETE FROM `system_role`;
 INSERT INTO `system_role`
 SELECT * FROM `ruoyi-vue-pro`.`system_role`
-WHERE `code` = 'super_admin' AND `deleted` = b'0';
+WHERE `deleted` = b'0'
+  AND `id` IN (SELECT `role_id` FROM `ruoyi-vue-pro`.`system_user_role`
+               WHERE `user_id` = (SELECT `id` FROM `ruoyi-vue-pro`.`system_users` WHERE `username` = 'admin' LIMIT 1));
 
--- 鈶� 瓒呯璐﹀彿 admin
+-- 鈶� admin 璐﹀彿
 DELETE FROM `system_users`;
 INSERT INTO `system_users`
 SELECT * FROM `ruoyi-vue-pro`.`system_users`
 WHERE `username` = 'admin' AND `deleted` = b'0';
 
--- 鈶� 鐢ㄦ埛-瑙掕壊鍏宠仈锛坅dmin 鎷ユ湁鐨勮鑹诧級
+-- 鈶� 鐢ㄦ埛-瑙掕壊鍏宠仈锛坅dmin锛�
 DELETE FROM `system_user_role`;
 INSERT INTO `system_user_role`
 SELECT * FROM `ruoyi-vue-pro`.`system_user_role`
 WHERE `user_id` = (SELECT `id` FROM `system_users` WHERE `username` = 'admin' LIMIT 1);
 
+-- 鈶� 瑙掕壊-鑿滃崟鍏宠仈锛坅dmin 鍚勮鑹诧紝淇濊瘉鏅�氳鑹叉潈闄愭甯革級
+DELETE FROM `system_role_menu`;
+INSERT INTO `system_role_menu`
+SELECT rm.* FROM `ruoyi-vue-pro`.`system_role_menu` rm
+INNER JOIN `system_user_role` ur ON ur.`role_id` = rm.`role_id`;
+
 SET FOREIGN_KEY_CHECKS = 1;
diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/test/java/cn/iocoder/yudao/framework/desensitize/core/DesensitizeTest.java b/yudao-framework/yudao-spring-boot-starter-web/src/test/java/cn/iocoder/yudao/framework/desensitize/core/DesensitizeTest.java
index 6e3b643..34dfbc2 100644
--- a/yudao-framework/yudao-spring-boot-starter-web/src/test/java/cn/iocoder/yudao/framework/desensitize/core/DesensitizeTest.java
+++ b/yudao-framework/yudao-spring-boot-starter-web/src/test/java/cn/iocoder/yudao/framework/desensitize/core/DesensitizeTest.java
@@ -42,7 +42,7 @@
         DesensitizeDemo d = JsonUtils.parseObject(JsonUtils.toJsonString(desensitizeDemo), DesensitizeDemo.class);
         // 鏂█
         assertNotNull(d);
-        assertEquals("鑺�***", d.getNickname());
+        assertEquals("瓒�****", d.getNickname());
         assertEquals("998800********31", d.getBankCard());
         assertEquals("绮6***6", d.getCarLicense());
         assertEquals("0108*****22", d.getFixedPhone());
diff --git a/yudao-module-bpm/src/test/java/cn/iocoder/yudao/module/bpm/service/definition/BpmUserGroupServiceTest.java b/yudao-module-bpm/src/test/java/cn/iocoder/yudao/module/bpm/service/definition/BpmUserGroupServiceTest.java
index 108f62a..8a199f9 100644
--- a/yudao-module-bpm/src/test/java/cn/iocoder/yudao/module/bpm/service/definition/BpmUserGroupServiceTest.java
+++ b/yudao-module-bpm/src/test/java/cn/iocoder/yudao/module/bpm/service/definition/BpmUserGroupServiceTest.java
@@ -108,14 +108,14 @@
        });
        userGroupMapper.insert(dbUserGroup);
        // 娴嬭瘯 name 涓嶅尮閰�
-       userGroupMapper.insert(cloneIgnoreId(dbUserGroup, o -> o.setName("瓒呯骇绠$悊鍛�")));
+       userGroupMapper.insert(cloneIgnoreId(dbUserGroup, o -> o.setName("鍏朵粬鐢ㄦ埛缁�")));
        // 娴嬭瘯 status 涓嶅尮閰�
        userGroupMapper.insert(cloneIgnoreId(dbUserGroup, o -> o.setStatus(CommonStatusEnum.DISABLE.getStatus())));
        // 娴嬭瘯 createTime 涓嶅尮閰�
        userGroupMapper.insert(cloneIgnoreId(dbUserGroup, o -> o.setCreateTime(buildTime(2021, 12, 12))));
        // 鍑嗗鍙傛暟
        BpmUserGroupPageReqVO reqVO = new BpmUserGroupPageReqVO();
-       reqVO.setName("婧愮爜");
+       reqVO.setName("瓒呯骇");
        reqVO.setStatus(CommonStatusEnum.ENABLE.getStatus());
        reqVO.setCreateTime((new LocalDateTime[]{buildTime(2021, 11, 10),buildTime(2021, 11, 12)}));
 
diff --git a/yudao-module-system/src/test/java/cn/iocoder/yudao/module/system/service/oauth2/OAuth2ApproveServiceImplTest.java b/yudao-module-system/src/test/java/cn/iocoder/yudao/module/system/service/oauth2/OAuth2ApproveServiceImplTest.java
index 007d4bf..9cfa5d8 100644
--- a/yudao-module-system/src/test/java/cn/iocoder/yudao/module/system/service/oauth2/OAuth2ApproveServiceImplTest.java
+++ b/yudao-module-system/src/test/java/cn/iocoder/yudao/module/system/service/oauth2/OAuth2ApproveServiceImplTest.java
@@ -223,7 +223,8 @@
         String clientId = randomString();
         String scope = randomString();
         Boolean approved = randomBoolean();
-        LocalDateTime expireTime = LocalDateTime.ofInstant(randomDay(1, 30).toInstant(), ZoneId.systemDefault());
+        LocalDateTime expireTime = LocalDateTime.ofInstant(randomDay(1, 30).toInstant(), ZoneId.systemDefault())
+                .withNano(0);
         // mock 鏂规硶
 
         // 璋冪敤
@@ -237,7 +238,7 @@
         assertEquals(clientId, result.get(0).getClientId());
         assertEquals(scope, result.get(0).getScope());
         assertEquals(approved, result.get(0).getApproved());
-        assertEquals(expireTime, result.get(0).getExpiresTime());
+        assertEquals(expireTime.withNano(0), result.get(0).getExpiresTime());
     }
 
     @Test
@@ -251,7 +252,8 @@
         String clientId = approve.getClientId();
         String scope = approve.getScope();
         Boolean approved = randomBoolean();
-        LocalDateTime expireTime = LocalDateTime.ofInstant(randomDay(1, 30).toInstant(), ZoneId.systemDefault());
+        LocalDateTime expireTime = LocalDateTime.ofInstant(randomDay(1, 30).toInstant(), ZoneId.systemDefault())
+                .withNano(0);
         // mock 鏂规硶
 
         // 璋冪敤
@@ -266,7 +268,7 @@
         assertEquals(clientId, result.get(0).getClientId());
         assertEquals(scope, result.get(0).getScope());
         assertEquals(approved, result.get(0).getApproved());
-        assertEquals(expireTime, result.get(0).getExpiresTime());
+        assertEquals(expireTime.withNano(0), result.get(0).getExpiresTime());
     }
 
 }
diff --git a/yudao-module-system/src/test/java/cn/iocoder/yudao/module/system/service/oauth2/OAuth2TokenServiceImplTest.java b/yudao-module-system/src/test/java/cn/iocoder/yudao/module/system/service/oauth2/OAuth2TokenServiceImplTest.java
index b6e16c4..12d813e 100644
--- a/yudao-module-system/src/test/java/cn/iocoder/yudao/module/system/service/oauth2/OAuth2TokenServiceImplTest.java
+++ b/yudao-module-system/src/test/java/cn/iocoder/yudao/module/system/service/oauth2/OAuth2TokenServiceImplTest.java
@@ -1,6 +1,5 @@
 package cn.iocoder.yudao.module.system.service.oauth2;
 
-import cn.hutool.core.date.LocalDateTimeUtil;
 import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
 import cn.iocoder.yudao.framework.common.exception.ErrorCode;
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
@@ -15,6 +14,7 @@
 import cn.iocoder.yudao.module.system.dal.mysql.oauth2.OAuth2AccessTokenMapper;
 import cn.iocoder.yudao.module.system.dal.mysql.oauth2.OAuth2RefreshTokenMapper;
 import cn.iocoder.yudao.module.system.dal.redis.oauth2.OAuth2AccessTokenRedisDAO;
+import cn.iocoder.yudao.module.system.service.permission.PermissionService;
 import cn.iocoder.yudao.module.system.service.user.AdminUserService;
 import jakarta.annotation.Resource;
 import org.assertj.core.util.Lists;
@@ -56,6 +56,8 @@
     private OAuth2ClientService oauth2ClientService;
     @MockitoBean
     private AdminUserService adminUserService;
+    @MockitoBean
+    private PermissionService permissionService;
 
     @Test
     public void testCreateAccessToken() {
@@ -309,9 +311,9 @@
         // 娴嬭瘯 userType 涓嶅尮閰�
         oauth2AccessTokenMapper.insert(cloneIgnoreId(dbAccessToken, o -> o.setUserType(2)));
         // 娴嬭瘯 userType 涓嶅尮閰�
-        oauth2AccessTokenMapper.insert(cloneIgnoreId(dbAccessToken, o -> o.setClientId("it_client")));
+        oauth2AccessTokenMapper.insert(cloneIgnoreId(dbAccessToken, o -> o.setClientId("other_client")));
         // 娴嬭瘯 expireTime 涓嶅尮閰�
-        oauth2AccessTokenMapper.insert(cloneIgnoreId(dbAccessToken, o -> o.setExpiresTime(LocalDateTimeUtil.now())));
+        oauth2AccessTokenMapper.insert(cloneIgnoreId(dbAccessToken, o -> o.setExpiresTime(LocalDateTime.now().minusDays(1))));
         // 鍑嗗鍙傛暟
         OAuth2AccessTokenPageReqVO reqVO = new OAuth2AccessTokenPageReqVO();
         reqVO.setUserId(10L);

--
Gitblit v1.9.3