Browse Source

v2.3.1

docker-svn
witersen 3 years ago
parent
commit
445e85bffb
  1. 6
      01.web/.gitignore
  2. 1
      01.web/dist/0.55456e93cfe3e0947bae.chunk.js
  3. 1
      01.web/dist/1.55456e93cfe3e0947bae.chunk.js
  4. 1
      01.web/dist/10.55456e93cfe3e0947bae.chunk.js
  5. BIN
      01.web/dist/143146fa24554ae2c5ac0a3982abb952.woff2
  6. 1
      01.web/dist/2.55456e93cfe3e0947bae.chunk.js
  7. 1
      01.web/dist/3.55456e93cfe3e0947bae.chunk.js
  8. 1
      01.web/dist/4.55456e93cfe3e0947bae.chunk.js
  9. 1
      01.web/dist/5.55456e93cfe3e0947bae.chunk.js
  10. BIN
      01.web/dist/537fba62e5b926e3ddff7bf13c8eee8e.png
  11. 1
      01.web/dist/6.55456e93cfe3e0947bae.chunk.js
  12. BIN
      01.web/dist/6eee7a3978d7d0d05d816816ca1b291c.png
  13. 1
      01.web/dist/7.55456e93cfe3e0947bae.chunk.js
  14. 1
      01.web/dist/8.55456e93cfe3e0947bae.chunk.js
  15. BIN
      01.web/dist/99ac3308dd8ee14f749f51538d0d5b9e.woff
  16. 870
      01.web/dist/a2c4a261a239aa84463dc70e4bac9b9a.svg
  17. BIN
      01.web/dist/d535a25a79fb1365ae814b61e88fae71.ttf
  18. 20
      01.web/dist/main.55456e93cfe3e0947bae.css
  19. 7
      01.web/dist/main.55456e93cfe3e0947bae.js
  20. 30
      01.web/dist/vendors.55456e93cfe3e0947bae.js
  21. 16
      01.web/index_prod.html
  22. 77
      01.web/src/views/advance/index.vue
  23. 51
      01.web/src/views/login/index.vue
  24. 86
      01.web/src/views/repositoryInfo/index.vue
  25. 2
      02.php/api.php
  26. 4
      02.php/app/controller/Common.php
  27. 35
      02.php/app/controller/Safe.php
  28. 11
      02.php/app/controller/Svnrep.php
  29. 4
      02.php/app/controller/base/Base.php
  30. 34
      02.php/app/service/Common.php
  31. 3
      02.php/app/service/Mail.php
  32. 4
      02.php/app/service/Personal.php
  33. 81
      02.php/app/service/Safe.php
  34. 11
      02.php/app/service/Statistics.php
  35. 16
      02.php/app/service/Svn.php
  36. 16
      02.php/app/service/Svngroup.php
  37. 141
      02.php/app/service/Svnrep.php
  38. 14
      02.php/app/service/Svnuser.php
  39. 4
      02.php/app/service/Update.php
  40. 24
      02.php/app/service/base/Base.php
  41. 4
      02.php/config/router.php
  42. 2
      02.php/config/svn.php
  43. 2
      02.php/config/version.php
  44. 136
      02.php/extension/Transfer/Transfer.php
  45. 271
      02.php/server/install.php
  46. 110
      02.php/server/svnadmind.php
  47. 11
      02.php/templete/svnadmind/svnadmind.service

6
01.web/.gitignore vendored

