chats 0.4.1 → 0.4.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +29 -0
- data/README.md +1 -1
- data/config/locales/en.yml +1 -0
- data/config/locales/es.yml +1 -0
- data/lib/chats/models/message.rb +32 -8
- data/lib/chats/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: f2f76b973f012e2c86514932efaca3db25eaf8c70ed4709276d1f5f33d520de2
|
|
4
|
+
data.tar.gz: 2b88c68ad0d239a9ba87b5e907193924926a3926715ed39b62f844e2d899bf19
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: be31c3ce5aad04e1c9d5d0ba141403514da0f547de42a4516ede78117025a12c7f3936060787a3935e477e4f2c03aa2fcfb7b7550c0fdca77a5c6d65a0c86db3
|
|
7
|
+
data.tar.gz: f22af91cf0ccb50bd933659d0fdc549306ecb2bfad09ee87cfb0193499a0839c2f468cd8e109ad7266ddba35200126b28d5f8958b065420fd828a065b9f40b80
|
data/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,35 @@ All notable changes to this project are documented here.
|
|
|
4
4
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
5
5
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
6
6
|
|
|
7
|
+
## [0.4.2] - 2026-10-17
|
|
8
|
+
|
|
9
|
+
### Changed
|
|
10
|
+
**Upgrade note: your `can_message` policy now runs on every direct send,
|
|
11
|
+
not only when a thread is opened.** Read yours before upgrading. If it
|
|
12
|
+
means "who may OPEN a conversation" (a listing must be live, a ride must be
|
|
13
|
+
accepted), existing threads will stop taking messages the moment it turns
|
|
14
|
+
false for the pair — which is usually what you want (a block already
|
|
15
|
+
behaves this way), but is a change. If it is expensive, it now costs that
|
|
16
|
+
on every direct message; make it cheap or cache what it reads. It must not
|
|
17
|
+
raise: an exception escapes the send like any other host error. Group
|
|
18
|
+
conversations and system messages are unchanged.
|
|
19
|
+
|
|
20
|
+
- **`can_message` holds on every direct send.** A block placed
|
|
21
|
+
mid-conversation already stopped the next message; the host's policy
|
|
22
|
+
turning false did not, so a pair allowed when the thread was opened kept
|
|
23
|
+
talking after an account was banned or a membership ended. Every text
|
|
24
|
+
message into a direct conversation now re-runs `Chats.can_message?`
|
|
25
|
+
exactly like the block check: `:blocked` when either side blocked the
|
|
26
|
+
other, `:not_allowed` (new, in `en` and `es`) when the policy says no.
|
|
27
|
+
The policy is asked last, only of a send that is otherwise valid (a
|
|
28
|
+
stranger, a locked thread or an empty body is refused before it runs).
|
|
29
|
+
The composer answers with its errors stream as before.
|
|
30
|
+
- **A direct thread with nobody on the other side takes no messages.** When
|
|
31
|
+
the counterpart's account was destroyed, its seat went with it (the
|
|
32
|
+
gem's `dependent: :destroy` on participations); a text message into that
|
|
33
|
+
thread is refused with `:not_allowed` instead of slipping past both the
|
|
34
|
+
block and the policy checks. The thread stays readable.
|
|
35
|
+
|
|
7
36
|
## [0.4.1] - 2026-10-17
|
|
8
37
|
|
|
9
38
|
### Fixed
|
data/README.md
CHANGED
|
@@ -171,7 +171,7 @@ That single hook makes moderate's bidirectional block table the law everywhere c
|
|
|
171
171
|
- **can't send** into an existing one (a block placed mid-conversation stops the very next message),
|
|
172
172
|
- and **stop seeing** each other's direct threads in the inbox and unread counts — *hidden, never deleted*: lift the block and the history reappears.
|
|
173
173
|
|
|
174
|
-
Two semantics worth knowing: blocking is enforced **beneath** your `can_message` policy (a permissive or buggy policy can never let a blocked pair talk), and **group conversations are exempt from pair blocks** — the industry standard: blocking someone removes your private line, not your seat in shared spaces. If your domain should eject blocked members from groups, do it in moderate's `on_block` hook by tearing down whatever domain relationship feeds the group membership.
|
|
174
|
+
Two semantics worth knowing: blocking is enforced **beneath** your `can_message` policy (a permissive or buggy policy can never let a blocked pair talk), both are checked on **every direct send**, not only when the thread is opened (a block placed, or a policy turning false, mid-conversation stops the very next message with `:blocked` / `:not_allowed`), and **group conversations are exempt from pair blocks** — the industry standard: blocking someone removes your private line, not your seat in shared spaces. If your domain should eject blocked members from groups, do it in moderate's `on_block` hook by tearing down whatever domain relationship feeds the group membership.
|
|
175
175
|
|
|
176
176
|
### 2. Reportable + filtered messages
|
|
177
177
|
|
data/config/locales/en.yml
CHANGED
|
@@ -82,6 +82,7 @@ en:
|
|
|
82
82
|
base:
|
|
83
83
|
locked: "This conversation is closed."
|
|
84
84
|
blocked: "You can't message this person."
|
|
85
|
+
not_allowed: "You can't message this person right now."
|
|
85
86
|
action:
|
|
86
87
|
invalid: "needs a label of up to %{count} characters and a link to an http(s) address or to a path on this site that starts with /"
|
|
87
88
|
author:
|
data/config/locales/es.yml
CHANGED
|
@@ -82,6 +82,7 @@ es:
|
|
|
82
82
|
base:
|
|
83
83
|
locked: "Esta conversación está cerrada."
|
|
84
84
|
blocked: "No puedes enviar mensajes a esta persona."
|
|
85
|
+
not_allowed: "Ahora mismo no puedes enviar mensajes a esta persona."
|
|
85
86
|
action:
|
|
86
87
|
invalid: "necesita un texto de hasta %{count} caracteres y un enlace a una dirección http(s) o a una ruta de este sitio que empiece por /"
|
|
87
88
|
author:
|
data/lib/chats/models/message.rb
CHANGED
|
@@ -115,13 +115,15 @@ module Chats
|
|
|
115
115
|
validate :body_or_files_required
|
|
116
116
|
validate :body_must_fit_length_limit
|
|
117
117
|
validate :sender_must_be_active_participant, on: :create
|
|
118
|
-
validate :sender_must_not_be_blocked, on: :create
|
|
119
118
|
validate :conversation_must_not_be_locked, on: :create
|
|
120
119
|
validate :author_must_be_persisted
|
|
121
120
|
# Checked at the write that SETS it, not on every save: an edit must
|
|
122
121
|
# never fail over an action nobody touched.
|
|
123
122
|
validate :action_must_be_well_formed, if: :will_save_change_to_action?
|
|
124
123
|
validate :files_must_be_allowed
|
|
124
|
+
# Last on purpose: the host's policy is asked only of a send that is
|
|
125
|
+
# otherwise valid (see the method).
|
|
126
|
+
validate :sender_must_still_be_allowed, on: :create
|
|
125
127
|
|
|
126
128
|
after_create :register_on_conversation
|
|
127
129
|
after_create_commit :broadcast_created
|
|
@@ -337,15 +339,37 @@ module Chats
|
|
|
337
339
|
errors.add(:sender, :not_a_participant) unless conversation.participant?(sender)
|
|
338
340
|
end
|
|
339
341
|
|
|
340
|
-
#
|
|
341
|
-
# block placed mid-conversation
|
|
342
|
-
#
|
|
343
|
-
#
|
|
344
|
-
|
|
345
|
-
|
|
342
|
+
# Who may talk to whom is decided at the WRITE, not just when the
|
|
343
|
+
# conversation was opened: a block placed mid-conversation stops the very
|
|
344
|
+
# next send, and so does the host's `can_message` policy turning false —
|
|
345
|
+
# an account banned, a listing closed, a membership ended. The pair was
|
|
346
|
+
# allowed when the thread began; what matters is whether it still is.
|
|
347
|
+
# Direct threads only — see Conversation.excluding_blocked_for for the
|
|
348
|
+
# group rationale. Two errors, because they read differently to the
|
|
349
|
+
# sender: `:blocked` (either side blocked the other) and `:not_allowed`
|
|
350
|
+
# (the policy said no).
|
|
351
|
+
#
|
|
352
|
+
# Asked last, and only of a send that is otherwise valid: a stranger to
|
|
353
|
+
# the conversation, a locked thread or an empty body is refused before
|
|
354
|
+
# the host's policy runs, so the policy is never consulted about a
|
|
355
|
+
# message that could not be sent anyway (it may be expensive, and it
|
|
356
|
+
# runs on every direct send now). A policy must not raise: an
|
|
357
|
+
# exception escapes the send like any other host error.
|
|
358
|
+
#
|
|
359
|
+
# A direct thread with nobody on the other side — the counterpart's
|
|
360
|
+
# account was destroyed and its seat went with it — takes no messages:
|
|
361
|
+
# there is no one the policy could allow.
|
|
362
|
+
def sender_must_still_be_allowed
|
|
363
|
+
return if system? || sender.nil? || conversation.nil? || !conversation.direct? || errors.any?
|
|
346
364
|
|
|
347
365
|
other = conversation.other_participants(sender).first&.messager
|
|
348
|
-
|
|
366
|
+
if other.nil?
|
|
367
|
+
errors.add(:base, :not_allowed)
|
|
368
|
+
elsif Chats.blocked_between?(sender, other)
|
|
369
|
+
errors.add(:base, :blocked)
|
|
370
|
+
elsif !Chats.config.can_message.call(sender, other)
|
|
371
|
+
errors.add(:base, :not_allowed)
|
|
372
|
+
end
|
|
349
373
|
end
|
|
350
374
|
|
|
351
375
|
# Authorship is a signature, not a conversation seat. A host may keep
|
data/lib/chats/version.rb
CHANGED