Authentication to use for user notifications using Crossbar/Autobahn? - python

I'm currently trying to implement a user notification system using Websockets via Crossbar/Autobahn. I have done multiple tests and gone through the documentation, however, I'm not sure if there's a solution to having the following workflow work:
User signs in with web app -- this is done through JWT
Frontend establishes a websocket connection to a running crossbar instance.
Frontend attempts to subscribe to a URI specifically for the user's notifications: i.e. com.example.notifications.user.23 or com.example.user.23.notifications'. Where23` is the user id.
User's JWT is checked to see if user is allowed to access subscription.
When activity is generated and causes a notification, the backend publishes the user-specific URIs.
For step 3, I can't tell if the current support auth methods have what I need. Ideally, I would like an auth method which I can customize (in order to implement a JWT authenticator within Crossbar) that I can apply to a URI pattern, but NOT give access to the entire pattern to the subscribing user. This is partially solved by the dynamic auth methods, but is missing the latter half:
For example (my ideal workflow):
User attempts to subscribe to a URI com.example.user.23.notifications.
URI matches com.example.user..notifications (wildcard pattern in http://crossbar.io/docs/Pattern-Based-Subscriptions/)
Auth token is validated and user is given access to only com.example.user.23.notifications.
Is the above achievable in a simple way? From what I can tell, it may only be possible if I somehow generate a .crossbar/config.json which contains URI permutations of all user ids...and automatically generate a new config for each new user -- which is completely not a reasonable solution.
Any help is appreciated!

Use authorizer.
See http://crossbar.io/docs/Authorization/#dynamic-authorization
Register a dynamic authorizer for the user role that session was assigned when joining/authenticating:
{
"name": "authorizer",
"permissions": [
{
"uri": "com.example.authorize",
"register": true
}
]
},
{
"name": "authenticator",
"permissions": [
{
"uri": "com.example.authenticate",
"register": true
}
]
},
{
"name": "user",
"authorizer": "com.example.authorize"
},
...
"components": [
{
"type": "class",
"classname": "example.AuthenticatorSession",
"realm": "realm1",
"role": "authenticator",
"extra": {
"backend_base_url": "http://localhost:8080/ws"
}
},
{
"type": "class",
"classname": "example.AuthorizerSession",
"realm": "realm1",
"role": "authorizer"
}
]
Write a class
class AuthorizerSession(ApplicationSession):
#inlineCallbacks
def onJoin(self, details):
print("In AuthorizerSession.onJoin({})".format(details))
try:
yield self.register(self.authorize, 'com.example.authorize')
print("AuthorizerSession: authorizer registered")
except Exception as e:
print("AuthorizerSession: failed to register authorizer procedure ({})".format(e))
def authorize(self, session, uri, action):
print("AuthorizerSession.authorize({}, {}, {})".format(session, uri, action))
if session['authrole'] == u'backend': # backnend can do whatever
return True
[Authorization logic here]
return authorized

Related

How to publish a View to Slack app for all users?

I have a Slack App that is connected to an AWS Lex bot. Thus, the Request URL for the Slack app is the Postback URL provided by Lex. However, I want to add a Home tab for the app, but am unable to publish a surface for all users. The Slack API only seems to allow you to publish a surface for a specific user (user_id is a required parameter for the POST call). How can I publish this view to all users who use the app?
publish_url = "https://slack.com/api/views.publish"
header = {'content-type':'application/json'}
parameters = {
"token": slack_token,
"user_id": member_id, # <--- This is my problem
"view": json.dumps({
"type": "home",
"blocks": [
{
"type": "section",
"text": {
"type": "mrkdwn",
"text": "Welcome to *Survey Analyzer*! ..."
}
},
...
]
})
}
r = requests.post(publish_url, params=parameters, headers=header)
When I use my own member ID, it pushes the view properly to me and me only. I've also tried using the app's ID, but that doesn't seem to push the view to any users.
You can only publish a home tab for each user separately. You can use users.list to retrieve all users of a workspace and then call views.publish for each user in that list.
Alternatively you can subscribe to the app_home_opened event through the Events API. Once a user opens the home tab it will fire an event including the user's id. That way you'll only publish a view for a user who is actually visiting the home tab of your app.

Slack Bot | Get datepicker value

I'm trying to create my first slack bot with python.
I need your help to explain how I can get the value of the datepicker.
This is my code :
import os
from slack import WebClient
from slack.errors import SlackApiError
import time
client = WebClient(token=os.environ['SLACK_KEY'])
message = "Hey ! Pourrais-tu saisir la date de tes congés ce mois-ci ?"
attachments = [{
"blocks": [
{
"type": "actions",
"elements": [
{
"type": "datepicker",
"initial_date": "1990-04-28",
"placeholder": {
"type": "plain_text",
"text": "Select a date",
}
},
{
"type": "datepicker",
"initial_date": "1990-04-28",
"placeholder": {
"type": "plain_text",
"text": "Select a date",
}
}
]
}
]
}]
def list_users():
users_call = client.api_call("users.list")
if users_call.get('ok'):
return users_call['members']
return None
def send_message(userid):
response = client.chat_postMessage(channel=userid, text=message, username='groupadamin', attachments=attachments)
if __name__ == '__main__':
users = list_users()
if users:
for u in users:
send_message(u['id'])
print("Success!")
My bot sends a private message to all users of the slack. I want to get every one of their answers of the datepicker.
If you want more details, ask me.
In general, you need to be listening to the action.
When the use clicks the datetimepicker, a so-called interaction-payload will be sent to your python slackbot.
That payload is documented here https://api.slack.com/reference/interaction-payloads/block-actions ; you can see you can get the picked date's value by accessing actions.value.
In particular for your use case, given your code sample, it seems you've just built a script that can send messages. This will not allow you to listen to actions. You need rather a python service (an API) that can send as well as receive messages.
For this, I suggest having a look at bolt which is a slack maintained library that will take care of a lot of the heavy lifting for you. Specifically, regarding actions you can check https://slack.dev/bolt-python/concepts#action-listening

How do I pull new employee information from DocuSign through API?

Is it possible to pull the new employee’s personal information who gets hired every day from DocuSign through API? I'm trying to find a way to automate the process of user account creation process from DocuSign to Active Directory by avoiding CSV file. New to this, any input might be useful?
There are two parts to this endeavor.
The first, is not related to DocuSign. You need to get an event fired everytime a new contact is added to AD and be able to process this request. I assume you have a way to do that.
Then, the second part is using our REST API to add a new user.
Make a POST request to:
POST /v2.1/accounts/{accountId}/users
You pass this information in the request body:
{
"newUsers": [
{
"userName": "Claire Horace",
"email": "claire#example.com.com"
},
{
"userName": "Tal Mason",
"email": "tal#example.com.com",
"userSettings": [
{
"name": "canSendEnvelope",
"value": "true"
},
{
"name": "locale",
"value": "fr"
}
]
}
]
}

Firebase Auth + Python backend

I am going to use Firebase Auth and Database modules to create my web app. However, not all things that I want my app to do is possible to achieve on only front end. So I want to also use backend with Python's Bottle framework to handle requests and Pyrebase to get access to Firebase Database.
Let's say that after logging in I need to go to mainpage and see personalized content, for example my notes. They are structured this way in DB:
{
"notes": [{
"id": "1",
"title": "X",
"author": "user1"
},
{
"id": "2",
"title": "Y",
"author": "user2"
} and so on... ]
}
So how it's possible to implement showing only my articles on main page?
I understand that I need to filter my notes based on author value, but how to let Bottle understand who is currently logged in?
I've read there, that I should somehow send unique token to backend server to authenticate current user, but how to do that? Inserting Token in every link as GET parameter seems to be silly, but I see no other way to implement that.
Start by organizing your database so that each note becomes a child object:
{
"notes": {
"id1": {
"id": "id1",
"title": "X",
"author": "user1",
},
"id2": {
}
}
}
Then this particular interaction can be implemented entirely in the client-side. Just execute a query to filter the notes you want. For example in a JS client:
var uid = firebase.auth().currentUser.uid;
var query = ref.orderByChild('author').equalTo(uid);
// Listen for query value events
If you want to run this on a backend server, and you want to ensure that only logged in users are allowed to execute it, then you must pass the ID token from the client app to the server on each request. Here's how to implement the server-side logic using the Python Admin SDK:
import firebase_admin
from firebase_admin import auth
from firebase_admin import db
token = '....' # Extract from the client request
try:
decoded = auth.verify_id_token(token)
uid = decoded.uid
ref = db.reference('path/to/notes')
notes = ref.order_by_child('author').equal_to(uid).get()
# Process notes response
except ValueError as ex:
print(ex)
# Send error to client

Python facebook-sdk: retrieving names of users who posted a message on a page

I want to use the Python facebook-sdk library to retrieve the names of the persons who posted a message on a Facebook page I created.
This is an example, returned by the Graph API explorer:
{
"feed": {
"data": [
{
"from": {
"name": "Ralph Crützen",
"id": "440590514975673"
},
"message": "Nog een test.",
"created_time": "2015-10-17T19:33:30+0000",
"id": "649463214822976_649745285127205"
},
{
"from": {
"name": "Ralph Crützen",
"id": "440590514975673"
},
"message": "Testing!",
"created_time": "2015-10-16T20:44:17+0000",
"id": "649463214822976_649492455153388"
},
... etc ...
But when I use the following Python code...
graph = facebook.GraphAPI(page_access_token)
profile = graph.get_object('tinkerlicht')
posts = graph.get_connections(profile['id'], 'feed')
print(posts['data'][0]['message'])
print(posts['data'][0]['from']['name'])
...only the message value is printed. Printing the name of the person who posted the message gives the error:
print(posts['data'][0]['from']['name'])
KeyError: 'from'
At first, I thought that I needed the read_page_mailboxes permission. To use this permission, it has to be approved by Facebook, so I submitted a request. But Facebook replied:
"You don't need any additional permissions to post to Pages or blogs that you administer. You only need to submit your app for review if your app will use a public-facing login."
So what exactly is the reason I can't retrieve the from data from the messages feed? (While reading it from the Graph API explorer works fine...)
Btw, I'm using a page access token which never expires. I generated this token the way it's described here.

Categories