@ -3,9 +3,5 @@ @@ -3,9 +3,5 @@
.DS_Store
node_modules/
.project
dist
dist/*
src/config/*.tmp
src/config/env.js
/index.html
/index_prod.html
src/config/env.js

1
01.web/dist/0.55456e93cfe3e0947bae.chunk.js vendored

@ -0,0 +1 @@ @@ -0,0 +1 @@
webpackJsonp([0],{377:function(e,t,r){r(398);var n=r(147)(r(387),r(415),"data-v-51f19c28",null);n.options.__file="D:\\SVN\\B06.svn管理面板V2.0\\09.软件开发\\01.web\\src\\views\\layout\\basicLayout\\index.vue",n.esModule&&Object.keys(n.esModule).some(function(e){return"default"!==e&&"__esModule"!==e})&&console.error("named exports are not supported in *.vue files."),n.options.functional&&console.error("[vue-loader] index.vue: functional components are not supported with templates, they should use render functions."),e.exports=n.exports},387:function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default={data:function(){return{currentActiveName:"",logoContent:"SVN Admin",currentUsername:sessionStorage.user_name,currentRoleName:sessionStorage.user_role_name,navList:[],breadcrumb:[]}},methods:{LogOut:function(){var e=this,t={};e.$axios.post("/api.php?c=Common&a=Logout&t=web",t).then(function(t){var r=t.data;1==r.status?(sessionStorage.removeItem("token"),sessionStorage.removeItem("user_name"),sessionStorage.removeItem("user_role_id"),sessionStorage.removeItem("user_role_name"),e.$Message.success(r.message),e.$router.push({name:"login"})):e.$Message.error(r.message)}).catch(function(t){console.log(t),e.$Message.error("出错了 请联系管理员!")})},handleCommand:function(e){switch(e){case"logOut":this.logOUt()}},CreateNav:function(){var e=this,t=e.$router.options.routes.filter(function(e){return"manage"==e.name});t=t[0].children;var r=t.map(function(e){return e.meta.group}).filter(function(e){return""!=e.name});t=t.filter(function(e){return e.meta.group.num>0}),t=t.filter(function(e){return-1!=e.meta.user_role_id.indexOf(sessionStorage.user_role_id)});for(var n=[],o=0;o<r.length;o++){for(var a=[],i=0;i<t.length;i++)t[i].meta.group.num==r[o].num&&a.push(t[i]);0!=a.length&&n.push({title:r[o].name,value:a})}e.navList=n},SetBreadcrumb:function(){var e=this;e.breadcrumb=e.$route.matched},SetActiveName:function(){this.currentActiveName=this.$route.name}},mounted:function(){var e=this;e.CreateNav(),e.SetBreadcrumb(),this.SetActiveName()},watch:{$route:function(){this.SetBreadcrumb()}}}},398:function(e,t){},410:function(e,t,r){e.exports=r.p+"6eee7a3978d7d0d05d816816ca1b291c.png"},415:function(e,t,r){e.exports={render:function(){var e=this,t=e.$createElement,n=e._self._c||t;return n("div",[n("Layout",[n("Header",{staticStyle:{"background-color":"#9b1be5","background-image":"linear-gradient(90deg, #9b1be5 0%, #2085ea 100%)",color:"#fff",position:"fixed",width:"100%","z-index":"99"}},[n("img",{staticStyle:{"line-height":"64px",position:"absolute",top:"12px",left:"1%"},attrs:{src:r(410)}}),e._v(" "),n("Dropdown",{staticStyle:{float:"right",zindex:"99"},attrs:{transfer:!0,trigger:"click"},on:{"on-click":e.LogOut}},[n("a",{staticStyle:{"margin-left":"8px",color:"#fff"},attrs:{href:"javascript:void(0)"}},[e._v("\n "+e._s(e.currentUsername)+"\n "),n("Icon",{attrs:{type:"md-arrow-dropdown"}})],1),e._v(" "),n("DropdownMenu",{attrs:{slot:"list"},slot:"list"},[n("DropdownItem",[e._v("退出")])],1)],1),e._v(" "),n("div",{staticStyle:{float:"right"}},[n("Divider",{attrs:{type:"vertical"}})],1),e._v(" "),n("div",{staticStyle:{float:"right"}},[n("a",{staticStyle:{"margin-left":"8px",color:"#fff",cursor:"default"}},[e._v(e._s(e.currentRoleName))])])],1),e._v(" "),n("Layout",{staticStyle:{"margin-top":"64px"}},[n("Sider",{staticStyle:{"min-height":"calc(100vh - 64px)",position:"fixed","z-index":"99",height:"100%"}},[n("Menu",{staticStyle:{height:"100%"},attrs:{theme:"light",width:"auto","active-name":e.currentActiveName}},e._l(e.navList,function(t,r){return n("MenuGroup",{key:r,attrs:{title:t.title}},e._l(t.value,function(t,o){return n("MenuItem",{key:r+"-"+o,attrs:{name:t.name,to:t.path}},[n("Icon",{attrs:{type:t.meta.icon}}),e._v("\n "+e._s(t.meta.title)+"\n ")],1)}))}))],1),e._v(" "),n("Layout",{staticStyle:{padding:"20px 30px 0px 220px",height:"calc(100vh - 64px)"}},[n("Breadcrumb",{staticStyle:{padding:"0px 0px 20px 0px"}},e._l(e.breadcrumb,function(t,r){return n("BreadcrumbItem",{key:r},[e._v(e._s(t.meta.title))])})),e._v(" "),n("Content",[n("router-view")],1)],1)],1)],1)],1)},staticRenderFns:[]},e.exports.render._withStripped=!0}});

1
01.web/dist/1.55456e93cfe3e0947bae.chunk.js vendored

@ -0,0 +1 @@ @@ -0,0 +1 @@
webpackJsonp([1],{383:function(e,t,o){o(396);var a=o(147)(o(393),o(413),null,null);a.options.__file="D:\\SVN\\B06.svn管理面板V2.0\\09.软件开发\\01.web\\src\\views\\systemLog\\index.vue",a.esModule&&Object.keys(a.esModule).some(function(e){return"default"!==e&&"__esModule"!==e})&&console.error("named exports are not supported in *.vue files."),a.options.functional&&console.error("[vue-loader] index.vue: functional components are not supported with templates, they should use render functions."),e.exports=a.exports},393:function(e,t,o){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default={data:function(){return{pageCurrentLog:1,pageSizeLog:10,totalLog:0,searchKeywordLog:"",loadingGetLogList:!0,loadingClearLogs:!1,tableColumnLog:[{title:"序号",type:"index",fixed:"left",minWidth:80},{title:"操作人",key:"log_add_user_name",minWidth:120},{title:"日志类型",key:"log_type_name",minWidth:150},{title:"详细信息",key:"log_content",tooltip:!0,minWidth:120},{title:"操作时间",key:"log_add_time",minWidth:150}],tableDataLog:[]}},computed:{},created:function(){},mounted:function(){this.GetLogList()},methods:{LogPageSizeChange:function(e){this.pageSizeLog=e,this.GetLogList()},LogPageChange:function(e){this.pageCurrentLog=e,this.GetLogList()},SearchGetLogList:function(){this.GetLogList()},GetLogList:function(){var e=this;e.loadingGetLogList=!0,e.tableDataLog=[];var t={pageSize:e.pageSizeLog,currentPage:e.pageCurrentLog,searchKeyword:e.searchKeywordLog};e.$axios.post("/api.php?c=Logs&a=GetLogList&t=web",t).then(function(t){e.loadingGetLogList=!1;var o=t.data;1==o.status?(e.tableDataLog=o.data.data,e.totalLog=o.data.total):e.$Message.error(o.message)}).catch(function(t){e.loadingGetLogList=!1,console.log(t),e.$Message.error("出错了 请联系管理员!")})},ClearLogs:function(){var e=this;e.$Modal.confirm({title:"清空日志",content:"确定要清空日志记录吗?此操作不可逆!",onOk:function(){e.loadingClearLogs=!0;var t={};e.$axios.post("/api.php?c=Logs&a=ClearLogs&t=web",t).then(function(t){e.loadingClearLogs=!1;var o=t.data;1==o.status?(e.$Message.success(o.message),e.GetLogList()):e.$Message.error(o.message)}).catch(function(t){e.loadingClearLogs=!1,console.log(t),e.$Message.error("出错了 请联系管理员!")})}})},ExportLog:function(){var e=this;o.e(10).then(function(){var t=o(394),a=t.export_json_to_excel,n=["序号","操作人","日志类型","详细信息","操作时间"],s=["index","log_add_user_name","log_type_name","log_content","log_add_time"],i=e.tableDataLog;for(var r in i)i[r].index=parseInt(r)+1;a(n,e.FormatJson(s,i),"logs-"+new Date)}.bind(null,o)).catch(o.oe)},FormatJson:function(e,t){return t.map(function(t){return e.map(function(e){return t[e]})})}}}},396:function(e,t){},413:function(e,t,o){e.exports={render:function(){var e=this,t=e.$createElement,o=e._self._c||t;return o("div",[o("Card",{attrs:{bordered:!1,"dis-hover":!0}},[o("Row",{staticStyle:{"margin-bottom":"15px"}},[o("Col",{attrs:{type:"flex",justify:"space-between",xs:21,sm:20,md:19,lg:18}},[o("Button",{attrs:{icon:"ios-trash-outline",type:"warning",ghost:"",loading:e.loadingClearLogs},on:{click:e.ClearLogs}},[e._v("清空日志")]),e._v(" "),o("Button",{attrs:{icon:"ios-cloud-download-outline",type:"success",ghost:""},on:{click:e.ExportLog}},[e._v("导出日志")])],1),e._v(" "),o("Col",{attrs:{xs:3,sm:4,md:5,lg:6}},[o("Input",{staticStyle:{width:"100%"},attrs:{search:"","enter-button":"",placeholder:"通过所有信息搜索..."},on:{"on-search":e.SearchGetLogList},model:{value:e.searchKeywordLog,callback:function(t){e.searchKeywordLog=t},expression:"searchKeywordLog"}})],1)],1),e._v(" "),o("Table",{attrs:{border:"",loading:e.loadingGetLogList,columns:e.tableColumnLog,data:e.tableDataLog,size:"small"}}),e._v(" "),o("Card",{attrs:{bordered:!1,"dis-hover":!0}},[0!=e.totalLog?o("Page",{attrs:{total:e.totalLog,current:e.pageCurrentLog,"page-size":e.pageSizeLog,size:"small","show-sizer":""},on:{"on-page-size-change":e.LogPageSizeChange,"on-change":e.LogPageChange}}):e._e()],1)],1)],1)},staticRenderFns:[]},e.exports.render._withStripped=!0}});

1
01.web/dist/10.55456e93cfe3e0947bae.chunk.js vendored

File diff suppressed because one or more lines are too long

BIN
01.web/dist/143146fa24554ae2c5ac0a3982abb952.woff2 vendored

Binary file not shown.

1
01.web/dist/2.55456e93cfe3e0947bae.chunk.js vendored

File diff suppressed because one or more lines are too long

1
01.web/dist/3.55456e93cfe3e0947bae.chunk.js vendored

File diff suppressed because one or more lines are too long

1
01.web/dist/4.55456e93cfe3e0947bae.chunk.js vendored

File diff suppressed because one or more lines are too long

1
01.web/dist/5.55456e93cfe3e0947bae.chunk.js vendored

File diff suppressed because one or more lines are too long

BIN
01.web/dist/537fba62e5b926e3ddff7bf13c8eee8e.png vendored

Binary file not shown.

After

Width:  |  Height:  |  Size: 399 KiB

1
01.web/dist/6.55456e93cfe3e0947bae.chunk.js vendored

File diff suppressed because one or more lines are too long

BIN
01.web/dist/6eee7a3978d7d0d05d816816ca1b291c.png vendored

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

1
01.web/dist/7.55456e93cfe3e0947bae.chunk.js vendored

File diff suppressed because one or more lines are too long

1
01.web/dist/8.55456e93cfe3e0947bae.chunk.js vendored

File diff suppressed because one or more lines are too long

BIN
01.web/dist/99ac3308dd8ee14f749f51538d0d5b9e.woff vendored

Binary file not shown.

870
01.web/dist/a2c4a261a239aa84463dc70e4bac9b9a.svg vendored

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 542 KiB

BIN
01.web/dist/d535a25a79fb1365ae814b61e88fae71.ttf vendored

Binary file not shown.

20
01.web/dist/main.55456e93cfe3e0947bae.css vendored

File diff suppressed because one or more lines are too long

7
01.web/dist/main.55456e93cfe3e0947bae.js vendored

File diff suppressed because one or more lines are too long

30
01.web/dist/vendors.55456e93cfe3e0947bae.js vendored

File diff suppressed because one or more lines are too long

16
01.web/index_prod.html

@ -0,0 +1,16 @@ @@ -0,0 +1,16 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<title>iView project</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0">
<link rel="stylesheet" href="/dist/main.55456e93cfe3e0947bae.css">
</head>
<body>
<div id="app"></div>
<script type="text/javascript" src="/dist/vendors.55456e93cfe3e0947bae.js"></script>
<script type="text/javascript" src="/dist/main.55456e93cfe3e0947bae.js"></script>
</body>
</html>

77
01.web/src/views/advance/index.vue

@ -15,7 +15,7 @@ @@ -15,7 +15,7 @@
<Tooltip
:transfer="true"
max-width="360"
content="可以使用系统提供的 install.php 文件在命令行模式下进行Subversion安装和初始化等操作"
content="可以使用系统提供的 server/install.php 文件在命令行模式下进行Subversion安装和初始化等操作"
>
<Button type="info">tips</Button>
</Tooltip>
@ -93,7 +93,7 @@ @@ -93,7 +93,7 @@
<Tooltip
:transfer="true"
max-width="350"
content="请注意,如果您的机器为公网服务器且非弹性IP,则可能会绑定失败。原因与云服务器厂商分配公网IP给服务器的方式有关。如果绑定失败,建议配置使用管理系统主机名代替检出地址。"
content="请注意,如果您的机器为公网服务器且非弹性IP,则可能会绑定失败。原因与云服务器厂商分配公网IP给服务器的方式有关。如果绑定失败,建议配置使用自定义主机名代替检出地址。"
>
<Button
type="warning"
@ -146,7 +146,11 @@ @@ -146,7 +146,11 @@
</TabPane>
<TabPane label="配置文件" name="2">
<Card :bordered="false" :dis-hover="true" style="width: 620px">
<Form :label-width="120" label-position="left">
<Alert
>可以使用系统提供的 server/install.php<br /><br />
文件在命令行模式下进行目录更换操作
</Alert>
<Form :label-width="160" label-position="left">
<FormItem
:label="item.key"
v-for="(item, index) in configList"
@ -402,10 +406,14 @@ @@ -402,10 +406,14 @@
<TabPane label="安全配置" name="5">
<Card :bordered="false" :dis-hover="true" style="width: 600px">
<Form :label-width="140">
<FormItem label="登录验证码">
<FormItem
:label="item.note"
v-for="(item, index) in listSafe"
:key="index"
>
<Row>
<Col span="12">
<Switch>
<Switch v-model="listSafe[index].enable">
<Icon type="md-checkmark" slot="open"></Icon>
<Icon type="md-close" slot="close"></Icon>
</Switch>
@ -415,8 +423,8 @@ @@ -415,8 +423,8 @@
<FormItem>
<Button
type="primary"
:loading="loadingEditPush"
@click="EditPush"
:loading="loadingEditSafe"
@click="SetSafeConfig"
>保存</Button
>
</FormItem>
@ -590,7 +598,7 @@ export default { @@ -590,7 +598,7 @@ export default {
* 版本信息
*/
version: {
current_verson: "2.3",
current_verson: "2.3.1",
php_version: "5.5 <= PHP < 8.0",
database: "MYSQL、SQLite",
github: "https://github.com/witersen/SvnAdminV2.0",
@ -616,6 +624,8 @@ export default { @@ -616,6 +624,8 @@ export default {
loadingEditEmail: false,
//
loadingEditPush: false,
//
loadingEditSafe: false,
//
loadingCheckUpdate: false,
@ -639,6 +649,8 @@ export default { @@ -639,6 +649,8 @@ export default {
configList: [],
//
listPush: [],
//
listSafe: [],
/**
* 对话框
@ -701,6 +713,7 @@ export default { @@ -701,6 +713,7 @@ export default {
this.GetConfig();
this.GetEmail();
this.GetPush();
this.GetSafeConfig();
},
methods: {
/**
@ -917,6 +930,27 @@ export default { @@ -917,6 +930,27 @@ export default {
that.$Message.error("出错了 请联系管理员!");
});
},
/**
* 获取安全配置选项
*/
GetSafeConfig() {
var that = this;
var data = {};
that.$axios
.post("/api.php?c=Safe&a=GetSafeConfig&t=web", data)
.then(function (response) {
var result = response.data;
if (result.status == 1) {
that.listSafe = result.data;
} else {
that.$Message.error(result.message);
}
})
.catch(function (error) {
console.log(error);
that.$Message.error("出错了 请联系管理员!");
});
},
/**
* 删除收件人邮箱
*/
@ -979,6 +1013,33 @@ export default { @@ -979,6 +1013,33 @@ export default {
that.$Message.error("出错了 请联系管理员!");
});
},
/**
* 保存安全配置选项
*/
SetSafeConfig() {
var that = this;
that.loadingEditSafe = true;
var data = {
listSafe: that.listSafe,
};
that.$axios
.post("/api.php?c=Safe&a=SetSafeConfig&t=web", data)
.then(function (response) {
that.loadingEditSafe = false;
var result = response.data;
if (result.status == 1) {
that.$Message.success(result.message);
that.GetSafeConfig();
} else {
that.$Message.error(result.message);
}
})
.catch(function (error) {
that.loadingEditSafe = false;
console.log(error);
that.$Message.error("出错了 请联系管理员!");
});
},
/**
* 安装SVN
*/

51
01.web/src/views/login/index.vue

@ -5,7 +5,7 @@ @@ -5,7 +5,7 @@
<template>
<div class="login">
<div class="login-con">
<Card icon="log-in" title="SVNAdmin V2.3" :bordered="false">
<Card icon="log-in" title="SVNAdmin V2.3.1" :bordered="false">
<div class="form-con">
<Form
ref="formUserLogin"
@ -41,7 +41,7 @@ @@ -41,7 +41,7 @@
<Option value="2">SVN用户</Option>
</Select>
</FormItem>
<FormItem prop="code">
<FormItem prop="code" v-if="verifyOption">
<Row>
<Col span="11"
><Input
@ -52,9 +52,9 @@ @@ -52,9 +52,9 @@
<Col span="1"></Col>
<Col span="12">
<img
@click="GetVeryfyCode"
@click="GetVerifyCode"
:src="formUserLogin.base64"
:alt="loadingGetVeryfyCode"
:alt="loadingGetVerifyCode"
style="width: 100%; cursor: pointer"
/>
</Col>
@ -83,9 +83,14 @@ export default { @@ -83,9 +83,14 @@ export default {
/**
* 加载
*/
loadingGetVeryfyCode: "loading......",
loadingGetVerifyCode: "loading......",
loadingLogin: false,
/**
* 组件状态
*/
verifyOption: false,
/**
* 表单
*/
@ -130,7 +135,7 @@ export default { @@ -130,7 +135,7 @@ export default {
}
}, 2000);
} else {
that.GetVeryfyCode();
that.GetVerifyOption();
}
},
methods: {
@ -144,16 +149,42 @@ export default { @@ -144,16 +149,42 @@ export default {
}
});
},
/**
* 获取验证码选项
*/
GetVerifyOption() {
var that = this;
var data = {};
that.$axios
.post("/api.php?c=Safe&a=GetVerifyOption&t=web", data)
.then(function (response) {
var result = response.data;
if (result.status == 1) {
if (result.data.enable == true) {
that.verifyOption = true;
that.GetVerifyCode();
} else {
that.verifyOption = false;
}
} else {
that.$Message.error(result.message);
}
})
.catch(function (error) {
console.log(error);
that.$Message.error("出错了 请联系管理员!");
});
},
/**
* 请求验证码
*/
GetVeryfyCode() {
GetVerifyCode() {
var that = this;
that.formUserLogin.base64 = "";
that.loadingGetVeryfyCode = "loading......";
that.loadingGetVerifyCode = "loading......";
var data = {};
that.$axios
.post("/api.php?c=Common&a=GetVeryfyCode&t=web", data)
.post("/api.php?c=Common&a=GetVerifyCode&t=web", data)
.then(function (response) {
var result = response.data;
if (result.status == 1) {
@ -204,7 +235,7 @@ export default { @@ -204,7 +235,7 @@ export default {
that.$router.push({ name: "repositoryInfo" });
}
} else {
that.GetVeryfyCode();
that.GetVerifyCode();
that.$Message.error(result.message);
}
})

86
01.web/src/views/repositoryInfo/index.vue

@ -249,14 +249,6 @@ @@ -249,14 +249,6 @@
>
</Col>
</Row>
<Alert type="warning"
>请注意当前的文件下载方案采用
<a href="https://github.com/jimmywarting/StreamSaver.js" target="_blank"
>StreamSaver</a
>
<br />
如要获取良好的下载体验请为站点配置HTTPS</Alert
>
<Table
height="200"
border
@ -269,7 +261,7 @@ @@ -269,7 +261,7 @@
<Button
type="success"
size="small"
@click="DownloadRepBackup(row.fileName)"
@click="DownloadRepBackup(row.fileUrl)"
>下载</Button
>
<Button type="error" size="small" @click="DelRepBackup(row.fileName)"
@ -826,6 +818,23 @@ @@ -826,6 +818,23 @@
</FormItem>
</Form>
</TabPane>
<!-- <TabPane label="从仓库导出权限">
<Alert
>将本仓库原有配置的权限导入到本系统<br /><br />
由于本系统采用多仓库对应一个配置文件的形式而不是传统的一个仓库对应一个配置文件的形式<br /><br />
因此您将之前的仓库通过本系统管理后原有仓库的人员和分组权限信息不再生效但是他们依然存在于配置文件中<br /><br />
因此您可通过识别功能将原来的人员和分组信息识别并导入到本系统以使原仓库的角色配置信息依然生效<br /><br />
此处只支持识别 authz 未加密的 passwd 文件
</Alert>
</TabPane> -->
<!-- <TabPane label="向仓库导入权限">
<Alert>
将本系统配置的角色和分组信息单独写入到本仓库中<br /><br />
由于本系统采用多仓库对应一个配置文件的形式而不是传统的一个仓库对应一个配置文件的形式<br /><br />
因此本操作适合于您不再使用本系统管理仓库并想回归一个仓库对应一个配置文件的形式
此处支持将内容写入到 authz passwd 文件
</Alert>
</TabPane> -->
</Tabs>
<div slot="footer">
<Button type="primary" ghost @click="modalRepAdvance = false"
@ -917,8 +926,6 @@ @@ -917,8 +926,6 @@
</template>
<script>
import { WritableStream } from "web-streams-polyfill/ponyfill";
export default {
data() {
return {
@ -1412,17 +1419,6 @@ export default { @@ -1412,17 +1419,6 @@ export default {
computed: {},
created() {},
mounted() {
// abort so it dose not look stuck
// window.onunload = () => {
// console.log('test-start');
// console.log(window.WritableStream);
// console.log(writer);
// console.log('test-end');
// writableStream.abort();
// // also possible to call abosrt on the writer you got from `getWriter()`
// writer.abort();
// };
this.GetStatus();
if (this.user_role_id == 1) {
this.GetRepList();
@ -1902,50 +1898,8 @@ export default { @@ -1902,50 +1898,8 @@ export default {
/**
* 下载备份文件
*/
DownloadRepBackup(fileName) {
var that = this;
const streamSaver = require("../../libs/streamsaver/StreamSaver");
fetch("/api.php?c=Svnrep&a=DownloadRepBackup&t=web", {
headers: {
"Content-Type": "application/json",
token: that.token,
},
method: "POST",
body: JSON.stringify({
fileName: fileName,
}),
}).then((response) => {
// These code section is adapted from an example of the StreamSaver.js
// https://jimmywarting.github.io/StreamSaver.js/examples/fetch.html
// If the WritableStream is not available (Firefox, Safari), take it from the ponyfill
if (!window.WritableStream) {
streamSaver.WritableStream = WritableStream;
window.WritableStream = WritableStream;
}
const fileStream = streamSaver.createWriteStream(fileName, {
size: response.headers.get("content-length"),
});
const readableStream = response.body;
// More optimized
if (readableStream.pipeTo) {
return readableStream.pipeTo(fileStream);
}
window.writer = fileStream.getWriter();
const reader = response.body.getReader();
const pump = () =>
reader
.read()
.then((res) =>
res.done ? writer.close() : writer.write(res.value).then(pump)
);
pump();
});
DownloadRepBackup(fileUrl) {
window.open(fileUrl, "_blank");
},
/**
* 删除备份文件

2
02.php/api.php

@ -3,7 +3,7 @@ @@ -3,7 +3,7 @@
* @Author: witersen
* @Date: 2022-04-24 23:37:06
* @LastEditors: witersen
* @LastEditTime: 2022-05-13 01:25:06
* @LastEditTime: 2022-05-21 12:51:28
* @Description: QQ:1801168257
*/

4
02.php/app/controller/Common.php

@ -52,9 +52,9 @@ class Common extends Base @@ -52,9 +52,9 @@ class Common extends Base
/**
* 获取验证码
*/
public function GetVeryfyCode()
public function GetVerifyCode()
{
$result = $this->ServiceCommon->GetVeryfyCode();
$result = $this->ServiceCommon->GetVerifyCode();
json2($result);
}
}

35
02.php/app/controller/Safe.php

@ -23,7 +23,40 @@ class Safe extends Base @@ -23,7 +23,40 @@ class Safe extends Base
function __construct()
{
parent::__construct();
$this->ServiceSafe = new ServiceSafe();
}
/**
* 获取安全配置选项
*
* @return array
*/
public function GetSafeConfig()
{
$result = $this->ServiceSafe->GetSafeConfig();
json2($result);
}
/**
* 设置安全配置选项
*
* @return array
*/
public function SetSafeConfig()
{
$result = $this->ServiceSafe->SetSafeConfig();
json2($result);
}
/**
* 获取登录验证码选项
*
* @return array
*/
public function GetVerifyOption()
{
$result = $this->ServiceSafe->GetVerifyOption();
json2($result);
}
}

11
02.php/app/controller/Svnrep.php

@ -3,7 +3,7 @@ @@ -3,7 +3,7 @@
* @Author: witersen
* @Date: 2022-04-24 23:37:05
* @LastEditors: witersen
* @LastEditTime: 2022-05-11 11:45:59
* @LastEditTime: 2022-05-21 13:55:49
* @Description: QQ:1801168257
*/
@ -191,6 +191,15 @@ class Svnrep extends Base @@ -191,6 +191,15 @@ class Svnrep extends Base
json2($result);
}
/**
* 重设仓库的UUID
*/
public function SetUUID()
{
$result = $this->ServiceSvnrep->SetUUID();
json2($result);
}
/**
* 获取备份文件夹下的文件列表
*/

4
02.php/app/controller/base/Base.php

@ -3,7 +3,7 @@ @@ -3,7 +3,7 @@
* @Author: witersen
* @Date: 2022-05-06 18:41:32
* @LastEditors: witersen
* @LastEditTime: 2022-05-07 12:11:40
* @LastEditTime: 2022-05-20 15:04:52
* @Description: QQ:1801168257
*/
@ -69,8 +69,6 @@ require_once BASE_PATH . '/app/service/Svnuser.php'; @@ -69,8 +69,6 @@ require_once BASE_PATH . '/app/service/Svnuser.php';
require_once BASE_PATH . '/app/service/Update.php';
//require extension
require_once BASE_PATH . '/extension/Transfer/Transfer.php';
require_once BASE_PATH . '/extension/Medoo-1.7.10/src/Medoo.php';
require_once BASE_PATH . '/extension/PHPMailer-6.6.0/src/Exception.php';

34
02.php/app/service/Common.php

@ -21,6 +21,7 @@ class Common extends Base @@ -21,6 +21,7 @@ class Common extends Base
private $Svnuser;
private $Logs;
private $Mail;
private $Safe;
function __construct()
{
@ -29,6 +30,7 @@ class Common extends Base @@ -29,6 +30,7 @@ class Common extends Base
$this->Svnuser = new Svnuser();
$this->Logs = new Logs();
$this->Mail = new Mail();
$this->Safe = new Safe();
}
/**
@ -39,17 +41,27 @@ class Common extends Base @@ -39,17 +41,27 @@ class Common extends Base
//清理过期token
$this->CleanBlack();
$codeResult = $this->database->get('verification_code', [
'end_time'
], [
'uuid' => $this->payload['uuid'],
'code' => $this->payload['code'],
]);
if ($codeResult == null) {
return message(200, 0, '验证码错误', $codeResult);
$verifyOptionResult = $this->Safe->GetVerifyOption();
if ($verifyOptionResult['status'] != 1) {
return message(200, 0, $verifyOptionResult['message']);
}
if ($codeResult['end_time'] < time()) {
return message(200, 0, '验证码过期');
$verifyOption = $verifyOptionResult['data'];
if ($verifyOption['enable'] == true) {
$codeResult = $this->database->get('verification_code', [
'end_time'
], [
'uuid' => $this->payload['uuid'],
'code' => $this->payload['code'],
]);
if ($codeResult == null) {
return message(200, 0, '验证码错误', $codeResult);
}
if ($codeResult['end_time'] < time()) {
return message(200, 0, '验证码过期');
}
}
$checkResult = FunCheckForm($this->payload, [
@ -152,7 +164,7 @@ class Common extends Base @@ -152,7 +164,7 @@ class Common extends Base
/**
* 获取验证码
*/
public function GetVeryfyCode()
public function GetVerifyCode()
{
//清除过期验证码
$this->Clean();

3
02.php/app/service/Mail.php

@ -372,6 +372,7 @@ class Mail extends Base @@ -372,6 +372,7 @@ class Mail extends Base
'option_value' => serialize($message_push_null),
'option_description' => ''
]);
return message(200, 1, '成功', $message_push_null);
}
if ($message_push['option_value'] == '') {
@ -380,6 +381,7 @@ class Mail extends Base @@ -380,6 +381,7 @@ class Mail extends Base
], [
'option_name' => 'message_push',
]);
return message(200, 1, '成功', $message_push_null);
}
@ -396,6 +398,7 @@ class Mail extends Base @@ -396,6 +398,7 @@ class Mail extends Base
], [
'option_name' => 'message_push'
]);
return message();
}
}

4
02.php/app/service/Personal.php

@ -3,7 +3,7 @@ @@ -3,7 +3,7 @@
* @Author: witersen
* @Date: 2022-04-24 23:37:05
* @LastEditors: witersen
* @LastEditTime: 2022-05-11 02:15:09
* @LastEditTime: 2022-05-20 16:29:41
* @Description: QQ:1801168257
*/
@ -119,8 +119,6 @@ class Personal extends Base @@ -119,8 +119,6 @@ class Personal extends Base
return message(200, 0, '用户不存在');
}
// FunShellExec('echo \'' . $result . '\' > ' . $this->config_svn['svn_passwd_file']);
FunFilePutContents($this->config_svn['svn_passwd_file'], $result);
$this->database->update('svn_users', [

81
02.php/app/service/Safe.php

@ -16,4 +16,85 @@ class Safe extends Base @@ -16,4 +16,85 @@ class Safe extends Base
parent::__construct();
}
/**
* 获取安全配置选项
*
* @return array
*/
public function GetSafeConfig()
{
$safe_config = $this->database->get('options', [
'option_value'
], [
'option_name' => 'safe_config'
]);
$safe_config_null = [
[
'name' => 'login_verify_code',
'note' => '登录验证码',
'enable' => true,
]
];
if ($safe_config == null) {
$this->database->insert('options', [
'option_name' => 'safe_config',
'option_value' => serialize($safe_config_null),
'option_description' => ''
]);
return message(200, 1, '成功', $safe_config_null);
}
if ($safe_config['option_value'] == '') {
$this->database->update('options', [
'option_value' => serialize($safe_config_null),
], [
'option_name' => 'safe_config',
]);
return message(200, 1, '成功', $safe_config_null);
}
return message(200, 1, '成功', unserialize($safe_config['option_value']));
}
/**
* 设置安全配置选项
*
* @return array
*/
public function SetSafeConfig()
{
$this->database->update('options', [
'option_value' => serialize($this->payload['listSafe'])
], [
'option_name' => 'safe_config'
]);
return message();
}
/**
* 获取登录验证码选项
*
* @return array
*/
public function GetVerifyOption()
{
$result = $this->GetSafeConfig();
if ($result['status'] != 1) {
return message(200, 0, '获取配置信息出错');
}
$safeConfig = $result['data'];
$index = array_search('login_verify_code', FunArrayColumn($safeConfig, 'name'));
if ($index === false) {
return message(200, 0, '获取配置信息出错');
}
return message(200, 1, '成功', $safeConfig[$index]);
}
}

11
02.php/app/service/Statistics.php

@ -218,8 +218,15 @@ class Statistics extends Base @@ -218,8 +218,15 @@ class Statistics extends Base
public function GetSystemAnalysis()
{
//操作系统类型和版本
$os = FunShellExec("cat /etc/redhat-release");
$os = $os['result'];
if (file_exists('/etc/redhat-release')) {
$os = FunShellExec("cat /etc/redhat-release");
$os = $os['result'];
} else if (file_exists('/etc/lsb-release')) {
$os = FunShellExec("cat /etc/lsb-release");
$os = $os['result'];
} else {
$os = 'Linux';
}
//仓库占用体积
$repSize = FunFormatSize(FunGetDirSizeDu($this->config_svn['rep_base_path']));

16
02.php/app/service/Svn.php

@ -3,7 +3,7 @@ @@ -3,7 +3,7 @@
* @Author: witersen
* @Date: 2022-04-24 23:37:05
* @LastEditors: witersen
* @LastEditTime: 2022-05-12 00:20:14
* @LastEditTime: 2022-05-20 16:29:48
* @Description: QQ:1801168257
*/
@ -140,8 +140,10 @@ class Svn extends Base @@ -140,8 +140,10 @@ class Svn extends Base
$bindPort = '';
$bindHost = '';
$svnserveContent = FunShellExec(sprintf("cat '%s'", $this->config_svn['svnserve_env_file']));
$svnserveContent = $svnserveContent['result'];
if (!is_readable($this->config_svn['svnserve_env_file'])) {
json1(200, 0, '文件' . $this->config_svn['svnserve_env_file'] . '不可读');
}
$svnserveContent = file_get_contents($this->config_svn['svnserve_env_file']);
//匹配端口
if (preg_match('/--listen-port[\s]+([0-9]+)/', $svnserveContent, $portMatchs) != 0) {
@ -248,8 +250,6 @@ class Svn extends Base @@ -248,8 +250,6 @@ class Svn extends Base
$config = sprintf("OPTIONS=\"-r '%s' --config-file '%s' --log-file '%s' --listen-port %s --listen-host %s\"", $this->config_svn['rep_base_path'], $this->config_svn['svn_conf_file'], $this->config_svn['svnserve_log_file'], $this->payload['bindPort'], $result['bindHost']);
//写入配置文件
// FunShellExec('echo \'' . $config . '\' > ' . $this->config_svn['svnserve_env_file']);
FunFilePutContents($this->config_svn['svnserve_env_file'], $config);
//启动svnserve
@ -284,8 +284,6 @@ class Svn extends Base @@ -284,8 +284,6 @@ class Svn extends Base
$config = sprintf("OPTIONS=\"-r '%s' --config-file '%s' --log-file '%s' --listen-port %s --listen-host %s\"", $this->config_svn['rep_base_path'], $this->config_svn['svn_conf_file'], $this->config_svn['svnserve_log_file'], $result['bindPort'], $this->payload['bindHost']);
//写入配置文件
// FunShellExec('echo \'' . $config . '\' > ' . $this->config_svn['svnserve_env_file']);
FunFilePutContents($this->config_svn['svnserve_env_file'], $config);
//启动svnserve
@ -349,6 +347,10 @@ class Svn extends Base @@ -349,6 +347,10 @@ class Svn extends Base
public function GetConfig()
{
return message(200, 1, '成功', [
[
'key' => '主目录',
'value' => $this->config_svn['home_path']
],
[
'key' => '仓库父目录',
'value' => $this->config_svn['rep_base_path']

16
02.php/app/service/Svngroup.php

@ -3,7 +3,7 @@ @@ -3,7 +3,7 @@
* @Author: witersen
* @Date: 2022-04-24 23:37:05
* @LastEditors: witersen
* @LastEditTime: 2022-05-11 02:16:31
* @LastEditTime: 2022-05-20 16:29:58
* @Description: QQ:1801168257
*/
@ -183,8 +183,6 @@ class Svngroup extends Base @@ -183,8 +183,6 @@ class Svngroup extends Base
}
//写入配置文件
// FunShellExec('echo \'' . $result . '\' > ' . $this->config_svn['svn_authz_file']);
FunFilePutContents($this->config_svn['svn_authz_file'], $result);
//写入数据库
@ -220,8 +218,6 @@ class Svngroup extends Base @@ -220,8 +218,6 @@ class Svngroup extends Base
return message(200, 0, '分组不存在');
}
// FunShellExec('echo \'' . $result . '\' > ' . $this->config_svn['svn_authz_file']);
FunFilePutContents($this->config_svn['svn_authz_file'], $result);
//从数据库删除
@ -267,8 +263,6 @@ class Svngroup extends Base @@ -267,8 +263,6 @@ class Svngroup extends Base
return message(200, 0, '文件格式错误(不存在[groups]标识)');
}
// FunShellExec('echo \'' . $result . '\' > ' . $this->config_svn['svn_authz_file']);
FunFilePutContents($this->config_svn['svn_authz_file'], $result);
return message();
@ -354,8 +348,6 @@ class Svngroup extends Base @@ -354,8 +348,6 @@ class Svngroup extends Base
return message(200, 0, '要添加的用户已存在该分组');
}
// FunShellExec('echo \'' . $result . '\' > ' . $this->config_svn['svn_authz_file']);
FunFilePutContents($this->config_svn['svn_authz_file'], $result);
return message();
@ -377,8 +369,6 @@ class Svngroup extends Base @@ -377,8 +369,6 @@ class Svngroup extends Base
return message(200, 0, '要删除的用户不在该分组');
}
// FunShellExec('echo \'' . $result . '\' > ' . $this->config_svn['svn_authz_file']);
FunFilePutContents($this->config_svn['svn_authz_file'], $result);
return message();
@ -411,8 +401,6 @@ class Svngroup extends Base @@ -411,8 +401,6 @@ class Svngroup extends Base
return message(200, 0, '存在分组循环嵌套的情况');
}
// FunShellExec('echo \'' . $result . '\' > ' . $this->config_svn['svn_authz_file']);
FunFilePutContents($this->config_svn['svn_authz_file'], $result);
return message();
@ -434,8 +422,6 @@ class Svngroup extends Base @@ -434,8 +422,6 @@ class Svngroup extends Base
return message(200, 0, '要删除的分组不在该分组');
}
// FunShellExec('echo \'' . $result . '\' > ' . $this->config_svn['svn_authz_file']);
FunFilePutContents($this->config_svn['svn_authz_file'], $result);
return message();

141
02.php/app/service/Svnrep.php

@ -3,14 +3,12 @@ @@ -3,14 +3,12 @@
* @Author: witersen
* @Date: 2022-04-24 23:37:05
* @LastEditors: witersen
* @LastEditTime: 2022-05-12 17:27:57
* @LastEditTime: 2022-05-21 14:14:40
* @Description: QQ:1801168257
*/
namespace app\service;
use Transfer;
class Svnrep extends Base
{
/**
@ -79,8 +77,6 @@ class Svnrep extends Base @@ -79,8 +77,6 @@ class Svnrep extends Base
//向authz写入仓库信息
$status = $this->SVNAdminRep->SetRepAuthz($this->authzContent, $this->payload['rep_name'], '/');
if ($status != '1') {
// FunShellExec('echo \'' . $status . '\' > ' . $this->config_svn['svn_authz_file']);
FunFilePutContents($this->config_svn['svn_authz_file'], $status);
}
@ -179,8 +175,6 @@ class Svnrep extends Base @@ -179,8 +175,6 @@ class Svnrep extends Base
}
if ($authzContet != $this->authzContent) {
// FunShellExec('echo \'' . $authzContet . '\' > ' . $this->config_svn['svn_authz_file']);
FunFilePutContents($this->config_svn['svn_authz_file'], $authzContet);
}
}
@ -241,8 +235,6 @@ class Svnrep extends Base @@ -241,8 +235,6 @@ class Svnrep extends Base
//写入配置文件
if ($authzContent != $this->authzContent) {
// FunShellExec('echo \'' . $authzContent . '\' > ' . $this->config_svn['svn_authz_file']);
FunFilePutContents($this->config_svn['svn_authz_file'], $authzContent);
}
}
@ -922,8 +914,6 @@ class Svnrep extends Base @@ -922,8 +914,6 @@ class Svnrep extends Base
}
//写入
// FunShellExec('echo \'' . $result . '\' > ' . $this->config_svn['svn_authz_file']);
FunFilePutContents($this->config_svn['svn_authz_file'], $result);
//返回
@ -947,8 +937,6 @@ class Svnrep extends Base @@ -947,8 +937,6 @@ class Svnrep extends Base
return message(200, 0, '已被删除');
} else {
//写入
// FunShellExec('echo \'' . $result . '\' > ' . $this->config_svn['svn_authz_file']);
FunFilePutContents($this->config_svn['svn_authz_file'], $result);
//返回
@ -978,8 +966,6 @@ class Svnrep extends Base @@ -978,8 +966,6 @@ class Svnrep extends Base
}
//写入
// FunShellExec('echo \'' . $result . '\' > ' . $this->config_svn['svn_authz_file']);
FunFilePutContents($this->config_svn['svn_authz_file'], $result);
//返回
@ -1033,8 +1019,6 @@ class Svnrep extends Base @@ -1033,8 +1019,6 @@ class Svnrep extends Base
}
//写入
// FunShellExec('echo \'' . $result . '\' > ' . $this->config_svn['svn_authz_file']);
FunFilePutContents($this->config_svn['svn_authz_file'], $result);
//返回
@ -1058,8 +1042,6 @@ class Svnrep extends Base @@ -1058,8 +1042,6 @@ class Svnrep extends Base
return message(200, 0, '已被删除');
} else {
//写入
// FunShellExec('echo \'' . $result . '\' > ' . $this->config_svn['svn_authz_file']);
FunFilePutContents($this->config_svn['svn_authz_file'], $result);
//返回
@ -1091,8 +1073,6 @@ class Svnrep extends Base @@ -1091,8 +1073,6 @@ class Svnrep extends Base
}
//写入
// FunShellExec('echo \'' . $result . '\' > ' . $this->config_svn['svn_authz_file']);
FunFilePutContents($this->config_svn['svn_authz_file'], $result);
//返回
@ -1164,8 +1144,6 @@ class Svnrep extends Base @@ -1164,8 +1144,6 @@ class Svnrep extends Base
//从配置文件删除指定仓库的所有路径
$result = $this->SVNAdminRep->DelRepAuthz($this->authzContent, $this->payload['rep_name']);
if ($result != '1') {
// FunShellExec('echo \'' . $result . '\' > ' . $this->config_svn['svn_authz_file']);
FunFilePutContents($this->config_svn['svn_authz_file'], $result);
}
@ -1231,6 +1209,26 @@ class Svnrep extends Base @@ -1231,6 +1209,26 @@ class Svnrep extends Base
return message(200, 1, '成功', $newArray);
}
/**
* 重设仓库的UUID
*/
public function SetUUID()
{
if ($this->payload['uuid'] == '') {
$cmd = sprintf("'%s' setuuid '%s'", $this->config_bin['svnadmin'], $this->config_svn['rep_base_path'] . $this->payload['rep_name']);
} else {
$cmd = sprintf("'%s' setuuid '%s' '%s'", $this->config_bin['svnadmin'], $this->config_svn['rep_base_path'] . $this->payload['rep_name'], $this->payload['uuid']);
}
$result = FunShellExec($cmd);
if ($result['resultCode'] == 0) {
return message();
} else {
return message(200, 0, $result['error']);
}
}
/**
* 获取备份文件夹下的文件列表
*/
@ -1238,6 +1236,11 @@ class Svnrep extends Base @@ -1238,6 +1236,11 @@ class Svnrep extends Base
{
$result = FunGetDirFileList($this->config_svn['backup_base_path']);
foreach ($result as $key => $value) {
$result[$key]['fileToken'] = hash_hmac('md5', $value['fileName'], $this->config_sign['signature']);
$result[$key]['fileUrl'] = sprintf('/api.php?c=Svnrep&a=DownloadRepBackup&t=web&fileName=%s&token=%s', $value['fileName'], $result[$key]['fileToken']);
}
return message(200, 1, '成功', $result);
}
@ -1262,19 +1265,37 @@ class Svnrep extends Base @@ -1262,19 +1265,37 @@ class Svnrep extends Base
}
/**
* 下载备份文件
* 下载前请求文件名和文件token
*/
public function DownloadRepBackup()
public function GetDownloadInfo()
{
$filePath = $this->config_svn['backup_base_path'] . $this->payload['fileName'];
$this->DownloadRepBackup2($filePath, $this->payload['fileName']);
}
/**
* 下载备份文件
*/
private function DownloadRepBackup1($filePath, $fileName)
public function DownloadRepBackup()
{
if (empty($_GET['fileName'])) {
json1(200, 0, '缺少文件名');
}
$fileName = $_GET['fileName'];
if (empty($_GET['token'])) {
json1(200, 0, '缺少文件token');
}
$token = $_GET['token'];
if ($token !== hash_hmac('md5', $fileName, $this->config_sign['signature'])) {
json1(200, 0, '文件token无效');
}
if (!file_exists($this->config_svn['backup_base_path'] . $fileName)) {
json1(200, 0, '文件不存在');
}
$filePath = $this->config_svn['backup_base_path'] . $fileName;
//以只读和二进制模式打开文件
$fp = @fopen($filePath, 'rb');
if ($fp) {
@ -1327,24 +1348,6 @@ class Svnrep extends Base @@ -1327,24 +1348,6 @@ class Svnrep extends Base
}
}
/**
* 下载备份文件
*/
private function DownloadRepBackup2($filePath, $fileName)
{
//文件类型
$mimeType = 'application/octet-stream';
//请求区域
$range = isset($_SERVER['HTTP_RANGE']) ? $_SERVER['HTTP_RANGE'] : null;
set_time_limit(0);
$transfer = new Transfer($filePath, $mimeType, $range);
$transfer->send();
}
/**
* 获取上传限制
*/
@ -1501,14 +1504,23 @@ class Svnrep extends Base @@ -1501,14 +1504,23 @@ class Svnrep extends Base
}
foreach ($repHooks as $key => $value) {
if (file_exists($hooksPath . $value['fileName'])) {
$hookFile = $hooksPath . $value['fileName'];
$hookTmpleFile = $hookFile . '.tmpl';
if (file_exists($hookFile)) {
$repHooks[$key]['hasFile'] = true;
$temp = FunShellExec(sprintf("cat '%s'", $hooksPath . $value['fileName']));
$repHooks[$key]['con'] = $temp['result'];
if (!is_readable($hookFile)) {
return message(200, 0, '文件' . $hookFile . '不可读');
}
$repHooks[$key]['con'] = file_get_contents($hookFile);
}
if (file_exists($hooksPath . $value['fileName'] . '.tmpl')) {
$temp = FunShellExec(sprintf("cat '%s'", $hooksPath . $value['fileName'] . '.tmpl'));
$repHooks[$key]['tmpl'] = $temp['result'];
if (file_exists($hookTmpleFile)) {
if (!is_readable($hookTmpleFile)) {
return message(200, 0, '文件' . $hookTmpleFile . '不可读');
}
$repHooks[$key]['tmpl'] = file_get_contents($hookTmpleFile);
}
}
@ -1566,6 +1578,9 @@ class Svnrep extends Base @@ -1566,6 +1578,9 @@ class Svnrep extends Base
return message(200, 0, '未创建自定义钩子目录');
}
if (!is_readable($recommend_hook_path)) {
return message(200, 0, '目录' . $recommend_hook_path . '不可读');
}
$dirs = scandir($recommend_hook_path);
foreach ($dirs as $dir) {
@ -1577,24 +1592,34 @@ class Svnrep extends Base @@ -1577,24 +1592,34 @@ class Svnrep extends Base
continue;
}
if (!is_readable($recommend_hook_path . $dir)) {
return message(200, 0, '目录' . $recommend_hook_path . $dir . '不可读');
}
$dirFiles = scandir($recommend_hook_path . $dir);
if (!in_array('hookDescription', $dirFiles) || !in_array('hookName', $dirFiles)) {
continue;
}
$hookName = FunShellExec(sprintf("cat '%s'", $recommend_hook_path . $dir . '/hookName'));
$hookName = $hookName['result'];
if (!is_readable($recommend_hook_path . $dir . '/hookName')) {
return message(200, 0, '文件' . $recommend_hook_path . $dir . '/hookName' . '不可读');
}
$hookName = file_get_contents($recommend_hook_path . $dir . '/hookName');
if (!file_exists($recommend_hook_path . $dir . '/' . trim($hookName))) {
continue;
}
$hookContent = FunShellExec(sprintf("cat '%s'", $recommend_hook_path . $dir . '/' . $hookName));
$hookContent = $hookContent['result'];
if (!is_readable($recommend_hook_path . $dir . '/' . $hookName)) {
return message(200, 0, '文件' . $recommend_hook_path . $dir . '/' . $hookName . '不可读');
}
$hookContent = file_get_contents($recommend_hook_path . $dir . '/' . $hookName);
$hookDescription = FunShellExec(sprintf("cat '%s'", $recommend_hook_path . $dir . '/hookDescription'));
$hookDescription = $hookDescription['result'];
if (!is_readable($recommend_hook_path . $dir . '/hookDescription')) {
return message(200, 0, '文件' . $recommend_hook_path . $dir . '/hookDescription' . '不可读');
}
$hookDescription = file_get_contents($recommend_hook_path . $dir . '/hookDescription');
array_push($list, [
'hookName' => $hookName,

14
02.php/app/service/Svnuser.php

@ -3,7 +3,7 @@ @@ -3,7 +3,7 @@
* @Author: witersen
* @Date: 2022-04-24 23:37:05
* @LastEditors: witersen
* @LastEditTime: 2022-05-11 02:21:30
* @LastEditTime: 2022-05-20 16:31:46
* @Description: QQ:1801168257
*/
@ -166,8 +166,6 @@ class Svnuser extends Base @@ -166,8 +166,6 @@ class Svnuser extends Base
return message(200, 0, '要启用的用户不存在');
}
// FunShellExec('echo \'' . $result . '\' > ' . $this->config_svn['svn_passwd_file']);
FunFilePutContents($this->config_svn['svn_passwd_file'], $result);
return message();
@ -186,8 +184,6 @@ class Svnuser extends Base @@ -186,8 +184,6 @@ class Svnuser extends Base
return message(200, 0, '要禁用的用户不存在');
}
// FunShellExec('echo \'' . $result . '\' > ' . $this->config_svn['svn_passwd_file']);
FunFilePutContents($this->config_svn['svn_passwd_file'], $result);
return message();
@ -233,8 +229,6 @@ class Svnuser extends Base @@ -233,8 +229,6 @@ class Svnuser extends Base
}
//写入配置文件
// FunShellExec('echo \'' . $result . '\' > ' . $this->config_svn['svn_passwd_file']);
FunFilePutContents($this->config_svn['svn_passwd_file'], $result);
//写入数据库
@ -275,8 +269,6 @@ class Svnuser extends Base @@ -275,8 +269,6 @@ class Svnuser extends Base
}
//写入配置文件
// FunShellExec('echo \'' . $result . '\' > ' . $this->config_svn['svn_passwd_file']);
FunFilePutContents($this->config_svn['svn_passwd_file'], $result);
//写入数据库
@ -316,12 +308,8 @@ class Svnuser extends Base @@ -316,12 +308,8 @@ class Svnuser extends Base
'svn_user_name' => $this->payload['svn_user_name']
]);
// FunShellExec('echo \'' . $resultAuthz . '\' > ' . $this->config_svn['svn_authz_file']);
FunFilePutContents($this->config_svn['svn_authz_file'], $resultAuthz);
// FunShellExec('echo \'' . $resultPasswd . '\' > ' . $this->config_svn['svn_passwd_file']);
FunFilePutContents($this->config_svn['svn_passwd_file'], $resultPasswd);
//日志

