When golem15.chat is active, Boot registers the context alias bm (id 1) on its registry. Membership is the user group jz.bm.chat.group (default studenci); CanOverseeChats is always false, so nobody reads other people's DMs or edits their messages; the broadcast channel is chat:context:1, never empty. GET /_bm/api/v1/chat answers the caller's membership behind jwt.auth and the per-user bucket jz.bm.chat (240 a minute). The chat config block (group, moderator_group, max_upload_bytes, max_embeds) is added. jz.bm still Requires only golem15.user; all chat wiring is gated by HasPlugin.
92 lines
3.3 KiB
Go
92 lines
3.3 KiB
Go
package classes
|
|
|
|
import (
|
|
"context"
|
|
|
|
chatcontracts "git.golem15.com/golem15/sm-chat-plugin/contracts"
|
|
userclasses "git.golem15.com/golem15/sm-user-plugin/classes"
|
|
"gorm.io/gorm"
|
|
)
|
|
|
|
var _ chatcontracts.Context = (*ChatContext)(nil)
|
|
|
|
// The BM chat context: one context of type bm with id 1, whose members are
|
|
// the members of one user group.
|
|
const (
|
|
// ChatContextType is the context alias (context_type) jz.bm registers on
|
|
// golem15.chat.
|
|
ChatContextType = "bm"
|
|
// ChatContextID is the id of the one BM chat context.
|
|
ChatContextID uint = 1
|
|
// ChatGeneralName is the name of the group conversation and its channel.
|
|
ChatGeneralName = "ogólny"
|
|
// ChatGeneralSlug is the slug of the adopted channel.
|
|
ChatGeneralSlug = "ogolny"
|
|
// ChatBroadcastChannel is the host channel golem15.chat publishes created
|
|
// events to. It must never be empty: an empty host channel silences the
|
|
// conversation channels too. No client can subscribe to it, because the
|
|
// chat authorizer only admits chat:conversation:{id}.
|
|
ChatBroadcastChannel = "chat:context:1"
|
|
)
|
|
|
|
// ChatContext is the golem15.chat context of the BM chat. Membership is the
|
|
// user group named by group; nobody oversees other people's chats, so a
|
|
// moderator reads no DM and edits no foreign message.
|
|
type ChatContext struct {
|
|
db *gorm.DB
|
|
group string
|
|
moderatorGroup string
|
|
}
|
|
|
|
// NewChatContext returns the BM chat context over db for the chat group
|
|
// code group and the moderator group code moderatorGroup.
|
|
func NewChatContext(db *gorm.DB, group, moderatorGroup string) *ChatContext {
|
|
return &ChatContext{db: db, group: group, moderatorGroup: moderatorGroup}
|
|
}
|
|
|
|
func (c *ChatContext) ID() uint { return ChatContextID }
|
|
func (c *ChatContext) Type() string { return ChatContextType }
|
|
func (c *ChatContext) ChatEnabled() bool { return true }
|
|
func (c *ChatContext) GroupName() string { return ChatGeneralName }
|
|
func (c *ChatContext) BroadcastChannel() string { return ChatBroadcastChannel }
|
|
|
|
// CanActFor is the default: a user acts only for themself.
|
|
func (c *ChatContext) CanActFor(ctx context.Context, actorID, memberID uint) bool {
|
|
return chatcontracts.DefaultCanActFor(ctx, actorID, memberID)
|
|
}
|
|
|
|
// CanOverseeChats is always false. golem15.chat grants an overseer read
|
|
// access to every conversation and edits of other people's messages, which
|
|
// no BM user gets; moderators delete through a narrower hook.
|
|
func (c *ChatContext) CanOverseeChats(context.Context, uint) (bool, error) {
|
|
return false, nil
|
|
}
|
|
|
|
// HasMember reports whether userID is in the chat group.
|
|
func (c *ChatContext) HasMember(ctx context.Context, userID uint) (bool, error) {
|
|
if userID == 0 || c.group == "" {
|
|
return false, nil
|
|
}
|
|
return userclasses.HasGroupCode(ctx, c.db, userID, c.group)
|
|
}
|
|
|
|
// Members lists the ids of the chat group's users that are not deleted.
|
|
func (c *ChatContext) Members(ctx context.Context) ([]uint, error) {
|
|
ids := []uint{}
|
|
if c.group == "" {
|
|
return ids, nil
|
|
}
|
|
err := c.db.WithContext(ctx).
|
|
Table("users_groups").
|
|
Joins("JOIN user_groups ON user_groups.id = users_groups.user_group_id").
|
|
Joins("JOIN users ON users.id = users_groups.user_id").
|
|
Where("user_groups.code = ? AND users.deleted_at IS NULL", c.group).
|
|
Distinct().
|
|
Order("users_groups.user_id").
|
|
Pluck("users_groups.user_id", &ids).Error
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return ids, nil
|
|
}
|