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
1 change: 1 addition & 0 deletions agent/app/api/v2/entry.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,4 +67,5 @@ var (

websiteCAService = service.NewIWebsiteCAService()
taskService = service.NewITaskService()
groupService = service.NewIGroupService()
)
96 changes: 96 additions & 0 deletions agent/app/api/v2/group.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
package v2

import (
"github.com/1Panel-dev/1Panel/agent/app/api/v2/helper"
"github.com/1Panel-dev/1Panel/agent/app/dto"
"github.com/gin-gonic/gin"
)

// @Tags System Group
// @Summary Create group
// @Accept json
// @Param request body dto.GroupCreate true "request"
// @Success 200
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /agent/groups [post]
// @x-panel-log {"bodyKeys":["name","type"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"创建组 [name][type]","formatEN":"create group [name][type]"}
func (b *BaseApi) CreateGroup(c *gin.Context) {
var req dto.GroupCreate
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}

if err := groupService.Create(req); err != nil {
helper.InternalServer(c, err)
return
}
helper.SuccessWithOutData(c)
}

// @Tags System Group
// @Summary Delete group
// @Accept json
// @Param request body dto.OperateByID true "request"
// @Success 200
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /agent/groups/del [post]
// @x-panel-log {"bodyKeys":["id"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"id","isList":false,"db":"groups","output_column":"name","output_value":"name"},{"input_column":"id","input_value":"id","isList":false,"db":"groups","output_column":"type","output_value":"type"}],"formatZH":"删除组 [type][name]","formatEN":"delete group [type][name]"}
func (b *BaseApi) DeleteGroup(c *gin.Context) {
var req dto.OperateByID
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}

if err := groupService.Delete(req.ID); err != nil {
helper.InternalServer(c, err)
return
}
helper.SuccessWithOutData(c)
}

// @Tags System Group
// @Summary Update group
// @Accept json
// @Param request body dto.GroupUpdate true "request"
// @Success 200
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /agent/groups/update [post]
// @x-panel-log {"bodyKeys":["name","type"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"更新组 [name][type]","formatEN":"update group [name][type]"}
func (b *BaseApi) UpdateGroup(c *gin.Context) {
var req dto.GroupUpdate
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}

if err := groupService.Update(req); err != nil {
helper.InternalServer(c, err)
return
}
helper.SuccessWithOutData(c)
}

// @Tags System Group
// @Summary List groups
// @Accept json
// @Param request body dto.GroupSearch true "request"
// @Success 200 {array} dto.OperateByType
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /agent/groups/search [post]
func (b *BaseApi) ListGroup(c *gin.Context) {
var req dto.OperateByType
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}

list, err := groupService.List(req)
if err != nil {
helper.InternalServer(c, err)
return
}

helper.SuccessWithData(c, list)
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are no apparent inconsistencies, issues, or optimizations necessary at this time. It appears that all functions in this package have been updated to adhere to current best practices and security measures. However, it's important to note there may be potential improvements based on more recent technology trends such as implementing JWT authentication for API key access management. This should not require any changes since the base structure is intact with respect to what was done up until September 1st, 2021.

29 changes: 29 additions & 0 deletions agent/app/dto/group.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package dto

type GroupCreate struct {
ID uint `json:"id"`
Name string `json:"name" validate:"required"`
Type string `json:"type" validate:"required"`
}

type GroupSearch struct {
Type string `json:"type" validate:"required"`
}

type GroupUpdate struct {
ID uint `json:"id"`
Name string `json:"name"`
Type string `json:"type" validate:"required"`
IsDefault bool `json:"isDefault"`
}

type GroupInfo struct {
ID uint `json:"id"`
Name string `json:"name"`
Type string `json:"type"`
IsDefault bool `json:"isDefault"`
}

type OperateByType struct {
Type string `json:"type"`
}
8 changes: 8 additions & 0 deletions agent/app/model/group.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package model

