oauthlib creating own oauthlib2 in python falcon - python-2.7

My database look like this
from sqlalchemy.ext.declarative import declarative_base
import os
import time
import datetime
import sys
import uuid
from sqlalchemy import Column, ForeignKey, Integer, String
from sqlalchemy.orm import relationship
from sqlalchemy import create_engine
from sqlalchemy import *
from sqlalchemy_utils.types.choice import ChoiceType
from sqlalchemy_utils.types.url import URLType
Base = declarative_base()
class User(Base):
__tablename__ = 'user'
id = Column(Integer, primary_key=True)
name = Column(String(250), nullable=False)
fullname = Column(String(250), nullable=False)
password = Column(String(250), nullable=False)
def __repr__(self):
return "<User(name='%s', fullname='%s', password='%s')>" % (self.name, self.fullname, self.password)
class Client(Base):
Grand_choice = [('authorization_code', 'Authorization code')]
Response_choice = [('code', 'Authorization code')]
__tablename__ = 'client'
id = Column(Integer, primary_key=True)
client_id = Column(String(250), default=uuid.uuid4() ,unique=True)
user = Column(Integer, ForeignKey('user.id'))
grant_type = Column(ChoiceType(Grand_choice))
response_type = Column(ChoiceType(Response_choice))
scopes = Column(String(260))
default_scopes = Column(String(260))
redirect_uri = Column(URLType)
default_redirect_uri = Column(URLType)
class Bearer_Token(Base):
__tablename__ = 'Bearer_Token'
id = Column(Integer, primary_key=True)
client = Column(Integer, ForeignKey('client.id'))
user = Column(Integer, ForeignKey('user.id'))
scopes = Column(String(250))
access_token = Column(String(100),unique=True)
refresh_token = Column(String(100),unique=True)
expires_at = Column(DateTime, onupdate=datetime.datetime.now)
class Authorization_Code(Base):
__tablename__ = 'Authorization_code'
id = Column(Integer, primary_key=True)
client = Column(Integer, ForeignKey('client.id'))
user = Column(Integer, ForeignKey('user.id'))
scopes = Column(String(250))
code = Column(String(100),unique=True)
expires_at = Column(DateTime, onupdate=datetime.datetime.now)
engine = create_engine('sqlite:///sqlalchemy_oauth.db')
Base.metadata.create_all(engine)
and my validator look like this
from oauthlib.oauth2 import RequestValidator
from modelsforoauth import User ,Client, Base
from sqlalchemy.orm import sessionmaker
from sqlalchemy import create_engine
engine = create_engine('sqlite:///sqlalchemy_oauth.db', echo=True)
Base.metadata.bind = engine
DBSession = sessionmaker()
DBSession.bind = engine
session = DBSession()
#session.query(Client.client_id).first()
class MyRequestValidator(RequestValidator):
def validate_client_id(self, client_id, request):
try:
session.query(Client).filter_by(client_id=client_id).first()
return True
except Client.DoesNotExist:
return False
I wannted to define endpoint for my api in falcon.
from My_validator import MyRequestValidator
from oauthlib.oauth2 import WebApplicationServer
validator = MyRequestValidator()
server = WebApplicationServer(validator)
class AuthorizationView(object):
def __init__(self):
self._authorization_endpoint = server
def on_get(self, req, resp):
When I look at the documentation in the following link oauthlibserver
this clearly says that
uri, http_method, body, headers = extract_params(request)
How do i acheive this in falcon
also i wanted to check if my datamodels are correct as per the requirement in documentaion
I also dont understand what should be scope and uri_redirect
If i have to make some changes in models or code please experts let me know
form a newbee
Thanks in Advance

Your extract param function should look like this:
def extract_params(request):
# returns uri, http_method, body, headers
return request.uri, request.method, request.stream.read(), request.headers

Related

Django unit testing FileField and ImageField using ContentFile

