2022-08-13 22:39:31 +00:00
|
|
|
package models
|
|
|
|
|
|
|
|
import (
|
2024-08-23 04:57:14 +00:00
|
|
|
"errors"
|
2022-08-13 22:39:31 +00:00
|
|
|
"time"
|
|
|
|
|
|
|
|
"gorm.io/gorm"
|
|
|
|
)
|
|
|
|
|
|
|
|
// CertificationPhoto table.
|
|
|
|
type CertificationPhoto struct {
|
2024-05-26 19:34:00 +00:00
|
|
|
ID uint64 `gorm:"primaryKey"`
|
|
|
|
UserID uint64 `gorm:"uniqueIndex"`
|
|
|
|
Filename string
|
|
|
|
Filesize int64
|
|
|
|
Status CertificationPhotoStatus
|
|
|
|
AdminComment string
|
|
|
|
SecondaryNeeded bool // a secondary form of ID has been requested
|
|
|
|
SecondaryFilename string // photo ID upload
|
|
|
|
SecondaryVerified bool // mark true when ID checked so original can be deleted
|
|
|
|
IPAddress string // the IP they uploaded the photo from
|
|
|
|
CreatedAt time.Time
|
|
|
|
UpdatedAt time.Time
|
2022-08-13 22:39:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
type CertificationPhotoStatus string
|
|
|
|
|
|
|
|
const (
|
|
|
|
CertificationPhotoNeeded CertificationPhotoStatus = "needed"
|
2023-05-25 01:40:27 +00:00
|
|
|
CertificationPhotoPending CertificationPhotoStatus = "pending"
|
|
|
|
CertificationPhotoApproved CertificationPhotoStatus = "approved"
|
|
|
|
CertificationPhotoRejected CertificationPhotoStatus = "rejected"
|
2024-05-26 19:34:00 +00:00
|
|
|
|
|
|
|
// If a photo is pending approval but the admin wants to engage the
|
|
|
|
// secondary check (prompt user for a photo ID upload)
|
|
|
|
CertificationPhotoSecondary CertificationPhotoStatus = "secondary"
|
2022-08-13 22:39:31 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
// GetCertificationPhoto retrieves the user's record from the DB or upserts their initial record.
|
|
|
|
func GetCertificationPhoto(userID uint64) (*CertificationPhoto, error) {
|
|
|
|
p := &CertificationPhoto{}
|
|
|
|
result := DB.Where("user_id = ?", userID).First(&p)
|
|
|
|
if result.Error == gorm.ErrRecordNotFound {
|
|
|
|
p = &CertificationPhoto{
|
|
|
|
UserID: userID,
|
|
|
|
Status: CertificationPhotoNeeded,
|
|
|
|
}
|
|
|
|
result = DB.Create(p)
|
|
|
|
return p, result.Error
|
|
|
|
}
|
|
|
|
return p, result.Error
|
|
|
|
}
|
|
|
|
|
2024-08-23 04:57:14 +00:00
|
|
|
// CertifiedSince retrieve's the last updated date of the user's certification photo, if approved.
|
|
|
|
//
|
|
|
|
// This incurs a DB query for their cert photo.
|
|
|
|
func (u *User) CertifiedSince() (time.Time, error) {
|
|
|
|
if !u.Certified {
|
|
|
|
return time.Time{}, errors.New("user is not certified")
|
|
|
|
}
|
|
|
|
|
|
|
|
cert, err := GetCertificationPhoto(u.ID)
|
|
|
|
if err != nil {
|
|
|
|
return time.Time{}, err
|
|
|
|
}
|
|
|
|
|
|
|
|
if cert.Status != CertificationPhotoApproved {
|
2024-08-29 01:42:49 +00:00
|
|
|
// The edge case can come up if a user was manually certified but didn't have an approved picture.
|
|
|
|
// Return their CreatedAt instead.
|
|
|
|
return u.CreatedAt, nil
|
2024-08-23 04:57:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return cert.UpdatedAt, nil
|
|
|
|
}
|
|
|
|
|
2022-08-13 22:39:31 +00:00
|
|
|
// CertificationPhotosNeedingApproval returns a pager of the pictures that require admin approval.
|
|
|
|
func CertificationPhotosNeedingApproval(status CertificationPhotoStatus, pager *Pagination) ([]*CertificationPhoto, error) {
|
|
|
|
var p = []*CertificationPhoto{}
|
|
|
|
|
|
|
|
query := DB.Where(
|
|
|
|
"status = ?",
|
|
|
|
status,
|
|
|
|
).Order(
|
|
|
|
pager.Sort,
|
|
|
|
)
|
|
|
|
|
|
|
|
// Get the total count.
|
|
|
|
query.Model(&CertificationPhoto{}).Count(&pager.Total)
|
|
|
|
|
|
|
|
result := query.Offset(
|
|
|
|
pager.GetOffset(),
|
|
|
|
).Limit(pager.PerPage).Find(&p)
|
|
|
|
|
|
|
|
return p, result.Error
|
|
|
|
}
|
|
|
|
|
2022-08-14 23:27:57 +00:00
|
|
|
// CountCertificationPhotosNeedingApproval gets the count of pending photos for admin alert.
|
|
|
|
func CountCertificationPhotosNeedingApproval() int64 {
|
|
|
|
var count int64
|
|
|
|
DB.Where("status = ?", CertificationPhotoPending).Model(&CertificationPhoto{}).Count(&count)
|
|
|
|
return count
|
|
|
|
}
|
|
|
|
|
2022-08-13 22:39:31 +00:00
|
|
|
// Save photo.
|
|
|
|
func (p *CertificationPhoto) Save() error {
|
|
|
|
result := DB.Save(p)
|
|
|
|
return result.Error
|
|
|
|
}
|
2022-08-14 21:40:57 +00:00
|
|
|
|
|
|
|
// Delete the DB entry.
|
|
|
|
func (p *CertificationPhoto) Delete() error {
|
|
|
|
return DB.Delete(p).Error
|
|
|
|
}
|