Fix various problems (#37129)
* Fix #37128 * Manually tested with various cases (issue, pr) X (close, reopen) * Fix #36792 * Fix the comment * Fix #36755 * Add a "sleep 3" * Follow up #36697 * Clarify the "attachment uploading" problem and function call --------- Signed-off-by: wxiaoguang <wxiaoguang@gmail.com> Co-authored-by: TheFox0x7 <thefox0x7@gmail.com>
This commit is contained in:
@@ -175,14 +175,15 @@ RUN_USER = ; git
|
|||||||
;; The port number the builtin SSH server should listen on, defaults to SSH_PORT
|
;; The port number the builtin SSH server should listen on, defaults to SSH_PORT
|
||||||
;SSH_LISTEN_PORT =
|
;SSH_LISTEN_PORT =
|
||||||
;;
|
;;
|
||||||
;; Root path of SSH directory, default is '~/.ssh', but you have to use '/home/git/.ssh'.
|
;; Root path of SSH user directory for the system's standalone SSH server if Gitea is not using its builtin SSH server.
|
||||||
|
;; Default is the '.ssh' directory in the run user's home directory.
|
||||||
;SSH_ROOT_PATH =
|
;SSH_ROOT_PATH =
|
||||||
;;
|
;;
|
||||||
;; Gitea will create a authorized_keys file by default when it is not using the internal ssh server
|
;; Gitea will create an authorized_keys file by default when it is not using the builtin SSH server
|
||||||
;; If you intend to use the AuthorizedKeysCommand functionality then you should turn this off.
|
;; If you intend to use the AuthorizedKeysCommand functionality then you should turn this off.
|
||||||
;SSH_CREATE_AUTHORIZED_KEYS_FILE = true
|
;SSH_CREATE_AUTHORIZED_KEYS_FILE = true
|
||||||
;;
|
;;
|
||||||
;; Gitea will create a authorized_principals file by default when it is not using the internal ssh server
|
;; Gitea will create an authorized_principals file by default when it is not using the builtin SSH server
|
||||||
;; If you intend to use the AuthorizedPrincipalsCommand functionality then you should turn this off.
|
;; If you intend to use the AuthorizedPrincipalsCommand functionality then you should turn this off.
|
||||||
;SSH_CREATE_AUTHORIZED_PRINCIPALS_FILE = true
|
;SSH_CREATE_AUTHORIZED_PRINCIPALS_FILE = true
|
||||||
;;
|
;;
|
||||||
@@ -1178,16 +1179,16 @@ LEVEL = Info
|
|||||||
;[repository.release]
|
;[repository.release]
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
;; Comma-separated list of allowed file extensions (`.zip`), mime types (`text/plain`) or wildcard type (`image/*`, `audio/*`, `video/*`). Empty value or `*/*` allows all types.
|
;; Comma-separated list of allowed release attachment file extensions (`.zip`), mime types (`text/plain`) or wildcard type (`image/*`, `audio/*`, `video/*`). Empty value or `*/*` allows all types.
|
||||||
;ALLOWED_TYPES =
|
;ALLOWED_TYPES =
|
||||||
;;
|
;;
|
||||||
;; Number of releases that are displayed on release page
|
;; Number of releases that are displayed on release page
|
||||||
;DEFAULT_PAGING_NUM = 10
|
;DEFAULT_PAGING_NUM = 10
|
||||||
;;
|
;;
|
||||||
;; Max size of each file in megabytes. Defaults to 2GB
|
;; Max size of each release attachment file in megabytes. Defaults to 2GB
|
||||||
;FILE_MAX_SIZE = 2048
|
;FILE_MAX_SIZE = 2048
|
||||||
;;
|
;;
|
||||||
;; Max number of files per upload. Defaults to 5
|
;; Max number of release attachment files per upload. Defaults to 5
|
||||||
;MAX_FILES = 5
|
;MAX_FILES = 5
|
||||||
|
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
@@ -1994,16 +1995,18 @@ LEVEL = Info
|
|||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
;;
|
;;
|
||||||
;; Whether issue and pull request attachments are enabled. Defaults to `true`
|
;; Whether issue, pull-request and release attachments are enabled. Defaults to `true`
|
||||||
|
;; ALLOWED_TYPES/MAX_SIZE/MAX_FILES in this section only affect issue and pull-request attachments, not release attachments.
|
||||||
|
;; Release attachment has its own config options in [repository.release] section.
|
||||||
;ENABLED = true
|
;ENABLED = true
|
||||||
;;
|
;;
|
||||||
;; Comma-separated list of allowed file extensions (`.zip`), mime types (`text/plain`) or wildcard type (`image/*`, `audio/*`, `video/*`). Empty value or `*/*` allows all types.
|
;; Comma-separated list of allowed issue/pull-request attachment file extensions (`.zip`), mime types (`text/plain`) or wildcard type (`image/*`, `audio/*`, `video/*`). Empty value or `*/*` allows all types.
|
||||||
;ALLOWED_TYPES = .avif,.cpuprofile,.csv,.dmp,.docx,.fodg,.fodp,.fods,.fodt,.gif,.gz,.jpeg,.jpg,.json,.jsonc,.log,.md,.mov,.mp4,.odf,.odg,.odp,.ods,.odt,.patch,.pdf,.png,.pptx,.svg,.tgz,.txt,.webm,.webp,.xls,.xlsx,.zip
|
;ALLOWED_TYPES = .avif,.cpuprofile,.csv,.dmp,.docx,.fodg,.fodp,.fods,.fodt,.gif,.gz,.jpeg,.jpg,.json,.jsonc,.log,.md,.mov,.mp4,.odf,.odg,.odp,.ods,.odt,.patch,.pdf,.png,.pptx,.svg,.tgz,.txt,.webm,.webp,.xls,.xlsx,.zip
|
||||||
;;
|
;;
|
||||||
;; Max size of each file. Defaults to 100MB
|
;; Max size of each issue/pull-request attachment file. Defaults to 100MB
|
||||||
;MAX_SIZE = 100
|
;MAX_SIZE = 100
|
||||||
;;
|
;;
|
||||||
;; Max number of files per upload. Defaults to 5
|
;; Max number of issue/pull-request attachment files per upload. Defaults to 5
|
||||||
;MAX_FILES = 5
|
;MAX_FILES = 5
|
||||||
;;
|
;;
|
||||||
;; Storage type for attachments, `local` for local disk or `minio` for s3 compatible
|
;; Storage type for attachments, `local` for local disk or `minio` for s3 compatible
|
||||||
|
|||||||
@@ -1,2 +1,8 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
# $1 = exit code of the run script, $2 = signal
|
||||||
|
if [ "$1" -ne 0 ]; then
|
||||||
|
# avoid immediately restarting the sshd service, which may cause CPU 100% if the error (permission, configuration) is not fixed
|
||||||
|
echo "openssh failed with exit code $1 - waiting a short delay before attempting a restart"
|
||||||
|
sleep 3
|
||||||
|
fi
|
||||||
exit 0
|
exit 0
|
||||||
|
|||||||
@@ -186,7 +186,7 @@ func CreateIssueAttachment(ctx *context.APIContext) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
uploaderFile := attachment_service.NewLimitedUploaderKnownSize(file, header.Size)
|
uploaderFile := attachment_service.NewLimitedUploaderKnownSize(file, header.Size)
|
||||||
attachment, err := attachment_service.UploadAttachmentGeneralSizeLimit(ctx, uploaderFile, setting.Attachment.AllowedTypes, &repo_model.Attachment{
|
attachment, err := attachment_service.UploadAttachmentForIssue(ctx, uploaderFile, &repo_model.Attachment{
|
||||||
Name: filename,
|
Name: filename,
|
||||||
UploaderID: ctx.Doer.ID,
|
UploaderID: ctx.Doer.ID,
|
||||||
RepoID: ctx.Repo.Repository.ID,
|
RepoID: ctx.Repo.Repository.ID,
|
||||||
|
|||||||
@@ -193,7 +193,7 @@ func CreateIssueCommentAttachment(ctx *context.APIContext) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
uploaderFile := attachment_service.NewLimitedUploaderKnownSize(file, header.Size)
|
uploaderFile := attachment_service.NewLimitedUploaderKnownSize(file, header.Size)
|
||||||
attachment, err := attachment_service.UploadAttachmentGeneralSizeLimit(ctx, uploaderFile, setting.Attachment.AllowedTypes, &repo_model.Attachment{
|
attachment, err := attachment_service.UploadAttachmentForIssue(ctx, uploaderFile, &repo_model.Attachment{
|
||||||
Name: filename,
|
Name: filename,
|
||||||
UploaderID: ctx.Doer.ID,
|
UploaderID: ctx.Doer.ID,
|
||||||
RepoID: ctx.Repo.Repository.ID,
|
RepoID: ctx.Repo.Repository.ID,
|
||||||
|
|||||||
@@ -242,7 +242,7 @@ func CreateReleaseAttachment(ctx *context.APIContext) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Create a new attachment and save the file
|
// Create a new attachment and save the file
|
||||||
attach, err := attachment_service.UploadAttachmentReleaseSizeLimit(ctx, uploaderFile, setting.Repository.Release.AllowedTypes, &repo_model.Attachment{
|
attach, err := attachment_service.UploadAttachmentForRelease(ctx, uploaderFile, &repo_model.Attachment{
|
||||||
Name: filename,
|
Name: filename,
|
||||||
UploaderID: ctx.Doer.ID,
|
UploaderID: ctx.Doer.ID,
|
||||||
RepoID: ctx.Repo.Repository.ID,
|
RepoID: ctx.Repo.Repository.ID,
|
||||||
|
|||||||
@@ -23,16 +23,16 @@ import (
|
|||||||
|
|
||||||
// UploadIssueAttachment response for Issue/PR attachments
|
// UploadIssueAttachment response for Issue/PR attachments
|
||||||
func UploadIssueAttachment(ctx *context.Context) {
|
func UploadIssueAttachment(ctx *context.Context) {
|
||||||
uploadAttachment(ctx, ctx.Repo.Repository.ID, setting.Attachment.AllowedTypes)
|
uploadAttachment(ctx, ctx.Repo.Repository.ID, attachment.UploadAttachmentForIssue)
|
||||||
}
|
}
|
||||||
|
|
||||||
// UploadReleaseAttachment response for uploading release attachments
|
// UploadReleaseAttachment response for uploading release attachments
|
||||||
func UploadReleaseAttachment(ctx *context.Context) {
|
func UploadReleaseAttachment(ctx *context.Context) {
|
||||||
uploadAttachment(ctx, ctx.Repo.Repository.ID, setting.Repository.Release.AllowedTypes)
|
uploadAttachment(ctx, ctx.Repo.Repository.ID, attachment.UploadAttachmentForRelease)
|
||||||
}
|
}
|
||||||
|
|
||||||
// UploadAttachment response for uploading attachments
|
// UploadAttachment response for uploading attachments
|
||||||
func uploadAttachment(ctx *context.Context, repoID int64, allowedTypes string) {
|
func uploadAttachment(ctx *context.Context, repoID int64, uploadFunc attachment.UploadAttachmentFunc) {
|
||||||
if !setting.Attachment.Enabled {
|
if !setting.Attachment.Enabled {
|
||||||
ctx.HTTPError(http.StatusNotFound, "attachment is not enabled")
|
ctx.HTTPError(http.StatusNotFound, "attachment is not enabled")
|
||||||
return
|
return
|
||||||
@@ -46,7 +46,7 @@ func uploadAttachment(ctx *context.Context, repoID int64, allowedTypes string) {
|
|||||||
defer file.Close()
|
defer file.Close()
|
||||||
|
|
||||||
uploaderFile := attachment.NewLimitedUploaderKnownSize(file, header.Size)
|
uploaderFile := attachment.NewLimitedUploaderKnownSize(file, header.Size)
|
||||||
attach, err := attachment.UploadAttachmentReleaseSizeLimit(ctx, uploaderFile, allowedTypes, &repo_model.Attachment{
|
attach, err := uploadFunc(ctx, uploaderFile, &repo_model.Attachment{
|
||||||
Name: header.Filename,
|
Name: header.Filename,
|
||||||
UploaderID: ctx.Doer.ID,
|
UploaderID: ctx.Doer.ID,
|
||||||
RepoID: repoID,
|
RepoID: repoID,
|
||||||
@@ -56,7 +56,7 @@ func uploadAttachment(ctx *context.Context, repoID int64, allowedTypes string) {
|
|||||||
ctx.HTTPError(http.StatusBadRequest, err.Error())
|
ctx.HTTPError(http.StatusBadRequest, err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
ctx.ServerError("UploadAttachmentReleaseSizeLimit", err)
|
ctx.ServerError("uploadAttachment(uploadFunc)", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -119,7 +119,7 @@ func DeleteAttachment(ctx *context.Context) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetAttachment serve attachments with the given UUID
|
// ServeAttachment serve attachments with the given UUID
|
||||||
func ServeAttachment(ctx *context.Context, uuid string) {
|
func ServeAttachment(ctx *context.Context, uuid string) {
|
||||||
attach, err := repo_model.GetAttachmentByUUID(ctx, uuid)
|
attach, err := repo_model.GetAttachmentByUUID(ctx, uuid)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -57,22 +57,26 @@ func NewComment(ctx *context.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
redirect := fmt.Sprintf("%s/%s/%d", ctx.Repo.RepoLink, issueType, issue.Index)
|
||||||
attachments := util.Iif(setting.Attachment.Enabled, form.Files, nil)
|
attachments := util.Iif(setting.Attachment.Enabled, form.Files, nil)
|
||||||
|
|
||||||
// Can allow empty comments if there are attachments or a status change (close, reopen, approve, reject)
|
// allow empty content if there are attachments
|
||||||
// So, only stop if there is no content, no attachments, and no status change.
|
if form.Content != "" || len(attachments) > 0 {
|
||||||
if form.Content == "" && len(attachments) == 0 && form.Status == "" {
|
comment, err := issue_service.CreateIssueComment(ctx, ctx.Doer, ctx.Repo.Repository, issue, form.Content, attachments)
|
||||||
ctx.JSONError(ctx.Tr("repo.issues.comment_no_content"))
|
if err != nil {
|
||||||
return
|
if errors.Is(err, user_model.ErrBlockedUser) {
|
||||||
}
|
ctx.JSONError(ctx.Tr("repo.issues.comment.blocked_user"))
|
||||||
|
} else {
|
||||||
comment, err := issue_service.CreateIssueComment(ctx, ctx.Doer, ctx.Repo.Repository, issue, form.Content, attachments)
|
ctx.ServerError("CreateIssueComment", err)
|
||||||
if err != nil {
|
}
|
||||||
if errors.Is(err, user_model.ErrBlockedUser) {
|
return
|
||||||
ctx.JSONError(ctx.Tr("repo.issues.comment.blocked_user"))
|
|
||||||
} else {
|
|
||||||
ctx.ServerError("CreateIssueComment", err)
|
|
||||||
}
|
}
|
||||||
|
// redirect to the comment's hashtag
|
||||||
|
redirect += "#" + comment.HashTag()
|
||||||
|
} else if form.Status == "" {
|
||||||
|
// if no status change (close, reopen), it is a plain comment, and content is required
|
||||||
|
// "approve/reject" are handled differently in SubmitReview
|
||||||
|
ctx.JSONError(ctx.Tr("repo.issues.comment_no_content"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -86,6 +90,7 @@ func NewComment(ctx *context.Context) {
|
|||||||
!(issue.IsPull && issue.PullRequest.HasMerged) {
|
!(issue.IsPull && issue.PullRequest.HasMerged) {
|
||||||
// Duplication and conflict check should apply to reopen pull request.
|
// Duplication and conflict check should apply to reopen pull request.
|
||||||
var branchOtherUnmergedPR *issues_model.PullRequest
|
var branchOtherUnmergedPR *issues_model.PullRequest
|
||||||
|
var err error
|
||||||
if form.Status == "reopen" && issue.IsPull {
|
if form.Status == "reopen" && issue.IsPull {
|
||||||
pull := issue.PullRequest
|
pull := issue.PullRequest
|
||||||
branchOtherUnmergedPR, err = issues_model.GetUnmergedPullRequest(ctx, pull.HeadRepoID, pull.BaseRepoID, pull.HeadBranch, pull.BaseBranch, pull.Flow)
|
branchOtherUnmergedPR, err = issues_model.GetUnmergedPullRequest(ctx, pull.HeadRepoID, pull.BaseRepoID, pull.HeadBranch, pull.BaseBranch, pull.Flow)
|
||||||
@@ -179,11 +184,6 @@ func NewComment(ctx *context.Context) {
|
|||||||
}
|
}
|
||||||
} // end if: handle close or reopen
|
} // end if: handle close or reopen
|
||||||
|
|
||||||
// Redirect to the comment, add hashtag if it exists
|
|
||||||
redirect := fmt.Sprintf("%s/%s/%d", ctx.Repo.RepoLink, issueType, issue.Index)
|
|
||||||
if comment != nil {
|
|
||||||
redirect += "#" + comment.HashTag()
|
|
||||||
}
|
|
||||||
ctx.JSONRedirect(redirect)
|
ctx.JSONRedirect(redirect)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -54,12 +54,17 @@ func NewLimitedUploaderMaxBytesReader(r io.ReadCloser, w http.ResponseWriter) *U
|
|||||||
return &UploaderFile{rd: r, size: -1, respWriter: w}
|
return &UploaderFile{rd: r, size: -1, respWriter: w}
|
||||||
}
|
}
|
||||||
|
|
||||||
func UploadAttachmentGeneralSizeLimit(ctx context.Context, file *UploaderFile, allowedTypes string, attach *repo_model.Attachment) (*repo_model.Attachment, error) {
|
type UploadAttachmentFunc func(ctx context.Context, file *UploaderFile, attach *repo_model.Attachment) (*repo_model.Attachment, error)
|
||||||
return uploadAttachment(ctx, file, allowedTypes, setting.Attachment.MaxSize<<20, attach)
|
|
||||||
|
func UploadAttachmentForIssue(ctx context.Context, file *UploaderFile, attach *repo_model.Attachment) (*repo_model.Attachment, error) {
|
||||||
|
return uploadAttachment(ctx, file, setting.Attachment.AllowedTypes, setting.Attachment.MaxSize<<20, attach)
|
||||||
}
|
}
|
||||||
|
|
||||||
func UploadAttachmentReleaseSizeLimit(ctx context.Context, file *UploaderFile, allowedTypes string, attach *repo_model.Attachment) (*repo_model.Attachment, error) {
|
func UploadAttachmentForRelease(ctx context.Context, file *UploaderFile, attach *repo_model.Attachment) (*repo_model.Attachment, error) {
|
||||||
return uploadAttachment(ctx, file, allowedTypes, setting.Repository.Release.FileMaxSize<<20, attach)
|
// FIXME: although the release attachment has different settings from the issue attachment,
|
||||||
|
// it still uses the same attachment table, the same storage and the same upload logic
|
||||||
|
// So if the "issue attachment [attachment]" is not enabled, it will also affect the release attachment, which is not expected.
|
||||||
|
return uploadAttachment(ctx, file, setting.Repository.Release.AllowedTypes, setting.Repository.Release.FileMaxSize<<20, attach)
|
||||||
}
|
}
|
||||||
|
|
||||||
func uploadAttachment(ctx context.Context, file *UploaderFile, allowedTypes string, maxFileSize int64, attach *repo_model.Attachment) (*repo_model.Attachment, error) {
|
func uploadAttachment(ctx context.Context, file *UploaderFile, allowedTypes string, maxFileSize int64, attach *repo_model.Attachment) (*repo_model.Attachment, error) {
|
||||||
|
|||||||
@@ -88,7 +88,7 @@ func (h *ReplyHandler) Handle(ctx context.Context, content *MailContent, doer *u
|
|||||||
for _, attachment := range content.Attachments {
|
for _, attachment := range content.Attachments {
|
||||||
attachmentBuf := bytes.NewReader(attachment.Content)
|
attachmentBuf := bytes.NewReader(attachment.Content)
|
||||||
uploaderFile := attachment_service.NewLimitedUploaderKnownSize(attachmentBuf, attachmentBuf.Size())
|
uploaderFile := attachment_service.NewLimitedUploaderKnownSize(attachmentBuf, attachmentBuf.Size())
|
||||||
a, err := attachment_service.UploadAttachmentGeneralSizeLimit(ctx, uploaderFile, setting.Attachment.AllowedTypes, &repo_model.Attachment{
|
a, err := attachment_service.UploadAttachmentForIssue(ctx, uploaderFile, &repo_model.Attachment{
|
||||||
Name: attachment.Name,
|
Name: attachment.Name,
|
||||||
UploaderID: doer.ID,
|
UploaderID: doer.ID,
|
||||||
RepoID: issue.Repo.ID,
|
RepoID: issue.Repo.ID,
|
||||||
|
|||||||
Reference in New Issue
Block a user