示例#1
0
def _admin_password_warn(uid):
    """ Admin still has `admin` password, flash a message via chatter.

    Uses a private mail.channel from the system (/ flectrabot) to the user, as
    using a more generic mail.thread could send an email which is undesirable

    Uses mail.channel directly because using mail.thread might send an email instead.
    """
    if request.params['password'] != 'admin':
        return
    if ipaddress.ip_address(request.httprequest.remote_addr).is_private:
        return
    env = request.env(user=SUPERUSER_ID, su=True)
    admin = env.ref('base.partner_admin')
    if uid not in admin.user_ids.ids:
        return
    has_demo = bool(env['ir.module.module'].search_count([('demo', '=', True)]))
    if has_demo:
        return

    user = request.env(user=uid)['res.users']
    MailChannel = env(context=user.context_get())['mail.channel']
    MailChannel.browse(MailChannel.channel_get([admin.id])['id'])\
        .message_post(
            body=_("Your password is the default (admin)! If this system is exposed to untrusted users it is important to change it immediately for security reasons. I will keep nagging you about it!"),
            message_type='comment',
            subtype_xmlid='mail.mt_comment'
        )
示例#2
0
文件: main.py 项目: yemanadep/Flectra
    def oauth2callback(self, **kw):
        """ This route/function is called by Google when user Accept/Refuse the consent of Google """
        state = json.loads(kw['state'])
        dbname = state.get('d')
        service = state.get('s')
        url_return = state.get('f')

        with registry(dbname).cursor() as cr:
            if kw.get('code'):
                request.env(cr, request.session.uid)['google.%s' % service].set_all_tokens(kw['code'])
                return redirect(url_return)
            elif kw.get('error'):
                return redirect("%s%s%s" % (url_return, "?error=", kw['error']))
            else:
                return redirect("%s%s" % (url_return, "?error=Unknown_error"))
示例#3
0
 def avatar(self, res_model, res_id, partner_id):
     headers = [('Content-Type', 'image/png')]
     status = 200
     content = 'R0lGODlhAQABAIABAP///wAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw=='  # default image is one white pixel
     if res_model in request.env:
         try:
             # if the current user has access to the document, get the partner avatar as sudo()
             request.env[res_model].browse(res_id).check_access_rule('read')
             if partner_id in request.env[res_model].browse(res_id).sudo(
             ).exists().message_ids.mapped('author_id').ids:
                 status, headers, _content = binary_content(
                     model='res.partner',
                     id=partner_id,
                     field='image_medium',
                     default_mimetype='image/png',
                     env=request.env(user=SUPERUSER_ID))
                 # binary content return an empty string and not a placeholder if obj[field] is False
                 if _content != '':
                     content = _content
                 if status == 304:
                     return werkzeug.wrappers.Response(status=304)
         except AccessError:
             pass
     image_base64 = base64.b64decode(content)
     headers.append(('Content-Length', len(image_base64)))
     response = request.make_response(image_base64, headers)
     response.status = str(status)
     return response
示例#4
0
def get_model_for_read(model, ENV=False):
    """Fetch a model object from the environment optimized for read.
    Postgres serialization levels are changed to allow parallel read queries.
    To increase the overall efficiency, as it is unlikely this API will be used
    as a mass transactional interface. Rather we assume sequential and structured
    integration workflows.
    :param str model: The model to retrieve from the environment.
    :param object env: Environment
    :returns: the framework model if exist, otherwise raises.
    :rtype: flectra.models.Model
    :raise: werkzeug.exceptions.HTTPException if the model not found in env.
    """
    if ENV:
        return ENV[model]
    cr, uid = request.cr, request.session.uid
    test_mode = request.registry.test_cr
    if not test_mode:
        # Permit parallel query execution on read
        # Contrary to ISOLATION_LEVEL_SERIALIZABLE as per Flectra Standard
        cr._cnx.set_isolation_level(ISOLATION_LEVEL_READ_COMMITTED)
    try:
        return request.env(cr, uid)[model]
    except KeyError:
        err = list(CODE__obj_not_found)
        err[2] = 'The "%s" model is not available on this instance.' % model
        raise werkzeug.exceptions.HTTPException(response=error_response(*err))
