profile
viewpoint
If you are wondering where the data of this site comes from, please visit https://api.github.com/users/PCatinean/events. GitMemory does not store any data, but only uses NGINX to cache data for a period of time. The idea behind GitMemory is simply to give users a better reading experience.
Paul Catinean PCatinean Pledra Romania - Bucharest https://www.pledra.com

PCatinean/ogd-import 1

OGD Import

PCatinean/charts 0

Curated applications for Kubernetes

PCatinean/charts-1 0

Helm Charts

PCatinean/connector 0

Odoo generic connector framework (jobs queue, asynchronous tasks, channels)

PCatinean/connector-magento 0

Connect Odoo with Magento

PCatinean/docker-duplicity 0

Docker image for running duplicity in a cron

PCatinean/doodba 0

Base image for making the creation of customized Odoo environments a piece of cake

PCatinean/doodba-scaffolding 0

Officially supported scaffolding template for your Doodba projects

PCatinean/maintainer-quality-tools 0

QA tools for Odoo maintainers

pull request commentOCA/product-configurator

[12.0][MIG] Backport of module product_configurator

Hi, the 12 version is already present in the originating repository: https://github.com/pledra/odoo-product-configurator/tree/12.0

gabrielcardoso21

comment created time in 2 days

push eventpledra/odoo-product-configurator

BizzAppDev

commit sha f6979b413bdc31535538288294506805836b24a9