I am using Django 3.2
I have a model like this:
Foo class
class Foo(models.Model):
name = models.CharField(max_length=124)
owner = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
description = models.TextField()
bio = models.TextField()
attachment = models.FileField()
photo = models.ImageField()
recorded_date = models.DateField()
time_of_day = models.TimeField()
timestamp = models.DateTimeField()
duration = models.DurationField()
website = models.URLField()
pseudo_array = models.CharField(max_length=256)
pseudo_tags = models.CharField(max_length=128)
Snippet of Unit test
import glob
import os
import json
from datetime import datetime, timedelta
from django.utils.timezone import make_aware
from model_bakery import baker
from django.test import TestCase
from django.core.exceptions import ValidationError
from django.core.files.base import ContentFile
image_mock =ContentFile(b"R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==", name='photo.png')
file_mock = ContentFile("Some random text", name='archive.txt')
class TestModels(TestCase):
def setUp(self):
current_timestamp = datetime.now(timezone.utc)
self.foo = Foo.objects.create( name='Accepted Object',bio='For accepted testing',
owner=self.pattysmith,
description='Object for accepted testing',
attachment = file_mock,
photo = image_mock,
recorded_date = datetime.strptime('20200101','%Y%m%d'),
time_of_day = datetime.strptime('10:00','%H:%M'),
timestamp = make_aware(timezone.now().strptime('20200101 10:00','%Y%m%d %H:%M')),
duration = timedelta(days=20, hours=10),
website = 'https://www.accepted.com',
moderation_status=1,
pseudo_tags='approved,nice, accepted'
)
def tearDown(self):
Foo.objects.all().delete()
User.objects.all().delete()
for f in glob.glob("*.png"):
os.remove(f)
for f in glob.glob("*.txt"):
os.remove(f)
def test_change_moderated_char_field(self):
self.foo.name='My new name'
self.foo.save(update_fields=['name'])
# test for number of changed fields ...
When I run the test test_change_moderated_char_field I see that the file and image field names have changed - looks like Django is auto-generating the file names.
Here is what my console printout looks like:
moderated_field_current_field_value: 'My new name' != 'Accepted Object' for moderated field: name
moderated_field_current_field_value: /path/to/archive_Fo8NWLI.txt != /path/to/archive.txt for moderated field: attachment
moderated_field_current_field_value: /path/to/photo_mVEyGtI.png != /path/to/photo.png for moderated field: photo
######### changed_fields: ["name", "attachment", "photo"] #####
I am currently accessing the name of the file/image by accessing the path attribute on the field. How do I get the name of the file when it is actually uploaded (since some name mangling seems to be taking place?

How to pass data to a wtforms QuerySelectField in flask

I'm working on a app with RBAC and I'm trying to populate a QuerySelectField with data from my Role database model but it doesn't work because I'm constantly getting one of those two errors:
sqlalchemy.exc.OperationalError: <unprintable OperationalError object>
or
TypeError: 'BaseQuery' object is not callable
models.py
class Role(db.Model):
id = db.Column(db.Integer, primary_key=True, autoincrement='auto')
name = db.Column(db.String(50), unique=True)
user = db.relationship('User', backref='role', lazy='dynamic')
not_view = db.Column(db.Text, nullable=False)
not_edit = db.Column(db.Text, nullable=False)
not_add = db.Column(db.Text, nullable=False)
not_delete = db.Column(db.Text, nullable=False)
forms.py
from flask_wtf import FlaskForm
from wtforms import StringField, PasswordField
from wtforms.validators import DataRequired, Email, EqualTo, Length
from app.models import Role
from wtforms.ext.sqlalchemy.fields import QuerySelectField
def role_choice():
return Role.query
class AddUserForm(FlaskForm):
username = StringField('Username', validators=[DataRequired(), Length(min=2, max=20)])
email = StringField('Email', validators=[DataRequired(), Email()])
password = PasswordField('Password', validators=[DataRequired()])
confirm_password = PasswordField('Confirm Password', validators=[DataRequired(), EqualTo('password')])
role_id = QuerySelectField(query_factory=role_choice)
I tried a few different ways of passing in data but none of them worked. Can someone help?
Don't bother to answer, I already solved the problem with a SelectField with a dynamic choice.
class UserDetails(Form):
group_id = SelectField(u'Group', coerce=int)
def edit_user(request, id):
user = User.query.get(id)
form = UserDetails(request.POST, obj=user)
form.group_id.choices = [(g.id, g.name) for g in Group.query.order_by('name')]

If a child object has an attribute=True then update all others to attribute=False

I have the following model:
class AddressOfUser(AddressMixin, BaseModel):
__tablename__ = 'adrusr_addressofuser'
user = db.relationship('User', backref='addresses')
user_id = db.Column(db.Integer, db.ForeignKey('users.id'), nullable=False)
default = db.Column('adrusr_default', db.Boolean, default=False)
first_name = db.Column('adrusr_first_name', db.String)
last_name = db.Column('adrusr_last_name', db.String)
phone = db.Column('adrusr_phone', db.String)
so when a user creates an address they can set that address to default by the default attribute to True using a checkbox in the form that is used to create the address.
The problem is that the user can set multiple addresses to default and that's a problem cause we won't be able to know which address to use as the default one so how can I make that if the latest address registered by the user is set as default so the rest of the addresses won't be default anymore? In other words if the latest element of has the attribute default = True then previous addresses should have default = False.
You can update the sibling objects using "after_insert" and "after_update" events. In the following example, if an Address is inserted or updated with is_default=True then the event handler will force all other Address entries for that particular User to be is_default=False.
# https://stackoverflow.com/q/66027263/2144390
import sqlalchemy as db
from sqlalchemy import event
from sqlalchemy.orm import declarative_base, relationship
connection_uri = "sqlite://"
engine = db.create_engine(
connection_uri,
future=True,
echo=True,
)
Base = declarative_base()
class Address(Base):
__tablename__ = "address"
id = db.Column(db.Integer, primary_key=True)
user_id = db.Column(db.Integer, db.ForeignKey("user.id"), nullable=False)
address = db.Column(db.String, nullable=False)
is_default = db.Column(db.Boolean, nullable=False, default=False)
user = relationship("User", back_populates="addresses")
def __repr__(self):
return (
f"<Address(user={self.user}, address='{self.address}'"
f", is_default={self.is_default})>"
)
class User(Base):
__tablename__ = "user"
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String)
addresses = relationship("Address", back_populates="user")
def __repr__(self):
return f"<User(id={self.id}, name='{self.name}')>"
Base.metadata.create_all(engine)
def _remove_other_default_addrs(mapper, connection, target):
if target.is_default:
session = db.inspect(target).session
session.query(Address).filter(
Address.user_id == target.user_id
).filter(Address.id != target.id).filter(
Address.is_default == True
).update(
values={"is_default": False}, synchronize_session="evaluate"
)
#event.listens_for(Address, "after_insert")
def receive_after_insert(mapper, connection, target):
_remove_other_default_addrs(mapper, connection, target)
#event.listens_for(Address, "after_update")
def receive_after_update(mapper, connection, target):
_remove_other_default_addrs(mapper, connection, target)
with db.orm.Session(engine, future=True) as session:
gord = User(name="Gord")
gord_old_addr = Address(user=gord, address="123 Old Ave", is_default=True)
session.add_all([gord, gord_old_addr])
session.commit()
print(f">>> gord_old_addr.is_default is {gord_old_addr.is_default}")
# >>> gord_old_addr.is_default is True
gord_new_addr = Address(user=gord, address="567 New Blvd", is_default=True)
session.add(gord_new_addr)
session.flush()
print(">>> session flushed")
print(f">>> gord_old_addr.is_default is {gord_old_addr.is_default}")
# >>> gord_old_addr.is_default is False

