Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,6 @@

# Dependency directories (remove the comment below to include it)
# vendor/

.idea
backend/__debug_bin
8 changes: 8 additions & 0 deletions .idea/.gitignore

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Empty file added Dockerfile
Empty file.
66 changes: 66 additions & 0 deletions backend/app.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
system:
port: 9999
db_type: mysql

jwt:
header_name: Authorization
signing_key: 1panelKey
expires_time: 604800 #过期时间
buffer_time: 86400 #缓冲时间 缓冲时间内会获取新的token刷新令牌
issuer: 1Panel

session:
session_name: psession
expires_time: 604800

captcha:
enable: true
source: "1234567890QWERTYUIOPLKJHGFDSAZXCVBNMqwertyuioplkjhgfdsazxcvbnm"
length: 4
noise-count: 0
img-width: 120
img-height: 50

mysql:
path: localhost
port: 3306
db_name: 1Panel
username: root
password: KubeOperator123@mysql
max_idle_conns: 10
max_open_conns: 100

sqlite:
path: /opt/1Panel/data/db
db_file: 1Panel.db

log:
level: info
path: /opt/1Panel/log
log_name: 1Panel
log_suffix: .log
log_size: 50 #日志文件大小,单位是 MB
log_backup: 10 #最大过期日志保留个数
log_data: 7 #保留过期文件最大时间,单位 天

cache:
path: /opt/1Panel/data/cache

# 跨域配置
cors:
mode: whitelist # 放行模式: allow-all, 放行全部; whitelist, 白名单模式, 来自白名单内域名的请求添加 cors 头; strict-whitelist 严格白名单模式, 白名单外的请求一律拒绝
whitelist:
- allow-origin: example1.com
allow-headers: content-type
allow-methods: GET, POST
expose-headers: Content-Length, Access-Control-Allow-Origin, Access-Control-Allow-Headers, Content-Type
allow-credentials: true # 布尔值
- allow-origin: example2.com
allow-headers: content-type
allow-methods: GET, POST
expose-headers: Content-Length, Access-Control-Allow-Origin, Access-Control-Allow-Headers, Content-Type
allow-credentials: true # 布尔值

# 加密设置
encrypt:
key: 1Panel123@2022!
14 changes: 14 additions & 0 deletions backend/app/api/v1/entry.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package v1

import "github.com/1Panel-dev/1Panel/app/service"

type ApiGroup struct {
BaseApi
}

var ApiGroupApp = new(ApiGroup)

var (
userService = service.ServiceGroupApp.UserService
operationService = service.ServiceGroupApp.OperationService
)
78 changes: 78 additions & 0 deletions backend/app/api/v1/helper/helper.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
package helper

import (
"net/http"
"strconv"

"github.com/pkg/errors"

"github.com/1Panel-dev/1Panel/app/dto"
"github.com/1Panel-dev/1Panel/constant"
"github.com/1Panel-dev/1Panel/i18n"
"github.com/gin-gonic/gin"
)

func GeneratePaginationFromReq(c *gin.Context) (*dto.PageInfo, bool) {
p, ok1 := c.GetQuery("page")
ps, ok2 := c.GetQuery("pageSize")
if !(ok1 && ok2) {
return nil, false
}

page, err := strconv.Atoi(p)
if err != nil {
return nil, false
}
pageSize, err := strconv.Atoi(ps)
if err != nil {
return nil, false
}

return &dto.PageInfo{Page: page, PageSize: pageSize}, true
}

func ErrorWithDetail(ctx *gin.Context, code int, msgKey string, err error) {
res := dto.Response{
Code: code,
Msg: "",
}
if msgKey == constant.ErrTypeInternalServer {
switch {
case errors.Is(err, constant.ErrRecordExist):
res.Msg = i18n.GetMsgWithMap("ErrRecordExist", map[string]interface{}{"detail": err})
case errors.Is(constant.ErrRecordNotFound, err):
res.Msg = i18n.GetMsgWithMap("ErrRecordNotFound", map[string]interface{}{"detail": err})
case errors.Is(constant.ErrStructTransform, err):
res.Msg = i18n.GetMsgWithMap("ErrStructTransform", map[string]interface{}{"detail": err})
case errors.Is(constant.ErrCaptchaCode, err):
res.Msg = i18n.GetMsgWithMap("ErrCaptchaCode", map[string]interface{}{"detail": err})
default:
res.Msg = i18n.GetMsgWithMap(msgKey, map[string]interface{}{"detail": err})
}
} else {
res.Msg = i18n.GetMsgWithMap(msgKey, map[string]interface{}{"detail": err})
}
ctx.JSON(http.StatusOK, res)
ctx.Abort()
}