示例#5
0
文件: main.py 项目: yemanadep/Flectra
    def jobs(self, country=None, department=None, office_id=None, **kwargs):
        env = request.env(context=dict(request.env.context, show_address=True, no_tag_br=True))

        Country = env['res.country']
        Jobs = env['hr.job']

        # List jobs available to current UID
        job_ids = Jobs.search([], order="website_published desc,no_of_recruitment desc").ids
        if not request.env['res.users'].has_group('website.group_website_publisher'):
            job_ids = Jobs.search([('website_ids', 'in', request.website.id)], order="website_published desc, no_of_recruitment desc").ids
        # Browse jobs as superuser, because address is restricted
        jobs = Jobs.sudo().browse(job_ids)

        # Default search by user country
        if not (country or department or office_id or kwargs.get('all_countries')):
            country_code = request.session['geoip'].get('country_code')
            if country_code:
                countries_ = Country.search([('code', '=', country_code)])
                country = countries_[0] if countries_ else None
                if not any(j for j in jobs if j.address_id and j.address_id.country_id == country):
                    country = False

        # Filter job / office for country
        if country and not kwargs.get('all_countries'):
            jobs = [j for j in jobs if j.address_id is None or j.address_id.country_id and j.address_id.country_id.id == country.id]
            offices = set(j.address_id for j in jobs if j.address_id is None or j.address_id.country_id and j.address_id.country_id.id == country.id)
        else:
            offices = set(j.address_id for j in jobs if j.address_id)

        # Deduce departments and countries offices of those jobs
        departments = set(j.department_id for j in jobs if j.department_id)
        countries = set(o.country_id for o in offices if o.country_id)

        if department:
            jobs = [j for j in jobs if j.department_id and j.department_id.id == department.id]
        if office_id and office_id in [x.id for x in offices]:
            jobs = [j for j in jobs if j.address_id and j.address_id.id == office_id]
        else:
            office_id = False

        # Render page
        return request.render("website_hr_recruitment.index", {
            'jobs': jobs,
            'countries': countries,
            'departments': departments,
            'offices': offices,
            'country_id': country,
            'department_id': department,
            'office_id': office_id,
        })
示例#6
0
 def _generate_auth_code(self, scope, name):
     auth_dict = {
         'scope': scope,
         'name': name,
         'timestamp': int(datetime.datetime.utcnow().timestamp(
         )),  # <- elapsed time should be < 3 mins when verifying
         'uid': request.uid,
     }
     auth_message = json.dumps(auth_dict, sort_keys=True).encode()
     signature = flectra.tools.misc.hmac(request.env(su=True),
                                         'mail_client_extension',
                                         auth_message).encode()
     auth_code = "%s.%s" % (base64.b64encode(auth_message).decode(),
                            base64.b64encode(signature).decode())
     _logger.info('Auth code created - user %s, scope %s', request.env.user,
                  scope)
     return auth_code
示例#7
0
    def _get_auth_code_data(self, auth_code):
        data, auth_code_signature = auth_code.split('.')
        data = base64.b64decode(data)
        auth_code_signature = base64.b64decode(auth_code_signature)
        signature = flectra.tools.misc.hmac(request.env(su=True),
                                            'mail_client_extension',
                                            data).encode()
        if not hmac.compare_digest(auth_code_signature, signature):
            return None

        auth_message = json.loads(data)
        # Check the expiration
        if datetime.datetime.utcnow() - datetime.datetime.fromtimestamp(
                auth_message['timestamp']) > datetime.timedelta(minutes=3):
            return None

        return auth_message
