How to use PermissionRequiredMixin in FBV? - python-3.x

I am thinking about how I can use PermissionRequiredMixin in FBV.(I have used the same in CBV and it is working as expected).
Please find the FBV(here need to implement permission). I don't want to use #login_required()
#login_required()
This will check only if the user is authenticated or not.
def delete_viewgen(request,PermissionRequiredMixin,id):
oneuser=ShiftChange.objects.get(id=id)
permission_required = ('abc.add_shiftchange',)
oneuser.delete()# delete
return redirect('/gensall')
I am getting ERROR : missing 1 required positional argument: 'PermissionRequiredMixin'
CBV Case where it is working fine.
class ShiftChangeUpdateView(PermissionRequiredMixin,UpdateView):
permission_required = ('abc.change_shiftchange',)
login_url = '/login/'
model=ShiftChange
fields='__all__'
In CBV it is working fine and if user is not having change permission it is giving 403 Forbidden how to implement same in FBV and also how to customize 403 Forbidden message.
Thanks!

On function based views you would use decorators, in your particular case
permission_required decorator
#permission_required('abc.change_shiftchange', raise_exception=True)
delete_viewgen(request,id)

Related

How to base queryset off of current user django rest serializer

I'm trying to create a serializer with DRF that is able to validate if a user has access to a primarykeyrelatedfield entry.
I have a separate function which returns a queryset of the files the user can access. All it needs as a parameter is the request object. I'd like to use this function as the queryset kwarg for the primarykeyrelatedfield.
However, I can't find a way to access "self" in this location, so there doesn't seem to be a way to define a Queryset which is dependent upon the current user for a serializer.
This is my current attempt, which fails since when calling _request(self) I cannot access self.
class MySerializer(serializers.Serializer):
def _request(self):
request = getattr(self.context, 'request', None)
if request:
return request
files = serializers.PrimaryKeyRelatedField(many=True, required=True, queryset=get_user_files(_request(self)))
I want to validate that the user has access to the file(s) they are referencing in the request. How would I do this?
I ended up settling on a slightly less clean answer than I'd have liked:
class MySerializer(serializers.Serializer):
files = serializers.PrimaryKeyRelatedField(many=True, required=True, queryset=ScanFile.objects.all())
def validate_files(self, value):
request = self.context.get('request')
queryset = get_user_files(request)
for file in value:
if not queryset.filter(pk=file.id).exists():
raise ValidationError({'Invalid file': file})
return value
This seems to be a bit inefficient, as it ends up querying for each file twice, but it achieves the affect of users can only access files they specifically have request to.

Passing attribute from AWS Connect to Lambda using Python

Stuck on a single step and doc searching isn't helping...
In Connect I have:
Store customer input : "What's your age?"
Set contact attribute: age -> system -> stored customer input
I know the above works because I've had a Play Prompt read back the attribute.
I want Lambda to handle somethings with the age. I setup a function, I attached it to the Connect instance. I added it to the flow with a simple value pair response and that works (the Play Prompt plays back the non-dynamic response from Lambda).
When I try to make it dynamic breaks.
My understanding is that I should be able to get to this attribute in Lambda by using the passed JSON.... so I'm doing this:
age = event["Details"]["ContactData"]["Attributes"]["age"]
Connect starts saying it has trouble accessing the attribute and ends the call. What am I doing wrong? The rest of the Python code is fine because if I hard set age (age = 24) the code runs fine.
There was nothing wrong my code as it pertains to the lambda / connect integration... it was with something that was just causing an error. I started monitoring the function in cloudwatch and that helped!

Permission denied to query class in the Parse Server with JS SDK