type Group struct {
BaseModel
IsDefault bool `json:"isDefault"`
Name string `json:"name"`
Type string `json:"type"`
}
56 changes: 56 additions & 0 deletions agent/app/repo/group.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package repo

import (
"github.com/1Panel-dev/1Panel/agent/app/model"
"github.com/1Panel-dev/1Panel/agent/global"
)

type GroupRepo struct{}

type IGroupRepo interface {
Get(opts ...DBOption) (model.Group, error)
GetList(opts ...DBOption) ([]model.Group, error)
Create(group *model.Group) error
Update(id uint, vars map[string]interface{}) error
Delete(opts ...DBOption) error
}

func NewIGroupRepo() IGroupRepo {
return &GroupRepo{}
}

func (g *GroupRepo) Get(opts ...DBOption) (model.Group, error) {
var group model.Group
db := global.DB
for _, opt := range opts {
db = opt(db)
}
err := db.First(&group).Error
return group, err
}

func (g *GroupRepo) GetList(opts ...DBOption) ([]model.Group, error) {
var groups []model.Group
db := global.DB.Model(&model.Group{})
for _, opt := range opts {
db = opt(db)
}
err := db.Find(&groups).Error
return groups, err
}

func (g *GroupRepo) Create(group *model.Group) error {
return global.DB.Create(group).Error
}

func (g *GroupRepo) Update(id uint, vars map[string]interface{}) error {
return global.DB.Model(&model.Group{}).Where("id = ?", id).Updates(vars).Error
}

func (g *GroupRepo) Delete(opts ...DBOption) error {
db := global.DB
for _, opt := range opts {
db = opt(db)
}
return db.Delete(&model.Group{}).Error
}
2 changes: 2 additions & 0 deletions agent/app/service/entry.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,4 +45,6 @@ var (
favoriteRepo = repo.NewIFavoriteRepo()

taskRepo = repo.NewITaskRepo()

groupRepo = repo.NewIGroupRepo()
)
87 changes: 87 additions & 0 deletions agent/app/service/group.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
package service

import (
"github.com/1Panel-dev/1Panel/agent/app/dto"
"github.com/1Panel-dev/1Panel/agent/app/model"
"github.com/1Panel-dev/1Panel/agent/app/repo"
"github.com/1Panel-dev/1Panel/agent/buserr"
"github.com/jinzhu/copier"
)

type GroupService struct{}

type IGroupService interface {
List(req dto.OperateByType) ([]dto.GroupInfo, error)
Create(req dto.GroupCreate) error
Update(req dto.GroupUpdate) error
Delete(id uint) error
}

func NewIGroupService() IGroupService {
return &GroupService{}
}

func (u *GroupService) List(req dto.OperateByType) ([]dto.GroupInfo, error) {
options := []repo.DBOption{
repo.WithOrderBy("is_default desc"),
repo.WithOrderBy("created_at desc"),
}
if len(req.Type) != 0 {
options = append(options, repo.WithByType(req.Type))
}
var (
groups []model.Group
err error
)
groups, err = groupRepo.GetList(options...)
if err != nil {
return nil, buserr.New("ErrRecordNotFound")
}
var dtoUsers []dto.GroupInfo
for _, group := range groups {
var item dto.GroupInfo
if err := copier.Copy(&item, &group); err != nil {
return nil, buserr.WithDetail("ErrStructTransform", err.Error(), nil)
}
dtoUsers = append(dtoUsers, item)
}
return dtoUsers, err
}

func (u *GroupService) Create(req dto.GroupCreate) error {
group, _ := groupRepo.Get(repo.WithByName(req.Name), repo.WithByType(req.Type))
if group.ID != 0 {
return buserr.New("ErrRecordExist")
}
if err := copier.Copy(&group, &req); err != nil {
return buserr.WithDetail("ErrStructTransform", err.Error(), nil)
}
if err := groupRepo.Create(&group); err != nil {
return err
}
return nil
}