示例#8
0
文件: pinguin.py 项目: mausvt/flectra
def wrap__resource__unlink_one(modelname, id, success_code):
    """Function to delete one record.

    :param str modelname: The name of the model.
    :param int id: The record id of which we want to delete.
    :param int success_code: The success code.

    :returns: successful response if the delete operation is performed
              otherwise error response
    :rtype: werkzeug.wrappers.Response
    """
    cr, uid = request.cr, request.session.uid
    record = request.env(cr, uid)[modelname].browse([id])
    if not record.exists():
        return error_response(*CODE__obj_not_found)
    record.unlink()
    return successful_response(success_code)
示例#9
0
    def user_avatar(self, user_id=0, **post):
        status, headers, content = binary_content(
            model='res.users',
            id=user_id,
            field='image_medium',
            default_mimetype='image/png',
            env=request.env(user=SUPERUSER_ID))

        if not content:
            img_path = modules.get_module_resource('web', 'static/src/img',
                                                   'placeholder.png')
            with open(img_path, 'rb') as f:
                image = f.read()
            content = base64.b64encode(image)
        if status == 304:
            return werkzeug.wrappers.Response(status=304)
        image_base64 = base64.b64decode(content)
        headers.append(('Content-Length', len(image_base64)))
        response = request.make_response(image_base64, headers)
        response.status = str(status)
        return response
示例#10
0
文件: pinguin.py 项目: mausvt/flectra
def wrap__resource__update_one(modelname, id, success_code, data):
    """Function to update one record.

    :param str modelname: The name of the model.
    :param int id: The record id of which we want to update.
    :param int success_code: The success code.
    :param dict data: The data for update.

    :returns: successful response if the update operation is performed
              otherwise error response
    :rtype: werkzeug.wrappers.Response
    """
    cr, uid = request.cr, request.session.uid
    record = request.env(cr, uid)[modelname].browse(id)
    if not record.exists():
        return error_response(*CODE__obj_not_found)
    try:
        record.write(data)
    except Exception as e:
        return error_response(400, type(e).__name__, str(e))
    return successful_response(success_code)
示例#11
0
文件: pinguin.py 项目: mausvt/flectra
def get_create_context(namespace, model, canned_context):
    """Get the requested preconfigured context of the model specification.

    The canned context is used to preconfigure default values or context flags.
    That are used in a repetitive way in namespace for specific model.

    As this should, for performance reasons, not repeatedly result in calls to the persistence
    layer, this method is cached in memory.

    :param str namespace: The namespace to also validate against.
    :param str model: The model, for which we retrieve the configuration.
    :param str canned_context: The preconfigured context, which we request.

    :returns: A dictionary containing the requested context.
    :rtype: dict
    :raise: werkzeug.exceptions.HTTPException TODO: add description in which case
    """
    cr, uid = request.cr, request.session.uid

    # Singleton by construction (_sql_constraints)
    openapi_access = request.env(cr, uid)["openapi.access"].search([
        ("model_id", "=", model), ("namespace_id.name", "=", namespace)
    ])

    assert (len(openapi_access) == 1
            ), "'openapi_access' is not a singleton, bad construction."
    # Singleton by construction (_sql_constraints)
    context = openapi_access.create_context_ids.filtered(
        lambda r: r["name"] == canned_context)
    assert len(context) == 1, "'context' is not a singleton, bad construction."

    if not context:
        raise werkzeug.exceptions.HTTPException(response=error_response(
            *CODE__canned_ctx_not_found))

    return context
示例#12
0
 def bundle(self):
     env = request.env(user=SUPERUSER_ID)
     bundle = env.ref('test_assetsbundle.bundle1')
     views = env['ir.ui.view'].search([('inherit_id', '=', bundle.id)])
     return views.with_context(check_view_ids=views.ids)._render_template(
         'test_assetsbundle.template1')
