Skip to content
Snippets Groups Projects
Verified Commit 39fff4a2 authored by aguestuser's avatar aguestuser
Browse files

[99][WIP] handle ACCEPT / DECLINE commands

TODO:

* translations
* tests
* make `addSubscriber` idempotent?
* extract `isMember` check from `#issue`? (and push into guard in
  execute layer?)
* use a richer return type from invite repo commands?
  (resolve/reject a status instead of always returning a boolean?)
parent 2b9b664e
No related tags found
No related merge requests found
import * as channelRepository from './membership'
const membershipRepository = require('./membership') const membershipRepository = require('./membership')
const { loggerOf } = require('../../services/util') const { loggerOf } = require('../../services/util')
const logger = loggerOf('db|inviteRepository') const logger = loggerOf('db|inviteRepository')
// (Database, string, string, string) -> boolean // (Database, string, string, string) -> Promise<boolean>
const issue = async (db, channelPhoneNumber, inviterPhoneNumber, inviteePhoneNumber) => { const issue = async (db, channelPhoneNumber, inviterPhoneNumber, inviteePhoneNumber) => {
// issues invite IFF invitee is not already member of channel or invited by same person // issues invite IFF invitee is not already member of channel or invited by same person
// returns true if invite issued, false otherwise // returns true if invite issued, false otherwise
try { try {
if (await membershipRepository.isMember(db, channelPhoneNumber, inviteePhoneNumber)) if (await membershipRepository.isMember(db, channelPhoneNumber, inviteePhoneNumber))
return false return false
const [, wasInviteCreated] = await db.invite.findOrCreate({ return (await db.invite.findOrCreate({
where: { channelPhoneNumber, inviterPhoneNumber, inviteePhoneNumber }, where: { channelPhoneNumber, inviterPhoneNumber, inviteePhoneNumber },
}) }))[1]
return wasInviteCreated } catch (e) {
logger.error(e)
return false
}
}
// (Database, string, string, string) -> Promise<boolean>
const accept = async (db, channelPhoneNumber, inviteePhoneNumber, language) => {
try {
await channelRepository.addSubscriber(db, channelPhoneNumber, inviteePhoneNumber, language)
await db.invite.destroy({ where: { channelPhoneNumber, inviteePhoneNumber } })
return true
} catch (e) {
logger.error(e)
return false
}
}
// (Database, string, string) -> Promise<boolean>
const decline = async (db, channelPhoneNumber, inviteePhoneNumber) => {
try {
await db.invite.destroy({ where: { channelPhoneNumber, inviteePhoneNumber } })
return true
} catch (e) { } catch (e) {
logger.error(e) logger.error(e)
return false return false
} }
} }
module.exports = { issue } module.exports = { issue, accept, decline }
...@@ -42,6 +42,7 @@ const addSubscriber = async ( ...@@ -42,6 +42,7 @@ const addSubscriber = async (
memberPhoneNumber, memberPhoneNumber,
language = defaultLanguage, language = defaultLanguage,
) => ) =>
// TODO: use findOrCreate here to make this idempotent!
performOpIfChannelExists(db, channelPhoneNumber, 'subscribe member to', () => performOpIfChannelExists(db, channelPhoneNumber, 'subscribe member to', () =>
db.membership.create({ db.membership.create({
type: memberTypes.SUBSCRIBER, type: memberTypes.SUBSCRIBER,
......
...@@ -34,7 +34,9 @@ const execute = async (executable, dispatchable) => { ...@@ -34,7 +34,9 @@ const execute = async (executable, dispatchable) => {
// don't allow command execution on the signup channel for non-admins // don't allow command execution on the signup channel for non-admins
if (channel.phoneNumber === signupPhoneNumber && sender.type !== ADMIN) return noop() if (channel.phoneNumber === signupPhoneNumber && sender.type !== ADMIN) return noop()
const result = await ({ const result = await ({
[commands.ACCEPT]: () => maybeAccept(db, channel, sender, language),
[commands.ADD]: () => maybeAddAdmin(db, channel, sender, payload), [commands.ADD]: () => maybeAddAdmin(db, channel, sender, payload),
[commands.DECLINE]: () => decline(db, channel, sender),
[commands.HELP]: () => showHelp(db, channel, sender), [commands.HELP]: () => showHelp(db, channel, sender),
[commands.INFO]: () => showInfo(db, channel, sender), [commands.INFO]: () => showInfo(db, channel, sender),
[commands.INVITE]: () => maybeInvite(db, channel, sender, payload), [commands.INVITE]: () => maybeInvite(db, channel, sender, payload),
...@@ -55,6 +57,27 @@ const execute = async (executable, dispatchable) => { ...@@ -55,6 +57,27 @@ const execute = async (executable, dispatchable) => {
* COMMAND EXECUTION * COMMAND EXECUTION
********************/ ********************/
// ACCEPT
const maybeAccept = async (db, channel, sender, language) => {
const cr = messagesIn(language).commandResponses.accept
return (await membershipRepository.isMember(db, channel.phoneNumber, inviteePhoneNumber))
? { status: statuses.ERROR, message: cr.alreadyMember }
: accept(db, channel, sender, language, cr)
}
const accept = async (db, channel, sender, language, cr) =>
(await accept(db, channel.phoneNumber, sender.phoneNumber, language))
? { status: statuses.SUCCESS, message: cr.success }
: { status: statuses.ERROR, message: cr.dbError }
// DECLINE
const decline = async (db, channel, sender, inviteePhoneNumber, language, cr) =>
(await decline(db, channel.phoneNumber, sender.phoneNumber))
? { status: statuses.SUCCESS, message: cr.success }
: { status: statuses.ERROR, message: cr.dbError }
// ADD // ADD
const maybeAddAdmin = async (db, channel, sender, phoneNumberInput) => { const maybeAddAdmin = async (db, channel, sender, phoneNumberInput) => {
......
...@@ -76,6 +76,14 @@ Reply with HELP for more info.`, ...@@ -76,6 +76,14 @@ Reply with HELP for more info.`,
} }
const commandResponses = { const commandResponses = {
// ACCEPT
accept: {
success: 'foo',
alreadyMember: 'bar',
dbError: 'lala',
},
// ADD // ADD
add: { add: {
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment