I'm attempting to configure Flask-Security to send email asynchronously.
I have some code which send async email via Flask-Mail, but I'm having trouble integrating it with my application factory function so that it works in conjunction with Flask-Security.
Application factory:
mail = Mail()
db = SQLAlchemy()
security = Security()
from app.models import User, Role
user_datastore = SQLAlchemyUserDatastore(db, User, Role)
def create_app(config_name):
# Config
app = Flask(__name__)
app.config.from_object(config[config_name])
config[config_name].init_app(app)
# Initialize extensions
mail.init_app(app)
db.init_app(app)
security.init_app(app, user_datastore)
return app
In the Flask-Security documentation it says to use #security.send_mail_task to override the way the extension sends emails.
So where exactly do I implement this decorator? Seems like anywhere I put it inside the application factory, I get circular imports.
These are the async email functions I am trying to use, taken from this issue:
#async
def send_security_email(msg):
with app.app_context():
mail.send(msg)
#security.send_mail_task
def async_security_email(msg):
send_security_email(msg)
Where does this code need to be put in order to work with the app factory?
Thanks in advance.
I was able to achieve this like so:
mail = Mail()
db = SQLAlchemy()
security = Security()
from app.models import User, Role
user_datastore = SQLAlchemyUserDatastore(db, User, Role)
def create_app(config_name):
# Config
app = Flask(__name__)
app.config.from_object(config[config_name])
config[config_name].init_app(app)
# Initialize extensions
mail.init_app(app)
db.init_app(app)
security_ctx = security.init_app(app, user_datastore)
# Send Flask-Security emails asynchronously
#security_ctx.send_mail_task
def async_security_email(msg):
send_security_email(app, mail, msg)
return app
Related
I need help understanding how to process a user-supplied token in my FastApi app.
I have a simple app that takes a user-session key, this may be a jwt or not. I will then call a separate API to validate this token and proceed with the request or not.
Where should this key go in the request:
In the Authorization header as a basic token?
In a custom user-session header key/value?
In the request body with the rest of the required information?
I've been playing around with option 2 and have found several ways of doing it:
Using APIKey as described here:
async def create(api_key: APIKey = Depends(validate)):
Declaring it in the function as described in the docs here
async def create(user_session: str = Header(description="The Users session key")): and having a separate Depends in the router config,
The best approach is to build a custom dependency using any one of the already existing authentication dependencies as a reference.
Example:
class APIKeyHeader(APIKeyBase):
def __init__(
self,
*,
name: str,
scheme_name: Optional[str] = None,
description: Optional[str] = None,
auto_error: bool = True
):
self.model: APIKey = APIKey(
**{"in": APIKeyIn.header}, name=name, description=description
)
self.scheme_name = scheme_name or self.__class__.__name__
self.auto_error = auto_error
async def __call__(self, request: Request) -> Optional[str]:
api_key: str = request.headers.get(self.model.name)
# add your logic here, something like the one below
if not api_key:
if self.auto_error:
raise HTTPException(
status_code=HTTP_403_FORBIDDEN, detail="Not authenticated"
)
else:
return None
return api_key
After that, just follow this from documentation to use your dependency.
After successful login from the consent screen, I am getting the access_token now the next step is to fetch all the view id from the google analytics account.Please help me out
Example: This is the access_token("ya29.A0ARrdaM8IvLg8jjVHWgxneSp_mxgFYHpKt4LwPGZEVqzOphMA2Cll6mjMxlQRFanbJHh1WrBEYVe2Y1BvBU6j7h_17nVeY4h-FWdUuv5bo0rzETTz_-xw4t5ZNBYpj26Cy3u4Y1trZnqVIA4")
You should check the Managment api quickstart python
"""A simple example of how to access the Google Analytics API."""
import argparse
from apiclient.discovery import build
import httplib2
from oauth2client import client
from oauth2client import file
from oauth2client import tools
def get_service(api_name, api_version, scope, client_secrets_path):
"""Get a service that communicates to a Google API.
Args:
api_name: string The name of the api to connect to.
api_version: string The api version to connect to.
scope: A list of strings representing the auth scopes to authorize for the
connection.
client_secrets_path: string A path to a valid client secrets file.
Returns:
A service that is connected to the specified API.
"""
# Parse command-line arguments.
parser = argparse.ArgumentParser(
formatter_class=argparse.RawDescriptionHelpFormatter,
parents=[tools.argparser])
flags = parser.parse_args([])
# Set up a Flow object to be used if we need to authenticate.
flow = client.flow_from_clientsecrets(
client_secrets_path, scope=scope,
message=tools.message_if_missing(client_secrets_path))
# Prepare credentials, and authorize HTTP object with them.
# If the credentials don't exist or are invalid run through the native client
# flow. The Storage object will ensure that if successful the good
# credentials will get written back to a file.
storage = file.Storage(api_name + '.dat')
credentials = storage.get()
if credentials is None or credentials.invalid:
credentials = tools.run_flow(flow, storage, flags)
http = credentials.authorize(http=httplib2.Http())
# Build the service object.
service = build(api_name, api_version, http=http)
return service
def get_first_profile_id(service):
# Use the Analytics service object to get the first profile id.
# Get a list of all Google Analytics accounts for the authorized user.
accounts = service.management().accounts().list().execute()
if accounts.get('items'):
# Get the first Google Analytics account.
account = accounts.get('items')[0].get('id')
# Get a list of all the properties for the first account.
properties = service.management().webproperties().list(
accountId=account).execute()
if properties.get('items'):
# Get the first property id.
property = properties.get('items')[0].get('id')
# Get a list of all views (profiles) for the first property.
profiles = service.management().profiles().list(
accountId=account,
webPropertyId=property).execute()
if profiles.get('items'):
# return the first view (profile) id.
return profiles.get('items')[0].get('id')
return None
def get_results(service, profile_id):
# Use the Analytics Service Object to query the Core Reporting API
# for the number of sessions in the past seven days.
return service.data().ga().get(
ids='ga:' + profile_id,
start_date='7daysAgo',
end_date='today',
metrics='ga:sessions').execute()
def print_results(results):
# Print data nicely for the user.
if results:
print 'View (Profile): %s' % results.get('profileInfo').get('profileName')
print 'Total Sessions: %s' % results.get('rows')[0][0]
else:
print 'No results found'
def main():
# Define the auth scopes to request.
scope = ['https://www.googleapis.com/auth/analytics.readonly']
# Authenticate and construct service.
service = get_service('analytics', 'v3', scope, 'client_secrets.json')
profile = get_first_profile_id(service)
print_results(get_results(service, profile))
if __name__ == '__main__':
main()
I'm trying to setup passwordless authentification in Firebase. I already enabled "email without password" auth in my Project settings.
Using this documentation : https://firebase.google.com/docs/auth/admin/email-action-links#generate_email_link_for_sign-in I managed to implement a way to create auth links.
My goal is to open https://dev.test.com/signup/ with the email of the user so he will be instantly signed in.
This is my code so far:
import firebase_admin
from firebase_admin import auth
def main():
default_app = firebase_admin.initialize_app()
email = 'name.chris#gmail.com'
action_code_settings = auth.ActionCodeSettings(
url=f'https://dev.test.com/signup/?email={email}',
handle_code_in_app=True,
ios_bundle_id='com.example.ios',
android_package_name='com.example.android',
android_install_app=True,
android_minimum_version='12',
dynamic_link_domain='magic42.page.link',
)
link = auth.generate_sign_in_with_email_link(email, action_code_settings)
print(f"LINK = {link}")
When I click on the link, I don't get automatically signed in. I guess I should also modify my front end. I'm using Angular. My signup looks like this :
signUp(email: string, password: string): Observable<UserCredential> {
const credential = firebase.auth.EmailAuthProvider.credential(email, password);
return from(firebase.auth().currentUser.linkWithCredential(credential));
}
I'm confused why you have email and password on frontend. To complete sign in using the email link, you should be using firebase.auth().signInWithEmailLink() method and not linkWithCredential on your /signup page.
You can get sample code (which should be executed on your /signup page) of completing sign in with email link in the documentation:
https://firebase.google.com/docs/auth/web/email-link-auth
I would like to have a common auth entry point, such as get_authed_user, that loops through a configurable list of authentication dependencies, and the first one that is able to return a user does so. Something like the following:
from app.conf import settings # this is pydantic's BaseSettings
async def get_authed_user(request: Request, Session = Depends(get_session)):
for cls_name in settings.AUTHENTICATION_CLASSES:
method = import_class(cls_name)(auto_error=False)
user = method() # how to resolve dependencies here?
if user:
return user
raise HTTP401Error
When calling the authentication callables, is there a way to resolve the dependencies of those callables?
Is there any way to use firebase push notification in electron?I want to create a push notification for my electron app which is a chat app and whenever a new message comes I want to get that notification.But I did not get any good material online to implement it.How can I do it?
You can use Websocket.
Python Snippet for websocket
Client Side:
from ws4py.client.threadedclient import WebSocketClient
client_url = "ws://server_url + "/websocket/create
ws_client = WebsocketClient(client_url)
ws_client.connect()
Server Side: Assuming you have a server with server_url serving the api /websocket/create:
from ws4py.websocket import WebSocket
class ws_server(Websocket):
WebSocket.__init__(self, *args, **kwargs)
class WebSocketHandler(object):
#cherrypy.expose
def create(self):
# wsInstance is of type ws_server. Must set userName.
wsInstance = cherrypy.request.ws_handler
And in the Server's config:
cherrypy.tree.mount(WebSocketHandler(), '/websocket',
config={
'/': {
'tools.response_headers.on': True,
'tools.sessions.locking': 'explicit',
'tools.websocket.on': True,
'tools.websocket.handler_cls': ws_server,
},
})