[FIX]add product variant in value of parameter product_id in _get_combination_info method call from product page view (#187) Co-authored-by: SHS <shs@bizzappdev.com>

view details

push time in 14 days

create barnchpledra/connector-ecommerce

branch : 13.0-mig-connector_ecommerce

created branch time in 15 days

create barnchpledra/pledra

branch : app-theme_diva

created branch time in 25 days

delete branch pledra/pledra

delete branch : 13.0

delete time in a month

create barnchpledra/pledra

branch : 14.0-staging

created branch time in a month

create barnchpledra/pledra

branch : 14.0

created branch time in a month

create barnchpledra/pledra

branch : 13.0

created branch time in a month

create barnchpledra/pledra

branch : main

created branch time in a month

created repositorypledra/pledra

created time in a month

issue commentrancher/k3d

[BUG] open /proc/sys/net/netfilter/nf_conntrack_max: permission denied

@ppicom @iwilltry42 I had the same issue on a single node docker installation and this was the workaround -> https://github.com/rancher/rancher/issues/33300#issuecomment-869273925

farzadmf

comment created time in a month

issue commentOCA/product-configurator

Issue with config session not created/ displaying in sales order line odoo 14 enterprise

Hi, we were not able to reproduce this issue and we have the session attached on both versions (there should be nothing really in enterprise that interfeers with it). Can you reproduce this on a vanilla V14, can you share the reproduction steps?

Woodlawnfurniture

comment created time in 2 months

startedmarcelduran/webpagetest-api

started time in 2 months

PullRequestReviewEvent

pull request commentOCA/connector-ecommerce

[13.0][MIG] connector_ecommerce

Tests are passing can you please review @StefanRijnhart ?

bizzappdev

comment created time in 3 months

PullRequestReviewEvent

pull request commentOCA/connector-ecommerce

[13.0][MIG] connector_ecommerce

@gurneyalex I tried rebuilding the runbot build but it still has a warning which fails the PR and I can't view the logs from the build to find out what is the issue. Could you help out?

bizzappdev

comment created time in 3 months

Pull request review commentOCA/server-auth

[13.0][MIG] auth_saml

+# Copyright (C) 2020 GlodoUK <https://www.glodo.uk>+# Copyright (C) 2010-2016 XCG Consulting <http://odoo.consulting>+# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).++import logging++import passlib++from odoo import SUPERUSER_ID, _, api, fields, models, tools+from odoo.exceptions import AccessDenied, ValidationError++_logger = logging.getLogger(__name__)+++class ResUser(models.Model):+    """+    Add SAML login capabilities to Odoo users.+    """++    _inherit = "res.users"++    saml_ids = fields.One2many("res.users.saml", "user_id")++    @api.constrains("password", "saml_ids")+    def check_no_password_with_saml(self):+        """Ensure no Odoo user posesses both an SAML user ID and an Odoo+        password. Except admin which is not constrained by this rule.+        """+        if not self._allow_saml_and_password():+            # Super admin is the only user we allow to have a local password+            # in the database+            if self.password and self.id is not SUPERUSER_ID and self.saml_ids:+                raise ValidationError(+                    _(+                        "This database disallows users to "+                        "have both passwords and SAML IDs. "+                        "Errors for login %s"+                    )+                    % (self.login)+                )++    def _auth_saml_validate(self, provider_id, token, base_url=None):+        provider = self.env["auth.saml.provider"].sudo().browse(provider_id)+        return provider._validate_auth_response(token, base_url)++    def _auth_saml_signin(self, provider, validation, saml_response):+        """ retrieve and sign into openerp the user corresponding to provider+        and validated access token++        :param provider: saml provider id (int)+            :param validation: result of validation of access token (dict)+            :param saml_response: saml parameters response from the IDP+            :return: user login (str)+            :raise: openerp.exceptions.AccessDenied if signin failed++            This method can be overridden to add alternative signin methods.+        """+        token_osv = self.env["auth_saml.token"]+        saml_uid = validation["user_id"]+        user = (+            self.env["res.users.saml"]+            .search(+                [("saml_uid", "=", saml_uid), ("saml_provider_id", "=", provider)],+                limit=1,+            )+            .user_id+        )+        if len(user) != 1:+            raise AccessDenied()+        # now find if a token for this user/provider already exists+        token_ids = token_osv.search(+            [("saml_provider_id", "=", provider), ("user_id", "=", user.id)]+        )++        if token_ids:+            token_ids.write({"saml_access_token": saml_response})+        else:+            _logger.info("Creating auth_saml.token")+            token_ids = token_osv.create(+                {+                    "saml_access_token": saml_response,+                    "saml_provider_id": provider,+                    "user_id": user.id,+                }+            )++        if validation.get("mapped_attrs", {}):+            user.write(validation.get("mapped_attrs", {}))++        return user.login++    @api.model+    def auth_saml(self, provider, saml_response, base_url=None):+        validation = self._auth_saml_validate(provider, saml_response, base_url)++        # required check+        if not validation.get("user_id"):+            raise AccessDenied()++        # retrieve and sign in user+        login = self._auth_saml_signin(provider, validation, saml_response)++        if not login:+            raise AccessDenied()++        # return user credentials+        return self.env.cr.dbname, login, saml_response++    def _check_credentials(self, password):+        """Override to handle SAML auths.++        The token can be a password if the user has used the normal form...+        but we are more interested in the case when they are tokens+        and the interesting code is inside the "except" clause.+        """+        try:+            # Attempt a regular login (via other auth addons) first.+            return super()._check_credentials(password)++        except (AccessDenied, passlib.exc.PasswordSizeError):+            # since normal auth did not succeed we now try to find if the user+            # has an active token attached to his uid+            token = (+                self.env["auth_saml.token"]+                .sudo()+                .search(+                    [+                        ("user_id", "=", self.env.user.id),+                        ("saml_access_token", "=", password),+                    ]+                )+            )+            if not token:+                raise AccessDenied()++    def _autoremove_password_if_saml(self):+        """Helper to remove password if it is forbidden for SAML users."""+        if self.env.context.get("auth_saml_no_autoremove_password"):+            return+        if self._allow_saml_and_password():+            return+        to_remove_password = self.filtered(+            lambda rec: rec.id != SUPERUSER_ID and rec.saml_ids and rec.password+        )+        if to_remove_password:++            to_remove_password.with_context(+                auth_saml_no_autoremove_password=True+            ).write({"password": self._autoremove_password_if_saml_gen_password()})++    @api.model+    def _autoremove_password_if_saml_gen_password(self):+        """+        If password_security is installed, we cannot have a False-y password.+        This is to avoid a very small bridging/compatbility module.+        """+        new_password = False+        modules = self.env["ir.module.module"].sudo()._installed().keys()+        if "password_security" in modules:+            new_password = passlib.utils.generate_password(size=24, charset="ascii_72")+        return new_password++    def write(self, vals):+        result = super().write(vals)+        self._autoremove_password_if_saml()+        self._ensure_saml_token_exists()+        return result++    @api.model_create_multi+    def create(self, vals_list):+        result = super().create(vals_list)+        result._autoremove_password_if_saml()+        result._ensure_saml_token_exists()+        return result++    @api.model+    def _allow_saml_and_password(self):+        """Can both SAML and local password auth methods can coexist."""+        return tools.str2bool(+            self.env["ir.config_parameter"]+            .sudo()+            .get_param("auth_saml.allow_saml_uid_and_internal_password", "True")+        )++    def _ensure_saml_token_exists(self):+        # workaround for Odoo not seeing the newly created auth_saml.token on+        # the very first login+        model_token = self.env["auth_saml.token"].sudo()+        for record in self.filtered(lambda r: r.saml_ids):

It comes from the fact that the user itself is writing on the res.user object (lang_id change) which triggers the write that triggers this method and tries to read own_user.saml_ids. This winds up in an access error because he does not have permissions to read the saml_ids even though they are attached to his own user

theangryangel

comment created time in 3 months

PullRequestReviewEvent

Pull request review commentOCA/server-auth

[13.0][MIG] auth_saml

+# Copyright (C) 2020 GlodoUK <https://www.glodo.uk>+# Copyright (C) 2010-2016 XCG Consulting <http://odoo.consulting>+# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).++import logging++import passlib++from odoo import SUPERUSER_ID, _, api, fields, models, tools+from odoo.exceptions import AccessDenied, ValidationError++_logger = logging.getLogger(__name__)+++class ResUser(models.Model):+    """+    Add SAML login capabilities to Odoo users.+    """++    _inherit = "res.users"++    saml_ids = fields.One2many("res.users.saml", "user_id")++    @api.constrains("password", "saml_ids")+    def check_no_password_with_saml(self):+        """Ensure no Odoo user posesses both an SAML user ID and an Odoo+        password. Except admin which is not constrained by this rule.+        """+        if not self._allow_saml_and_password():+            # Super admin is the only user we allow to have a local password+            # in the database+            if self.password and self.id is not SUPERUSER_ID and self.saml_ids:+                raise ValidationError(+                    _(+                        "This database disallows users to "+                        "have both passwords and SAML IDs. "+                        "Errors for login %s"+                    )+                    % (self.login)+                )++    def _auth_saml_validate(self, provider_id, token, base_url=None):+        provider = self.env["auth.saml.provider"].sudo().browse(provider_id)+        return provider._validate_auth_response(token, base_url)++    def _auth_saml_signin(self, provider, validation, saml_response):+        """ retrieve and sign into openerp the user corresponding to provider+        and validated access token++        :param provider: saml provider id (int)+            :param validation: result of validation of access token (dict)+            :param saml_response: saml parameters response from the IDP+            :return: user login (str)+            :raise: openerp.exceptions.AccessDenied if signin failed++            This method can be overridden to add alternative signin methods.+        """+        token_osv = self.env["auth_saml.token"]+        saml_uid = validation["user_id"]+        user = (+            self.env["res.users.saml"]+            .search(+                [("saml_uid", "=", saml_uid), ("saml_provider_id", "=", provider)],+                limit=1,+            )+            .user_id+        )+        if len(user) != 1:+            raise AccessDenied()+        # now find if a token for this user/provider already exists+        token_ids = token_osv.search(+            [("saml_provider_id", "=", provider), ("user_id", "=", user.id)]+        )++        if token_ids:+            token_ids.write({"saml_access_token": saml_response})+        else:+            _logger.info("Creating auth_saml.token")+            token_ids = token_osv.create(+                {+                    "saml_access_token": saml_response,+                    "saml_provider_id": provider,+                    "user_id": user.id,+                }+            )++        if validation.get("mapped_attrs", {}):+            user.write(validation.get("mapped_attrs", {}))++        return user.login++    @api.model+    def auth_saml(self, provider, saml_response, base_url=None):+        validation = self._auth_saml_validate(provider, saml_response, base_url)++        # required check+        if not validation.get("user_id"):+            raise AccessDenied()++        # retrieve and sign in user+        login = self._auth_saml_signin(provider, validation, saml_response)++        if not login:+            raise AccessDenied()++        # return user credentials+        return self.env.cr.dbname, login, saml_response++    def _check_credentials(self, password):+        """Override to handle SAML auths.++        The token can be a password if the user has used the normal form...+        but we are more interested in the case when they are tokens+        and the interesting code is inside the "except" clause.+        """+        try:+            # Attempt a regular login (via other auth addons) first.+            return super()._check_credentials(password)++        except (AccessDenied, passlib.exc.PasswordSizeError):+            # since normal auth did not succeed we now try to find if the user+            # has an active token attached to his uid+            token = (+                self.env["auth_saml.token"]+                .sudo()+                .search(+                    [+                        ("user_id", "=", self.env.user.id),+                        ("saml_access_token", "=", password),+                    ]+                )+            )+            if not token:+                raise AccessDenied()++    def _autoremove_password_if_saml(self):+        """Helper to remove password if it is forbidden for SAML users."""+        if self.env.context.get("auth_saml_no_autoremove_password"):+            return+        if self._allow_saml_and_password():+            return+        to_remove_password = self.filtered(+            lambda rec: rec.id != SUPERUSER_ID and rec.saml_ids and rec.password+        )+        if to_remove_password:++            to_remove_password.with_context(+                auth_saml_no_autoremove_password=True+            ).write({"password": self._autoremove_password_if_saml_gen_password()})++    @api.model+    def _autoremove_password_if_saml_gen_password(self):+        """+        If password_security is installed, we cannot have a False-y password.+        This is to avoid a very small bridging/compatbility module.+        """+        new_password = False+        modules = self.env["ir.module.module"].sudo()._installed().keys()+        if "password_security" in modules:+            new_password = passlib.utils.generate_password(size=24, charset="ascii_72")+        return new_password++    def write(self, vals):+        result = super().write(vals)+        self._autoremove_password_if_saml()+        self._ensure_saml_token_exists()+        return result++    @api.model_create_multi+    def create(self, vals_list):+        result = super().create(vals_list)+        result._autoremove_password_if_saml()+        result._ensure_saml_token_exists()+        return result++    @api.model+    def _allow_saml_and_password(self):+        """Can both SAML and local password auth methods can coexist."""+        return tools.str2bool(+            self.env["ir.config_parameter"]+            .sudo()+            .get_param("auth_saml.allow_saml_uid_and_internal_password", "True")+        )++    def _ensure_saml_token_exists(self):+        # workaround for Odoo not seeing the newly created auth_saml.token on+        # the very first login+        model_token = self.env["auth_saml.token"].sudo()+        for record in self.filtered(lambda r: r.saml_ids):

Yes, just log in as a regular user with no administrative privileges and try to change the language.

theangryangel

comment created time in 3 months

PullRequestReviewEvent

Pull request review commentOCA/server-auth

[13.0][MIG] auth_saml

+# Copyright (C) 2020 GlodoUK <https://www.glodo.uk>+# Copyright (C) 2010-2016 XCG Consulting <http://odoo.consulting>+# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).++import logging++import passlib++from odoo import SUPERUSER_ID, _, api, fields, models, tools+from odoo.exceptions import AccessDenied, ValidationError++_logger = logging.getLogger(__name__)+++class ResUser(models.Model):+    """+    Add SAML login capabilities to Odoo users.+    """++    _inherit = "res.users"++    saml_ids = fields.One2many("res.users.saml", "user_id")++    @api.constrains("password", "saml_ids")+    def check_no_password_with_saml(self):+        """Ensure no Odoo user posesses both an SAML user ID and an Odoo+        password. Except admin which is not constrained by this rule.+        """+        if not self._allow_saml_and_password():+            # Super admin is the only user we allow to have a local password+            # in the database+            if self.password and self.id is not SUPERUSER_ID and self.saml_ids:+                raise ValidationError(+                    _(+                        "This database disallows users to "+                        "have both passwords and SAML IDs. "+                        "Errors for login %s"+                    )+                    % (self.login)+                )++    def _auth_saml_validate(self, provider_id, token, base_url=None):+        provider = self.env["auth.saml.provider"].sudo().browse(provider_id)+        return provider._validate_auth_response(token, base_url)++    def _auth_saml_signin(self, provider, validation, saml_response):+        """ retrieve and sign into openerp the user corresponding to provider+        and validated access token++        :param provider: saml provider id (int)+            :param validation: result of validation of access token (dict)+            :param saml_response: saml parameters response from the IDP+            :return: user login (str)+            :raise: openerp.exceptions.AccessDenied if signin failed++            This method can be overridden to add alternative signin methods.+        """+        token_osv = self.env["auth_saml.token"]+        saml_uid = validation["user_id"]+        user = (+            self.env["res.users.saml"]+            .search(+                [("saml_uid", "=", saml_uid), ("saml_provider_id", "=", provider)],+                limit=1,+            )+            .user_id+        )+        if len(user) != 1:+            raise AccessDenied()+        # now find if a token for this user/provider already exists+        token_ids = token_osv.search(+            [("saml_provider_id", "=", provider), ("user_id", "=", user.id)]+        )++        if token_ids:+            token_ids.write({"saml_access_token": saml_response})+        else:+            _logger.info("Creating auth_saml.token")+            token_ids = token_osv.create(+                {+                    "saml_access_token": saml_response,+                    "saml_provider_id": provider,+                    "user_id": user.id,+                }+            )++        if validation.get("mapped_attrs", {}):+            user.write(validation.get("mapped_attrs", {}))++        return user.login++    @api.model+    def auth_saml(self, provider, saml_response, base_url=None):+        validation = self._auth_saml_validate(provider, saml_response, base_url)++        # required check+        if not validation.get("user_id"):+            raise AccessDenied()++        # retrieve and sign in user+        login = self._auth_saml_signin(provider, validation, saml_response)++        if not login:+            raise AccessDenied()++        # return user credentials+        return self.env.cr.dbname, login, saml_response++    def _check_credentials(self, password):+        """Override to handle SAML auths.++        The token can be a password if the user has used the normal form...+        but we are more interested in the case when they are tokens+        and the interesting code is inside the "except" clause.+        """+        try:+            # Attempt a regular login (via other auth addons) first.+            return super()._check_credentials(password)++        except (AccessDenied, passlib.exc.PasswordSizeError):+            # since normal auth did not succeed we now try to find if the user+            # has an active token attached to his uid+            token = (+                self.env["auth_saml.token"]+                .sudo()+                .search(+                    [+                        ("user_id", "=", self.env.user.id),+                        ("saml_access_token", "=", password),+                    ]+                )+            )+            if not token:+                raise AccessDenied()++    def _autoremove_password_if_saml(self):+        """Helper to remove password if it is forbidden for SAML users."""+        if self.env.context.get("auth_saml_no_autoremove_password"):+            return+        if self._allow_saml_and_password():+            return+        to_remove_password = self.filtered(+            lambda rec: rec.id != SUPERUSER_ID and rec.saml_ids and rec.password+        )+        if to_remove_password:++            to_remove_password.with_context(+                auth_saml_no_autoremove_password=True+            ).write({"password": self._autoremove_password_if_saml_gen_password()})++    @api.model+    def _autoremove_password_if_saml_gen_password(self):+        """+        If password_security is installed, we cannot have a False-y password.+        This is to avoid a very small bridging/compatbility module.+        """+        new_password = False+        modules = self.env["ir.module.module"].sudo()._installed().keys()+        if "password_security" in modules:+            new_password = passlib.utils.generate_password(size=24, charset="ascii_72")+        return new_password++    def write(self, vals):+        result = super().write(vals)+        self._autoremove_password_if_saml()+        self._ensure_saml_token_exists()+        return result++    @api.model_create_multi+    def create(self, vals_list):+        result = super().create(vals_list)+        result._autoremove_password_if_saml()+        result._ensure_saml_token_exists()+        return result++    @api.model+    def _allow_saml_and_password(self):+        """Can both SAML and local password auth methods can coexist."""+        return tools.str2bool(+            self.env["ir.config_parameter"]+            .sudo()+            .get_param("auth_saml.allow_saml_uid_and_internal_password", "True")+        )++    def _ensure_saml_token_exists(self):+        # workaround for Odoo not seeing the newly created auth_saml.token on+        # the very first login+        model_token = self.env["auth_saml.token"].sudo()+        for record in self.filtered(lambda r: r.saml_ids):

This also causes a problem when trying to change the language for example. It triggers the write method which triggers this one and you have an access error from a regular user.

theangryangel

comment created time in 3 months

PullRequestReviewEvent

push eventpledra/server-auth

Paul Catinean

commit sha ac2ab12be89ef229091f83d89ec216319c6045fc

sudo call on res_users When ensuring a saml token exists one must filter the list of users with sudo for cases such as changing language in backend.

view details

push time in 3 months

issue commentOCA/product-configurator

Website Product Configurator error message

Issue should be resolved with the above merged fix, can you confirm?

Woodlawnfurniture

comment created time in 3 months

pull request commentOCA/product-configurator

[14.0][FIX] product_configurator (Issue#36)

So after having a discussion with the team on this topic it seems that there are two ways to look at configurations and both need a compromise:

Every time a value is present in two or more restrictions the individual restrictions are checked with:

  1. AND operator (a.k.a all of them have to be true for this value to be available):

Here you need to create a separate restriction which concatenates two or more (instead of placing the value on two or more lines)

  1. OR operator (a.k.a if any line is true then ignore all the other lines)

Here you need to place ALL your possible restrictions on one single line (all others will be ignored).

Regardless of the approach you take you need to make a compromise. In your case the compromise is not to use the same value in two places but create a separate one called "Glass bottle or Can" and include both restrictions and the "None" value on that line only.

If we go with your changes and you had a scenario where a hypothetical color "Red" restriction also existed and Cap needed to be on color "Red" regardless of Bottle or Can then you are forced to have a single line with restriction "Red Cap or Red Bottle".

This example might not fit too good with your case but in scenarios with more complex configuration especially manufacturing the re-use of existing restrictions through the implicit "AND" exceeds the incidence or "OR" across multiple lines. We add on top of this the fact that this has been the design since the inception and there are a lot of databases using the configuration which rely on this implicit logic and it would cause a lot of issues during migration.

I hope I could explain this well enough :smiley:

patrickrwilson

comment created time in 3 months

PullRequestReviewEvent

push eventPCatinean/product-configurator

Paul Catinean

commit sha 07305b295cfd345720cdcdeef87cd31d463cdd37

Add pcatinean as maintainer for all modules

view details

push time in 3 months

pull request commentOCA/product-configurator

14.0 mig website product configurator mrp

MR ready for review

pledrateam

comment created time in 3 months