4
02.php/app/service/Update.php

@ -41,6 +41,10 @@ class Update extends Base @@ -41,6 +41,10 @@ class Update extends Base
if ($this->config_version['version'] < $last) {
return message(200, 1, '有新版本', $array);
}
if ($this->config_version['version'] > $last) {
return message(200, 1, '当前版本高于已发布版本');
}
}
return message(200, 0, '检测超时');

24
02.php/app/service/base/Base.php

@ -3,7 +3,7 @@ @@ -3,7 +3,7 @@
* @Author: witersen
* @Date: 2022-05-06 18:42:00
* @LastEditors: witersen
* @LastEditTime: 2022-05-09 21:10:15
* @LastEditTime: 2022-05-20 16:39:27
* @Description: QQ:1801168257
*/
@ -269,7 +269,16 @@ class Base @@ -269,7 +269,16 @@ class Base
*/
public function GetAuthz()
{
$this->authzContent = file_exists($this->config_svn['svn_authz_file']) ? file_get_contents($this->config_svn['svn_authz_file']) : '';
clearstatcache();
if (!file_exists($this->config_svn['svn_authz_file'])) {
json1(200, 0, '文件' . $this->config_svn['svn_authz_file'] . '不存在');
}
if (!is_readable($this->config_svn['svn_authz_file'])) {
json1(200, 0, '文件' . $this->config_svn['svn_authz_file'] . '不可读');
}
$this->authzContent = file_get_contents($this->config_svn['svn_authz_file']);
}
/**
@ -277,6 +286,15 @@ class Base @@ -277,6 +286,15 @@ class Base
*/
public function GetPasswd()
{
$this->passwdContent = file_exists($this->config_svn['svn_passwd_file']) ? file_get_contents($this->config_svn['svn_passwd_file']) : '';
clearstatcache();
if (!file_exists($this->config_svn['svn_passwd_file'])) {
json1(200, 0, '文件' . $this->config_svn['svn_passwd_file'] . '不存在');
}
if (!is_readable($this->config_svn['svn_passwd_file'])) {
json1(200, 0, '文件' . $this->config_svn['svn_passwd_file'] . '不可读');
}
$this->passwdContent = file_get_contents($this->config_svn['svn_passwd_file']);
}
}