示例#13
0
文件: pinguin.py 项目: mausvt/flectra
def get_model_openapi_access(namespace, model):
    """Get the model configuration and validate the requested namespace against the session.

    The namespace is a lightweight ACL + default implementation to integrate
    with various integration consumer, such as webstore, provisioning platform, etc.

    We validate the namespace at this latter stage, because it forms part of the http route.
    The token has been related to a namespace already previously

    This is a double purpose method.

    As this should, for performance reasons, not repeatedly result in calls to the persistence
    layer, this method is cached in memory.

    :param str namespace: The namespace to also validate against.
    :param str model: The model, for which we retrieve the configuration.

    :returns: The error response object if namespace validation failed.
        A dictionary containing the model API configuration for this namespace.
            The layout of the dict is as follows:
            ```python
            {'context':                 (Dict)      flectra context (default values through context),
            'out_fields_read_multi':    (Tuple)     field spec,
            'out_fields_read_one':      (Tuple)     field spec,
            'out_fields_create_one':    (Tuple)     field spec,
            'method' : {
                'public' : {
                     'mode':            (String)    one of 'all', 'none', 'custom',
                     'whitelist':       (List)      of method strings,
                 },
                'private' : {
                     'mode':            (String)    one of 'none', 'custom',
                     'whitelist':       (List)      of method strings,
                 },
                'main' : {
                     'mode':            (String)    one of 'none', 'custom',
                     'whitelist':       (List)      of method strings,
                 },
            }
            ```
    :rtype: dict
    :raise: werkzeug.exceptions.HTTPException if the namespace has no accesses.
    """
    # TODO: this method has code duplicates with openapi specification code (e.g. get_OAS_definitions_part)
    cr, uid = request.cr, request.session.uid
    # Singleton by construction (_sql_constraints)
    openapi_access = (request.env(cr, uid)["openapi.access"].sudo().search([
        ("model_id", "=", model), ("namespace_id.name", "=", namespace)
    ]))
    if not openapi_access.exists():
        raise werkzeug.exceptions.HTTPException(response=error_response(
            *CODE__canned_ctx_not_found))

    res = {
        "context":
        {},  # Take ot here FIXME: make sure it is for create_context
        "out_fields_read_multi": (),
        "out_fields_read_one": (),
        "out_fields_create_one": (),  # FIXME: for what?
        "method": {
            "public": {
                "mode": "",
                "whitelist": []
            },
            "private": {
                "mode": "",
                "whitelist": []
            },
            "main": {
                "mode": "",
                "whitelist": []
            },
        },
    }
    # Infer public method mode
    if openapi_access.api_public_methods and openapi_access.public_methods:
        res["method"]["public"]["mode"] = "custom"
        res["method"]["public"][
            "whitelist"] = openapi_access.public_methods.split()
    elif openapi_access.api_public_methods:
        res["method"]["public"]["mode"] = "all"
    else:
        res["method"]["public"]["mode"] = "none"

    # Infer private method mode
    if openapi_access.private_methods:
        res["method"]["private"]["mode"] = "custom"
        res["method"]["private"][
            "whitelist"] = openapi_access.private_methods.split()
    else:
        res["method"]["private"]["mode"] = "none"

    for c in openapi_access.create_context_ids.mapped("context"):
        res["context"].update(json.loads(c))

    res["out_fields_read_multi"] = openapi_access.read_many_id.export_fields.mapped(
        "name") or ("id", )
    res["out_fields_read_one"] = openapi_access.read_one_id.export_fields.mapped(
        "name") or ("id", )

    if openapi_access.public_methods:
        res["method"]["public"][
            "whitelist"] = openapi_access.public_methods.split()
    if openapi_access.private_methods:
        res["method"]["private"][
            "whitelist"] = openapi_access.private_methods.split()

    main_methods = ["api_create", "api_read", "api_update", "api_delete"]
    for method in main_methods:
        if openapi_access[method]:
            res["method"]["main"]["whitelist"].append(method)

    if len(res["method"]["main"]["whitelist"]) == len(main_methods):
        res["method"]["main"]["mode"] = "all"
    elif not res["method"]["main"]["whitelist"]:
        res["method"]["main"]["mode"] = "none"
    else:
        res["method"]["main"]["mode"] = "custom"

    return res