I am facing problems while passing custom Attributes to the SP.
Details:
I am using developersOKTA admin profile for IDP.
My SP is a python application which user Django/jinja/Django-CMS
My app attribute statement value is this.
Attempt1:
userName|${user.userName}|urn:oasis:names:tc:SAML:2.0:attrname-format:basic, firstName|${user.firstName}|urn:oasis:names:tc:SAML:2.0:attrname-format:basic, lastName|${user.lastName}|urn:oasis:names:tc:SAML:2.0:attrname-format:basic, email|${user.email}|urn:oasis:names:tc:SAML:2.0:attrname-format:basic, is_publisher|${template_saml_2_0.is_publisher}|urn:oasis:names:tc:SAML:2.0:attrname-format:basic, userRole|${template_saml_2_0.userRole}|urn:oasis:names:tc:SAML:2.0:attrname-format:basic,
Where, is_publisher(type boolean) and userRole(type string) are custom attributes defined and given value on both places - in user profile and in app user profile. And template_saml_2_0 is the app user object and user is the user object.
Next, I have mapped these variables together:
Mapping of okta->app
user.is_publisher is mapped to is_publisher, and
Mapping of app->okta
appuser.is_publisher is mapped to is_publisher.
Done similar for other attributes.
On click the app chiklet, with this attributes statement generates "500 internal server error". This error triggers before okta gives call to the SP. I have found nothing is logged in my SP's logs. And I do not know how to track OKTA IDP's logs.
Attempt2:.
Here I am taking values from the user object for the custom attributes, and rest keeping all same as in attempt 1.
is_publisher|${user.is_publisher}|urn:oasis:names:tc:SAML:2.0:attrname-format:basic, userRole|${user.userRole}|urn:oasis:names:tc:SAML:2.0:attrname-format:basic,
Now this change gives me the value of userRole(string type) and not for is_publisher(boolean type) in the assertion xml passed to the SP by OKTA. I guess this returns values if the custom attribute is only of string type and not for any others types. Is it the case?
Can you please tell me where I am going wrong? I need to set roles of users according the application which I have failed to do in Attempt1. and In Attempt2 I am only getting String type CustomAttribute's value.
Related
First of all, the documentation and examples are so bad, please explain for simple people, like me. Rant over.
I am trying to access my organizations ldap server. Ive tried python-ldap, but i ran into issues, where it decodes and encodes responses super weird. I am testing ldap3 lib atm. But i cannot use the same stuff using ldap3.
def ldap3_connection_initalizer(username, password):
server = ldap3.Server('ldap.blaah.blaaah')
connection = ldap3.Connection(server, user=f'uid={username},ou=people,ou=users,dc=blaah,dc=blaah', password=f'{password}')
with ldap3.Connection(server, user=f'uid={username},ou=people,ou=users,dc=blaah,dc=blaaah', password=f'{password}', auto_bind = True) as c:
print(c)
base_dn='ou=people,ou=users,dc=blaaah,dc=blaaah'
status, result, response, _ = c.search(search_base=base_dn, search_filter='(objectClass=group)', search_scope='SUBTREE', attributes = ['member'])
print(status)
print(result)
print(response)
Running this I get : ldap3.core.exceptions.LDAPObjectClassError: invalid class in objectClass attribute: group
and before that raise LDAPObjectClassError('invalid class in objectClass attribute: ' + str(value))
Could anyone explain why is this not working, but examples in the internet use similar response and it works?
EDIT: Update, tried to change group to person and got this error TypeError: cannot unpack non-iterable bool object
The 1st error says that group is not a valid objectClass (actually it exists but is specific to some Active Directory groups - AD only), so you need to fix the filter. The most generic objectClass for structuring a group entry (ie. having member attribute) is groupOfNames (cf. LDAP Group).
Then you changed the filter with (objectClass=person) which is valid (but for user entries), so you run into the 2nd error which is related to how is unpacked the returned value(s) from c.search(). By default ldap3' search() function returns only the status (other values are returned only when the "strategy" is defined to be thread-safe, which is not obvious at all).
When running a search the response is always added to the connection object via the response keyword, so in order to get the actual ldap entries whatever the thread mode, we can just iterate the connection response.
To sum it up, you can do :
status = c.search(search_base=base_dn, search_filter='(objectClass=groupOfNames)', search_scope='SUBTREE', attributes = ['member'])
print(status)
for entry in c.response:
print(entry['dn'])
print(entry['attributes'])
According to the Django channel docs,
You get access to a user’s normal Django session using the http_session
decorator - that gives you a message.http_session attribute that behaves
just like request.session. You can go one further and use
http_session_user which will provide a message.user attribute as well as
the session attribute.
Is there anyway I can set a session variable like so?
I did try it, and I get an error saying NoneType is not iterable.
if 'username' not in message.http_session:
message.http_session['username'] = 'temp'
In other words, message.http_session returns a NoneType. I've tried using the decorators #http_session and #channel_session_user_from_http, but they didn't help either.
You just set the variable.
foo = 'bar'
And it persists throughout the session
I'm using Odoo 10. After a new user sign up (through localhost:8069/web/signup) i want him to be automatically allocated inside a group i created on my very own custom module (the user will need authentication from an admin later on so he can be converted to a regular portal user; after signup he will receive restricted access).
I have tried many things. My latest effort looks like this:
class RestrictAccessOnSignup(auth_signup_controller.AuthSignupHome):
def do_signup(self, *args):
super(RestrictAccessOnSignup, self).do_signup(*args)
request.env['res.groups'].sudo().write({'groups_id': 'group_unuser'})
Note that I have import odoo.addons.auth_signup.controllers.main as auth_signup_controller so that I can override the auth_signup controller.
I have located that method as the responsible for doing the signup. So I call it in my new method and then try to change the newly created user's group_id.
What i miss is a fundamental understanding of how to overwrite a field's value from another model inside a controller method context. I'm using the 'request' object although i'm not sure of it. I have seen people using 'self.pool['res.users'] (e.g.) for such purposes but i don't understand how to apply it inside my problem's context.
I believe, also, that there is a way to change the default group for a user after it is created (i would like to know), but i also want to understand how to solve the general problem (accessing and overwriting a field's value from another module).
Another weird thing is that the field groups_id does exist in 'res.users' model, but it does not appear as a column in my pgAdmin interface when i click to see the 'res.users' table... Any idea why?
Thanks a lot!
i don't know if after calling :
super(RestrictAccessOnSignup,self).do_signup(*args)
you will have access to user record in request object but if so just add
the group to user like this, if not you have to find where the user record or id is saved after calling do_signup because you need to update that record to ad this group.
# create env variable i hate typing even i'm typing here ^^
env = request.env
env.user.sudo().write({'groups_id': [
# in odoo relation field accept a list of commands
# command 4 means add the id in the second position must be an integer
# ref return an object so we return the id
( 4, env.ref('your_module_name.group_unuser').id),
]
})
and if changes are not committed in database you may need to commit them
request.env.cr.commit()
Note: self.env.ref you must pass the full xmlID.
This is what worked for me:
def do_signup(self, *args):
super(RestrictAccessOnSignup, self).do_signup(*args)
group_id = request.env['ir.model.data'].get_object('academy2', 'group_unuser')
group_id.sudo().write({'users': [(4, request.env.uid)]})
In the get_object i pass as arguments the 'module' and the 'xmlID' of the group i want to fetch.
It is still not clear to me why 'ir.model.data' is the environment used, but this works as a charm. Please note that here we are adding a user to the group, and not a group to the user, and to me that actually makes more sense.
Any further elucidation or parallel solutions are welcome, the methods aren't as clear to me as they should be.
thanks.
I have add code in my db.py to add extra field before the auth.define_tables(username=False, signature=True):
auth.settings.extra_fields['auth_user'] = (
[Field('user_type',label="reg_type",default="Stu", requires=IS_IN_SET(['Stu, 'Com'],multiple=False))])
and I want to do some authentication in my action like the following:
#auth.requires(auth.user.user_type=="Stu",requires_login=True)
define someaction:
code
However I get a error ticket when I run my application.
'NoneType' object has no attribute 'user_type'
And I have read the manual book
#auth.requires also takes an optional argument requires_login which defaults to True. If set to False, it does not require login before
evaluating the condition as true/false. The condition can be a boolean
value or a function evaluating to boolean.
Note that access to all functions apart from the first one is
restricted based on permissions that the visitor may or may not have.
If the visitor is not logged in, then the permission cannot be
checked; the visitor is redirected to the login page and then back to
the page that requires permissions.
So I can't understand what results in the error. Thank you.
When the user is not logged in, auth.user is None. So, you must account for that in your condition:
#auth.requires(auth.user and auth.user.user_type == "Stu")
Note, requires_login=True is the default, so you don't have to specify that (and in this case, it would be unnecessary either way, as auth.user not being None implies the user is logged in).
I started using the new API of Odoo v8.0 but I cannot find useful information about store trigger in computed fields like this (for v7.0 and v6.1): Store Parameter in Odoo v6
In Odoo v8.0, I tried to use the same syntax of v7.0 but I couldn't get it to work because the JSON response cannot be returned back to the web client:
<function _store_trigger> is not JSON serializable.
I read then that store parameter had been converted to Boolean only field (no dict for triggers): Odoo store function: JSON not serializable
So how can I set trigger to store values in database for computed (and related) fields? I want to make filters and groups mainly for them so search function won't be useful.
In V8, you can use any fields as computed fields. In V8 store is a parameter which is a boolean and by default it is false.
If you set explicitly "store=True", the dependent field you mentioned in #api.depends('name'), will acts as a triggering field.
You can specify, the other object field as a triggering field which will be must in accounting module like #api.depends('other_object.field_name')
upper = fields.Char(compute='_compute_upper', store=True)
#api.depends('name')
def _compute_upper(self):
for rec in self:
self.upper = self.name.upper() if self.name else False
If it "false", then the value is not stored in database and will be computed everytime.
upper = fields.Char(compute='_compute_upper')