func (u *GroupService) Delete(id uint) error {
group, _ := groupRepo.Get(repo.WithByID(id))
if group.ID == 0 {
return buserr.New("ErrRecordNotFound")
}
if group.IsDefault {
return buserr.New("ErrGroupIsDefault")
}
if group.Type == "website" {
websites, _ := websiteRepo.List(websiteRepo.WithGroupID(group.ID))
if len(websites) > 0 {
return buserr.New("ErrGroupIsInWebsiteUse")
}
}
return groupRepo.Delete(repo.WithByID(id))
}

func (u *GroupService) Update(req dto.GroupUpdate) error {
upMap := make(map[string]interface{})
upMap["name"] = req.Name
upMap["is_default"] = req.IsDefault
return groupRepo.Update(req.ID, upMap)
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here are the discrepancies and improvements:

  1. Package Name: The package name should be pkg/service instead of service as service is already used for the Service type.

  2. Types:

    • Change from IGroupService to IGroupProvider.
    import (
        ...
         // Other imports 
        
         "github.com/1Panel-dev/1Panel/core/services/iprovider"

)

   
   In this context, it will also help if there's a corresponding struct named `IGroupProvider` that implements the same functions.

3. Function Names: Functions like `List`, `Create`, have redundant names because they are being imported twice by mistake. This causes redundancy in function imports. Also these functions don't implement any logic at all and can therefore be removed completely since Go doesn't allow duplicate public export per file but allows each different file with its own namespace.

4. Type Annotation (`dto.GroupInfo`) has been repeated throughout the code which may lead to confusion when importing other packages where you might expect similar types such as `dto.BaseResponse`, `*DtoSomething`. It would improve readability to only use one annotation on every occurrence.

5. Variable Declaration order: Ensure variables are declared in ascending order, based on their usage, especially in interfaces and structs.

6. Use case: Implement proper error handling methods around the APIs calls including checking return codes, error propagation etc

7. Code comments: If not implemented, add simple documentation about what each function does to ensure it works appropriately even without extensive testing.

Suggestion: Consider adding test cases to the various methods. Testing helps identify edge cases and makes sure everything is working properly before deploying publicly.

Remember this is just a basic level review. Depending upon project requirements more in-depth reviews could be applicable.

2 changes: 2 additions & 0 deletions agent/i18n/lang/en.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ ErrTypePort: "Port {{ .name }} format error"
Success: "Success"
Failed: "Failed"
SystemRestart: "System restart causes task interruption"
ErrGroupIsDefault: "Default group, cannot be deleted"
ErrGroupIsInWebsiteUse: "Group is being used by other websites, cannot be deleted"

#backup
ErrBackupLocalDelete: "Deleting local server backup accounts is not currently supported."
Expand Down
2 changes: 2 additions & 0 deletions agent/i18n/lang/ja.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ ErrTypePortRange: 'ポートレンジは1-65535の間である必要がありま
Success: "成功"
Failed: "失敗した"
SystemRestart: "システムの再起動により、タスクが中断されます"
ErrGroupIsDefault: "デフォルトグループ、削除できません"
ErrGroupIsInWebsiteUse: "グループは他のウェブサイトで使用されています、削除できません"

#app
ErrPortInUsed: "{{.Detail}}ポートはすでに使用されています"
Expand Down
2 changes: 2 additions & 0 deletions agent/i18n/lang/ko.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ ErrTypePortRange: '포트 범위는 1-65535 사이여야 합니다'
Success: "성공"
Failed: "실패"
SystemRestart: "시스템 재시작으로 인해 작업이 중단되었습니다"
ErrGroupIsDefault: "기본 그룹, 삭제할 수 없습니다"
ErrGroupIsInWebsiteUse: "그룹이 다른 웹사이트에서 사용 중입니다, 삭제할 수 없습니다"

# 애플리케이션
ErrPortInUsed: "{{ .detail }} 포트가 이미 사용 중입니다"
Expand Down
2 changes: 2 additions & 0 deletions agent/i18n/lang/ms.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ ErrTypePortRange: 'Julat port perlu berada di antara 1-65535'
Success: "Berjaya"
Failed: "Gagal"
SystemRestart: "Mulakan semula sistem menyebabkan gangguan tugas"
ErrGroupIsDefault: "Kumpulan lalai, tidak boleh dipadam"
ErrGroupIsInWebsiteUse: "Kumpulan sedang digunakan oleh laman web lain, tidak boleh dipadam"

#app
ErrPortInUsed: "Port {{ .detail }} sudah digunakan"
Expand Down
2 changes: 2 additions & 0 deletions agent/i18n/lang/pt-BR.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ ErrTypePortRange: 'O intervalo da porta deve estar entre 1-65535'
Success: "Sucesso"
Failed: "Falhou"
SystemRestart: "A reinicialização do sistema causa interrupção da tarefa"
ErrGroupIsDefault: "Grupo padrão, não pode ser excluído"
ErrGroupIsInWebsiteUse: "O grupo está sendo usado por outros sites, não pode ser excluído"

#app
ErrPortInUsed: "A porta {{ .detail }} já está em uso"
Expand Down
2 changes: 2 additions & 0 deletions agent/i18n/lang/ru.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ ErrTypePortRange: "Диапазон портов должен быть межд
Success: "Успех"
Failed: "Неудача"
SystemRestart: "Перезагрузка системы приводит к прерыванию задачи"
ErrGroupIsDefault: "Группа по умолчанию, невозможно удалить"
ErrGroupIsInWebsiteUse: "Группа используется другими сайтами, невозможно удалить"

#app
ErrPortInUsed: "Порт {{ .detail }} уже используется"
Expand Down
2 changes: 2 additions & 0 deletions agent/i18n/lang/zh-Hant.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ Success: "成功"
Failed: "失敗"
SystemRestart: "系統重啟導致任務中斷"
ErrInvalidChar: "禁止使用非法字元"
ErrGroupIsDefault: "預設分組,無法刪除"
ErrGroupIsInWebsiteUse: "分組正在被其他網站使用,無法刪除"

#backup
ErrBackupLocalDelete: "暫不支持刪除本地伺服器備份帳號"
Expand Down
2 changes: 2 additions & 0 deletions agent/i18n/lang/zh.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ ErrTypePortRange: '端口范围需要在 1-65535 之间'
Success: "成功"
Failed: "失败"
SystemRestart: "系统重启导致任务中断"
ErrGroupIsDefault: "默认分组,无法删除"
ErrGroupIsInWebsiteUse: "分组正在被其他网站使用,无法删除"

#backup
ErrBackupInUsed: "该备份账号已在计划任务中使用,无法删除"
Expand Down
1 change: 1 addition & 0 deletions agent/init/migration/migrate.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ func InitAgentDB() {
migrations.UpdateApp,
migrations.AddOllamaModel,
migrations.UpdateSettingStatus,
migrations.InitDefault,
})
if err := m.Migrate(); err != nil {
global.LOG.Error(err)
Expand Down
11 changes: 11 additions & 0 deletions agent/init/migration/migrations/init.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ var AddTable = &gormigrate.Migration{
&model.WebsiteDnsAccount{},
&model.WebsiteDomain{},
&model.WebsiteSSL{},
&model.Group{},
)
},
}
Expand Down Expand Up @@ -285,3 +286,13 @@ var UpdateSettingStatus = &gormigrate.Migration{
return nil
},
}

var InitDefault = &gormigrate.Migration{
ID: "20250301-init-default",
Migrate: func(tx *gorm.DB) error {
if err := tx.Create(&model.Group{Name: "Default", Type: "website", IsDefault: true}).Error; err != nil {
return err
}
return nil
},
}
Loading
Loading