chore: refresh gramsrv public release
This commit is contained in:
parent
75cebe8dbf
commit
70b6820474
1274 changed files with 378751 additions and 59919 deletions
159
internal/store/postgres/channel_admin_log.go
Normal file
159
internal/store/postgres/channel_admin_log.go
Normal file
|
|
@ -0,0 +1,159 @@
|
|||
package postgres
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"github.com/jackc/pgx/v5"
|
||||
"strings"
|
||||
"telesrv/internal/domain"
|
||||
)
|
||||
|
||||
func (s *ChannelStore) ListAdminLog(ctx context.Context, req domain.ChannelAdminLogRequest) (domain.ChannelAdminLogResult, error) {
|
||||
if req.UserID == 0 || req.ChannelID == 0 || req.MaxID < 0 || req.MinID < 0 {
|
||||
return domain.ChannelAdminLogResult{}, domain.ErrChannelInvalid
|
||||
}
|
||||
channel, member, err := s.getChannelForMember(ctx, s.db, req.UserID, req.ChannelID)
|
||||
if err != nil {
|
||||
return domain.ChannelAdminLogResult{}, err
|
||||
}
|
||||
if !isChannelAdmin(member) {
|
||||
return domain.ChannelAdminLogResult{}, domain.ErrChannelAdminRequired
|
||||
}
|
||||
limit := req.Limit
|
||||
if limit <= 0 || limit > domain.MaxChannelAdminLogLimit {
|
||||
limit = domain.MaxChannelAdminLogLimit
|
||||
}
|
||||
where := []string{"channel_id = $1"}
|
||||
args := []any{req.ChannelID}
|
||||
nextArg := func(v any) string {
|
||||
args = append(args, v)
|
||||
return fmt.Sprintf("$%d", len(args))
|
||||
}
|
||||
if req.MaxID > 0 {
|
||||
where = append(where, "id < "+nextArg(req.MaxID))
|
||||
}
|
||||
if req.MinID > 0 {
|
||||
where = append(where, "id > "+nextArg(req.MinID))
|
||||
}
|
||||
if len(req.AdminUserIDs) > 0 {
|
||||
where = append(where, "actor_user_id = ANY("+nextArg(int64s(req.AdminUserIDs))+"::bigint[])")
|
||||
}
|
||||
if types := adminLogEventTypesForFilter(req.Filter); len(types) > 0 {
|
||||
where = append(where, "event_type = ANY("+nextArg(types)+"::text[])")
|
||||
} else if !req.Filter.Empty() {
|
||||
return domain.ChannelAdminLogResult{Channel: channel}, nil
|
||||
}
|
||||
query := strings.ToLower(strings.TrimSpace(req.Query))
|
||||
if query != "" {
|
||||
like := adminLogLikePattern(query)
|
||||
where = append(where, `(lower(prev_string) LIKE `+nextArg(like)+` ESCAPE '\' OR lower(new_string) LIKE `+nextArg(like)+` ESCAPE '\' OR lower(query) LIKE `+nextArg(like)+` ESCAPE '\')`)
|
||||
}
|
||||
args = append(args, limit)
|
||||
rows, err := s.db.Query(ctx, `
|
||||
SELECT channel_id, id, actor_user_id, event_date, event_type, prev_string, new_string, prev_bool, new_bool, prev_int, new_int,
|
||||
prev_participant::text, new_participant::text, participant::text, message::text, prev_message::text, new_message::text, query
|
||||
FROM channel_admin_log_events
|
||||
WHERE `+strings.Join(where, " AND ")+`
|
||||
ORDER BY id DESC
|
||||
LIMIT $`+fmt.Sprint(len(args)), args...)
|
||||
if err != nil {
|
||||
return domain.ChannelAdminLogResult{}, fmt.Errorf("list channel admin log: %w", err)
|
||||
}
|
||||
defer rows.Close()
|
||||
events := make([]domain.ChannelAdminLogEvent, 0, limit)
|
||||
for rows.Next() {
|
||||
event, err := scanChannelAdminLogEvent(rows)
|
||||
if err != nil {
|
||||
return domain.ChannelAdminLogResult{}, err
|
||||
}
|
||||
events = append(events, event)
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
return domain.ChannelAdminLogResult{}, err
|
||||
}
|
||||
return domain.ChannelAdminLogResult{Channel: channel, Events: events}, nil
|
||||
}
|
||||
|
||||
func (s *ChannelStore) insertChannelAdminLogTx(ctx context.Context, tx pgx.Tx, event domain.ChannelAdminLogEvent) error {
|
||||
if event.ChannelID == 0 || event.UserID == 0 || event.Type == "" {
|
||||
return nil
|
||||
}
|
||||
if event.Date == 0 {
|
||||
event.Date = nowUnix()
|
||||
}
|
||||
id, err := nextChannelAdminLogIDTx(ctx, tx, event.ChannelID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
prevParticipant, err := marshalJSON(event.PrevParticipant, "{}")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
newParticipant, err := marshalJSON(event.NewParticipant, "{}")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
participant, err := marshalJSON(event.Participant, "{}")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
message, err := marshalJSON(event.Message, "{}")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
prevMessage, err := marshalJSON(event.PrevMessage, "{}")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
newMessage, err := marshalJSON(event.NewMessage, "{}")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
query := adminLogSearchText(event)
|
||||
if _, err := tx.Exec(ctx, `
|
||||
INSERT INTO channel_admin_log_events (
|
||||
channel_id, id, actor_user_id, event_date, event_type, prev_string, new_string,
|
||||
prev_bool, new_bool, prev_int, new_int, prev_participant, new_participant,
|
||||
participant, message, prev_message, new_message, query
|
||||
) VALUES ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14,$15,$16,$17,$18)`,
|
||||
event.ChannelID, id, event.UserID, event.Date, string(event.Type), event.PrevString, event.NewString,
|
||||
event.PrevBool, event.NewBool, event.PrevInt, event.NewInt, prevParticipant, newParticipant,
|
||||
participant, message, prevMessage, newMessage, query); err != nil {
|
||||
return fmt.Errorf("insert channel admin log: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func nextChannelAdminLogIDTx(ctx context.Context, tx pgx.Tx, channelID int64) (int64, error) {
|
||||
var id int64
|
||||
if err := tx.QueryRow(ctx, `
|
||||
UPDATE channels
|
||||
SET admin_log_seq = admin_log_seq + 1, updated_at = now()
|
||||
WHERE id = $1
|
||||
RETURNING admin_log_seq`, channelID).Scan(&id); err != nil {
|
||||
return 0, fmt.Errorf("allocate channel admin log id: %w", err)
|
||||
}
|
||||
return id, nil
|
||||
}
|
||||
|
||||
func scanChannelAdminLogEvent(row rowScanner) (domain.ChannelAdminLogEvent, error) {
|
||||
var event domain.ChannelAdminLogEvent
|
||||
var typ string
|
||||
var prevParticipant, newParticipant, participant, message, prevMessage, newMessage string
|
||||
if err := row.Scan(
|
||||
&event.ChannelID, &event.ID, &event.UserID, &event.Date, &typ,
|
||||
&event.PrevString, &event.NewString, &event.PrevBool, &event.NewBool,
|
||||
&event.PrevInt, &event.NewInt, &prevParticipant, &newParticipant, &participant,
|
||||
&message, &prevMessage, &newMessage, &event.Query,
|
||||
); err != nil {
|
||||
return domain.ChannelAdminLogEvent{}, err
|
||||
}
|
||||
event.Type = domain.ChannelAdminLogEventType(typ)
|
||||
event.PrevParticipant = decodeJSONPtr[domain.ChannelMember](prevParticipant)
|
||||
event.NewParticipant = decodeJSONPtr[domain.ChannelMember](newParticipant)
|
||||
event.Participant = decodeJSONPtr[domain.ChannelMember](participant)
|
||||
event.Message = decodeJSONPtr[domain.ChannelMessage](message)
|
||||
event.PrevMessage = decodeJSONPtr[domain.ChannelMessage](prevMessage)
|
||||
event.NewMessage = decodeJSONPtr[domain.ChannelMessage](newMessage)
|
||||
return event, nil
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue