Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 14 additions & 14 deletions internal/service/application.go
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,7 @@ func (s *Service) UpdateApplicationStatus(
application.Status.String(), inputs.Status.String())
return nil, nil, NewBadInputError(message)
}
if s.isAccountManagerRevertingAcceptedApplication(user, application.Status, inputs.Status) {
if s.isAccountManagerRevertingApprovedApplication(user, application.Status, inputs.Status) {
targets, err := s.repository.GetApplicationTargets(ctx, applicationID)
if err != nil {
logger.Error("failed to get application targets from repository", zap.Error(err))
Expand Down Expand Up @@ -262,31 +262,31 @@ func (s *Service) isAccountManager(user *User) bool {

func (s *Service) isAbleNoCommentUpdateStatus(currentStatus, newStatus Status) bool {
switch currentStatus {
case Submitted:
return newStatus != FixRequired && newStatus != Rejected
case Accepted:
return newStatus != Submitted
case FixRequired, Completed, Rejected:
case PendingReview:
return newStatus != ChangeRequested && newStatus != Rejected
case Approved:
return newStatus != PendingReview
case ChangeRequested, PaymentFinished, Rejected:
return true
default:
return false
}
}

func (s *Service) isAbleAccountManagerUpdateStatus(currentStatus, newStatus Status) bool {
return newStatus == Rejected && currentStatus == Submitted ||
newStatus == Submitted && currentStatus == FixRequired ||
newStatus == Accepted && currentStatus == Submitted ||
newStatus == Submitted && currentStatus == Accepted ||
newStatus == FixRequired && currentStatus == Submitted
return newStatus == Rejected && currentStatus == PendingReview ||
newStatus == PendingReview && currentStatus == ChangeRequested ||
newStatus == Approved && currentStatus == PendingReview ||
newStatus == PendingReview && currentStatus == Approved ||
newStatus == ChangeRequested && currentStatus == PendingReview
}

func (s *Service) isAbleCreatorChangeStatus(currentStatus, newStatus Status) bool {
return currentStatus == FixRequired && newStatus == Submitted
return currentStatus == ChangeRequested && newStatus == PendingReview
}

func (s *Service) isAccountManagerRevertingAcceptedApplication(
func (s *Service) isAccountManagerRevertingApprovedApplication(
user *User, currentStatus, newStatus Status,
) bool {
return user.AccountManager && currentStatus == Accepted && newStatus == Submitted
return user.AccountManager && currentStatus == Approved && newStatus == PendingReview
}
56 changes: 28 additions & 28 deletions internal/service/application_status.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,23 +14,23 @@ type Status int

const (
_ Status = iota
Submitted
FixRequired
Accepted
Completed
PendingReview
ChangeRequested
Approved
PaymentFinished
Rejected
)

func (s Status) String() string {
switch s {
case Submitted:
return "submitted"
case FixRequired:
return "fix_required"
case Accepted:
return "accepted"
case Completed:
return "completed"
case PendingReview:
return "pending_review"
case ChangeRequested:
return "change_requested"
case Approved:
return "approved"
case PaymentFinished:
return "payment_finished"
case Rejected:
return "rejected"
default:
Expand All @@ -42,14 +42,14 @@ func (s Status) String() string {
// dbにstringいれる今の実装だとMarshalJson入らなそう。
func (s Status) MarshalJSON() ([]byte, error) {
switch s {
case Submitted:
return json.Marshal("submitted")
case FixRequired:
return json.Marshal("fix_required")
case Accepted:
return json.Marshal("accepted")
case Completed:
return json.Marshal("completed")
case PendingReview:
return json.Marshal("pending_review")
case ChangeRequested:
return json.Marshal("change_requested")
case Approved:
return json.Marshal("approved")
case PaymentFinished:
return json.Marshal("payment_finished")
case Rejected:
return json.Marshal("rejected")
default:
Expand All @@ -65,14 +65,14 @@ func (s *Status) UnmarshalJSON(data []byte) error {

var st Status
switch str {
case "submitted":
st = Submitted
case "fix_required":
st = FixRequired
case "accepted":
st = Accepted
case "completed":
st = Completed
case "pending_review":
st = PendingReview
case "change_requested":
st = ChangeRequested
case "approved":
st = Approved
case "payment_finished":
st = PaymentFinished
case "rejected":
st = Rejected
default:
Expand Down
4 changes: 2 additions & 2 deletions internal/service/file.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ type File struct {
CreatedAt time.Time
}

var acceptedMimeTypes = map[string]bool{
var ApprovedMimeTypes = map[string]bool{
"image/jpeg": true,
"image/png": true,
"image/gif": true,
Expand Down Expand Up @@ -98,7 +98,7 @@ func (s *Service) WriteFile(
user *User, applicationID uuid.UUID,
name string, mimetype string, content io.Reader,
) (*File, error) {
if !acceptedMimeTypes[mimetype] {
if !ApprovedMimeTypes[mimetype] {
return nil, NewBadInputError("unsupported mime type")
Comment on lines +101 to 102

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# 生ヘッダー受け渡しと ParseMediaType 未使用の確認
rg -n -C2 'Header\.Get\(echo\.HeaderContentType\)'
rg -n -C2 '\bWriteFile\s*\(.*mimetype' --type=go
rg -n -C2 '\bParseMediaType\s*\(' --type=go

Repository: traPtitech/Jomon

Length of output: 608


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "=== internal/service/file.go (around 80-130) ==="
nl -ba internal/service/file.go | sed -n '70,140p'

echo
echo "=== Find ApprovedMimeTypes / IsApprovedMimeType ==="
rg -n "ApprovedMimeTypes|IsApprovedMimeType" --type=go .

echo
echo "=== internal/router/file.go (around 40-100) ==="
nl -ba internal/router/file.go | sed -n '40,110p'

echo
echo "=== Ensure ParseMediaType usage absence (more broad) ==="
rg -n "ParseMediaType" --type=go .

echo
echo "=== Any existing mime parsing/normalization helpers ==="
rg -n "Parse.*MediaType|ToLower\\(mediaType\\)|strings\\.ToLower\\(.*mim" --type=go internal || true

Repository: traPtitech/Jomon

Length of output: 170


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "=== internal/service/file.go (lines ~80-130) ==="
sed -n '70,140p' internal/service/file.go | cat -n

echo
echo "=== Find ApprovedMimeTypes / IsApprovedMimeType ==="
rg -n "ApprovedMimeTypes|IsApprovedMimeType" --type=go .

echo
echo
echo "=== internal/router/file.go (lines ~40-100) ==="
sed -n '40,110p' internal/router/file.go | cat -n

echo
echo
echo "=== ParseMediaType usage (anywhere) ==="
rg -n "ParseMediaType" --type=go .

Repository: traPtitech/Jomon

Length of output: 5033


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "=== internal/service/file.go (lines ~1-70) ==="
sed -n '1,80p' internal/service/file.go | cat -n

Repository: traPtitech/Jomon

Length of output: 2855


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "=== internal/service/file.go (lines ~1-80) ==="
sed -n '1,80p' internal/service/file.go | cat -n

Repository: traPtitech/Jomon

Length of output: 2855


Content-Typeを生値で完全一致判定しており、パラメータ付きで誤拒否する可能性があります。

internal/router/file.go:60 で echo.HeaderContentType をそのまま WriteFile に渡し、internal/service/file.go(WriteFile)で ApprovedMimeTypes[mimetype] の完全一致で判定しているため、image/jpeg; charset=binary のような値が来ると一致せず unsupported mime type になります。mime.ParseMediaType でパラメータを除いたメディアタイプ部分に正規化(小文字化)してから ApprovedMimeTypes[mediaType] を判定してください。

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@internal/service/file.go` around lines 101 - 102, The WriteFile flow is doing
a strict equals check against ApprovedMimeTypes using the raw Content-Type
header, which fails when parameters (e.g. "image/jpeg; charset=binary") are
present; modify WriteFile to call mime.ParseMediaType on the incoming mimetype
(from echo.HeaderContentType), extract the mediaType, normalize it to lowercase,
and then check ApprovedMimeTypes[mediaType]; ensure you handle ParseMediaType
errors (treat as unsupported) and keep the ApprovedMimeTypes lookup using the
normalized media type.

}
logger := logging.GetLogger(ctx)
Expand Down
Loading