Improve Immich-backed photos endpoints with robust mapping/error handling, full albums CRUD, reliable list pagination/sorting/filtering, and shared Nextcloud quota checks before upload.
124 lines
3.2 KiB
Go
124 lines
3.2 KiB
Go
package photos
|
|
|
|
import (
|
|
"strings"
|
|
|
|
"github.com/ultisuite/ulti-backend/internal/api/apivalidate"
|
|
)
|
|
|
|
const maxJSONRequestBody = 32 << 10
|
|
|
|
type createAlbumRequest struct {
|
|
Name string `json:"name"`
|
|
Description string `json:"description"`
|
|
AssetIDs []string `json:"asset_ids"`
|
|
}
|
|
|
|
type updateAlbumRequest struct {
|
|
Name *string `json:"name"`
|
|
Description *string `json:"description"`
|
|
}
|
|
|
|
type albumAssetsRequest struct {
|
|
AssetIDs []string `json:"asset_ids"`
|
|
}
|
|
|
|
func validateAssetID(assetID string) *apivalidate.ValidationError {
|
|
if strings.TrimSpace(assetID) == "" {
|
|
return apivalidate.NewValidationError(apivalidate.FieldDetail{
|
|
Field: "asset_id", Message: "required",
|
|
})
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func validateAlbumID(albumID string) *apivalidate.ValidationError {
|
|
if strings.TrimSpace(albumID) == "" {
|
|
return apivalidate.NewValidationError(apivalidate.FieldDetail{
|
|
Field: "album_id", Message: "required",
|
|
})
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func validateAlbumName(field, name string, required bool) *apivalidate.FieldDetail {
|
|
name = strings.TrimSpace(name)
|
|
if name == "" {
|
|
if required {
|
|
return &apivalidate.FieldDetail{Field: field, Message: "required"}
|
|
}
|
|
return nil
|
|
}
|
|
if strings.Contains(name, "\n") || strings.Contains(name, "\r") {
|
|
return &apivalidate.FieldDetail{Field: field, Message: "invalid"}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func validateAssetIDs(field string, assetIDs []string, required bool) []apivalidate.FieldDetail {
|
|
if len(assetIDs) == 0 {
|
|
if required {
|
|
return []apivalidate.FieldDetail{{Field: field, Message: "required"}}
|
|
}
|
|
return nil
|
|
}
|
|
var details []apivalidate.FieldDetail
|
|
for i, id := range assetIDs {
|
|
if strings.TrimSpace(id) == "" {
|
|
details = append(details, apivalidate.FieldDetail{
|
|
Field: field, Message: "invalid",
|
|
})
|
|
if i == 0 {
|
|
break
|
|
}
|
|
}
|
|
}
|
|
return details
|
|
}
|
|
|
|
func validateCreateAlbum(req *createAlbumRequest) *apivalidate.ValidationError {
|
|
var details []apivalidate.FieldDetail
|
|
if d := validateAlbumName("name", req.Name, true); d != nil {
|
|
details = append(details, *d)
|
|
}
|
|
if d := validateAlbumName("description", req.Description, false); d != nil {
|
|
details = append(details, *d)
|
|
}
|
|
details = append(details, validateAssetIDs("asset_ids", req.AssetIDs, false)...)
|
|
if len(details) == 0 {
|
|
return nil
|
|
}
|
|
return apivalidate.NewValidationError(details...)
|
|
}
|
|
|
|
func validateUpdateAlbum(req *updateAlbumRequest) *apivalidate.ValidationError {
|
|
if req.Name == nil && req.Description == nil {
|
|
return apivalidate.NewValidationError(apivalidate.FieldDetail{
|
|
Field: "body", Message: "required",
|
|
})
|
|
}
|
|
var details []apivalidate.FieldDetail
|
|
if req.Name != nil {
|
|
if d := validateAlbumName("name", *req.Name, true); d != nil {
|
|
details = append(details, *d)
|
|
}
|
|
}
|
|
if req.Description != nil {
|
|
if d := validateAlbumName("description", *req.Description, false); d != nil {
|
|
details = append(details, *d)
|
|
}
|
|
}
|
|
if len(details) == 0 {
|
|
return nil
|
|
}
|
|
return apivalidate.NewValidationError(details...)
|
|
}
|
|
|
|
func validateAlbumAssetsRequest(req *albumAssetsRequest) *apivalidate.ValidationError {
|
|
details := validateAssetIDs("asset_ids", req.AssetIDs, true)
|
|
if len(details) == 0 {
|
|
return nil
|
|
}
|
|
return apivalidate.NewValidationError(details...)
|
|
}
|