func SuccessWithData(ctx *gin.Context, data interface{}) {
if data == nil {
data = gin.H{}
}
res := dto.Response{
Code: constant.CodeSuccess,
Data: data,
}
ctx.JSON(http.StatusOK, res)
ctx.Abort()
}

func GetParamID(c *gin.Context) (uint, error) {
idParam, ok := c.Params.Get("id")
if !ok {
return 0, errors.New("error name")
}
intNum, _ := strconv.Atoi(idParam)
return uint(intNum), nil
}
46 changes: 46 additions & 0 deletions backend/app/api/v1/operation_log.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package v1

import (
"github.com/1Panel-dev/1Panel/app/api/v1/helper"
"github.com/1Panel-dev/1Panel/app/dto"
"github.com/1Panel-dev/1Panel/constant"
"github.com/1Panel-dev/1Panel/global"
"github.com/gin-gonic/gin"
)

func (b *BaseApi) GetOperationList(c *gin.Context) {
var req dto.PageInfo
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
return
}

total, list, err := operationService.Page(req)
if err != nil {
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
return
}

helper.SuccessWithData(c, dto.PageResult{
Items: list,
Total: total,
})
}

func (b *BaseApi) DeleteOperation(c *gin.Context) {
var req dto.BatchDeleteReq
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
return
}
if err := global.VALID.Struct(req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
return
}

if err := operationService.BatchDelete(req.Ids); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
return
}
helper.SuccessWithData(c, nil)
}
145 changes: 145 additions & 0 deletions backend/app/api/v1/user.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
package v1

import (
"github.com/1Panel-dev/1Panel/app/api/v1/helper"
"github.com/1Panel-dev/1Panel/app/dto"
"github.com/1Panel-dev/1Panel/constant"
"github.com/1Panel-dev/1Panel/global"
"github.com/1Panel-dev/1Panel/utils/captcha"
"github.com/gin-gonic/gin"
)

type BaseApi struct{}

func (b *BaseApi) Login(c *gin.Context) {
var req dto.Login
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
return
}
if err := global.VALID.Struct(req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
return
}
if err := captcha.VerifyCode(req.CaptchaID, req.Captcha); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
return
}

user, err := userService.Login(c, req)
if err != nil {
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
return
}
helper.SuccessWithData(c, user)
}

func (b *BaseApi) LogOut(c *gin.Context) {
if err := userService.LogOut(c); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
return
}
helper.SuccessWithData(c, nil)
}

func (b *BaseApi) Captcha(c *gin.Context) {
captcha, err := captcha.CreateCaptcha()
if err != nil {
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
}
helper.SuccessWithData(c, captcha)
}

func (b *BaseApi) Register(c *gin.Context) {
var req dto.UserCreate
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
return
}
if err := global.VALID.Struct(req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
return
}
if err := userService.Register(req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
return
}
helper.SuccessWithData(c, nil)
}

func (b *BaseApi) PageUsers(c *gin.Context) {
var req dto.UserPage
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
return
}

total, list, err := userService.Page(req)
if err != nil {
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
return
}

helper.SuccessWithData(c, dto.PageResult{
Items: list,
Total: total,
})
}

func (b *BaseApi) DeleteUser(c *gin.Context) {
var req dto.BatchDeleteReq
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
return
}
if err := global.VALID.Struct(req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
return
}

if err := userService.BatchDelete(req.Ids); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
return
}
helper.SuccessWithData(c, nil)
}

func (b *BaseApi) UpdateUser(c *gin.Context) {
var req dto.UserUpdate
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
return
}
if err := global.VALID.Struct(req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
return
}
id, err := helper.GetParamID(c)
if err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
return
}

upMap := make(map[string]interface{})
upMap["email"] = req.Email
upMap["name"] = req.Name
if err := userService.Update(id, upMap); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
return
}
helper.SuccessWithData(c, nil)
}

func (b *BaseApi) GetUserInfo(c *gin.Context) {
id, err := helper.GetParamID(c)
if err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
return
}
user, err := userService.Get(id)
if err != nil {
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
return
}
helper.SuccessWithData(c, user)
}
27 changes: 27 additions & 0 deletions backend/app/dto/common_req.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package dto

type PageInfo struct {
Page int `json:"page" validate:"required,number"`
PageSize int `json:"pageSize" validate:"required,number"`
}

type OperationWithName struct {
Name string `json:"name" validate:"required"`
}

type BatchDeleteReq struct {
Ids []uint `json:"ids" validate:"required"`
}

type OperationWithNameAndType struct {
Name string `json:"name" validate:"required"`
Type string `json:"type" validate:"required"`
}

type Login struct {
Name string `json:"name" validate:"name,required"`
Password string `json:"password" validate:"required"`
Captcha string `json:"captcha"`
CaptchaID string `json:"captchaID"`
AuthMethod string `json:"authMethod"`
}
Loading