Files
worker/app/models/contact.go
Gleb Tv 2c7a0236da feat: publish standalone worker
Separate worker packaging and service lifecycle from the control plane.
2026-07-13 17:55:14 +03:00

87 строки
3.2 KiB
Go

package models
import (
"gorm.io/datatypes"
"rsgit.ru/rsmon/rsmon/app/models/concerns"
)
// Contact represents a notification contact.
//
// Ownership / tenancy:
//
// - A Contact belongs to exactly one Account (tenant). AccountID may be
// nil for system-level admin contacts (see SystemContacts).
// - A Contact may belong to at most one User. UserID is set when the
// contact was created on behalf of a specific user (the typical
// case for self-service "My email" / "My Telegram" contacts) and is
// nil for account-wide contacts.
//
// `User` is omitempty because most list payloads don't preload it; the
// `/settings/users` page loads it server-side via the AccountUserRow
// payload.
type Contact struct {
concerns.Model
AccountID *int64 `json:"account_id" gorm:"type:bigint REFERENCES accounts(id)"`
Account *Account `json:"-"`
UserID *int64 `gorm:"type:bigint REFERENCES users(id)" json:"user_id"`
User *User `json:"user,omitempty"`
Name string `json:"name" gorm:"not null"`
Kind string `json:"kind" gorm:"not null;index:contact_value"`
Value string `json:"value" gorm:"index:contact_value"`
Enabled bool `json:"enabled" gorm:"not null;default:true"`
Data datatypes.JSON `json:"data"`
IsSystem *bool `json:"is_system" gorm:"default:false"`
Notifications []Notification `json:"-" gorm:"many2many:notification_contacts;"`
NotificationsCount int `gorm:"-:all" json:"notifications_count"`
MonitorsCount int `gorm:"-:all" json:"monitors_count"`
Messages []Message `json:"-"`
concerns.Timestamped
concerns.HasToken
Audited
}
// SystemContacts returns all contacts marked as system/admin (is_system=true).
// These are the contacts distributed workers notify directly when the main
// API is unreachable (see docs/worker-protocol.md "System Selfcheck").
func SystemContacts() ([]Contact, error) {
var contacts []Contact
err := DB().Where("is_system = ? AND enabled = ?", true, true).Find(&contacts).Error
return contacts, err
}
// ContactsCounts fills NotificationsCount and MonitorsCount for each contact.
func ContactsCounts(contacts *[]Contact) {
groupIDs := make(map[int64]bool, 0)
groupCount := make(map[int64]int, 0)
for i, c := range *contacts { //nolint:gocritic // range copy is acceptable here
(*contacts)[i].NotificationsCount = len(c.Notifications)
for _, n := range c.Notifications { //nolint:gocritic // range copy is acceptable here
for _, g := range n.Groups { //nolint:gocritic // range copy is acceptable here
groupIDs[g.ID] = true
groupCount[g.ID] = 0
}
}
}
gids := make([]int64, 0, len(groupIDs))
for g := range groupIDs {
gids = append(gids, g)
}
CountGroups(gids, &groupCount)
for i, c := range *contacts { //nolint:gocritic // range copy is acceptable here
cnt := 0
for _, n := range c.Notifications { //nolint:gocritic // range copy is acceptable here
for _, g := range n.Groups { //nolint:gocritic // range copy is acceptable here
cnt += groupCount[g.ID]
}
}
(*contacts)[i].MonitorsCount = cnt
}
}