Backend: Add account API #225
Signed-off-by: Michael Mayer <michael@liquidbytes.net>
This commit is contained in:
parent
81dc7bbb19
commit
1d667ada79
38 changed files with 471 additions and 146 deletions
187
internal/api/account.go
Normal file
187
internal/api/account.go
Normal file
|
@ -0,0 +1,187 @@
|
|||
package api
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"strconv"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/gin-gonic/gin/binding"
|
||||
"github.com/photoprism/photoprism/internal/config"
|
||||
"github.com/photoprism/photoprism/internal/entity"
|
||||
"github.com/photoprism/photoprism/internal/event"
|
||||
"github.com/photoprism/photoprism/internal/form"
|
||||
"github.com/photoprism/photoprism/internal/query"
|
||||
"github.com/photoprism/photoprism/pkg/txt"
|
||||
)
|
||||
|
||||
// GET /api/v1/accounts
|
||||
func GetAccounts(router *gin.RouterGroup, conf *config.Config) {
|
||||
router.GET("/accounts", func(c *gin.Context) {
|
||||
if Unauthorized(c, conf) {
|
||||
c.AbortWithStatusJSON(http.StatusUnauthorized, ErrUnauthorized)
|
||||
return
|
||||
}
|
||||
|
||||
var f form.AccountSearch
|
||||
|
||||
q := query.New(conf.Db())
|
||||
err := c.MustBindWith(&f, binding.Form)
|
||||
|
||||
if err != nil {
|
||||
c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"error": txt.UcFirst(err.Error())})
|
||||
return
|
||||
}
|
||||
|
||||
result, err := q.Accounts(f)
|
||||
|
||||
if err != nil {
|
||||
c.AbortWithStatusJSON(400, gin.H{"error": txt.UcFirst(err.Error())})
|
||||
return
|
||||
}
|
||||
|
||||
c.Header("X-Result-Count", strconv.Itoa(f.Count))
|
||||
c.Header("X-Result-Offset", strconv.Itoa(f.Offset))
|
||||
|
||||
c.JSON(http.StatusOK, result)
|
||||
})
|
||||
}
|
||||
|
||||
// GET /api/v1/accounts/:id
|
||||
//
|
||||
// Parameters:
|
||||
// id: string Account ID as returned by the API
|
||||
func GetAccount(router *gin.RouterGroup, conf *config.Config) {
|
||||
router.GET("/accounts/:id", func(c *gin.Context) {
|
||||
if Unauthorized(c, conf) {
|
||||
c.AbortWithStatusJSON(http.StatusUnauthorized, ErrUnauthorized)
|
||||
return
|
||||
}
|
||||
|
||||
q := query.New(conf.Db())
|
||||
id := ParseUint(c.Param("id"))
|
||||
|
||||
if m, err := q.AccountByID(id); err == nil {
|
||||
c.JSON(http.StatusOK, m)
|
||||
} else {
|
||||
c.AbortWithStatusJSON(http.StatusNotFound, ErrAccountNotFound)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// POST /api/v1/accounts
|
||||
func CreateAccount(router *gin.RouterGroup, conf *config.Config) {
|
||||
router.POST("/accounts", func(c *gin.Context) {
|
||||
if Unauthorized(c, conf) {
|
||||
c.AbortWithStatusJSON(http.StatusUnauthorized, ErrUnauthorized)
|
||||
return
|
||||
}
|
||||
|
||||
var f form.Account
|
||||
|
||||
if err := c.BindJSON(&f); err != nil {
|
||||
c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"error": txt.UcFirst(err.Error())})
|
||||
return
|
||||
}
|
||||
|
||||
m, err := entity.CreateAccount(f, conf.Db())
|
||||
|
||||
log.Debugf("create account: %+v %+v", f, m)
|
||||
|
||||
if err != nil {
|
||||
log.Error(err)
|
||||
c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"error": err})
|
||||
return
|
||||
}
|
||||
|
||||
event.Success("account created")
|
||||
|
||||
c.JSON(http.StatusOK, m)
|
||||
})
|
||||
}
|
||||
|
||||
// PUT /api/v1/accounts/:id
|
||||
//
|
||||
// Parameters:
|
||||
// id: string Account ID as returned by the API
|
||||
func UpdateAccount(router *gin.RouterGroup, conf *config.Config) {
|
||||
router.PUT("/accounts/:id", func(c *gin.Context) {
|
||||
if Unauthorized(c, conf) {
|
||||
c.AbortWithStatusJSON(http.StatusUnauthorized, ErrUnauthorized)
|
||||
return
|
||||
}
|
||||
|
||||
id := ParseUint(c.Param("id"))
|
||||
|
||||
q := query.New(conf.Db())
|
||||
|
||||
m, err := q.AccountByID(id)
|
||||
|
||||
if err != nil {
|
||||
c.AbortWithStatusJSON(http.StatusNotFound, ErrPhotoNotFound)
|
||||
return
|
||||
}
|
||||
|
||||
// 1) Init form with model values
|
||||
f, err := form.NewAccount(m)
|
||||
|
||||
if err != nil {
|
||||
c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"error": txt.UcFirst(err.Error())})
|
||||
return
|
||||
}
|
||||
|
||||
// 2) Update form with values from request
|
||||
if err := c.BindJSON(&f); err != nil {
|
||||
c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"error": txt.UcFirst(err.Error())})
|
||||
return
|
||||
}
|
||||
|
||||
// 3) Save model with values from form
|
||||
if err := m.Save(f, conf.Db()); err != nil {
|
||||
c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"error": txt.UcFirst(err.Error())})
|
||||
return
|
||||
}
|
||||
|
||||
event.Success("account saved")
|
||||
|
||||
m, err = q.AccountByID(id)
|
||||
|
||||
if err != nil {
|
||||
c.AbortWithStatusJSON(http.StatusNotFound, ErrAccountNotFound)
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, m)
|
||||
})
|
||||
}
|
||||
|
||||
// DELETE /api/v1/accounts/:id
|
||||
//
|
||||
// Parameters:
|
||||
// id: string Account ID as returned by the API
|
||||
func DeleteAccount(router *gin.RouterGroup, conf *config.Config) {
|
||||
router.DELETE("/accounts/:id", func(c *gin.Context) {
|
||||
if Unauthorized(c, conf) {
|
||||
c.AbortWithStatusJSON(http.StatusUnauthorized, ErrUnauthorized)
|
||||
return
|
||||
}
|
||||
|
||||
id := ParseUint(c.Param("id"))
|
||||
q := query.New(conf.Db())
|
||||
|
||||
m, err := q.AccountByID(id)
|
||||
|
||||
if err != nil {
|
||||
c.AbortWithStatusJSON(http.StatusNotFound, ErrAccountNotFound)
|
||||
return
|
||||
}
|
||||
|
||||
if err := m.Delete(conf.Db()); err != nil {
|
||||
c.AbortWithStatusJSON(http.StatusInternalServerError, err)
|
||||
return
|
||||
}
|
||||
|
||||
event.Success("account deleted")
|
||||
|
||||
c.JSON(http.StatusOK, m)
|
||||
})
|
||||
}
|
|
@ -35,7 +35,7 @@ func GetAlbums(router *gin.RouterGroup, conf *config.Config) {
|
|||
|
||||
var f form.AlbumSearch
|
||||
|
||||
q := query.New(conf.OriginalsPath(), conf.Db())
|
||||
q := query.New(conf.Db())
|
||||
err := c.MustBindWith(&f, binding.Form)
|
||||
|
||||
if err != nil {
|
||||
|
@ -60,8 +60,8 @@ func GetAlbums(router *gin.RouterGroup, conf *config.Config) {
|
|||
func GetAlbum(router *gin.RouterGroup, conf *config.Config) {
|
||||
router.GET("/albums/:uuid", func(c *gin.Context) {
|
||||
id := c.Param("uuid")
|
||||
q := query.New(conf.OriginalsPath(), conf.Db())
|
||||
m, err := q.FindAlbumByUUID(id)
|
||||
q := query.New(conf.Db())
|
||||
m, err := q.AlbumByUUID(id)
|
||||
|
||||
if err != nil {
|
||||
c.AbortWithStatusJSON(http.StatusNotFound, ErrAlbumNotFound)
|
||||
|
@ -87,7 +87,7 @@ func CreateAlbum(router *gin.RouterGroup, conf *config.Config) {
|
|||
return
|
||||
}
|
||||
|
||||
q := query.New(conf.OriginalsPath(), conf.Db())
|
||||
q := query.New(conf.Db())
|
||||
m := entity.NewAlbum(f.AlbumName)
|
||||
m.AlbumFavorite = f.AlbumFavorite
|
||||
|
||||
|
@ -125,9 +125,9 @@ func UpdateAlbum(router *gin.RouterGroup, conf *config.Config) {
|
|||
}
|
||||
|
||||
id := c.Param("uuid")
|
||||
q := query.New(conf.OriginalsPath(), conf.Db())
|
||||
q := query.New(conf.Db())
|
||||
|
||||
m, err := q.FindAlbumByUUID(id)
|
||||
m, err := q.AlbumByUUID(id)
|
||||
|
||||
if err != nil {
|
||||
c.AbortWithStatusJSON(http.StatusNotFound, ErrAlbumNotFound)
|
||||
|
@ -155,9 +155,9 @@ func DeleteAlbum(router *gin.RouterGroup, conf *config.Config) {
|
|||
}
|
||||
|
||||
id := c.Param("uuid")
|
||||
q := query.New(conf.OriginalsPath(), conf.Db())
|
||||
q := query.New(conf.Db())
|
||||
|
||||
m, err := q.FindAlbumByUUID(id)
|
||||
m, err := q.AlbumByUUID(id)
|
||||
|
||||
if err != nil {
|
||||
c.AbortWithStatusJSON(http.StatusNotFound, ErrAlbumNotFound)
|
||||
|
@ -187,9 +187,9 @@ func LikeAlbum(router *gin.RouterGroup, conf *config.Config) {
|
|||
}
|
||||
|
||||
id := c.Param("uuid")
|
||||
q := query.New(conf.OriginalsPath(), conf.Db())
|
||||
q := query.New(conf.Db())
|
||||
|
||||
album, err := q.FindAlbumByUUID(id)
|
||||
album, err := q.AlbumByUUID(id)
|
||||
|
||||
if err != nil {
|
||||
c.AbortWithStatusJSON(http.StatusNotFound, ErrAlbumNotFound)
|
||||
|
@ -218,8 +218,8 @@ func DislikeAlbum(router *gin.RouterGroup, conf *config.Config) {
|
|||
}
|
||||
|
||||
id := c.Param("uuid")
|
||||
q := query.New(conf.OriginalsPath(), conf.Db())
|
||||
album, err := q.FindAlbumByUUID(id)
|
||||
q := query.New(conf.Db())
|
||||
album, err := q.AlbumByUUID(id)
|
||||
|
||||
if err != nil {
|
||||
c.AbortWithStatusJSON(http.StatusNotFound, ErrAlbumNotFound)
|
||||
|
@ -252,8 +252,8 @@ func AddPhotosToAlbum(router *gin.RouterGroup, conf *config.Config) {
|
|||
}
|
||||
|
||||
uuid := c.Param("uuid")
|
||||
q := query.New(conf.OriginalsPath(), conf.Db())
|
||||
a, err := q.FindAlbumByUUID(uuid)
|
||||
q := query.New(conf.Db())
|
||||
a, err := q.AlbumByUUID(uuid)
|
||||
|
||||
if err != nil {
|
||||
c.AbortWithStatusJSON(http.StatusNotFound, ErrAlbumNotFound)
|
||||
|
@ -308,8 +308,8 @@ func RemovePhotosFromAlbum(router *gin.RouterGroup, conf *config.Config) {
|
|||
return
|
||||
}
|
||||
|
||||
q := query.New(conf.OriginalsPath(), conf.Db())
|
||||
a, err := q.FindAlbumByUUID(c.Param("uuid"))
|
||||
q := query.New(conf.Db())
|
||||
a, err := q.AlbumByUUID(c.Param("uuid"))
|
||||
|
||||
if err != nil {
|
||||
c.AbortWithStatusJSON(http.StatusNotFound, ErrAlbumNotFound)
|
||||
|
@ -333,8 +333,8 @@ func DownloadAlbum(router *gin.RouterGroup, conf *config.Config) {
|
|||
router.GET("/albums/:uuid/download", func(c *gin.Context) {
|
||||
start := time.Now()
|
||||
|
||||
q := query.New(conf.OriginalsPath(), conf.Db())
|
||||
a, err := q.FindAlbumByUUID(c.Param("uuid"))
|
||||
q := query.New(conf.Db())
|
||||
a, err := q.AlbumByUUID(c.Param("uuid"))
|
||||
|
||||
if err != nil {
|
||||
c.AbortWithStatusJSON(http.StatusNotFound, ErrAlbumNotFound)
|
||||
|
@ -434,7 +434,7 @@ func AlbumThumbnail(router *gin.RouterGroup, conf *config.Config) {
|
|||
return
|
||||
}
|
||||
|
||||
q := query.New(conf.OriginalsPath(), conf.Db())
|
||||
q := query.New(conf.Db())
|
||||
|
||||
gc := conf.Cache()
|
||||
cacheKey := fmt.Sprintf("album-thumbnail:%s:%s", uuid, typeName)
|
||||
|
@ -445,7 +445,7 @@ func AlbumThumbnail(router *gin.RouterGroup, conf *config.Config) {
|
|||
return
|
||||
}
|
||||
|
||||
f, err := q.FindAlbumThumbByUUID(uuid)
|
||||
f, err := q.AlbumThumbByUUID(uuid)
|
||||
|
||||
if err != nil {
|
||||
log.Debugf("album: no photos yet, using generic image for %s", uuid)
|
||||
|
|
|
@ -23,8 +23,8 @@ func GetDownload(router *gin.RouterGroup, conf *config.Config) {
|
|||
router.GET("/download/:hash", func(c *gin.Context) {
|
||||
fileHash := c.Param("hash")
|
||||
|
||||
q := query.New(conf.OriginalsPath(), conf.Db())
|
||||
f, err := q.FindFileByHash(fileHash)
|
||||
q := query.New(conf.Db())
|
||||
f, err := q.FileByHash(fileHash)
|
||||
|
||||
if err != nil {
|
||||
c.AbortWithStatusJSON(404, gin.H{"error": err.Error()})
|
||||
|
|
|
@ -12,6 +12,7 @@ var (
|
|||
ErrUnauthorized = gin.H{"code": http.StatusUnauthorized, "error": txt.UcFirst(config.ErrUnauthorized.Error())}
|
||||
ErrReadOnly = gin.H{"code": http.StatusForbidden, "error": txt.UcFirst(config.ErrReadOnly.Error())}
|
||||
ErrUploadNSFW = gin.H{"code": http.StatusForbidden, "error": txt.UcFirst(config.ErrUploadNSFW.Error())}
|
||||
ErrAccountNotFound = gin.H{"code": http.StatusNotFound, "error": "Account not found"}
|
||||
ErrAlbumNotFound = gin.H{"code": http.StatusNotFound, "error": "Album not found"}
|
||||
ErrPhotoNotFound = gin.H{"code": http.StatusNotFound, "error": "Photo not found"}
|
||||
ErrLabelNotFound = gin.H{"code": http.StatusNotFound, "error": "Label not found"}
|
||||
|
|
|
@ -17,7 +17,7 @@ const (
|
|||
EntityDeleted EntityEvent = "deleted"
|
||||
)
|
||||
|
||||
func PublishPhotoEvent(e EntityEvent, uuid string, c *gin.Context, q *query.Repo) {
|
||||
func PublishPhotoEvent(e EntityEvent, uuid string, c *gin.Context, q *query.Query) {
|
||||
f := form.PhotoSearch{ID: uuid}
|
||||
result, err := q.Photos(f)
|
||||
|
||||
|
@ -30,7 +30,7 @@ func PublishPhotoEvent(e EntityEvent, uuid string, c *gin.Context, q *query.Repo
|
|||
event.PublishEntities("photos", string(e), result)
|
||||
}
|
||||
|
||||
func PublishAlbumEvent(e EntityEvent, uuid string, c *gin.Context, q *query.Repo) {
|
||||
func PublishAlbumEvent(e EntityEvent, uuid string, c *gin.Context, q *query.Query) {
|
||||
f := form.AlbumSearch{ID: uuid}
|
||||
result, err := q.Albums(f)
|
||||
|
||||
|
@ -43,7 +43,7 @@ func PublishAlbumEvent(e EntityEvent, uuid string, c *gin.Context, q *query.Repo
|
|||
event.PublishEntities("albums", string(e), result)
|
||||
}
|
||||
|
||||
func PublishLabelEvent(e EntityEvent, uuid string, c *gin.Context, q *query.Repo) {
|
||||
func PublishLabelEvent(e EntityEvent, uuid string, c *gin.Context, q *query.Query) {
|
||||
f := form.LabelSearch{ID: uuid}
|
||||
result, err := q.Labels(f)
|
||||
|
||||
|
|
|
@ -19,8 +19,8 @@ func GetFile(router *gin.RouterGroup, conf *config.Config) {
|
|||
return
|
||||
}
|
||||
|
||||
q := query.New(conf.OriginalsPath(), conf.Db())
|
||||
p, err := q.FindFileByHash(c.Param("hash"))
|
||||
q := query.New(conf.Db())
|
||||
p, err := q.FileByHash(c.Param("hash"))
|
||||
|
||||
if err != nil {
|
||||
c.AbortWithStatusJSON(http.StatusNotFound, ErrPhotoNotFound)
|
||||
|
|
|
@ -24,7 +24,7 @@ func GetGeo(router *gin.RouterGroup, conf *config.Config) {
|
|||
|
||||
var f form.GeoSearch
|
||||
|
||||
q := query.New(conf.OriginalsPath(), conf.Db())
|
||||
q := query.New(conf.Db())
|
||||
err := c.MustBindWith(&f, binding.Form)
|
||||
|
||||
if err != nil {
|
||||
|
|
|
@ -29,7 +29,7 @@ func GetLabels(router *gin.RouterGroup, conf *config.Config) {
|
|||
|
||||
var f form.LabelSearch
|
||||
|
||||
q := query.New(conf.OriginalsPath(), conf.Db())
|
||||
q := query.New(conf.Db())
|
||||
err := c.MustBindWith(&f, binding.Form)
|
||||
|
||||
if err != nil {
|
||||
|
@ -66,9 +66,9 @@ func UpdateLabel(router *gin.RouterGroup, conf *config.Config) {
|
|||
}
|
||||
|
||||
id := c.Param("uuid")
|
||||
q := query.New(conf.OriginalsPath(), conf.Db())
|
||||
q := query.New(conf.Db())
|
||||
|
||||
m, err := q.FindLabelByUUID(id)
|
||||
m, err := q.LabelByUUID(id)
|
||||
|
||||
if err != nil {
|
||||
c.AbortWithStatusJSON(http.StatusNotFound, ErrLabelNotFound)
|
||||
|
@ -98,9 +98,9 @@ func LikeLabel(router *gin.RouterGroup, conf *config.Config) {
|
|||
}
|
||||
|
||||
id := c.Param("uuid")
|
||||
q := query.New(conf.OriginalsPath(), conf.Db())
|
||||
q := query.New(conf.Db())
|
||||
|
||||
label, err := q.FindLabelByUUID(id)
|
||||
label, err := q.LabelByUUID(id)
|
||||
|
||||
if err != nil {
|
||||
c.AbortWithStatusJSON(404, gin.H{"error": txt.UcFirst(err.Error())})
|
||||
|
@ -134,9 +134,9 @@ func DislikeLabel(router *gin.RouterGroup, conf *config.Config) {
|
|||
}
|
||||
|
||||
id := c.Param("uuid")
|
||||
q := query.New(conf.OriginalsPath(), conf.Db())
|
||||
q := query.New(conf.Db())
|
||||
|
||||
label, err := q.FindLabelByUUID(id)
|
||||
label, err := q.LabelByUUID(id)
|
||||
|
||||
if err != nil {
|
||||
c.AbortWithStatusJSON(404, gin.H{"error": txt.UcFirst(err.Error())})
|
||||
|
@ -179,7 +179,7 @@ func LabelThumbnail(router *gin.RouterGroup, conf *config.Config) {
|
|||
return
|
||||
}
|
||||
|
||||
q := query.New(conf.OriginalsPath(), conf.Db())
|
||||
q := query.New(conf.Db())
|
||||
|
||||
gc := conf.Cache()
|
||||
cacheKey := fmt.Sprintf("label-thumbnail:%s:%s", labelUUID, typeName)
|
||||
|
@ -190,7 +190,7 @@ func LabelThumbnail(router *gin.RouterGroup, conf *config.Config) {
|
|||
return
|
||||
}
|
||||
|
||||
f, err := q.FindLabelThumbByUUID(labelUUID)
|
||||
f, err := q.LabelThumbByUUID(labelUUID)
|
||||
|
||||
if err != nil {
|
||||
log.Errorf(err.Error())
|
||||
|
|
|
@ -18,7 +18,7 @@ func GetMomentsTime(router *gin.RouterGroup, conf *config.Config) {
|
|||
return
|
||||
}
|
||||
|
||||
q := query.New(conf.OriginalsPath(), conf.Db())
|
||||
q := query.New(conf.Db())
|
||||
|
||||
result, err := q.GetMomentsTime()
|
||||
if err != nil {
|
||||
|
|
13
internal/api/parse.go
Normal file
13
internal/api/parse.go
Normal file
|
@ -0,0 +1,13 @@
|
|||
package api
|
||||
|
||||
import "strconv"
|
||||
|
||||
func ParseUint(s string) uint {
|
||||
result, err := strconv.ParseUint(s, 10, 32)
|
||||
|
||||
if err != nil {
|
||||
log.Warnf("api: %s", err)
|
||||
}
|
||||
|
||||
return uint(result)
|
||||
}
|
|
@ -26,7 +26,7 @@ func GetPhoto(router *gin.RouterGroup, conf *config.Config) {
|
|||
return
|
||||
}
|
||||
|
||||
q := query.New(conf.OriginalsPath(), conf.Db())
|
||||
q := query.New(conf.Db())
|
||||
p, err := q.PreloadPhotoByUUID(c.Param("uuid"))
|
||||
|
||||
if err != nil {
|
||||
|
@ -47,9 +47,9 @@ func UpdatePhoto(router *gin.RouterGroup, conf *config.Config) {
|
|||
}
|
||||
|
||||
id := c.Param("uuid")
|
||||
q := query.New(conf.OriginalsPath(), conf.Db())
|
||||
q := query.New(conf.Db())
|
||||
|
||||
m, err := q.FindPhotoByUUID(id)
|
||||
m, err := q.PhotoByUUID(id)
|
||||
|
||||
if err != nil {
|
||||
c.AbortWithStatusJSON(http.StatusNotFound, ErrPhotoNotFound)
|
||||
|
@ -98,8 +98,8 @@ func UpdatePhoto(router *gin.RouterGroup, conf *config.Config) {
|
|||
// uuid: string PhotoUUID as returned by the API
|
||||
func GetPhotoDownload(router *gin.RouterGroup, conf *config.Config) {
|
||||
router.GET("/photos/:uuid/download", func(c *gin.Context) {
|
||||
q := query.New(conf.OriginalsPath(), conf.Db())
|
||||
f, err := q.FindFileByPhotoUUID(c.Param("uuid"))
|
||||
q := query.New(conf.Db())
|
||||
f, err := q.FileByPhotoUUID(c.Param("uuid"))
|
||||
|
||||
if err != nil {
|
||||
c.AbortWithStatusJSON(http.StatusNotFound, ErrPhotoNotFound)
|
||||
|
@ -138,8 +138,8 @@ func LikePhoto(router *gin.RouterGroup, conf *config.Config) {
|
|||
}
|
||||
|
||||
id := c.Param("uuid")
|
||||
q := query.New(conf.OriginalsPath(), conf.Db())
|
||||
m, err := q.FindPhotoByUUID(id)
|
||||
q := query.New(conf.Db())
|
||||
m, err := q.PhotoByUUID(id)
|
||||
|
||||
if err != nil {
|
||||
c.AbortWithStatusJSON(http.StatusNotFound, ErrPhotoNotFound)
|
||||
|
@ -171,8 +171,8 @@ func DislikePhoto(router *gin.RouterGroup, conf *config.Config) {
|
|||
}
|
||||
|
||||
id := c.Param("uuid")
|
||||
q := query.New(conf.OriginalsPath(), conf.Db())
|
||||
m, err := q.FindPhotoByUUID(id)
|
||||
q := query.New(conf.Db())
|
||||
m, err := q.PhotoByUUID(id)
|
||||
|
||||
if err != nil {
|
||||
c.AbortWithStatusJSON(http.StatusNotFound, ErrPhotoNotFound)
|
||||
|
|
|
@ -24,8 +24,8 @@ func AddPhotoLabel(router *gin.RouterGroup, conf *config.Config) {
|
|||
return
|
||||
}
|
||||
|
||||
q := query.New(conf.OriginalsPath(), conf.Db())
|
||||
m, err := q.FindPhotoByUUID(c.Param("uuid"))
|
||||
q := query.New(conf.Db())
|
||||
m, err := q.PhotoByUUID(c.Param("uuid"))
|
||||
db := conf.Db()
|
||||
|
||||
if err != nil {
|
||||
|
@ -84,8 +84,8 @@ func RemovePhotoLabel(router *gin.RouterGroup, conf *config.Config) {
|
|||
return
|
||||
}
|
||||
|
||||
q := query.New(conf.OriginalsPath(), conf.Db())
|
||||
m, err := q.FindPhotoByUUID(c.Param("uuid"))
|
||||
q := query.New(conf.Db())
|
||||
m, err := q.PhotoByUUID(c.Param("uuid"))
|
||||
|
||||
if err != nil {
|
||||
c.AbortWithStatusJSON(http.StatusNotFound, ErrPhotoNotFound)
|
||||
|
|
|
@ -36,7 +36,7 @@ func GetPhotos(router *gin.RouterGroup, conf *config.Config) {
|
|||
|
||||
var f form.PhotoSearch
|
||||
|
||||
q := query.New(conf.OriginalsPath(), conf.Db())
|
||||
q := query.New(conf.Db())
|
||||
err := c.MustBindWith(&f, binding.Form)
|
||||
|
||||
if err != nil {
|
||||
|
|
|
@ -31,8 +31,8 @@ func GetThumbnail(router *gin.RouterGroup, conf *config.Config) {
|
|||
}
|
||||
|
||||
db := conf.Db()
|
||||
q := query.New(conf.OriginalsPath(), db)
|
||||
f, err := q.FindFileByHash(fileHash)
|
||||
q := query.New(db)
|
||||
f, err := q.FileByHash(fileHash)
|
||||
|
||||
if err != nil {
|
||||
c.Data(http.StatusNotFound, "image/svg+xml", photoIconSvg)
|
||||
|
|
|
@ -45,7 +45,7 @@ func GetPreview(router *gin.RouterGroup, conf *config.Config) {
|
|||
f.Count = 12
|
||||
f.Order = "relevance"
|
||||
|
||||
q := query.New(conf.OriginalsPath(), conf.Db())
|
||||
q := query.New(conf.Db())
|
||||
p, err := q.Photos(f)
|
||||
|
||||
if err != nil {
|
||||
|
|
|
@ -42,8 +42,8 @@ func CreateZip(router *gin.RouterGroup, conf *config.Config) {
|
|||
return
|
||||
}
|
||||
|
||||
q := query.New(conf.OriginalsPath(), conf.Db())
|
||||
files, err := q.FindFilesByUUID(f.Photos, 1000, 0)
|
||||
q := query.New(conf.Db())
|
||||
files, err := q.FilesByUUID(f.Photos, 1000, 0)
|
||||
|
||||
if err != nil {
|
||||
c.AbortWithStatusJSON(404, gin.H{"error": err.Error()})
|
||||
|
|
|
@ -3,6 +3,10 @@ package entity
|
|||
import (
|
||||
"database/sql"
|
||||
"time"
|
||||
|
||||
"github.com/jinzhu/gorm"
|
||||
"github.com/photoprism/photoprism/internal/form"
|
||||
"github.com/ulule/deepcopier"
|
||||
)
|
||||
|
||||
// Account represents a remote service account for uploading, downloading or syncing media files.
|
||||
|
@ -38,3 +42,30 @@ type Account struct {
|
|||
UpdatedAt time.Time
|
||||
DeletedAt *time.Time `sql:"index"`
|
||||
}
|
||||
|
||||
// CreateAccount creates a new account entity in the database.
|
||||
func CreateAccount(form form.Account, db *gorm.DB) (model *Account, err error) {
|
||||
model = &Account{}
|
||||
|
||||
if err := deepcopier.Copy(&model).From(form); err != nil {
|
||||
return model, err
|
||||
}
|
||||
|
||||
err = db.Save(&model).Error
|
||||
|
||||
return model, err
|
||||
}
|
||||
|
||||
// Save updates the entity using form data and stores it in the database.
|
||||
func (m *Account) Save(form form.Account, db *gorm.DB) error {
|
||||
if err := deepcopier.Copy(m).From(form); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return db.Save(m).Error
|
||||
}
|
||||
|
||||
// Delete deletes the entity from the database.
|
||||
func (m *Account) Delete(db *gorm.DB) error {
|
||||
return db.Delete(m).Error
|
||||
}
|
||||
|
|
|
@ -74,8 +74,6 @@ func SavePhoto(model Photo, form form.Photo, db *gorm.DB) error {
|
|||
model.Description.PhotoKeywords = strings.Join(txt.UniqueKeywords(model.Description.PhotoKeywords), ", ")
|
||||
}
|
||||
|
||||
log.Debugf("model: %+v", model)
|
||||
|
||||
model.IndexKeywords(db)
|
||||
|
||||
return db.Save(&model).Error
|
||||
|
|
42
internal/form/account.go
Normal file
42
internal/form/account.go
Normal file
|
@ -0,0 +1,42 @@
|
|||
package form
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
|
||||
"github.com/ulule/deepcopier"
|
||||
)
|
||||
|
||||
// Account represents a remote service account form for uploading, downloading or syncing media files.
|
||||
type Account struct {
|
||||
AccName string `json:"AccName"`
|
||||
AccOwner string `json:"AccOwner"`
|
||||
AccURL string `json:"AccURL"`
|
||||
AccType string `json:"AccType"`
|
||||
AccKey string `json:"AccKey"`
|
||||
AccUser string `json:"AccUser"`
|
||||
AccPass string `json:"AccPass"`
|
||||
AccError string `json:"AccError"`
|
||||
AccPush bool `json:"AccPush"`
|
||||
AccSync bool `json:"AccSync"`
|
||||
RetryLimit uint `json:"RetryLimit"`
|
||||
PushPath string `json:"PushPath"`
|
||||
PushSize string `json:"PushSize"`
|
||||
PushExpires uint `json:"PushExpires"`
|
||||
PushExif bool `json:"PushExif"`
|
||||
PushSidecar bool `json:"PushSidecar"`
|
||||
SyncPath string `json:"SyncPath"`
|
||||
SyncInterval uint `json:"SyncInterval"`
|
||||
SyncUpload bool `json:"SyncUpload"`
|
||||
SyncDownload bool `json:"SyncDownload"`
|
||||
SyncDelete bool `json:"SyncDelete"`
|
||||
SyncRaw bool `json:"SyncRaw"`
|
||||
SyncVideo bool `json:"SyncVideo"`
|
||||
SyncSidecar bool `json:"SyncSidecar"`
|
||||
SyncStart sql.NullTime `json:"SyncStart"`
|
||||
}
|
||||
|
||||
func NewAccount(m interface{}) (f Account, err error) {
|
||||
err = deepcopier.Copy(m).To(&f)
|
||||
|
||||
return f, err
|
||||
}
|
25
internal/form/account_search.go
Normal file
25
internal/form/account_search.go
Normal file
|
@ -0,0 +1,25 @@
|
|||
package form
|
||||
|
||||
// AccountSearch represents search form fields for "/api/v1/accounts".
|
||||
type AccountSearch struct {
|
||||
Query string `form:"q"`
|
||||
Count int `form:"count" binding:"required"`
|
||||
Offset int `form:"offset"`
|
||||
Order string `form:"order"`
|
||||
}
|
||||
|
||||
func (f *AccountSearch) GetQuery() string {
|
||||
return f.Query
|
||||
}
|
||||
|
||||
func (f *AccountSearch) SetQuery(q string) {
|
||||
f.Query = q
|
||||
}
|
||||
|
||||
func (f *AccountSearch) ParseQueryString() error {
|
||||
return ParseQueryString(f)
|
||||
}
|
||||
|
||||
func NewAccountSearch(query string) AccountSearch {
|
||||
return AccountSearch{Query: query}
|
||||
}
|
24
internal/query/account.go
Normal file
24
internal/query/account.go
Normal file
|
@ -0,0 +1,24 @@
|
|||
package query
|
||||
|
||||
import (
|
||||
"github.com/photoprism/photoprism/internal/entity"
|
||||
"github.com/photoprism/photoprism/internal/form"
|
||||
)
|
||||
|
||||
// FindAccounts returns a list of accounts.
|
||||
func (s *Query) Accounts(f form.AccountSearch) (result []entity.Account, err error) {
|
||||
if err := s.db.Where(&entity.Account{}).Limit(f.Count).Offset(f.Offset).Find(&result).Error; err != nil {
|
||||
return result, err
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// AccountByID finds an account by primary key.
|
||||
func (s *Query) AccountByID(id uint) (result entity.Account, err error) {
|
||||
if err := s.db.Where("id = ?", id).First(&result).Error; err != nil {
|
||||
return result, err
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
|
@ -25,8 +25,8 @@ type AlbumResult struct {
|
|||
AlbumNotes string
|
||||
}
|
||||
|
||||
// FindAlbumByUUID returns a Album based on the UUID.
|
||||
func (s *Repo) FindAlbumByUUID(albumUUID string) (album entity.Album, err error) {
|
||||
// AlbumByUUID returns a Album based on the UUID.
|
||||
func (s *Query) AlbumByUUID(albumUUID string) (album entity.Album, err error) {
|
||||
if err := s.db.Where("album_uuid = ?", albumUUID).First(&album).Error; err != nil {
|
||||
return album, err
|
||||
}
|
||||
|
@ -34,8 +34,8 @@ func (s *Repo) FindAlbumByUUID(albumUUID string) (album entity.Album, err error)
|
|||
return album, nil
|
||||
}
|
||||
|
||||
// FindAlbumThumbByUUID returns a album preview file based on the uuid.
|
||||
func (s *Repo) FindAlbumThumbByUUID(albumUUID string) (file entity.File, err error) {
|
||||
// AlbumThumbByUUID returns a album preview file based on the uuid.
|
||||
func (s *Query) AlbumThumbByUUID(albumUUID string) (file entity.File, err error) {
|
||||
// s.db.LogMode(true)
|
||||
|
||||
if err := s.db.Where("files.file_primary AND files.deleted_at IS NULL").
|
||||
|
@ -49,7 +49,7 @@ func (s *Repo) FindAlbumThumbByUUID(albumUUID string) (file entity.File, err err
|
|||
}
|
||||
|
||||
// Albums searches albums based on their name.
|
||||
func (s *Repo) Albums(f form.AlbumSearch) (results []AlbumResult, err error) {
|
||||
func (s *Query) Albums(f form.AlbumSearch) (results []AlbumResult, err error) {
|
||||
if err := f.ParseQueryString(); err != nil {
|
||||
return results, err
|
||||
}
|
||||
|
|
|
@ -11,16 +11,16 @@ import (
|
|||
func TestRepo_FindAlbumByUUID(t *testing.T) {
|
||||
conf := config.TestConfig()
|
||||
|
||||
search := New(conf.OriginalsPath(), conf.Db())
|
||||
search := New(conf.Db())
|
||||
|
||||
t.Run("existing uuid", func(t *testing.T) {
|
||||
albums, err := search.FindAlbumByUUID("3")
|
||||
albums, err := search.AlbumByUUID("3")
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, "Christmas2030", albums.AlbumName)
|
||||
})
|
||||
|
||||
t.Run("not existing uuid", func(t *testing.T) {
|
||||
albums, err := search.FindAlbumByUUID("3765")
|
||||
albums, err := search.AlbumByUUID("3765")
|
||||
assert.Error(t, err, "record not found")
|
||||
t.Log(albums)
|
||||
})
|
||||
|
@ -29,16 +29,16 @@ func TestRepo_FindAlbumByUUID(t *testing.T) {
|
|||
func TestRepo_FindAlbumThumbByUUID(t *testing.T) {
|
||||
conf := config.TestConfig()
|
||||
|
||||
search := New(conf.OriginalsPath(), conf.Db())
|
||||
search := New(conf.Db())
|
||||
|
||||
t.Run("existing uuid", func(t *testing.T) {
|
||||
file, err := search.FindAlbumThumbByUUID("4")
|
||||
file, err := search.AlbumThumbByUUID("4")
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, "exampleFileName.jpg", file.FileName)
|
||||
})
|
||||
|
||||
t.Run("not existing uuid", func(t *testing.T) {
|
||||
file, err := search.FindAlbumThumbByUUID("3765")
|
||||
file, err := search.AlbumThumbByUUID("3765")
|
||||
assert.Error(t, err, "record not found")
|
||||
t.Log(file)
|
||||
})
|
||||
|
@ -47,7 +47,7 @@ func TestRepo_FindAlbumThumbByUUID(t *testing.T) {
|
|||
func TestRepo_Albums(t *testing.T) {
|
||||
conf := config.TestConfig()
|
||||
|
||||
search := New(conf.OriginalsPath(), conf.Db())
|
||||
search := New(conf.Db())
|
||||
|
||||
t.Run("search with string", func(t *testing.T) {
|
||||
query := form.NewAlbumSearch("chr")
|
||||
|
|
|
@ -9,7 +9,7 @@ type CategoryLabel struct {
|
|||
Title string
|
||||
}
|
||||
|
||||
func (s *Repo) CategoryLabels(limit, offset int) (results []CategoryLabel) {
|
||||
func (s *Query) CategoryLabels(limit, offset int) (results []CategoryLabel) {
|
||||
q := s.db.NewScope(nil).DB()
|
||||
|
||||
q = q.Table("categories").
|
||||
|
|
|
@ -10,7 +10,7 @@ import (
|
|||
func TestRepo_CategoryLabels(t *testing.T) {
|
||||
conf := config.TestConfig()
|
||||
|
||||
search := New(conf.OriginalsPath(), conf.Db())
|
||||
search := New(conf.Db())
|
||||
|
||||
categories := search.CategoryLabels(1000, 0)
|
||||
|
||||
|
|
|
@ -2,9 +2,9 @@ package query
|
|||
|
||||
import "github.com/photoprism/photoprism/internal/entity"
|
||||
|
||||
// FindFiles finds files returning maximum results defined by limit
|
||||
// Files finds files returning maximum results defined by limit
|
||||
// and finding them from an offest defined by offset.
|
||||
func (s *Repo) FindFiles(limit int, offset int) (files []entity.File, err error) {
|
||||
func (s *Query) Files(limit int, offset int) (files []entity.File, err error) {
|
||||
if err := s.db.Where(&entity.File{}).Limit(limit).Offset(offset).Find(&files).Error; err != nil {
|
||||
return files, err
|
||||
}
|
||||
|
@ -12,8 +12,8 @@ func (s *Repo) FindFiles(limit int, offset int) (files []entity.File, err error)
|
|||
return files, nil
|
||||
}
|
||||
|
||||
// FindFilesByUUID
|
||||
func (s *Repo) FindFilesByUUID(u []string, limit int, offset int) (files []entity.File, err error) {
|
||||
// FilesByUUID
|
||||
func (s *Query) FilesByUUID(u []string, limit int, offset int) (files []entity.File, err error) {
|
||||
if err := s.db.Where("(photo_uuid IN (?) AND file_primary = 1) OR file_uuid IN (?)", u, u).Preload("Photo").Limit(limit).Offset(offset).Find(&files).Error; err != nil {
|
||||
return files, err
|
||||
}
|
||||
|
@ -21,8 +21,8 @@ func (s *Repo) FindFilesByUUID(u []string, limit int, offset int) (files []entit
|
|||
return files, nil
|
||||
}
|
||||
|
||||
// FindFileByPhotoUUID
|
||||
func (s *Repo) FindFileByPhotoUUID(u string) (file entity.File, err error) {
|
||||
// FileByPhotoUUID
|
||||
func (s *Query) FileByPhotoUUID(u string) (file entity.File, err error) {
|
||||
if err := s.db.Where("photo_uuid = ? AND file_primary = 1", u).Preload("Photo").First(&file).Error; err != nil {
|
||||
return file, err
|
||||
}
|
||||
|
@ -30,8 +30,8 @@ func (s *Repo) FindFileByPhotoUUID(u string) (file entity.File, err error) {
|
|||
return file, nil
|
||||
}
|
||||
|
||||
// FindFileByID returns a MediaFile given a certain ID.
|
||||
func (s *Repo) FindFileByID(id string) (file entity.File, err error) {
|
||||
// FileByID returns a MediaFile given a certain ID.
|
||||
func (s *Query) FileByID(id string) (file entity.File, err error) {
|
||||
if err := s.db.Where("id = ?", id).Preload("Photo").First(&file).Error; err != nil {
|
||||
return file, err
|
||||
}
|
||||
|
@ -40,7 +40,7 @@ func (s *Repo) FindFileByID(id string) (file entity.File, err error) {
|
|||
}
|
||||
|
||||
// FirstFileByHash finds a file with a given hash string.
|
||||
func (s *Repo) FindFileByHash(fileHash string) (file entity.File, err error) {
|
||||
func (s *Query) FileByHash(fileHash string) (file entity.File, err error) {
|
||||
if err := s.db.Where("file_hash = ?", fileHash).Preload("Photo").First(&file).Error; err != nil {
|
||||
return file, err
|
||||
}
|
||||
|
|
|
@ -10,10 +10,10 @@ import (
|
|||
func TestRepo_FindFiles(t *testing.T) {
|
||||
conf := config.TestConfig()
|
||||
|
||||
search := New(conf.OriginalsPath(), conf.Db())
|
||||
search := New(conf.Db())
|
||||
|
||||
t.Run("files found", func(t *testing.T) {
|
||||
files, err := search.FindFiles(1000, 0)
|
||||
files, err := search.Files(1000, 0)
|
||||
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, 5, len(files))
|
||||
|
@ -23,10 +23,10 @@ func TestRepo_FindFiles(t *testing.T) {
|
|||
func TestRepo_FindFilesByUUID(t *testing.T) {
|
||||
conf := config.TestConfig()
|
||||
|
||||
search := New(conf.OriginalsPath(), conf.Db())
|
||||
search := New(conf.Db())
|
||||
|
||||
t.Run("files found", func(t *testing.T) {
|
||||
files, err := search.FindFilesByUUID([]string{"654"}, 100, 0)
|
||||
files, err := search.FilesByUUID([]string{"654"}, 100, 0)
|
||||
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, 1, len(files))
|
||||
|
@ -37,17 +37,17 @@ func TestRepo_FindFilesByUUID(t *testing.T) {
|
|||
func TestRepo_FindFileByPhotoUUID(t *testing.T) {
|
||||
conf := config.TestConfig()
|
||||
|
||||
search := New(conf.OriginalsPath(), conf.Db())
|
||||
search := New(conf.Db())
|
||||
|
||||
t.Run("files found", func(t *testing.T) {
|
||||
file, err := search.FindFileByPhotoUUID("655")
|
||||
file, err := search.FileByPhotoUUID("655")
|
||||
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, "exampleDNGFile.dng", file.FileName)
|
||||
})
|
||||
|
||||
t.Run("no files found", func(t *testing.T) {
|
||||
file, err := search.FindFileByPhotoUUID("111")
|
||||
file, err := search.FileByPhotoUUID("111")
|
||||
|
||||
assert.Error(t, err, "record not found")
|
||||
t.Log(file)
|
||||
|
@ -57,17 +57,17 @@ func TestRepo_FindFileByPhotoUUID(t *testing.T) {
|
|||
func TestRepo_FindFileByID(t *testing.T) {
|
||||
conf := config.TestConfig()
|
||||
|
||||
search := New(conf.OriginalsPath(), conf.Db())
|
||||
search := New(conf.Db())
|
||||
|
||||
t.Run("files found", func(t *testing.T) {
|
||||
file, err := search.FindFileByID("3")
|
||||
file, err := search.FileByID("3")
|
||||
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, "exampleXmpFile.xmp", file.FileName)
|
||||
})
|
||||
|
||||
t.Run("no files found", func(t *testing.T) {
|
||||
file, err := search.FindFileByID("111")
|
||||
file, err := search.FileByID("111")
|
||||
|
||||
assert.Error(t, err, "record not found")
|
||||
t.Log(file)
|
||||
|
@ -77,17 +77,17 @@ func TestRepo_FindFileByID(t *testing.T) {
|
|||
func TestRepo_FindFileByHash(t *testing.T) {
|
||||
conf := config.TestConfig()
|
||||
|
||||
search := New(conf.OriginalsPath(), conf.Db())
|
||||
search := New(conf.Db())
|
||||
|
||||
t.Run("files found", func(t *testing.T) {
|
||||
file, err := search.FindFileByHash("123xxx")
|
||||
file, err := search.FileByHash("123xxx")
|
||||
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, "exampleFileName.jpg", file.FileName)
|
||||
})
|
||||
|
||||
t.Run("no files found", func(t *testing.T) {
|
||||
file, err := search.FindFileByHash("111")
|
||||
file, err := search.FileByHash("111")
|
||||
|
||||
assert.Error(t, err, "record not found")
|
||||
t.Log(file)
|
||||
|
|
|
@ -25,7 +25,7 @@ type GeoResult struct {
|
|||
}
|
||||
|
||||
// Geo searches for photos based on a Form and returns a PhotoResult slice.
|
||||
func (s *Repo) Geo(f form.GeoSearch) (results []GeoResult, err error) {
|
||||
func (s *Query) Geo(f form.GeoSearch) (results []GeoResult, err error) {
|
||||
if err := f.ParseQueryString(); err != nil {
|
||||
return results, err
|
||||
}
|
||||
|
|
|
@ -11,7 +11,7 @@ import (
|
|||
func TestRepo_Geo(t *testing.T) {
|
||||
conf := config.TestConfig()
|
||||
|
||||
search := New(conf.OriginalsPath(), conf.Db())
|
||||
search := New(conf.Db())
|
||||
|
||||
t.Run("search all photos", func(t *testing.T) {
|
||||
query := form.NewGeoSearch("")
|
||||
|
|
|
@ -28,8 +28,8 @@ type LabelResult struct {
|
|||
LabelNotes string
|
||||
}
|
||||
|
||||
// FindLabelBySlug returns a Label based on the slug name.
|
||||
func (s *Repo) FindLabelBySlug(labelSlug string) (label entity.Label, err error) {
|
||||
// LabelBySlug returns a Label based on the slug name.
|
||||
func (s *Query) LabelBySlug(labelSlug string) (label entity.Label, err error) {
|
||||
if err := s.db.Where("label_slug = ?", labelSlug).First(&label).Error; err != nil {
|
||||
return label, err
|
||||
}
|
||||
|
@ -37,8 +37,8 @@ func (s *Repo) FindLabelBySlug(labelSlug string) (label entity.Label, err error)
|
|||
return label, nil
|
||||
}
|
||||
|
||||
// FindLabelByUUID returns a Label based on the label UUID.
|
||||
func (s *Repo) FindLabelByUUID(labelUUID string) (label entity.Label, err error) {
|
||||
// LabelByUUID returns a Label based on the label UUID.
|
||||
func (s *Query) LabelByUUID(labelUUID string) (label entity.Label, err error) {
|
||||
if err := s.db.Where("label_uuid = ?", labelUUID).First(&label).Error; err != nil {
|
||||
return label, err
|
||||
}
|
||||
|
@ -46,8 +46,8 @@ func (s *Repo) FindLabelByUUID(labelUUID string) (label entity.Label, err error)
|
|||
return label, nil
|
||||
}
|
||||
|
||||
// FindLabelThumbBySlug returns a label preview file based on the slug name.
|
||||
func (s *Repo) FindLabelThumbBySlug(labelSlug string) (file entity.File, err error) {
|
||||
// LabelThumbBySlug returns a label preview file based on the slug name.
|
||||
func (s *Query) LabelThumbBySlug(labelSlug string) (file entity.File, err error) {
|
||||
// s.db.LogMode(true)
|
||||
|
||||
if err := s.db.Where("files.file_primary AND files.deleted_at IS NULL").
|
||||
|
@ -61,8 +61,8 @@ func (s *Repo) FindLabelThumbBySlug(labelSlug string) (file entity.File, err err
|
|||
return file, nil
|
||||
}
|
||||
|
||||
// FindLabelThumbByUUID returns a label preview file based on the label UUID.
|
||||
func (s *Repo) FindLabelThumbByUUID(labelUUID string) (file entity.File, err error) {
|
||||
// LabelThumbByUUID returns a label preview file based on the label UUID.
|
||||
func (s *Query) LabelThumbByUUID(labelUUID string) (file entity.File, err error) {
|
||||
// Search matching label
|
||||
err = s.db.Where("files.file_primary AND files.deleted_at IS NULL").
|
||||
Joins("JOIN labels ON labels.label_uuid = ?", labelUUID).
|
||||
|
@ -86,7 +86,7 @@ func (s *Repo) FindLabelThumbByUUID(labelUUID string) (file entity.File, err err
|
|||
}
|
||||
|
||||
// Labels searches labels based on their name.
|
||||
func (s *Repo) Labels(f form.LabelSearch) (results []LabelResult, err error) {
|
||||
func (s *Query) Labels(f form.LabelSearch) (results []LabelResult, err error) {
|
||||
if err := f.ParseQueryString(); err != nil {
|
||||
return results, err
|
||||
}
|
||||
|
|
|
@ -11,17 +11,17 @@ import (
|
|||
func TestRepo_FindLabelBySlug(t *testing.T) {
|
||||
conf := config.TestConfig()
|
||||
|
||||
search := New(conf.OriginalsPath(), conf.Db())
|
||||
search := New(conf.Db())
|
||||
|
||||
t.Run("files found", func(t *testing.T) {
|
||||
label, err := search.FindLabelBySlug("flower")
|
||||
label, err := search.LabelBySlug("flower")
|
||||
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, "Flower", label.LabelName)
|
||||
})
|
||||
|
||||
t.Run("no files found", func(t *testing.T) {
|
||||
label, err := search.FindLabelBySlug("111")
|
||||
label, err := search.LabelBySlug("111")
|
||||
|
||||
assert.Error(t, err, "record not found")
|
||||
t.Log(label)
|
||||
|
@ -31,17 +31,17 @@ func TestRepo_FindLabelBySlug(t *testing.T) {
|
|||
func TestRepo_FindLabelByUUID(t *testing.T) {
|
||||
conf := config.TestConfig()
|
||||
|
||||
search := New(conf.OriginalsPath(), conf.Db())
|
||||
search := New(conf.Db())
|
||||
|
||||
t.Run("files found", func(t *testing.T) {
|
||||
label, err := search.FindLabelByUUID("14")
|
||||
label, err := search.LabelByUUID("14")
|
||||
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, "COW", label.LabelName)
|
||||
})
|
||||
|
||||
t.Run("no files found", func(t *testing.T) {
|
||||
label, err := search.FindLabelByUUID("111")
|
||||
label, err := search.LabelByUUID("111")
|
||||
|
||||
assert.Error(t, err, "record not found")
|
||||
t.Log(label)
|
||||
|
@ -51,17 +51,17 @@ func TestRepo_FindLabelByUUID(t *testing.T) {
|
|||
func TestRepo_FindLabelThumbBySlug(t *testing.T) {
|
||||
conf := config.TestConfig()
|
||||
|
||||
search := New(conf.OriginalsPath(), conf.Db())
|
||||
search := New(conf.Db())
|
||||
|
||||
t.Run("files found", func(t *testing.T) {
|
||||
file, err := search.FindLabelThumbBySlug("flower")
|
||||
file, err := search.LabelThumbBySlug("flower")
|
||||
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, "exampleFileName.jpg", file.FileName)
|
||||
})
|
||||
|
||||
t.Run("no files found", func(t *testing.T) {
|
||||
file, err := search.FindLabelThumbBySlug("cow")
|
||||
file, err := search.LabelThumbBySlug("cow")
|
||||
|
||||
assert.Error(t, err, "record not found")
|
||||
t.Log(file)
|
||||
|
@ -71,17 +71,17 @@ func TestRepo_FindLabelThumbBySlug(t *testing.T) {
|
|||
func TestRepo_FindLabelThumbByUUID(t *testing.T) {
|
||||
conf := config.TestConfig()
|
||||
|
||||
search := New(conf.OriginalsPath(), conf.Db())
|
||||
search := New(conf.Db())
|
||||
|
||||
t.Run("files found", func(t *testing.T) {
|
||||
file, err := search.FindLabelThumbByUUID("13")
|
||||
file, err := search.LabelThumbByUUID("13")
|
||||
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, "exampleFileName.jpg", file.FileName)
|
||||
})
|
||||
|
||||
t.Run("no files found", func(t *testing.T) {
|
||||
file, err := search.FindLabelThumbByUUID("14")
|
||||
file, err := search.LabelThumbByUUID("14")
|
||||
|
||||
assert.Error(t, err, "record not found")
|
||||
t.Log(file)
|
||||
|
@ -91,7 +91,7 @@ func TestRepo_FindLabelThumbByUUID(t *testing.T) {
|
|||
func TestRepo_Labels(t *testing.T) {
|
||||
conf := config.TestConfig()
|
||||
|
||||
search := New(conf.OriginalsPath(), conf.Db())
|
||||
search := New(conf.Db())
|
||||
|
||||
t.Run("search with query", func(t *testing.T) {
|
||||
query := form.NewLabelSearch("Query:C Count:1005 Order:slug")
|
||||
|
|
|
@ -8,7 +8,7 @@ type MomentsTimeResult struct {
|
|||
}
|
||||
|
||||
// GetMomentsTime counts photos per month and year
|
||||
func (s *Repo) GetMomentsTime() (results []MomentsTimeResult, err error) {
|
||||
func (s *Query) GetMomentsTime() (results []MomentsTimeResult, err error) {
|
||||
q := s.db.NewScope(nil).DB()
|
||||
|
||||
q = q.Table("photos").
|
||||
|
|
|
@ -10,7 +10,7 @@ import (
|
|||
func TestRepo_GetMomentsTime(t *testing.T) {
|
||||
conf := config.TestConfig()
|
||||
|
||||
search := New(conf.OriginalsPath(), conf.Db())
|
||||
search := New(conf.Db())
|
||||
|
||||
t.Run("result found", func(t *testing.T) {
|
||||
result, err := search.GetMomentsTime()
|
||||
|
|
|
@ -94,7 +94,7 @@ func (m *PhotoResult) DownloadFileName() string {
|
|||
}
|
||||
|
||||
// Photos searches for photos based on a Form and returns a PhotoResult slice.
|
||||
func (s *Repo) Photos(f form.PhotoSearch) (results []PhotoResult, err error) {
|
||||
func (s *Query) Photos(f form.PhotoSearch) (results []PhotoResult, err error) {
|
||||
if err := f.ParseQueryString(); err != nil {
|
||||
return results, err
|
||||
}
|
||||
|
@ -335,8 +335,8 @@ func (s *Repo) Photos(f form.PhotoSearch) (results []PhotoResult, err error) {
|
|||
return results, nil
|
||||
}
|
||||
|
||||
// FindPhotoByID returns a Photo based on the ID.
|
||||
func (s *Repo) FindPhotoByID(photoID uint64) (photo entity.Photo, err error) {
|
||||
// PhotoByID returns a Photo based on the ID.
|
||||
func (s *Query) PhotoByID(photoID uint64) (photo entity.Photo, err error) {
|
||||
if err := s.db.Where("id = ?", photoID).Preload("Description").First(&photo).Error; err != nil {
|
||||
return photo, err
|
||||
}
|
||||
|
@ -344,8 +344,8 @@ func (s *Repo) FindPhotoByID(photoID uint64) (photo entity.Photo, err error) {
|
|||
return photo, nil
|
||||
}
|
||||
|
||||
// FindPhotoByUUID returns a Photo based on the UUID.
|
||||
func (s *Repo) FindPhotoByUUID(photoUUID string) (photo entity.Photo, err error) {
|
||||
// PhotoByUUID returns a Photo based on the UUID.
|
||||
func (s *Query) PhotoByUUID(photoUUID string) (photo entity.Photo, err error) {
|
||||
if err := s.db.Where("photo_uuid = ?", photoUUID).Preload("Description").First(&photo).Error; err != nil {
|
||||
return photo, err
|
||||
}
|
||||
|
@ -354,7 +354,7 @@ func (s *Repo) FindPhotoByUUID(photoUUID string) (photo entity.Photo, err error)
|
|||
}
|
||||
|
||||
// PreloadPhotoByUUID returns a Photo based on the UUID with all dependencies preloaded.
|
||||
func (s *Repo) PreloadPhotoByUUID(photoUUID string) (photo entity.Photo, err error) {
|
||||
func (s *Query) PreloadPhotoByUUID(photoUUID string) (photo entity.Photo, err error) {
|
||||
if err := s.db.Where("photo_uuid = ?", photoUUID).
|
||||
Preload("Labels", func(db *gorm.DB) *gorm.DB {
|
||||
return db.Order("photos_labels.label_uncertainty ASC, photos_labels.label_id DESC")
|
||||
|
|
|
@ -31,16 +31,16 @@ import (
|
|||
func TestRepo_FindPhotoByID(t *testing.T) {
|
||||
conf := config.TestConfig()
|
||||
|
||||
search := New(conf.OriginalsPath(), conf.Db())
|
||||
search := New(conf.Db())
|
||||
|
||||
t.Run("photo found", func(t *testing.T) {
|
||||
result, err := search.FindPhotoByID(1)
|
||||
result, err := search.PhotoByID(1)
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, 2790, result.PhotoYear)
|
||||
})
|
||||
|
||||
t.Run("no photo found", func(t *testing.T) {
|
||||
result, err := search.FindPhotoByID(99999)
|
||||
result, err := search.PhotoByID(99999)
|
||||
assert.Error(t, err, "record not found")
|
||||
t.Log(result)
|
||||
})
|
||||
|
@ -49,16 +49,16 @@ func TestRepo_FindPhotoByID(t *testing.T) {
|
|||
func TestRepo_FindPhotoByUUID(t *testing.T) {
|
||||
conf := config.TestConfig()
|
||||
|
||||
search := New(conf.OriginalsPath(), conf.Db())
|
||||
search := New(conf.Db())
|
||||
|
||||
t.Run("photo found", func(t *testing.T) {
|
||||
result, err := search.FindPhotoByUUID("659")
|
||||
result, err := search.PhotoByUUID("659")
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, "Reunion", result.PhotoTitle)
|
||||
})
|
||||
|
||||
t.Run("no photo found", func(t *testing.T) {
|
||||
result, err := search.FindPhotoByUUID("99999")
|
||||
result, err := search.PhotoByUUID("99999")
|
||||
assert.Error(t, err, "record not found")
|
||||
t.Log(result)
|
||||
})
|
||||
|
@ -67,7 +67,7 @@ func TestRepo_FindPhotoByUUID(t *testing.T) {
|
|||
func TestRepo_PreloadPhotoByUUID(t *testing.T) {
|
||||
conf := config.TestConfig()
|
||||
|
||||
search := New(conf.OriginalsPath(), conf.Db())
|
||||
search := New(conf.Db())
|
||||
|
||||
t.Run("photo found", func(t *testing.T) {
|
||||
result, err := search.PreloadPhotoByUUID("659")
|
||||
|
@ -86,7 +86,7 @@ func TestSearch_Photos_Query(t *testing.T) {
|
|||
|
||||
conf.CreateDirectories()
|
||||
|
||||
search := New(conf.OriginalsPath(), conf.Db())
|
||||
search := New(conf.Db())
|
||||
|
||||
t.Run("normal query", func(t *testing.T) {
|
||||
var f form.PhotoSearch
|
||||
|
|
|
@ -18,10 +18,9 @@ var log = event.Log
|
|||
// About 1km ('good enough' for now)
|
||||
const SearchRadius = 0.009
|
||||
|
||||
// Repo searches given an originals path and a db instance.
|
||||
type Repo struct {
|
||||
originalsPath string
|
||||
db *gorm.DB
|
||||
// Query searches given an originals path and a db instance.
|
||||
type Query struct {
|
||||
db *gorm.DB
|
||||
}
|
||||
|
||||
// SearchCount is the total number of search hits.
|
||||
|
@ -29,12 +28,11 @@ type SearchCount struct {
|
|||
Total int
|
||||
}
|
||||
|
||||
// New returns a new Repo type with a given path and db instance.
|
||||
func New(originalsPath string, db *gorm.DB) *Repo {
|
||||
instance := &Repo{
|
||||
originalsPath: originalsPath,
|
||||
db: db,
|
||||
// New returns a new Query type with a given path and db instance.
|
||||
func New(db *gorm.DB) *Query {
|
||||
q := &Query{
|
||||
db: db,
|
||||
}
|
||||
|
||||
return instance
|
||||
return q
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@ import (
|
|||
)
|
||||
|
||||
// PhotoSelection returns all selected photos.
|
||||
func (s *Repo) PhotoSelection(f form.Selection) (results []entity.Photo, err error) {
|
||||
func (s *Query) PhotoSelection(f form.Selection) (results []entity.Photo, err error) {
|
||||
if f.Empty() {
|
||||
return results, errors.New("no photos selected")
|
||||
}
|
||||
|
|
|
@ -70,6 +70,12 @@ func registerRoutes(router *gin.Engine, conf *config.Config) {
|
|||
api.AddPhotosToAlbum(v1, conf)
|
||||
api.RemovePhotosFromAlbum(v1, conf)
|
||||
|
||||
api.GetAccounts(v1, conf)
|
||||
api.GetAccount(v1, conf)
|
||||
api.CreateAccount(v1, conf)
|
||||
api.DeleteAccount(v1, conf)
|
||||
api.UpdateAccount(v1, conf)
|
||||
|
||||
api.GetSettings(v1, conf)
|
||||
api.SaveSettings(v1, conf)
|
||||
|
||||
|
|
Loading…
Reference in a new issue