)]}'
{"/COMMIT_MSG":[{"author":{"_account_id":16465,"name":"Kristi Nikolla","email":"knikolla@bu.edu","username":"knikolla"},"change_message_id":"ac33df176a398acec93f19a06af3d69a441e6133","unresolved":false,"context_lines":[{"line_number":10,"context_line":"for the legacy mechanism via @protected decorators."},{"line_number":11,"context_line":""},{"line_number":12,"context_line":"Change-Id: I80662d9b23e706b720d56670cb849318e951a3b4"},{"line_number":13,"context_line":"Parital-Bug: #1776504"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":23,"id":"5f7c97a3_232176b6","line":13,"range":{"start_line":13,"start_character":0,"end_line":13,"end_character":11},"updated":"2018-06-29 20:32:07.000000000","message":"bah!","commit_id":"bb3b15bbf02993545d234d827dbb72ca24695e8d"}],"keystone/common/rbac_enforcer/enforcer.py":[{"author":{"_account_id":2903,"name":"Morgan Fainberg","email":"morgan.fainberg@gmail.com","username":"mdrnstm"},"change_message_id":"91f2cacb241e39c213d762b98c1407bbec4533c0","unresolved":false,"context_lines":[{"line_number":168,"context_line":"                       replaced by decorating the method/function with"},{"line_number":169,"context_line":"                       `policy_enforcer_action`."},{"line_number":170,"context_line":"        :type action: str"},{"line_number":171,"context_line":"        :param target_attr: complete override of the target data. This will"},{"line_number":172,"context_line":"                            replace all other generated target data meaning"},{"line_number":173,"context_line":"                            `member_target_type` and `member_target` are"},{"line_number":174,"context_line":"                            ignored. This will also prevent extraction of"},{"line_number":175,"context_line":"                            data from the X-Subject-Token."},{"line_number":176,"context_line":"        :type target_attr: dict"},{"line_number":177,"context_line":"        :param member_target_type: the type of the target, e.g. \u0027user\u0027. Both"},{"line_number":178,"context_line":"                                   this and `member_target` must be passed if"}],"source_content_type":"text/x-python","patch_set":3,"id":"5f7c97a3_49901fee","line":175,"range":{"start_line":171,"start_character":9,"end_line":175,"end_character":58},"updated":"2018-06-20 14:02:05.000000000","message":"Expand on an example.","commit_id":"68250da8dec2b4da3a6b1988af0b7c5960b73637"},{"author":{"_account_id":2903,"name":"Morgan Fainberg","email":"morgan.fainberg@gmail.com","username":"mdrnstm"},"change_message_id":"91f2cacb241e39c213d762b98c1407bbec4533c0","unresolved":false,"context_lines":[{"line_number":198,"context_line":"        # If \"action\" has not explicitly been overridden, see if it is set in"},{"line_number":199,"context_line":"        # Flask.g app-context (per-request thread local) meaning the"},{"line_number":200,"context_line":"        # @policy_enforcer_action decorator was used."},{"line_number":201,"context_line":"        action \u003d action or getattr(flask.g, cls.ACTION_STORE_ATTR, None)"},{"line_number":202,"context_line":"        if action not in _POSSIBLE_TARGET_ACTIONS:"},{"line_number":203,"context_line":"            LOG.warning(\u0027RBAC: Unknown/No enforcement action name. Rejecting \u0027"},{"line_number":204,"context_line":"                        \u0027as unauthorized, this is a programming error and a \u0027"}],"source_content_type":"text/x-python","patch_set":3,"id":"5f7c97a3_89af172a","line":201,"range":{"start_line":201,"start_character":0,"end_line":201,"end_character":72},"updated":"2018-06-20 14:02:05.000000000","message":"I wonder if it is possible to not directly reference \u0027g\u0027 and make this whole method \"Flask\" or \"not-flask\"\n\nReferencing \"g\" before the request lands in the flask dispatcher throws an exception.","commit_id":"68250da8dec2b4da3a6b1988af0b7c5960b73637"},{"author":{"_account_id":2903,"name":"Morgan Fainberg","email":"morgan.fainberg@gmail.com","username":"mdrnstm"},"change_message_id":"91f2cacb241e39c213d762b98c1407bbec4533c0","unresolved":false,"context_lines":[{"line_number":227,"context_line":"        # values are set last."},{"line_number":228,"context_line":""},{"line_number":229,"context_line":"        # Get the Target Data Set."},{"line_number":230,"context_line":"        if target_attr is not None:"},{"line_number":231,"context_line":"            policy_dict.update("},{"line_number":232,"context_line":"                cls._extract_member_target_data("},{"line_number":233,"context_line":"                    member_target_type, member_target))"}],"source_content_type":"text/x-python","patch_set":3,"id":"5f7c97a3_e99fabff","line":230,"range":{"start_line":230,"start_character":26,"end_line":230,"end_character":29},"updated":"2018-06-20 14:02:05.000000000","message":"is None\n\nRemove the \"NOT\"","commit_id":"68250da8dec2b4da3a6b1988af0b7c5960b73637"},{"author":{"_account_id":2903,"name":"Morgan Fainberg","email":"morgan.fainberg@gmail.com","username":"mdrnstm"},"change_message_id":"91f2cacb241e39c213d762b98c1407bbec4533c0","unresolved":false,"context_lines":[{"line_number":30,"context_line":""},{"line_number":31,"context_line":""},{"line_number":32,"context_line":"# SET Comprehension for possible action name(s)"},{"line_number":33,"context_line":"_POSSIBLE_TARGET_ACTIONS \u003d {rule.name for rule in policies.list_rules()}"},{"line_number":34,"context_line":""},{"line_number":35,"context_line":""},{"line_number":36,"context_line":"class RBACEnforcer(object):"}],"source_content_type":"text/x-python","patch_set":4,"id":"5f7c97a3_895dd749","line":33,"range":{"start_line":33,"start_character":0,"end_line":33,"end_character":24},"updated":"2018-06-20 14:02:05.000000000","message":"This needs some \"work\" to handle the update and extract the data if policy.json updates.","commit_id":"3b6fc94429a30db747d75d8b02318e65b20b0153"},{"author":{"_account_id":2903,"name":"Morgan Fainberg","email":"morgan.fainberg@gmail.com","username":"mdrnstm"},"change_message_id":"91f2cacb241e39c213d762b98c1407bbec4533c0","unresolved":false,"context_lines":[{"line_number":125,"context_line":"        if member_target is not None and member_target_type is not None:"},{"line_number":126,"context_line":"            ret_dict[\u0027target\u0027] \u003d {member_target_type: member_target}"},{"line_number":127,"context_line":"        else:"},{"line_number":128,"context_line":"            # Try and do some magic loading based upon the resource we\u0027ve"},{"line_number":129,"context_line":"            # matched in our route."},{"line_number":130,"context_line":"            if flask.request.endpoint:"},{"line_number":131,"context_line":"                # This only works for cases of Flask-RESTful"},{"line_number":132,"context_line":"                resource_object \u003d flask.current_app.view_functions["},{"line_number":133,"context_line":"                    flask.request.endpoint].__class__"},{"line_number":134,"context_line":"                member_name \u003d getattr(resource_object, \u0027member_name\u0027, None)"},{"line_number":135,"context_line":"                func \u003d getattr("},{"line_number":136,"context_line":"                    resource_object, \u0027get_member_from_driver\u0027, None)"},{"line_number":137,"context_line":"                if member_name is not None and func is not None:"},{"line_number":138,"context_line":"                    key \u003d \u0027%s_id\u0027 % member_name"},{"line_number":139,"context_line":"                    if key in (flask.request.view_args or {}):"},{"line_number":140,"context_line":"                        ret_dict[\u0027target\u0027] \u003d {"},{"line_number":141,"context_line":"                            member_name: func(flask.request.view_args[key])}"},{"line_number":142,"context_line":"        return ret_dict"},{"line_number":143,"context_line":""},{"line_number":144,"context_line":"    @staticmethod"}],"source_content_type":"text/x-python","patch_set":4,"id":"5f7c97a3_a96f73f8","line":141,"range":{"start_line":128,"start_character":11,"end_line":141,"end_character":76},"updated":"2018-06-20 14:02:05.000000000","message":"Add More comments.\n\nThis is not very clear.","commit_id":"3b6fc94429a30db747d75d8b02318e65b20b0153"},{"author":{"_account_id":2903,"name":"Morgan Fainberg","email":"morgan.fainberg@gmail.com","username":"mdrnstm"},"change_message_id":"91f2cacb241e39c213d762b98c1407bbec4533c0","unresolved":false,"context_lines":[{"line_number":168,"context_line":"                       replaced by decorating the method/function with"},{"line_number":169,"context_line":"                       `policy_enforcer_action`."},{"line_number":170,"context_line":"        :type action: str"},{"line_number":171,"context_line":"        :param target_attr: complete override of the target data. This will"},{"line_number":172,"context_line":"                            replace all other generated target data meaning"},{"line_number":173,"context_line":"                            `member_target_type` and `member_target` are"},{"line_number":174,"context_line":"                            ignored. This will also prevent extraction of"},{"line_number":175,"context_line":"                            data from the X-Subject-Token."},{"line_number":176,"context_line":"        :type target_attr: dict"},{"line_number":177,"context_line":"        :param member_target_type: the type of the target, e.g. \u0027user\u0027. Both"},{"line_number":178,"context_line":"                                   this and `member_target` must be passed if"}],"source_content_type":"text/x-python","patch_set":4,"id":"5f7c97a3_69a4fb4b","line":175,"range":{"start_line":171,"start_character":0,"end_line":175,"end_character":58},"updated":"2018-06-20 14:02:05.000000000","message":"Needs to give a more concrete example.","commit_id":"3b6fc94429a30db747d75d8b02318e65b20b0153"},{"author":{"_account_id":2903,"name":"Morgan Fainberg","email":"morgan.fainberg@gmail.com","username":"mdrnstm"},"change_message_id":"91f2cacb241e39c213d762b98c1407bbec4533c0","unresolved":false,"context_lines":[{"line_number":198,"context_line":"        # If \"action\" has not explicitly been overridden, see if it is set in"},{"line_number":199,"context_line":"        # Flask.g app-context (per-request thread local) meaning the"},{"line_number":200,"context_line":"        # @policy_enforcer_action decorator was used."},{"line_number":201,"context_line":"        action \u003d action or getattr(flask.g, cls.ACTION_STORE_ATTR, None)"},{"line_number":202,"context_line":"        if action not in _POSSIBLE_TARGET_ACTIONS:"},{"line_number":203,"context_line":"            LOG.warning(\u0027RBAC: Unknown/No enforcement action name. Rejecting \u0027"},{"line_number":204,"context_line":"                        \u0027as unauthorized, this is a programming error and a \u0027"}],"source_content_type":"text/x-python","patch_set":4,"id":"5f7c97a3_c96aefeb","line":201,"range":{"start_line":201,"start_character":8,"end_line":201,"end_character":72},"updated":"2018-06-20 14:02:05.000000000","message":"If I can avoid referencing \"g\" I can make this work for either flask or non-flask.\n\nReferencing flask.g throws an exception if you\u0027ve not hit the flask app dispatching yet.","commit_id":"3b6fc94429a30db747d75d8b02318e65b20b0153"},{"author":{"_account_id":2903,"name":"Morgan Fainberg","email":"morgan.fainberg@gmail.com","username":"mdrnstm"},"change_message_id":"91f2cacb241e39c213d762b98c1407bbec4533c0","unresolved":false,"context_lines":[{"line_number":227,"context_line":"        # values are set last."},{"line_number":228,"context_line":""},{"line_number":229,"context_line":"        # Get the Target Data Set."},{"line_number":230,"context_line":"        if target_attr is not None:"},{"line_number":231,"context_line":"            policy_dict.update("},{"line_number":232,"context_line":"                cls._extract_member_target_data("},{"line_number":233,"context_line":"                    member_target_type, member_target))"}],"source_content_type":"text/x-python","patch_set":4,"id":"5f7c97a3_0961c711","line":230,"range":{"start_line":230,"start_character":23,"end_line":230,"end_character":34},"updated":"2018-06-20 14:02:05.000000000","message":"is None","commit_id":"3b6fc94429a30db747d75d8b02318e65b20b0153"},{"author":{"_account_id":2903,"name":"Morgan Fainberg","email":"morgan.fainberg@gmail.com","username":"mdrnstm"},"change_message_id":"8b25f7d1da4084a90bf21942e4acfa818ba8f6aa","unresolved":false,"context_lines":[{"line_number":172,"context_line":"                       replaced by decorating the method/function with"},{"line_number":173,"context_line":"                       `policy_enforcer_action`."},{"line_number":174,"context_line":"        :type action: str"},{"line_number":175,"context_line":"        :param target_attr: complete override of the target data. This will"},{"line_number":176,"context_line":"                            replace all other generated target data meaning"},{"line_number":177,"context_line":"                            `member_target_type` and `member_target` are"},{"line_number":178,"context_line":"                            ignored. This will also prevent extraction of"},{"line_number":179,"context_line":"                            data from the X-Subject-Token."},{"line_number":180,"context_line":"        :type target_attr: dict"},{"line_number":181,"context_line":"        :param member_target_type: the type of the target, e.g. \u0027user\u0027. Both"},{"line_number":182,"context_line":"                                   this and `member_target` must be passed if"}],"source_content_type":"text/x-python","patch_set":5,"id":"5f7c97a3_9b375c4c","line":179,"range":{"start_line":175,"start_character":0,"end_line":179,"end_character":58},"updated":"2018-06-20 15:49:14.000000000","message":"Expand Example in docstring.","commit_id":"d53598a0434596ebd8eae6321a7aea39e4fab33f"},{"author":{"_account_id":2903,"name":"Morgan Fainberg","email":"morgan.fainberg@gmail.com","username":"mdrnstm"},"change_message_id":"8b25f7d1da4084a90bf21942e4acfa818ba8f6aa","unresolved":false,"context_lines":[{"line_number":231,"context_line":"        # values are set last."},{"line_number":232,"context_line":""},{"line_number":233,"context_line":"        # Get the Target Data Set."},{"line_number":234,"context_line":"        if target_attr is not None:"},{"line_number":235,"context_line":"            policy_dict.update("},{"line_number":236,"context_line":"                cls._extract_member_target_data("},{"line_number":237,"context_line":"                    member_target_type, member_target))"}],"source_content_type":"text/x-python","patch_set":5,"id":"5f7c97a3_7b3cc02f","line":234,"range":{"start_line":234,"start_character":23,"end_line":234,"end_character":34},"updated":"2018-06-20 15:49:14.000000000","message":"\"is None\"","commit_id":"d53598a0434596ebd8eae6321a7aea39e4fab33f"},{"author":{"_account_id":5280,"name":"Nicolas Simonds","email":"nic@metacloud.com","username":"nicolas.simonds"},"change_message_id":"e1684593e46d211a5192f8706b376eed9589b96e","unresolved":false,"context_lines":[{"line_number":30,"context_line":"LOG \u003d log.getLogger(__name__)"},{"line_number":31,"context_line":""},{"line_number":32,"context_line":""},{"line_number":33,"context_line":"# SET Comprehension for possible action name(s)"},{"line_number":34,"context_line":"_POSSIBLE_TARGET_ACTIONS \u003d {rule.name for rule in policies.list_rules()}"},{"line_number":35,"context_line":""},{"line_number":36,"context_line":""}],"source_content_type":"text/x-python","patch_set":6,"id":"5f7c97a3_79727fe5","line":33,"range":{"start_line":33,"start_character":2,"end_line":33,"end_character":47},"updated":"2018-06-21 04:28:16.000000000","message":"Using a long-form set constructor, e.g., \n\n    set([list comprehension])\n\n...is both clearer at first blush, and doesn\u0027t require a comment explaining what you\u0027re doing","commit_id":"3bc20527ffba27cfa63ee5b5dd4ba28b754a7826"},{"author":{"_account_id":2903,"name":"Morgan Fainberg","email":"morgan.fainberg@gmail.com","username":"mdrnstm"},"change_message_id":"6518d7841325f3bb0e6a23fcfaaceca2a3f701ba","unresolved":false,"context_lines":[{"line_number":30,"context_line":"LOG \u003d log.getLogger(__name__)"},{"line_number":31,"context_line":""},{"line_number":32,"context_line":""},{"line_number":33,"context_line":"# SET Comprehension for possible action name(s)"},{"line_number":34,"context_line":"_POSSIBLE_TARGET_ACTIONS \u003d {rule.name for rule in policies.list_rules()}"},{"line_number":35,"context_line":""},{"line_number":36,"context_line":""}],"source_content_type":"text/x-python","patch_set":6,"id":"5f7c97a3_a85bcd51","line":33,"range":{"start_line":33,"start_character":2,"end_line":33,"end_character":47},"in_reply_to":"5f7c97a3_79727fe5","updated":"2018-06-21 19:31:25.000000000","message":"You\u0027re right. in next.","commit_id":"3bc20527ffba27cfa63ee5b5dd4ba28b754a7826"},{"author":{"_account_id":5280,"name":"Nicolas Simonds","email":"nic@metacloud.com","username":"nicolas.simonds"},"change_message_id":"e1684593e46d211a5192f8706b376eed9589b96e","unresolved":false,"context_lines":[{"line_number":91,"context_line":""},{"line_number":92,"context_line":"    @staticmethod"},{"line_number":93,"context_line":"    def _build_filter_values(filters):"},{"line_number":94,"context_line":"        \"\"\"Extraxt fo;ter data from query params for RBAC enforcement.\"\"\""},{"line_number":95,"context_line":"        filters \u003d filters or []"},{"line_number":96,"context_line":"        target \u003d {i: flask.request.args[i] for"},{"line_number":97,"context_line":"                  i in filters if i in flask.request.args}"}],"source_content_type":"text/x-python","patch_set":6,"id":"5f7c97a3_d9615313","line":94,"range":{"start_line":94,"start_character":11,"end_line":94,"end_character":18},"updated":"2018-06-21 04:28:16.000000000","message":"typo","commit_id":"3bc20527ffba27cfa63ee5b5dd4ba28b754a7826"},{"author":{"_account_id":2903,"name":"Morgan Fainberg","email":"morgan.fainberg@gmail.com","username":"mdrnstm"},"change_message_id":"6518d7841325f3bb0e6a23fcfaaceca2a3f701ba","unresolved":false,"context_lines":[{"line_number":91,"context_line":""},{"line_number":92,"context_line":"    @staticmethod"},{"line_number":93,"context_line":"    def _build_filter_values(filters):"},{"line_number":94,"context_line":"        \"\"\"Extraxt fo;ter data from query params for RBAC enforcement.\"\"\""},{"line_number":95,"context_line":"        filters \u003d filters or []"},{"line_number":96,"context_line":"        target \u003d {i: flask.request.args[i] for"},{"line_number":97,"context_line":"                  i in filters if i in flask.request.args}"}],"source_content_type":"text/x-python","patch_set":6,"id":"5f7c97a3_48547922","line":94,"range":{"start_line":94,"start_character":11,"end_line":94,"end_character":18},"in_reply_to":"5f7c97a3_d9615313","updated":"2018-06-21 19:31:25.000000000","message":"I think this doesn\u0027t qualify as a typo anymore... look at that second word \"fo;ter\" THE HECK... ;) \n\nFixed in next.","commit_id":"3bc20527ffba27cfa63ee5b5dd4ba28b754a7826"},{"author":{"_account_id":2903,"name":"Morgan Fainberg","email":"morgan.fainberg@gmail.com","username":"mdrnstm"},"change_message_id":"8e70aa5ac6f9c556a8cb068a79b6fdd03a542bf3","unresolved":false,"context_lines":[{"line_number":183,"context_line":""},{"line_number":184,"context_line":"    @classmethod"},{"line_number":185,"context_line":"    def enforce_call(cls, enforcer\u003dNone, action\u003dNone, target_attr\u003dNone,"},{"line_number":186,"context_line":"                     member_target_type\u003dNone, member_target\u003dNone, *filters):"},{"line_number":187,"context_line":"        \"\"\"Enforce RBAC on the current request."},{"line_number":188,"context_line":""},{"line_number":189,"context_line":"        This will do some legwork and then instantiate the Enforcer if an"}],"source_content_type":"text/x-python","patch_set":6,"id":"5f7c97a3_c8408962","line":186,"range":{"start_line":186,"start_character":67,"end_line":186,"end_character":74},"updated":"2018-06-21 19:30:01.000000000","message":"This can\u0027t be *filters, must be turned into accepting an iterable (list/set/tuple/generator/etc)","commit_id":"3bc20527ffba27cfa63ee5b5dd4ba28b754a7826"},{"author":{"_account_id":2903,"name":"Morgan Fainberg","email":"morgan.fainberg@gmail.com","username":"mdrnstm"},"change_message_id":"96f3dfb242af52718ca54f89d4223d5036c3801e","unresolved":false,"context_lines":[{"line_number":142,"context_line":"                # crafted endpoints that live on a class. Ultimately, there"},{"line_number":143,"context_line":"                # should be more protection against something wonky"},{"line_number":144,"context_line":"                # here."},{"line_number":145,"context_line":"                resource \u003d flask.current_app.view_functions["},{"line_number":146,"context_line":"                    flask.request.endpoint].view_class"},{"line_number":147,"context_line":"                member_name \u003d getattr(resource, \u0027member_name\u0027, None)"},{"line_number":148,"context_line":"                func \u003d getattr("},{"line_number":149,"context_line":"                    resource, \u0027get_member_from_driver\u0027, None)"},{"line_number":150,"context_line":"                if member_name is not None and callable(func):"},{"line_number":151,"context_line":"                    key \u003d \u0027%s_id\u0027 % member_name"},{"line_number":152,"context_line":"                    if key in (flask.request.view_args or {}):"},{"line_number":153,"context_line":"                        ret_dict[\u0027target\u0027] \u003d {"},{"line_number":154,"context_line":"                            member_name: func("},{"line_number":155,"context_line":"                                resource,"},{"line_number":156,"context_line":"                                flask.request.view_args[key])[member_name]}"},{"line_number":157,"context_line":"        return ret_dict"},{"line_number":158,"context_line":""},{"line_number":159,"context_line":"    @staticmethod"}],"source_content_type":"text/x-python","patch_set":17,"id":"5f7c97a3_8a0fa937","line":156,"range":{"start_line":145,"start_character":16,"end_line":156,"end_character":75},"updated":"2018-06-26 02:32:53.000000000","message":"apparently this works in python3 but not python2. I\u0027ll debug, but this is still ready for reviews for the rest of the code.","commit_id":"9aad85ec2763734478197927b298d1b0e7db79b3"},{"author":{"_account_id":5046,"name":"Lance Bragstad","email":"lbragstad@redhat.com","username":"ldbragst"},"change_message_id":"0ee63260d0019cebc2b4594f7983f03d96562dc3","unresolved":false,"context_lines":[{"line_number":34,"context_line":""},{"line_number":35,"context_line":""},{"line_number":36,"context_line":"_POSSIBLE_TARGET_ACTIONS \u003d frozenset(["},{"line_number":37,"context_line":"    rule.name for rule in policies.list_rules()])"},{"line_number":38,"context_line":""},{"line_number":39,"context_line":""},{"line_number":40,"context_line":"class RBACEnforcer(object):"}],"source_content_type":"text/x-python","patch_set":19,"id":"5f7c97a3_29944c43","line":37,"range":{"start_line":37,"start_character":4,"end_line":37,"end_character":14},"updated":"2018-06-26 21:54:27.000000000","message":"Will this work for deprecated policies? I think in cases like that the deprecated policy name is nested within the new registered rule (just like we do when we deprecate configuration options). In that case, this list not contain the deprecated rule name. Is that going to be a problem?","commit_id":"6c36441df331c8b4a3f54b4ba1d21695ebc7006e"},{"author":{"_account_id":2903,"name":"Morgan Fainberg","email":"morgan.fainberg@gmail.com","username":"mdrnstm"},"change_message_id":"4320d3382203175b305d1291bc400af5cbd223a8","unresolved":false,"context_lines":[{"line_number":34,"context_line":""},{"line_number":35,"context_line":""},{"line_number":36,"context_line":"_POSSIBLE_TARGET_ACTIONS \u003d frozenset(["},{"line_number":37,"context_line":"    rule.name for rule in policies.list_rules()])"},{"line_number":38,"context_line":""},{"line_number":39,"context_line":""},{"line_number":40,"context_line":"class RBACEnforcer(object):"}],"source_content_type":"text/x-python","patch_set":19,"id":"5f7c97a3_64ad8b82","line":37,"range":{"start_line":37,"start_character":4,"end_line":37,"end_character":14},"in_reply_to":"5f7c97a3_29944c43","updated":"2018-06-26 22:01:53.000000000","message":"Ok, we need to expand on that, lets get a test for that and expand the deprecated rule name explicitly, since it is still a valid action.","commit_id":"6c36441df331c8b4a3f54b4ba1d21695ebc7006e"},{"author":{"_account_id":2903,"name":"Morgan Fainberg","email":"morgan.fainberg@gmail.com","username":"mdrnstm"},"change_message_id":"80e2c597df59672d2b7cb2cbb7ccea743dff0cb0","unresolved":false,"context_lines":[{"line_number":34,"context_line":""},{"line_number":35,"context_line":""},{"line_number":36,"context_line":"_POSSIBLE_TARGET_ACTIONS \u003d frozenset(["},{"line_number":37,"context_line":"    rule.name for rule in policies.list_rules()])"},{"line_number":38,"context_line":""},{"line_number":39,"context_line":""},{"line_number":40,"context_line":"class RBACEnforcer(object):"}],"source_content_type":"text/x-python","patch_set":19,"id":"5f7c97a3_7bbe7765","line":37,"range":{"start_line":37,"start_character":4,"end_line":37,"end_character":14},"in_reply_to":"5f7c97a3_64ad8b82","updated":"2018-06-27 15:42:21.000000000","message":"Done in next, and tested.","commit_id":"6c36441df331c8b4a3f54b4ba1d21695ebc7006e"},{"author":{"_account_id":2903,"name":"Morgan Fainberg","email":"morgan.fainberg@gmail.com","username":"mdrnstm"},"change_message_id":"fbfa36785c83e9e06b591994f9f0373980ee5219","unresolved":false,"context_lines":[{"line_number":34,"context_line":""},{"line_number":35,"context_line":""},{"line_number":36,"context_line":"_POSSIBLE_TARGET_ACTIONS \u003d frozenset(["},{"line_number":37,"context_line":"    rule.name for rule in policies.list_rules()])"},{"line_number":38,"context_line":""},{"line_number":39,"context_line":""},{"line_number":40,"context_line":"class RBACEnforcer(object):"}],"source_content_type":"text/x-python","patch_set":19,"id":"5f7c97a3_e99ddd58","line":37,"range":{"start_line":37,"start_character":4,"end_line":37,"end_character":14},"in_reply_to":"5f7c97a3_7bbe7765","updated":"2018-06-27 16:39:24.000000000","message":"Wild goose-chase. We never will refer to a deprecated action in code only ever the new name.","commit_id":"6c36441df331c8b4a3f54b4ba1d21695ebc7006e"},{"author":{"_account_id":5046,"name":"Lance Bragstad","email":"lbragstad@redhat.com","username":"ldbragst"},"change_message_id":"0ee63260d0019cebc2b4594f7983f03d96562dc3","unresolved":false,"context_lines":[{"line_number":166,"context_line":"        return ret_dict"},{"line_number":167,"context_line":""},{"line_number":168,"context_line":"    @staticmethod"},{"line_number":169,"context_line":"    def _extract_policy_check_credentials(action):"},{"line_number":170,"context_line":"        # Pull out the auth context"},{"line_number":171,"context_line":"        return flask.request.environ.get(authorization.AUTH_CONTEXT_ENV, {})"},{"line_number":172,"context_line":""}],"source_content_type":"text/x-python","patch_set":19,"id":"5f7c97a3_c9d5981c","line":169,"range":{"start_line":169,"start_character":42,"end_line":169,"end_character":48},"updated":"2018-06-26 21:54:27.000000000","message":"This isn\u0027t used here, we should be safe to remove it.","commit_id":"6c36441df331c8b4a3f54b4ba1d21695ebc7006e"},{"author":{"_account_id":2903,"name":"Morgan Fainberg","email":"morgan.fainberg@gmail.com","username":"mdrnstm"},"change_message_id":"80e2c597df59672d2b7cb2cbb7ccea743dff0cb0","unresolved":false,"context_lines":[{"line_number":166,"context_line":"        return ret_dict"},{"line_number":167,"context_line":""},{"line_number":168,"context_line":"    @staticmethod"},{"line_number":169,"context_line":"    def _extract_policy_check_credentials(action):"},{"line_number":170,"context_line":"        # Pull out the auth context"},{"line_number":171,"context_line":"        return flask.request.environ.get(authorization.AUTH_CONTEXT_ENV, {})"},{"line_number":172,"context_line":""}],"source_content_type":"text/x-python","patch_set":19,"id":"5f7c97a3_3bb8ff73","line":169,"range":{"start_line":169,"start_character":42,"end_line":169,"end_character":48},"in_reply_to":"5f7c97a3_44c64f4b","updated":"2018-06-27 15:42:21.000000000","message":"Done","commit_id":"6c36441df331c8b4a3f54b4ba1d21695ebc7006e"},{"author":{"_account_id":2903,"name":"Morgan Fainberg","email":"morgan.fainberg@gmail.com","username":"mdrnstm"},"change_message_id":"4320d3382203175b305d1291bc400af5cbd223a8","unresolved":false,"context_lines":[{"line_number":166,"context_line":"        return ret_dict"},{"line_number":167,"context_line":""},{"line_number":168,"context_line":"    @staticmethod"},{"line_number":169,"context_line":"    def _extract_policy_check_credentials(action):"},{"line_number":170,"context_line":"        # Pull out the auth context"},{"line_number":171,"context_line":"        return flask.request.environ.get(authorization.AUTH_CONTEXT_ENV, {})"},{"line_number":172,"context_line":""}],"source_content_type":"text/x-python","patch_set":19,"id":"5f7c97a3_44c64f4b","line":169,"range":{"start_line":169,"start_character":42,"end_line":169,"end_character":48},"in_reply_to":"5f7c97a3_c9d5981c","updated":"2018-06-26 22:01:53.000000000","message":"++","commit_id":"6c36441df331c8b4a3f54b4ba1d21695ebc7006e"},{"author":{"_account_id":5046,"name":"Lance Bragstad","email":"lbragstad@redhat.com","username":"ldbragst"},"change_message_id":"0ee63260d0019cebc2b4594f7983f03d96562dc3","unresolved":false,"context_lines":[{"line_number":236,"context_line":"        This will do some legwork and then instantiate the Enforcer if an"},{"line_number":237,"context_line":"        enforcer is not passed in."},{"line_number":238,"context_line":""},{"line_number":239,"context_line":"        :param enforcer: A pre-instantiated Enforcer object (optional)"},{"line_number":240,"context_line":"        :type enforcer: :class:`RBACEnforcer`"},{"line_number":241,"context_line":"        :param action: the name of the rule/policy enforcement to be checked"},{"line_number":242,"context_line":"                       against, e.g. `identity:get_user` (optional may be"},{"line_number":243,"context_line":"                       replaced by decorating the method/function with"}],"source_content_type":"text/x-python","patch_set":19,"id":"5f7c97a3_49cae86d","line":240,"range":{"start_line":239,"start_character":0,"end_line":240,"end_character":45},"updated":"2018-06-26 21:54:27.000000000","message":"Is this mainly for testing purposes or do we expect various APIs across keystone to instantiate their own enforcers prior to calling this method?","commit_id":"6c36441df331c8b4a3f54b4ba1d21695ebc7006e"},{"author":{"_account_id":2903,"name":"Morgan Fainberg","email":"morgan.fainberg@gmail.com","username":"mdrnstm"},"change_message_id":"80e2c597df59672d2b7cb2cbb7ccea743dff0cb0","unresolved":false,"context_lines":[{"line_number":236,"context_line":"        This will do some legwork and then instantiate the Enforcer if an"},{"line_number":237,"context_line":"        enforcer is not passed in."},{"line_number":238,"context_line":""},{"line_number":239,"context_line":"        :param enforcer: A pre-instantiated Enforcer object (optional)"},{"line_number":240,"context_line":"        :type enforcer: :class:`RBACEnforcer`"},{"line_number":241,"context_line":"        :param action: the name of the rule/policy enforcement to be checked"},{"line_number":242,"context_line":"                       against, e.g. `identity:get_user` (optional may be"},{"line_number":243,"context_line":"                       replaced by decorating the method/function with"}],"source_content_type":"text/x-python","patch_set":19,"id":"5f7c97a3_dbac6b38","line":240,"range":{"start_line":239,"start_character":0,"end_line":240,"end_character":45},"in_reply_to":"5f7c97a3_24f9d37e","updated":"2018-06-27 15:42:21.000000000","message":"No change needed.","commit_id":"6c36441df331c8b4a3f54b4ba1d21695ebc7006e"},{"author":{"_account_id":2903,"name":"Morgan Fainberg","email":"morgan.fainberg@gmail.com","username":"mdrnstm"},"change_message_id":"4320d3382203175b305d1291bc400af5cbd223a8","unresolved":false,"context_lines":[{"line_number":236,"context_line":"        This will do some legwork and then instantiate the Enforcer if an"},{"line_number":237,"context_line":"        enforcer is not passed in."},{"line_number":238,"context_line":""},{"line_number":239,"context_line":"        :param enforcer: A pre-instantiated Enforcer object (optional)"},{"line_number":240,"context_line":"        :type enforcer: :class:`RBACEnforcer`"},{"line_number":241,"context_line":"        :param action: the name of the rule/policy enforcement to be checked"},{"line_number":242,"context_line":"                       against, e.g. `identity:get_user` (optional may be"},{"line_number":243,"context_line":"                       replaced by decorating the method/function with"}],"source_content_type":"text/x-python","patch_set":19,"id":"5f7c97a3_24f9d37e","line":240,"range":{"start_line":239,"start_character":0,"end_line":240,"end_character":45},"in_reply_to":"5f7c97a3_49cae86d","updated":"2018-06-26 22:01:53.000000000","message":"This is to support the concept of the enforcer being locally instantiated ahead of the game. It is currently for testing but it may help to save some overhead in the grand scheme of things if each API or each resource has it\u0027s own enforcer.\n\nI was envisioning the resource base having self.enforcer instantiated and implementing a .enforce_call that passes self.enforcer as the enforcer argument.\n\nI wanted to allow both to work in the case that something had to call enforce and didn\u0027t want to pre-instantiate (wasn\u0027t a resource object) an enforcer.\n\nFor now everything is on-demand.","commit_id":"6c36441df331c8b4a3f54b4ba1d21695ebc7006e"},{"author":{"_account_id":5046,"name":"Lance Bragstad","email":"lbragstad@redhat.com","username":"ldbragst"},"change_message_id":"0ee63260d0019cebc2b4594f7983f03d96562dc3","unresolved":false,"context_lines":[{"line_number":297,"context_line":""},{"line_number":298,"context_line":"        # NOTE(morgan): !!! ORDER OF THESE OPERATIONS IS IMPORTANT !!!"},{"line_number":299,"context_line":"        # The lowest priority values are set first and the highest priority"},{"line_number":300,"context_line":"        # values are set last."},{"line_number":301,"context_line":""},{"line_number":302,"context_line":"        # Get the Target Data Set."},{"line_number":303,"context_line":"        if target_attr is None:"}],"source_content_type":"text/x-python","patch_set":19,"id":"5f7c97a3_69c7a499","line":300,"updated":"2018-06-26 21:54:27.000000000","message":"Why do we do it that way?","commit_id":"6c36441df331c8b4a3f54b4ba1d21695ebc7006e"},{"author":{"_account_id":2903,"name":"Morgan Fainberg","email":"morgan.fainberg@gmail.com","username":"mdrnstm"},"change_message_id":"80e2c597df59672d2b7cb2cbb7ccea743dff0cb0","unresolved":false,"context_lines":[{"line_number":297,"context_line":""},{"line_number":298,"context_line":"        # NOTE(morgan): !!! ORDER OF THESE OPERATIONS IS IMPORTANT !!!"},{"line_number":299,"context_line":"        # The lowest priority values are set first and the highest priority"},{"line_number":300,"context_line":"        # values are set last."},{"line_number":301,"context_line":""},{"line_number":302,"context_line":"        # Get the Target Data Set."},{"line_number":303,"context_line":"        if target_attr is None:"}],"source_content_type":"text/x-python","patch_set":19,"id":"5f7c97a3_fba92725","line":300,"in_reply_to":"5f7c97a3_64302b56","updated":"2018-06-27 15:42:21.000000000","message":"No change needed.","commit_id":"6c36441df331c8b4a3f54b4ba1d21695ebc7006e"},{"author":{"_account_id":2903,"name":"Morgan Fainberg","email":"morgan.fainberg@gmail.com","username":"mdrnstm"},"change_message_id":"4320d3382203175b305d1291bc400af5cbd223a8","unresolved":false,"context_lines":[{"line_number":297,"context_line":""},{"line_number":298,"context_line":"        # NOTE(morgan): !!! ORDER OF THESE OPERATIONS IS IMPORTANT !!!"},{"line_number":299,"context_line":"        # The lowest priority values are set first and the highest priority"},{"line_number":300,"context_line":"        # values are set last."},{"line_number":301,"context_line":""},{"line_number":302,"context_line":"        # Get the Target Data Set."},{"line_number":303,"context_line":"        if target_attr is None:"}],"source_content_type":"text/x-python","patch_set":19,"id":"5f7c97a3_64302b56","line":300,"in_reply_to":"5f7c97a3_69c7a499","updated":"2018-06-26 22:01:53.000000000","message":"Because we did it that way previously :P\n\nThis is largely copying @protected behavior(s).","commit_id":"6c36441df331c8b4a3f54b4ba1d21695ebc7006e"},{"author":{"_account_id":5046,"name":"Lance Bragstad","email":"lbragstad@redhat.com","username":"ldbragst"},"change_message_id":"0ee63260d0019cebc2b4594f7983f03d96562dc3","unresolved":false,"context_lines":[{"line_number":321,"context_line":"        policy_dict.update(cls._extract_filter_values(filters))"},{"line_number":322,"context_line":""},{"line_number":323,"context_line":"        # Extract the cred data"},{"line_number":324,"context_line":"        creds \u003d cls._extract_policy_check_credentials(action\u003daction)"},{"line_number":325,"context_line":"        flattened \u003d utils.flatten_dict(policy_dict)"},{"line_number":326,"context_line":"        if LOG.logger.getEffectiveLevel() \u003c\u003d log.DEBUG:"},{"line_number":327,"context_line":"            # LOG the Args"}],"source_content_type":"text/x-python","patch_set":19,"id":"5f7c97a3_e9ebb4d9","line":324,"range":{"start_line":324,"start_character":54,"end_line":324,"end_character":67},"updated":"2018-06-26 21:54:27.000000000","message":"This doesn\u0027t appear to be used in the method we\u0027re calling.","commit_id":"6c36441df331c8b4a3f54b4ba1d21695ebc7006e"},{"author":{"_account_id":2903,"name":"Morgan Fainberg","email":"morgan.fainberg@gmail.com","username":"mdrnstm"},"change_message_id":"80e2c597df59672d2b7cb2cbb7ccea743dff0cb0","unresolved":false,"context_lines":[{"line_number":321,"context_line":"        policy_dict.update(cls._extract_filter_values(filters))"},{"line_number":322,"context_line":""},{"line_number":323,"context_line":"        # Extract the cred data"},{"line_number":324,"context_line":"        creds \u003d cls._extract_policy_check_credentials(action\u003daction)"},{"line_number":325,"context_line":"        flattened \u003d utils.flatten_dict(policy_dict)"},{"line_number":326,"context_line":"        if LOG.logger.getEffectiveLevel() \u003c\u003d log.DEBUG:"},{"line_number":327,"context_line":"            # LOG the Args"}],"source_content_type":"text/x-python","patch_set":19,"id":"5f7c97a3_9ba6f354","line":324,"range":{"start_line":324,"start_character":54,"end_line":324,"end_character":67},"in_reply_to":"5f7c97a3_84330761","updated":"2018-06-27 15:42:21.000000000","message":"Done","commit_id":"6c36441df331c8b4a3f54b4ba1d21695ebc7006e"},{"author":{"_account_id":2903,"name":"Morgan Fainberg","email":"morgan.fainberg@gmail.com","username":"mdrnstm"},"change_message_id":"4320d3382203175b305d1291bc400af5cbd223a8","unresolved":false,"context_lines":[{"line_number":321,"context_line":"        policy_dict.update(cls._extract_filter_values(filters))"},{"line_number":322,"context_line":""},{"line_number":323,"context_line":"        # Extract the cred data"},{"line_number":324,"context_line":"        creds \u003d cls._extract_policy_check_credentials(action\u003daction)"},{"line_number":325,"context_line":"        flattened \u003d utils.flatten_dict(policy_dict)"},{"line_number":326,"context_line":"        if LOG.logger.getEffectiveLevel() \u003c\u003d log.DEBUG:"},{"line_number":327,"context_line":"            # LOG the Args"}],"source_content_type":"text/x-python","patch_set":19,"id":"5f7c97a3_84330761","line":324,"range":{"start_line":324,"start_character":54,"end_line":324,"end_character":67},"in_reply_to":"5f7c97a3_e9ebb4d9","updated":"2018-06-26 22:01:53.000000000","message":"Yep, can be removed.","commit_id":"6c36441df331c8b4a3f54b4ba1d21695ebc7006e"},{"author":{"_account_id":1916,"name":"Guang Yee","email":"gyee@suse.com","username":"guang-yee"},"change_message_id":"c4321fd48f865034c8487a0557902eba84b0c0b0","unresolved":false,"context_lines":[{"line_number":33,"context_line":"PROVIDER_APIS \u003d provider_api.ProviderAPIs"},{"line_number":34,"context_line":""},{"line_number":35,"context_line":""},{"line_number":36,"context_line":"_POSSIBLE_TARGET_ACTIONS \u003d frozenset(["},{"line_number":37,"context_line":"    rule.name for"},{"line_number":38,"context_line":"    rule in policies.list_rules() if not rule.deprecated_for_removal"},{"line_number":39,"context_line":"])"}],"source_content_type":"text/x-python","patch_set":22,"id":"5f7c97a3_324ed9c2","line":36,"range":{"start_line":36,"start_character":0,"end_line":36,"end_character":24},"updated":"2018-06-27 22:36:52.000000000","message":"I thought oslo.policy can dynamically reload the policies. Will this still work?","commit_id":"edc2ff74fd54a14a9cd7383f099e6d190c3f6adc"},{"author":{"_account_id":2903,"name":"Morgan Fainberg","email":"morgan.fainberg@gmail.com","username":"mdrnstm"},"change_message_id":"cbd34bc899d11dd845e8b82fad3ec750a3f773b4","unresolved":false,"context_lines":[{"line_number":33,"context_line":"PROVIDER_APIS \u003d provider_api.ProviderAPIs"},{"line_number":34,"context_line":""},{"line_number":35,"context_line":""},{"line_number":36,"context_line":"_POSSIBLE_TARGET_ACTIONS \u003d frozenset(["},{"line_number":37,"context_line":"    rule.name for"},{"line_number":38,"context_line":"    rule in policies.list_rules() if not rule.deprecated_for_removal"},{"line_number":39,"context_line":"])"}],"source_content_type":"text/x-python","patch_set":22,"id":"5f7c97a3_d2f8c54b","line":36,"range":{"start_line":36,"start_character":0,"end_line":36,"end_character":24},"in_reply_to":"5f7c97a3_324ed9c2","updated":"2018-06-27 22:43:38.000000000","message":"This is just the referred action name. This is all in-code. The policy.json is loaded by oslo_policy lib. It will still work.","commit_id":"edc2ff74fd54a14a9cd7383f099e6d190c3f6adc"},{"author":{"_account_id":1916,"name":"Guang Yee","email":"gyee@suse.com","username":"guang-yee"},"change_message_id":"c4321fd48f865034c8487a0557902eba84b0c0b0","unresolved":false,"context_lines":[{"line_number":49,"context_line":"    def __init__(self):"},{"line_number":50,"context_line":"        # NOTE(morgan): All Enforcer Instances use the same shared state;"},{"line_number":51,"context_line":"        # BORG pattern."},{"line_number":52,"context_line":"        self.__dict__ \u003d self.__shared_state__"},{"line_number":53,"context_line":""},{"line_number":54,"context_line":"    def _enforce(self, credentials, action, target, do_raise\u003dTrue):"},{"line_number":55,"context_line":"        \"\"\"Verify that the action is valid on the target in this context."}],"source_content_type":"text/x-python","patch_set":22,"id":"5f7c97a3_527ef5e3","line":52,"range":{"start_line":52,"start_character":8,"end_line":52,"end_character":45},"updated":"2018-06-27 22:36:52.000000000","message":"nice interview question right there :-)","commit_id":"edc2ff74fd54a14a9cd7383f099e6d190c3f6adc"},{"author":{"_account_id":1916,"name":"Guang Yee","email":"gyee@suse.com","username":"guang-yee"},"change_message_id":"c4321fd48f865034c8487a0557902eba84b0c0b0","unresolved":false,"context_lines":[{"line_number":289,"context_line":"                    \u0027lookup\u0027))"},{"line_number":290,"context_line":""},{"line_number":291,"context_line":"        # Assert we are actually authenticated"},{"line_number":292,"context_line":"        cls._assert_is_authenticated()"},{"line_number":293,"context_line":""},{"line_number":294,"context_line":"        # Check if \"is_admin\", this is in support of the old \"admin auth token\""},{"line_number":295,"context_line":"        # middleware with a shared \"admin\" token for auth"}],"source_content_type":"text/x-python","patch_set":22,"id":"5f7c97a3_32c9f950","line":292,"updated":"2018-06-27 22:36:52.000000000","message":"I presume \u0027unenforced_api()\u0027 in server.flask.common doesn\u0027t go through this path as it is checking for a valid token?","commit_id":"edc2ff74fd54a14a9cd7383f099e6d190c3f6adc"},{"author":{"_account_id":2903,"name":"Morgan Fainberg","email":"morgan.fainberg@gmail.com","username":"mdrnstm"},"change_message_id":"cbd34bc899d11dd845e8b82fad3ec750a3f773b4","unresolved":false,"context_lines":[{"line_number":289,"context_line":"                    \u0027lookup\u0027))"},{"line_number":290,"context_line":""},{"line_number":291,"context_line":"        # Assert we are actually authenticated"},{"line_number":292,"context_line":"        cls._assert_is_authenticated()"},{"line_number":293,"context_line":""},{"line_number":294,"context_line":"        # Check if \"is_admin\", this is in support of the old \"admin auth token\""},{"line_number":295,"context_line":"        # middleware with a shared \"admin\" token for auth"}],"source_content_type":"text/x-python","patch_set":22,"id":"5f7c97a3_3281f9a1","line":292,"in_reply_to":"5f7c97a3_32c9f950","updated":"2018-06-27 22:43:38.000000000","message":"An un-enforced API never calls enforcer.enforce_call. if you look at the follow-up patch you will see how that works.","commit_id":"edc2ff74fd54a14a9cd7383f099e6d190c3f6adc"},{"author":{"_account_id":15054,"name":"wangxiyuan","email":"wangxiyuan1007@gmail.com","username":"wangxiyuan"},"change_message_id":"e0ec2de39475705e0b92c9a10746c4d25932f3af","unresolved":false,"context_lines":[{"line_number":263,"context_line":"        :type member_target: dict"},{"line_number":264,"context_line":"        :param filters: A variable number of optional string filters, these are"},{"line_number":265,"context_line":"                        used to extract values from the query params. The"},{"line_number":266,"context_line":"                        filters are added to the reques data that is passed to"},{"line_number":267,"context_line":"                        the enforcer and may be used to determine policy"},{"line_number":268,"context_line":"                        action. In practice these are mainly supplied in the"},{"line_number":269,"context_line":"                        various \"list\" APIs and are un-used in the default"}],"source_content_type":"text/x-python","patch_set":23,"id":"5f7c97a3_735eaee9","line":266,"range":{"start_line":266,"start_character":49,"end_line":266,"end_character":55},"updated":"2018-07-13 01:10:58.000000000","message":"request","commit_id":"bb3b15bbf02993545d234d827dbb72ca24695e8d"},{"author":{"_account_id":16465,"name":"Kristi Nikolla","email":"knikolla@bu.edu","username":"knikolla"},"change_message_id":"ac33df176a398acec93f19a06af3d69a441e6133","unresolved":false,"context_lines":[{"line_number":283,"context_line":"                        \u0027as unauthorized, this is a programming error and a \u0027"},{"line_number":284,"context_line":"                        \u0027bug should be filed with as much information about \u0027"},{"line_number":285,"context_line":"                        \u0027the request that caused this as possible.\u0027)"},{"line_number":286,"context_line":"            raise exception.Unauthorized("},{"line_number":287,"context_line":"                message\u003d_("},{"line_number":288,"context_line":"                    \u0027Internal RBAC enforcement error, no rule/action name to \u0027"},{"line_number":289,"context_line":"                    \u0027lookup\u0027))"},{"line_number":290,"context_line":""},{"line_number":291,"context_line":"        # Assert we are actually authenticated"},{"line_number":292,"context_line":"        cls._assert_is_authenticated()"}],"source_content_type":"text/x-python","patch_set":23,"id":"5f7c97a3_3138e0d2","line":289,"range":{"start_line":286,"start_character":12,"end_line":289,"end_character":30},"updated":"2018-06-29 20:32:07.000000000","message":"Since this is an application error, shouldn\u0027t this be a 500?","commit_id":"bb3b15bbf02993545d234d827dbb72ca24695e8d"},{"author":{"_account_id":2903,"name":"Morgan Fainberg","email":"morgan.fainberg@gmail.com","username":"mdrnstm"},"change_message_id":"ad7198d057492d101b0d3b477084919af88f737d","unresolved":false,"context_lines":[{"line_number":283,"context_line":"                        \u0027as unauthorized, this is a programming error and a \u0027"},{"line_number":284,"context_line":"                        \u0027bug should be filed with as much information about \u0027"},{"line_number":285,"context_line":"                        \u0027the request that caused this as possible.\u0027)"},{"line_number":286,"context_line":"            raise exception.Unauthorized("},{"line_number":287,"context_line":"                message\u003d_("},{"line_number":288,"context_line":"                    \u0027Internal RBAC enforcement error, no rule/action name to \u0027"},{"line_number":289,"context_line":"                    \u0027lookup\u0027))"},{"line_number":290,"context_line":""},{"line_number":291,"context_line":"        # Assert we are actually authenticated"},{"line_number":292,"context_line":"        cls._assert_is_authenticated()"}],"source_content_type":"text/x-python","patch_set":23,"id":"5f7c97a3_5f19de20","line":289,"range":{"start_line":286,"start_character":12,"end_line":289,"end_character":30},"in_reply_to":"5f7c97a3_3138e0d2","updated":"2018-06-30 15:06:12.000000000","message":"I always err to the side of a 500 should never be an intended error under any circumstances. 500 means we screwed up and some error is leaking to the outside.\n\nThis should probably be a 403 not a 401. [Will correct in a followup]","commit_id":"bb3b15bbf02993545d234d827dbb72ca24695e8d"},{"author":{"_account_id":5046,"name":"Lance Bragstad","email":"lbragstad@redhat.com","username":"ldbragst"},"change_message_id":"e6bc0ca9af3a3c03754e50d79804a1725435ea51","unresolved":false,"context_lines":[{"line_number":283,"context_line":"                        \u0027as unauthorized, this is a programming error and a \u0027"},{"line_number":284,"context_line":"                        \u0027bug should be filed with as much information about \u0027"},{"line_number":285,"context_line":"                        \u0027the request that caused this as possible.\u0027)"},{"line_number":286,"context_line":"            raise exception.Unauthorized("},{"line_number":287,"context_line":"                message\u003d_("},{"line_number":288,"context_line":"                    \u0027Internal RBAC enforcement error, no rule/action name to \u0027"},{"line_number":289,"context_line":"                    \u0027lookup\u0027))"},{"line_number":290,"context_line":""},{"line_number":291,"context_line":"        # Assert we are actually authenticated"},{"line_number":292,"context_line":"        cls._assert_is_authenticated()"}],"source_content_type":"text/x-python","patch_set":23,"id":"5f7c97a3_6285edad","line":289,"range":{"start_line":286,"start_character":12,"end_line":289,"end_character":30},"in_reply_to":"5f7c97a3_5f19de20","updated":"2018-07-03 19:17:10.000000000","message":"This is going to get fixed before anything starts using it though, right? Otherwise we\u0027ll be going from a 401 to a 403?","commit_id":"bb3b15bbf02993545d234d827dbb72ca24695e8d"},{"author":{"_account_id":2903,"name":"Morgan Fainberg","email":"morgan.fainberg@gmail.com","username":"mdrnstm"},"change_message_id":"f220c911eacc5889e74c04ce11a7db3c5e25778d","unresolved":false,"context_lines":[{"line_number":283,"context_line":"                        \u0027as unauthorized, this is a programming error and a \u0027"},{"line_number":284,"context_line":"                        \u0027bug should be filed with as much information about \u0027"},{"line_number":285,"context_line":"                        \u0027the request that caused this as possible.\u0027)"},{"line_number":286,"context_line":"            raise exception.Unauthorized("},{"line_number":287,"context_line":"                message\u003d_("},{"line_number":288,"context_line":"                    \u0027Internal RBAC enforcement error, no rule/action name to \u0027"},{"line_number":289,"context_line":"                    \u0027lookup\u0027))"},{"line_number":290,"context_line":""},{"line_number":291,"context_line":"        # Assert we are actually authenticated"},{"line_number":292,"context_line":"        cls._assert_is_authenticated()"}],"source_content_type":"text/x-python","patch_set":23,"id":"5f7c97a3_05f7625c","line":289,"range":{"start_line":286,"start_character":12,"end_line":289,"end_character":30},"in_reply_to":"5f7c97a3_6285edad","updated":"2018-07-03 20:28:59.000000000","message":"YEs, already fixed in a followup..","commit_id":"bb3b15bbf02993545d234d827dbb72ca24695e8d"}],"keystone/server/flask/common.py":[{"author":{"_account_id":5046,"name":"Lance Bragstad","email":"lbragstad@redhat.com","username":"ldbragst"},"change_message_id":"0ee63260d0019cebc2b4594f7983f03d96562dc3","unresolved":false,"context_lines":[{"line_number":15,"context_line":"import functools"},{"line_number":16,"context_line":""},{"line_number":17,"context_line":"from flask import blueprints"},{"line_number":18,"context_line":"from flask import g"},{"line_number":19,"context_line":"import flask_restful"},{"line_number":20,"context_line":"from oslo_log import log"},{"line_number":21,"context_line":"import six"}],"source_content_type":"text/x-python","patch_set":6,"id":"5f7c97a3_8854d155","line":18,"range":{"start_line":18,"start_character":17,"end_line":18,"end_character":19},"updated":"2018-06-26 21:54:27.000000000","message":"?","commit_id":"3bc20527ffba27cfa63ee5b5dd4ba28b754a7826"},{"author":{"_account_id":5046,"name":"Lance Bragstad","email":"lbragstad@redhat.com","username":"ldbragst"},"change_message_id":"0ee63260d0019cebc2b4594f7983f03d96562dc3","unresolved":false,"context_lines":[{"line_number":199,"context_line":"        self.__after_request_functions_added \u003d True"},{"line_number":200,"context_line":""},{"line_number":201,"context_line":"    @staticmethod"},{"line_number":202,"context_line":"    def unenforced_api(f):"},{"line_number":203,"context_line":"        \"\"\"Decorate a resource method to mark is as an unenforced API."},{"line_number":204,"context_line":""},{"line_number":205,"context_line":"        Explicitly whitelists an API from receiving the enforced API check,"}],"source_content_type":"text/x-python","patch_set":6,"id":"5f7c97a3_280a5d89","line":202,"range":{"start_line":202,"start_character":8,"end_line":202,"end_character":18},"updated":"2018-06-26 21:54:27.000000000","message":"nit: unprotected* might be a bit more clear, but that could just be my personal preference","commit_id":"3bc20527ffba27cfa63ee5b5dd4ba28b754a7826"},{"author":{"_account_id":1916,"name":"Guang Yee","email":"gyee@suse.com","username":"guang-yee"},"change_message_id":"c4321fd48f865034c8487a0557902eba84b0c0b0","unresolved":false,"context_lines":[{"line_number":199,"context_line":"        self.__after_request_functions_added \u003d True"},{"line_number":200,"context_line":""},{"line_number":201,"context_line":"    @staticmethod"},{"line_number":202,"context_line":"    def unenforced_api(f):"},{"line_number":203,"context_line":"        \"\"\"Decorate a resource method to mark is as an unenforced API."},{"line_number":204,"context_line":""},{"line_number":205,"context_line":"        Explicitly whitelists an API from receiving the enforced API check,"}],"source_content_type":"text/x-python","patch_set":22,"id":"5f7c97a3_12f4fdcf","line":202,"updated":"2018-06-27 22:36:52.000000000","message":"How is this one being used? Just curious.","commit_id":"edc2ff74fd54a14a9cd7383f099e6d190c3f6adc"},{"author":{"_account_id":2903,"name":"Morgan Fainberg","email":"morgan.fainberg@gmail.com","username":"mdrnstm"},"change_message_id":"cbd34bc899d11dd845e8b82fad3ec750a3f773b4","unresolved":false,"context_lines":[{"line_number":199,"context_line":"        self.__after_request_functions_added \u003d True"},{"line_number":200,"context_line":""},{"line_number":201,"context_line":"    @staticmethod"},{"line_number":202,"context_line":"    def unenforced_api(f):"},{"line_number":203,"context_line":"        \"\"\"Decorate a resource method to mark is as an unenforced API."},{"line_number":204,"context_line":""},{"line_number":205,"context_line":"        Explicitly whitelists an API from receiving the enforced API check,"}],"source_content_type":"text/x-python","patch_set":22,"id":"5f7c97a3_72b8d174","line":202,"in_reply_to":"5f7c97a3_12f4fdcf","updated":"2018-06-27 22:43:38.000000000","message":"See the following review to this one.","commit_id":"edc2ff74fd54a14a9cd7383f099e6d190c3f6adc"},{"author":{"_account_id":2218,"name":"Adam Young","email":"adam@younglogic.com","username":"ayoung"},"change_message_id":"c7df53344952661120e5513a8b416258fc7b0737","unresolved":false,"context_lines":[{"line_number":202,"context_line":"    def unenforced_api(f):"},{"line_number":203,"context_line":"        \"\"\"Decorate a resource method to mark is as an unenforced API."},{"line_number":204,"context_line":""},{"line_number":205,"context_line":"        Explicitly whitelists an API from receiving the enforced API check,"},{"line_number":206,"context_line":"        specifically for cases such as user self-service password changes (or"},{"line_number":207,"context_line":"        other APIs that must work without already having a token)."},{"line_number":208,"context_line":""}],"source_content_type":"text/x-python","patch_set":22,"id":"5f7c97a3_d75bd71f","line":205,"updated":"2018-06-27 21:21:11.000000000","message":"Not \"whitelists\" but rather \"exempts\"","commit_id":"edc2ff74fd54a14a9cd7383f099e6d190c3f6adc"},{"author":{"_account_id":2903,"name":"Morgan Fainberg","email":"morgan.fainberg@gmail.com","username":"mdrnstm"},"change_message_id":"cbd34bc899d11dd845e8b82fad3ec750a3f773b4","unresolved":false,"context_lines":[{"line_number":202,"context_line":"    def unenforced_api(f):"},{"line_number":203,"context_line":"        \"\"\"Decorate a resource method to mark is as an unenforced API."},{"line_number":204,"context_line":""},{"line_number":205,"context_line":"        Explicitly whitelists an API from receiving the enforced API check,"},{"line_number":206,"context_line":"        specifically for cases such as user self-service password changes (or"},{"line_number":207,"context_line":"        other APIs that must work without already having a token)."},{"line_number":208,"context_line":""}],"source_content_type":"text/x-python","patch_set":22,"id":"5f7c97a3_12addd31","line":205,"in_reply_to":"5f7c97a3_d75bd71f","updated":"2018-06-27 22:43:38.000000000","message":"Done","commit_id":"edc2ff74fd54a14a9cd7383f099e6d190c3f6adc"},{"author":{"_account_id":10873,"name":"Juan Antonio Osorio Robles","email":"jaosorior@redhat.com","username":"ejuaoso"},"change_message_id":"34b7339441e93eedbd1ce75b495c8b19bb63ff64","unresolved":false,"context_lines":[{"line_number":15,"context_line":"import functools"},{"line_number":16,"context_line":""},{"line_number":17,"context_line":"from flask import blueprints"},{"line_number":18,"context_line":"from flask import g"},{"line_number":19,"context_line":"import flask_restful"},{"line_number":20,"context_line":"from oslo_log import log"},{"line_number":21,"context_line":"import six"}],"source_content_type":"text/x-python","patch_set":23,"id":"5f7c97a3_efd38a36","line":18,"updated":"2018-06-28 10:59:04.000000000","message":"nit: could you import flask.g so that\u0027s what\u0027s used in the code? or rename g to something else? such as flask_g or flask_global? It is quite hard to grep for g :/","commit_id":"bb3b15bbf02993545d234d827dbb72ca24695e8d"},{"author":{"_account_id":2903,"name":"Morgan Fainberg","email":"morgan.fainberg@gmail.com","username":"mdrnstm"},"change_message_id":"f220c911eacc5889e74c04ce11a7db3c5e25778d","unresolved":false,"context_lines":[{"line_number":15,"context_line":"import functools"},{"line_number":16,"context_line":""},{"line_number":17,"context_line":"from flask import blueprints"},{"line_number":18,"context_line":"from flask import g"},{"line_number":19,"context_line":"import flask_restful"},{"line_number":20,"context_line":"from oslo_log import log"},{"line_number":21,"context_line":"import six"}],"source_content_type":"text/x-python","patch_set":23,"id":"5f7c97a3_25f4de54","line":18,"in_reply_to":"5f7c97a3_6273ade9","updated":"2018-07-03 20:28:59.000000000","message":"Will fix in a followup.","commit_id":"bb3b15bbf02993545d234d827dbb72ca24695e8d"},{"author":{"_account_id":5046,"name":"Lance Bragstad","email":"lbragstad@redhat.com","username":"ldbragst"},"change_message_id":"e6bc0ca9af3a3c03754e50d79804a1725435ea51","unresolved":false,"context_lines":[{"line_number":15,"context_line":"import functools"},{"line_number":16,"context_line":""},{"line_number":17,"context_line":"from flask import blueprints"},{"line_number":18,"context_line":"from flask import g"},{"line_number":19,"context_line":"import flask_restful"},{"line_number":20,"context_line":"from oslo_log import log"},{"line_number":21,"context_line":"import six"}],"source_content_type":"text/x-python","patch_set":23,"id":"5f7c97a3_6273ade9","line":18,"in_reply_to":"5f7c97a3_a380264b","updated":"2018-07-03 19:17:10.000000000","message":"++ I thought the same thing when I saw random \"g\u0027s\" in the code.. aliasing to flask_global would be awesome.","commit_id":"bb3b15bbf02993545d234d827dbb72ca24695e8d"},{"author":{"_account_id":2903,"name":"Morgan Fainberg","email":"morgan.fainberg@gmail.com","username":"mdrnstm"},"change_message_id":"f5630d86adccf6fe9cba6d3fbaa76d7e0af8e409","unresolved":false,"context_lines":[{"line_number":15,"context_line":"import functools"},{"line_number":16,"context_line":""},{"line_number":17,"context_line":"from flask import blueprints"},{"line_number":18,"context_line":"from flask import g"},{"line_number":19,"context_line":"import flask_restful"},{"line_number":20,"context_line":"from oslo_log import log"},{"line_number":21,"context_line":"import six"}],"source_content_type":"text/x-python","patch_set":23,"id":"5f7c97a3_a380264b","line":18,"in_reply_to":"5f7c97a3_efd38a36","updated":"2018-06-29 18:05:18.000000000","message":"yeah, we can change this to flask.g in a later patch.","commit_id":"bb3b15bbf02993545d234d827dbb72ca24695e8d"},{"author":{"_account_id":5046,"name":"Lance Bragstad","email":"lbragstad@redhat.com","username":"ldbragst"},"change_message_id":"e6bc0ca9af3a3c03754e50d79804a1725435ea51","unresolved":false,"context_lines":[{"line_number":32,"context_line":"    setattr(g, _ENFORCEMENT_CHECK_ATTR, False)"},{"line_number":33,"context_line":""},{"line_number":34,"context_line":""},{"line_number":35,"context_line":"def _assert_rbac_enforcement_called():"},{"line_number":36,"context_line":"    # assert is intended to be used to ensure code during development works"},{"line_number":37,"context_line":"    # as expected, it is fine to be optimized out with `python -O`"},{"line_number":38,"context_line":"    assert getattr(g, _ENFORCEMENT_CHECK_ATTR, False)  # nosec"}],"source_content_type":"text/x-python","patch_set":23,"id":"5f7c97a3_c213a164","line":35,"updated":"2018-07-03 19:17:10.000000000","message":"As we collect more before and after functions, I wouldn\u0027t be opposed to putting them in a separate module to keep from cluttering this one. It should help keep their purpose clear based on their location and naming convention, too.\n\nSomething to do in a follow up I suppose.\n\n\nMaybe in a place like:\n\n  keystone/server/flask/before_check_functions.py\n  keystone/server/flask/after_check_functions.py","commit_id":"bb3b15bbf02993545d234d827dbb72ca24695e8d"},{"author":{"_account_id":2903,"name":"Morgan Fainberg","email":"morgan.fainberg@gmail.com","username":"mdrnstm"},"change_message_id":"f220c911eacc5889e74c04ce11a7db3c5e25778d","unresolved":false,"context_lines":[{"line_number":32,"context_line":"    setattr(g, _ENFORCEMENT_CHECK_ATTR, False)"},{"line_number":33,"context_line":""},{"line_number":34,"context_line":""},{"line_number":35,"context_line":"def _assert_rbac_enforcement_called():"},{"line_number":36,"context_line":"    # assert is intended to be used to ensure code during development works"},{"line_number":37,"context_line":"    # as expected, it is fine to be optimized out with `python -O`"},{"line_number":38,"context_line":"    assert getattr(g, _ENFORCEMENT_CHECK_ATTR, False)  # nosec"}],"source_content_type":"text/x-python","patch_set":23,"id":"5f7c97a3_8598521a","line":35,"in_reply_to":"5f7c97a3_c213a164","updated":"2018-07-03 20:28:59.000000000","message":"I expect there will not be a lot of \"global\" functions, but if we do, sure we can easily break them out.","commit_id":"bb3b15bbf02993545d234d827dbb72ca24695e8d"}],"keystone/tests/unit/common/test_rbac_enforcer.py":[{"author":{"_account_id":2903,"name":"Morgan Fainberg","email":"morgan.fainberg@gmail.com","username":"mdrnstm"},"change_message_id":"311a49840265f8284fb8a8cc7b85ed6bffa00579","unresolved":false,"context_lines":[{"line_number":326,"context_line":"        with self.test_client() as c:"},{"line_number":327,"context_line":"            r \u003d c.post(token_path, json\u003dauth_json, expected_status_code\u003d201)"},{"line_number":328,"context_line":"            token_id \u003d r.headers.get(\u0027X-Subject-Token\u0027)"},{"line_number":329,"context_line":"            # NOTE(morgan): The request has to hit the flask app itself before"},{"line_number":330,"context_line":"            # a context is generated. For now, hitting \u0027/\u0027 for version"},{"line_number":331,"context_line":"            # discovery does everything we need. This should be changed to"},{"line_number":332,"context_line":"            # a test-specific API eventually."},{"line_number":333,"context_line":"            c.get(\u0027%s/argument/%s\u0027 % (self.restful_api_url_prefix,"},{"line_number":334,"context_line":"                                      uuid.uuid4().hex),"},{"line_number":335,"context_line":"                  headers\u003d{\u0027X-Auth-Token\u0027: token_id})"}],"source_content_type":"text/x-python","patch_set":18,"id":"5f7c97a3_50738480","line":332,"range":{"start_line":329,"start_character":0,"end_line":332,"end_character":45},"updated":"2018-06-26 04:01:48.000000000","message":"NIT: Comment no longer applies.","commit_id":"318b067d88586c429e058171e9702f0d60e79d14"},{"author":{"_account_id":5046,"name":"Lance Bragstad","email":"lbragstad@redhat.com","username":"ldbragst"},"change_message_id":"0ee63260d0019cebc2b4594f7983f03d96562dc3","unresolved":false,"context_lines":[{"line_number":194,"context_line":"            c.get(\u0027%s/argument/%s\u0027 % (self.restful_api_url_prefix,"},{"line_number":195,"context_line":"                                      uuid.uuid4().hex),"},{"line_number":196,"context_line":"                  headers\u003d{authorization.AUTH_TOKEN_HEADER: \u0027ADMIN\u0027})"},{"line_number":197,"context_line":"            self.assertTrue(self.enforcer._is_admin())"},{"line_number":198,"context_line":""},{"line_number":199,"context_line":"    def test_enforcer_is_admin_check_without_token(self):"},{"line_number":200,"context_line":"        with self.test_client() as c:"}],"source_content_type":"text/x-python","patch_set":19,"id":"5f7c97a3_041297fd","line":197,"range":{"start_line":197,"start_character":42,"end_line":197,"end_character":51},"updated":"2018-06-26 21:54:27.000000000","message":"nit: is this property solely for the purpose of checking if the legacy shared secret was used?\n\nIf so, I\u0027d love to rename _is_admin() to something more specific in a later patch (is_admin_token_set()).","commit_id":"6c36441df331c8b4a3f54b4ba1d21695ebc7006e"},{"author":{"_account_id":2903,"name":"Morgan Fainberg","email":"morgan.fainberg@gmail.com","username":"mdrnstm"},"change_message_id":"4320d3382203175b305d1291bc400af5cbd223a8","unresolved":false,"context_lines":[{"line_number":194,"context_line":"            c.get(\u0027%s/argument/%s\u0027 % (self.restful_api_url_prefix,"},{"line_number":195,"context_line":"                                      uuid.uuid4().hex),"},{"line_number":196,"context_line":"                  headers\u003d{authorization.AUTH_TOKEN_HEADER: \u0027ADMIN\u0027})"},{"line_number":197,"context_line":"            self.assertTrue(self.enforcer._is_admin())"},{"line_number":198,"context_line":""},{"line_number":199,"context_line":"    def test_enforcer_is_admin_check_without_token(self):"},{"line_number":200,"context_line":"        with self.test_client() as c:"}],"source_content_type":"text/x-python","patch_set":19,"id":"5f7c97a3_a413a3b7","line":197,"range":{"start_line":197,"start_character":42,"end_line":197,"end_character":51},"in_reply_to":"5f7c97a3_041297fd","updated":"2018-06-26 22:01:53.000000000","message":"Yes, that is the sole purpose. Easy enough to rename it.","commit_id":"6c36441df331c8b4a3f54b4ba1d21695ebc7006e"},{"author":{"_account_id":2903,"name":"Morgan Fainberg","email":"morgan.fainberg@gmail.com","username":"mdrnstm"},"change_message_id":"80e2c597df59672d2b7cb2cbb7ccea743dff0cb0","unresolved":false,"context_lines":[{"line_number":194,"context_line":"            c.get(\u0027%s/argument/%s\u0027 % (self.restful_api_url_prefix,"},{"line_number":195,"context_line":"                                      uuid.uuid4().hex),"},{"line_number":196,"context_line":"                  headers\u003d{authorization.AUTH_TOKEN_HEADER: \u0027ADMIN\u0027})"},{"line_number":197,"context_line":"            self.assertTrue(self.enforcer._is_admin())"},{"line_number":198,"context_line":""},{"line_number":199,"context_line":"    def test_enforcer_is_admin_check_without_token(self):"},{"line_number":200,"context_line":"        with self.test_client() as c:"}],"source_content_type":"text/x-python","patch_set":19,"id":"5f7c97a3_1b418364","line":197,"range":{"start_line":197,"start_character":42,"end_line":197,"end_character":51},"in_reply_to":"5f7c97a3_a413a3b7","updated":"2018-06-27 15:42:21.000000000","message":"Done","commit_id":"6c36441df331c8b4a3f54b4ba1d21695ebc7006e"},{"author":{"_account_id":2218,"name":"Adam Young","email":"adam@younglogic.com","username":"ayoung"},"change_message_id":"c7df53344952661120e5513a8b416258fc7b0737","unresolved":false,"context_lines":[{"line_number":87,"context_line":"        # Force a reset on the enforcer to load up new policy rules."},{"line_number":88,"context_line":"        self.enforcer._reset()"},{"line_number":89,"context_line":""},{"line_number":90,"context_line":"    def _setup_dynmic_flask_blueprint_api(self):"},{"line_number":91,"context_line":"        # Create a dynamic flask blueprint with a known prefix"},{"line_number":92,"context_line":"        api \u003d uuid.uuid4().hex"},{"line_number":93,"context_line":"        url_prefix \u003d \u0027/_%s_TEST\u0027 % api"}],"source_content_type":"text/x-python","patch_set":22,"id":"5f7c97a3_37a00bf4","line":90,"updated":"2018-06-27 21:21:11.000000000","message":"dynamic","commit_id":"edc2ff74fd54a14a9cd7383f099e6d190c3f6adc"},{"author":{"_account_id":2903,"name":"Morgan Fainberg","email":"morgan.fainberg@gmail.com","username":"mdrnstm"},"change_message_id":"cbd34bc899d11dd845e8b82fad3ec750a3f773b4","unresolved":false,"context_lines":[{"line_number":87,"context_line":"        # Force a reset on the enforcer to load up new policy rules."},{"line_number":88,"context_line":"        self.enforcer._reset()"},{"line_number":89,"context_line":""},{"line_number":90,"context_line":"    def _setup_dynmic_flask_blueprint_api(self):"},{"line_number":91,"context_line":"        # Create a dynamic flask blueprint with a known prefix"},{"line_number":92,"context_line":"        api \u003d uuid.uuid4().hex"},{"line_number":93,"context_line":"        url_prefix \u003d \u0027/_%s_TEST\u0027 % api"}],"source_content_type":"text/x-python","patch_set":22,"id":"5f7c97a3_f2a38142","line":90,"in_reply_to":"5f7c97a3_37a00bf4","updated":"2018-06-27 22:43:38.000000000","message":"Done","commit_id":"edc2ff74fd54a14a9cd7383f099e6d190c3f6adc"},{"author":{"_account_id":5046,"name":"Lance Bragstad","email":"lbragstad@redhat.com","username":"ldbragst"},"change_message_id":"e6bc0ca9af3a3c03754e50d79804a1725435ea51","unresolved":false,"context_lines":[{"line_number":69,"context_line":"            rules \u003d self._testing_policy_rules()"},{"line_number":70,"context_line":"            enforcer.register_defaults(rules)"},{"line_number":71,"context_line":""},{"line_number":72,"context_line":"        self.useFixture(fixtures.MockPatchObject("},{"line_number":73,"context_line":"            self.enforcer, \u0027register_rules\u0027, register_new_rules))"},{"line_number":74,"context_line":""},{"line_number":75,"context_line":"        # Set the possible actions to our limited list"},{"line_number":76,"context_line":"        original_actions \u003d rbac_enforcer.enforcer._POSSIBLE_TARGET_ACTIONS"}],"source_content_type":"text/x-python","patch_set":23,"id":"5f7c97a3_fd83e053","line":73,"range":{"start_line":72,"start_character":9,"end_line":73,"end_character":65},"updated":"2018-07-03 19:17:10.000000000","message":"Any reason to use the mock instead of just writing your custom test policies to a file? Just thinking if anything changes about how rules are registered, it could affect this (even if it is unlikely).","commit_id":"bb3b15bbf02993545d234d827dbb72ca24695e8d"},{"author":{"_account_id":5046,"name":"Lance Bragstad","email":"lbragstad@redhat.com","username":"ldbragst"},"change_message_id":"3582883e469358dc6f23ce2a1603239d0ea0789b","unresolved":false,"context_lines":[{"line_number":69,"context_line":"            rules \u003d self._testing_policy_rules()"},{"line_number":70,"context_line":"            enforcer.register_defaults(rules)"},{"line_number":71,"context_line":""},{"line_number":72,"context_line":"        self.useFixture(fixtures.MockPatchObject("},{"line_number":73,"context_line":"            self.enforcer, \u0027register_rules\u0027, register_new_rules))"},{"line_number":74,"context_line":""},{"line_number":75,"context_line":"        # Set the possible actions to our limited list"},{"line_number":76,"context_line":"        original_actions \u003d rbac_enforcer.enforcer._POSSIBLE_TARGET_ACTIONS"}],"source_content_type":"text/x-python","patch_set":23,"id":"5f7c97a3_28ea739f","line":73,"range":{"start_line":72,"start_character":9,"end_line":73,"end_character":65},"in_reply_to":"5f7c97a3_450b1a2a","updated":"2018-07-03 21:25:22.000000000","message":"\u003e If how rules get registered changes, I hope we know about it.\n \u003e Things are going to get very broken.\n\nWhich has probably happened once or twice before :)\n\n \u003e \n \u003e The reason for the mock is two-fold. 1) to generate the allowed\n \u003e actions (see other comment on later patch), and 2) to isolate and\n \u003e ensure we are never leaving our examples laying around.\n \u003e \n \u003e If `example:allowed` is ever possible in production, we\u0027ve really\n \u003e messed up.\n\nIs there something about using the mock that allows us to do something we can\u0027t do by putting them in a file? #1 doesn\u0027t really seem like a reason to use a mock, but I could be misunderstanding it. If we use a file fixture, the temp policy file should be cleaned up in setup just like a mock would.","commit_id":"bb3b15bbf02993545d234d827dbb72ca24695e8d"},{"author":{"_account_id":2903,"name":"Morgan Fainberg","email":"morgan.fainberg@gmail.com","username":"mdrnstm"},"change_message_id":"d1bb26310b8f9f9f31f1af01961535ed3c7dbc44","unresolved":false,"context_lines":[{"line_number":69,"context_line":"            rules \u003d self._testing_policy_rules()"},{"line_number":70,"context_line":"            enforcer.register_defaults(rules)"},{"line_number":71,"context_line":""},{"line_number":72,"context_line":"        self.useFixture(fixtures.MockPatchObject("},{"line_number":73,"context_line":"            self.enforcer, \u0027register_rules\u0027, register_new_rules))"},{"line_number":74,"context_line":""},{"line_number":75,"context_line":"        # Set the possible actions to our limited list"},{"line_number":76,"context_line":"        original_actions \u003d rbac_enforcer.enforcer._POSSIBLE_TARGET_ACTIONS"}],"source_content_type":"text/x-python","patch_set":23,"id":"5f7c97a3_450b1a2a","line":73,"range":{"start_line":72,"start_character":9,"end_line":73,"end_character":65},"in_reply_to":"5f7c97a3_fd83e053","updated":"2018-07-03 20:39:51.000000000","message":"If how rules get registered changes, I hope we know about it. Things are going to get very broken.\n\nThe reason for the mock is two-fold. 1) to generate the allowed actions (see other comment on later patch), and 2) to isolate and ensure we are never leaving our examples laying around.\n\nIf `example:allowed` is ever possible in production, we\u0027ve really messed up.","commit_id":"bb3b15bbf02993545d234d827dbb72ca24695e8d"},{"author":{"_account_id":5046,"name":"Lance Bragstad","email":"lbragstad@redhat.com","username":"ldbragst"},"change_message_id":"e6bc0ca9af3a3c03754e50d79804a1725435ea51","unresolved":false,"context_lines":[{"line_number":140,"context_line":"                },"},{"line_number":141,"context_line":"                \u0027scope\u0027: {"},{"line_number":142,"context_line":"                    \u0027project\u0027: {"},{"line_number":143,"context_line":"                        \u0027id\u0027: self.tenant_service[\u0027id\u0027]"},{"line_number":144,"context_line":"                    }"},{"line_number":145,"context_line":"                }"},{"line_number":146,"context_line":"            }"}],"source_content_type":"text/x-python","patch_set":23,"id":"5f7c97a3_ddce24b6","line":143,"range":{"start_line":143,"start_character":35,"end_line":143,"end_character":49},"updated":"2018-07-03 19:17:10.000000000","message":"I don\u0027t expect this to change in this patch, just making the note since I noticed it. \n\nI\u0027d love for all of this self.\u003ctest_data\u003e stuff to go away in favor of just using what we\u0027re given with bootstrap. IMHO it\u0027s just another mental mapping I have to maintain to understand tests (e.g. does user X have a specific role assignment on self.tenant_service?). I like to get to the point where we just have bootstrap and everything else needed outside of that is setup in setUpClass() methods.","commit_id":"bb3b15bbf02993545d234d827dbb72ca24695e8d"},{"author":{"_account_id":16465,"name":"Kristi Nikolla","email":"knikolla@bu.edu","username":"knikolla"},"change_message_id":"ac33df176a398acec93f19a06af3d69a441e6133","unresolved":false,"context_lines":[{"line_number":176,"context_line":"            policy.RuleDefault("},{"line_number":177,"context_line":"                name\u003d\u0027example:denied\u0027,"},{"line_number":178,"context_line":"                check_str\u003d\u0027false:false\u0027,"},{"line_number":179,"context_line":"                scope_types\u003d[\u0027project\u0027],"},{"line_number":180,"context_line":"            ),"},{"line_number":181,"context_line":"        ]"},{"line_number":182,"context_line":"        return test_policy_rules"}],"source_content_type":"text/x-python","patch_set":23,"id":"5f7c97a3_c6e8d016","line":179,"range":{"start_line":179,"start_character":30,"end_line":179,"end_character":37},"updated":"2018-06-29 20:32:07.000000000","message":"Do we also eventually want some rules with system scope?","commit_id":"bb3b15bbf02993545d234d827dbb72ca24695e8d"},{"author":{"_account_id":2903,"name":"Morgan Fainberg","email":"morgan.fainberg@gmail.com","username":"mdrnstm"},"change_message_id":"ad7198d057492d101b0d3b477084919af88f737d","unresolved":false,"context_lines":[{"line_number":176,"context_line":"            policy.RuleDefault("},{"line_number":177,"context_line":"                name\u003d\u0027example:denied\u0027,"},{"line_number":178,"context_line":"                check_str\u003d\u0027false:false\u0027,"},{"line_number":179,"context_line":"                scope_types\u003d[\u0027project\u0027],"},{"line_number":180,"context_line":"            ),"},{"line_number":181,"context_line":"        ]"},{"line_number":182,"context_line":"        return test_policy_rules"}],"source_content_type":"text/x-python","patch_set":23,"id":"5f7c97a3_ff178aed","line":179,"range":{"start_line":179,"start_character":30,"end_line":179,"end_character":37},"in_reply_to":"5f7c97a3_c6e8d016","updated":"2018-06-30 15:06:12.000000000","message":"We can add them. Lets do that in a followup.","commit_id":"bb3b15bbf02993545d234d827dbb72ca24695e8d"},{"author":{"_account_id":16465,"name":"Kristi Nikolla","email":"knikolla@bu.edu","username":"knikolla"},"change_message_id":"ac33df176a398acec93f19a06af3d69a441e6133","unresolved":false,"context_lines":[{"line_number":335,"context_line":"                extracted_creds)"},{"line_number":336,"context_line":""},{"line_number":337,"context_line":"    def test_extract_member_target_data_inferred(self):"},{"line_number":338,"context_line":"        self.restful_api_resource.member_name \u003d \u0027argument\u0027"},{"line_number":339,"context_line":"        member_from_driver \u003d self.restful_api_resource.get"},{"line_number":340,"context_line":"        self.restful_api_resource.get_member_from_driver \u003d member_from_driver"},{"line_number":341,"context_line":""},{"line_number":342,"context_line":"        argument_id \u003d uuid.uuid4().hex"},{"line_number":343,"context_line":""}],"source_content_type":"text/x-python","patch_set":23,"id":"5f7c97a3_c6bbf0e1","line":340,"range":{"start_line":338,"start_character":8,"end_line":340,"end_character":77},"updated":"2018-06-29 20:32:07.000000000","message":"I would love a note about what\u0027s happening here.","commit_id":"bb3b15bbf02993545d234d827dbb72ca24695e8d"},{"author":{"_account_id":2903,"name":"Morgan Fainberg","email":"morgan.fainberg@gmail.com","username":"mdrnstm"},"change_message_id":"ad7198d057492d101b0d3b477084919af88f737d","unresolved":false,"context_lines":[{"line_number":335,"context_line":"                extracted_creds)"},{"line_number":336,"context_line":""},{"line_number":337,"context_line":"    def test_extract_member_target_data_inferred(self):"},{"line_number":338,"context_line":"        self.restful_api_resource.member_name \u003d \u0027argument\u0027"},{"line_number":339,"context_line":"        member_from_driver \u003d self.restful_api_resource.get"},{"line_number":340,"context_line":"        self.restful_api_resource.get_member_from_driver \u003d member_from_driver"},{"line_number":341,"context_line":""},{"line_number":342,"context_line":"        argument_id \u003d uuid.uuid4().hex"},{"line_number":343,"context_line":""}],"source_content_type":"text/x-python","patch_set":23,"id":"5f7c97a3_1f136603","line":340,"range":{"start_line":338,"start_character":8,"end_line":340,"end_character":77},"in_reply_to":"5f7c97a3_c6bbf0e1","updated":"2018-06-30 15:06:12.000000000","message":"Ok Will add in a followup.","commit_id":"bb3b15bbf02993545d234d827dbb72ca24695e8d"}]}
