202 lines
5.0 KiB
Go
202 lines
5.0 KiB
Go
package models
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"strings"
|
|
"time"
|
|
|
|
"code.nonshy.com/nonshy/website/pkg/config"
|
|
"code.nonshy.com/nonshy/website/pkg/log"
|
|
)
|
|
|
|
// UserNote table where users can write private notes about each other.
|
|
type UserNote struct {
|
|
ID uint64 `gorm:"primaryKey"`
|
|
UserID uint64 `gorm:"index"` // author ID
|
|
AboutUserID uint64 `gorm:"index"` // target user ID
|
|
Message string
|
|
CreatedAt time.Time
|
|
UpdatedAt time.Time
|
|
}
|
|
|
|
// GetNoteBetweenUsers finds the existing note or creates an empty model if not found.
|
|
func GetNoteBetweenUsers(currentUser *User, user *User) *UserNote {
|
|
var (
|
|
note = &UserNote{}
|
|
result = DB.Model(note).Where(
|
|
"user_id = ? AND about_user_id = ?",
|
|
currentUser.ID, user.ID,
|
|
).First(¬e)
|
|
)
|
|
if result.Error != nil {
|
|
note = &UserNote{
|
|
UserID: currentUser.ID,
|
|
AboutUserID: user.ID,
|
|
}
|
|
}
|
|
return note
|
|
}
|
|
|
|
// GetNote finds a user note by its ID.
|
|
func GetNote(id uint64) (*UserNote, error) {
|
|
p := &UserNote{}
|
|
result := DB.First(&p, id)
|
|
return p, result.Error
|
|
}
|
|
|
|
// CountNotesAboutUser returns the number of notes (the current user) has about the other user.
|
|
//
|
|
// For regular user, will return zero or one; for admins, will return the total count of notes
|
|
// left by any other users about this user.
|
|
func CountNotesAboutUser(currentUser *User, user *User) int64 {
|
|
var (
|
|
wheres = []string{}
|
|
placeholders = []interface{}{}
|
|
count int64
|
|
)
|
|
|
|
if currentUser.HasAdminScope(config.ScopeUserNotes) {
|
|
wheres = append(wheres, "about_user_id = ?")
|
|
placeholders = append(placeholders, user.ID)
|
|
} else {
|
|
wheres = append(wheres, "user_id = ? AND about_user_id = ?")
|
|
placeholders = append(placeholders, currentUser.ID, user.ID)
|
|
}
|
|
|
|
query := DB.Model(&UserNote{}).Where(
|
|
strings.Join(wheres, " AND "),
|
|
placeholders...,
|
|
).Count(&count)
|
|
if query.Error != nil {
|
|
log.Error("CountNotesAboutUser(%s, %s): %s", currentUser.Username, user.Username, query.Error)
|
|
}
|
|
|
|
return count
|
|
}
|
|
|
|
// PaginateUserNotes shows all notes written by users about the target user.
|
|
func PaginateUserNotes(user *User, pager *Pagination) ([]*UserNote, error) {
|
|
var (
|
|
notes = []*UserNote{}
|
|
wheres = []string{}
|
|
placeholders = []interface{}{}
|
|
)
|
|
|
|
wheres = append(wheres, "about_user_id = ?")
|
|
placeholders = append(placeholders, user.ID)
|
|
|
|
query := DB.Joins("JOIN users ON users.id = user_notes.user_id").Where(
|
|
strings.Join(wheres, " AND "),
|
|
placeholders...,
|
|
).Order(
|
|
"users.is_admin desc, " + pager.Sort,
|
|
)
|
|
|
|
query.Model(&UserNote{}).Count(&pager.Total)
|
|
|
|
result := query.Offset(
|
|
pager.GetOffset(),
|
|
).Limit(pager.PerPage).Find(¬es)
|
|
|
|
return notes, result.Error
|
|
}
|
|
|
|
// PaginateMyUserNotes shows all notes written by the current user about others.
|
|
func PaginateMyUserNotes(currentUser *User, search string, pager *Pagination) ([]*UserNote, error) {
|
|
var (
|
|
notes = []*UserNote{}
|
|
wheres = []string{}
|
|
placeholders = []interface{}{}
|
|
ilike = "%" + search + "%"
|
|
)
|
|
|
|
wheres = append(wheres, "user_notes.user_id = ?")
|
|
placeholders = append(placeholders, currentUser.ID)
|
|
|
|
// Searching?
|
|
if search != "" {
|
|
wheres = append(wheres, "(users.username ILIKE ? OR user_notes.message ILIKE ?)")
|
|
placeholders = append(placeholders, ilike, ilike)
|
|
}
|
|
|
|
query := DB.Joins("JOIN users ON users.id = user_notes.about_user_id").Where(
|
|
strings.Join(wheres, " AND "),
|
|
placeholders...,
|
|
).Order(
|
|
pager.Sort,
|
|
)
|
|
|
|
query.Model(&UserNote{}).Count(&pager.Total)
|
|
|
|
result := query.Offset(
|
|
pager.GetOffset(),
|
|
).Limit(pager.PerPage).Find(¬es)
|
|
|
|
return notes, result.Error
|
|
}
|
|
|
|
// PaginateAdminUserNotes shows all notes written by any admin user account on nonshy.
|
|
func PaginateAdminUserNotes(search string, pager *Pagination) ([]*UserNote, error) {
|
|
var (
|
|
adminUserIDs = []uint64{}
|
|
notes = []*UserNote{}
|
|
wheres = []string{}
|
|
placeholders = []interface{}{}
|
|
ilike = "%" + search + "%"
|
|
)
|
|
|
|
// Get all the admin users.
|
|
adminUsers, err := ListAdminUsers()
|
|
if err != nil {
|
|
return nil, fmt.Errorf("couldn't get admin users: %s", err)
|
|
}
|
|
|
|
for _, user := range adminUsers {
|
|
adminUserIDs = append(adminUserIDs, user.ID)
|
|
}
|
|
|
|
// Filter to notes written by admin users.
|
|
wheres = append(wheres, "user_notes.user_id IN ?")
|
|
placeholders = append(placeholders, adminUserIDs)
|
|
|
|
// Searching?
|
|
if search != "" {
|
|
wheres = append(wheres, "(users.username ILIKE ? OR user_notes.message ILIKE ?)")
|
|
placeholders = append(placeholders, ilike, ilike)
|
|
}
|
|
|
|
query := DB.Joins("JOIN users ON users.id = user_notes.about_user_id").Where(
|
|
strings.Join(wheres, " AND "),
|
|
placeholders...,
|
|
).Order(
|
|
pager.Sort,
|
|
)
|
|
|
|
query.Model(&UserNote{}).Count(&pager.Total)
|
|
|
|
result := query.Offset(
|
|
pager.GetOffset(),
|
|
).Limit(pager.PerPage).Find(¬es)
|
|
|
|
return notes, result.Error
|
|
}
|
|
|
|
// Save the note.
|
|
func (p *UserNote) Save() error {
|
|
if p.ID == 0 {
|
|
return DB.Create(p).Error
|
|
}
|
|
return DB.Save(p).Error
|
|
}
|
|
|
|
var ErrNoUserNoteToDelete = errors.New("you had no user note to delete")
|
|
|
|
// Delete the DB entry.
|
|
func (p *UserNote) Delete() error {
|
|
if p.ID == 0 {
|
|
return ErrNoUserNoteToDelete
|
|
}
|
|
return DB.Delete(p).Error
|
|
}
|