How to filter groups where the user is an admin? - facebook-graph-api

Making a request on the graph API in a user/groups node, I would like to bring only the data of groups in which the user is an administrator.
Can I pass some filter parameter to the administrator bringing only 'true' results? Or is there any other way to do this?
I've tried a few uses of .filtering, but none have worked. Other Meta APIs have filter defaults of admin_only, but I couldn't make use of them here.
Request:
https://graph.facebook.com/me?fields=name,id,first_name,last_name,email,picture{url},groups.limit(250){id,name,administrator}&access_token=xx

https://developers.facebook.com/docs/graph-api/reference/user/groups/#parameters:
admin_only
boolean
Default value: false
Filter to get only groups admined by this viewer
Will need the user_managed_groups permission, without it I get an empty list.

Related

need a better way to validate fields in request body django depending on a specific field value

The requirement is to verify body fields in an api request depending on another field.
Like:
the request data has a field:
action
If actions is deactivate
then no other field should be present in the body data however if the action is anything else we want to allow updating other fields as well such as name.
currently we have a validation where we are going through the dictionary keys
and comparing like below:
expected_keys = ['client_updated', 'updated_by', 'actions']
if key not in expected_keys:
raise ValidationError("Deactivation action does not allow {} to be updated".format(key))
Just wanted to know if there is a better way to handle via django or django rest framework, with somewhat less harcoding.

Efficient way of checking if a User has permissions from a list and converting results to a dictionary

i wish to be able to do the following :
Pass in a list of permissions , for example: ['can_change_xxx' , 'can_add_xxx',...]
The function would convert it to {'can_change_xxx':True,'can_add_xxx':False,...}
as efficiently as possible.
The reason for doing so would be to create a permissions field serializer whereby i would pass the boolean values to the front end to do some conditional rendering.
You can use the method on the User model to get the objects permissions. It returns a set of strings. With a little dict comprehension and checking to see if the
def get_perm_dict(user, perm_list):
// Gives me a set of user permissions
user_perms = User.get_user_permissions(obj=user)
// Iterates through the passed in permission list and see if the user has them
perms_dict = { permission: True if permission in user_perms else False for permission in perms_list }
This removes the need for manually checking that a user has each permission in the list via user.has_perm
You can make use dict comprehensions like this:
def get_perm_dict(user, perm_list):
return { p: user.has_perm(p) for p in perm_list}
Thats a fast way to generate dictionaries, but I'm not sure if django provides a more efficient way to get all user permissions at once intead of checking each individually.

Allowing users to only view data related to them in Apache Superset

