Skip to content

Commit

Permalink
RocketChat Token Support (#1060)
Browse files Browse the repository at this point in the history
  • Loading branch information
caronc authored Apr 13, 2024
1 parent 7a985ea commit 33c7569
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 15 deletions.
59 changes: 44 additions & 15 deletions apprise/plugins/NotifyRocketChat.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,13 +59,17 @@ class RocketChatAuthMode:
# providing a webhook
WEBHOOK = "webhook"

# Support token submission
TOKEN = "token"

# Providing a username and password (default)
BASIC = "basic"


# Define our authentication modes
ROCKETCHAT_AUTH_MODES = (
RocketChatAuthMode.WEBHOOK,
RocketChatAuthMode.TOKEN,
RocketChatAuthMode.BASIC,
)

Expand Down Expand Up @@ -107,6 +111,8 @@ class NotifyRocketChat(NotifyBase):
templates = (
'{schema}://{user}:{password}@{host}:{port}/{targets}',
'{schema}://{user}:{password}@{host}/{targets}',
'{schema}://{user}:{token}@{host}:{port}/{targets}',
'{schema}://{user}:{token}@{host}/{targets}',
'{schema}://{webhook}@{host}',
'{schema}://{webhook}@{host}:{port}',
'{schema}://{webhook}@{host}/{targets}',
Expand Down Expand Up @@ -135,6 +141,11 @@ class NotifyRocketChat(NotifyBase):
'type': 'string',
'private': True,
},
'token': {
'name': _('API Token'),
'map_to': 'password',
'private': True,
},
'webhook': {
'name': _('Webhook'),
'type': 'string',
Expand Down Expand Up @@ -230,13 +241,20 @@ def __init__(self, webhook=None, targets=None, mode=None, avatar=None,
if self.webhook is not None:
# Just a username was specified, we treat this as a webhook
self.mode = RocketChatAuthMode.WEBHOOK
elif self.password and len(self.password) > 32:
self.mode = RocketChatAuthMode.TOKEN
else:
self.mode = RocketChatAuthMode.BASIC

if self.mode == RocketChatAuthMode.BASIC \
self.logger.debug(
"Auto-Detected Rocketchat Auth Mode: %s", self.mode)

if self.mode in (RocketChatAuthMode.BASIC, RocketChatAuthMode.TOKEN) \
and not (self.user and self.password):
# Username & Password is required for Rocket Chat to work
msg = 'No Rocket.Chat user/pass combo was specified.'
msg = 'No Rocket.Chat {} was specified.'.format(
'user/pass combo' if self.mode == RocketChatAuthMode.BASIC else
'user/apikey')
self.logger.warning(msg)
raise TypeError(msg)

Expand All @@ -245,6 +263,13 @@ def __init__(self, webhook=None, targets=None, mode=None, avatar=None,
self.logger.warning(msg)
raise TypeError(msg)

if self.mode == RocketChatAuthMode.TOKEN:
# Set our headers for further communication
self.headers.update({
'X-User-Id': self.user,
'X-Auth-Token': self.password,
})

# Validate recipients and drop bad ones:
for recipient in parse_list(targets):
result = IS_CHANNEL.match(recipient)
Expand Down Expand Up @@ -309,12 +334,13 @@ def url(self, privacy=False, *args, **kwargs):
params.update(self.url_parameters(privacy=privacy, *args, **kwargs))

# Determine Authentication
if self.mode == RocketChatAuthMode.BASIC:
if self.mode in (RocketChatAuthMode.BASIC, RocketChatAuthMode.TOKEN):
auth = '{user}:{password}@'.format(
user=NotifyRocketChat.quote(self.user, safe=''),
password=self.pprint(
self.password, privacy, mode=PrivacyMode.Secret, safe=''),
)

else:
auth = '{user}{webhook}@'.format(
user='{}:'.format(NotifyRocketChat.quote(self.user, safe=''))
Expand Down Expand Up @@ -359,8 +385,11 @@ def send(self, body, title='', notify_type=NotifyType.INFO, **kwargs):
# Call the _send_ function applicable to whatever mode we're in
# - calls _send_webhook_notification if the mode variable is set
# - calls _send_basic_notification if the mode variable is not set
return getattr(self, '_send_{}_notification'.format(self.mode))(
body=body, title=title, notify_type=notify_type, **kwargs)
return getattr(self, '_send_{}_notification'.format(
RocketChatAuthMode.WEBHOOK
if self.mode == RocketChatAuthMode.WEBHOOK
else RocketChatAuthMode.BASIC))(
body=body, title=title, notify_type=notify_type, **kwargs)

def _send_webhook_notification(self, body, title='',
notify_type=NotifyType.INFO, **kwargs):
Expand Down Expand Up @@ -412,7 +441,7 @@ def _send_basic_notification(self, body, title='',
"""
# Track whether we authenticated okay

if not self.login():
if self.mode == RocketChatAuthMode.BASIC and not self.login():
return False

# prepare JSON Object
Expand All @@ -432,9 +461,7 @@ def _send_basic_notification(self, body, title='',
channel = channels.pop(0)
payload['channel'] = channel

if not self._send(
payload, notify_type=notify_type, headers=self.headers,
**kwargs):
if not self._send(payload, notify_type=notify_type, **kwargs):

# toggle flag
has_error = True
Expand All @@ -447,15 +474,14 @@ def _send_basic_notification(self, body, title='',
room = rooms.pop(0)
payload['roomId'] = room

if not self._send(
payload, notify_type=notify_type, headers=self.headers,
**kwargs):
if not self._send(payload, notify_type=notify_type, **kwargs):

# toggle flag
has_error = True

# logout
self.logout()
if self.mode == RocketChatAuthMode.BASIC:
# logout
self.logout()

return not has_error

Expand All @@ -476,7 +502,7 @@ def _payload(self, body, title='', notify_type=NotifyType.INFO):
return payload

def _send(self, payload, notify_type, path='api/v1/chat.postMessage',
headers={}, **kwargs):
**kwargs):
"""
Perform Notify Rocket.Chat Notification
"""
Expand All @@ -487,6 +513,9 @@ def _send(self, payload, notify_type, path='api/v1/chat.postMessage',
api_url, self.verify_certificate))
self.logger.debug('Rocket.Chat Payload: %s' % str(payload))

# Copy our existing headers
headers = self.headers.copy()

# Apply minimum headers
headers.update({
'User-Agent': self.app_id,
Expand Down
10 changes: 10 additions & 0 deletions test/test_plugin_rocket_chat.py
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,16 @@
},
'privacy_url': 'rockets://user:****@localhost',
}),
# A channel using token based
('rockets://user:token@localhost/#channel?mode=token', {
'instance': NotifyRocketChat,
'privacy_url': 'rockets://user:****@localhost',
}),
# Token is detected based o it's length
('rockets://user:{}@localhost/#channel'.format('t' * 40), {
'instance': NotifyRocketChat,
'privacy_url': 'rockets://user:****@localhost',
}),
# Several channels
('rocket://user:pass@localhost/#channel1/#channel2/?avatar=Yes', {
'instance': NotifyRocketChat,
Expand Down

0 comments on commit 33c7569

Please sign in to comment.