IntegrityError in Django testcase

I am suspecting that transaction.atomic() does not commit my instance to the database during testing. The problem might comes from multiple databases
from django.db import models
from model_utils.models import TimeStampedModel
class PIIField(TimeStampedModel):
"""
Personal Information Identifier configuration model
This model is M2M on `Plan`
"""
name = models.CharField(max_length=30)
detail = models.CharField(max_length=50, null=True, blank=True)
order = models.SmallIntegerField(unique=True)
def __str__(self):
return self.name
class Plan(timestamp.Model, models.Model):
class Meta:
db_table = "catalog_plans"
product = models.ForeignKey(Product,
on_delete=models.CASCADE,
related_name="plans")
coverages = models.ManyToManyField(Coverage, through="PlanCoverage")
code = models.TextField(null=True)
name = models.TextField()
pii_fields = models.ManyToManyField(PIIField, related_name='plans', related_query_name='plan')
Here is my tests.py
from django.db import transaction
from django.test import TransactionTestCase
from model_mommy import mommy
from rest_framework import status
from rest_framework.reverse import reverse
from rest_framework.test import APIClient
from catalog.models import Plan
from pii_fields.models import PIIField
class PIIFieldTestCase(TransactionTestCase):
databases = {'default', 'product', 'customer'}
def setUp(self) -> None:
with transaction.atomic():
self.plan = mommy.make(Plan, code='88', name='Non risky life') # single `plan` with no` pii_fields` attached
self.field_1 = mommy.make(PIIField, name='first_name', detail='text box', order=1)
self.field_2 = mommy.make(PIIField, name='last_name', detail='text box', order=2)
self.field_3 = mommy.make(PIIField, name='weight', detail='real number', order=3)
self.field_4 = mommy.make(PIIField, name='nationality', detail='drop down', order=4)
self.plan.pii_fields.set([self.field_1, self.field_2, self.field_3, self.field_4])
def test_get(self):
"""
Get the endpoint and see the payload sample
:return:
"""
client = APIClient()
url = reverse('api:pii_field-detail', args=[self.plan.id])
res = client.get(url)
self.assertEqual(status.HTTP_200_OK, res.status_code)
Error:
django.db.utils.IntegrityError: insert or update on table "catalog_plans_pii_fields" violates foreign key constraint "catalog_plans_pii_fi_piifield_id_58130345_fk_pii_field"
DETAIL: Key (piifield_id)=(1) is not present in table "pii_fields_piifield".
Question:
How to test my database and viewsets?
I have to use another syntax to add my records. I had tried bulk_create, but it does not work
self.plan.pii_fields.create(name='first_name', detail='text box', order=1)
self.plan.pii_fields.create(name='last_name', detail='text box', order=2)
self.plan.pii_fields.create(name='weight', detail='real number', order=3)
self.plan.pii_fields.create(name='nationality', detail='drop down', order=4)

