mirror of
https://github.com/yhl452493373/frpc-panel.git
synced 2026-04-04 14:27:01 +08:00
remove unused sturct;
add new user popup
This commit is contained in:
@@ -154,3 +154,26 @@ section.common-info .text-row {
|
|||||||
section.common-info .text-row .text-col {
|
section.common-info .text-row .text-col {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#addProxyForm {
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#addProxyForm .layui-tab {
|
||||||
|
margin: 15px 15px 0 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#addProxyForm .layui-tab .layui-tab-content {
|
||||||
|
padding-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#addProxyForm .layui-textarea {
|
||||||
|
min-height: 80px;
|
||||||
|
padding: 9px 10px;
|
||||||
|
resize: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
#addProxyForm .layui-row .layui-form-item {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -57,6 +57,8 @@ var loadProxyInfo = (function ($) {
|
|||||||
text: {none: i18n['EmptyData']},
|
text: {none: i18n['EmptyData']},
|
||||||
cols: [cols],
|
cols: [cols],
|
||||||
page: navigator.language.indexOf("zh") !== -1,
|
page: navigator.language.indexOf("zh") !== -1,
|
||||||
|
toolbar: '#proxyListToolbarTemplate',
|
||||||
|
defaultToolbar: false,
|
||||||
data: dataList,
|
data: dataList,
|
||||||
initSort: {
|
initSort: {
|
||||||
field: 'name',
|
field: 'name',
|
||||||
@@ -75,6 +77,21 @@ var loadProxyInfo = (function ($) {
|
|||||||
* bind event of {{@link layui.form}}
|
* bind event of {{@link layui.form}}
|
||||||
*/
|
*/
|
||||||
function bindFormEvent() {
|
function bindFormEvent() {
|
||||||
|
layui.table.on('toolbar(proxyListTable)', function (obj) {
|
||||||
|
var id = obj.config.id;
|
||||||
|
var checkStatus = layui.table.checkStatus(id);
|
||||||
|
var data = checkStatus.data;
|
||||||
|
|
||||||
|
switch (obj.event) {
|
||||||
|
case 'add':
|
||||||
|
addPopup();
|
||||||
|
break
|
||||||
|
case 'remove':
|
||||||
|
// batchRemovePopup(data);
|
||||||
|
break
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
layui.table.on('tool(proxyListTable)', function (obj) {
|
layui.table.on('tool(proxyListTable)', function (obj) {
|
||||||
var data = obj.data;
|
var data = obj.data;
|
||||||
|
|
||||||
@@ -89,5 +106,115 @@ var loadProxyInfo = (function ($) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* add proxy popup
|
||||||
|
*/
|
||||||
|
function addPopup() {
|
||||||
|
layui.layer.open({
|
||||||
|
type: 1,
|
||||||
|
title: 'NewProxy',
|
||||||
|
area: ['500px'],
|
||||||
|
content: layui.laytpl(document.getElementById('addProxyTemplate').innerHTML).render(),
|
||||||
|
btn: ['Confirm', 'Cancel'],
|
||||||
|
btn1: function (index) {
|
||||||
|
if (layui.form.validate('#addProxyTemplate')) {
|
||||||
|
var formData = layui.form.val('addProxyTemplate');
|
||||||
|
add(formData, index);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
btn2: function (index) {
|
||||||
|
layui.layer.close(index);
|
||||||
|
},
|
||||||
|
success: function (layero, index, that) {
|
||||||
|
layero.find('.layui-layer-content').css('overflow', 'visible');
|
||||||
|
layui.form.render(null, 'addProxyForm');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* add proxy action
|
||||||
|
* @param data {{user:string, token:string, comment:string, enable:boolean, ports:[string|number], domains:[string], subdomains:[string]}} user data
|
||||||
|
* @param index popup index
|
||||||
|
*/
|
||||||
|
function add(data, index) {
|
||||||
|
var loading = layui.layer.load();
|
||||||
|
$.ajax({
|
||||||
|
url: '/add',
|
||||||
|
type: 'post',
|
||||||
|
contentType: 'application/json',
|
||||||
|
data: JSON.stringify(data),
|
||||||
|
success: function (result) {
|
||||||
|
// if (result.success) {
|
||||||
|
// reloadTable();
|
||||||
|
// layui.layer.close(index);
|
||||||
|
// layui.layer.msg(i18n['OperateSuccess'], function (index) {
|
||||||
|
// layui.layer.close(index);
|
||||||
|
// });
|
||||||
|
// } else {
|
||||||
|
// errorMsg(result);
|
||||||
|
// }
|
||||||
|
},
|
||||||
|
complete: function () {
|
||||||
|
layui.layer.close(loading);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* update proxy action
|
||||||
|
* @param before {{user:string, token:string, comment:string, enable:boolean, ports:[string|number], domains:[string], subdomains:[string]}} data before update
|
||||||
|
* @param after {{user:string, token:string, comment:string, enable:boolean, ports:[string|number], domains:[string], subdomains:[string]}} data after update
|
||||||
|
*/
|
||||||
|
function update(before, after) {
|
||||||
|
before.ports.forEach(function (port, index) {
|
||||||
|
if (/^\d+$/.test(String(port))) {
|
||||||
|
before.ports[index] = parseInt(String(port));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
after.ports.forEach(function (port, index) {
|
||||||
|
if (/^\d+$/.test(String(port)) && typeof port === "string") {
|
||||||
|
after.ports[index] = parseInt(String(port));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
var loading = layui.layer.load();
|
||||||
|
$.ajax({
|
||||||
|
url: '/update',
|
||||||
|
type: 'post',
|
||||||
|
contentType: 'application/json',
|
||||||
|
data: JSON.stringify({
|
||||||
|
before: before,
|
||||||
|
after: after,
|
||||||
|
}),
|
||||||
|
success: function (result) {
|
||||||
|
if (result.success) {
|
||||||
|
layui.layer.msg(i18n['OperateSuccess']);
|
||||||
|
} else {
|
||||||
|
errorMsg(result);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
complete: function () {
|
||||||
|
layui.layer.close(loading);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* batch remove proxy popup
|
||||||
|
* @param data {[{user:string, token:string, comment:string, enable:boolean, ports:[string|number], domains:[string], subdomains:[string]}]} user data list
|
||||||
|
*/
|
||||||
|
function batchRemovePopup(data) {
|
||||||
|
if (data.length === 0) {
|
||||||
|
layui.layer.msg(i18n['ShouldCheckUser']);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
layui.layer.confirm(i18n['ConfirmRemoveUser'], {
|
||||||
|
title: i18n['OperationConfirm'],
|
||||||
|
btn: [i18n['Confirm'], i18n['Cancel']]
|
||||||
|
}, function (index) {
|
||||||
|
operate(apiType.Remove, data, index);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
return loadProxyInfo;
|
return loadProxyInfo;
|
||||||
})(layui.$);
|
})(layui.$);
|
||||||
@@ -143,6 +143,89 @@
|
|||||||
</section>
|
</section>
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
<!--用户列表-添加用户表单模板-->
|
||||||
|
<script type="text/html" id="addProxyTemplate">
|
||||||
|
<form class="layui-form" id="addProxyForm" lay-filter="addProxyForm">
|
||||||
|
<div class="layui-tab layui-tab-brief">
|
||||||
|
<ul class="layui-tab-title">
|
||||||
|
<li class="layui-this">Basic</li>
|
||||||
|
<li>Extra</li>
|
||||||
|
</ul>
|
||||||
|
<div class="layui-tab-content">
|
||||||
|
<div class="layui-tab-item layui-show">
|
||||||
|
<div class="layui-form-item">
|
||||||
|
<label class="layui-form-label">ProxyType</label>
|
||||||
|
<div class="layui-input-block">
|
||||||
|
<select name="type" id="type">
|
||||||
|
<option value="http">HTTP</option>
|
||||||
|
<option value="https">HTTPS</option>
|
||||||
|
<option value="tcp">TCP</option>
|
||||||
|
<option value="udp">UDP</option>
|
||||||
|
<option value="stcp">STCP</option>
|
||||||
|
<option value="sudp">SUDP</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="layui-form-item">
|
||||||
|
<label class="layui-form-label">LocalIp</label>
|
||||||
|
<div class="layui-input-block">
|
||||||
|
<input type="text" name="local_ip" placeholder="LocalIp"
|
||||||
|
autocomplete="off" class="layui-input"/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="layui-form-item">
|
||||||
|
<label class="layui-form-label">LocalPort</label>
|
||||||
|
<div class="layui-input-block">
|
||||||
|
<input type="text" name="local_port" placeholder="LocalPort"
|
||||||
|
autocomplete="off" class="layui-input"/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="layui-form-item layui-hide http https">
|
||||||
|
<label class="layui-form-label">CustomizeDomains</label>
|
||||||
|
<div class="layui-input-block">
|
||||||
|
<textarea name="custom_domains" placeholder="CustomDomains" autocomplete="off"
|
||||||
|
class="layui-textarea"></textarea>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="layui-form-item layui-form-text layui-hide http https">
|
||||||
|
<label class="layui-form-label">Subdomain</label>
|
||||||
|
<div class="layui-input-block">
|
||||||
|
<textarea name="subdomain" placeholder="Subdomain" autocomplete="off"
|
||||||
|
class="layui-textarea"></textarea>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="layui-form-item layui-hide tcp udp">
|
||||||
|
<label class="layui-form-label">RemotePort</label>
|
||||||
|
<div class="layui-input-block">
|
||||||
|
<input type="text" name="remote_port" placeholder="RemotePort"
|
||||||
|
autocomplete="off" class="layui-input"/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="layui-row">
|
||||||
|
<div class="layui-col-xs6">
|
||||||
|
<div class="layui-form-item">
|
||||||
|
<label class="layui-form-label">UseEncryption</label>
|
||||||
|
<div class="layui-input-block">
|
||||||
|
<input type="checkbox" name="use_encryption" value="true" title="ON">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="layui-col-xs6">
|
||||||
|
<div class="layui-form-item">
|
||||||
|
<label class="layui-form-label">UseCompression</label>
|
||||||
|
<div class="layui-input-block">
|
||||||
|
<input type="checkbox" name="use_compression" value="true" title="ON">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="layui-tab-item">内容-2</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</script>
|
||||||
|
|
||||||
<!--代理列表-代理表格模板-->
|
<!--代理列表-代理表格模板-->
|
||||||
<script type="text/html" id="proxyListTableTemplate">
|
<script type="text/html" id="proxyListTableTemplate">
|
||||||
<section class="proxy-list">
|
<section class="proxy-list">
|
||||||
@@ -150,6 +233,14 @@
|
|||||||
</section>
|
</section>
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
<!--代理列表-表格工具条按钮模板-->
|
||||||
|
<script type="text/html" id="proxyListToolbarTemplate">
|
||||||
|
<div class="layui-btn-container">
|
||||||
|
<button class="layui-btn layui-btn-sm" lay-event="add">NewProxy</button>
|
||||||
|
<button class="layui-btn layui-btn-sm" lay-event="remove">RemoveProxy</button>
|
||||||
|
</div>
|
||||||
|
</script>
|
||||||
|
|
||||||
<!--代理列表-操作按钮模板-->
|
<!--代理列表-操作按钮模板-->
|
||||||
<script type="text/html" id="proxyListOperationTemplate">
|
<script type="text/html" id="proxyListOperationTemplate">
|
||||||
<div class="layui-clear-space">
|
<div class="layui-clear-space">
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
|
||||||
"frps-panel/pkg/server"
|
"frps-panel/pkg/server"
|
||||||
"frps-panel/pkg/server/controller"
|
"frps-panel/pkg/server/controller"
|
||||||
"github.com/BurntSushi/toml"
|
"github.com/BurntSushi/toml"
|
||||||
@@ -72,21 +71,11 @@ func Execute() {
|
|||||||
|
|
||||||
func parseConfigFile(configFile, tokensFile string) (controller.HandleController, server.TLS, error) {
|
func parseConfigFile(configFile, tokensFile string) (controller.HandleController, server.TLS, error) {
|
||||||
var common controller.Common
|
var common controller.Common
|
||||||
var tokens controller.Tokens
|
|
||||||
_, err := toml.DecodeFile(configFile, &common)
|
_, err := toml.DecodeFile(configFile, &common)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("decode config file %v error: %v", configFile, err)
|
log.Fatalf("decode config file %v error: %v", configFile, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = toml.DecodeFile(tokensFile, &tokens)
|
|
||||||
if err != nil {
|
|
||||||
if errors.Is(err, os.ErrNotExist) {
|
|
||||||
tokens = controller.Tokens{Tokens: make(map[string]controller.TokenInfo)}
|
|
||||||
} else {
|
|
||||||
log.Fatalf("decode token file %v error: %v", tokensFile, err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
common.Common.DashboardTls = strings.HasPrefix("https://", strings.ToLower(common.Common.DashboardAddr))
|
common.Common.DashboardTls = strings.HasPrefix("https://", strings.ToLower(common.Common.DashboardAddr))
|
||||||
|
|
||||||
tls := server.TLS{
|
tls := server.TLS{
|
||||||
@@ -108,7 +97,6 @@ func parseConfigFile(configFile, tokensFile string) (controller.HandleController
|
|||||||
|
|
||||||
return controller.HandleController{
|
return controller.HandleController{
|
||||||
CommonInfo: common.Common,
|
CommonInfo: common.Common,
|
||||||
Tokens: tokens.Tokens,
|
|
||||||
Version: version,
|
Version: version,
|
||||||
ConfigFile: configFile,
|
ConfigFile: configFile,
|
||||||
TokensFile: tokensFile,
|
TokensFile: tokensFile,
|
||||||
|
|||||||
@@ -10,7 +10,6 @@ import (
|
|||||||
"io"
|
"io"
|
||||||
"log"
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
"sort"
|
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
@@ -76,62 +75,25 @@ func (c *HandleController) MakeLangFunc() func(context *gin.Context) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *HandleController) MakeQueryTokensFunc() func(context *gin.Context) {
|
func (c *HandleController) MakeAddProxyFunc() func(context *gin.Context) {
|
||||||
return func(context *gin.Context) {
|
return func(context *gin.Context) {
|
||||||
|
proxyType, exist := context.GetQuery("type")
|
||||||
|
if !exist {
|
||||||
|
|
||||||
search := TokenSearch{}
|
|
||||||
search.Limit = 0
|
|
||||||
|
|
||||||
err := context.BindQuery(&search)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var tokenList []TokenInfo
|
proxy, exist := proxyConfTypeMap[proxyType]
|
||||||
for _, tokenInfo := range c.Tokens {
|
if !exist {
|
||||||
tokenList = append(tokenList, tokenInfo)
|
|
||||||
}
|
|
||||||
sort.Slice(tokenList, func(i, j int) bool {
|
|
||||||
return strings.Compare(tokenList[i].User, tokenList[j].User) < 0
|
|
||||||
})
|
|
||||||
|
|
||||||
var filtered []TokenInfo
|
|
||||||
for _, tokenInfo := range tokenList {
|
|
||||||
if filter(tokenInfo, search.TokenInfo) {
|
|
||||||
filtered = append(filtered, tokenInfo)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if filtered == nil {
|
|
||||||
filtered = []TokenInfo{}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
count := len(filtered)
|
|
||||||
if search.Limit > 0 {
|
|
||||||
start := max((search.Page-1)*search.Limit, 0)
|
|
||||||
end := min(search.Page*search.Limit, len(filtered))
|
|
||||||
filtered = filtered[start:end]
|
|
||||||
}
|
|
||||||
|
|
||||||
context.JSON(http.StatusOK, &TokenResponse{
|
|
||||||
Code: 0,
|
|
||||||
Msg: "query Tokens success",
|
|
||||||
Count: count,
|
|
||||||
Data: filtered,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *HandleController) MakeAddTokenFunc() func(context *gin.Context) {
|
|
||||||
return func(context *gin.Context) {
|
|
||||||
info := TokenInfo{
|
|
||||||
Enable: true,
|
|
||||||
}
|
|
||||||
response := OperationResponse{
|
response := OperationResponse{
|
||||||
Success: true,
|
Success: true,
|
||||||
Code: Success,
|
Code: Success,
|
||||||
Message: "user add success",
|
Message: "user add success",
|
||||||
}
|
}
|
||||||
err := context.BindJSON(&info)
|
|
||||||
|
err := context.BindJSON(&proxy)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
response.Success = false
|
response.Success = false
|
||||||
response.Code = ParamError
|
response.Code = ParamError
|
||||||
@@ -141,21 +103,7 @@ func (c *HandleController) MakeAddTokenFunc() func(context *gin.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
result := c.verifyToken(info, TOKEN_ADD)
|
err = c.reloadFrpc()
|
||||||
|
|
||||||
if !result.Success {
|
|
||||||
context.JSON(http.StatusOK, &result)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
info.Comment = cleanString(info.Comment)
|
|
||||||
info.Ports = cleanPorts(info.Ports)
|
|
||||||
info.Domains = cleanStrings(info.Domains)
|
|
||||||
info.Subdomains = cleanStrings(info.Subdomains)
|
|
||||||
|
|
||||||
c.Tokens[info.User] = info
|
|
||||||
|
|
||||||
err = c.saveToken()
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
response.Success = false
|
response.Success = false
|
||||||
response.Code = SaveError
|
response.Code = SaveError
|
||||||
@@ -169,15 +117,25 @@ func (c *HandleController) MakeAddTokenFunc() func(context *gin.Context) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *HandleController) MakeUpdateTokensFunc() func(context *gin.Context) {
|
func (c *HandleController) MakeUpdateProxyFunc() func(context *gin.Context) {
|
||||||
return func(context *gin.Context) {
|
return func(context *gin.Context) {
|
||||||
|
proxyType, exist := context.GetQuery("type")
|
||||||
|
if !exist {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
proxy, exist := proxyConfTypeMap[proxyType]
|
||||||
|
if !exist {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
response := OperationResponse{
|
response := OperationResponse{
|
||||||
Success: true,
|
Success: true,
|
||||||
Code: Success,
|
Code: Success,
|
||||||
Message: "user update success",
|
Message: "user update success",
|
||||||
}
|
}
|
||||||
update := TokenUpdate{}
|
|
||||||
err := context.BindJSON(&update)
|
err := context.BindJSON(&proxy)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
response.Success = false
|
response.Success = false
|
||||||
response.Code = ParamError
|
response.Code = ParamError
|
||||||
@@ -187,33 +145,7 @@ func (c *HandleController) MakeUpdateTokensFunc() func(context *gin.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
before := update.Before
|
err = c.reloadFrpc()
|
||||||
after := update.After
|
|
||||||
|
|
||||||
if before.User != after.User {
|
|
||||||
response.Success = false
|
|
||||||
response.Code = ParamError
|
|
||||||
response.Message = fmt.Sprintf("update failed, user should be same : before -> %v, after -> %v", before.User, after.User)
|
|
||||||
log.Printf(response.Message)
|
|
||||||
context.JSON(http.StatusOK, &response)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
result := c.verifyToken(after, TOKEN_UPDATE)
|
|
||||||
|
|
||||||
if !result.Success {
|
|
||||||
context.JSON(http.StatusOK, &result)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
after.Comment = cleanString(after.Comment)
|
|
||||||
after.Ports = cleanPorts(after.Ports)
|
|
||||||
after.Domains = cleanStrings(after.Domains)
|
|
||||||
after.Subdomains = cleanStrings(after.Subdomains)
|
|
||||||
|
|
||||||
c.Tokens[after.User] = after
|
|
||||||
|
|
||||||
err = c.saveToken()
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
response.Success = false
|
response.Success = false
|
||||||
response.Code = SaveError
|
response.Code = SaveError
|
||||||
@@ -227,15 +159,25 @@ func (c *HandleController) MakeUpdateTokensFunc() func(context *gin.Context) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *HandleController) MakeRemoveTokensFunc() func(context *gin.Context) {
|
func (c *HandleController) MakeRemoveProxyFunc() func(context *gin.Context) {
|
||||||
return func(context *gin.Context) {
|
return func(context *gin.Context) {
|
||||||
|
proxyType, exist := context.GetQuery("type")
|
||||||
|
if !exist {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
proxy, exist := proxyConfTypeMap[proxyType]
|
||||||
|
if !exist {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
response := OperationResponse{
|
response := OperationResponse{
|
||||||
Success: true,
|
Success: true,
|
||||||
Code: Success,
|
Code: Success,
|
||||||
Message: "user remove success",
|
Message: "proxy remove success",
|
||||||
}
|
}
|
||||||
remove := TokenRemove{}
|
|
||||||
err := context.BindJSON(&remove)
|
err := context.BindJSON(&proxy)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
response.Success = false
|
response.Success = false
|
||||||
response.Code = ParamError
|
response.Code = ParamError
|
||||||
@@ -245,20 +187,7 @@ func (c *HandleController) MakeRemoveTokensFunc() func(context *gin.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, user := range remove.Users {
|
err = c.reloadFrpc()
|
||||||
result := c.verifyToken(user, TOKEN_REMOVE)
|
|
||||||
|
|
||||||
if !result.Success {
|
|
||||||
context.JSON(http.StatusOK, &result)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, user := range remove.Users {
|
|
||||||
delete(c.Tokens, user.User)
|
|
||||||
}
|
|
||||||
|
|
||||||
err = c.saveToken()
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
response.Success = false
|
response.Success = false
|
||||||
response.Code = SaveError
|
response.Code = SaveError
|
||||||
@@ -272,102 +201,6 @@ func (c *HandleController) MakeRemoveTokensFunc() func(context *gin.Context) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *HandleController) MakeDisableTokensFunc() func(context *gin.Context) {
|
|
||||||
return func(context *gin.Context) {
|
|
||||||
response := OperationResponse{
|
|
||||||
Success: true,
|
|
||||||
Code: Success,
|
|
||||||
Message: "remove success",
|
|
||||||
}
|
|
||||||
disable := TokenDisable{}
|
|
||||||
err := context.BindJSON(&disable)
|
|
||||||
if err != nil {
|
|
||||||
response.Success = false
|
|
||||||
response.Code = ParamError
|
|
||||||
response.Message = fmt.Sprintf("disable failed, param error : %v", err)
|
|
||||||
log.Printf(response.Message)
|
|
||||||
context.JSON(http.StatusOK, &response)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, user := range disable.Users {
|
|
||||||
result := c.verifyToken(user, TOKEN_DISABLE)
|
|
||||||
|
|
||||||
if !result.Success {
|
|
||||||
context.JSON(http.StatusOK, &result)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, user := range disable.Users {
|
|
||||||
token := c.Tokens[user.User]
|
|
||||||
token.Enable = false
|
|
||||||
c.Tokens[user.User] = token
|
|
||||||
}
|
|
||||||
|
|
||||||
err = c.saveToken()
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
response.Success = false
|
|
||||||
response.Code = SaveError
|
|
||||||
response.Message = fmt.Sprintf("disable failed, error : %v", err)
|
|
||||||
log.Printf(response.Message)
|
|
||||||
context.JSON(http.StatusOK, &response)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
context.JSON(http.StatusOK, &response)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *HandleController) MakeEnableTokensFunc() func(context *gin.Context) {
|
|
||||||
return func(context *gin.Context) {
|
|
||||||
response := OperationResponse{
|
|
||||||
Success: true,
|
|
||||||
Code: Success,
|
|
||||||
Message: "remove success",
|
|
||||||
}
|
|
||||||
enable := TokenEnable{}
|
|
||||||
err := context.BindJSON(&enable)
|
|
||||||
if err != nil {
|
|
||||||
response.Success = false
|
|
||||||
response.Code = ParamError
|
|
||||||
response.Message = fmt.Sprintf("enable failed, param error : %v", err)
|
|
||||||
log.Printf(response.Message)
|
|
||||||
context.JSON(http.StatusOK, &response)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, user := range enable.Users {
|
|
||||||
result := c.verifyToken(user, TOKEN_ENABLE)
|
|
||||||
|
|
||||||
if !result.Success {
|
|
||||||
context.JSON(http.StatusOK, &result)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, user := range enable.Users {
|
|
||||||
token := c.Tokens[user.User]
|
|
||||||
token.Enable = true
|
|
||||||
c.Tokens[user.User] = token
|
|
||||||
}
|
|
||||||
|
|
||||||
err = c.saveToken()
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
log.Printf("enable failed, error : %v", err)
|
|
||||||
response.Success = false
|
|
||||||
response.Code = SaveError
|
|
||||||
response.Message = "enable failed"
|
|
||||||
context.JSON(http.StatusOK, &response)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
context.JSON(http.StatusOK, &response)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *HandleController) MakeProxyFunc() func(context *gin.Context) {
|
func (c *HandleController) MakeProxyFunc() func(context *gin.Context) {
|
||||||
return func(context *gin.Context) {
|
return func(context *gin.Context) {
|
||||||
var client *http.Client
|
var client *http.Client
|
||||||
|
|||||||
@@ -1,193 +0,0 @@
|
|||||||
package controller
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
plugin "github.com/fatedier/frp/pkg/plugin/server"
|
|
||||||
"log"
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
func (c *HandleController) HandleLogin(content *plugin.LoginContent) plugin.Response {
|
|
||||||
token := content.Metas["token"]
|
|
||||||
user := content.User
|
|
||||||
return c.JudgeToken(user, token)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *HandleController) HandleNewProxy(content *plugin.NewProxyContent) plugin.Response {
|
|
||||||
token := content.User.Metas["token"]
|
|
||||||
user := content.User.User
|
|
||||||
judgeToken := c.JudgeToken(user, token)
|
|
||||||
if judgeToken.Reject {
|
|
||||||
return judgeToken
|
|
||||||
}
|
|
||||||
return c.JudgePort(content)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *HandleController) HandlePing(content *plugin.PingContent) plugin.Response {
|
|
||||||
token := content.User.Metas["token"]
|
|
||||||
user := content.User.User
|
|
||||||
return c.JudgeToken(user, token)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *HandleController) HandleNewWorkConn(content *plugin.NewWorkConnContent) plugin.Response {
|
|
||||||
token := content.User.Metas["token"]
|
|
||||||
user := content.User.User
|
|
||||||
return c.JudgeToken(user, token)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *HandleController) HandleNewUserConn(content *plugin.NewUserConnContent) plugin.Response {
|
|
||||||
token := content.User.Metas["token"]
|
|
||||||
user := content.User.User
|
|
||||||
return c.JudgeToken(user, token)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *HandleController) JudgeToken(user string, token string) plugin.Response {
|
|
||||||
var res plugin.Response
|
|
||||||
if len(c.Tokens) == 0 {
|
|
||||||
res.Unchange = true
|
|
||||||
} else if user == "" || token == "" {
|
|
||||||
res.Reject = true
|
|
||||||
res.RejectReason = "user or meta token can not be empty"
|
|
||||||
} else if info, exist := c.Tokens[user]; exist {
|
|
||||||
if !info.Enable {
|
|
||||||
res.Reject = true
|
|
||||||
res.RejectReason = fmt.Sprintf("user [%s] is disabled", user)
|
|
||||||
} else {
|
|
||||||
if info.Token != token {
|
|
||||||
res.Reject = true
|
|
||||||
res.RejectReason = fmt.Sprintf("invalid meta token for user [%s]", user)
|
|
||||||
} else {
|
|
||||||
res.Unchange = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
res.Reject = true
|
|
||||||
res.RejectReason = fmt.Sprintf("user [%s] not exist", user)
|
|
||||||
}
|
|
||||||
|
|
||||||
return res
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *HandleController) JudgePort(content *plugin.NewProxyContent) plugin.Response {
|
|
||||||
var res plugin.Response
|
|
||||||
var portErr error
|
|
||||||
var reject = false
|
|
||||||
supportProxyTypes := []string{
|
|
||||||
"tcp", "tcpmux", "udp", "http", "https",
|
|
||||||
}
|
|
||||||
proxyType := content.ProxyType
|
|
||||||
if stringContains(proxyType, supportProxyTypes) {
|
|
||||||
log.Printf("proxy type [%v] not support, plugin do nothing", proxyType)
|
|
||||||
res.Unchange = true
|
|
||||||
return res
|
|
||||||
}
|
|
||||||
|
|
||||||
user := content.User.User
|
|
||||||
userPort := content.RemotePort
|
|
||||||
userDomains := content.CustomDomains
|
|
||||||
userSubdomain := content.SubDomain
|
|
||||||
|
|
||||||
portAllowed := true
|
|
||||||
if proxyType == "tcp" || proxyType == "udp" {
|
|
||||||
portAllowed = false
|
|
||||||
if token, exist := c.Tokens[user]; exist {
|
|
||||||
for _, port := range token.Ports {
|
|
||||||
if str, ok := port.(string); ok {
|
|
||||||
if strings.Contains(str, "-") {
|
|
||||||
allowedRanges := strings.Split(str, "-")
|
|
||||||
if len(allowedRanges) != 2 {
|
|
||||||
portErr = fmt.Errorf("user [%v] port range [%v] format error", user, port)
|
|
||||||
break
|
|
||||||
}
|
|
||||||
start, err := strconv.Atoi(trimString(allowedRanges[0]))
|
|
||||||
if err != nil {
|
|
||||||
portErr = fmt.Errorf("user [%v] port rang [%v] start port [%v] is not a number", user, port, allowedRanges[0])
|
|
||||||
break
|
|
||||||
}
|
|
||||||
end, err := strconv.Atoi(trimString(allowedRanges[1]))
|
|
||||||
if err != nil {
|
|
||||||
portErr = fmt.Errorf("user [%v] port rang [%v] end port [%v] is not a number", user, port, allowedRanges[0])
|
|
||||||
break
|
|
||||||
}
|
|
||||||
if max(userPort, start) == userPort && min(userPort, end) == userPort {
|
|
||||||
portAllowed = true
|
|
||||||
break
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
allowed, err := strconv.Atoi(str)
|
|
||||||
if err != nil {
|
|
||||||
portErr = fmt.Errorf("user [%v] allowed port [%v] is not a number", user, port)
|
|
||||||
}
|
|
||||||
if allowed == userPort {
|
|
||||||
portAllowed = true
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
allowed := port
|
|
||||||
if allowed == userPort {
|
|
||||||
portAllowed = true
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
portAllowed = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if !portAllowed {
|
|
||||||
if portErr == nil {
|
|
||||||
portErr = fmt.Errorf("user [%v] port [%v] is not allowed", user, userPort)
|
|
||||||
}
|
|
||||||
reject = true
|
|
||||||
}
|
|
||||||
|
|
||||||
domainAllowed := true
|
|
||||||
if proxyType == "http" || proxyType == "https" || proxyType == "tcpmux" {
|
|
||||||
if portAllowed {
|
|
||||||
if token, exist := c.Tokens[user]; exist {
|
|
||||||
for _, userDomain := range userDomains {
|
|
||||||
if stringContains(userDomain, token.Domains) {
|
|
||||||
domainAllowed = false
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if !domainAllowed {
|
|
||||||
portErr = fmt.Errorf("user [%v] domain [%v] is not allowed", user, strings.Join(userDomains, ","))
|
|
||||||
reject = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
subdomainAllowed := true
|
|
||||||
if proxyType == "http" || proxyType == "https" {
|
|
||||||
subdomainAllowed = false
|
|
||||||
if portAllowed && domainAllowed {
|
|
||||||
if token, exist := c.Tokens[user]; exist {
|
|
||||||
for _, subdomain := range token.Subdomains {
|
|
||||||
if subdomain == userSubdomain {
|
|
||||||
subdomainAllowed = true
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
subdomainAllowed = true
|
|
||||||
}
|
|
||||||
if !subdomainAllowed {
|
|
||||||
portErr = fmt.Errorf("user [%v] subdomain [%v] is not allowed", user, userSubdomain)
|
|
||||||
reject = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if reject {
|
|
||||||
res.Reject = true
|
|
||||||
res.RejectReason = portErr.Error()
|
|
||||||
} else {
|
|
||||||
res.Unchange = true
|
|
||||||
}
|
|
||||||
return res
|
|
||||||
}
|
|
||||||
@@ -8,7 +8,6 @@ import (
|
|||||||
|
|
||||||
type HandleController struct {
|
type HandleController struct {
|
||||||
CommonInfo CommonInfo
|
CommonInfo CommonInfo
|
||||||
Tokens map[string]TokenInfo
|
|
||||||
Version string
|
Version string
|
||||||
ConfigFile string
|
ConfigFile string
|
||||||
TokensFile string
|
TokensFile string
|
||||||
@@ -40,11 +39,8 @@ func (c *HandleController) Register(rootDir string, engine *gin.Engine) {
|
|||||||
group = engine.Group("/")
|
group = engine.Group("/")
|
||||||
}
|
}
|
||||||
group.GET("/", c.MakeIndexFunc())
|
group.GET("/", c.MakeIndexFunc())
|
||||||
group.GET("/tokens", c.MakeQueryTokensFunc())
|
group.POST("/add", c.MakeAddProxyFunc())
|
||||||
group.POST("/add", c.MakeAddTokenFunc())
|
group.POST("/update", c.MakeUpdateProxyFunc())
|
||||||
group.POST("/update", c.MakeUpdateTokensFunc())
|
group.POST("/remove", c.MakeRemoveProxyFunc())
|
||||||
group.POST("/remove", c.MakeRemoveTokensFunc())
|
|
||||||
group.POST("/disable", c.MakeDisableTokensFunc())
|
|
||||||
group.POST("/enable", c.MakeEnableTokensFunc())
|
|
||||||
group.GET("/proxy/*serverApi", c.MakeProxyFunc())
|
group.GET("/proxy/*serverApi", c.MakeProxyFunc())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,189 +1,13 @@
|
|||||||
package controller
|
package controller
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
"github.com/BurntSushi/toml"
|
|
||||||
"log"
|
|
||||||
"os"
|
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
func filter(main TokenInfo, sub TokenInfo) bool {
|
|
||||||
replaceSpaceUser := trimAllSpace.ReplaceAllString(sub.User, "")
|
|
||||||
if len(replaceSpaceUser) != 0 {
|
|
||||||
if !strings.Contains(main.User, replaceSpaceUser) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
replaceSpaceToken := trimAllSpace.ReplaceAllString(sub.Token, "")
|
|
||||||
if len(replaceSpaceToken) != 0 {
|
|
||||||
if !strings.Contains(main.Token, replaceSpaceToken) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
replaceSpaceComment := trimAllSpace.ReplaceAllString(sub.Comment, "")
|
|
||||||
if len(replaceSpaceComment) != 0 {
|
|
||||||
if !strings.Contains(main.Comment, replaceSpaceComment) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
func trimString(str string) string {
|
func trimString(str string) string {
|
||||||
return strings.TrimSpace(str)
|
return strings.TrimSpace(str)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *HandleController) verifyToken(token TokenInfo, operate int) OperationResponse {
|
|
||||||
response := OperationResponse{
|
|
||||||
Success: true,
|
|
||||||
Code: Success,
|
|
||||||
Message: "operate success",
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
|
||||||
validateExist = false
|
|
||||||
validateNotExist = false
|
|
||||||
validateUser = false
|
|
||||||
validateToken = false
|
|
||||||
validateComment = false
|
|
||||||
validatePorts = false
|
|
||||||
validateDomains = false
|
|
||||||
validateSubdomains = false
|
|
||||||
)
|
|
||||||
|
|
||||||
if operate == TOKEN_ADD {
|
|
||||||
validateExist = true
|
|
||||||
validateUser = true
|
|
||||||
validateToken = true
|
|
||||||
validateComment = true
|
|
||||||
validatePorts = true
|
|
||||||
validateDomains = true
|
|
||||||
validateSubdomains = true
|
|
||||||
} else if operate == TOKEN_UPDATE {
|
|
||||||
validateNotExist = true
|
|
||||||
validateUser = true
|
|
||||||
validateToken = true
|
|
||||||
validateComment = true
|
|
||||||
validatePorts = true
|
|
||||||
validateDomains = true
|
|
||||||
validateSubdomains = true
|
|
||||||
} else if operate == TOKEN_ENABLE || operate == TOKEN_DISABLE || operate == TOKEN_REMOVE {
|
|
||||||
validateNotExist = true
|
|
||||||
}
|
|
||||||
|
|
||||||
if validateUser && !userFormat.MatchString(token.User) {
|
|
||||||
response.Success = false
|
|
||||||
response.Code = UserFormatError
|
|
||||||
response.Message = fmt.Sprintf("operate failed, user [%s] format error", token.User)
|
|
||||||
log.Printf(response.Message)
|
|
||||||
return response
|
|
||||||
}
|
|
||||||
|
|
||||||
if validateExist {
|
|
||||||
if _, exist := c.Tokens[token.User]; exist {
|
|
||||||
response.Success = false
|
|
||||||
response.Code = UserExist
|
|
||||||
response.Message = fmt.Sprintf("operate failed, user [%s] exist ", token.User)
|
|
||||||
log.Printf(response.Message)
|
|
||||||
return response
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if validateNotExist {
|
|
||||||
if _, exist := c.Tokens[token.User]; !exist {
|
|
||||||
response.Success = false
|
|
||||||
response.Code = UserNotExist
|
|
||||||
response.Message = fmt.Sprintf("operate failed, user [%s] not exist ", token.User)
|
|
||||||
log.Printf(response.Message)
|
|
||||||
return response
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if validateToken && !tokenFormat.MatchString(token.Token) {
|
|
||||||
response.Success = false
|
|
||||||
response.Code = TokenFormatError
|
|
||||||
response.Message = fmt.Sprintf("operate failed, token [%s] format error", token.Token)
|
|
||||||
log.Printf(response.Message)
|
|
||||||
return response
|
|
||||||
}
|
|
||||||
|
|
||||||
trimmedComment := trimString(token.Comment)
|
|
||||||
if validateComment && trimmedComment != "" && commentFormat.MatchString(trimmedComment) {
|
|
||||||
response.Success = false
|
|
||||||
response.Code = CommentFormatError
|
|
||||||
response.Message = fmt.Sprintf("operate failed, comment [%s] format error", token.Comment)
|
|
||||||
log.Printf(response.Message)
|
|
||||||
return response
|
|
||||||
}
|
|
||||||
|
|
||||||
if validatePorts {
|
|
||||||
for _, port := range token.Ports {
|
|
||||||
if str, ok := port.(string); ok {
|
|
||||||
trimmedPort := trimString(str)
|
|
||||||
if trimmedPort != "" && !portsFormatSingle.MatchString(trimmedPort) && !portsFormatRange.MatchString(trimmedPort) {
|
|
||||||
response.Success = false
|
|
||||||
response.Code = PortsFormatError
|
|
||||||
response.Message = fmt.Sprintf("operate failed, ports [%v] format error", token.Ports)
|
|
||||||
log.Printf(response.Message)
|
|
||||||
return response
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if validateDomains {
|
|
||||||
for _, domain := range token.Domains {
|
|
||||||
trimmedDomain := trimString(domain)
|
|
||||||
if trimmedDomain != "" && !domainFormat.MatchString(trimmedDomain) {
|
|
||||||
response.Success = false
|
|
||||||
response.Code = DomainsFormatError
|
|
||||||
response.Message = fmt.Sprintf("operate failed, domains [%v] format error", token.Domains)
|
|
||||||
log.Printf(response.Message)
|
|
||||||
return response
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if validateSubdomains {
|
|
||||||
for _, subdomain := range token.Subdomains {
|
|
||||||
trimmedSubdomain := trimString(subdomain)
|
|
||||||
if trimmedSubdomain != "" && !subdomainFormat.MatchString(trimmedSubdomain) {
|
|
||||||
response.Success = false
|
|
||||||
response.Code = SubdomainsFormatError
|
|
||||||
response.Message = fmt.Sprintf("operate failed, subdomains [%v] format error", token.Subdomains)
|
|
||||||
log.Printf(response.Message)
|
|
||||||
return response
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return response
|
|
||||||
}
|
|
||||||
|
|
||||||
func cleanPorts(ports []any) []any {
|
|
||||||
cleanedPorts := make([]any, len(ports))
|
|
||||||
for i, port := range ports {
|
|
||||||
if str, ok := port.(string); ok {
|
|
||||||
cleanedPorts[i] = cleanString(str)
|
|
||||||
} else {
|
|
||||||
//float64, for JSON numbers
|
|
||||||
cleanedPorts[i] = int(port.(float64))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return cleanedPorts
|
|
||||||
}
|
|
||||||
|
|
||||||
func cleanStrings(originalStrings []string) []string {
|
|
||||||
cleanedStrings := make([]string, len(originalStrings))
|
|
||||||
for i, str := range originalStrings {
|
|
||||||
cleanedStrings[i] = cleanString(str)
|
|
||||||
}
|
|
||||||
return cleanedStrings
|
|
||||||
}
|
|
||||||
|
|
||||||
func cleanString(originalString string) string {
|
func cleanString(originalString string) string {
|
||||||
return trimString(originalString)
|
return trimString(originalString)
|
||||||
}
|
}
|
||||||
@@ -197,26 +21,6 @@ func stringContains(element string, data []string) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func tokensList(tokens map[string]TokenInfo) Tokens {
|
func (c *HandleController) reloadFrpc() error {
|
||||||
return Tokens{
|
return nil
|
||||||
tokens,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *HandleController) saveToken() error {
|
|
||||||
tokenFile, err := os.Create(c.TokensFile)
|
|
||||||
if err != nil {
|
|
||||||
log.Printf("error to crate file %v: %v", c.TokensFile, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
encoder := toml.NewEncoder(tokenFile)
|
|
||||||
encoder.Indent = " "
|
|
||||||
if err = encoder.Encode(tokensList(c.Tokens)); err != nil {
|
|
||||||
log.Printf("error to encode tokens: %v", err)
|
|
||||||
}
|
|
||||||
if err = tokenFile.Close(); err != nil {
|
|
||||||
log.Printf("error to close file %v: %v", c.TokensFile, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,30 +1,22 @@
|
|||||||
package controller
|
package controller
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"regexp"
|
"github.com/fatedier/frp/pkg/config"
|
||||||
|
"github.com/fatedier/frp/pkg/consts"
|
||||||
|
"reflect"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
Success int = iota
|
Success int = iota
|
||||||
ParamError
|
ParamError
|
||||||
UserExist
|
|
||||||
UserNotExist
|
|
||||||
SaveError
|
SaveError
|
||||||
UserFormatError
|
|
||||||
TokenFormatError
|
|
||||||
CommentFormatError
|
|
||||||
PortsFormatError
|
|
||||||
DomainsFormatError
|
|
||||||
SubdomainsFormatError
|
|
||||||
FrpServerError
|
FrpServerError
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
TOKEN_ADD int = iota
|
ProxyAdd int = iota
|
||||||
TOKEN_UPDATE
|
ProxyUpdate
|
||||||
TOKEN_REMOVE
|
ProxyRemove
|
||||||
TOKEN_ENABLE
|
|
||||||
TOKEN_DISABLE
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@@ -37,18 +29,19 @@ const (
|
|||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
userFormat = regexp.MustCompile("^\\w+$")
|
proxyConfTypeMap map[string]reflect.Type
|
||||||
tokenFormat = regexp.MustCompile("^[\\w!@#$%^&*()]+$")
|
|
||||||
commentFormat = regexp.MustCompile("[\\n\\t\\r]")
|
|
||||||
portsFormatSingle = regexp.MustCompile("^\\s*\\d{1,5}\\s*$")
|
|
||||||
portsFormatRange = regexp.MustCompile("^\\s*\\d{1,5}\\s*-\\s*\\d{1,5}\\s*$")
|
|
||||||
domainFormat = regexp.MustCompile("^([a-zA-Z0-9]+(-[a-zA-Z0-9]+)*\\.)+[a-zA-Z]{2,}$")
|
|
||||||
subdomainFormat = regexp.MustCompile("^[a-zA-z0-9-]{1,20}$")
|
|
||||||
trimAllSpace = regexp.MustCompile("[\\n\\t\\r\\s]")
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type Response struct {
|
func init() {
|
||||||
Msg string `json:"msg"`
|
proxyConfTypeMap = make(map[string]reflect.Type)
|
||||||
|
proxyConfTypeMap[consts.TCPProxy] = reflect.TypeOf(config.TCPProxyConf{})
|
||||||
|
proxyConfTypeMap[consts.TCPMuxProxy] = reflect.TypeOf(config.TCPMuxProxyConf{})
|
||||||
|
proxyConfTypeMap[consts.UDPProxy] = reflect.TypeOf(config.UDPProxyConf{})
|
||||||
|
proxyConfTypeMap[consts.HTTPProxy] = reflect.TypeOf(config.HTTPProxyConf{})
|
||||||
|
proxyConfTypeMap[consts.HTTPSProxy] = reflect.TypeOf(config.HTTPSProxyConf{})
|
||||||
|
proxyConfTypeMap[consts.STCPProxy] = reflect.TypeOf(config.STCPProxyConf{})
|
||||||
|
proxyConfTypeMap[consts.XTCPProxy] = reflect.TypeOf(config.XTCPProxyConf{})
|
||||||
|
proxyConfTypeMap[consts.SUDPProxy] = reflect.TypeOf(config.SUDPProxyConf{})
|
||||||
}
|
}
|
||||||
|
|
||||||
type HTTPError struct {
|
type HTTPError struct {
|
||||||
@@ -76,27 +69,6 @@ type CommonInfo struct {
|
|||||||
DashboardTls bool
|
DashboardTls bool
|
||||||
}
|
}
|
||||||
|
|
||||||
type Tokens struct {
|
|
||||||
Tokens map[string]TokenInfo `toml:"tokens"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type TokenInfo struct {
|
|
||||||
User string `toml:"user" json:"user" form:"user"`
|
|
||||||
Token string `toml:"token" json:"token" form:"token"`
|
|
||||||
Comment string `toml:"comment" json:"comment" form:"comment"`
|
|
||||||
Ports []any `toml:"ports" json:"ports" from:"ports"`
|
|
||||||
Domains []string `toml:"domains" json:"domains" from:"domains"`
|
|
||||||
Subdomains []string `toml:"subdomains" json:"subdomains" from:"subdomains"`
|
|
||||||
Enable bool `toml:"enable" json:"enable" form:"enable"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type TokenResponse struct {
|
|
||||||
Code int `json:"code"`
|
|
||||||
Msg string `json:"msg"`
|
|
||||||
Count int `json:"count"`
|
|
||||||
Data []TokenInfo `json:"data"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type OperationResponse struct {
|
type OperationResponse struct {
|
||||||
Success bool `json:"success"`
|
Success bool `json:"success"`
|
||||||
Code int `json:"code"`
|
Code int `json:"code"`
|
||||||
@@ -108,29 +80,6 @@ type ProxyResponse struct {
|
|||||||
Data any `json:"data"`
|
Data any `json:"data"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type TokenSearch struct {
|
|
||||||
TokenInfo
|
|
||||||
Page int `form:"page"`
|
|
||||||
Limit int `form:"limit"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type TokenUpdate struct {
|
|
||||||
Before TokenInfo `json:"before"`
|
|
||||||
After TokenInfo `json:"after"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type TokenRemove struct {
|
|
||||||
Users []TokenInfo `json:"users"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type TokenDisable struct {
|
|
||||||
TokenRemove
|
|
||||||
}
|
|
||||||
|
|
||||||
type TokenEnable struct {
|
|
||||||
TokenDisable
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *HTTPError) Error() string {
|
func (e *HTTPError) Error() string {
|
||||||
return e.Err.Error()
|
return e.Err.Error()
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user