feat: add explicit FTP identity initialization - #13390
Conversation
There was a problem hiding this comment.
Pull request overview
This PR introduces an explicit “FTP identity initialization” flow so the system UID/GID used by pure-ftpd (and related filesystem ownership) can be created on-demand, and the frontend can guide users to initialize before managing FTP accounts.
Changes:
- Add
/toolbox/ftp/initAPI (agent-side) and corresponding frontendinitFtp()call, plus UI gating when FTP identity is not initialized. - Extend FTP base info (
isInit) across API interfaces and i18n strings to support the new initialization UX. - Update generated swagger/log docs to include the new endpoint (alongside other regenerated schema changes).
Reviewed changes
Copilot reviewed 26 out of 26 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| frontend/src/views/toolbox/ftp/index.vue | Adds isInit/baseLoaded gating and an “Initialize” action in the FTP toolbox UI. |
| frontend/src/lang/modules/zh.ts | Adds toolbox.ftp.initHelper string. |
| frontend/src/lang/modules/zh-Hant.ts | Adds toolbox.ftp.initHelper string. |
| frontend/src/lang/modules/tr.ts | Adds toolbox.ftp.initHelper string. |
| frontend/src/lang/modules/ru.ts | Adds toolbox.ftp.initHelper string. |
| frontend/src/lang/modules/pt-br.ts | Adds toolbox.ftp.initHelper string. |
| frontend/src/lang/modules/ms.ts | Adds toolbox.ftp.initHelper string. |
| frontend/src/lang/modules/lo.ts | Adds toolbox.ftp.initHelper string. |
| frontend/src/lang/modules/ko.ts | Adds toolbox.ftp.initHelper string. |
| frontend/src/lang/modules/ja.ts | Adds toolbox.ftp.initHelper string. |
| frontend/src/lang/modules/fa.ts | Adds toolbox.ftp.initHelper string. |
| frontend/src/lang/modules/es-es.ts | Adds toolbox.ftp.initHelper string. |
| frontend/src/lang/modules/en.ts | Adds toolbox.ftp.initHelper string. |
| frontend/src/api/modules/toolbox.ts | Adds initFtp() API wrapper for /toolbox/ftp/init. |
| frontend/src/api/interface/toolbox.ts | Extends FtpBaseInfo with isInit. |
| core/cmd/server/docs/x-log.json | Adds panel-log metadata for /toolbox/ftp/init. |
| core/cmd/server/docs/swagger.json | Documents /toolbox/ftp/init (and includes other regenerated schema deltas). |
| core/cmd/server/docs/docs.go | Embedded swagger template updated to include /toolbox/ftp/init (and other regen changes). |
| agent/utils/toolbox/pure-ftpd.go | Adds initialization checks/creation for the system FTP identity; switches ownership to configured UID/GID constants. |
| agent/router/ro_toolbox.go | Registers POST /ftp/init route in toolbox router. |
| agent/constant/host_tool.go | Introduces FTPUser/FTPUid/FTPGid constants. |
| agent/cmd/server/docs/x-log.json | Adds panel-log metadata for /toolbox/ftp/init. |
| agent/app/service/website_utils.go | Uses FTPUid/FTPGid constants for chown owner formatting. |
| agent/app/service/ftp.go | Adds Init() service method; includes isInit in base info; gates some operations on initialization. |
| agent/app/dto/ftp.go | Extends DTO base info with IsInit. |
| agent/app/api/v2/ftp.go | Adds /toolbox/ftp/init endpoint handler and swagger annotations. |
Comments suppressed due to low confidence (1)
agent/utils/toolbox/pure-ftpd.go:293
chown -Ris run on the requestedpathafterpure-pw usermod, but there’s no guard againstpath == "/"(or empty). This makes it possible to accidentally/abusefully change ownership of the whole filesystem.
owner := fmt.Sprintf("%d:%d", constant.FTPUid, constant.FTPGid)
if err := cmd.NewCommandMgr().Run("chown", "-R", owner, path); err != nil {
return err
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
051edff to
d97c8b3
Compare
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 26 out of 26 changed files in this pull request and generated no new comments.
Comments suppressed due to low confidence (3)
frontend/src/views/toolbox/ftp/index.vue:48
- The content mask is only applied when
baseLoadedis true. IfgetFtpBase()fails,baseLoadedstays false and the page becomes interactive with defaultformvalues, which can allow actions while the service/init state is unknown. Consider masking (or otherwise disabling interactions) wheneverbaseLoadedis false as well.
<LayoutContent
v-loading="loading"
:title="$t('toolbox.ftp.ftp', 2)"
:class="{ mask: baseLoaded && (!form.isActive || !form.isInit) }"
>
agent/app/service/website_utils.go:1225
chownis invoked without a--argument, so a path starting with-could be interpreted as an option bychown. Other new call sites (e.g.agent/utils/toolbox/pure-ftpd.go) already use--; consider doing the same here for consistency and safety.
owner := fmt.Sprintf("%d:%d", constant.FTPUid, constant.FTPGid)
if err := cmdMgr.Run("chown", "-R", owner, path); err != nil {
return err
agent/app/service/ftp.go:87
SearchWithPagecallstoolbox.NewFtpClient()only to validate initialization, but discards the client. This hides intent and does extra work; usingtoolbox.IsFtpInitialized()(and returningtoolbox.ErrFtpNotInitializedwhen false) would be clearer.
func (f *FtpService) SearchWithPage(req dto.SearchWithPage) (int64, interface{}, error) {
if _, err := toolbox.NewFtpClient(); err != nil {
return 0, nil, err
}
No description provided.