Beispiel #1
0
 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)
Beispiel #2
0
    def oea(self, **kw):
        """login user via Odoo Account provider"""
        dbname = kw.pop('db', None)
        if not dbname:
            dbname = db_monodb()
        if not dbname:
            return BadRequest()

        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, 'auth_oauth', 'provider_openerp')
            except ValueError:
                return set_cookie_and_redirect('/web?db=%s' % dbname)
            assert model == 'auth.oauth.provider'

        state = {
            'd': dbname,
            'p': provider_id,
            'c': {
                'no_user_creation': True
            },
        }

        kw['state'] = simplejson.dumps(state)
        return self.signin(**kw)
Beispiel #3
0
    def oea(self, req, **kw):
        """login user via OpenERP Account provider"""
        dbname = kw.pop('db', None)
        if not dbname:
            dbname = db_monodb(req)
        if not dbname:
            return BadRequest()

        registry = RegistryManager.get(dbname)
        with registry.cursor() as cr:
            IMD = registry['ir.model.data']
            model, provider_id = IMD.get_object_reference(
                cr, SUPERUSER_ID, 'auth_oauth', 'provider_openerp')
            assert model == 'auth.oauth.provider'

        state = {
            'd': dbname,
            'p': provider_id,
            'c': {
                'no_user_creation': True
            },
        }

        kw['state'] = simplejson.dumps(state)
        return self.signin(req, **kw)
Beispiel #4
0
    def oea(self, **kw):
        """login user via OpenERP Account provider"""
        dbname = kw.pop('db', None)
        if not dbname:
            dbname = db_monodb()
        if not dbname:
            return BadRequest()

        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, 'auth_oauth', 'provider_openerp')
            except ValueError:
                return set_cookie_and_redirect('/web?db=%s' % dbname)
            assert model == 'auth.oauth.provider'

        state = {
            'd': dbname,
            'p': provider_id,
            'c': {'no_user_creation': True},
        }

        kw['state'] = simplejson.dumps(state)
        return self.signin(**kw)
Beispiel #5
0
 def get_current_db(self, req, db):
     """
     Retrieve the database to use, from Lemon header, URI parameter or the default one
     """
     db = db if db and len(db) > 0 else db_monodb(req)
     if not db:
         raise Exception('Can not found a database to use...')
     return db
Beispiel #6
0
    def oea(self, **kw):
        """login user via OpenERP Account provider"""
        dbname = kw.pop("db", None)
        if not dbname:
            dbname = db_monodb()
        if not dbname:
            return BadRequest()

        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, "auth_oauth", "provider_openerp")
            except ValueError:
                return set_cookie_and_redirect("/web?db=%s" % dbname)
            assert model == "auth.oauth.provider"

        state = {"d": dbname, "p": provider_id, "c": {"no_user_creation": True}}

        kw["state"] = simplejson.dumps(state)
        return self.signin(**kw)
 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)
Beispiel #8
0
 def stats(self, **post):
     # TODO auth
     server_db = db_monodb()
     res = request.registry['saas_server.client'].update_all(
         request.cr, SUPERUSER_ID, server_db)
     return simplejson.dumps(res)
Beispiel #9
0
    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)
Beispiel #10
0
    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)
Beispiel #11
0
    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 '})
 def stats(self, **post):
     # TODO auth
     server_db = db_monodb()
     res = request.registry['saas_server.client'].update_all(request.cr, SUPERUSER_ID, server_db)
     return simplejson.dumps(res)
