diff --git a/app/db/repositories/invite.js b/app/db/repositories/invite.js index bfc9ac915366aec298c02f8000bfc5063faaa6cd..a0e0854cfc1441f18bf742194ddcf2594a47f854 100644 --- a/app/db/repositories/invite.js +++ b/app/db/repositories/invite.js @@ -1,22 +1,46 @@ +import * as channelRepository from './membership' + const membershipRepository = require('./membership') const { loggerOf } = require('../../services/util') const logger = loggerOf('db|inviteRepository') -// (Database, string, string, string) -> boolean +// (Database, string, string, string) -> Promise<boolean> const issue = async (db, channelPhoneNumber, inviterPhoneNumber, inviteePhoneNumber) => { // issues invite IFF invitee is not already member of channel or invited by same person // returns true if invite issued, false otherwise try { if (await membershipRepository.isMember(db, channelPhoneNumber, inviteePhoneNumber)) return false - const [, wasInviteCreated] = await db.invite.findOrCreate({ + return (await db.invite.findOrCreate({ where: { channelPhoneNumber, inviterPhoneNumber, inviteePhoneNumber }, - }) - return wasInviteCreated + }))[1] + } 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) { logger.error(e) return false } } -module.exports = { issue } +module.exports = { issue, accept, decline } diff --git a/app/db/repositories/membership.js b/app/db/repositories/membership.js index a2c9d396061321e6a3785513774252c6ba9999c8..f966487ae080ffac1da0d768cdc792cad8e77a52 100644 --- a/app/db/repositories/membership.js +++ b/app/db/repositories/membership.js @@ -42,6 +42,7 @@ const addSubscriber = async ( memberPhoneNumber, language = defaultLanguage, ) => + // TODO: use findOrCreate here to make this idempotent! performOpIfChannelExists(db, channelPhoneNumber, 'subscribe member to', () => db.membership.create({ type: memberTypes.SUBSCRIBER, diff --git a/app/services/dispatcher/commands/execute.js b/app/services/dispatcher/commands/execute.js index ab53c24b01ed0607c9265b833df930f142643744..6031b21ba171046a253858f70126fc322aa0b9a9 100644 --- a/app/services/dispatcher/commands/execute.js +++ b/app/services/dispatcher/commands/execute.js @@ -34,7 +34,9 @@ const execute = async (executable, dispatchable) => { // don't allow command execution on the signup channel for non-admins if (channel.phoneNumber === signupPhoneNumber && sender.type !== ADMIN) return noop() const result = await ({ + [commands.ACCEPT]: () => maybeAccept(db, channel, sender, language), [commands.ADD]: () => maybeAddAdmin(db, channel, sender, payload), + [commands.DECLINE]: () => decline(db, channel, sender), [commands.HELP]: () => showHelp(db, channel, sender), [commands.INFO]: () => showInfo(db, channel, sender), [commands.INVITE]: () => maybeInvite(db, channel, sender, payload), @@ -55,6 +57,27 @@ const execute = async (executable, dispatchable) => { * 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 const maybeAddAdmin = async (db, channel, sender, phoneNumberInput) => { diff --git a/app/services/dispatcher/strings/messages/EN.js b/app/services/dispatcher/strings/messages/EN.js index 939b7e690ac16adda33aa8eac2c9aba7677cbd06..02fd11c752c9fbd7eae9fad6cf341fa9551b8052 100644 --- a/app/services/dispatcher/strings/messages/EN.js +++ b/app/services/dispatcher/strings/messages/EN.js @@ -76,6 +76,14 @@ Reply with HELP for more info.`, } const commandResponses = { + // ACCEPT + + accept: { + success: 'foo', + alreadyMember: 'bar', + dbError: 'lala', + }, + // ADD add: {