feat(guilds): приватные комнаты — права доступа поверх серверных
Сервер:
- store: оверрайды всех комнат сервера одним запросом (без N+1) и снятие
оверрайда с признаком «был ли он»;
- API: PUT/DELETE /guilds/{id}/channels/{cid}/overwrites/{role|user}/{tid}
(права именами через `|`, как у ролей), step-up на изменение, проверка что
роль принадлежит серверу, а участник состоит в нём;
- список комнат отдаёт permission_overwrites; после правки сбрасывается кэш
прав комнаты, пишется аудит (channel.overwrite_set/delete) и уходит событие
GUILD_CHANNELS_SYNC — видимость комнаты меняется у всех участников.
Клиент:
- редактор «Доступ к комнате»: приватность одним переключателем (запрет
VIEW_CHANNEL для @everyone), права просмотра/переписки/входа для ролей и
участников, подтверждение личности по требованию сервера;
- в настройках комнаты теперь и голосовые комнаты (фон и права), вебхуки —
только у текстовых; событие GUILD_CHANNELS_SYNC перечитывает список комнат.
Тесты: 2 Go-теста (скрытие и открытие комнаты ролями, проверка цели и прав) и
3 web-теста редактора (маски, step-up, скрытие без MANAGE_ROLES).
This commit is contained in:
@@ -192,6 +192,50 @@ func (s *Store) SetChannelOverride(ctx context.Context, override ChannelOverride
|
||||
return err
|
||||
}
|
||||
|
||||
// ListGuildChannelOverrides отдаёт оверрайды всех комнат сервера одним
|
||||
// запросом: список комнат в API не должен превращаться в N+1 (AGENT.md 6.2).
|
||||
func (s *Store) ListGuildChannelOverrides(ctx context.Context, guildID uint64) (map[uint64][]ChannelOverride, error) {
|
||||
rows, err := s.reader.QueryContext(ctx, `
|
||||
SELECT o.channel_id, o.target_type, o.target_id, o.allow, o.deny
|
||||
FROM channel_overrides o
|
||||
JOIN channels c ON c.id = o.channel_id
|
||||
WHERE c.guild_id = ?`, int64(guildID))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
result := make(map[uint64][]ChannelOverride)
|
||||
for rows.Next() {
|
||||
var (
|
||||
override ChannelOverride
|
||||
allow, deny int64
|
||||
)
|
||||
if err := rows.Scan(&override.ChannelID, &override.TargetType, &override.TargetID, &allow, &deny); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
override.Allow = intToID(allow)
|
||||
override.Deny = intToID(deny)
|
||||
result[override.ChannelID] = append(result[override.ChannelID], override)
|
||||
}
|
||||
return result, rows.Err()
|
||||
}
|
||||
|
||||
// DeleteChannelOverride снимает оверрайд: признак «был ли он» нужен аудиту.
|
||||
func (s *Store) DeleteChannelOverride(ctx context.Context, channelID uint64, targetType string, targetID uint64) (bool, error) {
|
||||
result, err := s.writer.ExecContext(ctx,
|
||||
`DELETE FROM channel_overrides WHERE channel_id = ? AND target_type = ? AND target_id = ?`,
|
||||
int64(channelID), targetType, int64(targetID))
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
affected, err := result.RowsAffected()
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
return affected > 0, nil
|
||||
}
|
||||
|
||||
func (s *Store) ListChannelOverrides(ctx context.Context, channelID uint64) ([]ChannelOverride, error) {
|
||||
rows, err := s.reader.QueryContext(ctx, `
|
||||
SELECT channel_id, target_type, target_id, allow, deny
|
||||
|
||||
Reference in New Issue
Block a user