-
Notifications
You must be signed in to change notification settings - Fork 3.2k
feat(website): fix issues with create website with ftp failed #8272
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -410,26 +410,6 @@ func (w WebsiteService) CreateWebsite(create request.WebsiteCreate) (err error) | |
| website.ParentWebsiteID = parentWebsite.ID | ||
| } | ||
|
|
||
| if len(create.FtpUser) != 0 && len(create.FtpPassword) != 0 { | ||
| createFtpUser := func(t *task.Task) error { | ||
| indexDir := GetSitePath(*website, SiteIndexDir) | ||
| itemID, err := NewIFtpService().Create(dto.FtpCreate{User: create.FtpUser, Password: create.FtpPassword, Path: indexDir}) | ||
| if err != nil { | ||
| createTask.Log(fmt.Sprintf("create ftp for website failed, err: %v", err)) | ||
| } | ||
| website.FtpID = itemID | ||
| return nil | ||
| } | ||
| deleteFtpUser := func(t *task.Task) { | ||
| if website.FtpID > 0 { | ||
| if err = NewIFtpService().Delete(dto.BatchDeleteReq{Ids: []uint{website.FtpID}}); err != nil { | ||
| createTask.Log(err.Error()) | ||
| } | ||
| } | ||
| } | ||
| createTask.AddSubTask(i18n.GetWithName("ConfigFTP", create.FtpUser), createFtpUser, deleteFtpUser) | ||
| } | ||
|
|
||
| configNginx := func(t *task.Task) error { | ||
| if err = configDefaultNginx(website, domains, appInstall, runtime); err != nil { | ||
| return err | ||
|
|
@@ -488,6 +468,19 @@ func (w WebsiteService) CreateWebsite(create request.WebsiteCreate) (err error) | |
| createTask.AddSubTaskWithIgnoreErr(i18n.GetMsgByKey("EnableSSL"), enableSSL) | ||
| } | ||
|
|
||
| if len(create.FtpUser) != 0 && len(create.FtpPassword) != 0 { | ||
| createFtpUser := func(t *task.Task) error { | ||
| indexDir := GetSitePath(*website, SiteIndexDir) | ||
| itemID, err := NewIFtpService().Create(dto.FtpCreate{User: create.FtpUser, Password: create.FtpPassword, Path: indexDir}) | ||
| if err != nil { | ||
| return err | ||
| } | ||
| website.FtpID = itemID | ||
| return nil | ||
| } | ||
| createTask.AddSubTaskWithIgnoreErr(i18n.GetWithName("ConfigFTP", create.FtpUser), createFtpUser) | ||
| } | ||
|
|
||
| return createTask.Execute() | ||
| } | ||
|
|
||
|
|
@@ -2061,7 +2054,7 @@ func (w WebsiteService) GetPathAuthBasics(req request.NginxAuthReq) (res []respo | |
| } | ||
| directives := config.Directives | ||
| location, _ := directives[0].(*components.Location) | ||
| pathAuth.Path = location.Match | ||
| pathAuth.Path = strings.TrimPrefix(location.Match, "^") | ||
| passPath := path.Join(passDir, fmt.Sprintf("%s.pass", name)) | ||
| authContent, err = fileOp.GetContent(passPath) | ||
| if err != nil { | ||
|
|
@@ -2130,7 +2123,7 @@ func (w WebsiteService) UpdatePathAuthBasic(req request.NginxPathAuthUpdate) err | |
| directives := config.Directives | ||
| location, _ := directives[0].(*components.Location) | ||
| location.UpdateDirective("auth_basic_user_file", []string{fmt.Sprintf("/www/sites/%s/path_auth/pass/%s", website.Alias, fmt.Sprintf("%s.pass", req.Name))}) | ||
| location.ChangePath("~*", req.Path) | ||
| location.ChangePath("~*", fmt.Sprintf("^%s", req.Path)) | ||
| var passwdHash []byte | ||
| passwdHash, err = bcrypt.GenerateFromPassword([]byte(req.Password), bcrypt.DefaultCost) | ||
| if err != nil { | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The provided code has some areas that can be reviewed for better organization, clarity, and performance. Code Snippet 1if len(create.FtpUser) != 0 && len(create.FtpPassword) != 0 {
createFtpUser := func(t *task.Task) error {
indexDir := GetSitePath(*website, SiteIndexDir)
itemID, err := NewIFtpService().Create(dto.FtpCreate{User: create.FtpUser, Password: create.FtpPassword, Path: indexDir})
if err != nil {
t.Log(fmt.Sprintf("create ftp for website failed, err: %v", err))
}
website.FtpID = itemID
return nil
}
deleteFtpUser := func(t *task.Task) {
if website.FtpID > 0 {
if err = NewIFtpService().Delete(dto.BatchDeleteReq{Ids: []uint{website.FtpID}}); err != nil {
t.Log(err.Error())
}
}
}
createTask.AddSubTask(i18n.GetWithName("ConfigFTP", create.FtpUser), createFtpUser, deleteFtpUser)
}Recommendations:
func ensureFtpUserExists(t context.Context) func(ctx context.Context) error {
return func(ctx context.Context) error {
user := dto.FtpCreate{
User: create.FtpUser,
Password: create.FtpPassword,
Path: GetSitePath(*website, SiteIndexDir),
}
itemID, err := NewIFtpService().Create(user)
if err != nil {
return err
}
website.FtpID = itemID
// Cleanup on failure
defer cleanupFunc(itemID)
return nil
}
}
func cleanupFunc(id uint) {
if id > 0 {
if err := NewIFtpService().Delete(dto.BatchDeleteReq{Ids: []uint{id}}); err != nil {
log.Printf("Unable to clean up FTP resource: %v\n", err)
}
}
}
Code Snippet 2if len(create.FtpUser) != 0 && len(create.FtpPassword) != 0 {
createFtpUser := func(t *task.Task) error {
...
}
createTask.AddSubTask(i18n.GetWithName("ConfigFTP", create.FtpUser), createFtpUser)
}No significant changes here but the pattern is similar to snippet 1. General Recommendations
Overall Feedback: The code seems well-structured except for minor inefficiencies and inconsistent logging practices which could impact maintainability and debugging effort. Suggestions focus on improving code cleanliness, consistency, and efficiency. |
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -25,7 +25,7 @@ | |
| /> | ||
| </ComplexTable> | ||
| </el-tab-pane> | ||
| <el-tab-pane :label="$t('website.path')"> | ||
| <el-tab-pane :label="$t('website.path')" v-if="showPath"> | ||
| <ComplexTable :data="pathData" @search="searchPath" v-loading="loading" :heightDiff="420"> | ||
| <template #toolbar> | ||
| <el-button type="primary" plain @click="openCreate('path')"> | ||
|
|
@@ -54,7 +54,13 @@ | |
|
|
||
| <script lang="ts" setup name="proxy"> | ||
| import { Website } from '@/api/interface/website'; | ||
| import { operateAuthConfig, getAuthConfig, getPathAuthConfig, operatePathAuthConfig } from '@/api/modules/website'; | ||
| import { | ||
| operateAuthConfig, | ||
| getAuthConfig, | ||
| getPathAuthConfig, | ||
| operatePathAuthConfig, | ||
| getWebsite, | ||
| } from '@/api/modules/website'; | ||
| import { computed, onMounted, ref } from 'vue'; | ||
| import i18n from '@/lang'; | ||
| import Create from './create/index.vue'; | ||
|
|
@@ -80,6 +86,7 @@ const createRef = ref(); | |
| const enable = ref(false); | ||
| const opRef = ref(); | ||
| const pathData = ref([]); | ||
| const showPath = ref(false); | ||
|
|
||
| const buttons = [ | ||
| { | ||
|
|
@@ -207,7 +214,14 @@ const searchAll = () => { | |
| searchPath(); | ||
| }; | ||
|
|
||
| const getSiteDetail = async () => { | ||
| getWebsite(id.value).then(async (res) => { | ||
| showPath.value = res.data.type !== 'proxy' && res.data.type !== 'deployment'; | ||
| }); | ||
| }; | ||
|
|
||
| onMounted(() => { | ||
| getSiteDetail(); | ||
| searchAll(); | ||
| }); | ||
| </script> | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There are several areas where this code can be improved: 1. Remove Unused Code
// remove this line: const createRef = ref();Additionally, the unused methods 2. Simplify Variable DeclarationsDeclare variables more clearly when using const data = ref([]); // instead of let data = [];
const loading = ref(false);
...
onMounted(() => {
loadData();
});3. Refactor Complex LogicIf the complex logic related to checking conditions should only run under certain circumstances, consider wrapping it in a separate function with conditional checks within. function handleShowPath(websiteType) {
showPath.value = websiteType !== 'proxy' && websiteType !== 'deployment';
}
...
handleShowPath(siteDetail.type);This makes the code cleaner and easier to maintain. 4. Add More TypeScript Type CheckingEnsure that types are correctly defined and used throughout the component. interface WebSiteType { /** Define your interface here */ }
const siteDetail: WebSiteType = computed(() => {/* logic to compute siteDetail*/ });
... other similar uses.5. Ensure Error HandlingInclude error handling for APIs like async function loadWebsites() {
try {
const response = await getWebsite(id.value);
pathData.value = response.data;
} catch (error) {
console.error("Error fetching websites", error.message);
}
}
loadWebsites();These recommendations will help streamline the codebase by removing unnecessary parts, simplifying variable declarations, improving modularity, adding type definitions explicitly, and ensuring robustness through proper error handling. |
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is an issue with the logic inside the
ifblock before saving the runtime status to running if no errors occur up to that point. Specifically:The function should not call
_runtimeRepo.Save(runtime)inside both branches of the conditional statement (before and after the installation command) since it may overwrite changes made in one branch.After processing the installation command, there might be some additional cleanup needed (depending on what
compose.DownAndUp()does), but this part needs clarification based on the actual implementation.For optimization, consider moving any operations unrelated to runtime state updates above the conditional statements to reduce redundancy. Additionally, ensure error handling when calling
downAndUp()since downgrading and upgrading the container can fail as well.