4
02.php/config/router.php

@ -21,7 +21,9 @@ return [ @@ -21,7 +21,9 @@ return [
"public" => [
'web' => [
'Common/Login',
'Common/GetVeryfyCode'
'Common/GetVerifyCode',
'Safe/GetVerifyOption',
'Svnrep/DownloadRepBackup'
],
'mini' => []
],

2
02.php/config/svn.php

@ -8,7 +8,7 @@ @@ -8,7 +8,7 @@
*/
/**
* 如果要修改安装路径 ,请在安装本程序前修改$home_path的值,安装程序后不支持修改
* 如果要修改安装路径 ,可通过执行 server/install.php 来实现
*/
$home_path = '/home/svnadmin/';

2
02.php/config/version.php

@ -12,5 +12,5 @@ @@ -12,5 +12,5 @@
* 用户请不要自行修改 以免影响后续升级检测
*/
return [
'version' => '2.3'
'version' => '2.3.1'
];

136
02.php/extension/Transfer/Transfer.php

@ -1,136 +0,0 @@ @@ -1,136 +0,0 @@
<?php
/**
* 文件传输,支持断点续传。
* 2g以上超大文件也有效
* @author MoXie
*/
class Transfer
{
/**
* 缓冲单元
*/
const BUFF_SIZE = 5120; // 1024 * 5
/**
* 文件地址
* @var <String>
*/
private $filePath;
/**
* 文件大小
* @var <String> Php超大数字 字符串形式描述
*/
private $fileSize;
/**
* 文件类型
* @var <String>
*/
private $mimeType;
/**
* 请求区域(范围)
* @var <String>
*/
private $range;
/**
*
* @param <String> $filePath 文件路径
* @param <String> $mimeType 文件类型
* @param <String> $range 请求区域(范围)
*/
function __construct($filePath, $mimeType = null, $range = null)
{
$this->filePath = $filePath;
$this->fileSize = sprintf('%u', filesize($filePath));
$this->mimeType = ($mimeType != null) ? $mimeType : "application/octet-stream"; // bin
$this->range = trim($range);
}
/**
* 获取文件区域
* @return <Map> {'start':long,'end':long} or null
*/
private function getRange()
{
/**
* Range: bytes=-128
* Range: bytes=-128
* Range: bytes=28-175,382-399,510-541,644-744,977-980
* Range: bytes=28-175\n380
* type 1
* RANGE: bytes=1000-9999
* RANGE: bytes=2000-9999
* type 2
* RANGE: bytes=1000-1999
* RANGE: bytes=2000-2999
* RANGE: bytes=3000-3999
*/
if (!empty($this->range)) {
$range = preg_replace('/[\s|,].*/', '', $this->range);
$range = explode('-', substr($range, 6));
if (count($range) < 2) {
$range[1] = $this->fileSize; // Range: bytes=-100
}
$range = array_combine(array('start', 'end'), $range);
if (empty($range['start'])) {
$range['start'] = 0;
}
if (!isset($range['end']) || empty($range['end'])) {
$range['end'] = $this->fileSize;
}
return $range;
}
return null;
}
/**
* 向客户端发送文件
*/
public function send()
{
$fileHande = fopen($this->filePath, 'rb');
if ($fileHande) {
// setting
ob_end_clean(); // clean cache
ob_start();
ini_set('output_buffering', 'Off');
ini_set('zlib.output_compression', 'Off');
// init
$lastModified = gmdate('D, d M Y H:i:s', filemtime($this->filePath)) . ' GMT';
$etag = sprintf('w/"%s:%s"', md5($lastModified), $this->fileSize);
$ranges = $this->getRange();
// headers
header(sprintf('Last-Modified: %s', $lastModified));
header(sprintf('ETag: %s', $etag));
header(sprintf('Content-Type: %s', $this->mimeType));
$disposition = 'attachment';
if (strpos($this->mimeType, 'image/') !== FALSE) {
$disposition = 'inline';
}
header(sprintf('Content-Disposition: %s; filename="%s"', $disposition, basename($this->filePath)));
if ($ranges != null) {
header('HTTP/1.1 206 Partial Content');
header('Accept-Ranges: bytes');
header(sprintf('Content-Length: %u', $ranges['end'] - $ranges['start']));
header(sprintf('Content-Range: bytes %s-%s/%s', $ranges['start'], $ranges['end'], $this->fileSize));
//
fseek($fileHande, sprintf('%u', $ranges['start']));
} else {
header("HTTP/1.1 200 OK");
header(sprintf('Content-Length: %s', $this->fileSize));
}
// read file
$lastSize = 0;
while (!feof($fileHande) && !connection_aborted()) {
$lastSize = sprintf("%u", bcsub($this->fileSize, sprintf("%u", ftell($fileHande))));
if (bccomp($lastSize, self::BUFF_SIZE) > 0) {
$lastSize = self::BUFF_SIZE;
}
echo fread($fileHande, $lastSize);
ob_flush();
flush();
}
ob_end_flush();
}
if ($fileHande != null) {
fclose($fileHande);
}
}
}

271
02.php/server/install.php

@ -37,6 +37,7 @@ class Install @@ -37,6 +37,7 @@ class Install
private $config_svn;
private $config_update;
private $config_version;
private $config_bin;
private $scripts = [
[
@ -51,6 +52,10 @@ class Install @@ -51,6 +52,10 @@ class Install
'index' => 3,
'note' => '检测SVNAdmin的新版本'
],
[
'index' => 4,
'note' => '修改当前的数据存储主目录'
]
];
function __construct()
@ -62,6 +67,7 @@ class Install @@ -62,6 +67,7 @@ class Install
$this->config_svn = Config::get('svn');
$this->config_update = Config::get('update');
$this->config_version = Config::get('version');
$this->config_bin = Config::get('bin');
}
/**
@ -182,6 +188,11 @@ class Install @@ -182,6 +188,11 @@ class Install
echo '===============================================' . PHP_EOL;
exit();
}
if ($this->config_version['version'] > $last) {
echo '当前版本高于已发布版本' . PHP_EOL;
echo '===============================================' . PHP_EOL;
exit();
}
}
}
@ -242,6 +253,26 @@ class Install @@ -242,6 +253,26 @@ class Install
}
}
/**
* 检测目标路径是否为空
*
* @return bool
*/
private function IsDirEmpty($path)
{
clearstatcache();
$filename = scandir($path);
foreach ($filename as $key => $value) {
if ($value != '.' && $value != '..') {
return false;
}
}
return true;
}
/**
* 修改已经安装的Subversion配置以适合SVNAdmin的管理
*/
@ -392,11 +423,49 @@ CON; @@ -392,11 +423,49 @@ CON;
//写入authz文件
$con_svn_authz_file = file_get_contents($templete_path . 'svnserve/authz');
file_put_contents($this->config_svn['svn_authz_file'], $con_svn_authz_file);
if (file_exists($this->config_svn['svn_authz_file'])) {
echo PHP_EOL . '===============================================' . PHP_EOL;
echo '要覆盖原有的权限配置文件 authz 吗?[y/n]:';
$continue = strtolower(trim(fgets(STDIN)));
if (!in_array($continue, ['y', 'n'])) {
echo '不正确的选项!' . PHP_EOL;
echo '===============================================' . PHP_EOL;
exit();
}
if ($continue == 'y') {
//备份
copy($this->config_svn['svn_authz_file'], $this->config_svn['home_path'] . time() . 'authz');
//操作
file_put_contents($this->config_svn['svn_authz_file'], $con_svn_authz_file);
}
} else {
file_put_contents($this->config_svn['svn_authz_file'], $con_svn_authz_file);
}
//写入passwd文件
$con_svn_passwd_file = file_get_contents($templete_path . 'svnserve/passwd');
file_put_contents($this->config_svn['svn_passwd_file'], $con_svn_passwd_file);
if (file_exists($this->config_svn['svn_passwd_file'])) {
echo PHP_EOL . '===============================================' . PHP_EOL;
echo '要覆盖原有的权限配置文件 passwd 吗?[y/n]:';
$continue = strtolower(trim(fgets(STDIN)));
if (!in_array($continue, ['y', 'n'])) {
echo '不正确的选项!' . PHP_EOL;
echo '===============================================' . PHP_EOL;
exit();
}
if ($continue == 'y') {
//备份
copy($this->config_svn['svn_passwd_file'], $this->config_svn['home_path'] . time() . 'passwd');
//操作
file_put_contents($this->config_svn['svn_passwd_file'], $con_svn_passwd_file);
}
} else {
file_put_contents($this->config_svn['svn_passwd_file'], $con_svn_passwd_file);
}
//创建svnserve运行日志文件
file_put_contents($this->config_svn['svnserve_log_file'], '');
@ -425,7 +494,26 @@ CON; @@ -425,7 +494,26 @@ CON;
*/
echo '配置并启用SQLite数据库' . PHP_EOL;
copy($templete_path . '/database/sqlite/svnadmin.db', $this->config_svn['home_path'] . 'svnadmin.db');
if (file_exists($this->config_svn['home_path'] . 'svnadmin.db')) {
echo PHP_EOL . '===============================================' . PHP_EOL;
echo '要覆盖原有的SQLite数据库文件 svnadmin.db 吗?[y/n]:';
$continue = strtolower(trim(fgets(STDIN)));
if (!in_array($continue, ['y', 'n'])) {
echo '不正确的选项!' . PHP_EOL;
echo '===============================================' . PHP_EOL;
exit();
}
if ($continue == 'y') {
//备份
copy($this->config_svn['home_path'] . 'svnadmin.db', $this->config_svn['home_path'] . time() . 'svnadmin.db');
//操作
copy($templete_path . '/database/sqlite/svnadmin.db', $this->config_svn['home_path'] . 'svnadmin.db');
}
} else {
copy($templete_path . '/database/sqlite/svnadmin.db', $this->config_svn['home_path'] . 'svnadmin.db');
}
//配置SQLite数据库文件的父目录权限配置为777 解决无法写入且不报错的问题
shell_exec('chmod 777 ' . $this->config_svn['home_path']);
@ -495,6 +583,180 @@ CON; @@ -495,6 +583,180 @@ CON;
echo '===============================================' . PHP_EOL;
}
/**
* 修改当前的数据存储主目录
*/
function MoveHome()
{
//检查是否停止了svnserve
if (shell_exec('ps auxf|grep -v "grep"|grep svnserve') != '') {
echo '请先手动停止正在运行的 svnserve 程序后重试!' . PHP_EOL;
echo '===============================================' . PHP_EOL;
exit();
}
//输入路径
echo '请输入目标目录的绝对路径:';
$newHomePath = trim(fgets(STDIN));
if ($newHomePath == '') {
echo '===============================================' . PHP_EOL;
echo '输入不能为空!' . PHP_EOL;
echo '===============================================' . PHP_EOL;
exit();
}
//检查要修改的目标路径是否存在
clearstatcache();
if (!is_dir($newHomePath)) {
echo '===============================================' . PHP_EOL;
echo '目标目录不存在!' . PHP_EOL;
echo '===============================================' . PHP_EOL;
exit();
}
//路径是否相同
if ($newHomePath == $this->config_svn['home_path']) {
echo '===============================================' . PHP_EOL;
echo '路径无变化!' . PHP_EOL;
echo '===============================================' . PHP_EOL;
exit();
}
//检查目标路径是否为空
if (!$this->IsDirEmpty($newHomePath)) {
echo '===============================================' . PHP_EOL;
echo '目标目录需要为空!' . PHP_EOL;
echo '===============================================' . PHP_EOL;
exit();
}
echo '===============================================' . PHP_EOL;
echo '提醒!该步骤适用于您之前执行过 [1] 或 [2] 步骤进行过初始化配置的情况' . PHP_EOL;
echo '===============================================' . PHP_EOL;
echo '提醒!不建议将数据存储主目录移动到 root 目录下,因为这会导致读取权限出现问题(除非将 root 目录设置 777 ,但是也不是好主意)' . PHP_EOL;
//对输入的路径规范化,如果末尾没有带有 / 则自动补全
if (substr($newHomePath, strlen($newHomePath) - 1) != '/') {
$newHomePath .= '/';
}
//再次确认
echo '===============================================' . PHP_EOL;
echo sprintf('将数据存储主目录从 %s 修改为 %s', $this->config_svn['home_path'], $newHomePath) . PHP_EOL;
echo '===============================================' . PHP_EOL;
echo '确定要继续操作吗[y/n]:';
$continue = strtolower(trim(fgets(STDIN)));
echo '===============================================' . PHP_EOL;
if (!in_array($continue, ['y', 'n'])) {
echo '不正确的选项!' . PHP_EOL;
echo '===============================================' . PHP_EOL;
exit();
}
if ($continue == 'n') {
echo '已取消!' . PHP_EOL;
echo '===============================================' . PHP_EOL;
exit();
}
//旧内容
$old_config_svn = $this->config_svn;
//修改配置文件 svn.php
$con = file_get_contents(BASE_PATH . '/../config/svn.php');
$con = preg_replace("/\\\$home_path[\s]*=[\s]*(['\"])(.*)\\1[;]/", sprintf("\$home_path = '%s';", $newHomePath), $con);
//判断是否匹配成功
file_put_contents(BASE_PATH . '/../config/svn.php', $con);
//新内容
$new_config_svn = Config::get('svn');
//修改svnserve文件中的仓库路径、配置文件路径、日志文件路径
echo '修改svnserve环境变量文件' . PHP_EOL;
$templete_path = BASE_PATH . '/../templete/';
$con_svnserve_env_file = file_get_contents($templete_path . 'svnserve/svnserve');
$con_svnserve_env_file = sprintf($con_svnserve_env_file, $new_config_svn['rep_base_path'], $new_config_svn['svn_conf_file'], $new_config_svn['svnserve_log_file']);
file_put_contents($old_config_svn['svnserve_env_file'], $con_svnserve_env_file);
echo '===============================================' . PHP_EOL;
//开始移动主目录
echo '开始移动主目录' . PHP_EOL;
passthru(sprintf("mv %s* %s", $old_config_svn['home_path'], $new_config_svn['home_path']));
echo '===============================================' . PHP_EOL;
//为新目录授权
echo '为新目录授权' . PHP_EOL;
shell_exec('chmod 777 -R ' . $new_config_svn['home_path']);
echo '===============================================' . PHP_EOL;
echo '清理之前注册的svnserve服务' . PHP_EOL;
passthru('systemctl stop svnserve.service');
passthru('systemctl disable svnserve.service');
passthru('systemctl daemon-reload');
echo '===============================================' . PHP_EOL;
echo '注册新的svnserve服务' . PHP_EOL;
$os = $this->GetOS();
$con_svnserve_service_file = file_get_contents($templete_path . 'svnserve/svnserve.service');
$con_svnserve_service_file = sprintf($con_svnserve_service_file, $new_config_svn['svnserve_env_file'], $this->config_bin['svnserve'], $new_config_svn['svnserve_pid_file']);
if ($os == 'centos 7' || $os == 'centos 8') {
file_put_contents($new_config_svn['svnserve_service_file']['centos'], $con_svnserve_service_file);
} else if ($os == 'ubuntu') {
file_put_contents($new_config_svn['svnserve_service_file']['ubuntu'], $con_svnserve_service_file);
} else if ($os == 'rocky') {
file_put_contents($new_config_svn['svnserve_service_file']['centos'], $con_svnserve_service_file);
} else {
file_put_contents($new_config_svn['svnserve_service_file']['centos'], $con_svnserve_service_file);
echo '===============================================' . PHP_EOL;
echo '警告!当前操作系统版本未测试,使用过程中可能会遇到问题!' . PHP_EOL;
echo '===============================================' . PHP_EOL;
}
echo '===============================================' . PHP_EOL;
//启动
echo '开始启动svnserve服务' . PHP_EOL;
passthru('systemctl daemon-reload');
passthru('systemctl start svnserve');
echo '===============================================' . PHP_EOL;
//开机自启动
echo '将svnserve服务加入到开机自启动' . PHP_EOL;
passthru('systemctl enable svnserve');
echo '===============================================' . PHP_EOL;
//查看状态
echo 'svnserve重新配置成功,打印运行状态:' . PHP_EOL;
passthru('systemctl status svnserve');
echo '===============================================' . PHP_EOL;
//重启守护进程
echo '请运行 svnadmind.php 程序手动重启后台程序!' . PHP_EOL;
passthru('php svnadmind.php stop');
echo '===============================================' . PHP_EOL;
//sqlite数据库
}
/**
* 程序入口
*/
@ -587,6 +849,9 @@ CON; @@ -587,6 +849,9 @@ CON;
} else if ($answer == 3) {
//检测SVNAdmin的新版本
$this->DetectUpdate();
} else if ($answer == 4) {
//修改当前的数据存储主目录
$this->MoveHome();
}
}
}