Flask SQLalchemy many-to-many relationship, need secondaryjoin and primaryjoin for some reason

In SQLAlchemy docs, http://docs.sqlalchemy.org/en/rel_0_9/orm/relationships.html Everything should work fine but I get an error called
Original exception was: Could not determine join condition between parent/child tables on relationship User.rank_r. Specify a 'primaryjoin' expression. If 'secondary' is present, 'secondaryjoin' is needed as well.
class User(db.Model, UserMixin):
__tablename__ = 'users'
rank_r = db.relationship('Rank',
secondary=ranks,
backref=db.backref('users', lazy='dynamic'))
class Rank(db.Model):
__tablename__ = 'rank'
id = Column(db.Integer, primary_key=True)
name = Column(db.String(STRING_LEN), nullable=False, unique=True)
ranks = db.Table('ranks',
db.Column('rank_id', db.Integer, db.ForeignKey('rank.id')),
db.Column('user_id', db.Integer, db.ForeignKey('users.id'))
)
Basically I am trying to do this:
SELECT u.id, u.name, r.name users u INNER JOIN ranks r ON r.id=rr.rank_id INNER JOIN rank rr ON rr.user_id==u.id
This would return something like:
1 Bob Major
2 Joey Captain
3 Adam Brigadier General
This relationship code also seems to fail:
rank_r = db.relationship('Rank',
primaryjoin="(rank.c.id==ranks.c.rank_id)",
secondary="ranks",
secondaryjoin="(id==ranks.c.user_id)",
backref=db.backref('users', lazy='dynamic'))
with error:
StatementError: No column rank.id is configured on mapper Mapper|User|users... (original cause: UnmappedColumnError: No column rank.id is configured on mapper Mapper|User|users...) 'SELECT rank.id AS rank_id, rank.name AS rank_name \nFROM rank, ranks, users \nWHERE ? = ranks.rank_id AND users.id = ranks.user_id' [immutabledict({})]
This is what is displayed when i try to call "User.rank_r" in the template.
You code seems alright, I removed a couple of things (just to reduce my imports) and it seems to do what you're after:
from flask import Flask
from flask.ext.sqlalchemy import SQLAlchemy
app = Flask(__name__)
app.secret_key = 'MOO.'
app.config["SQLALCHEMY_DATABASE_URI"] = 'sqlite://' # In memory.
db = SQLAlchemy(app)
ranks = db.Table('ranks',
db.Column('rank_id', db.Integer, db.ForeignKey('rank.id')),
db.Column('user_id', db.Integer, db.ForeignKey('users.id'))
)
class User(db.Model):
__tablename__ = 'users'
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String())
ranks = db.relationship('Rank',secondary=ranks,
backref=db.backref('users', lazy='dynamic'))
def __init__(self, name):
self.name = name
def __repr__(self):
return self.name
class Rank(db.Model):
__tablename__ = 'rank'
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(), nullable=False, unique=True)
def __repr__(self):
return self.name
#app.route('/')
def hello_world():
return 'Hello World!'
if __name__ == '__main__':
with app.app_context():
db.create_all()
bob = User('Bob')
joey = User('Joey')
adam = User('Adam')
major = Rank(name='Major')
captain = Rank(name='Captain')
general = Rank(name='General')
db.session.add_all([bob, joey, adam, major, captain, general])
bob.ranks.append(major)
joey.ranks.append(captain)
adam.ranks.append(general)
adam.ranks.append(captain)
db.session.commit()
users = User.query.all()
for user in users:
for rank in user.ranks:
print '{} {}'.format(user, rank)
# Bob Major
# Joey Captain
# Adam Captain
# Adam General