lists.sr.ht/api/graph/model/mailinglist.go

172 lines
3.9 KiB
Go

package model
import (
"context"
"database/sql"
"strconv"
"strings"
"time"
sq "github.com/Masterminds/squirrel"
"git.sr.ht/~sircmpwn/core-go/auth"
"git.sr.ht/~sircmpwn/core-go/database"
"git.sr.ht/~sircmpwn/core-go/model"
)
const (
ACCESS_NONE = 0
ACCESS_BROWSE = 1
ACCESS_REPLY = 2
ACCESS_POST = 4
ACCESS_MODERATE = 8
ACCESS_ALL = 1 | 2 | 4 | 8
)
type MailingList struct {
ID int `json:"id"`
Created time.Time `json:"created"`
Updated time.Time `json:"updated"`
Name string `json:"name"`
Description *string `json:"description"`
Visibility Visibility `json:"visibility"`
Importing bool `json:"importing"`
OwnerID int
RawPermitMime string
RawRejectMime string
Access int
DefaultAccess uint
AccessID *int
SubscriptionID *int
alias string
fields *database.ModelFields
}
func (list *MailingList) PermitMime() []string {
if len(list.RawPermitMime) == 0 {
return nil
}
return strings.Split(list.RawPermitMime, ",")
}
func (list *MailingList) RejectMime() []string {
if len(list.RawRejectMime) == 0 {
return nil
}
return strings.Split(list.RawRejectMime, ",")
}
func (list *MailingList) DefaultACL() *GeneralACL {
return &GeneralACL{
Browse: list.DefaultAccess&ACCESS_BROWSE > 0,
Reply: list.DefaultAccess&ACCESS_REPLY > 0,
Post: list.DefaultAccess&ACCESS_POST > 0,
Moderate: list.DefaultAccess&ACCESS_MODERATE > 0,
}
}
func (list *MailingList) As(alias string) *MailingList {
list.alias = alias
return list
}
func (list *MailingList) Alias() string {
return list.alias
}
func (list *MailingList) Table() string {
return "list"
}
func (list *MailingList) Fields() *database.ModelFields {
if list.fields != nil {
return list.fields
}
list.fields = &database.ModelFields{
Fields: []*database.FieldMap{
{"id", "id", &list.ID},
{"created", "created", &list.Created},
{"name", "name", &list.Name},
{"description", "description", &list.Description},
{"import_in_progress", "importing", &list.Importing},
{"permit_mimetypes", "permitMime", &list.RawPermitMime},
{"reject_mimetypes", "rejectMime", &list.RawRejectMime},
{"visibility", "visibility", &list.Visibility},
{"default_access", "defaultACL", &list.DefaultAccess},
// Always fetch:
{"id", "", &list.ID},
{"owner_id", "", &list.OwnerID},
{"updated", "", &list.Updated},
},
}
return list.fields
}
func (list *MailingList) QueryWithCursor(ctx context.Context,
runner sq.BaseRunner, q sq.SelectBuilder,
cur *model.Cursor) ([]*MailingList, *model.Cursor) {
var (
err error
rows *sql.Rows
)
if cur.Next != "" {
ts, _ := strconv.ParseInt(cur.Next, 10, 64)
updated := time.Unix(ts, 0)
q = q.Where(database.WithAlias(list.alias, "updated")+"<= ?", updated)
}
user := auth.ForContext(ctx)
q = q.
LeftJoin(`access ON
access.list_id = list.id AND
access.user_id = ?`, user.UserID).
LeftJoin(`subscription sub ON
sub.list_id = list.id AND
sub.user_id = ?`, user.UserID).
Column(`COALESCE(
access.permissions,
CASE WHEN list.owner_id = ?
THEN ?
ELSE list.default_access
END)`,
user.UserID, ACCESS_ALL).
Column(`access.id`).
Column(`sub.id`).
OrderBy(database.WithAlias(list.alias, `updated`) + " DESC").
Limit(uint64(cur.Count + 1))
if rows, err = q.RunWith(runner).QueryContext(ctx); err != nil {
panic(err)
}
defer rows.Close()
var lists []*MailingList
for rows.Next() {
var list MailingList
if err := rows.Scan(append(database.Scan(ctx, &list),
&list.Access,
&list.AccessID,
&list.SubscriptionID)...); err != nil {
panic(err)
}
lists = append(lists, &list)
}
if len(lists) > cur.Count {
cur = &model.Cursor{
Count: cur.Count,
Next: strconv.FormatInt(lists[len(lists)-1].Updated.Unix(), 10),
Search: cur.Search,
}
lists = lists[:cur.Count]
} else {
cur = nil
}
return lists, cur
}