11 Commits
Author SHA1 Message Date
Li4n0 acbdbee26a chore(release): 0.2.0 2021-07-22 22:47:22 +08:00
Li4n0 9863821dbc feat: support deleting logs based on filtering results (#35)
* feat: support deleting logs based on filtering results

* fix(record): fix the problem of wrong number of parameters when outputting delete logs
2021-07-22 22:46:11 +08:00
Li4n0 206808e83a chore(release): 0.1.7 2021-07-11 16:24:57 +08:00
Li4n0 a248c6e39e chore: release 0.1.7 2021-07-11 16:24:44 +08:00
Li4n0 5e2020efff ci: remove architectures other than amd64 2021-07-11 16:23:15 +08:00
Li4n0 c0bda707b7 fix(mysql): fix the bug that crashes when mysql port conflicts 2021-07-11 14:49:35 +08:00
Li4n0 ffc4318725 fix(http): fix the bug that http record url search does not work 2021-07-11 13:55:20 +08:00
Li4n0 8023a9b021 chore(release): 0.1.6 2021-06-25 22:38:27 +08:00
Li4n0 56153510e1 fix(cli): fix the bug that the prompt may not be output when generating config file 2021-06-25 22:37:58 +08:00
Li4n0 be7343191d ci(release.yml): use -tags netgo when compiling on linux platform
fix #32
2021-06-25 22:32:41 +08:00
Li4n0 b1773ee5e9 fix(ipinfo): fix a potential panic when downloading ip location database (#33) 2021-06-25 21:15:47 +08:00
30 changed files with 392 additions and 58 deletions
+7 -15
View File
@@ -12,14 +12,11 @@ jobs:
with: with:
go-version: '^1.16.0' go-version: '^1.16.0'
- name: compile - name: compile
env:
CGO_ENABLE: 1
CGO_LDFLAGS: -static
run: | run: |
GOARCH="amd64" go build -v -ldflags="-s -w -extldflags=-static" -trimpath -o "bin/revsuit_linux_amd64" ./cmd/revsuit/revsuit.go GOARCH="amd64" go build -v -ldflags="-s -w -extldflags=-static" -tags netgo -trimpath -o "bin/revsuit_linux_amd64" ./cmd/revsuit/revsuit.go
GOARCH="386" go build -v -ldflags="-s -w -extldflags=-static" -trimpath -o "bin/revsuit_linux_i386" ./cmd/revsuit/revsuit.go # GOARCH="386" go build -v -ldflags="-s -w -extldflags=-static" -tags netgo -trimpath -o "bin/revsuit_linux_i386" ./cmd/revsuit/revsuit.go
GOARCH="arm" go build -v -ldflags="-s -w -extldflags=-static" -trimpath -o "bin/revsuit_linux_arm" ./cmd/revsuit/revsuit.go # GOARCH="arm" go build -v -ldflags="-s -w -extldflags=-static" -tags netgo -trimpath -o "bin/revsuit_linux_arm" ./cmd/revsuit/revsuit.go
GOARCH="arm64" go build -v -ldflags="-s -w -extldflags=-static" -trimpath -o "bin/revsuit_linux_arm64" ./cmd/revsuit/revsuit.go # GOARCH="arm64" go build -v -ldflags="-s -w -extldflags=-static" -tags netgo -trimpath -o "bin/revsuit_linux_arm64" ./cmd/revsuit/revsuit.go
- name: Upload the artifacts - name: Upload the artifacts
uses: li4n0/upload-release-action@v2 uses: li4n0/upload-release-action@v2
with: with:
@@ -37,11 +34,9 @@ jobs:
with: with:
go-version: '^1.16.0' go-version: '^1.16.0'
- name: compile - name: compile
env:
CGO_ENABLE: 1
run: | run: |
GOARCH="amd64" go build -v -ldflags="-s -w" -trimpath -o "bin/revsuit_darwin_amd64" ./cmd/revsuit/revsuit.go GOARCH="amd64" go build -v -ldflags="-s -w" -trimpath -o "bin/revsuit_darwin_amd64" ./cmd/revsuit/revsuit.go
GOARCH="arm64" go build -v -ldflags="-s -w" -trimpath -o "bin/revsuit_darwin_arm64" ./cmd/revsuit/revsuit.go # GOARCH="arm64" go build -v -ldflags="-s -w" -trimpath -o "bin/revsuit_darwin_arm64" ./cmd/revsuit/revsuit.go
- name: Upload the artifacts - name: Upload the artifacts
uses: li4n0/upload-release-action@v2 uses: li4n0/upload-release-action@v2
with: with:
@@ -59,13 +54,10 @@ jobs:
with: with:
go-version: '^1.16.0' go-version: '^1.16.0'
- name: compile - name: compile
env:
CGO_ENABLE: 1
CGO_LDFLAGS: -static
run: | run: |
env GOARCH=amd64 go build -v -ldflags="-s -w -extldflags=-static" -trimpath -o "bin/revsuit_windows_amd64.exe" ./cmd/revsuit/revsuit.go env GOARCH=amd64 go build -v -ldflags="-s -w -extldflags=-static" -trimpath -o "bin/revsuit_windows_amd64.exe" ./cmd/revsuit/revsuit.go
env GOARCH=386 go build -v -ldflags="-s -w -extldflags=-static" -trimpath -o "bin/revsuit_windows_i386.exe" ./cmd/revsuit/revsuit.go # env GOARCH=386 go build -v -ldflags="-s -w -extldflags=-static" -trimpath -o "bin/revsuit_windows_i386.exe" ./cmd/revsuit/revsuit.go
env GOARCH=arm go build -v -ldflags="-s -w -extldflags=-static" -trimpath -o "bin/revsuit_windows_arm.exe" ./cmd/revsuit/revsuit.go # env GOARCH=arm go build -v -ldflags="-s -w -extldflags=-static" -trimpath -o "bin/revsuit_windows_arm.exe" ./cmd/revsuit/revsuit.go
- name: Upload the artifacts - name: Upload the artifacts
uses: li4n0/upload-release-action@v2 uses: li4n0/upload-release-action@v2
with: with:
+23
View File
@@ -2,6 +2,29 @@
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
## [0.2.0](https://github.com/Li4n0/revsuit/compare/v0.1.7...v0.2.0) (2021-07-22)
### Features
* support deleting logs based on filtering results ([#35](https://github.com/Li4n0/revsuit/issues/35)) ([9863821](https://github.com/Li4n0/revsuit/commit/9863821dbc351734569b7ec1eda2b6712bd02bb0))
### [0.1.7](https://github.com/Li4n0/revsuit/compare/v0.1.6...v0.1.7) (2021-07-11)
### Bug Fixes
* **http:** fix the bug that http record url search does not work ([ffc4318](https://github.com/Li4n0/revsuit/commit/ffc4318725017c7eda7ec11ca67d5de16ad1e8a8))
* **mysql:** fix the bug that crashes when mysql port conflicts ([c0bda70](https://github.com/Li4n0/revsuit/commit/c0bda707b750b7858fdd4efc414b726ee37e71da))
### [0.1.6](https://github.com/Li4n0/revsuit/compare/v0.1.5...v0.1.6) (2021-06-25)
### Bug Fixes
* **cli:** fix the bug that the prompt may not be output when generating config file ([5615351](https://github.com/Li4n0/revsuit/commit/56153510e11783c08843cbb8b0f827d5f8567842))
* **ipinfo:** fix a potential panic when downloading ip location database ([#33](https://github.com/Li4n0/revsuit/issues/33)) ([b1773ee](https://github.com/Li4n0/revsuit/commit/b1773ee5e9ebd8c8be72f315981268992c08b3f1))
### [0.1.5](https://github.com/Li4n0/revsuit/compare/v0.1.5-beta...v0.1.5) (2021-06-22 公开该项目以庆祝毕业,愿工作多年后的我,归来时仍是少年) ### [0.1.5](https://github.com/Li4n0/revsuit/compare/v0.1.5-beta...v0.1.5) (2021-06-22 公开该项目以庆祝毕业,愿工作多年后的我,归来时仍是少年)
+2 -1
View File
@@ -26,7 +26,8 @@ Powerful:
### Preparation ### Preparation
Download the latest release firstly. Download the latest release firstly. For the time being, only the binary for amd64 architecture is available for
download, if you need to use it in other architectures, you can compile it yourself.
RevSuit will generate default configuration file on first run. Modify the configuration file according to your needs, RevSuit will generate default configuration file on first run. Modify the configuration file according to your needs,
then re-run. then re-run.
+1 -1
View File
@@ -23,7 +23,7 @@ RevSuit 是一款灵活并且强大的反连平台。目前支持 HTTP、DNS、R
### 安装 ### 安装
在 Releases 里下载最新版本的 RevSuit。 在 Releases 里下载最新版本的 RevSuit。暂时只提供 amd64 架构下的二进制文件下载,如需要在其它架构下使用,可以自行编译。
RevSuit 首次运行时将会生成配置文件模板,你需要编辑其中的内容然后重新运行。 RevSuit 首次运行时将会生成配置文件模板,你需要编辑其中的内容然后重新运行。
+1 -1
View File
@@ -1 +1 @@
.custom-icons-list[data-v-05a908c2] .anticon{margin-right:6px}body[data-v-1bc6d13e],html[data-v-1bc6d13e]{height:100%;margin:0}.fade-transform-enter-active[data-v-1bc6d13e],.fade-transform-leave-active[data-v-1bc6d13e]{transition:all .3s;opacity:0}.fade-transform-enter[data-v-1bc6d13e],.fade-transform-leave[data-v-1bc6d13e]{opacity:0}.fade-transform-enter-to[data-v-1bc6d13e]{opacity:0}.ant-menu-item>span>a[data-v-1bc6d13e]{color:hsla(0,0%,100%,.65)}.ant-menu-item-selected>span>a[data-v-1bc6d13e]{color:#fff}#app[data-v-1bc6d13e]{min-height:100%}#app .trigger[data-v-1bc6d13e]{font-size:18px;line-height:64px;padding:0 24px;cursor:pointer;transition:color .3s}#app .trigger[data-v-1bc6d13e]:hover{color:#1890ff}#app .logo[data-v-1bc6d13e]{height:32px;background:#0a1d2d;margin:16px;text-align:center;font-size:1.2rem;color:#fff;padding-bottom:5px;border-bottom:2px solid #b6befa}.copyright[data-v-1bc6d13e]{color:#888;text-align:right;margin-right:1rem} .custom-icons-list[data-v-05a908c2] .anticon{margin-right:6px}body[data-v-3b44ba10],html[data-v-3b44ba10]{height:100%;margin:0}.fade-transform-enter-active[data-v-3b44ba10],.fade-transform-leave-active[data-v-3b44ba10]{transition:all .3s;opacity:0}.fade-transform-enter[data-v-3b44ba10],.fade-transform-leave[data-v-3b44ba10]{opacity:0}.fade-transform-enter-to[data-v-3b44ba10]{opacity:0}.ant-menu-item>span>a[data-v-3b44ba10]{color:hsla(0,0%,100%,.65)}.ant-menu-item-selected>span>a[data-v-3b44ba10]{color:#fff}#app[data-v-3b44ba10]{min-height:100%}#app .trigger[data-v-3b44ba10]{font-size:18px;line-height:64px;padding:0 24px;cursor:pointer;transition:color .3s}#app .trigger[data-v-3b44ba10]:hover{color:#1890ff}#app .logo[data-v-3b44ba10]{height:32px;background:#0a1d2d;margin:16px;text-align:center;font-size:1.2rem;color:#fff;padding-bottom:5px;border-bottom:2px solid #b6befa}.copyright[data-v-3b44ba10]{color:#888;text-align:right;margin-right:1rem}
+1 -1
View File
File diff suppressed because one or more lines are too long
+1 -1
View File
File diff suppressed because one or more lines are too long
+1 -1
View File
File diff suppressed because one or more lines are too long
+1 -1
View File
File diff suppressed because one or more lines are too long
+1 -1
View File
File diff suppressed because one or more lines are too long
+1 -1
View File
File diff suppressed because one or more lines are too long
+27 -4
View File
@@ -62,7 +62,7 @@
/> />
<div v-if="isLogMode" style="float: right; min-width:60% ;padding: 12px 0;line-height: 24px;"> <div v-if="isLogMode" style="float: right; min-width:60% ;padding: 12px 0;line-height: 24px;">
<a-row :gutter="24" type="flex"> <a-row :gutter="24" type="flex">
<a-col :span="21"> <a-col :span="20">
<a-form-model v-show="showSettings" ref="settings" layout="inline"> <a-form-model v-show="showSettings" ref="settings" layout="inline">
<a-row :gutter="24" type="flex"> <a-row :gutter="24" type="flex">
<a-col :span="9" :offset="2"> <a-col :span="9" :offset="2">
@@ -80,9 +80,23 @@
</a-row> </a-row>
</a-form-model> </a-form-model>
</a-col> </a-col>
<a-col :span="3"> <a-col :span="4">
<a-popconfirm
:title="showLogNum?`This will delete all logs in the current filtered state, a total of ${this.$refs.content.pagination.total}, are you sure?`:'This will delete all logs in the current filtered state, a total of 0, are you sure?'"
ok-text="Yes"
cancel-text="No"
@visibleChange="showLogNum?delayChangeShowLogNum():showLogNum=!showLogNum"
@confirm="deleteLogs"
>
<a-icon slot="icon" type="question-circle-o" style="color: red"/>
<a-icon
:style="'font-size: 18px;padding: 12px 0;'"
type="delete"
@click="()=>{}"
/>
</a-popconfirm>
<a-icon <a-icon
:style="'font-size: 18px;padding: 12px 0;'+(showSettings?'color: #1b90ff;':'')" :style="'font-size: 18px;padding:12px 15px;'+(showSettings?'color: #1b90ff;':'')"
type="setting" type="setting"
@click="showSettings = !showSettings" @click="showSettings = !showSettings"
/> />
@@ -123,6 +137,7 @@ export default {
pageSize: store.pageSize, pageSize: store.pageSize,
collapsed: false, collapsed: false,
showSettings: false, showSettings: false,
showLogNum: false,
openKeys: [], openKeys: [],
version: "", version: "",
}; };
@@ -130,7 +145,7 @@ export default {
computed: { computed: {
isLogMode() { isLogMode() {
return this.$route.path.includes('logs') return this.$route.path.includes('logs')
} },
}, },
methods: { methods: {
timing() { timing() {
@@ -145,6 +160,14 @@ export default {
getVersion().then(res => { getVersion().then(res => {
this.version = res.data.result this.version = res.data.result
}) })
},
deleteLogs() {
this.$refs.content.delete()
},
delayChangeShowLogNum() {
setTimeout(() => {
this.showLogNum = !this.showLogNum
}, 1000)
} }
}, },
mounted() { mounted() {
+41
View File
@@ -9,6 +9,15 @@ export function getHttpRecord(params) {
}) })
} }
export function deleteHttpRecord(params) {
return request({
url: '/record/http',
params: params,
method: 'delete',
})
}
export function getDnsRecord(params) { export function getDnsRecord(params) {
return request({ return request({
url: '/record/dns', url: '/record/dns',
@@ -17,6 +26,14 @@ export function getDnsRecord(params) {
}) })
} }
export function deleteDnsRecord(params) {
return request({
url: '/record/dns',
params: params,
method: 'delete'
})
}
export function getMysqlRecord(params) { export function getMysqlRecord(params) {
return request({ return request({
url: '/record/mysql', url: '/record/mysql',
@@ -25,6 +42,14 @@ export function getMysqlRecord(params) {
}) })
} }
export function deleteMysqlRecord(params) {
return request({
url: '/record/mysql',
params: params,
method: 'delete'
})
}
export function getRmiRecord(params) { export function getRmiRecord(params) {
return request({ return request({
url: '/record/rmi', url: '/record/rmi',
@@ -33,10 +58,26 @@ export function getRmiRecord(params) {
}) })
} }
export function deleteRmiRecord(params) {
return request({
url: '/record/rmi',
params: params,
method: 'delete'
})
}
export function getFtpRecord(params) { export function getFtpRecord(params) {
return request({ return request({
url: '/record/ftp', url: '/record/ftp',
params: params, params: params,
method: 'get' method: 'get'
}) })
}
export function deleteFtpRecord(params) {
return request({
url: '/record/ftp',
params: params,
method: 'delete'
})
} }
+16 -1
View File
@@ -37,7 +37,7 @@
</style> </style>
<script> <script>
import {getDnsRecord} from '@/api/record' import {deleteDnsRecord, getDnsRecord} from '@/api/record'
import {store} from '@/main' import {store} from '@/main'
import FilterDropdown from '@/components/FilterDropdown' import FilterDropdown from '@/components/FilterDropdown'
@@ -145,6 +145,21 @@ export default {
} }
}) })
}, },
delete: function () {
let params = {
...this.filters,
}
this.loading = true;
deleteDnsRecord(params).then(() => {
this.$message.success('Deleted successfully')
this.filters = {}
this.fetch()
}).catch(e => {
if (e.response.status !== 403) {
this.$message.error('Failed to delete: ' + e.response.data.error)
}
})
},
}, },
mounted() { mounted() {
this.fetch(); this.fetch();
+16 -1
View File
@@ -72,7 +72,7 @@
</style> </style>
<script> <script>
import {getFtpRecord} from '@/api/record' import {deleteFtpRecord, getFtpRecord} from '@/api/record'
import {store} from '@/main' import {store} from '@/main'
import FilterDropdown from '@/components/FilterDropdown' import FilterDropdown from '@/components/FilterDropdown'
@@ -234,6 +234,21 @@ export default {
} }
}) })
}, },
delete: function () {
let params = {
...this.filters,
}
this.loading = true;
deleteFtpRecord(params).then(() => {
this.$message.success('Deleted successfully')
this.filters = {}
this.fetch()
}).catch(e => {
if (e.response.status !== 403) {
this.$message.error('Failed to delete: ' + e.response.data.error)
}
})
},
}, },
mounted() { mounted() {
this.fetch(); this.fetch();
+16 -1
View File
@@ -49,7 +49,7 @@
</style> </style>
<script> <script>
import {getHttpRecord} from '@/api/record' import {getHttpRecord, deleteHttpRecord} from '@/api/record'
import {store} from '@/main' import {store} from '@/main'
import FilterDropdown from '@/components/FilterDropdown' import FilterDropdown from '@/components/FilterDropdown'
@@ -179,6 +179,21 @@ export default {
} }
}) })
}, },
delete: function () {
let params = {
...this.filters,
}
this.loading = true;
deleteHttpRecord(params).then(() => {
this.$message.success('Deleted successfully')
this.filters = {}
this.fetch()
}).catch(e => {
if (e.response.status !== 403) {
this.$message.error('Failed to delete: ' + e.response.data.error)
}
})
},
}, },
mounted() { mounted() {
this.fetch(); this.fetch();
+16 -1
View File
@@ -70,7 +70,7 @@
</style> </style>
<script> <script>
import {getMysqlRecord} from '@/api/record' import {deleteMysqlRecord, getMysqlRecord} from '@/api/record'
import {store} from '@/main' import {store} from '@/main'
import FilterDropdown from '@/components/FilterDropdown' import FilterDropdown from '@/components/FilterDropdown'
@@ -231,6 +231,21 @@ export default {
} }
}) })
}, },
delete: function () {
let params = {
...this.filters,
}
this.loading = true;
deleteMysqlRecord(params).then(() => {
this.$message.success('Deleted successfully')
this.filters = {}
this.fetch()
}).catch(e => {
if (e.response.status !== 403) {
this.$message.error('Failed to delete: ' + e.response.data.error)
}
})
},
}, },
mounted() { mounted() {
this.fetch(); this.fetch();
+18 -2
View File
@@ -37,7 +37,7 @@
</style> </style>
<script> <script>
import {getRmiRecord} from '@/api/record' import {deleteRmiRecord, getRmiRecord} from '@/api/record'
import {store} from '@/main' import {store} from '@/main'
import FilterDropdown from '@/components/FilterDropdown' import FilterDropdown from '@/components/FilterDropdown'
@@ -110,7 +110,8 @@ export default {
onShowSizeChange: (current, size) => { onShowSizeChange: (current, size) => {
store.pageSize = size store.pageSize = size
} }
}, filters: {}, },
filters: {},
order: "desc", order: "desc",
loading: false, loading: false,
columns, columns,
@@ -146,6 +147,21 @@ export default {
} }
}) })
}, },
delete: function () {
let params = {
...this.filters,
}
this.loading = true;
deleteRmiRecord(params).then(() => {
this.$message.success('Deleted successfully')
this.filters = {}
this.fetch()
}).catch(e => {
if (e.response.status !== 403) {
this.$message.error('Failed to delete: ' + e.response.data.error)
}
})
},
}, },
mounted() { mounted() {
this.fetch(); this.fetch();
+1
View File
@@ -16,6 +16,7 @@ func Start() {
log.ConsoleConfig{ log.ConsoleConfig{
Level: log.LevelInfo, Level: log.LevelInfo,
}) })
defer log.Stop()
app := &cli.App{ app := &cli.App{
Name: "RevSuit", Name: "RevSuit",
Usage: "An Open-Sourced Reverse Platform Designed for Receive Various Kinds of Connection", Usage: "An Open-Sourced Reverse Platform Designed for Receive Various Kinds of Connection",
+11 -3
View File
@@ -2,11 +2,19 @@ package database
import "gorm.io/gorm" import "gorm.io/gorm"
var DB *gorm.DB var (
DB *gorm.DB
Driver DriverType
)
func InitDB(driver, dsn string) (err error) { type DriverType = string
const Sqlite = "sqlite"
func InitDB(driver DriverType, dsn string) (err error) {
Driver = driver
switch driver { switch driver {
case "sqlite": case Sqlite:
DB, err = NewSqlite3(dsn) DB, err = NewSqlite3(dsn)
} }
return err return err
+14 -3
View File
@@ -20,6 +20,7 @@ const (
) )
func get(url string) (b []byte, err error) { func get(url string) (b []byte, err error) {
var resp *http.Response
client := http.Client{ client := http.Client{
Timeout: 90 * time.Second, Timeout: 90 * time.Second,
Transport: &http.Transport{ Transport: &http.Transport{
@@ -28,11 +29,17 @@ func get(url string) (b []byte, err error) {
request, _ := http.NewRequest(http.MethodGet, url, nil) request, _ := http.NewRequest(http.MethodGet, url, nil)
request.Header.Add("User-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.77 Safari/537.36") request.Header.Add("User-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.77 Safari/537.36")
resp, err := client.Do(request) resp, err = client.Do(request)
if err != nil { if err != nil {
return return
} }
defer resp.Body.Close()
defer func(Body io.ReadCloser) {
err := Body.Close()
if err != nil {
log.Warn("%v", err)
}
}(resp.Body)
return io.ReadAll(resp.Body) return io.ReadAll(resp.Body)
} }
@@ -65,10 +72,14 @@ func extractTarGz(gzipStream io.Reader) error {
if err != nil { if err != nil {
return err return err
} }
defer outFile.Close()
if _, err := io.Copy(outFile, tarReader); err != nil { if _, err := io.Copy(outFile, tarReader); err != nil {
_ = outFile.Close()
return err return err
} }
err = outFile.Close()
if err != nil {
log.Warn("%v", err)
}
} }
} }
return nil return nil
+19 -4
View File
@@ -21,6 +21,7 @@ const (
) )
func get(url string) (b []byte, err error) { func get(url string) (b []byte, err error) {
var resp *http.Response
client := http.Client{ client := http.Client{
Timeout: 90 * time.Second, Timeout: 90 * time.Second,
Transport: &http.Transport{ Transport: &http.Transport{
@@ -29,11 +30,17 @@ func get(url string) (b []byte, err error) {
request, _ := http.NewRequest("GET", url, nil) request, _ := http.NewRequest("GET", url, nil)
request.Header.Add("User-Agent", "Nali/2.1.2 (Nali CLI, https://nali.skk.moe)") request.Header.Add("User-Agent", "Nali/2.1.2 (Nali CLI, https://nali.skk.moe)")
resp, err := client.Do(request) resp, err = client.Do(request)
if err != nil { if err != nil {
return return
} }
defer resp.Body.Close()
defer func(Body io.ReadCloser) {
err := Body.Close()
if err != nil {
log.Warn("%v", err)
}
}(resp.Body)
return io.ReadAll(resp.Body) return io.ReadAll(resp.Body)
} }
@@ -47,17 +54,25 @@ func getKey(b []byte) (key uint32, err error) {
} }
func decrypt(b []byte, key uint32) (_ []byte, err error) { func decrypt(b []byte, key uint32) (_ []byte, err error) {
var rc io.ReadCloser
for i := 0; i < 0x200; i++ { for i := 0; i < 0x200; i++ {
key *= uint32(0x805) key *= uint32(0x805)
key++ key++
key &= uint32(0xff) key &= uint32(0xff)
b[i] = b[i] ^ byte(key) b[i] = b[i] ^ byte(key)
} }
rc, err := zlib.NewReader(bytes.NewBuffer(b)) rc, err = zlib.NewReader(bytes.NewBuffer(b))
if err != nil { if err != nil {
return return
} }
defer rc.Close()
defer func(rc io.ReadCloser) {
err := rc.Close()
if err != nil {
log.Warn("%v", err)
}
}(rc)
return io.ReadAll(rc) return io.ReadAll(rc)
} }
+29 -1
View File
@@ -1,6 +1,7 @@
package dns package dns
import ( import (
"net/http"
"strconv" "strconv"
"time" "time"
@@ -8,6 +9,8 @@ import (
"github.com/li4n0/revsuit/internal/database" "github.com/li4n0/revsuit/internal/database"
"github.com/li4n0/revsuit/internal/notice" "github.com/li4n0/revsuit/internal/notice"
"github.com/li4n0/revsuit/internal/record" "github.com/li4n0/revsuit/internal/record"
"gorm.io/gorm"
log "unknwon.dev/clog/v2"
) )
var _ record.Record = (*Record)(nil) var _ record.Record = (*Record)(nil)
@@ -41,7 +44,7 @@ func newRecord(rule *Rule, flag, domain, remoteIp, ipArea string) (r *Record, er
return r, database.DB.Create(r).Error return r, database.DB.Create(r).Error
} }
func ListRecords(c *gin.Context) { func Records(c *gin.Context) {
var ( var (
dnsRecord Record dnsRecord Record
res []Record res []Record
@@ -80,6 +83,31 @@ func ListRecords(c *gin.Context) {
db.Where("rule_name = ?", dnsRecord.RuleName) db.Where("rule_name = ?", dnsRecord.RuleName)
} }
//Delete records
if c.Request.Method == http.MethodDelete {
if err := db.Session(&gorm.Session{AllowGlobalUpdate: true}).Delete(&res).Error; err != nil {
c.JSON(400, gin.H{
"status": "failed",
"error": err.Error(),
"data": nil,
})
return
}
if database.Driver == database.Sqlite {
db.Exec("VACUUM")
}
c.JSON(200, gin.H{
"status": "succeed",
"error": nil,
})
log.Info("%d dns records deleted by %s", db.RowsAffected, c.Request.RemoteAddr)
return
}
//List records
page, err := strconv.Atoi(c.Query("page")) page, err := strconv.Atoi(c.Query("page"))
if err != nil { if err != nil {
c.JSON(400, gin.H{ c.JSON(400, gin.H{
+28 -1
View File
@@ -1,6 +1,7 @@
package ftp package ftp
import ( import (
"net/http"
"strconv" "strconv"
"time" "time"
@@ -10,6 +11,7 @@ import (
"github.com/li4n0/revsuit/internal/ipinfo" "github.com/li4n0/revsuit/internal/ipinfo"
"github.com/li4n0/revsuit/internal/notice" "github.com/li4n0/revsuit/internal/notice"
"github.com/li4n0/revsuit/internal/record" "github.com/li4n0/revsuit/internal/record"
"gorm.io/gorm"
log "unknwon.dev/clog/v2" log "unknwon.dev/clog/v2"
) )
@@ -53,7 +55,7 @@ func NewRecord(rule *Rule, flag, user, password, method, path, ip, area string,
return r, database.DB.Create(r).Error return r, database.DB.Create(r).Error
} }
func ListRecords(c *gin.Context) { func Records(c *gin.Context) {
var ( var (
ftpRecord Record ftpRecord Record
res []Record res []Record
@@ -105,6 +107,31 @@ func ListRecords(c *gin.Context) {
db.Where("rule_name = ?", ftpRecord.RuleName) db.Where("rule_name = ?", ftpRecord.RuleName)
} }
//Delete records
if c.Request.Method == http.MethodDelete {
if err := db.Session(&gorm.Session{AllowGlobalUpdate: true}).Delete(&res).Error; err != nil {
c.JSON(400, gin.H{
"status": "failed",
"error": err.Error(),
"data": nil,
})
return
}
if database.Driver == database.Sqlite {
db.Exec("VACUUM")
}
c.JSON(200, gin.H{
"status": "succeed",
"error": nil,
})
log.Info("%d ftp records deleted by %s", db.RowsAffected, c.Request.RemoteAddr)
return
}
//List records
page, err := strconv.Atoi(c.Query("page")) page, err := strconv.Atoi(c.Query("page"))
if err != nil { if err != nil {
c.JSON(400, gin.H{ c.JSON(400, gin.H{
+2 -1
View File
@@ -302,10 +302,11 @@ func (s *Server) Run() {
s.listener, err = vmysql.NewListener("tcp", s.Addr, authServer, s, s.VersionString, 0, 0) s.listener, err = vmysql.NewListener("tcp", s.Addr, authServer, s, s.VersionString, 0, 0)
if err != nil { if err != nil {
log.Error("New MySQL Server failed: %s", err) log.Error("New MySQL Server failed: %s", err)
return
} }
go func() { go func() {
s.livingLock.Lock()
if !s.Enable { if !s.Enable {
s.listener.Close() s.listener.Close()
} }
+28 -1
View File
@@ -1,6 +1,7 @@
package mysql package mysql
import ( import (
"net/http"
"strconv" "strconv"
"time" "time"
@@ -9,6 +10,8 @@ import (
"github.com/li4n0/revsuit/internal/file" "github.com/li4n0/revsuit/internal/file"
"github.com/li4n0/revsuit/internal/notice" "github.com/li4n0/revsuit/internal/notice"
"github.com/li4n0/revsuit/internal/record" "github.com/li4n0/revsuit/internal/record"
"gorm.io/gorm"
log "unknwon.dev/clog/v2"
) )
var _ record.Record = (*Record)(nil) var _ record.Record = (*Record)(nil)
@@ -51,7 +54,7 @@ func newRecord(rule *Rule, flag, username, schema, clientName, clientOS, remoteI
return r, database.DB.Create(r).Error return r, database.DB.Create(r).Error
} }
func ListRecords(c *gin.Context) { func Records(c *gin.Context) {
var ( var (
mysqlRecord Record mysqlRecord Record
res []Record res []Record
@@ -103,6 +106,30 @@ func ListRecords(c *gin.Context) {
} }
} }
//Delete records
if c.Request.Method == http.MethodDelete {
if err := db.Session(&gorm.Session{AllowGlobalUpdate: true}).Delete(&res).Error; err != nil {
c.JSON(400, gin.H{
"status": "failed",
"error": err.Error(),
"data": nil,
})
return
}
if database.Driver == database.Sqlite {
db.Exec("VACUUM")
}
c.JSON(200, gin.H{
"status": "succeed",
"error": nil,
})
log.Info("%d mysql records deleted by %s", db.RowsAffected, c.Request.RemoteAddr)
return
}
//List records
page, err := strconv.Atoi(c.Query("page")) page, err := strconv.Atoi(c.Query("page"))
if err != nil { if err != nil {
c.JSON(400, gin.H{ c.JSON(400, gin.H{
+29 -2
View File
@@ -1,6 +1,7 @@
package rhttp package rhttp
import ( import (
"net/http"
"strconv" "strconv"
"time" "time"
@@ -8,6 +9,8 @@ import (
"github.com/li4n0/revsuit/internal/database" "github.com/li4n0/revsuit/internal/database"
"github.com/li4n0/revsuit/internal/notice" "github.com/li4n0/revsuit/internal/notice"
"github.com/li4n0/revsuit/internal/record" "github.com/li4n0/revsuit/internal/record"
"gorm.io/gorm"
log "unknwon.dev/clog/v2"
) )
var _ record.Record = (*Record)(nil) var _ record.Record = (*Record)(nil)
@@ -44,7 +47,7 @@ func NewRecord(rule *Rule, flag, method, url, ip, area, raw string) (r *Record,
return r, database.DB.Create(r).Error return r, database.DB.Create(r).Error
} }
func ListRecords(c *gin.Context) { func Records(c *gin.Context) {
var ( var (
httpRecord Record httpRecord Record
res []Record res []Record
@@ -78,7 +81,7 @@ func ListRecords(c *gin.Context) {
db.Where("method = ?", httpRecord.Method) db.Where("method = ?", httpRecord.Method)
} }
if httpRecord.URI != "" { if httpRecord.URI != "" {
db.Where("path like ?", "%"+httpRecord.URI+"%") db.Where("uri like ?", "%"+httpRecord.URI+"%")
} }
if httpRecord.RemoteIP != "" { if httpRecord.RemoteIP != "" {
db.Where("remote_ip = ?", httpRecord.RemoteIP) db.Where("remote_ip = ?", httpRecord.RemoteIP)
@@ -87,6 +90,30 @@ func ListRecords(c *gin.Context) {
db.Where("rule_name = ?", httpRecord.RuleName) db.Where("rule_name = ?", httpRecord.RuleName)
} }
//Delete records
if c.Request.Method == http.MethodDelete {
if err := db.Session(&gorm.Session{AllowGlobalUpdate: true}).Delete(&res).Error; err != nil {
c.JSON(400, gin.H{
"status": "failed",
"error": err.Error(),
"data": nil,
})
return
}
if database.Driver == database.Sqlite {
db.Exec("VACUUM")
}
c.JSON(200, gin.H{
"status": "succeed",
"error": nil,
})
log.Info("%d http records deleted by %s", db.RowsAffected, c.Request.RemoteAddr)
return
}
//List records
page, err := strconv.Atoi(c.Query("page")) page, err := strconv.Atoi(c.Query("page"))
if err != nil { if err != nil {
c.JSON(400, gin.H{ c.JSON(400, gin.H{
+29 -1
View File
@@ -1,6 +1,7 @@
package rmi package rmi
import ( import (
"net/http"
"strconv" "strconv"
"time" "time"
@@ -8,6 +9,8 @@ import (
"github.com/li4n0/revsuit/internal/database" "github.com/li4n0/revsuit/internal/database"
"github.com/li4n0/revsuit/internal/notice" "github.com/li4n0/revsuit/internal/notice"
"github.com/li4n0/revsuit/internal/record" "github.com/li4n0/revsuit/internal/record"
"gorm.io/gorm"
log "unknwon.dev/clog/v2"
) )
var _ record.Record = (*Record)(nil) var _ record.Record = (*Record)(nil)
@@ -40,7 +43,7 @@ func NewRecord(rule *Rule, flag, path, ip, area string) (r *Record, err error) {
return r, database.DB.Create(r).Error return r, database.DB.Create(r).Error
} }
func ListRecords(c *gin.Context) { func Records(c *gin.Context) {
var ( var (
rmiRecord Record rmiRecord Record
res []Record res []Record
@@ -80,6 +83,31 @@ func ListRecords(c *gin.Context) {
db.Where("rule_name = ?", rmiRecord.RuleName) db.Where("rule_name = ?", rmiRecord.RuleName)
} }
//Delete records
if c.Request.Method == http.MethodDelete {
if err := db.Session(&gorm.Session{AllowGlobalUpdate: true}).Delete(&res).Error; err != nil {
c.JSON(400, gin.H{
"status": "failed",
"error": err.Error(),
"data": nil,
})
return
}
if database.Driver == database.Sqlite {
db.Exec("VACUUM")
}
c.JSON(200, gin.H{
"status": "succeed",
"error": nil,
})
log.Info("%d rmi records deleted by %s", db.RowsAffected, c.Request.RemoteAddr)
return
}
//List records
page, err := strconv.Atoi(c.Query("page")) page, err := strconv.Atoi(c.Query("page"))
if err != nil { if err != nil {
c.JSON(400, gin.H{ c.JSON(400, gin.H{
+10 -5
View File
@@ -77,19 +77,24 @@ func (revsuit *Revsuit) registerHttpRouter() {
recordGroup := revsuit.http.ApiGroup.Group("/record") recordGroup := revsuit.http.ApiGroup.Group("/record")
httpGroup := recordGroup.Group("/http") httpGroup := recordGroup.Group("/http")
httpGroup.GET("", rhttp.ListRecords) httpGroup.GET("", rhttp.Records)
httpGroup.DELETE("", rhttp.Records)
dnsGroup := recordGroup.Group("/dns") dnsGroup := recordGroup.Group("/dns")
dnsGroup.GET("", dns.ListRecords) dnsGroup.GET("", dns.Records)
dnsGroup.DELETE("", dns.Records)
mysqlGroup := recordGroup.Group("/mysql") mysqlGroup := recordGroup.Group("/mysql")
mysqlGroup.GET("", mysql.ListRecords) mysqlGroup.GET("", mysql.Records)
mysqlGroup.DELETE("", mysql.Records)
rmiGroup := recordGroup.Group("/rmi") rmiGroup := recordGroup.Group("/rmi")
rmiGroup.GET("", rmi.ListRecords) rmiGroup.GET("", rmi.Records)
rmiGroup.DELETE("", rmi.Records)
ftpGroup := recordGroup.Group("/ftp") ftpGroup := recordGroup.Group("/ftp")
ftpGroup.GET("", ftp.ListRecords) ftpGroup.GET("", ftp.Records)
ftpGroup.DELETE("", ftp.Records)
// init rule router group // init rule router group
ruleGroup := revsuit.http.ApiGroup.Group("/rule") ruleGroup := revsuit.http.ApiGroup.Group("/rule")
+2 -2
View File
@@ -18,7 +18,7 @@ import (
log "unknwon.dev/clog/v2" log "unknwon.dev/clog/v2"
) )
const VERSION = "0.1.5" const VERSION = "0.2.0"
type Revsuit struct { type Revsuit struct {
config *Config config *Config
@@ -60,7 +60,7 @@ func initDatabase(dsn string) {
Level: log.LevelInfo, Level: log.LevelInfo,
}) })
err := database.InitDB("sqlite", dsn) err := database.InitDB(database.Sqlite, dsn)
if err != nil { if err != nil {
log.Fatal(err.Error()) log.Fatal(err.Error())
} }