website/pkg/models/user_note.go

201 lines
5.0 KiB
Go

package models
import (
"errors"
"fmt"
"strings"
"time"
"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(&note)
)
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.IsAdmin {
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(&notes)
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(&notes)
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(&notes)
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
}