I have some information related to different vendors in my database and I want to allow each registered vendor (representative person) to view slices/dashboards which contains only data related to them.
One possible solution could be to create separate views for each vendor as well as separate roles for each vendor. But it feels like a bad idea if you have 100+ vendors (as is my case); and it's not a flexible or scalable solution.
Is there some way to automatically filter a given view for each user? For example, we have a "general profit by product" bar chart, and user X can see only products of vendor X
What you're looking for is multi-tenancy support, and this is not currently supported out-of-the-box in Superset.
There is however an open PR for one possible solution: https://github.com/apache/incubator-superset/pull/3729
One option could be to re-use and/or adapt that code for your use-case.
Another option might be to look into JINJA_CONTEXT_ADDONS [https://github.com/apache/incubator-superset/blob/master/docs/installation.rst#sql-lab] and see whether you might be able to pass additional context to your query (e.g. your vendor_id) and restrict the scope of your query using that parameter.
Superset config has the below two configurations(DB_CONNECTION_MUTATOR, SQL_QUERY_MUTATOR), which can allow for multi-tenancy to an extent.
A callable that allows altering the database conneciton URL and params
on the fly, at runtime. This allows for things like impersonation or
arbitrary logic. For instance you can wire different users to
use different connection parameters, or pass their email address as the
username. The function receives the connection uri object, connection
params, the username, and returns the mutated uri and params objects.
Example:
def DB_CONNECTION_MUTATOR(uri, params, username, security_manager, source):
user = security_manager.find_user(username=username)
if user and user.email:
uri.username = user.email
return uri, params
Note that the returned uri and params are passed directly to sqlalchemy's
as such create_engine(url, **params)
DB_CONNECTION_MUTATOR = None
A function that intercepts the SQL to be executed and can alter it.
The use case is can be around adding some sort of comment header
with information such as the username and worker node information
def SQL_QUERY_MUTATOR(sql, username, security_manager):
dttm = datetime.now().isoformat()
return f"-- [SQL LAB] {username} {dttm}\n{sql}"
SQL_QUERY_MUTATOR = None
One easy way of solving this problem is by using pre-defined JINJA parameters.
Two parameters that can be used are '{{current_username() }}' and {{current_user_id() }}
First you need to ensure that you can use JINJA templates -
In superset_config.py add the following
FEATURE_FLAGS = {
"ENABLE_TEMPLATE_PROCESSING": True,
}
Restart
Now if you go to the SQL LAB and type the following -
SELECT '{{ current_username() }}',{{ current_user_id() }};
You should get an output
?column?
?column?__1
PayalC
5
Now all you have to do is append one of the two following sql snippet in all your queries.
select ........ from ...... where ...... vendorid={{ current_user_id() }}
select ........ from ...... where ...... vendorname='{{ current_username() }}'
vendorid={{ current_user_id() }} and/or
vendorname='{{ current_username() }}' will restrict the user to view only her data.
You could also make it more flexible by creating a table which has a mapping of user to vendorid. That table can be your added to all the queries and you could map multiple vendors to a single user or even all vendors to a single user for a super admin.

Using ActiveRecord to search through an object's associations and return instances where all of the associations do/do not contain a certain value

I'm attempting to query an object's associations, and only return objects where all of their associations are of a certain value. For example, if a User has a memberships association, and memberships has an active(boolean) field, I want to return a collection of all users that only have memberships with active: false.
The query I'm working with right now is:
User.includes(:memberships).where(memberships: {active: false})
However, this gives me all users that have inactive memberships, but also all users that have both active: false and active: true memberships. I tried doing an extra .where.not on this, but of course, that returned the same group.
I've considered mapping over the collection of users and creating a new array, kicking out the users with active memberships, but I need to keep the final value as an AR Collection as I continue to query it further in the controller.
I would prefer to stick to using ActiveRecord for this, but if it's not doable and I need to use SQL instead, I'm also open to that.
Any help would be greatly appreciated. Thank you!
Couple things here - you want a LEFT OUTTER joins, so make sure your SQL query is being constructed properly. Check with
User.includes(:memberships).where(memberships: {active: false}).explain
or
User.includes(:memberships).where(memberships: {active: false}).to_sql
Second, try:
User.joins(:memberships).where("memberships.active = ?", false)
or perhaps give .merge a try, which I like to use:
User.joins(:memberships).merge(Membership.inactive)
assuming you have a scope/class method .inactive on the Membership model
def self.inactive
where(active: false)
end
.includes should really only be used if you need the relationship loaded into memory.
EDIT:
Easiest way to exclude any user that has a single (of many) memberships would be to split this up into 2 queries.
active_user_ids = Membership.active.pluck(:user_id).uniq
User.where("id NOT IN (?)", active_user_ids.join(","))
To exclude Users with both a valid and invalid membership try--
User.includes(:memberships).where(memberships: {active: false}).where.not(memberships: {active: true})
Also--you probably want to use #joins instead of #includes. If you don't need access to the Memberships except for the query, there is no need to load that into memory (which #include does).
This article has a nice explanation--
http://tomdallimore.com/blog/includes-vs-joins-in-rails-when-and-where/

How to find user group and use of caching in django?

I am new to django/python and working my way through my webapp. I need assistance in solving one of my problems.
In my app, I am planning to assign each user (from auth_user) to one of the group ( from auth_group). Each group can have multiple users. I have entry in auth_group, auth_user and auth_user_groups. Here is my question:
At time of login I want to check that logging user belongs to which group?
I want to keep that group info in session/cache so all pages I can show information about that group only.
If you have any sample code will be great.
Giving support to the very well #trinchet's answer with an example of context_processor code.
Puts inside your webapp a new file called context_processors.py and writes this lines on it:
def user_groups(request):
"""
Add `groups` var to the context with all the
groups the logged in user has, so you can access
in your templates to this var as: {{ groups }}
"""
groups = None
if request.user.is_authenticated():
groups = user.groups
return {'groups': groups}
Finally on your settings.py add 'webbapp.context_processors.user_groups'to TEMPLATE_CONTEXT_PROCESSOR:
TEMPLATE_CONTEXT_PROCESSORS = (
'webbapp.context_processors.user_groups',
)
1) Be user an instance of auth.models.User, you can get all groups the user belong to, through user.groups. If you want to ask at time of login then you should do this in your login view.
2) You can use session or cache approaches to deal with, this is irrelevant, but once you have the group you need to render the pages having this value, i mean, you need to provide the group to the template rendering, to do this I suggest to you using a custom context processor.