admins can BAN senders of abusive hotline messages

Value

  • As an admin running a channel that can receive messages from people i don't know
  • I want a way to permanently ban users who send abusive messages or photos
  • So that I can do my work free from verbal violence without having to shut off hotline messages (which would impair my work)

Behavior

how hotline messages currently work:

GIVEN a channel with HOTLINE ON

  • WHEN a user sends a hotline message
  • THEN that message will be prefixed by the header [HOTLINE MESSAGE @<N>] (where N is an integer from 1 to 100)

discovering the BAN command

GIVEN an admin, alice, on a channel foo

  • WHEN alice sends HELP to foo
  • THEN she will see a listing for the BAN command that includes:
BAN @123
-> bans an unwanted subscriber from this channel. 

issuing a ban

GIVEN an admin, alice, of a channel with HOTLINE mode on

  • AND GIVEN a subscriber bob that has sent an abusive message prefixed with [HOTLINE FROM @2]
  • WHEN alice issues BAN 2 OR BAN @2
  • THEN bob receives a message that says An admin of this channel has banned you. Any further interaction will not be received by the admins of the channel.
  • AND THEN all admins of the channel receive a notification saying The sender of hotline message #2 has been banned.

redundant bans

GIVEN an admin has already blocked the sender of HOTLINE MESSAGE 2

  • WHEN another admin issues BAN @2
  • THEN that admin will receive a response saying The sender of hotline message 2 has already been banned.
  • AND THEN other admins will not receive any notification, nor will the sender of message #2 (closed)

enforcing a ban

GIVEN a user bob, who has been blocked from channel #foo

  • WHEN bob issues any message to #foo (including HELP, INFO, or HELLO)
  • THEN bob receives a response that says Sorry, you are banned from this channel

security guarantees

WHEN a user is banned

  • THEN the system will only ever store the sha-256 hash of their password (so that even banned users will not have their phone numbers permanently stored on our system without their knowledge if they choose to leave signalboost entirely)

Implementation

data model changes

  • this feature will require a new table called bans, which should (likely) have the following fields:
    • id: string (a uuid)
    • channelPhoneNumber: string (a valid e164-formatted phone number)
    • hashedMemberPhoneNumber: string (salted sha256 hash of a valid e164-formatted phone number)
    • createdAt: Date
    • updatedAt: Date
  • should also have a unique index on channelPhoneNumber + memberPhoneNumber combinations (both for faster lookup and to avoid dupes)
    • for an example of such an index, see: app/db/migrations/20200531233616-create-hotlineMessages.js

logic for creating a ban

  • whenever an admin issues a ban:
    • parse a hotline message id from the ban command
    • use the id to lookup the hotlineMessage record, and retrieve the memberPhoneNumber
    • create a ban record joining the channelPhoneNumber and memberPhoneNumber (unless such a ban already exists)

logic for enforcing a ban

  • whenever an incoming message arrives on a channel (in app/dispatcher/index)
    • hash the sender's phone number and look it up in the bans table (along with the channel phone number)
      • see app.util.sha256Hash to do this!
    • if there is a ban, drop the message, if not proceed with processing
    • consider extending the set of detect<SomeCondition> helpers in app.dispatcher.dispatch as a good spot to stick this checkz
  • as a potential optimisation (to save on queries for a routine that will run on every incoming relayable message):
    • create a hasMany association between channel and bans
    • include bans in app.db.repositories.channel.findDeep
    • now, we don't need to query the bans table to check for bans, as it will already been eagerly loaded by the call to channelRepository.findDeep in dispatcher/index.js:67

spots to create a new command

where HELP text is defined:

  • app/dispatcher/strings/messages

relevant files where creating new commands takes place:

  • app/dispatcher/strings/commands
  • app/dispatcher/constants
  • app/dispatcher/execute

all commands and message strings need translations!

Edited by aguestuser