Beispiel #13
0
    def xml(self, **kwargs):
        database = kwargs.get('database', None)
        if not database:
            database = db_monodb()
        req = openerp.http.request
        language = kwargs.get('language', None)
        if req.httprequest.method == 'GET':
            # Login
            database = kwargs.get('database', None)
            req.session.db = database
            try:
                self.authenticate(req, database, language)
            except Exception as e:
                logger.warning("Failed login attempt: %s" % e)
                return Response(
                    'Login with Odoo user name and password', 401,
                    headers=[('WWW-Authenticate', 'Basic realm="odoo"')]
                    )

            # As an optional extra security check we can validate a web token attached
            # to the request. It allows use to verify that the request is generated
            # from frePPLe and not from somebody else.

            # Generate data
            try:
                xp = exporter(
                  req,
                  database = database,
                  company = kwargs.get('company', None),
                  mode = int(kwargs.get('mode', 1))
                  )
                # TODO Returning an iterator to stream the response back to the client and
                # to save memory on the server side
                return req.make_response(
                    ''.join([i for i in xp.run()]),
                    headers=[
                        ('Content-Type', 'application/xml;charset=utf8'),
                        ('Cache-Control', 'no-cache, no-store, must-revalidate'),
                        ('Pragma', 'no-cache'),
                        ('Expires', '0')
                    ])
            except Exception as e:
                logger.exception('Error generating frePPLe XML data')
                raise InternalServerError(description='Error generating frePPLe XML data: check the Odoo log file for more details')
        elif req.httprequest.method == 'POST':
            # Authenticate the user
            database = req.httprequest.form.get('database', None)
            req.session.db = database
            try:
                self.authenticate(req, database, language)
            except Exception as e:
                logger.warning("Failed login attempt %s" % e)
                return Response(
                    'Login with Odoo user name and password', 401,
                    headers=[('WWW-Authenticate', 'Basic realm="odoo"')]
                    )

            # Validate the company argument
            company_name = req.httprequest.form.get('company', None)
            company = None
            m = req.session.model('res.company')
            m_search = m.search([('name', '=', company_name)])
            for i in m.browse(m_search):
              company = i
            if not company:
              return Response('Invalid company name argument', 401)

            # Verify that the data was posted from frePPLe and nobody else
            try:
              webtoken = req.httprequest.form.get('webtoken', None)
              decoded = jwt.decode(
                webtoken,
                company.webtoken_key,
                algorithms=['HS256']
                )
              if self.user != decoded.get('user', None):
                return Response('Incorrect or missing webtoken', 401)
            except:
                return Response('Incorrect or missing webtoken', 401)

            # Import the data
            try:
                ip = importer(
                  req,
                  database=database,
                  company=company,
                  mode=req.httprequest.form.get('mode', 1)
                  )
                return req.make_response(
                    ip.run(),
                    [
                        ('Content-Type', 'text/plain'),
                        ('Cache-Control', 'no-cache, no-store, must-revalidate'),
                        ('Pragma', 'no-cache'),
                        ('Expires', '0')
                    ])
            except Exception as e:
                logger.exception('Error processing data posted by frePPLe')
                raise InternalServerError(description='Error processing data posted by frePPLe: check the Odoo log file for more details')
        else:
            raise MethodNotAllowed('Only GET and POST requests are accepted')
    def xml(self, **kwargs):
        req = openerp.http.request
        language = kwargs.get("language", None)
        if req.httprequest.method == "GET":
            # Login
            database = kwargs.get("database", None)
            if not database:
                database = db_monodb()
            req.session.db = database
            try:
                self.authenticate(req, database, language)
            except Exception as e:
                logger.warning("Failed login attempt: %s" % e)
                return Response(
                    "Login with Odoo user name and password",
                    401,
                    headers=[("WWW-Authenticate", 'Basic realm="odoo"')],
                )

            # As an optional extra security check we can validate a web token attached
            # to the request. It allows use to verify that the request is generated
            # from frePPLe and not from somebody else.

            # Generate data
            try:
                xp = exporter(
                    req,
                    database=database,
                    company=kwargs.get("company", None),
                    mode=int(kwargs.get("mode", 1)),
                )
                # TODO Returning an iterator to stream the response back to the client and
                # to save memory on the server side
                return req.make_response(
                    "".join([i for i in xp.run()]),
                    headers=[
                        ("Content-Type", "application/xml;charset=utf8"),
                        ("Cache-Control",
                         "no-cache, no-store, must-revalidate"),
                        ("Pragma", "no-cache"),
                        ("Expires", "0"),
                    ],
                )
            except Exception as e:
                logger.exception("Error generating frePPLe XML data")
                raise InternalServerError(
                    description=
                    "Error generating frePPLe XML data: check the Odoo log file for more details"
                )
        elif req.httprequest.method == "POST":
            # Authenticate the user
            database = req.httprequest.form.get("database", None)
            if not database:
                database = db_monodb()
            req.session.db = database
            try:
                self.authenticate(req, database, language)
            except Exception as e:
                logger.warning("Failed login attempt %s" % e)
                return Response(
                    "Login with Odoo user name and password",
                    401,
                    headers=[("WWW-Authenticate", 'Basic realm="odoo"')],
                )

            # Validate the company argument
            company_name = req.httprequest.form.get("company", None)
            company = None
            m = req.session.model("res.company")
            m_search = m.search([("name", "=", company_name)])
            for i in m.browse(m_search):
                company = i
            if not company:
                return Response("Invalid company name argument", 401)

            # Verify that the data was posted from frePPLe and nobody else
            try:
                webtoken = req.httprequest.form.get("webtoken", None)
                decoded = jwt.decode(webtoken,
                                     company.webtoken_key,
                                     algorithms=["HS256"])
                if self.user != decoded.get("user", None):
                    return Response("Incorrect or missing webtoken", 401)
            except Exception:
                return Response("Incorrect or missing webtoken", 401)

            # Import the data
            try:
                ip = importer(
                    req,
                    database=database,
                    company=company,
                    mode=req.httprequest.form.get("mode", 1),
                )
                return req.make_response(
                    ip.run(),
                    [
                        ("Content-Type", "text/plain"),
                        ("Cache-Control",
                         "no-cache, no-store, must-revalidate"),
                        ("Pragma", "no-cache"),
                        ("Expires", "0"),
                    ],
                )
            except Exception as e:
                logger.exception("Error processing data posted by frePPLe")
                raise InternalServerError(
                    description=
                    "Error processing data posted by frePPLe: check the Odoo log file for more details"
                )
        else:
            raise MethodNotAllowed("Only GET and POST requests are accepted")