I created a class in my Parse Server, using the Parse Dashboard, and then I changed the Class Level Permissions to allow only one user to perform read and write operations in the documents of this class:
The user that is supposed to have access to this class was also created manually through the Parse Dashboard and it looks like this:
However, when I try to query documents from this class, using this user in specific, I keep getting the error message "Permission denied for action find on class Person". This is how my code to login and query the class looks like:
const Person = Parse.Object.extend('Person')
Parse.Object.registerSubclass('Person', Person)
Parse.User.logIn('username', 'password').then(user => {
console.log('E-mail: ' + user.getEmail())
console.log('Created: ' + user.createdAt)
console.log('Current: ' + user.isCurrent())
console.log('Authenticated: ' + user.authenticated())
const query = new Parse.Query(Person)
query.equalTo('name', 'John')
return query.find()
})
I included a bunch of console.log's to check what information about the user is being printed and I confirm that the login seems to complete successfully because the fields email and createdAt match the information that I see in the Parse Dashboard. However, the field authenticated and current both return false, but I don't know why. I was expecting them to return true.
This is the only place in the application that I try to login the Parse Server and perform an operation that is restricted to only one user. Any idea why I'm getting this "Permission denied for action find on class Person" error?
I guess that this is related to security. Generally Parse will not allow a user to get data about any other user, unless you do some actions - e.g. - allow it from the dashboard. But anyway I guess that you have to do it one by one.

Get username from local session Telethon

I'm using telethon library to crawl some telegram channels. While crawling, i need to resolve many join links, usernames and channel ids. To resolve these items, i used method client.get_entity() but after a while telegram servers banned my crawler for resolving too many usernames. I searched around and found from this issue, i should use get_input_entity() instead of get_entity(). Actually telethon saves entities inside a local SQLite file and whenever a call to get_input_entity() is made, it first searches the local SQLite database, if no match found it then sends request to telegram servers. So far so good but i have two problems with this approach:
get_input_entity() just returns two attributes: ID and hash but there are other columns like username, phone and name in the SQLite database. I need a method to not just return ID and hash, but to return other columns too.
I need to control the number of resolve requests sent to telegram server but get_input_entity() sends request to telegram servers whenever founds no match in the local database. The problem is that i can't control this method when to request telegram servers. Actually i need a boolean argument for this method indicating whether or not the method should send a request to telegram servers when no match in the local database is found.
I read some of the telethon source codes, mainly get_input_entity() and wrote my own version of get_input_entity():
def my_own_get_input_entity(self, target, with_info: bool = False):
if self._client:
if target in ('me', 'self'):
return types.InputPeerSelf()
def get_info():
nonlocal self, result
res_id = 0
if isinstance(result, InputPeerChannel):
res_id = result.channel_id
elif isinstance(result, InputPeerChat):
res_id = result.chat_id
elif isinstance(result, InputPeerUser):
res_id = result.user_id
return self._sqlite_session._execute(
'select username, name from entities where id = ?', res_id
)
try:
result = self._client.session.get_input_entity(target)
info = get_info() if with_info else None
return result, info
except ValueError:
record_current_time()
try:
# when we are here, we are actually going to
# send request to telegram servers
if not check_if_appropriate_time_elapsed_from_last_telegram_request():
return None
result = self._client.get_input_entity(target)
info = get_info() if with_info else None
return result, info
except ChannelPrivateError:
pass
except ValueError:
pass
except Exception:
pass
But my code is somehow performance problematic because it makes redundant queries to SQLite database. For example, if the target is actually an entity inside the local database and with_info is True, it first queries the local database in line self._client.session.get_input_entity(target) and checks if with_info is True, then queries the database again to get username and name columns. In another situation, if target is not found inside the local database, calling self._client.get_input_entity(target) makes a redundant call to local database.
Knowing these performance issues, i delved deeper in telethon source codes but as i don't know much about asyncio, i couldn't write any better code than above.
Any ideas how to solve the problems?
client.session.get_input_entity will make no API call (it can't), and fails if there is no match in the local database, which is probably the behaviour you want.
You can, for now, access the client.session._conn private attribute. It's a sqlite3.Connection object so you can use that to make all the queries you want. Note that this is prone to breaking since you're accessing a private member although no changes are expected soon. Ideally, you should subclass the session file to suit your needs. See Session Files in the documentation.

How to translate error messages in Colander

How can I translate the error messages from the colander validators? The documentation just says that it's possible.
def valid_text(node, value):
raise Invalid(node, u"Some error message")
class form(colander.MappingSchema):
name = colander.SchemaNode(colander.String(), validator=valid_text)
I know that deform does it already but I need to use colander on his own.
According to the API documentation, the msg argument to Invalid can be a translation string instance. Information on working with translation strings is here.
Looks like this issue was already addressed and fixed, but it will be part of the next release. I've just added the changes from commit f6be836 and it works like a charm.

Resources