Can't connect to MongoDB via flask_pymongo - flask

I just encountered a problem while playing with Flask and MongoDB. Here are scenarios
With Authorization Enabled
If I use PyMongo() from flask_pymongo with mongo = PyMongo(app) pattern, I just get Authorization Errors. While I am able to successfully retrieve database via MonogoClient() from pymongo using same connection string.
Without Authorization Enabled
If I use flask_pymongo, no errors. But I am not getting any data either. For example, mongo.db.collection_names() just returns empty array. With MongoClient(), the same operation was successful.
I am using:
python = 3.6.3
flask = 0.12.2
flask_pymongo = 0.5.1
pymongo = 3.5.1
Thanks in Advance

I've been using Flask with Flask-PyMongo for a while now, and below is how I make my connections to a mongodb.
from flask import Flask
from flask_cors import CORS
from flask_pymongo import PyMongo
app = Flask(__name__)
CORS(app) # very important!
USERNAME = '<username>'
PASSWORD = '<password>'
PORT = '27017'
HOST = 'localhost'
app.config['MONGO_DBNAME'] = '<DB Name>'
app.config['MONGO_HOST'] = HOST
app.config['MONGO_PORT'] = PORT
app.config['MONGO_USERNAME'] = USERNAME
app.config['MONGO_PASSWORD'] = PASSWORD
mongo = PyMongo(app)
You may not need the CORS(app) depending on your setup.
To create multiple connections do the following:
# Users db
app.config['MONGO2_DBNAME'] = 'users'
app.config['MONGO2_HOST'] = HOST
app.config['MONGO2_PORT'] = PORT
app.config['MONGO2_USERNAME'] = USERNAME
app.config['MONGO2_PASSWORD'] = PASSWORD
users_mongo = PyMongo(app, config_prefix='MONGO2')
I should also note that I had problems connecting with authorization through Flask-PyMongo because the database needed to have authorization configured a certain way. Flask-PyMongo expects the db authority to be on the database itself and not elsewhere. So when creating a user and password for a db do the following inside a mongo shell:
Create user admin
use admin
db.createUser({user: "userAdmin", pwd: "", roles: [ { role: "userAdminAnyDatabase", db: "admin" } ] } )
Create user on YOUR db
use <YOUR db>
db.createUser({user: "", pwd: "", roles:[{ role: "dbAdmin", db: ""}, {role: "readWrite", db: ""}]})
Within mongo and even with PyMongo you can create users within one database and give them access to other dbs, but Flask-PyMongo for whatever reason does not play nice here and you'll need the user created within the database you want to use.
Hope this helps as I've struggled here as well. Feel free to ask for clarification

Related

Mapping roles in AzureAD to Django groups

Okay, I can now do SSO in Django via AzureAD by using django-microsoft-auth.
But I would like to manage the groups there as well. For that we configured to pass roles in the token. But how do I map those to Django groups? I don't seem to find any example for that.
Found it. For anyone with the same question, you'll have to use the 'MICROSOFT_AUTH_AUTHENTICATE_HOOK' setting.
I made a module in my 'app' called aad.py:
import jwt
def add_to_group(user, token):
from django.contrib.auth.models import Group
id_token = token['id_token']
token_data = jwt.decode(id_token, options={"verify_signature": False})
roles = token_data.get('roles', [])
user.groups.clear()
for r in roles:
current_group, created = Group.objects.get_or_create(name=r)
current_group.user_set.add(user)
in the settings I added the following setting:
MICROSOFT_AUTH_AUTHENTICATE_HOOK = "myApp.aad.add_to_group"
Of course things could be neater, but it works for now.

How to implement FirebaseDB with a Django Web Application

