photoprism/internal/entity/auth_user_share.go
Michael Mayer 693108fd53 Sharing: Refactor UserShare entity #98 #782
Signed-off-by: Michael Mayer <michael@photoprism.app>
2022-10-04 00:54:39 +02:00

170 lines
4.1 KiB
Go

package entity
import (
"fmt"
"time"
"github.com/photoprism/photoprism/internal/event"
"github.com/photoprism/photoprism/pkg/clean"
"github.com/photoprism/photoprism/pkg/rnd"
)
const PermDefault uint = 0
const (
PermNone uint = 1 << iota
PermView
PermReact
PermComment
PermUpload
PermEdit
PermShare
PermAll
)
// SharePrefix for RefID.
const (
SharePrefix = "share"
)
// UserShares represents shared content.
type UserShares []UserShare
// UIDs returns shared UIDs.
func (m UserShares) UIDs() UIDs {
result := make(UIDs, len(m))
for i, share := range m {
result[i] = share.ShareUID
}
return result
}
// Empty checks if there are no shares.
func (m UserShares) Empty() bool {
return m == nil || len(m) == 0
}
// Contains checks the uid is shared.
func (m UserShares) Contains(uid string) bool {
if len(m) == 0 {
return false
}
for _, share := range m {
if share.ShareUID == uid {
return true
}
}
return false
}
// UserShare represents content shared with a user.
type UserShare struct {
UserUID string `gorm:"type:VARBINARY(42);primary_key;auto_increment:false;" json:"-" yaml:"UserUID"`
ShareUID string `gorm:"type:VARBINARY(42);primary_key;index;" json:"ShareUID" yaml:"ShareUID"`
LinkUID string `gorm:"type:VARBINARY(42);" json:"LinkUID,omitempty" yaml:"LinkUID,omitempty"`
ExpiresAt *time.Time `sql:"index" json:"ExpiresAt,omitempty" yaml:"ExpiresAt,omitempty"`
Comment string `gorm:"size:512;" json:"Comment,omitempty" yaml:"Comment,omitempty"`
Perm uint `json:"Perm,omitempty" yaml:"Perm,omitempty"`
RefID string `gorm:"type:VARBINARY(16);" json:"-" yaml:"-"`
CreatedAt time.Time `json:"CreatedAt" yaml:"-"`
UpdatedAt time.Time `json:"UpdatedAt" yaml:"-"`
}
// TableName returns the entity table name.
func (UserShare) TableName() string {
return "auth_users_shares"
}
// NewUserShare creates a new entity model.
func NewUserShare(userUID, shareUid string, perm uint, expires *time.Time) *UserShare {
result := &UserShare{
UserUID: userUID,
ShareUID: shareUid,
Perm: perm,
RefID: rnd.RefID(SharePrefix),
CreatedAt: TimeStamp(),
UpdatedAt: TimeStamp(),
ExpiresAt: expires,
}
return result
}
// FindUserShare fetches the matching record or returns null if it was not found.
func FindUserShare(find UserShare) *UserShare {
if !find.HasID() {
return nil
}
m := &UserShare{}
// Find matching record.
if UnscopedDb().First(m, "user_uid = ? AND share_uid = ?", find.UserUID, find.ShareUID).RecordNotFound() {
return nil
}
return m
}
// FindUserShares finds all shares to which the user has access.
func FindUserShares(userUid string) UserShares {
found := UserShares{}
if rnd.InvalidUID(userUid, UserUID) {
return found
}
// Find matching record.
if err := UnscopedDb().Find(&found, "user_uid = ? AND (expires_at IS NULL OR expires_at > ?)", userUid, TimeStamp()).Error; err != nil {
event.AuditWarn([]string{"user %s", "find shares", "%s"}, clean.Log(userUid), err)
return nil
}
return found
}
// HasID tests if the entity has a valid uid.
func (m *UserShare) HasID() bool {
return rnd.IsUID(m.UserUID, UserUID) && rnd.IsUID(m.ShareUID, 0)
}
// Create inserts a new record into the database.
func (m *UserShare) Create() error {
return Db().Create(m).Error
}
// Save updates the record in the database or inserts a new record if it does not already exist.
func (m *UserShare) Save() error {
return Db().Save(m).Error
}
// Updates changes multiple record values.
func (m *UserShare) Updates(values interface{}) error {
return UnscopedDb().Model(m).Updates(values).Error
}
// UpdateLink updates the share data using the Link provided.
func (m *UserShare) UpdateLink(link Link) error {
if m.ShareUID != link.ShareUID {
return fmt.Errorf("shared uid does not match")
}
m.LinkUID = link.LinkUID
m.Comment = link.Comment
m.Perm = link.Perm
m.UpdatedAt = TimeStamp()
m.ExpiresAt = link.ExpiresAt()
values := Values{
"link_uid": m.LinkUID,
"expires_at": m.ExpiresAt,
"comment": m.Comment,
"perm": m.Perm,
"updated_at": m.UpdatedAt}
return m.Updates(values)
}