def cas_authenticate(self, req, dbname, cur_url, cas_host, auto_create, ticket): """ Checks if the user attempts to authenticate is authorized to do it and, if it is, authenticate him. """ # cas_server = cas_host + ':' + cas_port cas_server = cas_host service_url = urllib.quote(cur_url, safe='') # The login function, from pycas, check if the ticket given by # CAS is a real ticket. The login of the user # connected by CAS is returned. status, idUser, cookie = login(cas_server, service_url, ticket) result = False if idUser and status == 0: cr = pooler.get_db(dbname).cursor() registry = RegistryManager.get(dbname) users = registry.get('res.users') ids = users.search(cr, SUPERUSER_ID, [('login', '=', idUser)]) assert len(ids) < 2 # We check if the user authenticated have an OpenERP account or if # the auto_create field is True if ids or auto_create == 'True': if ids: user_id = ids[0] # If the user have no account, we create one else: user_id = users.create(cr, SUPERUSER_ID, { 'name': idUser.capitalize(), 'login': idUser }) # A random key is generated in order to verify if the # login request come from here or if the user # try to authenticate by any other way cas_key = randomString(16, '0123456789abcdefghijklmnopqrstuvwxyz') users.write(cr, SUPERUSER_ID, [user_id], {'cas_key': cas_key}) cr.commit() login_and_redirect(dbname, idUser, cas_key) result = {'status': status, 'session_id': req.session_id} else: result = { 'status': status, 'fail': True, 'session_id': req.session_id } cr.close() if not result: result = {'status': status} return result
def index(self, req, s_action=None, db=None, **kw): """ If LemonLDAP module is activated, auto login the user and keep him connected automatically Warning: Security is not managed on OpenERP anymore, OpenERP has to be behind a proxy and not accessible from outside ! """ # handle 500 error manually, to retrieve error as a string, not a json object try: lemon_params = self.get_lemon_params(req) log.debug('Lemon > db: %s, user_id: %s, username: %s, secret: %s', lemon_params['db'], lemon_params['user_id'], lemon_params['username'], lemon_params['secret']) db = self.get_current_db(req, lemon_params['db'] or db) config = self.get_sso_config(req, db) # only process if the module is activated if config['enabled']: log.debug('forwarded > header: %s, config: %s', lemon_params['forwarded'], config['forwarded']) # some basic security check to identify LemonLDAP and the proxy if lemon_params['forwarded'] not in config['forwarded']: raise Exception('OpenERP is not behind a proxy or the forwarded domain is wrong') if config['lemon_secret'] != lemon_params['secret']: raise Exception('LemonLDAP secret is not the same than secret configured on OpenERP !') log.debug("db_monodb(req): %s, db: %s", db_monodb(req), db) session = self.get_current_session(req) if db_monodb(req) != db: log.info('force re authenticate user %s', lemon_params['username']) # force the db retrieved from request header req.params.update({'db': db }) url = '/?db=%s' % db # login with a fake password, the security check has been disabled on res.users model return login_and_redirect(req, db, lemon_params['username'], 'nopassword', redirect_url=url) if not session or str(session._uid) != lemon_params['user_id']: log.info('auto-authenticate user %s', lemon_params['username']) # login with a fake password, the security check has been disabled on res.users model return login_and_redirect(req, db, lemon_params['username'], 'nopassword') log.info('user %s already authenticated', lemon_params['username']) except Exception as e: body = "<h1>OpenERP - LemonLDAP Authorization Error</h1><p>%s</p>" % str(e) return Response(body, status=500, headers=[('Content-Type', 'text/html'), ('Content-Length', len(body))]) return super(SSO, self).index(req, s_action, db, **kw)
def cas_authenticate(self, req, dbname, cur_url, cas_host, auto_create, ticket): """ Checks if the user attempts to authenticate is authorized to do it and, if it is, authenticate him. """ # cas_server = cas_host + ':' + cas_port cas_server = cas_host service_url = urllib.quote(cur_url, safe='') # The login function, from pycas, check if the ticket given by CAS is a real ticket. The login of the user # connected by CAS is returned. status, idUser, cookie = login(cas_server, service_url, ticket) result = False if idUser and status == 0: cr = pooler.get_db(dbname).cursor() registry = RegistryManager.get(dbname) users = registry.get('res.users') ids = users.search(cr, SUPERUSER_ID, [('login', '=', idUser)]) assert len(ids) < 2 # We check if the user authenticated have an OpenERP account or if # the auto_create field is True if ids or auto_create == 'True': if ids: user_id = ids[0] # If the user have no account, we create one else: user_id = users.create( cr, SUPERUSER_ID, {'name': idUser.capitalize(), 'login': idUser}) # A random key is generated in order to verify if the login request come from here or if the user # try to authenticate by any other way cas_key = randomString( 16, '0123456789abcdefghijklmnopqrstuvwxyz') users.write(cr, SUPERUSER_ID, [user_id], {'cas_key': cas_key}) cr.commit() login_and_redirect(dbname, idUser, cas_key) result = {'status': status, 'session_id': req.session_id} else: result = { 'status': status, 'fail': True, 'session_id': req.session_id} cr.close() if not result: result = {'status': status} return result
def _cas_login(self, redirect=None, **kw): cas_url, service_url, dbname = self._get_config_url() ticket = self._get_cas_ticket(request) if not ticket: cas_login = cas_url + '/login?service=' + service_url # response return werkzeug.utils.redirect(cas_login) # return http.redirect_with_hash(cas_redirect) else: # userName = self.validateCASTicket(ticket, cas_url, service_url) status, userName, cookie = login(cas_url, service_url, ticket) ids = [] if userName and status == 0: # def getUidFromUserName(userName): cr = pooler.get_db(dbname).cursor() registry = RegistryManager.get(dbname) users = registry.get('res.users') ids = users.search( cr, SUPERUSER_ID, [('login', '=', userName)]) assert len(ids) == 1 cas_key = randomString( 16, '0123456789abcdefghijklmnopqrstuvwxyz') users.write(cr, SUPERUSER_ID, ids, {'cas_key': cas_key}) cr.commit() # set cookie for relogin res = login_and_redirect(dbname, userName, cas_key) return res return
def new_database(self, **post): if not request.session.uid: return login_and_redirect() plan_id = int(post.get('plan_id')) res = self.create_new_database(plan_id) return request.redirect(res.get('url'))
def signin(self, **kw): state = simplejson.loads(kw['state']) dbname = state['d'] provider = state['p'] context = state.get('c', {}) registry = RegistryManager.get(dbname) with registry.cursor() as cr: try: u = registry.get('res.users') credentials = u.auth_oauth(cr, SUPERUSER_ID, provider, kw, context=context) cr.commit() action = state.get('a') menu = state.get('m') url = '/web' if action: url = '/web#action=%s' % action elif menu: url = '/web#menu_id=%s' % menu return login_and_redirect(*credentials, redirect_url=url) except AttributeError: # auth_signup is not installed _logger.error("auth_signup not installed on database %s: oauth sign up cancelled." % (dbname,)) url = "/web/login?oauth_error=1" except openerp.exceptions.AccessDenied: # oauth credentials not valid, user could be on a temporary session _logger.info('OAuth2: access denied, redirect to main page in case a valid session exists, without setting cookies') url = "/web/login?oauth_error=3" redirect = werkzeug.utils.redirect(url, 303) redirect.autocorrect_location_header = False return redirect except Exception, e: # signup error _logger.exception("OAuth2: %s" % str(e)) url = "/web/login?oauth_error=2"
def signin(self, req, **kw): state = simplejson.loads(kw['state']) dbname = state['d'] provider = state['p'] context = state.get('c', {}) registry = RegistryManager.get(dbname) with registry.cursor() as cr: try: u = registry.get('res.users') credentials = u.auth_oauth(cr, SUPERUSER_ID, provider, kw, context=context) cr.commit() action = state.get('a') menu = state.get('m') url = '/' if action: url = '/#action=%s' % action elif menu: url = '/#menu_id=%s' % menu return login_and_redirect(req, *credentials, redirect_url=url) except AttributeError: # auth_signup is not installed _logger.error("auth_signup not installed on database %s: oauth sign up cancelled." % (dbname,)) url = "/#action=login&oauth_error=1" except openerp.exceptions.AccessDenied: # oauth credentials not valid, user could be on a temporary session _logger.info('OAuth2: access denied, redirect to main page in case a valid session exists, without setting cookies') url = "/#action=login&oauth_error=3" redirect = werkzeug.utils.redirect(url, 303) redirect.autocorrect_location_header = False return redirect except Exception, e: # signup error _logger.exception("OAuth2: %s" % str(e)) url = "/#action=login&oauth_error=2"
def weixin_name_email(self, **kw): qcontext = request.params.copy() if kw.get('email') and kw.get('name'): import re def validateEmail(email): if email: if len(email) > 7: if re.match("^.+\\@(\\[?)[a-zA-Z0-9\\-\\.]+\\.([a-zA-Z]{2,3}|[0-9]{1,3})(\\]?)$", email) != None: return 1 return 0 if not validateEmail(kw['email']) or kw['name'] == '': qcontext['error'] = _('name or email error') if 'error' not in qcontext and kw.get('state') and kw.get('access_token') and kw.get('name') and kw.get('email'): dbname = kw['state'] registry = RegistryManager.get(dbname) u = registry.get('res.users') with registry.cursor() as cr: try: credentials = u.weixin_auth_signup(cr, SUPERUSER_ID, kw) url='/web' cr.commit() return login_and_redirect(*credentials, redirect_url=url) except Exception, e: _logger.exception("OAuth2: %s" % str(e)) url = "/weixin/login?oauth_error=2" return set_cookie_and_redirect(url)
def signin(self, req, **kw): state = simplejson.loads(kw['state']) dbname = state['d'] provider = state['p'] context = state.get('c', {}) registry = RegistryManager.get(dbname) with registry.cursor() as cr: try: u = registry.get('res.users') credentials = u.auth_oauth(cr, SUPERUSER_ID, provider, kw, context=context) cr.commit() action = state.get('a', None) url = '/#action=' + action if action else '/' return login_and_redirect(req, *credentials, redirect_url=url) except AttributeError: # auth_signup is not installed _logger.error( "auth_signup not installed on database %s: oauth sign up cancelled." % (dbname, )) url = "/#action=login&oauth_error=1" except Exception, e: # signup error _logger.exception("OAuth2: %s" % str(e)) url = "/#action=login&oauth_error=2"
def signin(self, req, **kw): """JS client obtained a saml token and passed it back to us... we need to validate it """ saml_response = kw.get('SAMLResponse', None) if not kw.get('RelayState', None): # here we are in front of a client that went through # some routes that "lost" its relaystate... this can happen # if the client visited his IDP and successfully logged in # then the IDP gave him a portal with his available applications # but the provided link does not include the necessary relaystate url = "/?type=signup" redirect = werkzeug.utils.redirect(url, 303) redirect.autocorrect_location_header = True return redirect state = simplejson.loads(kw['RelayState']) dbname = state['d'] provider = state['p'] context = state.get('c', {}) registry = RegistryManager.get(dbname) with registry.cursor() as cr: try: u = registry.get('res.users') credentials = u.auth_saml(cr, SUPERUSER_ID, provider, saml_response, context=context) cr.commit() action = state.get('a') menu = state.get('m') url = '/' if action: url = '/#action=%s' % action elif menu: url = '/#menu_id=%s' % menu return login_and_redirect(req, *credentials, redirect_url=url) except AttributeError, e: print e # auth_signup is not installed _logger.error("auth_signup not installed on database " "%s: saml sign up cancelled." % (dbname, )) url = "/#action=login&saml_error=1" except openerp.exceptions.AccessDenied: # saml credentials not valid, # user could be on a temporary session _logger.info('SAML2: access denied, redirect to main page ' 'in case a valid session exists, ' 'without setting cookies') url = "/#action=login&saml_error=3" redirect = werkzeug.utils.redirect(url, 303) redirect.autocorrect_location_header = False return redirect
def signin(self, req, **kw): """JS client obtained a saml token and passed it back to us... we need to validate it """ saml_response = kw.get('SAMLResponse', None) if not kw.get('RelayState', None): # here we are in front of a client that went through # some routes that "lost" its relaystate... this can happen # if the client visited his IDP and successfully logged in # then the IDP gave him a portal with his available applications # but the provided link does not include the necessary relaystate url = "/?type=signup" redirect = werkzeug.utils.redirect(url, 303) redirect.autocorrect_location_header = True return redirect state = simplejson.loads(kw['RelayState']) dbname = state['d'] provider = state['p'] context = state.get('c', {}) registry = RegistryManager.get(dbname) with registry.cursor() as cr: try: u = registry.get('res.users') credentials = u.auth_saml( cr, SUPERUSER_ID, provider, saml_response, context=context ) cr.commit() action = state.get('a') menu = state.get('m') url = '/' if action: url = '/#action=%s' % action elif menu: url = '/#menu_id=%s' % menu return login_and_redirect(req, *credentials, redirect_url=url) except AttributeError, e: print e # auth_signup is not installed _logger.error("auth_signup not installed on database " "%s: saml sign up cancelled." % (dbname,)) url = "/#action=login&saml_error=1" except openerp.exceptions.AccessDenied: # saml credentials not valid, # user could be on a temporary session _logger.info('SAML2: access denied, redirect to main page ' 'in case a valid session exists, ' 'without setting cookies') url = "/#action=login&saml_error=3" redirect = werkzeug.utils.redirect(url, 303) redirect.autocorrect_location_header = False return redirect
def login(self, request, code=None, error=None, **kward): state = self.retrieve_state(kward.get("state", False)) dbname = self.get_dbname(request, state) result = self._validate_token(request, dbname, code, error) if not result or 'error' in result: return set_cookie_and_redirect( request, '/#action=login&loginerror=1&' + urllib.urlencode(result)) return login_and_redirect(request, dbname, result.get('login', False), result.get('token', False))
def login(self, request, code=None, error=None, **kward): state = self.retrieve_state(kward.get("state", False)) dbname = self.get_dbname(request, state) result = self._validate_token(request, dbname, code, error) if not result or 'error' in result: return set_cookie_and_redirect(request, '/#action=login&loginerror=1&' + urllib.urlencode(result)) return login_and_redirect(request, dbname, result.get('login', False), result.get('token', False))
def signin(self, **kw): state = json.loads(kw['state']) dbname = state['d'] if not http.db_filter([dbname]): return BadRequest() provider = state['p'] context = state.get('c', {}) registry = RegistryManager.get(dbname) with registry.cursor() as cr: try: u = registry.get('res.users') credentials = u.auth_oauth(cr, SUPERUSER_ID, provider, kw, context=context) cr.commit() action = state.get('a') menu = state.get('m') redirect = werkzeug.url_unquote_plus( state['r']) if state.get('r') else False url = '/web' if redirect: url = redirect elif action: url = '/web#action=%s' % action elif menu: url = '/web#menu_id=%s' % menu resp = login_and_redirect(*credentials, redirect_url=url) #Since /web is hardcoded, verify user has right to land on it if urlparse.urlparse( resp.location).path == '/web' and not request.registry[ 'res.users'].has_group(request.cr, request.uid, 'base.group_user'): resp.location = '/' return resp except AttributeError: # auth_signup is not installed _logger.error( "auth_signup not installed on database %s: oauth sign up cancelled." % (dbname, )) url = "/web/login?oauth_error=1" except openerp.exceptions.AccessDenied: # oauth credentials not valid, user could be on a temporary session _logger.info( 'OAuth2: access denied, redirect to main page in case a valid session exists, without setting cookies' ) url = "/web/login?oauth_error=3" redirect = werkzeug.utils.redirect(url, 303) redirect.autocorrect_location_header = False return redirect except Exception, e: # signup error _logger.exception("OAuth2: %s" % str(e)) url = "/web/login?oauth_error=2"
def signin(self, **kw): _logger.debug(kw) _logger.debug('dbname: %s', http.request.db) registry = RegistryManager.get(http.request.db) with registry.cursor() as cr: try: u = registry.get('res.users') credentials = u.auth_weixin(cr, SUPERUSER_ID, kw) cr.commit() redirect = kw.get('redirect', '') return login_and_redirect(*credentials, redirect_url=redirect) except Exception, e: _logger.exception("OAuth2: %s" % str(e)) url = "/web/login?oauth_error=2"
def signup(self, req, dbname, token, name, login, password, state=""): """ sign up a user (new or existing), and log it in """ url = "/" registry = RegistryManager.get(dbname) with registry.cursor() as cr: try: res_users = registry.get("res.users") values = {"name": name, "login": login, "password": password} credentials = res_users.signup(cr, openerp.SUPERUSER_ID, values, token) cr.commit() return login_and_redirect(req, *credentials, redirect_url="/#%s" % state) except Exception as e: # signup error _logger.exception("error when signup") url = "/#action=login&error_message=%s" % werkzeug.urls.url_quote(e.message) return werkzeug.utils.redirect(url)
def signin(self, **kw): # TODO faltaria implementar el redirect y no hardcodear el my/home ensure_db() partner_uuid = kw['partner_uuid'] dbname = kw.pop('db', None) if not dbname: dbname = db_monodb() if not dbname: return werkzeug.exceptions.BadRequest() registry = RegistryManager.get(dbname) with registry.cursor() as cr: url = '/my/home' try: u = registry.get('res.users') credentials = u.partner_uuid_login( cr, SUPERUSER_ID, partner_uuid) cr.commit() return login_and_redirect(*credentials, redirect_url=url) except: pass return set_cookie_and_redirect(url)
def signin(self, req, **kw): state = simplejson.loads(kw['state']) dbname = state['d'] provider = state['p'] context = state.get('c', {}) registry = RegistryManager.get(dbname) with registry.cursor() as cr: try: u = registry.get('res.users') credentials = u.auth_oauth(cr, SUPERUSER_ID, provider, kw, context=context) cr.commit() action = state.get('a', None) url = '/#action=' + action if action else '/' return login_and_redirect(req, *credentials, redirect_url=url) except AttributeError: # auth_signup is not installed _logger.error("auth_signup not installed on database %s: oauth sign up cancelled." % (dbname,)) url = "/#action=login&oauth_error=1" except Exception, e: # signup error _logger.exception("OAuth2: %s" % str(e)) url = "/#action=login&oauth_error=2"
def product_comment(self, product_template_id, **post): if not request.session.uid: return login_and_redirect() cr, uid, context = request.cr, request.uid, request.context if post.get('comment'): mid = request.registry['product.template'].message_post( cr, uid, product_template_id, body=post.get('comment'), type='comment', subtype='mt_comment', context=dict(context, mail_create_nosubscribe=True)) if post.get('rating', 0): data = { 'rating': int(post.get('rating')), } request.registry['mail.message'].write(cr, uid, [mid], data, context) res = werkzeug.utils.redirect(request.httprequest.referrer + "#comments") return res
def weixin_signin(self, **kw): #https://baoshunkeji.com/weixin/signin?code=0015b3203e9151b79c93fa46ea0d9aeo&state=test dbname = kw['state'] registry = RegistryManager.get(dbname) with registry.cursor() as cr: try: u = registry.get('res.users') user_ids, token_data = u.weixin_auth_oauth(cr, SUPERUSER_ID, kw) if user_ids: assert len(user_ids) == 1 credentials = u.weixin_auth_signin(cr, SUPERUSER_ID, token_data, user_ids, kw) else: json_token_data = {'openid': token_data['openid'], 'refresh_token': token_data['refresh_token'], 'access_token': token_data['access_token']} url = "/weixin/name_email?" + werkzeug.url_encode(json_token_data) + '&state=' + kw['state'] return set_cookie_and_redirect(url) cr.commit() url='/web' return login_and_redirect(*credentials, redirect_url=url) except Exception, e: # signup error _logger.exception("OAuth2: %s" % str(e)) url = "/weixin/login?oauth_error=2"
def meine_daten(self, **kwargs): # Token related fstoken = kwargs.get('fstoken') partner = None messages_token = list() warnings_token = list() errors_token = list() # Form related apf_fields = list() field_errors = dict() messages = list() warnings = list() errors = list() countries = None states = None bpkfields = {"firstname": "bpk_forced_firstname", "lastname": "bpk_forced_lastname", "birthdate_web": "bpk_forced_birthdate", "zip": "bpk_forced_zip"} # Honey Pot Field Test if kwargs.get('fs_hpf'): if request.uid != request.website.user_id.id: errors.append(_('Data found in field with label: "Do not enter data here please!"')) return http.request.render('auth_partner_form.meinedaten', {'kwargs': dict(), 'fs_ptoken': '', 'partner': '', 'apf_fields': list(), 'field_errors': dict(), 'errors_token': errors_token, 'warnings_token': warnings_token, 'messages_token': messages_token, 'errors': errors, 'warnings': warnings, 'messages': messages, 'countries': None, 'states': None, }) # CHECK TOKEN AND LOGIN token_record = None if fstoken: # Check token token_record, token_user, token_error = fstoken_check(fstoken) # Valid token (= Valid res.partner and valid res.user) if token_record: # Login if token res.user is different from request user if token_user and token_user.id != request.uid: redirect_url = '/meine-daten?fstoken=' + urllib2.quote(fstoken) _logger.info('Login by /meine-daten FS-Token input (%s): user.login %s (%s) and redirect to %s' % (token_record.id, token_user.login, token_user.id, redirect_url)) return login_and_redirect(request.db, token_user.login, token_record.name, redirect_url=redirect_url) # Wrong or invalid token if token_error: field_errors['fstoken'] = fstoken # Check if a custom message was set for the token error message # or use the standard error message from fstoken_check try: if request.website.apf_token_error_message and len(request.website.apf_token_error_message) > 2: errors_token += [request.website.apf_token_error_message] else: errors_token += token_error except: errors_token += token_error # UPDATE PARTNER # HINT: Only if logged in (so different from the default user request.website.user_id) if request.website.user_id.id != request.uid: _logger.debug('/meine-daten request.website.user_id %s, request.uid %s' % (request.website.user_id, request.uid)) user = request.env['res.users'].sudo().browse([request.uid]) partner = user.partner_id # Add sorted countries and states # HINT: Sort by language in context for name field is not implemented in o8 fixed in o9 and up! # https://github.com/odoo/odoo/issues/5283 start_locale = locale.getlocale() try: # Try to set locale by website language for correct unicode sorting by name of countries locale.setlocale(locale.LC_ALL, request.env.context.get("lang", "de_AT")+".UTF-8") except: logging.warning("Could not set locale for auth_partner_form for country and state " "sorting by website lang!") pass # Sorted Countries (add Austria and Germany to the top) countries_obj = request.env['res.country'].sudo() countries = countries_obj.search([]) countries_sorted = sorted(countries, cmp=locale.strcoll, key=lambda c: c.name) countries_sorted_ids = [c.id for c in countries_sorted] germany = countries_obj.search([('code', '=', 'DE')]) if germany: countries_sorted_ids = [germany.id] + countries_sorted_ids austria = countries_obj.search([('code', '=', 'AT')]) if austria: countries_sorted_ids = [austria.id] + countries_sorted_ids countries = countries_obj.browse(countries_sorted_ids) # Sorted States states_obj = request.env['res.country.state'] states = states_obj.sudo().search([]) states_sorted = sorted(states, cmp=locale.strcoll, key=lambda s: s.name) states = states_obj.sudo().browse([s.id for s in states_sorted]) try: # Revert to original locale locale.setlocale(locale.LC_ALL, start_locale) except: logging.warning("Could not revert to initial locale for auth_partner_form after country and state " "sorting by website lang!") pass # Find fields_to_update fields_to_update = dict() apf_fields = request.env['website.apf_partner_fields'] apf_fields = apf_fields.sudo().search([]) for field in apf_fields: if field.res_partner_field_id: fname = field.res_partner_field_id.name ftype = field.res_partner_field_id.ttype # Search for field values given by the form inputs if fname in kwargs: # NoData Fields can only be updated if there is something in the kwargs ELSE do NOT clear it! if not field.nodata or field.nodata and kwargs[fname].strip() or ftype == 'boolean': # Fix for Boolean fields: convert str() to boolean() # HINT boolean field will ignore field.nodata setting if ftype == 'boolean': fields_to_update[fname] = True if kwargs[fname] else False # Fix for Date fields: convert '' to None elif ftype == 'date': fields_to_update[fname] = kwargs[fname].strip() if kwargs[fname].strip() else None if fields_to_update[fname]: # Convert Date from %d.%m.%Y to %Y-%m-%d # HINT: In the meine-daten form only a date-format %d.%m.%Y is allowed! # Language settings of odoo are not taken into account! Therefore we must # Convert the date string from the website to a datetime here with the correct # format. fields_to_update[fname] = fields.datetime.strptime(fields_to_update[fname], '%d.%m.%Y') else: value = kwargs[fname].strip() if isinstance(kwargs[fname], basestring) else \ kwargs[fname] fields_to_update[fname] = value # Write to the res.partner (after field validation) # HINT: Only validate fields and write the partner if we found fields_to_update if fields_to_update: # VALIDATE FIELDS (before we update anything) # HINT: We do this here since fields_to_update indicates that something was entered in the # Your Data section of the form. (= a partner was already found before) for field in apf_fields: if field.res_partner_field_id: fname = field.res_partner_field_id.name ftype = field.res_partner_field_id.ttype # Validate "mandatory" setting if field.mandatory and not kwargs.get(fname): field_errors[fname] = fname # Validate date fields if ftype == 'date' and kwargs[fname].strip(): date_de = kwargs[fname].strip() try: datetime.datetime.strptime(date_de, '%d.%m.%Y') except: field_errors[fname] = fname # Update res.partner (if no errors where found) if not field_errors: # Add fstoken_update and fstoken_update_date # DEPRECATION WARNING! This is only here for the auth_partner_form and was # replaced by field "last_date_of_use" in "res.partner.fstoken" in the # function fstoken_check() if fstoken: fields_to_update['fstoken_update'] = fstoken fields_to_update['fstoken_update_date'] = fields.datetime.now() # Update BPKForced... fields instead of the regular fields if already set for the partner if partner.bpk_forced_firstname or partner.bpk_forced_lastname or partner.bpk_forced_birthdate: # Swap firstname, lastname, birthdate_web and zip with the BPKForced... field names for key in bpkfields: if key in fields_to_update: fields_to_update[bpkfields[key]] = fields_to_update.pop(key) if partner.sudo().write(fields_to_update): success_message = request.website.apf_update_success_message or \ _('Your data was successfully updated!') messages.append(success_message) else: warnings.append(_('Your data could not be updated. Please try again.')) # Add error message for field_errors if field_errors: errors.append(_('Missing or incorrect information! Please check your input.')) # Show a token success message after login but before the first partner data form submission if token_record and fstoken and len(kwargs) <= 2: token_valid_message = request.website.apf_token_success_message or _('Your code is valid!') messages_token.append(token_valid_message) # Add a dict with the partner BPKForced... field values but the regular field keys # HINT: This dict takes precedence in the form over the regular partner fields partner_bpk = {} if partner and (partner.bpk_forced_firstname or partner.bpk_forced_lastname or partner.bpk_forced_birthdate): for key in bpkfields: partner_bpk[key] = partner[bpkfields[key]] return http.request.render('auth_partner_form.meinedaten', {'kwargs': kwargs, 'fstoken': fstoken, 'partner': partner, 'partner_bpk': partner_bpk, 'apf_fields': apf_fields, 'field_errors': field_errors, 'errors_token': errors_token, 'warnings_token': warnings_token, 'messages_token': messages_token, 'errors': errors, 'warnings': warnings, 'messages': messages, 'countries': countries, 'states': states, })
def process(self, req, **kw): session = getattr(req.session, "openid_session", None) if not session: return set_cookie_and_redirect(req, "/") oidconsumer = consumer.Consumer(session, self._store, consumer_class=GoogleAppsAwareConsumer) query = req.httprequest.args info = oidconsumer.complete(query, req.httprequest.base_url) display_identifier = info.getDisplayIdentifier() session["status"] = info.status if info.status == consumer.SUCCESS: dbname = session["dbname"] registry = RegistryManager.get(dbname) with registry.cursor() as cr: Modules = registry.get("ir.module.module") installed = ( Modules.search_count( cr, SUPERUSER_ID, ["&", ("name", "=", "auth_openid"), ("state", "=", "installed")] ) == 1 ) if installed: Users = registry.get("res.users") # openid_url = info.endpoint.canonicalID or display_identifier openid_url = session["openid_url"] attrs = self._get_attributes_from_success_response(info) attrs["openid_url"] = openid_url session["attributes"] = attrs openid_email = attrs.get("email", False) domain = [] if openid_email: domain += ["|", ("openid_email", "=", False)] domain += [("openid_email", "=", openid_email)] domain += [("openid_url", "=", openid_url), ("active", "=", True)] ids = Users.search(cr, SUPERUSER_ID, domain) assert len(ids) < 2 if ids: user_id = ids[0] login = Users.browse(cr, SUPERUSER_ID, user_id).login key = randomString(utils.KEY_LENGTH, "0123456789abcdef") Users.write(cr, SUPERUSER_ID, [user_id], {"openid_key": key}) # TODO fill empty fields with the ones from sreg/ax cr.commit() return login_and_redirect(req, dbname, login, key) session["message"] = "This OpenID identifier is not associated to any active users" elif info.status == consumer.SETUP_NEEDED: session["message"] = info.setup_url elif info.status == consumer.FAILURE and display_identifier: fmt = "Verification of %s failed: %s" session["message"] = fmt % (display_identifier, info.message) else: # FAILURE # Either we don't understand the code or there is no # openid_url included with the error. Give a generic # failure message. The library should supply debug # information in a log. session["message"] = "Verification failed." return set_cookie_and_redirect(req, "/#action=login&loginerror=1")
def doorkeeper_cb(self, **kw): if kw.get('state', False): state = simplejson.loads(kw['state']) master_db = db_monodb() proto, root_url = request.httprequest.url_root.split("://") if not master_db: return BadRequest() if state.get('login', False): login = state['login'] db_prefix = state['login'].split('@')[0] if state.get('demo', False): db_prefix = "%s-%s" % (db_prefix, 'demo') dbname = "%s_%s" % (db_prefix, master_db) redirect = "%s://%s.%s" % (proto, db_prefix, root_url) if not redirect.endswith("/"): redirect += "/" state.update({'d': dbname}) kw['state'] = simplejson.dumps(state) if openerp.service.db.exp_db_exist(dbname): registry = RegistryManager.get(dbname) with registry.cursor() as cr: IMD = registry['ir.model.data'] try: model, provider_id = IMD.get_object_reference( cr, SUPERUSER_ID, 'cenit_saas_server', 'saas_oauth_provider') except ValueError: return set_cookie_and_redirect('/web?db=%s' % dbname) assert model == 'auth.oauth.provider' params = { 'access_token': kw['access_token'], 'state': simplejson.dumps({ 'd': dbname, 'p': provider_id, }), } return werkzeug.utils.redirect( '{host}{controller}?{params}'.format( host=redirect, controller='auth_oauth/signin', params=werkzeug.url_encode(params))) else: _logger.info("\n\nNo existing tenant\n") registry = RegistryManager.get(master_db) if not state.get('name', False): state.update({'name': db_prefix.capitalize()}) if not state.get('organization', False): state.update({'organization': db_prefix.capitalize()}) if state.get('demo', False): plan = self.get_demo_plan() else: if state.get('plan', False): plan = self.get_plan(state.get('plan')) else: plan = self.get_default_plan() state.update({ 'db_template': plan['template'], 'plan': plan['id'] }) kw['state'] = simplejson.dumps(state) try: provider = self.__create_app_for_db(state['d']) partner_id, credentials = self.__signup_user(provider, kw) request.cr.commit() except Exception, e: _logger.exception(e) url = "/web/login?oauth_error=2" return set_cookie_and_redirect(url) url = "/saas_server/new_database" kw['admin_data'] = simplejson.dumps({ 'user_id': partner_id, 'client_id': provider.client_id, 'email': login, 'name': state['name'] }) full_url = '%s?%s' % (url, werkzeug.url_encode(kw)) _logger.info("\n\nFullURL: %s\n", full_url) return login_and_redirect(*credentials, redirect_url=full_url)
def web_login_fs_ptoken(self, **kwargs): fs_ptoken = kwargs.get('fs_ptoken', '') redirect_url_after_token_login = kwargs.get( 'redirect_url_after_token_login', '') # Form Template form_template = 'website_login_fs_ptoken.token_login_form' # Messages tlf_messages = list() tlf_warning_messages = list() tlf_error_messages = list() # Field Errors field_errors = dict() # Honey Pot Field Test if kwargs.get('tlf_hpf'): if request.uid != request.website.user_id.id: tlf_error_messages.append( _('Data found in field with label: "Do not enter data here please!"' )) return http.request.render( form_template, { 'kwargs': dict(), 'fs_ptoken': '', 'redirect_url_after_token_login': urllib2.quote(redirect_url_after_token_login), }) # Check Token if fs_ptoken: # Check the token token_record, token_user, token_error = fstoken_check(fs_ptoken) # VALID TOKEN (= Valid res.partner and valid res.user) if token_record: # Redirect URL redirect_url = redirect_url_after_token_login if not redirect_url: tlf_messages += _("Success!") redirect_url = '/web/login/fs_ptoken?fs_ptoken=%s' % urllib2.quote( fs_ptoken) # Login and Redirect _logger.info( 'Login by /web/login/fs_ptoken with token %s, user.login %s (%s)! Redirect to %s' % (token_record.id, token_user.login, token_user.id, redirect_url)) return login_and_redirect(request.db, token_user.login, token_record.name, redirect_url=redirect_url) # INVALID TOKEN if token_error: field_errors['fs_ptoken'] = 'invalid_fs_ptoken' tlf_error_messages += token_error return http.request.render( form_template, { 'kwargs': kwargs, 'fs_ptoken': fs_ptoken, 'redirect_url_after_token_login': urllib2.quote(redirect_url_after_token_login), # Messages 'tlf_messages': tlf_messages, 'tlf_warning_messages': tlf_warning_messages, 'tlf_error_messages': tlf_error_messages, # Field Errors 'field_errors': field_errors, })
def process(self, **kw): session = getattr(request.session, 'openid_session', None) if not session: return set_cookie_and_redirect('/') oidconsumer = consumer.Consumer(session, self._store, consumer_class=GoogleAppsAwareConsumer) query = request.httprequest.args info = oidconsumer.complete(query, request.httprequest.base_url) display_identifier = info.getDisplayIdentifier() session['status'] = info.status if info.status == consumer.SUCCESS: dbname = session['dbname'] registry = RegistryManager.get(dbname) with registry.cursor() as cr: Modules = registry.get('ir.module.module') installed = Modules.search_count(cr, SUPERUSER_ID, ['&', ('name', '=', 'auth_openid'), ('state', '=', 'installed')]) == 1 if installed: Users = registry.get('res.users') #openid_url = info.endpoint.canonicalID or display_identifier openid_url = session['openid_url'] attrs = self._get_attributes_from_success_response(info) attrs['openid_url'] = openid_url session['attributes'] = attrs openid_email = attrs.get('email', False) domain = [] if openid_email: domain += ['|', ('openid_email', '=', False)] domain += [('openid_email', '=', openid_email)] domain += [('openid_url', '=', openid_url), ('active', '=', True)] ids = Users.search(cr, SUPERUSER_ID, domain) assert len(ids) < 2 if ids: user_id = ids[0] login = Users.browse(cr, SUPERUSER_ID, user_id).login key = randomString(utils.KEY_LENGTH, '0123456789abcdef') Users.write(cr, SUPERUSER_ID, [user_id], {'openid_key': key}) # TODO fill empty fields with the ones from sreg/ax cr.commit() return login_and_redirect(dbname, login, key) session['message'] = 'This OpenID identifier is not associated to any active users' elif info.status == consumer.SETUP_NEEDED: session['message'] = info.setup_url elif info.status == consumer.FAILURE and display_identifier: fmt = "Verification of %s failed: %s" session['message'] = fmt % (display_identifier, info.message) else: # FAILURE # Either we don't understand the code or there is no # openid_url included with the error. Give a generic # failure message. The library should supply debug # information in a log. session['message'] = 'Verification failed.' return set_cookie_and_redirect('/#action=login&loginerror=1')
def doorkeeper_cb (self, **kw): if kw.get('state', False): state = simplejson.loads(kw['state']) master_db = db_monodb () proto, root_url = request.httprequest.url_root.split ("://") if not master_db: return BadRequest() if state.get ('login', False): login = state['login'] db_prefix = state['login'].split ('@')[0] if state.get ('demo', False): db_prefix = "%s-%s" % (db_prefix, 'demo') dbname = "%s_%s" %(db_prefix, master_db) redirect = "%s://%s.%s" %(proto, db_prefix, root_url) if not redirect.endswith ("/"): redirect += "/" state.update ({'d': dbname}) kw['state'] = simplejson.dumps (state) if openerp.service.db.exp_db_exist (dbname): registry = RegistryManager.get (dbname) with registry.cursor() as cr: IMD = registry['ir.model.data'] try: model, provider_id = IMD.get_object_reference( cr, SUPERUSER_ID, 'cenit_saas_server', 'saas_oauth_provider' ) except ValueError: return set_cookie_and_redirect('/web?db=%s' % dbname) assert model == 'auth.oauth.provider' params = { 'access_token': kw['access_token'], 'state': simplejson.dumps({ 'd': dbname, 'p': provider_id, }), } return werkzeug.utils.redirect('{host}{controller}?{params}'.format( host = redirect, controller = 'auth_oauth/signin', params = werkzeug.url_encode(params) ) ) else: _logger.info ("\n\nNo existing tenant\n") registry = RegistryManager.get (master_db) if not state.get ('name', False): state.update ({ 'name': db_prefix.capitalize () }) if not state.get ('organization', False): state.update ({ 'organization': db_prefix.capitalize () }) if state.get ('demo', False): plan = self.get_demo_plan () else: if state.get ('plan', False): plan = self.get_plan (state.get ('plan')) else: plan = self.get_default_plan () state.update ({ 'db_template': plan['template'], 'plan': plan['id'] }) kw['state'] = simplejson.dumps (state) try: provider = self.__create_app_for_db (state['d']) partner_id, credentials = self.__signup_user (provider, kw) request.cr.commit () except Exception, e: _logger.exception (e) url = "/web/login?oauth_error=2" return set_cookie_and_redirect (url) url = "/saas_server/new_database" kw['admin_data'] = simplejson.dumps ({ 'user_id': partner_id, 'client_id': provider.client_id, 'email': login, 'name': state['name'] }) full_url = '%s?%s' % (url, werkzeug.url_encode(kw)) _logger.info ("\n\nFullURL: %s\n", full_url) return login_and_redirect (*credentials, redirect_url=full_url)
def _dispatch(self): # Process the request first response = super(ir_http, self)._dispatch() # In case there is no request yet (unbound object error catch) # https://github.com/OCA/e-commerce/issues/152 # https://github.com/OCA/e-commerce/pull/190 if not request: return response # Check for fs_ptoken before returning the requests response if hasattr(request, 'website') and request.website: fs_ptoken = request.httprequest.args.get('fs_ptoken') if fs_ptoken: # Compute the new url but without the fs_ptoken appended for security reasons request_url = request.httprequest.url url_parsed = urlparse(request_url) query_dict = parse_qs(url_parsed.query, keep_blank_values=True) query_dict.pop('fs_ptoken', None) url_parsed_clean = url_parsed._replace( query=urlencode(query_dict, True)) redirect_url = urlunparse(url_parsed_clean) # Check token and login if valid # HINT: If the token is wrong or the login fails there is no message or hint at all # which is the intended behaviour _logger.info('Check fs_ptoken %s in _dispatch()' % fs_ptoken) token_record, user, errors = fstoken_check(fs_ptoken) # Log every successful token request if token_record: _logger.info( 'FS-Token (%s) found for res.partner %s (%s)' % (token_record.id, token_record.partner_id.name, token_record.partner_id.id)) if hasattr(request, 'session') and hasattr( request.session, 'context') and request.session.context: request.session.context[ 'fs_ptoken'] = token_record.name else: _logger.info('Invalid or expired fs_ptoken given: %s!' % fs_ptoken) # DISABLED BY MIKE because too aggressive - would kick logged in user just because they reuse an # an expired token link in one of their valid e-mails # request.session.logout(keep_db=True) if hasattr(request, 'session') and hasattr( request.session, 'context') and request.session.context: request.session.context.pop('fs_ptoken', False) request.session.context.pop('fs_origin', False) # Login and redirect if needed if token_record and user and user.id != request.uid: _logger.info( 'Login by FS-Token (%s) for res.user with login %s (%s) and redirect to %s' % (token_record.id, user.login, user.id, request.httprequest.url)) # ATTENTION: !!! It is VERY important to logout before any login to destroy the old session !!! _logger.info( 'Destroy session before token login! (request.session.logout(keep_db=True))' ) request.session.logout(keep_db=True) # abort_and_redirect(request.httprequest.url) res = login_and_redirect(request.db, user.login, token_record.name, redirect_url=redirect_url) # Update the 'new context after login' with fs_ptoken and fs_origin if hasattr(request, 'session') and hasattr( request.session, 'context') and request.session.context: request.session.context[ 'fs_ptoken'] = token_record.name request.session.context[ 'fs_origin'] = token_record.fs_origin or False return res # If the token was not valid we still redirect to the initially called url but without the fs_ptoken return request.redirect(redirect_url) return response
def verify(self, **kw): # if select database db= kw.pop('db', None) # login, password,.. login= kw.pop('login', None) password = kw.pop('password', None) redirect = kw.pop('redirect', None) pincode= kw.pop('pincode', None) numpin= kw.pop('numpin', None) if not db: db=db_monodb() if not numpin: numpin=0 registry = RegistryManager.get(db) ipuser=request.httprequest.remote_addr with registry.cursor() as cr: res_users = registry.get('res.users') #check password/login for user => return l'id or false iduser=res_users.authenticate(db, login, password,user_agent_env=None) cr.commit() if iduser<>False : user=res_users.browse(cr,SUPERUSER_ID,iduser,context=None) if int(numpin)>0 : #verify pin, if error return login/password auth_log = registry.get('pincode.log') auth_log=user.pincode_log_id[0] if pincode<>auth_log.pincode: vals=dict() vals['states']="wrong" vals['ipuser']=ipuser authen_log = registry.get('pincode.log') idlog=authen_log.write(cr,SUPERUSER_ID,user.pincode_log_id[0].id,vals) return http.request.render('web.login', {'error':'Wrong pincode '}) else: # if ok pincode # is outdated ?? interval=str(datetime.now()-datetime.strptime(auth_log.date+".000000","%Y-%m-%d %H:%M:%S.%f")).split(".") interval_sec=sum(int(x) * 60 ** i for i,x in enumerate(reversed(interval[0].split(":")))) time_validity_sec=(user.pincode_id[int(numpin)-1].type_id.time_validity)*60*60 # in seconde user.pincode_id[int(numpin)-1].type_id.time_validity if interval_sec>time_validity_sec: vals=dict() vals['states']='outdated' vals['ipuser']=ipuser authen_log = registry.get('pincode.log') idlog=authen_log.write(cr,SUPERUSER_ID,user.pincode_log_id[0].id,vals) return http.request.render('web.login', {'error':'pincode outdated'}) else: vals=dict() vals['states']="used" vals['ipuser']=ipuser authen_log = registry.get('pincode.log') idlog=authen_log.write(cr,SUPERUSER_ID,user.pincode_log_id[0].id,vals) if user.pincode_id and int(numpin)==0: self.create_pincode(cr,registry,user.pincode_id[0],user.id) return http.request.render('pincode.pincode', { 'login': login, 'password':password, 'db':db, 'redirect':redirect, 'numpin':1, }) # Login ok , pin ok => menu ! url="/web" credentials=(cr.dbname, login, password) return login_and_redirect(*credentials, redirect_url=url) #if error return login return http.request.render('web.login', {'error':'Wrong login/password '})