Beispiel #15
0
    def xml(self, **kwargs):
        database = kwargs.get('database', None)
        if not database:
            database = db_monodb()
        req = openerp.http.request
        language = kwargs.get('language', None)
        if req.httprequest.method == 'GET':
            # Login
            database = kwargs.get('database', None)
            req.session.db = database
            try:
                self.authenticate(req, database, language)
            except Exception as e:
                logger.warning("Failed login attempt: %s" % e)
                return Response('Login with Odoo user name and password',
                                401,
                                headers=[('WWW-Authenticate',
                                          'Basic realm="odoo"')])

            # As an optional extra security check we can validate a web token attached
            # to the request. It allows use to verify that the request is generated
            # from frePPLe and not from somebody else.

            # Generate data
            try:
                xp = exporter(req,
                              database=database,
                              company=kwargs.get('company', None),
                              mode=int(kwargs.get('mode', 1)))
                # TODO Returning an iterator to stream the response back to the client and
                # to save memory on the server side
                return req.make_response(
                    ''.join([i for i in xp.run()]),
                    headers=[('Content-Type', 'application/xml;charset=utf8'),
                             ('Cache-Control',
                              'no-cache, no-store, must-revalidate'),
                             ('Pragma', 'no-cache'), ('Expires', '0')])
            except Exception as e:
                logger.exception('Error generating frePPLe XML data')
                raise InternalServerError(
                    description=
                    'Error generating frePPLe XML data: check the Odoo log file for more details'
                )
        elif req.httprequest.method == 'POST':
            # Authenticate the user
            database = req.httprequest.form.get('database', None)
            req.session.db = database
            try:
                self.authenticate(req, database, language)
            except Exception as e:
                logger.warning("Failed login attempt %s" % e)
                return Response('Login with Odoo user name and password',
                                401,
                                headers=[('WWW-Authenticate',
                                          'Basic realm="odoo"')])

            # Validate the company argument
            company_name = req.httprequest.form.get('company', None)
            company = None
            m = req.session.model('res.company')
            m_search = m.search([('name', '=', company_name)])
            for i in m.browse(m_search):
                company = i
            if not company:
                return Response('Invalid company name argument', 401)

            # Verify that the data was posted from frePPLe and nobody else
            try:
                webtoken = req.httprequest.form.get('webtoken', None)
                decoded = jwt.decode(webtoken,
                                     company.webtoken_key,
                                     algorithms=['HS256'])
                if self.user != decoded.get('user', None):
                    return Response('Incorrect or missing webtoken', 401)
            except:
                return Response('Incorrect or missing webtoken', 401)

            # Import the data
            try:
                ip = importer(req,
                              database=database,
                              company=company,
                              mode=req.httprequest.form.get('mode', 1))
                return req.make_response(
                    ip.run(),
                    [('Content-Type', 'text/plain'),
                     ('Cache-Control', 'no-cache, no-store, must-revalidate'),
                     ('Pragma', 'no-cache'), ('Expires', '0')])
            except Exception as e:
                logger.exception('Error processing data posted by frePPLe')
                raise InternalServerError(
                    description=
                    'Error processing data posted by frePPLe: check the Odoo log file for more details'
                )
        else:
            raise MethodNotAllowed('Only GET and POST requests are accepted')