110
02.php/server/svnadmind.php

@ -3,7 +3,7 @@ @@ -3,7 +3,7 @@
* @Author: witersen
* @Date: 2022-04-24 23:37:06
* @LastEditors: witersen
* @LastEditTime: 2022-05-13 01:24:54
* @LastEditTime: 2022-05-20 16:06:09
* @Description: QQ:1801168257
*/
@ -29,7 +29,6 @@ class Daemon @@ -29,7 +29,6 @@ class Daemon
private $scripts = [
'start',
'stop',
'restart',
'console'
];
private $config_daemon;
@ -44,42 +43,6 @@ class Daemon @@ -44,42 +43,6 @@ class Daemon
$this->config_svn = Config::get('svn');
}
/**
* 将程序变为守护进程
*/
private function InitDeamon()
{
$pid = pcntl_fork();
if ($pid < 0) {
exit('pcntl_fork 错误' . PHP_EOL);
} elseif ($pid > 0) {
exit();
}
$sid = posix_setsid();
if (!$sid) {
exit('posix_setsid 错误' . PHP_EOL);
}
$pid = pcntl_fork();
if ($pid < 0) {
exit('pcntl_fork 错误' . PHP_EOL);
} elseif ($pid > 0) {
exit();
}
chdir('/');
umask(0);
if (defined('STDIN')) {
fclose(STDIN);
}
if (defined('STDOUT')) {
fclose(STDOUT);
}
if (defined('STDERR')) {
fclose(STDERR);
}
file_put_contents($this->pidFile, getmypid());
$this->InitSocket();
}
/**
* 创建TCP套接字并监听指定端口
*/
@ -282,29 +245,9 @@ class Daemon @@ -282,29 +245,9 @@ class Daemon
}
/**
* 以守护进程模式工作
*/
private function StartDaemon()
{
if (file_exists($this->pidFile)) {
$pid = file_get_contents($this->pidFile);
$result = trim(shell_exec("ps -ax | awk '{ print $1 }' | grep -e \"^$pid$\""));
if (strstr($result, $pid)) {
exit('程序正在运行中' . PHP_EOL);
}
}
$this->UpdateSign();
echo '启动成功' . PHP_EOL;
echo '可进行网站访问' . PHP_EOL;
echo '检出SVN仓库前请注意放行协议端口(默认3690)' . PHP_EOL;
echo '已自动更改系统加密密钥,在线用户会退出登录' . PHP_EOL;
$this->InitDeamon();
}
/**
* 关闭守护进程
* 停止
*/
private function StopDaemon()
private function Stop()
{
if (file_exists($this->pidFile)) {
$pid = file_get_contents($this->pidFile);
@ -314,18 +257,36 @@ class Daemon @@ -314,18 +257,36 @@ class Daemon
}
/**
* 重启守护进程
* 启动
*/
private function RestartDeamon()
private function Start()
{
$this->StopDaemon();
$this->StartDaemon();
file_put_contents($this->pidFile, getmypid());
$this->UpdateSign();
echo '启动成功' . PHP_EOL;
echo '可进行网站访问' . PHP_EOL;
echo '检出SVN仓库前请注意放行协议端口(默认3690)' . PHP_EOL;
echo '已自动更改系统加密密钥,在线用户会退出登录' . PHP_EOL;
echo '建议将本程序通过nohup启动或加入系统管理' . PHP_EOL;
chdir('/');
umask(0);
if (defined('STDIN')) {
fclose(STDIN);
}
if (defined('STDOUT')) {
fclose(STDOUT);
}
if (defined('STDERR')) {
fclose(STDERR);
}
$this->InitSocket();
}
/**
* 以控制台模式工作 用于调试
* 调试
*/
private function StartConsole()
private function Console()
{
if (file_exists($this->pidFile)) {
$pid = file_get_contents($this->pidFile);
@ -339,28 +300,25 @@ class Daemon @@ -339,28 +300,25 @@ class Daemon
public function Run($argv)
{
if (isset($argv[1])) {
$this->workMode = $argv[1];
if (!in_array($this->workMode, $this->scripts)) {
exit('用法:php svnadmin.php [start | stop | restart | console]' . PHP_EOL);
exit('用法:php svnadmin.php [' . implode(' | ', $this->scripts) . ']' . PHP_EOL);
}
if ($this->workMode == 'stop') {
$this->StopDaemon();
$this->Stop();
} else {
$this->CheckSysType();
$this->CheckPhpVersion();
$this->CheckDisabledFun();
if ($this->workMode == 'start') {
$this->StartDaemon();
} else if ($this->workMode == 'restart') {
$this->RestartDeamon();
} else if ($this->workMode == 'console') {
$this->StartConsole();
if ($this->workMode == 'console') {
$this->Console();
} else if ($this->workMode == 'start') {
$this->Start();
}
}
} else {
exit('用法:php svnadmin.php [start | stop restart | console]' . PHP_EOL);
exit('用法:php svnadmin.php [' . implode(' | ', $this->scripts) . ']' . PHP_EOL);
}
}
}

11
02.php/templete/svnadmind/svnadmind.service

@ -0,0 +1,11 @@ @@ -0,0 +1,11 @@
[Unit]
Description=Subversion protocol daemon
After=syslog.target network.target
[Service]
Type=simple
ExecStart=/usr/bin/php /var/www/html/server/svnadmind.php start
ExecStop=/usr/bin/php /var/www/html/server/svnadmind.php stop
[Install]
WantedBy=multi-user.target
Loading…
Cancel
Save