-
-
Notifications
You must be signed in to change notification settings - Fork 5.7k
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
Implement basic file uploads to wiki #6024
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 |
---|---|---|
|
@@ -22,7 +22,7 @@ import ( | |
) | ||
|
||
var ( | ||
reservedWikiNames = []string{"_pages", "_new", "_edit", "raw"} | ||
reservedWikiNames = []string{"_pages", "_new", "_edit", "_upload", "raw"} | ||
wikiWorkingPool = sync.NewExclusivePool() | ||
) | ||
|
||
|
@@ -242,3 +242,77 @@ func (repo *Repository) DeleteWikiPage(doer *User, wikiName string) (err error) | |
|
||
return nil | ||
} | ||
|
||
// UploadWikiFiles uploads files to wiki's repo | ||
func (repo *Repository) UploadWikiFiles(doer *User, message string, files []string) (err error) { | ||
if len(files) == 0 { | ||
return nil | ||
} | ||
|
||
uploads, err := GetUploadsByUUIDs(files) | ||
if err != nil { | ||
return fmt.Errorf("GetUploadsByUUIDs [uuids: %v]: %v", files, err) | ||
} | ||
|
||
wikiWorkingPool.CheckIn(com.ToStr(repo.ID)) | ||
defer wikiWorkingPool.CheckOut(com.ToStr(repo.ID)) | ||
|
||
if err = repo.InitWiki(); err != nil { | ||
return fmt.Errorf("InitWiki: %v", err) | ||
} | ||
|
||
localPath := repo.LocalWikiPath() | ||
|
||
if err = discardLocalWikiChanges(localPath); err != nil { | ||
return fmt.Errorf("discardLocalWikiChanges: %v", err) | ||
} else if err = repo.updateLocalWiki(); err != nil { | ||
return fmt.Errorf("UpdateLocalWiki: %v", err) | ||
} | ||
|
||
// Copy uploaded files into repository. | ||
for _, upload := range uploads { | ||
tmpPath := upload.LocalPath() | ||
targetPath := path.Join(localPath, upload.Name) | ||
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. This will allow you to write to arbitrary places in the filesystem. Admittedly you can't overwrite anything with your current code but you can certainly inject into hooks. 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. Perhaps this could be solved by using the hash of the file path instead of the actual path, in a way similar to what is currently done with avatars (although for avatars it's a hash of the file contents, which I don't think is the best way here). 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. @guillep2k I think if we look for forbidden pathern this shouldnt be a problem. If we hash files on the wiki wont have a human redable name anymore allow normal chars a-Z numbers and '-' '_' '.' and add a check for 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. @6543 but then the users will need to think about how they need to name their files. We should allow them to use any name, as long as it renders a serviceable path from Macaron (i.e. no slashes, no empty string). |
||
|
||
if !com.IsFile(tmpPath) { | ||
continue | ||
} | ||
|
||
if com.IsExist(targetPath) { | ||
return ErrWikiAlreadyExist{targetPath} | ||
} | ||
|
||
// SECURITY: if new file is a symlink to non-exist critical file, | ||
// attack content can be written to the target file (e.g. authorized_keys2) | ||
// as a new page operation. | ||
// So we want to make sure the symlink is removed before write anything. | ||
// The new file we created will be in normal text format. | ||
if err = os.RemoveAll(targetPath); err != nil { | ||
return err | ||
} | ||
|
||
if err = com.Copy(tmpPath, targetPath); err != nil { | ||
return fmt.Errorf("Copy: %v", err) | ||
} | ||
} | ||
|
||
if len(message) == 0 { | ||
message = "Upload files" | ||
} | ||
|
||
if err = git.AddChanges(localPath, true); err != nil { | ||
return fmt.Errorf("AddChanges: %v", err) | ||
} else if err = git.CommitChanges(localPath, git.CommitChangesOptions{ | ||
Committer: doer.NewGitSig(), | ||
Message: message, | ||
}); err != nil { | ||
return fmt.Errorf("CommitChanges: %v", err) | ||
} else if err = git.Push(localPath, git.PushOptions{ | ||
Remote: "origin", | ||
Branch: "master", | ||
}); err != nil { | ||
return fmt.Errorf("Push: %v", err) | ||
} | ||
|
||
return DeleteUploads(uploads...) | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -23,10 +23,11 @@ import ( | |
) | ||
|
||
const ( | ||
tplWikiStart base.TplName = "repo/wiki/start" | ||
tplWikiView base.TplName = "repo/wiki/view" | ||
tplWikiNew base.TplName = "repo/wiki/new" | ||
tplWikiPages base.TplName = "repo/wiki/pages" | ||
tplWikiStart base.TplName = "repo/wiki/start" | ||
tplWikiView base.TplName = "repo/wiki/view" | ||
tplWikiNew base.TplName = "repo/wiki/new" | ||
tplWikiPages base.TplName = "repo/wiki/pages" | ||
tplWikiUpload base.TplName = "repo/wiki/upload" | ||
) | ||
|
||
// MustEnableWiki check if wiki is enabled, if external then redirect | ||
|
@@ -435,3 +436,43 @@ func DeleteWikiPagePost(ctx *context.Context) { | |
"redirect": ctx.Repo.RepoLink + "/wiki/", | ||
}) | ||
} | ||
|
||
// UploadWikiFile render wiki upload page | ||
func UploadWikiFile(ctx *context.Context) { | ||
ctx.Data["PageIsWiki"] = true | ||
ctx.Data["PageIsUpload"] = true | ||
renderUploadSettings(ctx) | ||
|
||
if !ctx.Repo.Repository.HasWiki() { | ||
ctx.Redirect(ctx.Repo.RepoLink + "/wiki") | ||
return | ||
} | ||
|
||
renderWikiPage(ctx, false) | ||
if ctx.Written() { | ||
return | ||
} | ||
|
||
ctx.HTML(200, tplWikiUpload) | ||
} | ||
|
||
// UploadWikiFilePost response for wiki upload request | ||
func UploadWikiFilePost(ctx *context.Context, form auth.UploadWikiFileForm) { | ||
fmt.Println("UploadWikiFilePost") | ||
|
||
ctx.Data["PageIsWiki"] = true | ||
ctx.Data["PageIsUpload"] = true | ||
renderUploadSettings(ctx) | ||
|
||
if ctx.HasError() { | ||
ctx.HTML(200, tplWikiUpload) | ||
return | ||
} | ||
|
||
if err := ctx.Repo.Repository.UploadWikiFiles(ctx.User, strings.TrimSpace(form.Message), form.Files); err != nil { | ||
ctx.ServerError("DeleteWikiPage", err) | ||
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. why DeleteWikiPage |
||
return | ||
} | ||
|
||
ctx.Redirect(ctx.Repo.RepoLink + "/wiki/") | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
{{template "base/head" .}} | ||
<div class="repository file editor upload"> | ||
{{template "repo/header" .}} | ||
<div class="ui container"> | ||
{{template "base/alert" .}} | ||
<form class="ui comment form" method="post"> | ||
{{.CsrfTokenHtml}} | ||
<div class="field"> | ||
<div class="files"></div> | ||
<div class="ui basic button dropzone" id="dropzone" data-upload-url="{{.RepoLink}}/upload-file" data-remove-url="{{.RepoLink}}/upload-remove" data-csrf="{{.CsrfToken}}" data-accepts="{{.UploadAllowedTypes}}" data-max-file="{{.UploadMaxFiles}}" data-max-size="{{.UploadMaxSize}}" data-default-message="{{.i18n.Tr "dropzone.default_message"}}" data-invalid-input-type="{{.i18n.Tr "dropzone.invalid_input_type"}}" data-file-too-big="{{.i18n.Tr "dropzone.file_too_big"}}" data-remove-file="{{.i18n.Tr "dropzone.remove_file"}}"></div> | ||
</div> | ||
<div class="field"> | ||
<input name="message" placeholder="{{.i18n.Tr "repo.wiki.default_commit_message"}}"> | ||
</div> | ||
<div class="text right"> | ||
<button class="ui green button"> | ||
{{.i18n.Tr "repo.wiki.upload_files_button"}} | ||
</button> | ||
</div> | ||
</form> | ||
</div> | ||
</div> | ||
{{template "base/footer" .}} |
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 should be a migration check or something if we add a new reserved name.
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.
maybe we should reverse all word begin with
_
. :)