diff --git a/backend/app/api/v1/entry.go b/backend/app/api/v1/entry.go index 058dd497b..f1638c09f 100644 --- a/backend/app/api/v1/entry.go +++ b/backend/app/api/v1/entry.go @@ -21,10 +21,10 @@ var ( imageService = service.NewIImageService() dockerService = service.NewIDockerService() - mysqlService = service.NewIMysqlService() - postgresqlService = service.NewIPostgresqlService() - databaseService = service.NewIDatabaseService() - redisService = service.NewIRedisService() + mysqlService = service.NewIMysqlService() + postgresqlService = service.NewIPostgresqlService() + databaseService = service.NewIDatabaseService() + redisService = service.NewIRedisService() cronjobService = service.NewICronjobService() @@ -53,8 +53,9 @@ var ( snapshotService = service.NewISnapshotService() upgradeService = service.NewIUpgradeService() - runtimeService = service.NewRuntimeService() - processService = service.NewIProcessService() + runtimeService = service.NewRuntimeService() + processService = service.NewIProcessService() + phpExtensionsService = service.NewIPHPExtensionsService() hostToolService = service.NewIHostToolService() diff --git a/backend/app/api/v1/php_extensions.go b/backend/app/api/v1/php_extensions.go new file mode 100644 index 000000000..9af31f4f1 --- /dev/null +++ b/backend/app/api/v1/php_extensions.go @@ -0,0 +1,103 @@ +package v1 + +import ( + "github.com/1Panel-dev/1Panel/backend/app/api/v1/helper" + "github.com/1Panel-dev/1Panel/backend/app/dto" + "github.com/1Panel-dev/1Panel/backend/app/dto/request" + "github.com/1Panel-dev/1Panel/backend/constant" + "github.com/gin-gonic/gin" +) + +// @Tags PHP Extensions +// @Summary Page Extensions +// @Description Page Extensions +// @Accept json +// @Param request body request.PHPExtensionsSearch true "request" +// @Success 200 {array} response.PHPExtensionsDTO +// @Security ApiKeyAuth +// @Router /runtimes/php/extensions/search [post] +func (b *BaseApi) PagePHPExtensions(c *gin.Context) { + var req request.PHPExtensionsSearch + if err := helper.CheckBindAndValidate(&req, c); err != nil { + return + } + if req.All { + list, err := phpExtensionsService.List() + if err != nil { + helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) + return + } + helper.SuccessWithData(c, list) + } else { + total, list, err := phpExtensionsService.Page(req) + if err != nil { + helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) + return + } + helper.SuccessWithData(c, dto.PageResult{ + Total: total, + Items: list, + }) + } + +} + +// @Tags PHP Extensions +// @Summary Create Extensions +// @Description Create Extensions +// @Accept json +// @Param request body request.PHPExtensionsCreate true "request" +// @Success 200 +// @Security ApiKeyAuth +// @Router /runtimes/php/extensions [post] +func (b *BaseApi) CreatePHPExtensions(c *gin.Context) { + var req request.PHPExtensionsCreate + if err := helper.CheckBindAndValidate(&req, c); err != nil { + return + } + if err := phpExtensionsService.Create(req); err != nil { + helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) + return + } + helper.SuccessWithOutData(c) +} + +// @Tags PHP Extensions +// @Summary Update Extensions +// @Description Update Extensions +// @Accept json +// @Param request body request.PHPExtensionsUpdate true "request" +// @Success 200 +// @Security ApiKeyAuth +// @Router /runtimes/php/extensions/update [post] +func (b *BaseApi) UpdatePHPExtensions(c *gin.Context) { + var req request.PHPExtensionsUpdate + if err := helper.CheckBindAndValidate(&req, c); err != nil { + return + } + if err := phpExtensionsService.Update(req); err != nil { + helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) + return + } + helper.SuccessWithOutData(c) +} + +// @Tags PHP Extensions +// @Summary Delete Extensions +// @Description Delete Extensions +// @Accept json +// @Param request body request.PHPExtensionsDelete true "request" +// @Success 200 +// @Security ApiKeyAuth +// @Router /runtimes/php/extensions/del [post] +func (b *BaseApi) DeletePHPExtensions(c *gin.Context) { + var req request.PHPExtensionsDelete + if err := helper.CheckBindAndValidate(&req, c); err != nil { + return + } + if err := phpExtensionsService.Delete(req); err != nil { + helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) + return + } + helper.SuccessWithOutData(c) +} diff --git a/backend/app/dto/request/php_extensions.go b/backend/app/dto/request/php_extensions.go new file mode 100644 index 000000000..a163859ff --- /dev/null +++ b/backend/app/dto/request/php_extensions.go @@ -0,0 +1,22 @@ +package request + +import "github.com/1Panel-dev/1Panel/backend/app/dto" + +type PHPExtensionsSearch struct { + dto.PageInfo + All bool `json:"all"` +} + +type PHPExtensionsCreate struct { + Name string `json:"name" validate:"required"` + Extensions string `json:"extensions" validate:"required"` +} + +type PHPExtensionsUpdate struct { + ID uint `json:"id" validate:"required"` + Extensions string `json:"extensions" validate:"required"` +} + +type PHPExtensionsDelete struct { + ID uint `json:"id" validate:"required"` +} diff --git a/backend/app/dto/response/php_extensions.go b/backend/app/dto/response/php_extensions.go new file mode 100644 index 000000000..91a96f0d2 --- /dev/null +++ b/backend/app/dto/response/php_extensions.go @@ -0,0 +1,7 @@ +package response + +import "github.com/1Panel-dev/1Panel/backend/app/model" + +type PHPExtensionsDTO struct { + model.PHPExtensions +} diff --git a/backend/app/model/php_extensions.go b/backend/app/model/php_extensions.go new file mode 100644 index 000000000..0055bd258 --- /dev/null +++ b/backend/app/model/php_extensions.go @@ -0,0 +1,7 @@ +package model + +type PHPExtensions struct { + BaseModel + Name string ` json:"name" gorm:"not null"` + Extensions string `json:"extensions" gorm:"not null"` +} diff --git a/backend/app/repo/php_extensions.go b/backend/app/repo/php_extensions.go new file mode 100644 index 000000000..81da5f364 --- /dev/null +++ b/backend/app/repo/php_extensions.go @@ -0,0 +1,59 @@ +package repo + +import ( + "github.com/1Panel-dev/1Panel/backend/app/model" +) + +type PHPExtensionsRepo struct { +} + +type IPHPExtensionsRepo interface { + Page(page, size int, opts ...DBOption) (int64, []model.PHPExtensions, error) + Save(extension *model.PHPExtensions) error + Create(extension *model.PHPExtensions) error + GetFirst(opts ...DBOption) (model.PHPExtensions, error) + DeleteBy(opts ...DBOption) error + List() ([]model.PHPExtensions, error) +} + +func NewIPHPExtensionsRepo() IPHPExtensionsRepo { + return &PHPExtensionsRepo{} +} + +func (p *PHPExtensionsRepo) Page(page, size int, opts ...DBOption) (int64, []model.PHPExtensions, error) { + var ( + phpExtensions []model.PHPExtensions + ) + db := getDb(opts...).Model(&model.PHPExtensions{}) + count := int64(0) + db = db.Count(&count) + err := db.Limit(size).Offset(size * (page - 1)).Find(&phpExtensions).Error + return count, phpExtensions, err +} + +func (p *PHPExtensionsRepo) List() ([]model.PHPExtensions, error) { + var ( + phpExtensions []model.PHPExtensions + ) + err := getDb().Model(&model.PHPExtensions{}).Find(&phpExtensions).Error + return phpExtensions, err +} + +func (p *PHPExtensionsRepo) Save(extension *model.PHPExtensions) error { + return getDb().Save(&extension).Error +} + +func (p *PHPExtensionsRepo) Create(extension *model.PHPExtensions) error { + return getDb().Create(&extension).Error +} + +func (p *PHPExtensionsRepo) GetFirst(opts ...DBOption) (model.PHPExtensions, error) { + var extension model.PHPExtensions + db := getDb(opts...).Model(&model.PHPExtensions{}) + err := db.First(&extension).Error + return extension, err +} + +func (p *PHPExtensionsRepo) DeleteBy(opts ...DBOption) error { + return getDb(opts...).Delete(&model.PHPExtensions{}).Error +} diff --git a/backend/app/service/entry.go b/backend/app/service/entry.go index 4b2956eb3..bb97578a3 100644 --- a/backend/app/service/entry.go +++ b/backend/app/service/entry.go @@ -12,9 +12,9 @@ var ( appInstallRepo = repo.NewIAppInstallRepo() appInstallResourceRepo = repo.NewIAppInstallResourceRpo() - mysqlRepo = repo.NewIMysqlRepo() - postgresqlRepo = repo.NewIPostgresqlRepo() - databaseRepo = repo.NewIDatabaseRepo() + mysqlRepo = repo.NewIMysqlRepo() + postgresqlRepo = repo.NewIPostgresqlRepo() + databaseRepo = repo.NewIDatabaseRepo() imageRepoRepo = repo.NewIImageRepoRepo() composeRepo = repo.NewIComposeTemplateRepo() @@ -38,7 +38,8 @@ var ( logRepo = repo.NewILogRepo() snapshotRepo = repo.NewISnapshotRepo() - runtimeRepo = repo.NewIRunTimeRepo() + runtimeRepo = repo.NewIRunTimeRepo() + phpExtensionsRepo = repo.NewIPHPExtensionsRepo() favoriteRepo = repo.NewIFavoriteRepo() ) diff --git a/backend/app/service/php_extensions.go b/backend/app/service/php_extensions.go new file mode 100644 index 000000000..665d71857 --- /dev/null +++ b/backend/app/service/php_extensions.go @@ -0,0 +1,86 @@ +package service + +import ( + "github.com/1Panel-dev/1Panel/backend/app/dto/request" + "github.com/1Panel-dev/1Panel/backend/app/dto/response" + "github.com/1Panel-dev/1Panel/backend/app/model" + "github.com/1Panel-dev/1Panel/backend/buserr" + "github.com/1Panel-dev/1Panel/backend/constant" +) + +type PHPExtensionsService struct { +} + +type IPHPExtensionsService interface { + Page(req request.PHPExtensionsSearch) (int64, []response.PHPExtensionsDTO, error) + List() ([]response.PHPExtensionsDTO, error) + Create(req request.PHPExtensionsCreate) error + Update(req request.PHPExtensionsUpdate) error + Delete(req request.PHPExtensionsDelete) error +} + +func NewIPHPExtensionsService() IPHPExtensionsService { + return &PHPExtensionsService{} +} + +func (p PHPExtensionsService) Page(req request.PHPExtensionsSearch) (int64, []response.PHPExtensionsDTO, error) { + var ( + total int64 + extensions []model.PHPExtensions + err error + result []response.PHPExtensionsDTO + ) + total, extensions, err = phpExtensionsRepo.Page(req.Page, req.PageSize) + if err != nil { + return 0, nil, err + } + for _, extension := range extensions { + result = append(result, response.PHPExtensionsDTO{ + PHPExtensions: extension, + }) + } + return total, result, nil +} + +func (p PHPExtensionsService) List() ([]response.PHPExtensionsDTO, error) { + var ( + extensions []model.PHPExtensions + err error + result []response.PHPExtensionsDTO + ) + extensions, err = phpExtensionsRepo.List() + if err != nil { + return nil, err + } + for _, extension := range extensions { + result = append(result, response.PHPExtensionsDTO{ + PHPExtensions: extension, + }) + } + return result, nil +} + +func (p PHPExtensionsService) Create(req request.PHPExtensionsCreate) error { + exist, _ := phpExtensionsRepo.GetFirst(commonRepo.WithByName(req.Name)) + if exist.ID == 0 { + return buserr.New(constant.ErrNameIsExist) + } + extension := model.PHPExtensions{ + Name: req.Name, + Extensions: req.Extensions, + } + return phpExtensionsRepo.Create(&extension) +} + +func (p PHPExtensionsService) Update(req request.PHPExtensionsUpdate) error { + exist, err := phpExtensionsRepo.GetFirst(commonRepo.WithByID(req.ID)) + if err != nil { + return err + } + exist.Extensions = req.Extensions + return phpExtensionsRepo.Save(&exist) +} + +func (p PHPExtensionsService) Delete(req request.PHPExtensionsDelete) error { + return phpExtensionsRepo.DeleteBy(commonRepo.WithByID(req.ID)) +} diff --git a/backend/init/migration/migrate.go b/backend/init/migration/migrate.go index 8380cad7f..aaf2d1647 100644 --- a/backend/init/migration/migrate.go +++ b/backend/init/migration/migrate.go @@ -62,6 +62,8 @@ func Init() { migrations.AddDefaultCA, migrations.AddSettingRecycleBin, migrations.UpdateWebsiteBackupRecord, + + migrations.AddTablePHPExtensions, }) if err := m.Migrate(); err != nil { global.LOG.Error(err) diff --git a/backend/init/migration/migrations/v_1_9.go b/backend/init/migration/migrations/v_1_9.go index 2c212b621..cba434b6b 100644 --- a/backend/init/migration/migrations/v_1_9.go +++ b/backend/init/migration/migrations/v_1_9.go @@ -103,3 +103,16 @@ var UpdateWebsiteBackupRecord = &gormigrate.Migration{ return nil }, } + +var AddTablePHPExtensions = &gormigrate.Migration{ + ID: "20240102-add-php-extensions", + Migrate: func(tx *gorm.DB) error { + if err := tx.AutoMigrate(&model.PHPExtensions{}); err != nil { + return err + } + if err := tx.Create(&model.PHPExtensions{Name: "默认", Extensions: "bcmath,gd,gettext,intl,pcntl,shmop,soap,sockets,sysvsem,xmlrpc,zip"}).Error; err != nil { + return err + } + return nil + }, +} diff --git a/backend/router/ro_runtime.go b/backend/router/ro_runtime.go index c43a3c170..e77ada55b 100644 --- a/backend/router/ro_runtime.go +++ b/backend/router/ro_runtime.go @@ -20,10 +20,16 @@ func (r *RuntimeRouter) InitRouter(Router *gin.RouterGroup) { groupRouter.POST("/del", baseApi.DeleteRuntime) groupRouter.POST("/update", baseApi.UpdateRuntime) groupRouter.GET("/:id", baseApi.GetRuntime) + groupRouter.POST("/node/package", baseApi.GetNodePackageRunScript) groupRouter.POST("/operate", baseApi.OperateRuntime) groupRouter.POST("/node/modules", baseApi.GetNodeModules) groupRouter.POST("/node/modules/operate", baseApi.OperateNodeModules) + + groupRouter.POST("/php/extensions/search", baseApi.PagePHPExtensions) + groupRouter.POST("/php/extensions", baseApi.CreatePHPExtensions) + groupRouter.POST("/php/extensions/update", baseApi.UpdatePHPExtensions) + groupRouter.POST("/php/extensions/del", baseApi.DeletePHPExtensions) } } diff --git a/cmd/server/docs/docs.go b/cmd/server/docs/docs.go index cc84b0314..7f9a3d3e3 100644 --- a/cmd/server/docs/docs.go +++ b/cmd/server/docs/docs.go @@ -8995,6 +8995,144 @@ const docTemplate = `{ } } }, + "/runtimes/php/extensions": { + "post": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "description": "Create Extensions", + "consumes": [ + "application/json" + ], + "tags": [ + "PHP Extensions" + ], + "summary": "Create Extensions", + "parameters": [ + { + "description": "request", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/request.PHPExtensionsCreate" + } + } + ], + "responses": { + "200": { + "description": "OK" + } + } + } + }, + "/runtimes/php/extensions/del": { + "post": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "description": "Delete Extensions", + "consumes": [ + "application/json" + ], + "tags": [ + "PHP Extensions" + ], + "summary": "Delete Extensions", + "parameters": [ + { + "description": "request", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/request.PHPExtensionsDelete" + } + } + ], + "responses": { + "200": { + "description": "OK" + } + } + } + }, + "/runtimes/php/extensions/search": { + "post": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "description": "Page Extensions", + "consumes": [ + "application/json" + ], + "tags": [ + "PHP Extensions" + ], + "summary": "Page Extensions", + "parameters": [ + { + "description": "request", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/request.PHPExtensionsSearch" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/response.PHPExtensionsDTO" + } + } + } + } + } + }, + "/runtimes/php/extensions/update": { + "post": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "description": "Update Extensions", + "consumes": [ + "application/json" + ], + "tags": [ + "PHP Extensions" + ], + "summary": "Update Extensions", + "parameters": [ + { + "description": "request", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/request.PHPExtensionsUpdate" + } + } + ], + "responses": { + "200": { + "description": "OK" + } + } + } + }, "/runtimes/search": { "post": { "security": [ @@ -19390,6 +19528,65 @@ const docTemplate = `{ } } }, + "request.PHPExtensionsCreate": { + "type": "object", + "required": [ + "extensions", + "name" + ], + "properties": { + "extensions": { + "type": "string" + }, + "name": { + "type": "string" + } + } + }, + "request.PHPExtensionsDelete": { + "type": "object", + "required": [ + "id" + ], + "properties": { + "id": { + "type": "integer" + } + } + }, + "request.PHPExtensionsSearch": { + "type": "object", + "required": [ + "page", + "pageSize" + ], + "properties": { + "all": { + "type": "boolean" + }, + "page": { + "type": "integer" + }, + "pageSize": { + "type": "integer" + } + } + }, + "request.PHPExtensionsUpdate": { + "type": "object", + "required": [ + "extensions", + "id" + ], + "properties": { + "extensions": { + "type": "string" + }, + "id": { + "type": "integer" + } + } + }, "request.PortUpdate": { "type": "object", "properties": { @@ -20915,6 +21112,26 @@ const docTemplate = `{ } } }, + "response.PHPExtensionsDTO": { + "type": "object", + "properties": { + "createdAt": { + "type": "string" + }, + "extensions": { + "type": "string" + }, + "id": { + "type": "integer" + }, + "name": { + "type": "string" + }, + "updatedAt": { + "type": "string" + } + } + }, "response.WebsiteAcmeAccountDTO": { "type": "object", "properties": { diff --git a/cmd/server/docs/swagger.json b/cmd/server/docs/swagger.json index 7a3fcbdf4..5b5a7929f 100644 --- a/cmd/server/docs/swagger.json +++ b/cmd/server/docs/swagger.json @@ -8988,6 +8988,144 @@ } } }, + "/runtimes/php/extensions": { + "post": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "description": "Create Extensions", + "consumes": [ + "application/json" + ], + "tags": [ + "PHP Extensions" + ], + "summary": "Create Extensions", + "parameters": [ + { + "description": "request", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/request.PHPExtensionsCreate" + } + } + ], + "responses": { + "200": { + "description": "OK" + } + } + } + }, + "/runtimes/php/extensions/del": { + "post": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "description": "Delete Extensions", + "consumes": [ + "application/json" + ], + "tags": [ + "PHP Extensions" + ], + "summary": "Delete Extensions", + "parameters": [ + { + "description": "request", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/request.PHPExtensionsDelete" + } + } + ], + "responses": { + "200": { + "description": "OK" + } + } + } + }, + "/runtimes/php/extensions/search": { + "post": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "description": "Page Extensions", + "consumes": [ + "application/json" + ], + "tags": [ + "PHP Extensions" + ], + "summary": "Page Extensions", + "parameters": [ + { + "description": "request", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/request.PHPExtensionsSearch" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/response.PHPExtensionsDTO" + } + } + } + } + } + }, + "/runtimes/php/extensions/update": { + "post": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "description": "Update Extensions", + "consumes": [ + "application/json" + ], + "tags": [ + "PHP Extensions" + ], + "summary": "Update Extensions", + "parameters": [ + { + "description": "request", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/request.PHPExtensionsUpdate" + } + } + ], + "responses": { + "200": { + "description": "OK" + } + } + } + }, "/runtimes/search": { "post": { "security": [ @@ -19383,6 +19521,65 @@ } } }, + "request.PHPExtensionsCreate": { + "type": "object", + "required": [ + "extensions", + "name" + ], + "properties": { + "extensions": { + "type": "string" + }, + "name": { + "type": "string" + } + } + }, + "request.PHPExtensionsDelete": { + "type": "object", + "required": [ + "id" + ], + "properties": { + "id": { + "type": "integer" + } + } + }, + "request.PHPExtensionsSearch": { + "type": "object", + "required": [ + "page", + "pageSize" + ], + "properties": { + "all": { + "type": "boolean" + }, + "page": { + "type": "integer" + }, + "pageSize": { + "type": "integer" + } + } + }, + "request.PHPExtensionsUpdate": { + "type": "object", + "required": [ + "extensions", + "id" + ], + "properties": { + "extensions": { + "type": "string" + }, + "id": { + "type": "integer" + } + } + }, "request.PortUpdate": { "type": "object", "properties": { @@ -20908,6 +21105,26 @@ } } }, + "response.PHPExtensionsDTO": { + "type": "object", + "properties": { + "createdAt": { + "type": "string" + }, + "extensions": { + "type": "string" + }, + "id": { + "type": "integer" + }, + "name": { + "type": "string" + }, + "updatedAt": { + "type": "string" + } + } + }, "response.WebsiteAcmeAccountDTO": { "type": "object", "properties": { diff --git a/cmd/server/docs/swagger.yaml b/cmd/server/docs/swagger.yaml index bc20e3b66..a0d93370f 100644 --- a/cmd/server/docs/swagger.yaml +++ b/cmd/server/docs/swagger.yaml @@ -3706,6 +3706,45 @@ definitions: codeDir: type: string type: object + request.PHPExtensionsCreate: + properties: + extensions: + type: string + name: + type: string + required: + - extensions + - name + type: object + request.PHPExtensionsDelete: + properties: + id: + type: integer + required: + - id + type: object + request.PHPExtensionsSearch: + properties: + all: + type: boolean + page: + type: integer + pageSize: + type: integer + required: + - page + - pageSize + type: object + request.PHPExtensionsUpdate: + properties: + extensions: + type: string + id: + type: integer + required: + - extensions + - id + type: object request.PortUpdate: properties: key: @@ -4732,6 +4771,19 @@ definitions: uploadMaxSize: type: string type: object + response.PHPExtensionsDTO: + properties: + createdAt: + type: string + extensions: + type: string + id: + type: integer + name: + type: string + updatedAt: + type: string + type: object response.WebsiteAcmeAccountDTO: properties: createdAt: @@ -10612,6 +10664,90 @@ paths: formatEN: Operate runtime [name] formatZH: 操作运行环境 [name] paramKeys: [] + /runtimes/php/extensions: + post: + consumes: + - application/json + description: Create Extensions + parameters: + - description: request + in: body + name: request + required: true + schema: + $ref: '#/definitions/request.PHPExtensionsCreate' + responses: + "200": + description: OK + security: + - ApiKeyAuth: [] + summary: Create Extensions + tags: + - PHP Extensions + /runtimes/php/extensions/del: + post: + consumes: + - application/json + description: Delete Extensions + parameters: + - description: request + in: body + name: request + required: true + schema: + $ref: '#/definitions/request.PHPExtensionsDelete' + responses: + "200": + description: OK + security: + - ApiKeyAuth: [] + summary: Delete Extensions + tags: + - PHP Extensions + /runtimes/php/extensions/search: + post: + consumes: + - application/json + description: Page Extensions + parameters: + - description: request + in: body + name: request + required: true + schema: + $ref: '#/definitions/request.PHPExtensionsSearch' + responses: + "200": + description: OK + schema: + items: + $ref: '#/definitions/response.PHPExtensionsDTO' + type: array + security: + - ApiKeyAuth: [] + summary: Page Extensions + tags: + - PHP Extensions + /runtimes/php/extensions/update: + post: + consumes: + - application/json + description: Update Extensions + parameters: + - description: request + in: body + name: request + required: true + schema: + $ref: '#/definitions/request.PHPExtensionsUpdate' + responses: + "200": + description: OK + security: + - ApiKeyAuth: [] + summary: Update Extensions + tags: + - PHP Extensions /runtimes/search: post: consumes: diff --git a/frontend/src/api/interface/runtime.ts b/frontend/src/api/interface/runtime.ts index 8fc913ecb..228b219d5 100644 --- a/frontend/src/api/interface/runtime.ts +++ b/frontend/src/api/interface/runtime.ts @@ -97,4 +97,29 @@ export namespace Runtime { Module?: string; PkgManager?: string; } + + export interface PHPExtensions extends CommonModel { + id: number; + name: string; + extensions: string; + } + + export interface PHPExtensionsList extends ReqPage { + all: boolean; + } + + export interface PHPExtensionsCreate { + name: string; + extensions: string; + } + + export interface PHPExtensionsUpdate { + id: number; + name: string; + extensions: string; + } + + export interface PHPExtensionsDelete { + id: number; + } } diff --git a/frontend/src/api/modules/runtime.ts b/frontend/src/api/modules/runtime.ts index d09bfff2a..8562b6692 100644 --- a/frontend/src/api/modules/runtime.ts +++ b/frontend/src/api/modules/runtime.ts @@ -1,5 +1,5 @@ import http from '@/api'; -import { ResPage } from '../interface'; +import { ResPage, ReqPage } from '../interface'; import { Runtime } from '../interface/runtime'; import { TimeoutEnum } from '@/enums/http-enum'; @@ -38,3 +38,23 @@ export const GetNodeModules = (req: Runtime.NodeModuleReq) => { export const OperateNodeModule = (req: Runtime.NodeModuleReq) => { return http.post(`/runtimes/node/modules/operate`, req, TimeoutEnum.T_10M); }; + +export const SearchPHPExtensions = (req: ReqPage) => { + return http.post>(`/runtimes/php/extensions/search`, req); +}; + +export const ListPHPExtensions = (req: Runtime.PHPExtensionsList) => { + return http.post(`/runtimes/php/extensions/search`, req); +}; + +export const CreatePHPExtensions = (req: Runtime.PHPExtensionsCreate) => { + return http.post(`/runtimes/php/extensions`, req); +}; + +export const UpdatePHPExtensions = (req: Runtime.PHPExtensionsUpdate) => { + return http.post(`/runtimes/php/extensions/update`, req); +}; + +export const DeletePHPExtensions = (req: Runtime.PHPExtensionsDelete) => { + return http.post(`/runtimes/php/extensions/del`, req); +}; diff --git a/frontend/src/global/form-rules.ts b/frontend/src/global/form-rules.ts index 6c3b58c44..cae019b0d 100644 --- a/frontend/src/global/form-rules.ts +++ b/frontend/src/global/form-rules.ts @@ -474,6 +474,19 @@ const checkFilePermission = (rule, value, callback) => { } }; +const checkPHPExtensions = (rule, value, callback) => { + if (value === '' || typeof value === 'undefined' || value == null) { + callback(new Error(i18n.global.t('commons.rule.phpExtension'))); + } else { + const reg = /^[a-z0-9,_]{3,300}$/; + if (!reg.test(value)) { + callback(new Error(i18n.global.t('commons.rule.phpExtension'))); + } else { + callback(); + } + } +}; + interface CommonRule { requiredInput: FormItemRule; requiredSelect: FormItemRule; @@ -507,6 +520,7 @@ interface CommonRule { leechExts: FormItemRule; domainWithPort: FormItemRule; filePermission: FormItemRule; + phpExtensions: FormItemRule; paramCommon: FormItemRule; paramComplexity: FormItemRule; @@ -711,4 +725,9 @@ export const Rules: CommonRule = { validator: checkFilePermission, trigger: 'blur', }, + phpExtensions: { + required: true, + validator: checkPHPExtensions, + trigger: 'blur', + }, }; diff --git a/frontend/src/lang/modules/en.ts b/frontend/src/lang/modules/en.ts index 9ccc67588..471bb81db 100644 --- a/frontend/src/lang/modules/en.ts +++ b/frontend/src/lang/modules/en.ts @@ -191,6 +191,7 @@ const message = { paramSimple: 'Support lowercase letters and numbers, length 1-128', filePermission: 'File Permission Error', formatErr: 'Format error, please check and retry', + phpExtension: 'Only supports , _ lowercase English and numbers', }, res: { paramError: 'The request failed, please try again later!', @@ -1839,6 +1840,10 @@ const message = { uploadMaxSize: 'Upload limit', indexHelper: 'In order to ensure the normal operation of the PHP website, please place the code in the index directory and avoid renaming', + extensions: 'Extension template', + extension: 'Extension', + extensionHelper: 'Please use multiple extensions, split', + toExtensionsList: 'View extension list', }, nginx: { serverNamesHashBucketSizeHelper: 'The hash table size of the server name', diff --git a/frontend/src/lang/modules/tw.ts b/frontend/src/lang/modules/tw.ts index 8a8f0d93c..c389a6656 100644 --- a/frontend/src/lang/modules/tw.ts +++ b/frontend/src/lang/modules/tw.ts @@ -190,6 +190,7 @@ const message = { paramSimple: '支持小寫字母和數字,長度 1-128', filePermission: '權限錯誤', formatErr: '格式錯誤,檢查後重試', + phpExtension: '僅支持 , _ 小寫英文和數字', }, res: { paramError: '請求失敗,請稍後重試!', @@ -1725,6 +1726,10 @@ const message = { disableFunctionHelper: '輸入要禁用的函數,例如exec,多個請用,分割', uploadMaxSize: '上傳限製', indexHelper: '為保障PHP網站正常運行,請將代碼放置於 index 目錄,並避免重命名', + extensions: '擴充範本', + extension: '擴充', + extensionHelper: '多個擴充功能,分割', + toExtensionsList: '檢視擴充清單', }, nginx: { serverNamesHashBucketSizeHelper: '服務器名字的hash表大小', diff --git a/frontend/src/lang/modules/zh.ts b/frontend/src/lang/modules/zh.ts index 32ca4d837..f419b3ae2 100644 --- a/frontend/src/lang/modules/zh.ts +++ b/frontend/src/lang/modules/zh.ts @@ -190,6 +190,7 @@ const message = { paramSimple: '支持小写字母和数字,长度1-128', filePermission: '权限错误', formatErr: '格式错误,检查后重试', + phpExtension: '仅支持 , _ 小写英文和数字', }, res: { paramError: '请求失败,请稍后重试!', @@ -1725,6 +1726,10 @@ const message = { disableFunctionHelper: '输入要禁用的函数,例如exec,多个请用,分割', uploadMaxSize: '上传限制', indexHelper: '为保障 PHP 网站正常运行,请将代码放置于主目录下的 index 目录,并避免重命名', + extensions: '扩展模版', + extension: '扩展', + extensionsHelper: '多个扩展请用,分割', + toExtensionsList: '查看扩展列表', }, nginx: { serverNamesHashBucketSizeHelper: '服务器名字的hash表大小', diff --git a/frontend/src/views/website/runtime/php/create/index.vue b/frontend/src/views/website/runtime/php/create/index.vue index 75e967fa3..bb3e9e2b8 100644 --- a/frontend/src/views/website/runtime/php/create/index.vue +++ b/frontend/src/views/website/runtime/php/create/index.vue @@ -81,7 +81,16 @@ {{ $t('runtime.phpsourceHelper') }} - + + + + + (); const editParams = ref(); const appVersions = ref([]); +const phpExtensions = ref([]); const appReq = reactive({ type: 'php', page: 1, @@ -187,6 +197,7 @@ const initData = (type: string) => ({ rebuild: false, source: 'mirrors.ustc.edu.cn', }); +const extensions = ref(); let runtime = reactive(initData('php')); @@ -364,6 +375,21 @@ const getRuntime = async (id: number) => { } catch (error) {} }; +const listPHPExtensions = async () => { + try { + const res = await ListPHPExtensions({ + all: true, + page: 1, + pageSize: 100, + }); + phpExtensions.value = res.data; + } catch (error) {} +}; + +const changePHPExtension = () => { + runtime.params['PHP_EXTENSIONS'] = extensions.value.split(','); +}; + const acceptParams = async (props: OperateRrops) => { mode.value = props.mode; initParam.value = false; @@ -374,6 +400,8 @@ const acceptParams = async (props: OperateRrops) => { searchApp(props.appID); getRuntime(props.id); } + extensions.value = ''; + listPHPExtensions(); open.value = true; }; diff --git a/frontend/src/views/website/runtime/php/extensions/index.vue b/frontend/src/views/website/runtime/php/extensions/index.vue new file mode 100644 index 000000000..278cc0c69 --- /dev/null +++ b/frontend/src/views/website/runtime/php/extensions/index.vue @@ -0,0 +1,101 @@ + + diff --git a/frontend/src/views/website/runtime/php/extensions/operate/index.vue b/frontend/src/views/website/runtime/php/extensions/operate/index.vue new file mode 100644 index 000000000..b451fe613 --- /dev/null +++ b/frontend/src/views/website/runtime/php/extensions/operate/index.vue @@ -0,0 +1,121 @@ + + + diff --git a/frontend/src/views/website/runtime/php/index.vue b/frontend/src/views/website/runtime/php/index.vue index 9b7b23a76..bcbb86717 100644 --- a/frontend/src/views/website/runtime/php/index.vue +++ b/frontend/src/views/website/runtime/php/index.vue @@ -13,6 +13,10 @@ {{ $t('runtime.create') }} + + + {{ $t('php.extensions') }} + @@ -88,6 +93,7 @@ import Status from '@/components/status/index.vue'; import i18n from '@/lang'; import RouterMenu from '../index.vue'; import Log from '@/components/log-dialog/index.vue'; +import Extensions from './extensions/index.vue'; const paginationConfig = reactive({ cacheSizeKey: 'runtime-page-size', @@ -104,6 +110,7 @@ let req = reactive({ let timer: NodeJS.Timer | null = null; const opRef = ref(); const logRef = ref(); +const extensionsRef = ref(); const buttons = [ { @@ -156,13 +163,17 @@ const openCreateLog = (id: number) => { logRef.value.acceptParams({ id: id, type: 'php', tail: true }); }; +const openExtensions = () => { + extensionsRef.value.acceptParams(); +}; + const openDelete = async (row: Runtime.Runtime) => { opRef.value.acceptParams({ title: i18n.global.t('commons.msg.deleteTitle'), names: [row.name], msg: i18n.global.t('commons.msg.operatorHelper', [ i18n.global.t('website.runtime'), - i18n.global.t('commons.msg.delete'), + i18n.global.t('commons.button.delete'), ]), api: DeleteRuntime, params: { id: row.id, forceDelete: true },