Am trying to implement Firebase Realtime Database with my Django Web Application. After properly setting up the configuration with Firebase, I got confused about how data will write into my Firebase Database from my Django website instead of using Sqlite, or Postgres.
Under settings.py, do I need to set my engine to Firebase? Am totally confused here. I do not want to use the normal ORM such as Sqlite, Postgres etc. I want my app to use Firebase.
Is there something else I need to understand about Firebase?
settings.py
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
}
}
pyrebase_settings file
import pyrebase
config = {
"apiKey": "my_api_key_is_here",
"authDomain": "my_auth_domain_is_here",
"databaseURL": "my_firebase_database_url_is_here",
"projectId": "my_firebase_project_id_is_here",
"storageBucket": "my_firebase_storageBucket_is_here",
"serviceAccount": "my_serviceAccount.json_file_path_is_here",
"messagingSenderId": "messagingSenderId_is_here"
}
# initialize app with config
firebase = pyrebase.initialize_app(config)
# authenticate a user
auth = firebase.auth()
user = auth.sign_in_with_email_and_password("email#usedforauthentication.com", "FstrongPasswordHere")
db = firebase.database()
take a look at the database section of the doc. It details how you would interact with the database API. Typically you would use these in your views where you need to save or retrieve something from the database.
e.g say you want a view that gets users, you could have something like this:
#views.py
from pyrebase_settings import db, auth
from django.shortcuts import render
def get_users(request):
users = db.child("users").get()
return render(request, 'users.html', {'users': users.val()})
The documentation for retrieving data can be seen here
also say you want a view to save(signup) users, you could have something like so:
#views.py
from pyrebase_settings import db, auth
def signup(request):
form = SignupForm(request.POST)
if form.is_valid():
email = form.cleaned_data('email')
password = form.cleaned_data('password')
auth.create_user_with_email_and_password(email, password)
# the rest of your code goes here
the create_user_with_email_and_password method is documented here
PS. I have never made use of the pyrebase library so I write only based on what is specified in its docs. Also I am only writing these django snippets off the top of my head so forgive me if there are any syntax errors or typos :)
Hope this helps :)
Is there something else I need to understand about Firebase?
No, there is something you need to understand about Django -- it is designed to use a relational database engine as its primary data store. Firebase is not relational.
Sorry to be the bearer of bad news.
Many answers on this question are missing this point, and suggesting code or libraries that let you access Firebase from Python. Sure, that's possible. But that doesn't make it work as a primary data store for Django. Django's ORM features and contrib apps all presume a relational database.
In order for this to work you'd need something along the lines of django-nonrel that supported Firebase. As far as I know that doesn't exist.
consider having a look at the fcm-django library here https://github.com/xtrinch/fcm-django
My solution for getting multiple files from html and upload that files in firebase storage in web django
index.html
<div id="fine-uploader-manual-trigger">
<input class="custom-file" type="file" name="imgname" id="productImgUpload" accept=".xlsx,.xls,image/*,.doc,audio/*,.docx,video/*,.ppt,.pptx,.txt,.pdf" multiple>
</div>
views.py
from firebase import Firebase
def storeimg(request):
config = {
"apiKey": "",
"authDomain": "",
"databaseURL": "",
"storageBucket": ""
}
firebase = Firebase(config)
storage = firebase.storage()
finalimglist = []
imglist = []
for i in range(len(filepath)):
storage.child("Product/"+cname+"/"+str(filepath[i])).put(filepath[i])
imgurl = storage.child("Product/"+cname+"/"+str(filepath[i])).get_url(token='null')
imglist.append(imgurl)
finalimglist.append(imglist)
Pyrebase is a wrapper around the Firebase for python. I don't recommend using Pyrebase because it lags support for Firestore and FCM. When everything in Django is done on Serverside, why not use the Firebase Admin SDK on the Django server. You can also manage users with it. I mean there is good documentation for adding the Firebase to our server. Also, they have docs in Python, NodeJS etc., for the server. I know its kind of going towards API stuff. But I feel its the right way to do in Django since Django is a server application. Check out this link

Django allauth get credentials to make further requests on behalf of the user

I'm working on a Django project that requires user authentication for BitBucket, I have setup allauth such that users can authenticate with Bitbucket, I just don't understand how to make further requests to the Bitbucket API now that the user is authenticated.
I understand that allauth is purely for authentication purposes, there is just no documentation on how to access and make further use of the authentication, in this case accessing the credentials (oauth_token) such that I can make further requests on behalf of the resource-owner.
I found the authentication details to make a further requests.
Workflow
from allauth.socialaccount.models import SocialAccount, SocialApp
bitbucket_app = SocialApp.objects.get(provider='bitbucket')
user_account = SocialAccount.objects.get(user=request.user)
# User should only have one SocialToken object per SocialApp
# https://github.com/pennersr/django-allauth/blob/master/allauth/socialaccount/models.py#L137
user_token = useraccount.socialtoken_set.first()
# Credentials to make further requests
client_key = bitbucket_app.client_id
client_secret = bitbucket_app.secret
resource_owner_key = user_token.token
resource_owner_secret = user_token.token_secret
Using credentials with requests and requests_oauthlib
import requests
from requests_oathlib import OAuth1
auth = OAuth1(client_key, client_secret, resource_owner_key, resource_owner_secret)
r = requests.get(protected_url, auth=auth)
An example with the bitbucket-api
https://bitbucket-api.readthedocs.org/en/latest/index.html
from bitbucket.bitbucket import Bitbucket
bb = Bitbucket(user_account.uid) # Initialise with bitbucket username
bb.authorize(client_key, client_secret, 'http://localhost', resource_owner_key, resource_owner_secret)
# Get user repositories as an example
bb.repository.all()

REST login with Django social_auth

