github.com/Azareal/Gosora@v0.0.0-20210729070923-553e66b59003/common/report_store.go (about)

     1  package common
     2  
     3  import (
     4  	"database/sql"
     5  	"errors"
     6  	"strconv"
     7  
     8  	qgen "github.com/Azareal/Gosora/query_gen"
     9  )
    10  
    11  // TODO: Make the default report forum ID configurable
    12  // TODO: Make sure this constant is used everywhere for the report forum ID
    13  const ReportForumID = 1
    14  
    15  var Reports ReportStore
    16  var ErrAlreadyReported = errors.New("This item has already been reported")
    17  
    18  // The report system mostly wraps around the topic system for simplicty
    19  type ReportStore interface {
    20  	Create(title, content string, u *User, itemType string, itemID int) (int, error)
    21  }
    22  
    23  type DefaultReportStore struct {
    24  	create *sql.Stmt
    25  	exists *sql.Stmt
    26  }
    27  
    28  func NewDefaultReportStore(acc *qgen.Accumulator) (*DefaultReportStore, error) {
    29  	t := "topics"
    30  	return &DefaultReportStore{
    31  		create: acc.Insert(t).Columns("title, content, parsed_content, ip, createdAt, lastReplyAt, createdBy, lastReplyBy, data, parentID, css_class").Fields("?,?,?,?,UTC_TIMESTAMP(),UTC_TIMESTAMP(),?,?,?,?,'report'").Prepare(),
    32  		exists: acc.Count(t).Where("data=? AND data!='' AND parentID=?").Prepare(),
    33  	}, acc.FirstError()
    34  }
    35  
    36  // ! There's a data race in this. If two users report one item at the exact same time, then both reports will go through
    37  func (s *DefaultReportStore) Create(title, content string, u *User, itemType string, itemID int) (tid int, err error) {
    38  	var count int
    39  	err = s.exists.QueryRow(itemType+"_"+strconv.Itoa(itemID), ReportForumID).Scan(&count)
    40  	if err != nil && err != sql.ErrNoRows {
    41  		return 0, err
    42  	}
    43  	if count != 0 {
    44  		return 0, ErrAlreadyReported
    45  	}
    46  
    47  	ip := u.GetIP()
    48  	if Config.DisablePostIP {
    49  		ip = ""
    50  	}
    51  	res, err := s.create.Exec(title, content, ParseMessage(content, 0, "", nil, nil), ip, u.ID, u.ID, itemType+"_"+strconv.Itoa(itemID), ReportForumID)
    52  	if err != nil {
    53  		return 0, err
    54  	}
    55  	lastID, err := res.LastInsertId()
    56  	if err != nil {
    57  		return 0, err
    58  	}
    59  	tid = int(lastID)
    60  
    61  	return tid, Forums.AddTopic(tid, u.ID, ReportForumID)
    62  }