Create & Init Project...
This commit is contained in:
51
app/admin/ep/merlin/http/BUILD
Normal file
51
app/admin/ep/merlin/http/BUILD
Normal file
@ -0,0 +1,51 @@
|
||||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
load(
|
||||
"@io_bazel_rules_go//go:def.bzl",
|
||||
"go_library",
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = [
|
||||
"audit.go",
|
||||
"bilihub.go",
|
||||
"cluster.go",
|
||||
"dashboard.go",
|
||||
"devicefarm.go",
|
||||
"http.go",
|
||||
"image.go",
|
||||
"machine.go",
|
||||
"machineV2.go",
|
||||
"node.go",
|
||||
"tree.go",
|
||||
"user.go",
|
||||
],
|
||||
importpath = "go-common/app/admin/ep/merlin/http",
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
"//app/admin/ep/merlin/conf:go_default_library",
|
||||
"//app/admin/ep/merlin/model:go_default_library",
|
||||
"//app/admin/ep/merlin/service:go_default_library",
|
||||
"//library/ecode:go_default_library",
|
||||
"//library/log:go_default_library",
|
||||
"//library/net/http/blademaster:go_default_library",
|
||||
"//library/net/http/blademaster/binding:go_default_library",
|
||||
"//library/net/http/blademaster/middleware/permit:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "package-srcs",
|
||||
srcs = glob(["**"]),
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "all-srcs",
|
||||
srcs = [":package-srcs"],
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
141
app/admin/ep/merlin/http/audit.go
Normal file
141
app/admin/ep/merlin/http/audit.go
Normal file
@ -0,0 +1,141 @@
|
||||
package http
|
||||
|
||||
import (
|
||||
"go-common/app/admin/ep/merlin/model"
|
||||
bm "go-common/library/net/http/blademaster"
|
||||
"go-common/library/net/http/blademaster/binding"
|
||||
)
|
||||
|
||||
func delayMachineEndTime(c *bm.Context) {
|
||||
var (
|
||||
username string
|
||||
v = new(struct {
|
||||
MachineID int64 `form:"machine_id"`
|
||||
})
|
||||
err error
|
||||
)
|
||||
|
||||
if username, err = getUsername(c); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if err = c.Bind(v); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(svc.DelayMachineEndTime(c, v.MachineID, username))
|
||||
}
|
||||
|
||||
func applyMachineEndTime(c *bm.Context) {
|
||||
var (
|
||||
applyEndTimeRequest = &model.ApplyEndTimeRequest{}
|
||||
err error
|
||||
username string
|
||||
)
|
||||
if username, err = getUsername(c); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if err = c.BindWith(applyEndTimeRequest, binding.JSON); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(svc.ApplyDelayMachineEndTime(c, username, applyEndTimeRequest))
|
||||
}
|
||||
|
||||
func cancelMachineEndTime(c *bm.Context) {
|
||||
var (
|
||||
username string
|
||||
v = new(struct {
|
||||
AuditID int64 `form:"audit_id"`
|
||||
})
|
||||
err error
|
||||
)
|
||||
|
||||
if username, err = getUsername(c); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if err = c.Bind(v); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(svc.CancelMachineEndTime(c, v.AuditID, username))
|
||||
}
|
||||
|
||||
func auditMachineEndTime(c *bm.Context) {
|
||||
var (
|
||||
username string
|
||||
auditEndTimeRequest = &model.AuditEndTimeRequest{}
|
||||
err error
|
||||
)
|
||||
|
||||
if username, err = getUsername(c); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if err = c.BindWith(auditEndTimeRequest, binding.JSON); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(svc.AuditMachineEndTime(c, auditEndTimeRequest.AuditID, username, auditEndTimeRequest.AuditResult, auditEndTimeRequest.Comment))
|
||||
}
|
||||
|
||||
func queryApplicationRecordsByApplicant(c *bm.Context) {
|
||||
var (
|
||||
v = &model.Pagination{}
|
||||
err error
|
||||
username string
|
||||
)
|
||||
|
||||
if username, err = getUsername(c); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if err = c.Bind(v); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if err = v.Verify(); err != nil {
|
||||
c.JSON(nil, err)
|
||||
return
|
||||
}
|
||||
c.JSON(svc.GetApplicationRecordsByApplicant(c, username, v.PageNum, v.PageSize))
|
||||
}
|
||||
|
||||
func queryApplicationRecordsByAuditor(c *bm.Context) {
|
||||
var (
|
||||
v = &model.Pagination{}
|
||||
err error
|
||||
username string
|
||||
)
|
||||
|
||||
if username, err = getUsername(c); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if err = c.Bind(v); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if err = v.Verify(); err != nil {
|
||||
c.JSON(nil, err)
|
||||
return
|
||||
}
|
||||
c.JSON(svc.GetApplicationRecordsByAuditor(c, username, v.PageNum, v.PageSize))
|
||||
}
|
||||
|
||||
func queryApplicationRecordsByMachineID(c *bm.Context) {
|
||||
v := new(struct {
|
||||
model.Pagination
|
||||
MachineID int64 `form:"machine_id"`
|
||||
})
|
||||
if err := c.Bind(v); err != nil {
|
||||
return
|
||||
}
|
||||
if err := v.Verify(); err != nil {
|
||||
c.JSON(nil, err)
|
||||
return
|
||||
}
|
||||
c.JSON(svc.GetApplicationRecordsByMachineID(c, v.MachineID, v.PageNum, v.PageSize))
|
||||
}
|
337
app/admin/ep/merlin/http/bilihub.go
Normal file
337
app/admin/ep/merlin/http/bilihub.go
Normal file
@ -0,0 +1,337 @@
|
||||
package http
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"go-common/app/admin/ep/merlin/model"
|
||||
bm "go-common/library/net/http/blademaster"
|
||||
"go-common/library/net/http/blademaster/binding"
|
||||
)
|
||||
|
||||
func projects(c *bm.Context) {
|
||||
var (
|
||||
username string
|
||||
err error
|
||||
)
|
||||
if username, err = getUsername(c); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(svc.Projects(c, username))
|
||||
}
|
||||
|
||||
func accessPullProjects(c *bm.Context) {
|
||||
var (
|
||||
username string
|
||||
err error
|
||||
)
|
||||
if username, err = getUsername(c); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(svc.AccessPullProjects(c, username))
|
||||
}
|
||||
|
||||
func authHub(c *bm.Context) {
|
||||
var (
|
||||
err error
|
||||
session *http.Cookie
|
||||
)
|
||||
if session, err = c.Request.Cookie(_sessIDKey); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(nil, svc.AuthHub(c, session.Value))
|
||||
}
|
||||
|
||||
func accessAuthHub(c *bm.Context) {
|
||||
var (
|
||||
username string
|
||||
err error
|
||||
)
|
||||
if username, err = getUsername(c); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(svc.AccessAuthHub(c, username))
|
||||
}
|
||||
|
||||
func repos(c *bm.Context) {
|
||||
v := new(struct {
|
||||
model.Pagination
|
||||
ProjectID int `form:"project_id"`
|
||||
KeyWord string `form:"key_word"`
|
||||
})
|
||||
|
||||
if err := c.Bind(v); err != nil {
|
||||
return
|
||||
}
|
||||
c.JSON(svc.ProjectRepositories(c, v.ProjectID, v.PageNum, v.PageSize, v.KeyWord))
|
||||
}
|
||||
|
||||
func tags(c *bm.Context) {
|
||||
v := new(struct {
|
||||
RepoName string `form:"repository_name"`
|
||||
})
|
||||
if err := c.Bind(v); err != nil {
|
||||
return
|
||||
}
|
||||
c.JSON(svc.RepositoryTags(c, v.RepoName))
|
||||
}
|
||||
|
||||
func deleteRepoTag(c *bm.Context) {
|
||||
var (
|
||||
v = new(struct {
|
||||
RepoName string `form:"repository_name"`
|
||||
TagName string `form:"tag_name"`
|
||||
})
|
||||
username string
|
||||
err error
|
||||
)
|
||||
|
||||
if username, err = getUsername(c); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if err = c.Bind(v); err != nil {
|
||||
return
|
||||
}
|
||||
c.JSON(svc.DeleteRepositoryTag(c, username, v.RepoName, v.TagName))
|
||||
}
|
||||
|
||||
func deleteRepo(c *bm.Context) {
|
||||
var (
|
||||
v = new(struct {
|
||||
RepoName string `form:"repository_name"`
|
||||
})
|
||||
username string
|
||||
err error
|
||||
)
|
||||
|
||||
if username, err = getUsername(c); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if err = c.Bind(v); err != nil {
|
||||
return
|
||||
}
|
||||
c.JSON(svc.DeleteRepository(c, username, v.RepoName))
|
||||
}
|
||||
|
||||
func allImage(c *bm.Context) {
|
||||
c.JSON(svc.GetAllImagesInDocker())
|
||||
}
|
||||
|
||||
func addTag(c *bm.Context) {
|
||||
var (
|
||||
v = new(struct {
|
||||
RepoName string `json:"repository_name"`
|
||||
TagName string `json:"tag_name"`
|
||||
NewRepoName string `json:"new_repository"`
|
||||
NewTagName string `json:"new_tag"`
|
||||
})
|
||||
username string
|
||||
err error
|
||||
)
|
||||
|
||||
if username, err = getUsername(c); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if err = c.BindWith(v, binding.JSON); err != nil {
|
||||
return
|
||||
}
|
||||
c.JSON(svc.AddRepositoryTag(c, username, v.RepoName, v.TagName, v.NewRepoName, v.NewTagName))
|
||||
}
|
||||
|
||||
func push(c *bm.Context) {
|
||||
var (
|
||||
v = new(struct {
|
||||
RepoName string `json:"repository_name"`
|
||||
TagName string `json:"tag_name"`
|
||||
})
|
||||
username string
|
||||
err error
|
||||
)
|
||||
|
||||
if username, err = getUsername(c); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if err = c.BindWith(v, binding.JSON); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(svc.Push(c, username, v.RepoName, v.TagName, 0))
|
||||
}
|
||||
|
||||
func reTag(c *bm.Context) {
|
||||
var (
|
||||
v = new(struct {
|
||||
RepoName string `json:"repository_name"`
|
||||
TagName string `json:"tag_name"`
|
||||
NewRepoName string `json:"new_repository"`
|
||||
NewTagName string `json:"new_tag"`
|
||||
})
|
||||
username string
|
||||
err error
|
||||
)
|
||||
|
||||
if username, err = getUsername(c); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if err = c.BindWith(v, binding.JSON); err != nil {
|
||||
return
|
||||
}
|
||||
c.JSON(svc.ReTag(c, username, v.RepoName, v.TagName, v.NewRepoName, v.NewTagName, 0))
|
||||
}
|
||||
|
||||
func pull(c *bm.Context) {
|
||||
var (
|
||||
v = new(struct {
|
||||
RepoName string `json:"repository_name"`
|
||||
TagName string `json:"tag_name"`
|
||||
})
|
||||
username string
|
||||
err error
|
||||
)
|
||||
|
||||
if username, err = getUsername(c); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if err = c.BindWith(v, binding.JSON); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(svc.Pull(c, username, v.RepoName, v.TagName, 0))
|
||||
}
|
||||
|
||||
func snapshot(c *bm.Context) {
|
||||
var (
|
||||
v = new(struct {
|
||||
MachineID int64 `form:"machine_id"`
|
||||
})
|
||||
username string
|
||||
err error
|
||||
)
|
||||
|
||||
if username, err = getUsername(c); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if err = c.Bind(v); err != nil {
|
||||
return
|
||||
}
|
||||
c.JSON(svc.CreateSnapShot(c, username, v.MachineID))
|
||||
}
|
||||
|
||||
func querySnapshot(c *bm.Context) {
|
||||
var (
|
||||
v = new(struct {
|
||||
MachineID int64 `form:"machine_id"`
|
||||
})
|
||||
err error
|
||||
)
|
||||
|
||||
if err = c.Bind(v); err != nil {
|
||||
return
|
||||
}
|
||||
c.JSON(svc.QuerySnapShot(c, v.MachineID))
|
||||
}
|
||||
|
||||
func callbackSnapshot(c *bm.Context) {
|
||||
var (
|
||||
v = new(struct {
|
||||
MachineName string `json:"name"`
|
||||
ImageName string `json:"image_name"`
|
||||
ResultStatus bool `json:"status"`
|
||||
Message string `json:"msg"`
|
||||
})
|
||||
err error
|
||||
)
|
||||
|
||||
if err = c.BindWith(v, binding.JSON); err != nil {
|
||||
return
|
||||
}
|
||||
c.JSON(nil, svc.CallBackSnapShot(c, v.MachineName, v.ImageName, v.Message, v.ResultStatus))
|
||||
}
|
||||
|
||||
func machine2image(c *bm.Context) {
|
||||
var (
|
||||
username string
|
||||
err error
|
||||
v = new(struct {
|
||||
MachineID int64 `json:"machine_id"`
|
||||
ImageName string `json:"image_name"`
|
||||
NewImageName string `json:"new_image_name"`
|
||||
})
|
||||
)
|
||||
|
||||
if err = c.BindWith(v, binding.JSON); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if username, err = getUsername(c); err != nil {
|
||||
return
|
||||
}
|
||||
c.JSON(nil, svc.Machine2Image(c, username, v.ImageName, v.NewImageName, v.MachineID))
|
||||
}
|
||||
|
||||
func queryMachine2ImageLog(c *bm.Context) {
|
||||
var (
|
||||
v = &model.QueryMachine2ImageLogRequest{}
|
||||
err error
|
||||
)
|
||||
|
||||
if err = c.Bind(v); err != nil {
|
||||
return
|
||||
}
|
||||
c.JSON(svc.QueryMachine2ImageLog(c, v))
|
||||
}
|
||||
|
||||
func machine2imageForceFailed(c *bm.Context) {
|
||||
var (
|
||||
v = new(struct {
|
||||
MachineID int64 `form:"machine_id"`
|
||||
})
|
||||
err error
|
||||
)
|
||||
|
||||
if err = c.Bind(v); err != nil {
|
||||
return
|
||||
}
|
||||
c.JSON(svc.Machine2ImageForceFailed(c, v.MachineID))
|
||||
}
|
||||
|
||||
func updateImageConf(c *bm.Context) {
|
||||
var (
|
||||
username string
|
||||
err error
|
||||
v = &model.ImageConfiguration{}
|
||||
)
|
||||
|
||||
if err = c.BindWith(v, binding.JSON); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if username, err = getUsername(c); err != nil {
|
||||
return
|
||||
}
|
||||
c.JSON(svc.UpdateImageConf(c, username, v))
|
||||
}
|
||||
|
||||
func queryImageConf(c *bm.Context) {
|
||||
var (
|
||||
v = new(struct {
|
||||
ImageName string `form:"image_full_name"`
|
||||
})
|
||||
err error
|
||||
)
|
||||
|
||||
if err = c.Bind(v); err != nil {
|
||||
return
|
||||
}
|
||||
c.JSON(svc.QueryImageConf(c, v.ImageName))
|
||||
}
|
9
app/admin/ep/merlin/http/cluster.go
Normal file
9
app/admin/ep/merlin/http/cluster.go
Normal file
@ -0,0 +1,9 @@
|
||||
package http
|
||||
|
||||
import (
|
||||
bm "go-common/library/net/http/blademaster"
|
||||
)
|
||||
|
||||
func queryCluster(c *bm.Context) {
|
||||
c.JSON(svc.QueryCluster(c))
|
||||
}
|
33
app/admin/ep/merlin/http/dashboard.go
Normal file
33
app/admin/ep/merlin/http/dashboard.go
Normal file
@ -0,0 +1,33 @@
|
||||
package http
|
||||
|
||||
import (
|
||||
bm "go-common/library/net/http/blademaster"
|
||||
)
|
||||
|
||||
func queryMachineLifeCycle(c *bm.Context) {
|
||||
c.JSON(svc.QueryMachineLifeCycle(c))
|
||||
}
|
||||
|
||||
func queryMachineCount(c *bm.Context) {
|
||||
c.JSON(svc.QueryMachineCount(c))
|
||||
}
|
||||
|
||||
func queryMachineTime(c *bm.Context) {
|
||||
c.JSON(svc.QueryMachineCreatedAndEndTime(c))
|
||||
}
|
||||
|
||||
func queryMachineUsage(c *bm.Context) {
|
||||
c.JSON(svc.QueryMachineUsage(c))
|
||||
}
|
||||
|
||||
func queryMobileMachineUsageCount(c *bm.Context) {
|
||||
c.JSON(svc.QueryMobileMachineUsageCount(c))
|
||||
}
|
||||
|
||||
func queryMobileMachineModeCount(c *bm.Context) {
|
||||
c.JSON(svc.QueryMobileMachineModeCount(c))
|
||||
}
|
||||
|
||||
func queryMobileMachineUsageTime(c *bm.Context) {
|
||||
c.JSON(svc.QueryMobileMachineUsageTime(c))
|
||||
}
|
275
app/admin/ep/merlin/http/devicefarm.go
Normal file
275
app/admin/ep/merlin/http/devicefarm.go
Normal file
@ -0,0 +1,275 @@
|
||||
package http
|
||||
|
||||
import (
|
||||
"go-common/app/admin/ep/merlin/model"
|
||||
bm "go-common/library/net/http/blademaster"
|
||||
"go-common/library/net/http/blademaster/binding"
|
||||
)
|
||||
|
||||
func queryMobileDevice(c *bm.Context) {
|
||||
var (
|
||||
qdfr = &model.QueryMobileDeviceRequest{}
|
||||
err error
|
||||
)
|
||||
if err = c.BindWith(qdfr, binding.JSON); err != nil {
|
||||
return
|
||||
}
|
||||
if err = qdfr.Verify(); err != nil {
|
||||
c.JSON(nil, err)
|
||||
return
|
||||
}
|
||||
c.JSON(svc.QueryMobileDeviceList(c, qdfr))
|
||||
}
|
||||
|
||||
func refreshMobileDeviceDetail(c *bm.Context) {
|
||||
v := new(struct {
|
||||
ID int64 `form:"id"`
|
||||
})
|
||||
if err := c.Bind(v); err != nil {
|
||||
return
|
||||
}
|
||||
c.JSON(svc.RefreshMobileDeviceDetail(c, v.ID))
|
||||
}
|
||||
|
||||
func bindMobileDevice(c *bm.Context) {
|
||||
var (
|
||||
username string
|
||||
v = new(struct {
|
||||
ID int64 `form:"id"`
|
||||
})
|
||||
err error
|
||||
)
|
||||
|
||||
if username, err = getUsername(c); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if err = c.Bind(v); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(svc.BindMobileDevice(c, v.ID, username))
|
||||
}
|
||||
|
||||
func releaseMobileDevice(c *bm.Context) {
|
||||
var (
|
||||
username string
|
||||
v = new(struct {
|
||||
ID int64 `form:"id"`
|
||||
})
|
||||
err error
|
||||
)
|
||||
|
||||
if username, err = getUsername(c); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if err = c.Bind(v); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(svc.ReleaseMobileDevice(c, v.ID, username))
|
||||
}
|
||||
|
||||
func lendOutMobileDevice(c *bm.Context) {
|
||||
var (
|
||||
username string
|
||||
v = new(struct {
|
||||
ID int64 `form:"id"`
|
||||
})
|
||||
err error
|
||||
)
|
||||
|
||||
if username, err = getUsername(c); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if err = c.Bind(v); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(svc.LendOutMobileDevice(c, v.ID, username))
|
||||
}
|
||||
|
||||
func returnMobileDevice(c *bm.Context) {
|
||||
var (
|
||||
username string
|
||||
v = new(struct {
|
||||
ID int64 `form:"id"`
|
||||
})
|
||||
err error
|
||||
)
|
||||
|
||||
if username, err = getUsername(c); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if err = c.Bind(v); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(svc.ReturnMobileDevice(c, v.ID, username))
|
||||
}
|
||||
|
||||
func startMobileDevice(c *bm.Context) {
|
||||
var (
|
||||
username string
|
||||
v = new(struct {
|
||||
ID int64 `form:"id"`
|
||||
})
|
||||
err error
|
||||
)
|
||||
|
||||
if username, err = getUsername(c); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if err = c.Bind(v); err != nil {
|
||||
return
|
||||
}
|
||||
c.JSON(svc.StartMobileDevice(c, v.ID, username))
|
||||
}
|
||||
|
||||
func shutDownMobileDevice(c *bm.Context) {
|
||||
var (
|
||||
username string
|
||||
v = new(struct {
|
||||
ID int64 `form:"id"`
|
||||
})
|
||||
err error
|
||||
)
|
||||
|
||||
if username, err = getUsername(c); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if err = c.Bind(v); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(svc.ShutdownMobileDevice(c, v.ID, username))
|
||||
}
|
||||
|
||||
func syncMobileDevice(c *bm.Context) {
|
||||
c.JSON(svc.SyncMobileDeviceList(c))
|
||||
}
|
||||
|
||||
func queryCategory(c *bm.Context) {
|
||||
var (
|
||||
v = new(struct {
|
||||
IsShowOfflineMB bool `form:"is_show_offline"`
|
||||
})
|
||||
err error
|
||||
)
|
||||
if err = c.Bind(v); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(svc.MobileMachineCategory(c, v.IsShowOfflineMB))
|
||||
}
|
||||
|
||||
func reportMobileDeviceError(c *bm.Context) {
|
||||
var (
|
||||
v = new(struct {
|
||||
SerialName string `json:"serial"`
|
||||
ErrorMessage string `json:"error_message"`
|
||||
ErrorCode int `json:"error_code"`
|
||||
})
|
||||
err error
|
||||
)
|
||||
|
||||
if err = c.BindWith(v, binding.JSON); err != nil {
|
||||
return
|
||||
}
|
||||
c.JSON(nil, svc.ReportMobileDeviceError(c, v.SerialName, v.ErrorMessage, v.ErrorCode))
|
||||
}
|
||||
|
||||
func queryMobileMachineLogs(c *bm.Context) {
|
||||
v := &model.QueryMobileMachineLogRequest{}
|
||||
if err := c.Bind(v); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if err := v.Verify(); err != nil {
|
||||
c.JSON(nil, err)
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(svc.QueryMobileMachineLogs(c, v))
|
||||
}
|
||||
|
||||
func queryMobileMachineLendOut(c *bm.Context) {
|
||||
var (
|
||||
v = &model.QueryMobileMachineLogRequest{}
|
||||
err error
|
||||
username string
|
||||
)
|
||||
if err = c.Bind(v); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if err = v.Verify(); err != nil {
|
||||
c.JSON(nil, err)
|
||||
return
|
||||
}
|
||||
|
||||
if username, err = getUsername(c); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(svc.QueryMobileMachineLendOutLogs(c, username, v))
|
||||
}
|
||||
|
||||
func queryMobileMachineErrorLogs(c *bm.Context) {
|
||||
v := &model.QueryMobileMachineErrorLogRequest{}
|
||||
if err := c.Bind(v); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if err := v.Verify(); err != nil {
|
||||
c.JSON(nil, err)
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(svc.QueryMobileMachineErrorLogs(c, v))
|
||||
}
|
||||
|
||||
func callbackMobileDeviceError(c *bm.Context) {
|
||||
var (
|
||||
v = new(struct {
|
||||
SerialName string `json:"serial"`
|
||||
ErrorMessage string `json:"error_message"`
|
||||
ErrorCode int `json:"error_code"`
|
||||
})
|
||||
err error
|
||||
)
|
||||
|
||||
if err = c.BindWith(v, binding.JSON); err != nil {
|
||||
return
|
||||
}
|
||||
c.JSON(nil, svc.CallBackMobileDeviceError(c, v.SerialName, v.ErrorMessage, v.ErrorCode))
|
||||
}
|
||||
|
||||
func queryDeviceFarmSuperUser(c *bm.Context) {
|
||||
c.JSON(svc.DeviceFarmSuperUser(), nil)
|
||||
}
|
||||
|
||||
func isBindByTheUser(c *bm.Context) {
|
||||
var (
|
||||
username string
|
||||
v = new(struct {
|
||||
ID int64 `form:"id"`
|
||||
})
|
||||
err error
|
||||
)
|
||||
|
||||
if username, err = getUsername(c); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if err = c.Bind(v); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(svc.IsBindMobileDeviceByTheUser(c, v.ID, username))
|
||||
}
|
242
app/admin/ep/merlin/http/http.go
Normal file
242
app/admin/ep/merlin/http/http.go
Normal file
@ -0,0 +1,242 @@
|
||||
package http
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"go-common/app/admin/ep/merlin/conf"
|
||||
"go-common/app/admin/ep/merlin/service"
|
||||
"go-common/library/log"
|
||||
bm "go-common/library/net/http/blademaster"
|
||||
"go-common/library/net/http/blademaster/middleware/permit"
|
||||
)
|
||||
|
||||
const (
|
||||
_sessIDKey = "_AJSESSIONID"
|
||||
)
|
||||
|
||||
var (
|
||||
svc *service.Service
|
||||
authSvc *permit.Permit
|
||||
)
|
||||
|
||||
// Init init
|
||||
func Init(c *conf.Config, s *service.Service) {
|
||||
svc = s
|
||||
authSvc = permit.New(c.Auth)
|
||||
|
||||
engine := bm.DefaultServer(c.BM)
|
||||
engine.Ping(ping)
|
||||
outerRouter(engine)
|
||||
if err := engine.Start(); err != nil {
|
||||
log.Error("engine.Start error(%v)", err)
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
// outerRouter init outer router api path.
|
||||
func outerRouter(e *bm.Engine) {
|
||||
e.GET("/ep/admin/merlin/version", getVersion)
|
||||
e.GET("/ep/admin/merlin/conf/version", confVersion)
|
||||
|
||||
base := e.Group("/ep/admin/merlin", authSvc.Permit(""))
|
||||
{
|
||||
v1 := base.Group("/v1")
|
||||
{
|
||||
cluster := v1.Group("/cluster")
|
||||
{
|
||||
cluster.GET("/query", queryCluster)
|
||||
}
|
||||
|
||||
machine := v1.Group("/machine")
|
||||
{
|
||||
machine.POST("/gen", genMachines)
|
||||
machine.GET("/del", delMachine)
|
||||
machine.GET("/query/detail", queryMachineDetail)
|
||||
machine.GET("/query", queryMachines)
|
||||
machine.GET("/query/status", queryMachineStatus)
|
||||
machine.GET("/transfer", transferMachine)
|
||||
|
||||
machinePackage := machine.Group("/package")
|
||||
{
|
||||
machinePackage.GET("/query", queryMachinePackages)
|
||||
}
|
||||
|
||||
machineLog := machine.Group("/log")
|
||||
{
|
||||
machineLog.GET("/query", queryMachineLogs)
|
||||
}
|
||||
|
||||
machineNode := machine.Group("/node")
|
||||
{
|
||||
machineNode.POST("update", updateNodes)
|
||||
machineNode.GET("query", queryNodes)
|
||||
}
|
||||
}
|
||||
|
||||
image := v1.Group("image")
|
||||
{
|
||||
image.GET("/query", queryImage)
|
||||
image.POST("/add", addImage)
|
||||
image.POST("/update", updateImage)
|
||||
image.POST("/del", delImage)
|
||||
}
|
||||
|
||||
serviceTree := v1.Group("/tree")
|
||||
{
|
||||
serviceTree.GET("/query", userTree)
|
||||
serviceTree.GET("/container/query", userTreeContainer)
|
||||
serviceTree.GET("/auditors/query", treeAuditors)
|
||||
|
||||
}
|
||||
|
||||
audit := v1.Group("/audit")
|
||||
{
|
||||
auditEndTime := audit.Group("/endTime")
|
||||
{
|
||||
auditEndTime.GET("/delay", delayMachineEndTime) //手动延期 done ok
|
||||
auditEndTime.POST("/apply", applyMachineEndTime) //申请延期 done
|
||||
auditEndTime.GET("/cancel", cancelMachineEndTime) //取消延期 done
|
||||
auditEndTime.POST("/audit", auditMachineEndTime) //审批 通过或驳回 done
|
||||
auditEndTime.GET("/query/applyList", queryApplicationRecordsByMachineID) //done ok
|
||||
auditEndTime.GET("/query/user/applyList", queryApplicationRecordsByApplicant) //done ok
|
||||
auditEndTime.GET("/query/user/auditList", queryApplicationRecordsByAuditor) //done ok
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
user := v1.Group("/user")
|
||||
{
|
||||
user.GET("/query", queryUserInfo)
|
||||
}
|
||||
|
||||
mobileDevice := v1.Group("/mobiledevice")
|
||||
{
|
||||
mobileDevice.POST("/query", queryMobileDevice)
|
||||
mobileDevice.GET("/refresh", refreshMobileDeviceDetail)
|
||||
mobileDevice.GET("/bind", bindMobileDevice)
|
||||
mobileDevice.GET("/release", releaseMobileDevice)
|
||||
mobileDevice.GET("/isbind", isBindByTheUser)
|
||||
|
||||
mobileDevice.GET("/pullout", lendOutMobileDevice)
|
||||
mobileDevice.GET("/return", returnMobileDevice)
|
||||
|
||||
mobileDevice.GET("/start", startMobileDevice)
|
||||
mobileDevice.GET("/shutdown", shutDownMobileDevice)
|
||||
mobileDevice.GET("/syncall", syncMobileDevice)
|
||||
|
||||
mobileDevice.GET("/category/query", queryCategory)
|
||||
mobileDevice.GET("/superuser/query", queryDeviceFarmSuperUser)
|
||||
|
||||
mobileDeviceLog := mobileDevice.Group("/log")
|
||||
{
|
||||
mobileDeviceLog.GET("/query", queryMobileMachineLogs)
|
||||
mobileDeviceLog.GET("/lendout/query", queryMobileMachineLendOut)
|
||||
}
|
||||
|
||||
mobileDeviceErrorLog := mobileDevice.Group("/error/log")
|
||||
{
|
||||
mobileDeviceErrorLog.GET("/query", queryMobileMachineErrorLogs)
|
||||
mobileDeviceErrorLog.POST("/report", reportMobileDeviceError)
|
||||
}
|
||||
}
|
||||
|
||||
biliHub := v1.Group("/bilihub")
|
||||
{
|
||||
biliHub.GET("/auth", authHub)
|
||||
biliHub.GET("/auth/access", accessAuthHub)
|
||||
|
||||
biliHub.GET("/projects/accesspull", accessPullProjects)
|
||||
biliHub.GET("/projects", projects)
|
||||
|
||||
biliHub.GET("/repos", repos)
|
||||
biliHub.GET("/repotags", tags)
|
||||
biliHub.GET("/repos/delete", deleteRepo)
|
||||
biliHub.GET("/repotags/delete", deleteRepoTag)
|
||||
|
||||
biliHub.GET("/snapshot", snapshot)
|
||||
biliHub.GET("/snapshot/query", querySnapshot)
|
||||
|
||||
biliHub.POST("/machine2image", machine2image)
|
||||
biliHub.GET("/machine2image/forcefailed", machine2imageForceFailed)
|
||||
biliHub.GET("/machine2image/log/query", queryMachine2ImageLog)
|
||||
|
||||
image := biliHub.Group("/image")
|
||||
{
|
||||
image.GET("/all", allImage)
|
||||
image.POST("/addtag", addTag)
|
||||
image.POST("/push", push)
|
||||
image.POST("/retag", reTag)
|
||||
image.POST("/pull", pull)
|
||||
|
||||
conf := image.Group("/conf")
|
||||
{
|
||||
conf.POST("/update", updateImageConf)
|
||||
conf.GET("/query", queryImageConf)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dashboard := v1.Group("/dashboard")
|
||||
{
|
||||
machine := dashboard.Group("/machine")
|
||||
{
|
||||
machine.GET("/lifecycle", queryMachineLifeCycle)
|
||||
machine.GET("/count", queryMachineCount)
|
||||
machine.GET("/time", queryMachineTime)
|
||||
machine.GET("/usage", queryMachineUsage)
|
||||
}
|
||||
|
||||
deviceFarm := dashboard.Group("/devicefarm")
|
||||
{
|
||||
deviceFarm.GET("/usagecount", queryMobileMachineUsageCount)
|
||||
deviceFarm.GET("/modecount", queryMobileMachineModeCount)
|
||||
deviceFarm.GET("/usagetime", queryMobileMachineUsageTime)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
v2 := base.Group("/v2")
|
||||
{
|
||||
machine := v2.Group("/machine")
|
||||
{
|
||||
machine.POST("/gen", genMachinesV2)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
callback := e.Group("/ep/admin/merlin/callback")
|
||||
{
|
||||
v1 := callback.Group("/v1")
|
||||
{
|
||||
|
||||
v1.POST("/bilihub/snapshot", callbackSnapshot)
|
||||
v1.POST("/mobiledevice/error", callbackMobileDeviceError)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
func ping(c *bm.Context) {
|
||||
if err := svc.Ping(c); err != nil {
|
||||
log.Error("ping error(%v)", err)
|
||||
c.AbortWithStatus(http.StatusServiceUnavailable)
|
||||
}
|
||||
}
|
||||
|
||||
func getVersion(c *bm.Context) {
|
||||
v := new(struct {
|
||||
Version string `json:"version"`
|
||||
})
|
||||
v.Version = "v.1.5.9.3"
|
||||
c.JSON(v, nil)
|
||||
|
||||
}
|
||||
|
||||
func confVersion(c *bm.Context) {
|
||||
v := new(struct {
|
||||
Version string `json:"version"`
|
||||
})
|
||||
v.Version = svc.ConfVersion(c)
|
||||
c.JSON(v, nil)
|
||||
|
||||
}
|
44
app/admin/ep/merlin/http/image.go
Normal file
44
app/admin/ep/merlin/http/image.go
Normal file
@ -0,0 +1,44 @@
|
||||
package http
|
||||
|
||||
import (
|
||||
"go-common/app/admin/ep/merlin/model"
|
||||
bm "go-common/library/net/http/blademaster"
|
||||
"go-common/library/net/http/blademaster/binding"
|
||||
)
|
||||
|
||||
func queryImage(c *bm.Context) {
|
||||
c.JSON(svc.QueryImage())
|
||||
}
|
||||
|
||||
func addImage(c *bm.Context) {
|
||||
var (
|
||||
image = &model.Image{}
|
||||
err error
|
||||
)
|
||||
if err = c.BindWith(image, binding.JSON); err != nil {
|
||||
return
|
||||
}
|
||||
c.JSON(nil, svc.AddImage(image))
|
||||
}
|
||||
|
||||
func updateImage(c *bm.Context) {
|
||||
var (
|
||||
image = &model.Image{}
|
||||
err error
|
||||
)
|
||||
if err = c.BindWith(image, binding.JSON); err != nil {
|
||||
return
|
||||
}
|
||||
c.JSON(nil, svc.UpdateImage(image))
|
||||
}
|
||||
|
||||
func delImage(c *bm.Context) {
|
||||
var (
|
||||
image = &model.Image{}
|
||||
err error
|
||||
)
|
||||
if err = c.BindWith(image, binding.JSON); err != nil {
|
||||
return
|
||||
}
|
||||
c.JSON(nil, svc.DeleteImage(image.ID))
|
||||
}
|
131
app/admin/ep/merlin/http/machine.go
Normal file
131
app/admin/ep/merlin/http/machine.go
Normal file
@ -0,0 +1,131 @@
|
||||
package http
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"go-common/app/admin/ep/merlin/model"
|
||||
bm "go-common/library/net/http/blademaster"
|
||||
"go-common/library/net/http/blademaster/binding"
|
||||
)
|
||||
|
||||
func genMachines(c *bm.Context) {
|
||||
var (
|
||||
gmr = &model.GenMachinesRequest{}
|
||||
err error
|
||||
username string
|
||||
)
|
||||
|
||||
if username, err = getUsername(c); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if err = c.BindWith(gmr, binding.JSON); err != nil {
|
||||
return
|
||||
}
|
||||
if err = gmr.Verify(); err != nil {
|
||||
c.JSON(nil, err)
|
||||
return
|
||||
}
|
||||
c.JSON(nil, svc.GenMachines(c, gmr, username))
|
||||
}
|
||||
|
||||
func delMachine(c *bm.Context) {
|
||||
var (
|
||||
username string
|
||||
v = new(struct {
|
||||
ID int64 `form:"id"`
|
||||
})
|
||||
err error
|
||||
)
|
||||
|
||||
if username, err = getUsername(c); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if err = c.Bind(v); err != nil {
|
||||
return
|
||||
}
|
||||
c.JSON(svc.DelMachineWhenCanBeDel(c, v.ID, username))
|
||||
}
|
||||
|
||||
func queryMachineDetail(c *bm.Context) {
|
||||
v := new(struct {
|
||||
ID int64 `form:"id"`
|
||||
})
|
||||
if err := c.Bind(v); err != nil {
|
||||
return
|
||||
}
|
||||
c.JSON(svc.QueryMachineDetail(c, v.ID))
|
||||
}
|
||||
|
||||
func queryMachinePackages(c *bm.Context) {
|
||||
c.JSON(svc.QueryMachinePackages(c))
|
||||
}
|
||||
|
||||
func queryMachines(c *bm.Context) {
|
||||
var (
|
||||
qmr = &model.QueryMachineRequest{}
|
||||
session *http.Cookie
|
||||
err error
|
||||
)
|
||||
if err = c.Bind(qmr); err != nil {
|
||||
return
|
||||
}
|
||||
if err = qmr.Verify(); err != nil {
|
||||
c.JSON(nil, err)
|
||||
return
|
||||
}
|
||||
if session, err = c.Request.Cookie(_sessIDKey); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if qmr.Requester, err = getUsername(c); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(svc.QueryMachines(c, session.Value, qmr))
|
||||
}
|
||||
|
||||
func queryMachineLogs(c *bm.Context) {
|
||||
v := &model.QueryMachineLogRequest{}
|
||||
if err := c.Bind(v); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if err := v.Verify(); err != nil {
|
||||
c.JSON(nil, err)
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(svc.QueryMachineLogs(c, v))
|
||||
}
|
||||
|
||||
func queryMachineStatus(c *bm.Context) {
|
||||
v := new(struct {
|
||||
MachineID int64 `form:"machine_id"`
|
||||
})
|
||||
if err := c.Bind(v); err != nil {
|
||||
return
|
||||
}
|
||||
c.JSON(svc.QueryMachineStatus(c, v.MachineID))
|
||||
}
|
||||
|
||||
func transferMachine(c *bm.Context) {
|
||||
var (
|
||||
v = new(struct {
|
||||
MachineID int64 `form:"machine_id"`
|
||||
Receiver string `form:"receiver"`
|
||||
})
|
||||
username string
|
||||
err error
|
||||
)
|
||||
if err = c.Bind(v); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if username, err = getUsername(c); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(svc.TransferMachine(c, v.MachineID, username, v.Receiver))
|
||||
}
|
29
app/admin/ep/merlin/http/machineV2.go
Normal file
29
app/admin/ep/merlin/http/machineV2.go
Normal file
@ -0,0 +1,29 @@
|
||||
package http
|
||||
|
||||
import (
|
||||
"go-common/app/admin/ep/merlin/model"
|
||||
bm "go-common/library/net/http/blademaster"
|
||||
"go-common/library/net/http/blademaster/binding"
|
||||
)
|
||||
|
||||
func genMachinesV2(c *bm.Context) {
|
||||
var (
|
||||
gmr = &model.GenMachinesRequest{}
|
||||
err error
|
||||
username string
|
||||
)
|
||||
|
||||
if username, err = getUsername(c); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if err = c.BindWith(gmr, binding.JSON); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if err = gmr.Verify(); err != nil {
|
||||
c.JSON(nil, err)
|
||||
return
|
||||
}
|
||||
c.JSON(nil, svc.GenMachinesV2(c, gmr, username))
|
||||
}
|
32
app/admin/ep/merlin/http/node.go
Normal file
32
app/admin/ep/merlin/http/node.go
Normal file
@ -0,0 +1,32 @@
|
||||
package http
|
||||
|
||||
import (
|
||||
"go-common/app/admin/ep/merlin/model"
|
||||
bm "go-common/library/net/http/blademaster"
|
||||
"go-common/library/net/http/blademaster/binding"
|
||||
)
|
||||
|
||||
func updateNodes(c *bm.Context) {
|
||||
var (
|
||||
umnr = &model.UpdateMachineNodeRequest{}
|
||||
err error
|
||||
)
|
||||
if err = c.BindWith(umnr, binding.JSON); err != nil {
|
||||
return
|
||||
}
|
||||
if err = umnr.VerifyNodes(); err != nil {
|
||||
c.JSON(nil, err)
|
||||
return
|
||||
}
|
||||
c.JSON(nil, svc.UpdateMachineNode(c, umnr))
|
||||
}
|
||||
|
||||
func queryNodes(c *bm.Context) {
|
||||
v := new(struct {
|
||||
MachineID int64 `form:"machine_id"`
|
||||
})
|
||||
if err := c.Bind(v); err != nil {
|
||||
return
|
||||
}
|
||||
c.JSON(svc.QueryMachineNodes(v.MachineID))
|
||||
}
|
50
app/admin/ep/merlin/http/tree.go
Normal file
50
app/admin/ep/merlin/http/tree.go
Normal file
@ -0,0 +1,50 @@
|
||||
package http
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"go-common/app/admin/ep/merlin/model"
|
||||
bm "go-common/library/net/http/blademaster"
|
||||
)
|
||||
|
||||
func userTree(c *bm.Context) {
|
||||
session, err := c.Request.Cookie(_sessIDKey)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
c.JSON(svc.UserTreeAsOption(c, session.Value))
|
||||
|
||||
}
|
||||
|
||||
func userTreeContainer(c *bm.Context) {
|
||||
var (
|
||||
tnr = &model.TreeNode{}
|
||||
err error
|
||||
session *http.Cookie
|
||||
)
|
||||
if err = c.Bind(tnr); err != nil {
|
||||
return
|
||||
}
|
||||
if err = tnr.VerifyFieldValue(); err != nil {
|
||||
return
|
||||
}
|
||||
if session, err = c.Request.Cookie(_sessIDKey); err != nil {
|
||||
return
|
||||
}
|
||||
c.JSON(nil, svc.VerifyTreeContainerNode(c, session.Value, tnr))
|
||||
}
|
||||
|
||||
func treeAuditors(c *bm.Context) {
|
||||
v := new(struct {
|
||||
FirstNode string `form:"first_node"`
|
||||
})
|
||||
if err := c.Bind(v); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
session, err := c.Request.Cookie(_sessIDKey)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
c.JSON(svc.TreeRoleAsAuditor(c, session.Value, v.FirstNode))
|
||||
}
|
34
app/admin/ep/merlin/http/user.go
Normal file
34
app/admin/ep/merlin/http/user.go
Normal file
@ -0,0 +1,34 @@
|
||||
package http
|
||||
|
||||
import (
|
||||
"go-common/library/ecode"
|
||||
bm "go-common/library/net/http/blademaster"
|
||||
)
|
||||
|
||||
const (
|
||||
_sessUnKey = "username"
|
||||
)
|
||||
|
||||
func queryUserInfo(c *bm.Context) {
|
||||
var (
|
||||
username string
|
||||
err error
|
||||
)
|
||||
if username, err = getUsername(c); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(svc.QueryUserInfo(c, username))
|
||||
|
||||
}
|
||||
|
||||
func getUsername(c *bm.Context) (username string, err error) {
|
||||
user, exist := c.Get(_sessUnKey)
|
||||
if !exist {
|
||||
err = ecode.AccessKeyErr
|
||||
c.JSON(nil, err)
|
||||
return
|
||||
}
|
||||
username = user.(string)
|
||||
return
|
||||
}
|
Reference in New Issue
Block a user