I've been asked to provide a "Login with Facebook" functionality to an iOS app I am creating.
The app connects to a REST api created with Piston, the web application is created with Django and uses social_auth. The application also has a Facebook login.
My thought was to create a service 'FBLogin' providing just the Facebook profile UID (separate FB login procedure on iPhone to get the ID). Using the SocialAuth models I can query the DB with uid and provider to fetch the user... but how can i use the authentication mechanism to get this user instance authenticated?
Any ideas on getting this right?
This just doesn't feel good ... getting the user instance authenticated is a pain...
The username password authentication is already implemented ... without a problem.
Btw, don't have django experience ... do have a lot of other development experience so understanding python and django isn't that hard :)
Tx
Y
It doesn't really seem to be documented anywhere, but you can do this in your REST handler:
from social_auth.backends.pipeline.social import associate_user
from social_auth.backends.facebook import FacebookBackend
from social_auth.models import UserSocialAuth
myextra_data = {
'access_token' : 'jfkdlfsdgeyejfghfdsjdfpoweipuo',
'id' : 123456789,
}
usa, created = UserSocialAuth.objects.get_or_create(provider = 'facebook',
uid=123456789)
usa.user = user
usa.extra_data = myextra_data
usa.save()
if created:
associate_user(backend=FacebookBackend, user=user, uid=usa.uid)
These get pretty vendor-specific in terms of how data gets formatted in extra_data so YMMV

Create users in LDAP using Django

I am having trouble with the LDAP authentification module django-auth-ldap. I am using the example configuration from this site: http://packages.python.org/django-auth-ldap/
I'd like to do two things:
1) Authentificate against LDAP:
For the moment, my LDAP database is empty, I didn't add anything to it, in fact I don't know how to. However, I still am able to log in into my django-based site with my old logins/passwords stored in my django database. Why is that? Shouldn't this be ignored, shouldn't the login process occur with LDAP user/passwords instead? In other words, if my LDAP database is empty, shouldn't every single of my login fail? However, it doesn't, I have the impression that django completly ignores the django-auth-ldap module.
2) Synchronize LDAP with django (and not the other way around)
I don't want to use an existing user database to authentificate against. I want to be able to create new users in Django and propagate these users to LDAP so they can be shared by other services, in my case, an openfire server. How do you do that with django-auth-ldap?
Here is the copy/paste of my configuration:
# Baseline configuration.
AUTH_LDAP_SERVER_URI = "127.0.0.1"
AUTH_LDAP_BIND_DN = "cn=admin,dc=nodomain"
AUTH_LDAP_BIND_PASSWORD = "admin"
AUTH_LDAP_USER_SEARCH = LDAPSearch("ou=users,dc=nodomain",
ldap.SCOPE_SUBTREE, "(uid=%(user)s)")
# Set up the basic group parameters.
AUTH_LDAP_GROUP_SEARCH = LDAPSearch("ou=django,ou=groups,dc=nodomain",
ldap.SCOPE_SUBTREE, "(objectClass=groupOfNames)"
)
AUTH_LDAP_GROUP_TYPE = GroupOfNamesType(name_attr="cn")
# Only users in this group can log in.
AUTH_LDAP_REQUIRE_GROUP = "cn=enabled,ou=django,ou=groups,dc=nodomain"
# Populate the Django user from the LDAP directory.
AUTH_LDAP_USER_ATTR_MAP = {
"first_name": "givenName",
"last_name": "sn",
"email": "mail"
}
AUTH_LDAP_PROFILE_ATTR_MAP = {
"employee_number": "employeeNumber"
}
AUTH_LDAP_USER_FLAGS_BY_GROUP = {
"is_active": "cn=active,ou=django,ou=groups,dc=nodomain",
"is_staff": "cn=staff,ou=django,ou=groups,dc=nodomain",
"is_superuser": "cn=superuser,ou=django,ou=groups,dc=nodomain"
}
AUTH_LDAP_ALWAYS_UPDATE_USER = True
AUTH_LDAP_FIND_GROUP_PERMS = True
AUTH_LDAP_CACHE_GROUPS = True
AUTH_LDAP_GROUP_CACHE_TIMEOUT = 3600
# Keep ModelBackend around for per-user permissions and maybe a local
# superuser.
AUTHENTICATION_BACKENDS = (
'django_auth_ldap.backend.LDAPBackend',
'django.contrib.auth.backends.ModelBackend',
)
Sorry I don't know much about LDAP, I just installed it this morning so my question may sound naive. I just need a centralized user base that I would be able to update and share between several servers.
Thanks very much for your help.
1) Your configuration has two authentication backends installed:
AUTHENTICATION_BACKENDS = ( 'django_auth_ldap.backend.LDAPBackend', 'django.contrib.auth.backends.ModelBackend', )
Django will attempt to authenticate against each one in turn until it finds one that succeeds (or until it runs out). Since your LDAP directory is empty, it will presumably always fail, so ModelBackend will always get a shot. If you don't want to authenticate users against the Django user database, you have to remove ModelBackend from the list.
2) django-auth-ldap doesn't propagate Django users up to LDAP, only the other way around. It's designed to allow Django deployments to authenticate against existing LDAP services that are managed separately. To manipulate the contents of an LDAP directory from a Django app you might want to look at django-ldapdb.