Rewrites the internal/api comment blocks to rule 32: task, milestone and rule ids gone, the stories behind them restated as the constraint they left, stale references corrected (the stream secret is wired from config, the timezone handler already refreshes the scheduler, the Android app is the native client, the design docs cited are not in the repo). Also rewraps comment lines over 80 columns left by the earlier batches. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
59 lines
2.1 KiB
Go
59 lines
2.1 KiB
Go
package api
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"log/slog"
|
|
"net/http"
|
|
|
|
"git.fabledsword.com/bvandeusen/minstrel/internal/apierror"
|
|
"git.fabledsword.com/bvandeusen/minstrel/internal/library"
|
|
)
|
|
|
|
// fileRemoveAPIError answers a delete that could not reach the track's file.
|
|
// Both delete endpoints use it, so an admin gets the same
|
|
// explanation from the admin remove-track action and from quarantine's Delete
|
|
// file.
|
|
//
|
|
// The unwritable case is a 409 rather than a 500 because nothing is broken: the
|
|
// request conflicts with how the library is mounted, and the fix is the
|
|
// host's. The message names the directory — removal writes to the parent,
|
|
// not the file — and the uid/gid the process runs as, which is the half of a
|
|
// permission problem invisible from the host. Every case says nothing was
|
|
// deleted, because that is exactly what an admin will be worried about.
|
|
func fileRemoveAPIError(err error) (*apierror.Error, bool) {
|
|
var fre *library.FileRemoveError
|
|
if !errors.As(err, &fre) {
|
|
return nil, false
|
|
}
|
|
if fre.NotWritable() {
|
|
return &apierror.Error{
|
|
Status: http.StatusConflict,
|
|
Code: "library_not_writable",
|
|
Message: fmt.Sprintf(
|
|
"Minstrel runs as uid %d, gid %d and cannot delete from %s (%s). "+
|
|
"The library mount must be writable by that user. Nothing was deleted.",
|
|
fre.UID, fre.GID, fre.Dir(), fre.Reason()),
|
|
Cause: err,
|
|
}, true
|
|
}
|
|
return &apierror.Error{
|
|
Status: http.StatusInternalServerError,
|
|
Code: "file_delete_failed",
|
|
Message: fmt.Sprintf("Could not delete %s (%s). Nothing was deleted.", fre.Path, fre.Reason()),
|
|
Cause: err,
|
|
}, true
|
|
}
|
|
|
|
// logFileRemoveFailure records a delete that could not reach its file. An
|
|
// unwritable library is an environment fact an admin can fix, so it is a
|
|
// Warn; anything else is a real fault.
|
|
func logFileRemoveFailure(logger *slog.Logger, apiErr *apierror.Error, attrs ...any) {
|
|
attrs = append(attrs, "code", apiErr.Code, "err", apiErr.Cause)
|
|
if apiErr.Status == http.StatusConflict {
|
|
logger.Warn("api: track file could not be deleted", attrs...)
|
|
return
|
|
}
|
|
logger.Error("api: track file could not be deleted", attrs...)
|
|
}
|