)]}'
{"keystone/api/_shared/authentication.py":[{"author":{"_account_id":10420,"name":"Adrian Turjak","email":"devs+openstack@uncaught-exceptions.com","username":"adriant"},"change_message_id":"7ea9aa5e40081ca27bfc0e2be63b12e6f54b5835","unresolved":false,"context_lines":[{"line_number":199,"context_line":"                receipt_id)"},{"line_number":200,"context_line":""},{"line_number":201,"context_line":"            if auth_context[\u0027user_id\u0027] !\u003d receipt.user_id:"},{"line_number":202,"context_line":"                raise exception.AuthReceiptUserMismatch("},{"line_number":203,"context_line":"                    user_id\u003dauth_context[\u0027user_id\u0027],"},{"line_number":204,"context_line":"                    receipt_user_id\u003dreceipt.user_id)"},{"line_number":205,"context_line":"        else:"}],"source_content_type":"text/x-python","patch_set":1,"id":"3f79a3b5_d4be7c00","line":202,"range":{"start_line":202,"start_character":32,"end_line":202,"end_character":55},"updated":"2018-10-17 04:27:00.000000000","message":"Morgan wrote last time:\n\"Be sure this is not exposed (a plain unauthorized: bad username/password/receipt, non specific as to which) outside of debug mode.\"\n\nI should fix this and make sure that is the case.","commit_id":"2f5a50a44370556d48bc6b215b4814d32446b9fb"},{"author":{"_account_id":2903,"name":"Morgan Fainberg","email":"morgan.fainberg@gmail.com","username":"mdrnstm"},"change_message_id":"faf9e8b05d91e5f803f765c1d64d405d14058b53","unresolved":false,"context_lines":[{"line_number":192,"context_line":"        )"},{"line_number":193,"context_line":"        trust_id \u003d trust.get(\u0027id\u0027) if trust else None"},{"line_number":194,"context_line":""},{"line_number":195,"context_line":"        receipt_id \u003d flask.request.headers.get("},{"line_number":196,"context_line":"            authorization.AUTH_RECEIPT_HEADER, None)"},{"line_number":197,"context_line":"        if receipt_id:"},{"line_number":198,"context_line":"            receipt \u003d PROVIDERS.receipt_provider_api.validate_receipt("},{"line_number":199,"context_line":"                receipt_id)"},{"line_number":200,"context_line":""},{"line_number":201,"context_line":"            if auth_context[\u0027user_id\u0027] !\u003d receipt.user_id:"},{"line_number":202,"context_line":"                raise exception.AuthReceiptUserMismatch("},{"line_number":203,"context_line":"                    user_id\u003dauth_context[\u0027user_id\u0027],"},{"line_number":204,"context_line":"                    receipt_user_id\u003dreceipt.user_id)"},{"line_number":205,"context_line":"        else:"},{"line_number":206,"context_line":"            receipt \u003d None"},{"line_number":207,"context_line":""},{"line_number":208,"context_line":"        # NOTE(notmorgan): only methods that actually run and succeed will"},{"line_number":209,"context_line":"        # be in the auth_context[\u0027method_names\u0027] list. Do not blindly take"}],"source_content_type":"text/x-python","patch_set":3,"id":"3f79a3b5_d07096de","line":206,"range":{"start_line":195,"start_character":0,"end_line":206,"end_character":26},"updated":"2018-10-18 23:17:51.000000000","message":"Suggest extracting this to it\u0027s own function, just for ease of maintenance.","commit_id":"1514eaf699bfdd468229a80cbb89bda75ba20b30"},{"author":{"_account_id":10420,"name":"Adrian Turjak","email":"devs+openstack@uncaught-exceptions.com","username":"adriant"},"change_message_id":"4fdd97b0e4b80de8385dcae32396aa8d86bf242f","unresolved":false,"context_lines":[{"line_number":192,"context_line":"        )"},{"line_number":193,"context_line":"        trust_id \u003d trust.get(\u0027id\u0027) if trust else None"},{"line_number":194,"context_line":""},{"line_number":195,"context_line":"        receipt_id \u003d flask.request.headers.get("},{"line_number":196,"context_line":"            authorization.AUTH_RECEIPT_HEADER, None)"},{"line_number":197,"context_line":"        if receipt_id:"},{"line_number":198,"context_line":"            receipt \u003d PROVIDERS.receipt_provider_api.validate_receipt("},{"line_number":199,"context_line":"                receipt_id)"},{"line_number":200,"context_line":""},{"line_number":201,"context_line":"            if auth_context[\u0027user_id\u0027] !\u003d receipt.user_id:"},{"line_number":202,"context_line":"                raise exception.AuthReceiptUserMismatch("},{"line_number":203,"context_line":"                    user_id\u003dauth_context[\u0027user_id\u0027],"},{"line_number":204,"context_line":"                    receipt_user_id\u003dreceipt.user_id)"},{"line_number":205,"context_line":"        else:"},{"line_number":206,"context_line":"            receipt \u003d None"},{"line_number":207,"context_line":""},{"line_number":208,"context_line":"        # NOTE(notmorgan): only methods that actually run and succeed will"},{"line_number":209,"context_line":"        # be in the auth_context[\u0027method_names\u0027] list. Do not blindly take"}],"source_content_type":"text/x-python","patch_set":3,"id":"3f79a3b5_52c0ce2b","line":206,"range":{"start_line":195,"start_character":0,"end_line":206,"end_character":26},"in_reply_to":"3f79a3b5_d07096de","updated":"2018-10-23 02:01:17.000000000","message":"Done","commit_id":"1514eaf699bfdd468229a80cbb89bda75ba20b30"},{"author":{"_account_id":2903,"name":"Morgan Fainberg","email":"morgan.fainberg@gmail.com","username":"mdrnstm"},"change_message_id":"faf9e8b05d91e5f803f765c1d64d405d14058b53","unresolved":false,"context_lines":[{"line_number":209,"context_line":"        # be in the auth_context[\u0027method_names\u0027] list. Do not blindly take"},{"line_number":210,"context_line":"        # the values from auth_info, look at the authoritative values. Make"},{"line_number":211,"context_line":"        # sure the set is unique."},{"line_number":212,"context_line":"        if receipt:"},{"line_number":213,"context_line":"            method_names_set \u003d set("},{"line_number":214,"context_line":"                auth_context.get(\u0027method_names\u0027, []) + receipt.methods)"},{"line_number":215,"context_line":"        else:"},{"line_number":216,"context_line":"            method_names_set \u003d set(auth_context.get(\u0027method_names\u0027, []))"},{"line_number":217,"context_line":"        method_names \u003d list(method_names_set)"},{"line_number":218,"context_line":""}],"source_content_type":"text/x-python","patch_set":3,"id":"3f79a3b5_907a1eb9","line":215,"range":{"start_line":212,"start_character":0,"end_line":215,"end_character":13},"updated":"2018-10-18 23:17:51.000000000","message":"Please add to the above NOTE indicating receipt methods are included.","commit_id":"1514eaf699bfdd468229a80cbb89bda75ba20b30"},{"author":{"_account_id":10420,"name":"Adrian Turjak","email":"devs+openstack@uncaught-exceptions.com","username":"adriant"},"change_message_id":"4fdd97b0e4b80de8385dcae32396aa8d86bf242f","unresolved":false,"context_lines":[{"line_number":209,"context_line":"        # be in the auth_context[\u0027method_names\u0027] list. Do not blindly take"},{"line_number":210,"context_line":"        # the values from auth_info, look at the authoritative values. Make"},{"line_number":211,"context_line":"        # sure the set is unique."},{"line_number":212,"context_line":"        if receipt:"},{"line_number":213,"context_line":"            method_names_set \u003d set("},{"line_number":214,"context_line":"                auth_context.get(\u0027method_names\u0027, []) + receipt.methods)"},{"line_number":215,"context_line":"        else:"},{"line_number":216,"context_line":"            method_names_set \u003d set(auth_context.get(\u0027method_names\u0027, []))"},{"line_number":217,"context_line":"        method_names \u003d list(method_names_set)"},{"line_number":218,"context_line":""}],"source_content_type":"text/x-python","patch_set":3,"id":"3f79a3b5_72bb8abd","line":215,"range":{"start_line":212,"start_character":0,"end_line":215,"end_character":13},"in_reply_to":"3f79a3b5_907a1eb9","updated":"2018-10-23 02:01:17.000000000","message":"Done","commit_id":"1514eaf699bfdd468229a80cbb89bda75ba20b30"},{"author":{"_account_id":2903,"name":"Morgan Fainberg","email":"morgan.fainberg@gmail.com","username":"mdrnstm"},"change_message_id":"faf9e8b05d91e5f803f765c1d64d405d14058b53","unresolved":false,"context_lines":[{"line_number":226,"context_line":"                auth_context[\u0027user_id\u0027], method_names_set):"},{"line_number":227,"context_line":"            raise exception.InsufficientAuthMethods("},{"line_number":228,"context_line":"                user_id\u003dauth_context[\u0027user_id\u0027],"},{"line_number":229,"context_line":"                methods\u003dmethod_names)"},{"line_number":230,"context_line":""},{"line_number":231,"context_line":"        expires_at \u003d auth_context.get(\u0027expires_at\u0027)"},{"line_number":232,"context_line":"        token_audit_id \u003d auth_context.get(\u0027audit_id\u0027)"}],"source_content_type":"text/x-python","patch_set":3,"id":"3f79a3b5_10404e5f","line":229,"range":{"start_line":229,"start_character":16,"end_line":229,"end_character":37},"updated":"2018-10-18 23:17:51.000000000","message":"This change looks to be materially changing the log message, was this intended?","commit_id":"1514eaf699bfdd468229a80cbb89bda75ba20b30"},{"author":{"_account_id":10420,"name":"Adrian Turjak","email":"devs+openstack@uncaught-exceptions.com","username":"adriant"},"change_message_id":"4fdd97b0e4b80de8385dcae32396aa8d86bf242f","unresolved":false,"context_lines":[{"line_number":226,"context_line":"                auth_context[\u0027user_id\u0027], method_names_set):"},{"line_number":227,"context_line":"            raise exception.InsufficientAuthMethods("},{"line_number":228,"context_line":"                user_id\u003dauth_context[\u0027user_id\u0027],"},{"line_number":229,"context_line":"                methods\u003dmethod_names)"},{"line_number":230,"context_line":""},{"line_number":231,"context_line":"        expires_at \u003d auth_context.get(\u0027expires_at\u0027)"},{"line_number":232,"context_line":"        token_audit_id \u003d auth_context.get(\u0027audit_id\u0027)"}],"source_content_type":"text/x-python","patch_set":3,"id":"3f79a3b5_f2e47ae1","line":229,"range":{"start_line":229,"start_character":16,"end_line":229,"end_character":37},"in_reply_to":"3f79a3b5_10404e5f","updated":"2018-10-23 02:01:17.000000000","message":"This needs to happen so I can pass the actual valid auth methods up to an error handler which will build a receipt from them.\n\nThis error is now effectively internal only and will never be seen by a user.","commit_id":"1514eaf699bfdd468229a80cbb89bda75ba20b30"}],"keystone/api/auth.py":[{"author":{"_account_id":2903,"name":"Morgan Fainberg","email":"morgan.fainberg@gmail.com","username":"mdrnstm"},"change_message_id":"faf9e8b05d91e5f803f765c1d64d405d14058b53","unresolved":false,"context_lines":[{"line_number":313,"context_line":"        include_catalog \u003d \u0027nocatalog\u0027 not in flask.request.args"},{"line_number":314,"context_line":"        auth_data \u003d self.request_body_json.get(\u0027auth\u0027)"},{"line_number":315,"context_line":"        auth_schema.validate_issue_token_auth(auth_data)"},{"line_number":316,"context_line":"        try:"},{"line_number":317,"context_line":"            token \u003d authentication.authenticate_for_token(auth_data)"},{"line_number":318,"context_line":"            resp_data \u003d render_token.render_token_response_from_model("},{"line_number":319,"context_line":"                token, include_catalog\u003dinclude_catalog"},{"line_number":320,"context_line":"            )"},{"line_number":321,"context_line":"            resp_body \u003d jsonutils.dumps(resp_data)"},{"line_number":322,"context_line":"            response \u003d flask.make_response(resp_body, http_client.CREATED)"},{"line_number":323,"context_line":"            response.headers[authorization.SUBJECT_TOKEN_HEADER] \u003d token.id"},{"line_number":324,"context_line":"            response.headers[\u0027Content-Type\u0027] \u003d \u0027application/json\u0027"},{"line_number":325,"context_line":"            return response"},{"line_number":326,"context_line":"        except exception.InsufficientAuthMethods as mfa_error:"},{"line_number":327,"context_line":"            receipt \u003d PROVIDERS.receipt_provider_api. \\"},{"line_number":328,"context_line":"                issue_receipt(mfa_error.user_id, mfa_error.methods)"},{"line_number":329,"context_line":"            resp_data \u003d render_receipt.render_receipt_response_from_model("},{"line_number":330,"context_line":"                receipt)"},{"line_number":331,"context_line":"            resp_body \u003d jsonutils.dumps(resp_data)"},{"line_number":332,"context_line":"            response \u003d flask.make_response(resp_body, http_client.UNAUTHORIZED)"},{"line_number":333,"context_line":"            response.headers[authorization.AUTH_RECEIPT_HEADER] \u003d receipt.id"},{"line_number":334,"context_line":"            response.headers[\u0027Content-Type\u0027] \u003d \u0027application/json\u0027"},{"line_number":335,"context_line":"            return response"},{"line_number":336,"context_line":""},{"line_number":337,"context_line":"    def delete(self):"},{"line_number":338,"context_line":"        \"\"\"Revoke a token."}],"source_content_type":"text/x-python","patch_set":3,"id":"3f79a3b5_732d0c44","line":335,"range":{"start_line":316,"start_character":8,"end_line":335,"end_character":27},"updated":"2018-10-18 23:17:51.000000000","message":"Embed this additional information for the response in the flask error handler like we do for Unauthorized (once https://review.openstack.org/#/c/609796/ merges)","commit_id":"1514eaf699bfdd468229a80cbb89bda75ba20b30"},{"author":{"_account_id":10420,"name":"Adrian Turjak","email":"devs+openstack@uncaught-exceptions.com","username":"adriant"},"change_message_id":"4fdd97b0e4b80de8385dcae32396aa8d86bf242f","unresolved":false,"context_lines":[{"line_number":313,"context_line":"        include_catalog \u003d \u0027nocatalog\u0027 not in flask.request.args"},{"line_number":314,"context_line":"        auth_data \u003d self.request_body_json.get(\u0027auth\u0027)"},{"line_number":315,"context_line":"        auth_schema.validate_issue_token_auth(auth_data)"},{"line_number":316,"context_line":"        try:"},{"line_number":317,"context_line":"            token \u003d authentication.authenticate_for_token(auth_data)"},{"line_number":318,"context_line":"            resp_data \u003d render_token.render_token_response_from_model("},{"line_number":319,"context_line":"                token, include_catalog\u003dinclude_catalog"},{"line_number":320,"context_line":"            )"},{"line_number":321,"context_line":"            resp_body \u003d jsonutils.dumps(resp_data)"},{"line_number":322,"context_line":"            response \u003d flask.make_response(resp_body, http_client.CREATED)"},{"line_number":323,"context_line":"            response.headers[authorization.SUBJECT_TOKEN_HEADER] \u003d token.id"},{"line_number":324,"context_line":"            response.headers[\u0027Content-Type\u0027] \u003d \u0027application/json\u0027"},{"line_number":325,"context_line":"            return response"},{"line_number":326,"context_line":"        except exception.InsufficientAuthMethods as mfa_error:"},{"line_number":327,"context_line":"            receipt \u003d PROVIDERS.receipt_provider_api. \\"},{"line_number":328,"context_line":"                issue_receipt(mfa_error.user_id, mfa_error.methods)"},{"line_number":329,"context_line":"            resp_data \u003d render_receipt.render_receipt_response_from_model("},{"line_number":330,"context_line":"                receipt)"},{"line_number":331,"context_line":"            resp_body \u003d jsonutils.dumps(resp_data)"},{"line_number":332,"context_line":"            response \u003d flask.make_response(resp_body, http_client.UNAUTHORIZED)"},{"line_number":333,"context_line":"            response.headers[authorization.AUTH_RECEIPT_HEADER] \u003d receipt.id"},{"line_number":334,"context_line":"            response.headers[\u0027Content-Type\u0027] \u003d \u0027application/json\u0027"},{"line_number":335,"context_line":"            return response"},{"line_number":336,"context_line":""},{"line_number":337,"context_line":"    def delete(self):"},{"line_number":338,"context_line":"        \"\"\"Revoke a token."}],"source_content_type":"text/x-python","patch_set":3,"id":"3f79a3b5_92cbc649","line":335,"range":{"start_line":316,"start_character":8,"end_line":335,"end_character":27},"in_reply_to":"3f79a3b5_732d0c44","updated":"2018-10-23 02:01:17.000000000","message":"Done","commit_id":"1514eaf699bfdd468229a80cbb89bda75ba20b30"},{"author":{"_account_id":10420,"name":"Adrian Turjak","email":"devs+openstack@uncaught-exceptions.com","username":"adriant"},"change_message_id":"00b732845bfba88541df6f7a41320d5f4febaf09","unresolved":false,"context_lines":[{"line_number":318,"context_line":"        )"},{"line_number":319,"context_line":"        resp_body \u003d jsonutils.dumps(resp_data)"},{"line_number":320,"context_line":"        response \u003d flask.make_response(resp_body, http_client.CREATED)"},{"line_number":321,"context_line":"        response.headers[authorization.SUBJECT_TOKEN_HEADER] \u003d token.id"},{"line_number":322,"context_line":"        response.headers[\u0027Content-Type\u0027] \u003d \u0027application/json\u0027"},{"line_number":323,"context_line":"        return response"},{"line_number":324,"context_line":""}],"source_content_type":"text/x-python","patch_set":6,"id":"3f79a3b5_1215764c","line":321,"range":{"start_line":321,"start_character":25,"end_line":321,"end_character":59},"updated":"2018-10-23 02:11:56.000000000","message":"sort of unrelated change, but one that should be done somewhere anyway.","commit_id":"c7fbb0c00ece2698d052f40ad5a2b3b623e246bf"}],"keystone/cmd/cli.py":[{"author":{"_account_id":2903,"name":"Morgan Fainberg","email":"morgan.fainberg@gmail.com","username":"mdrnstm"},"change_message_id":"faf9e8b05d91e5f803f765c1d64d405d14058b53","unresolved":false,"context_lines":[{"line_number":408,"context_line":"            futils.initialize_key_repository("},{"line_number":409,"context_line":"                keystone_user_id, keystone_group_id)"},{"line_number":410,"context_line":""},{"line_number":411,"context_line":"        # WARNING(adriant): If the directories are the same, \u0027max_active_keys\u0027"},{"line_number":412,"context_line":"        # is ignored from fernet_receipts in favor of fernet_tokens to"},{"line_number":413,"context_line":"        # avoid a potential mismatch. Only if the directories are different"},{"line_number":414,"context_line":"        # do we create a different one for receipts, and then respect"},{"line_number":415,"context_line":"        # \u0027max_active_keys\u0027 for receipts."},{"line_number":416,"context_line":"        if (CONF.fernet_tokens.key_repository !\u003d"},{"line_number":417,"context_line":"                CONF.fernet_receipts.key_repository):"},{"line_number":418,"context_line":"            futils \u003d fernet_utils.FernetUtils("}],"source_content_type":"text/x-python","patch_set":3,"id":"3f79a3b5_7062e217","line":415,"range":{"start_line":411,"start_character":0,"end_line":415,"end_character":41},"updated":"2018-10-18 23:17:51.000000000","message":"Please emit an info/warning in this case. Thanks!","commit_id":"1514eaf699bfdd468229a80cbb89bda75ba20b30"},{"author":{"_account_id":10420,"name":"Adrian Turjak","email":"devs+openstack@uncaught-exceptions.com","username":"adriant"},"change_message_id":"00b732845bfba88541df6f7a41320d5f4febaf09","unresolved":false,"context_lines":[{"line_number":408,"context_line":"            futils.initialize_key_repository("},{"line_number":409,"context_line":"                keystone_user_id, keystone_group_id)"},{"line_number":410,"context_line":""},{"line_number":411,"context_line":"        # WARNING(adriant): If the directories are the same, \u0027max_active_keys\u0027"},{"line_number":412,"context_line":"        # is ignored from fernet_receipts in favor of fernet_tokens to"},{"line_number":413,"context_line":"        # avoid a potential mismatch. Only if the directories are different"},{"line_number":414,"context_line":"        # do we create a different one for receipts, and then respect"},{"line_number":415,"context_line":"        # \u0027max_active_keys\u0027 for receipts."},{"line_number":416,"context_line":"        if (CONF.fernet_tokens.key_repository !\u003d"},{"line_number":417,"context_line":"                CONF.fernet_receipts.key_repository):"},{"line_number":418,"context_line":"            futils \u003d fernet_utils.FernetUtils("}],"source_content_type":"text/x-python","patch_set":6,"id":"3f79a3b5_52020e0e","line":415,"range":{"start_line":411,"start_character":8,"end_line":415,"end_character":41},"updated":"2018-10-23 02:11:56.000000000","message":"make this log \u0027info\u0027 if the directories match.","commit_id":"c7fbb0c00ece2698d052f40ad5a2b3b623e246bf"},{"author":{"_account_id":8482,"name":"Colleen Murphy","email":"colleen@gazlene.net","username":"krinkle"},"change_message_id":"4d8f332bfdbf58cb4ae1ac310dc8a1fb7e64a31f","unresolved":false,"context_lines":[{"line_number":408,"context_line":"            futils.initialize_key_repository("},{"line_number":409,"context_line":"                keystone_user_id, keystone_group_id)"},{"line_number":410,"context_line":""},{"line_number":411,"context_line":"        # WARNING(adriant): If the directories are the same, \u0027max_active_keys\u0027"},{"line_number":412,"context_line":"        # is ignored from fernet_receipts in favor of fernet_tokens to"},{"line_number":413,"context_line":"        # avoid a potential mismatch. Only if the directories are different"},{"line_number":414,"context_line":"        # do we create a different one for receipts, and then respect"},{"line_number":415,"context_line":"        # \u0027max_active_keys\u0027 for receipts."},{"line_number":416,"context_line":"        if (CONF.fernet_tokens.key_repository !\u003d"},{"line_number":417,"context_line":"                CONF.fernet_receipts.key_repository):"},{"line_number":418,"context_line":"            futils \u003d fernet_utils.FernetUtils("}],"source_content_type":"text/x-python","patch_set":6,"id":"3f79a3b5_c09048f6","line":415,"range":{"start_line":411,"start_character":8,"end_line":415,"end_character":41},"in_reply_to":"3f79a3b5_52020e0e","updated":"2018-10-25 13:09:36.000000000","message":"Maybe it could compare both key_repository and max_active_keys of both sections and exit 1 if the combination doesn\u0027t make sense?","commit_id":"c7fbb0c00ece2698d052f40ad5a2b3b623e246bf"},{"author":{"_account_id":10420,"name":"Adrian Turjak","email":"devs+openstack@uncaught-exceptions.com","username":"adriant"},"change_message_id":"ce4f2d0e954b23c0ed8865a1c62363e5dbb8e54f","unresolved":false,"context_lines":[{"line_number":408,"context_line":"            futils.initialize_key_repository("},{"line_number":409,"context_line":"                keystone_user_id, keystone_group_id)"},{"line_number":410,"context_line":""},{"line_number":411,"context_line":"        # WARNING(adriant): If the directories are the same, \u0027max_active_keys\u0027"},{"line_number":412,"context_line":"        # is ignored from fernet_receipts in favor of fernet_tokens to"},{"line_number":413,"context_line":"        # avoid a potential mismatch. Only if the directories are different"},{"line_number":414,"context_line":"        # do we create a different one for receipts, and then respect"},{"line_number":415,"context_line":"        # \u0027max_active_keys\u0027 for receipts."},{"line_number":416,"context_line":"        if (CONF.fernet_tokens.key_repository !\u003d"},{"line_number":417,"context_line":"                CONF.fernet_receipts.key_repository):"},{"line_number":418,"context_line":"            futils \u003d fernet_utils.FernetUtils("}],"source_content_type":"text/x-python","patch_set":6,"id":"3f79a3b5_35e92a18","line":415,"range":{"start_line":411,"start_character":8,"end_line":415,"end_character":41},"in_reply_to":"3f79a3b5_c09048f6","updated":"2018-10-29 01:14:08.000000000","message":"We probably still want it to print/log something.\n\nIf triggered directly from the cli by a human won\u0027t an exit 1 still look like a silent success?","commit_id":"c7fbb0c00ece2698d052f40ad5a2b3b623e246bf"},{"author":{"_account_id":8482,"name":"Colleen Murphy","email":"colleen@gazlene.net","username":"krinkle"},"change_message_id":"4d8f332bfdbf58cb4ae1ac310dc8a1fb7e64a31f","unresolved":false,"context_lines":[{"line_number":541,"context_line":""},{"line_number":542,"context_line":"    \"\"\""},{"line_number":543,"context_line":""},{"line_number":544,"context_line":"    name \u003d \u0027receipt_rotate\u0027"},{"line_number":545,"context_line":""},{"line_number":546,"context_line":"    @classmethod"},{"line_number":547,"context_line":"    def main(cls):"}],"source_content_type":"text/x-python","patch_set":6,"id":"3f79a3b5_408438b2","line":544,"range":{"start_line":544,"start_character":12,"end_line":544,"end_character":26},"updated":"2018-10-25 13:09:36.000000000","message":"setup","commit_id":"c7fbb0c00ece2698d052f40ad5a2b3b623e246bf"},{"author":{"_account_id":8482,"name":"Colleen Murphy","email":"colleen@gazlene.net","username":"krinkle"},"change_message_id":"4d8f332bfdbf58cb4ae1ac310dc8a1fb7e64a31f","unresolved":false,"context_lines":[{"line_number":589,"context_line":"        keystone_user_id, keystone_group_id \u003d cls.get_user_group()"},{"line_number":590,"context_line":"        if futils.validate_key_repository(requires_write\u003dTrue):"},{"line_number":591,"context_line":"            futils.rotate_keys(keystone_user_id, keystone_group_id)"},{"line_number":592,"context_line":""},{"line_number":593,"context_line":""},{"line_number":594,"context_line":"class CredentialSetup(BasePermissionsSetup):"},{"line_number":595,"context_line":"    \"\"\"Setup a Fernet key repository for credential encryption."}],"source_content_type":"text/x-python","patch_set":6,"id":"3f79a3b5_60aa941a","line":592,"updated":"2018-10-25 13:09:36.000000000","message":"So you\u0027ve added this functionality directly to fernet_setup/rotate but you\u0027re also adding a new command for it? I think I would prefer to choose one or the other.","commit_id":"c7fbb0c00ece2698d052f40ad5a2b3b623e246bf"},{"author":{"_account_id":8482,"name":"Colleen Murphy","email":"colleen@gazlene.net","username":"krinkle"},"change_message_id":"bafb6d38e36cf4d2ba088845100e8321392aebaa","unresolved":false,"context_lines":[{"line_number":550,"context_line":""},{"line_number":551,"context_line":"    \"\"\""},{"line_number":552,"context_line":""},{"line_number":553,"context_line":"    name \u003d \u0027receipt_rotate\u0027"},{"line_number":554,"context_line":""},{"line_number":555,"context_line":"    @classmethod"},{"line_number":556,"context_line":"    def main(cls):"}],"source_content_type":"text/x-python","patch_set":10,"id":"3f79a3b5_857c4575","line":553,"range":{"start_line":553,"start_character":12,"end_line":553,"end_character":26},"updated":"2018-10-30 21:31:41.000000000","message":"This is still wrong","commit_id":"5196e47954f3135741f0be17e10181631f2e0d36"},{"author":{"_account_id":10420,"name":"Adrian Turjak","email":"devs+openstack@uncaught-exceptions.com","username":"adriant"},"change_message_id":"3cc3f356eada2d992dd09e88a1993f54fe166039","unresolved":false,"context_lines":[{"line_number":550,"context_line":""},{"line_number":551,"context_line":"    \"\"\""},{"line_number":552,"context_line":""},{"line_number":553,"context_line":"    name \u003d \u0027receipt_rotate\u0027"},{"line_number":554,"context_line":""},{"line_number":555,"context_line":"    @classmethod"},{"line_number":556,"context_line":"    def main(cls):"}],"source_content_type":"text/x-python","patch_set":10,"id":"3f79a3b5_a087ef11","line":553,"range":{"start_line":553,"start_character":12,"end_line":553,"end_character":26},"in_reply_to":"3f79a3b5_857c4575","updated":"2018-10-30 22:35:17.000000000","message":"bah, yep, will fix.","commit_id":"5196e47954f3135741f0be17e10181631f2e0d36"},{"author":{"_account_id":8482,"name":"Colleen Murphy","email":"colleen@gazlene.net","username":"krinkle"},"change_message_id":"bafb6d38e36cf4d2ba088845100e8321392aebaa","unresolved":false,"context_lines":[{"line_number":599,"context_line":"        if futils.validate_key_repository(requires_write\u003dTrue):"},{"line_number":600,"context_line":"            futils.rotate_keys(keystone_user_id, keystone_group_id)"},{"line_number":601,"context_line":""},{"line_number":602,"context_line":""},{"line_number":603,"context_line":"class CredentialSetup(BasePermissionsSetup):"},{"line_number":604,"context_line":"    \"\"\"Setup a Fernet key repository for credential encryption."},{"line_number":605,"context_line":""}],"source_content_type":"text/x-python","patch_set":10,"id":"3f79a3b5_45394da0","line":602,"updated":"2018-10-30 21:31:41.000000000","message":"It still seems clumsy to me to have both the fernet_* and receipt_* commands do the same thing. The fernet_* commands already handle this, I don\u0027t think we need another command.","commit_id":"5196e47954f3135741f0be17e10181631f2e0d36"},{"author":{"_account_id":10420,"name":"Adrian Turjak","email":"devs+openstack@uncaught-exceptions.com","username":"adriant"},"change_message_id":"3cc3f356eada2d992dd09e88a1993f54fe166039","unresolved":false,"context_lines":[{"line_number":599,"context_line":"        if futils.validate_key_repository(requires_write\u003dTrue):"},{"line_number":600,"context_line":"            futils.rotate_keys(keystone_user_id, keystone_group_id)"},{"line_number":601,"context_line":""},{"line_number":602,"context_line":""},{"line_number":603,"context_line":"class CredentialSetup(BasePermissionsSetup):"},{"line_number":604,"context_line":"    \"\"\"Setup a Fernet key repository for credential encryption."},{"line_number":605,"context_line":""}],"source_content_type":"text/x-python","patch_set":10,"id":"3f79a3b5_8082f301","line":602,"in_reply_to":"3f79a3b5_45394da0","updated":"2018-10-30 22:35:17.000000000","message":"The reason I\u0027ve left them is that if we keep the option to split receipt and token fernet key directories, then we should retain the option to setup/rotate them independently of each other.\n\nNot to mention, fernet_* does the same as token_* yet we still keep token_* around.","commit_id":"5196e47954f3135741f0be17e10181631f2e0d36"}],"keystone/common/authorization.py":[{"author":{"_account_id":8482,"name":"Colleen Murphy","email":"colleen@gazlene.net","username":"krinkle"},"change_message_id":"4d8f332bfdbf58cb4ae1ac310dc8a1fb7e64a31f","unresolved":false,"context_lines":[{"line_number":29,"context_line":""},{"line_number":30,"context_line":""},{"line_number":31,"context_line":"# Header used to transmit the auth receipt"},{"line_number":32,"context_line":"AUTH_RECEIPT_HEADER \u003d \u0027Openstack-Auth-Receipt\u0027"},{"line_number":33,"context_line":""},{"line_number":34,"context_line":""},{"line_number":35,"context_line":"# Header used to transmit the subject token"}],"source_content_type":"text/x-python","patch_set":6,"id":"3f79a3b5_e04c649e","line":32,"range":{"start_line":32,"start_character":23,"end_line":32,"end_character":32},"updated":"2018-10-25 13:09:36.000000000","message":"I sort of forget why we went with Openstack-* instead of X-* but I guess I like it better.","commit_id":"c7fbb0c00ece2698d052f40ad5a2b3b623e246bf"},{"author":{"_account_id":10420,"name":"Adrian Turjak","email":"devs+openstack@uncaught-exceptions.com","username":"adriant"},"change_message_id":"ce4f2d0e954b23c0ed8865a1c62363e5dbb8e54f","unresolved":false,"context_lines":[{"line_number":29,"context_line":""},{"line_number":30,"context_line":""},{"line_number":31,"context_line":"# Header used to transmit the auth receipt"},{"line_number":32,"context_line":"AUTH_RECEIPT_HEADER \u003d \u0027Openstack-Auth-Receipt\u0027"},{"line_number":33,"context_line":""},{"line_number":34,"context_line":""},{"line_number":35,"context_line":"# Header used to transmit the subject token"}],"source_content_type":"text/x-python","patch_set":6,"id":"3f79a3b5_75da4276","line":32,"range":{"start_line":32,"start_character":23,"end_line":32,"end_character":32},"in_reply_to":"3f79a3b5_e04c649e","updated":"2018-10-29 01:14:08.000000000","message":"Morgan wanted this because the X-* headers were overused and I believe based on an old http spec everyone took too literally.","commit_id":"c7fbb0c00ece2698d052f40ad5a2b3b623e246bf"},{"author":{"_account_id":10420,"name":"Adrian Turjak","email":"devs+openstack@uncaught-exceptions.com","username":"adriant"},"change_message_id":"fc018f1edf7258eda64fb080462ea9d74879197d","unresolved":false,"context_lines":[{"line_number":21,"context_line":"# Header used to transmit the auth token"},{"line_number":22,"context_line":"AUTH_TOKEN_HEADER \u003d \u0027X-Auth-Token\u0027"},{"line_number":23,"context_line":""},{"line_number":24,"context_line":"\u003c\u003c\u003c\u003c\u003c\u003c\u003c HEAD"},{"line_number":25,"context_line":"\u003d\u003d\u003d\u003d\u003d\u003d\u003d"},{"line_number":26,"context_line":""},{"line_number":27,"context_line":"# Header used to transmit the auth receipt"},{"line_number":28,"context_line":"AUTH_RECEIPT_HEADER \u003d \u0027Openstack-Auth-Receipt\u0027"},{"line_number":29,"context_line":""},{"line_number":30,"context_line":""},{"line_number":31,"context_line":"\u003e\u003e\u003e\u003e\u003e\u003e\u003e Implement auth receipts spec"},{"line_number":32,"context_line":"# Header used to transmit the subject token"},{"line_number":33,"context_line":"SUBJECT_TOKEN_HEADER \u003d \u0027X-Subject-Token\u0027"},{"line_number":34,"context_line":""}],"source_content_type":"text/x-python","patch_set":7,"id":"3f79a3b5_9fccbb33","line":31,"range":{"start_line":24,"start_character":0,"end_line":31,"end_character":36},"updated":"2018-10-29 04:02:52.000000000","message":"oh crap...","commit_id":"b5c9fa12ccbd2d092c468d5153b7d9836db2dc45"}],"keystone/common/render_receipt.py":[{"author":{"_account_id":2903,"name":"Morgan Fainberg","email":"morgan.fainberg@gmail.com","username":"mdrnstm"},"change_message_id":"faf9e8b05d91e5f803f765c1d64d405d14058b53","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":3,"id":"3f79a3b5_30130a68","updated":"2018-10-18 23:17:51.000000000","message":"This could live in keystone.api.auth unless it is used outside of the API itself. The render_token bits are only in common because there is a hard dependency in the RBACEnforcer on the token rendered format.","commit_id":"1514eaf699bfdd468229a80cbb89bda75ba20b30"},{"author":{"_account_id":10420,"name":"Adrian Turjak","email":"devs+openstack@uncaught-exceptions.com","username":"adriant"},"change_message_id":"4fdd97b0e4b80de8385dcae32396aa8d86bf242f","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":3,"id":"3f79a3b5_52d52ee5","in_reply_to":"3f79a3b5_30130a68","updated":"2018-10-23 02:01:17.000000000","message":"Done","commit_id":"1514eaf699bfdd468229a80cbb89bda75ba20b30"}],"keystone/conf/fernet_receipts.py":[{"author":{"_account_id":2903,"name":"Morgan Fainberg","email":"morgan.fainberg@gmail.com","username":"mdrnstm"},"change_message_id":"faf9e8b05d91e5f803f765c1d64d405d14058b53","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":3,"id":"3f79a3b5_3308f425","updated":"2018-10-18 23:17:51.000000000","message":"Do we really want to call this \"fernet receipts\" maybe auth receipts instead? or combine into main receipts section? Not sure if this is worth isolating.","commit_id":"1514eaf699bfdd468229a80cbb89bda75ba20b30"},{"author":{"_account_id":10420,"name":"Adrian Turjak","email":"devs+openstack@uncaught-exceptions.com","username":"adriant"},"change_message_id":"4fdd97b0e4b80de8385dcae32396aa8d86bf242f","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":3,"id":"3f79a3b5_b2d042c8","in_reply_to":"3f79a3b5_3308f425","updated":"2018-10-23 02:01:17.000000000","message":"I\u0027m calling it fernet_receipts to match fernet_tokens.\n\nIf/when we introduce JWT tokens, we\u0027ll probably want to also introduce JWT receipts because it likely doesn\u0027t make sense to have a keystone with JWT tokens and Fernet Receipts, and a question that will crop up then is do we lock token and receipt provider types together.\n\nI also don\u0027t know if JWT will be using the same key directories (as in, will we rename it all to \u0027/etc/keystone/auth-keys/\u0027). In theory a key for fernet should also be compatible for JWT, but that discussion shouldn\u0027t happen here. We already have plenty of deployments using \u0027fernet-keys\u0027 and will need to transition, so that\u0027s a bigger discussion.","commit_id":"1514eaf699bfdd468229a80cbb89bda75ba20b30"}],"keystone/conf/receipt.py":[{"author":{"_account_id":5046,"name":"Lance Bragstad","email":"lbragstad@redhat.com","username":"ldbragst"},"change_message_id":"ff87b4cc7a66fc26f4c7cfa811bdcbc01e6555cf","unresolved":false,"context_lines":[{"line_number":28,"context_line":"auth with the missing auth methods."},{"line_number":29,"context_line":"\"\"\"))"},{"line_number":30,"context_line":""},{"line_number":31,"context_line":"provider \u003d cfg.StrOpt("},{"line_number":32,"context_line":"    \u0027provider\u0027,"},{"line_number":33,"context_line":"    default\u003d\u0027fernet\u0027,"},{"line_number":34,"context_line":"    help\u003dutils.fmt(\"\"\""},{"line_number":35,"context_line":"Entry point for the receipt provider in the `keystone.receipt.provider`"},{"line_number":36,"context_line":"namespace. The receipt provider controls the receipt construction and"},{"line_number":37,"context_line":"validation operations. Keystone includes just the `fernet` receipt provider for"},{"line_number":38,"context_line":"now. `fernet` receipts do not need to be persisted at all, but require that you"},{"line_number":39,"context_line":"run `keystone-manage fernet_setup` (also see the `keystone-manage"},{"line_number":40,"context_line":"fernet_rotate` command)."},{"line_number":41,"context_line":"\"\"\"))"},{"line_number":42,"context_line":""},{"line_number":43,"context_line":"caching \u003d cfg.BoolOpt("},{"line_number":44,"context_line":"    \u0027caching\u0027,"}],"source_content_type":"text/x-python","patch_set":4,"id":"3f79a3b5_9b45289e","line":41,"range":{"start_line":31,"start_character":0,"end_line":41,"end_character":5},"updated":"2018-10-22 20:56:20.000000000","message":"Related to the below comment. Do we expect to offer support for people to override recept implementation initially? If not, then I think we should remove this.","commit_id":"58fc38157efbe8e0dde7bbffe09b0c061619be99"},{"author":{"_account_id":10420,"name":"Adrian Turjak","email":"devs+openstack@uncaught-exceptions.com","username":"adriant"},"change_message_id":"4fdd97b0e4b80de8385dcae32396aa8d86bf242f","unresolved":false,"context_lines":[{"line_number":28,"context_line":"auth with the missing auth methods."},{"line_number":29,"context_line":"\"\"\"))"},{"line_number":30,"context_line":""},{"line_number":31,"context_line":"provider \u003d cfg.StrOpt("},{"line_number":32,"context_line":"    \u0027provider\u0027,"},{"line_number":33,"context_line":"    default\u003d\u0027fernet\u0027,"},{"line_number":34,"context_line":"    help\u003dutils.fmt(\"\"\""},{"line_number":35,"context_line":"Entry point for the receipt provider in the `keystone.receipt.provider`"},{"line_number":36,"context_line":"namespace. The receipt provider controls the receipt construction and"},{"line_number":37,"context_line":"validation operations. Keystone includes just the `fernet` receipt provider for"},{"line_number":38,"context_line":"now. `fernet` receipts do not need to be persisted at all, but require that you"},{"line_number":39,"context_line":"run `keystone-manage fernet_setup` (also see the `keystone-manage"},{"line_number":40,"context_line":"fernet_rotate` command)."},{"line_number":41,"context_line":"\"\"\"))"},{"line_number":42,"context_line":""},{"line_number":43,"context_line":"caching \u003d cfg.BoolOpt("},{"line_number":44,"context_line":"    \u0027caching\u0027,"}],"source_content_type":"text/x-python","patch_set":4,"id":"3f79a3b5_b26cc205","line":41,"range":{"start_line":31,"start_character":0,"end_line":41,"end_character":5},"in_reply_to":"3f79a3b5_9b45289e","updated":"2018-10-23 02:01:17.000000000","message":"I don\u0027t think there is any particular harm in leaving this, since otherwise we have to hardcode \u0027fernet\u0027 in place of this config in super(Manager, self).__init__(CONF.receipt.provider)\n\nWhen JWT tokens are a thing we will end up doing JWT receipts so this will end up here anyway.\n\nRight now we don\u0027t even have alternative options for tokens, but the config option still exists simply because we know it will be used later.","commit_id":"58fc38157efbe8e0dde7bbffe09b0c061619be99"},{"author":{"_account_id":5046,"name":"Lance Bragstad","email":"lbragstad@redhat.com","username":"ldbragst"},"change_message_id":"ff87b4cc7a66fc26f4c7cfa811bdcbc01e6555cf","unresolved":false,"context_lines":[{"line_number":71,"context_line":"GROUP_NAME \u003d __name__.split(\u0027.\u0027)[-1]"},{"line_number":72,"context_line":"ALL_OPTS \u003d ["},{"line_number":73,"context_line":"    expiration,"},{"line_number":74,"context_line":"    provider,"},{"line_number":75,"context_line":"    caching,"},{"line_number":76,"context_line":"    cache_time,"},{"line_number":77,"context_line":"    cache_on_issue,"},{"line_number":78,"context_line":"]"},{"line_number":79,"context_line":""},{"line_number":80,"context_line":""}],"source_content_type":"text/x-python","patch_set":4,"id":"3f79a3b5_1b5a7881","line":77,"range":{"start_line":74,"start_character":0,"end_line":77,"end_character":19},"updated":"2018-10-22 20:56:20.000000000","message":"If we don\u0027t expect to use these we should remove them.","commit_id":"58fc38157efbe8e0dde7bbffe09b0c061619be99"},{"author":{"_account_id":10420,"name":"Adrian Turjak","email":"devs+openstack@uncaught-exceptions.com","username":"adriant"},"change_message_id":"4fdd97b0e4b80de8385dcae32396aa8d86bf242f","unresolved":false,"context_lines":[{"line_number":71,"context_line":"GROUP_NAME \u003d __name__.split(\u0027.\u0027)[-1]"},{"line_number":72,"context_line":"ALL_OPTS \u003d ["},{"line_number":73,"context_line":"    expiration,"},{"line_number":74,"context_line":"    provider,"},{"line_number":75,"context_line":"    caching,"},{"line_number":76,"context_line":"    cache_time,"},{"line_number":77,"context_line":"    cache_on_issue,"},{"line_number":78,"context_line":"]"},{"line_number":79,"context_line":""},{"line_number":80,"context_line":""}],"source_content_type":"text/x-python","patch_set":4,"id":"3f79a3b5_d2405e62","line":77,"range":{"start_line":74,"start_character":0,"end_line":77,"end_character":19},"in_reply_to":"3f79a3b5_1b5a7881","updated":"2018-10-23 02:01:17.000000000","message":"caching values are used so I don\u0027t see why we\u0027d remove them.","commit_id":"58fc38157efbe8e0dde7bbffe09b0c061619be99"}],"keystone/exception.py":[{"author":{"_account_id":2903,"name":"Morgan Fainberg","email":"morgan.fainberg@gmail.com","username":"mdrnstm"},"change_message_id":"faf9e8b05d91e5f803f765c1d64d405d14058b53","unresolved":false,"context_lines":[{"line_number":276,"context_line":""},{"line_number":277,"context_line":"    def __init__(self, message\u003dNone, user_id\u003dNone, methods\u003dNone):"},{"line_number":278,"context_line":"        super(InsufficientAuthMethods, self).__init__("},{"line_number":279,"context_line":"            message, user_id\u003duser_id, methods\u003d\u0027[%s]\u0027 % \u0027,\u0027.join(methods))"},{"line_number":280,"context_line":""},{"line_number":281,"context_line":"        self.user_id \u003d user_id"},{"line_number":282,"context_line":"        self.methods \u003d methods"}],"source_content_type":"text/x-python","patch_set":3,"id":"3f79a3b5_7030a207","line":279,"range":{"start_line":279,"start_character":37,"end_line":279,"end_character":72},"updated":"2018-10-18 23:17:51.000000000","message":"This feels like the wrong place perhaps override _build_message instead. At least do the join on it\u0027s own line before the super.","commit_id":"1514eaf699bfdd468229a80cbb89bda75ba20b30"},{"author":{"_account_id":10420,"name":"Adrian Turjak","email":"devs+openstack@uncaught-exceptions.com","username":"adriant"},"change_message_id":"00b732845bfba88541df6f7a41320d5f4febaf09","unresolved":false,"context_lines":[{"line_number":284,"context_line":""},{"line_number":285,"context_line":""},{"line_number":286,"context_line":"class InsufficientAuthMethods(Error):"},{"line_number":287,"context_line":"    # NOTE(adrian): This is an internal only error that is built into"},{"line_number":288,"context_line":"    # an auth receipt response."},{"line_number":289,"context_line":"    message_format \u003d _(\"Insufficient auth methods received for %(user_id)s. \""},{"line_number":290,"context_line":"                       \"Auth Methods Provided: %(methods)s.\")"}],"source_content_type":"text/x-python","patch_set":6,"id":"3f79a3b5_f51f8457","line":287,"range":{"start_line":287,"start_character":11,"end_line":287,"end_character":17},"updated":"2018-10-23 02:11:56.000000000","message":"adriant","commit_id":"c7fbb0c00ece2698d052f40ad5a2b3b623e246bf"},{"author":{"_account_id":2903,"name":"Morgan Fainberg","email":"morgan.fainberg@gmail.com","username":"mdrnstm"},"change_message_id":"4be67619fe2e42b645db5e86c784c4bc88fa7668","unresolved":false,"context_lines":[{"line_number":300,"context_line":"        self.methods \u003d methods"},{"line_number":301,"context_line":""},{"line_number":302,"context_line":""},{"line_number":303,"context_line":"class ReceiptNotFound(Unauthorized):"},{"line_number":304,"context_line":"    message_format \u003d _(\"Could not find auth receipt: %(receipt_id)s.\")"},{"line_number":305,"context_line":""},{"line_number":306,"context_line":""}],"source_content_type":"text/x-python","patch_set":12,"id":"3f79a3b5_e2dfe836","line":303,"range":{"start_line":303,"start_character":6,"end_line":303,"end_character":21},"updated":"2018-11-02 16:44:53.000000000","message":"This should probably be an \"Invalid\" Can be fixed later. We don\u0027t really have concrete auth receipts as a resource so a NotFound doesn\u0027t make sense.","commit_id":"d9e6c1d4dd693143bae3bf9eed6e63ff469586f3"}],"keystone/models/receipt_model.py":[{"author":{"_account_id":2903,"name":"Morgan Fainberg","email":"morgan.fainberg@gmail.com","username":"mdrnstm"},"change_message_id":"faf9e8b05d91e5f803f765c1d64d405d14058b53","unresolved":false,"context_lines":[{"line_number":133,"context_line":"        return serialized"},{"line_number":134,"context_line":""},{"line_number":135,"context_line":"    def deserialize(self, data):"},{"line_number":136,"context_line":"        token_data \u003d msgpackutils.loads(data, registry\u003dself._registry)"},{"line_number":137,"context_line":"        try:"},{"line_number":138,"context_line":"            token_model \u003d ReceiptModel()"},{"line_number":139,"context_line":"            for k, v in iter(token_data.items()):"},{"line_number":140,"context_line":"                setattr(token_model, k, v)"},{"line_number":141,"context_line":"        except Exception:"},{"line_number":142,"context_line":"            LOG.debug("},{"line_number":143,"context_line":"                \"Failed to deserialize ReceiptModel. Data is %s\", token_data"},{"line_number":144,"context_line":"            )"},{"line_number":145,"context_line":"            raise exception.CacheDeserializationError("},{"line_number":146,"context_line":"                ReceiptModel.__name__, token_data"},{"line_number":147,"context_line":"            )"},{"line_number":148,"context_line":"        return token_model"},{"line_number":149,"context_line":""},{"line_number":150,"context_line":""},{"line_number":151,"context_line":"cache.register_model_handler(_ReceiptModelHandler)"}],"source_content_type":"text/x-python","patch_set":3,"id":"3f79a3b5_131cd864","line":148,"range":{"start_line":136,"start_character":8,"end_line":148,"end_character":26},"updated":"2018-10-18 23:17:51.000000000","message":"NIT: swap token_model for receipt_model.","commit_id":"1514eaf699bfdd468229a80cbb89bda75ba20b30"},{"author":{"_account_id":10420,"name":"Adrian Turjak","email":"devs+openstack@uncaught-exceptions.com","username":"adriant"},"change_message_id":"4fdd97b0e4b80de8385dcae32396aa8d86bf242f","unresolved":false,"context_lines":[{"line_number":133,"context_line":"        return serialized"},{"line_number":134,"context_line":""},{"line_number":135,"context_line":"    def deserialize(self, data):"},{"line_number":136,"context_line":"        token_data \u003d msgpackutils.loads(data, registry\u003dself._registry)"},{"line_number":137,"context_line":"        try:"},{"line_number":138,"context_line":"            token_model \u003d ReceiptModel()"},{"line_number":139,"context_line":"            for k, v in iter(token_data.items()):"},{"line_number":140,"context_line":"                setattr(token_model, k, v)"},{"line_number":141,"context_line":"        except Exception:"},{"line_number":142,"context_line":"            LOG.debug("},{"line_number":143,"context_line":"                \"Failed to deserialize ReceiptModel. Data is %s\", token_data"},{"line_number":144,"context_line":"            )"},{"line_number":145,"context_line":"            raise exception.CacheDeserializationError("},{"line_number":146,"context_line":"                ReceiptModel.__name__, token_data"},{"line_number":147,"context_line":"            )"},{"line_number":148,"context_line":"        return token_model"},{"line_number":149,"context_line":""},{"line_number":150,"context_line":""},{"line_number":151,"context_line":"cache.register_model_handler(_ReceiptModelHandler)"}],"source_content_type":"text/x-python","patch_set":3,"id":"3f79a3b5_93a6a8ac","line":148,"range":{"start_line":136,"start_character":8,"end_line":148,"end_character":26},"in_reply_to":"3f79a3b5_131cd864","updated":"2018-10-23 02:01:17.000000000","message":"UGH! I knew I\u0027d probably missed some.\n\ndone","commit_id":"1514eaf699bfdd468229a80cbb89bda75ba20b30"},{"author":{"_account_id":8482,"name":"Colleen Murphy","email":"colleen@gazlene.net","username":"krinkle"},"change_message_id":"4d8f332bfdbf58cb4ae1ac310dc8a1fb7e64a31f","unresolved":false,"context_lines":[{"line_number":26,"context_line":"LOG \u003d log.getLogger(__name__)"},{"line_number":27,"context_line":"PROVIDERS \u003d provider_api.ProviderAPIs"},{"line_number":28,"context_line":""},{"line_number":29,"context_line":""},{"line_number":30,"context_line":"class ReceiptModel(object):"},{"line_number":31,"context_line":"    \"\"\"An object that represents a receipt emitted by keystone."},{"line_number":32,"context_line":""}],"source_content_type":"text/x-python","patch_set":6,"id":"3f79a3b5_03e88add","line":29,"updated":"2018-10-25 13:09:36.000000000","message":"Could we please make a generic keystone.models.BaseAuthObject (or something) class that TokenModel and ReceiptModel can inherit from? It doesn\u0027t make sense for there to be so much duplication.","commit_id":"c7fbb0c00ece2698d052f40ad5a2b3b623e246bf"},{"author":{"_account_id":10420,"name":"Adrian Turjak","email":"devs+openstack@uncaught-exceptions.com","username":"adriant"},"change_message_id":"ce4f2d0e954b23c0ed8865a1c62363e5dbb8e54f","unresolved":false,"context_lines":[{"line_number":26,"context_line":"LOG \u003d log.getLogger(__name__)"},{"line_number":27,"context_line":"PROVIDERS \u003d provider_api.ProviderAPIs"},{"line_number":28,"context_line":""},{"line_number":29,"context_line":""},{"line_number":30,"context_line":"class ReceiptModel(object):"},{"line_number":31,"context_line":"    \"\"\"An object that represents a receipt emitted by keystone."},{"line_number":32,"context_line":""}],"source_content_type":"text/x-python","patch_set":6,"id":"3f79a3b5_20024abb","line":29,"in_reply_to":"3f79a3b5_03e88add","updated":"2018-10-29 01:14:08.000000000","message":"I\u0027m more than happy to do that, just not sure if we\u0027d be happy with doing it in the scope of this patch.","commit_id":"c7fbb0c00ece2698d052f40ad5a2b3b623e246bf"},{"author":{"_account_id":8482,"name":"Colleen Murphy","email":"colleen@gazlene.net","username":"krinkle"},"change_message_id":"4d8f332bfdbf58cb4ae1ac310dc8a1fb7e64a31f","unresolved":false,"context_lines":[{"line_number":46,"context_line":"        self.__issued_at \u003d None"},{"line_number":47,"context_line":""},{"line_number":48,"context_line":"    def __repr__(self):"},{"line_number":49,"context_line":"        \"\"\"Return string representation of KeystoneReceipt.\"\"\""},{"line_number":50,"context_line":"        desc \u003d (\u0027\u003c%(type)s at %(loc)s\u003e\u0027)"},{"line_number":51,"context_line":"        self_cls_name \u003d reflection.get_class_name(self, fully_qualified\u003dFalse)"},{"line_number":52,"context_line":"        return desc % {\u0027type\u0027: self_cls_name, \u0027loc\u0027: hex(id(self))}"}],"source_content_type":"text/x-python","patch_set":6,"id":"3f79a3b5_03b72a24","line":49,"range":{"start_line":49,"start_character":43,"end_line":49,"end_character":58},"updated":"2018-10-25 13:09:36.000000000","message":"ReceiptModel","commit_id":"c7fbb0c00ece2698d052f40ad5a2b3b623e246bf"},{"author":{"_account_id":8482,"name":"Colleen Murphy","email":"colleen@gazlene.net","username":"krinkle"},"change_message_id":"4d8f332bfdbf58cb4ae1ac310dc8a1fb7e64a31f","unresolved":false,"context_lines":[{"line_number":115,"context_line":"        example. Once a Receipt object accurately represents this information"},{"line_number":116,"context_line":"        it should be \"minted\". Receipt are minted when they get an ``id``"},{"line_number":117,"context_line":"        attribute and their creation time is recorded."},{"line_number":118,"context_line":"        \"\"\""},{"line_number":119,"context_line":"        self.id \u003d receipt_id"},{"line_number":120,"context_line":"        self.issued_at \u003d issued_at"},{"line_number":121,"context_line":""}],"source_content_type":"text/x-python","patch_set":6,"id":"3f79a3b5_e32eae40","line":118,"updated":"2018-10-25 13:09:36.000000000","message":"There\u0027s no validation step here, shouldn\u0027t there be? If there\u0027s no validation then it feels like there\u0027s not much point in calling this method.","commit_id":"c7fbb0c00ece2698d052f40ad5a2b3b623e246bf"},{"author":{"_account_id":10420,"name":"Adrian Turjak","email":"devs+openstack@uncaught-exceptions.com","username":"adriant"},"change_message_id":"ce4f2d0e954b23c0ed8865a1c62363e5dbb8e54f","unresolved":false,"context_lines":[{"line_number":115,"context_line":"        example. Once a Receipt object accurately represents this information"},{"line_number":116,"context_line":"        it should be \"minted\". Receipt are minted when they get an ``id``"},{"line_number":117,"context_line":"        attribute and their creation time is recorded."},{"line_number":118,"context_line":"        \"\"\""},{"line_number":119,"context_line":"        self.id \u003d receipt_id"},{"line_number":120,"context_line":"        self.issued_at \u003d issued_at"},{"line_number":121,"context_line":""}],"source_content_type":"text/x-python","patch_set":6,"id":"3f79a3b5_8061dea4","line":118,"in_reply_to":"3f79a3b5_e32eae40","updated":"2018-10-29 01:14:08.000000000","message":"I\u0027m not sure what there is to validate here that isn\u0027t already validated by the provider in the creation process, or in validation functions.\n\nWe could just set these fields directly I guess.","commit_id":"c7fbb0c00ece2698d052f40ad5a2b3b623e246bf"},{"author":{"_account_id":2903,"name":"Morgan Fainberg","email":"morgan.fainberg@gmail.com","username":"mdrnstm"},"change_message_id":"4be67619fe2e42b645db5e86c784c4bc88fa7668","unresolved":false,"context_lines":[{"line_number":45,"context_line":"        self.__expires_at \u003d None"},{"line_number":46,"context_line":"        self.__issued_at \u003d None"},{"line_number":47,"context_line":""},{"line_number":48,"context_line":"    def __repr__(self):"},{"line_number":49,"context_line":"        \"\"\"Return string representation of KeystoneReceipt.\"\"\""},{"line_number":50,"context_line":"        desc \u003d (\u0027\u003c%(type)s at %(loc)s\u003e\u0027)"},{"line_number":51,"context_line":"        self_cls_name \u003d reflection.get_class_name(self, fully_qualified\u003dFalse)"}],"source_content_type":"text/x-python","patch_set":12,"id":"3f79a3b5_42b25c07","line":48,"updated":"2018-11-02 16:44:53.000000000","message":"This is really superfluous at the moment. You\u0027re not meaningfully adding data to the repr. Remove or expand to contain the other information.\n\n(FIX IN FOLLOWUP)","commit_id":"d9e6c1d4dd693143bae3bf9eed6e63ff469586f3"},{"author":{"_account_id":2903,"name":"Morgan Fainberg","email":"morgan.fainberg@gmail.com","username":"mdrnstm"},"change_message_id":"4be67619fe2e42b645db5e86c784c4bc88fa7668","unresolved":false,"context_lines":[{"line_number":65,"context_line":"    def issued_at(self):"},{"line_number":66,"context_line":"        return self.__issued_at"},{"line_number":67,"context_line":""},{"line_number":68,"context_line":"    @issued_at.setter"},{"line_number":69,"context_line":"    def issued_at(self, value):"},{"line_number":70,"context_line":"        if not isinstance(value, six.string_types):"},{"line_number":71,"context_line":"            raise ValueError(\u0027issued_at must be a string.\u0027)"}],"source_content_type":"text/x-python","patch_set":12,"id":"3f79a3b5_e28da836","line":68,"updated":"2018-11-02 16:44:53.000000000","message":"The Setters should also not accept changes after mint is called (basically if ID is set). I have had the same complaint about the token model","commit_id":"d9e6c1d4dd693143bae3bf9eed6e63ff469586f3"}],"keystone/notifications.py":[{"author":{"_account_id":10420,"name":"Adrian Turjak","email":"devs+openstack@uncaught-exceptions.com","username":"adriant"},"change_message_id":"7ea9aa5e40081ca27bfc0e2be63b12e6f54b5835","unresolved":false,"context_lines":[{"line_number":84,"context_line":"REMOVE_APP_CREDS_FOR_USER \u003d \u0027remove_application_credentials_for_user\u0027"},{"line_number":85,"context_line":"DOMAIN_DELETED \u003d \u0027domain_deleted\u0027"},{"line_number":86,"context_line":""},{"line_number":87,"context_line":"# NOTE(adriant): For potential use later if we need the ability to clear the"},{"line_number":88,"context_line":"# receipt cache."},{"line_number":89,"context_line":"INVALIDATE_RECEIPT_CACHE \u003d \u0027invalidate_receipt_cache\u0027"},{"line_number":90,"context_line":""},{"line_number":91,"context_line":""},{"line_number":92,"context_line":"def build_audit_initiator():"}],"source_content_type":"text/x-python","patch_set":1,"id":"3f79a3b5_147dd41d","line":89,"range":{"start_line":87,"start_character":0,"end_line":89,"end_character":53},"updated":"2018-10-17 04:27:00.000000000","message":"morgan\u0027s comment:\n\"If this is not used. Do not add it. We don\u0027t need \"for potential future use\" code. if this is used, comment is inaccurate.\"","commit_id":"2f5a50a44370556d48bc6b215b4814d32446b9fb"},{"author":{"_account_id":2903,"name":"Morgan Fainberg","email":"morgan.fainberg@gmail.com","username":"mdrnstm"},"change_message_id":"faf9e8b05d91e5f803f765c1d64d405d14058b53","unresolved":false,"context_lines":[{"line_number":83,"context_line":"PERSIST_REVOCATION_EVENT_FOR_USER \u003d \u0027persist_revocation_event_for_user\u0027"},{"line_number":84,"context_line":"REMOVE_APP_CREDS_FOR_USER \u003d \u0027remove_application_credentials_for_user\u0027"},{"line_number":85,"context_line":"DOMAIN_DELETED \u003d \u0027domain_deleted\u0027"},{"line_number":86,"context_line":"INVALIDATE_RECEIPT_CACHE \u003d \u0027invalidate_receipt_cache\u0027"},{"line_number":87,"context_line":""},{"line_number":88,"context_line":""},{"line_number":89,"context_line":"def build_audit_initiator():"}],"source_content_type":"text/x-python","patch_set":3,"id":"3f79a3b5_7383cc56","line":86,"updated":"2018-10-18 23:17:51.000000000","message":"Where is this used?","commit_id":"1514eaf699bfdd468229a80cbb89bda75ba20b30"},{"author":{"_account_id":10420,"name":"Adrian Turjak","email":"devs+openstack@uncaught-exceptions.com","username":"adriant"},"change_message_id":"4fdd97b0e4b80de8385dcae32396aa8d86bf242f","unresolved":false,"context_lines":[{"line_number":83,"context_line":"PERSIST_REVOCATION_EVENT_FOR_USER \u003d \u0027persist_revocation_event_for_user\u0027"},{"line_number":84,"context_line":"REMOVE_APP_CREDS_FOR_USER \u003d \u0027remove_application_credentials_for_user\u0027"},{"line_number":85,"context_line":"DOMAIN_DELETED \u003d \u0027domain_deleted\u0027"},{"line_number":86,"context_line":"INVALIDATE_RECEIPT_CACHE \u003d \u0027invalidate_receipt_cache\u0027"},{"line_number":87,"context_line":""},{"line_number":88,"context_line":""},{"line_number":89,"context_line":"def build_audit_initiator():"}],"source_content_type":"text/x-python","patch_set":3,"id":"3f79a3b5_12eb367b","line":86,"in_reply_to":"3f79a3b5_7383cc56","updated":"2018-10-23 02:01:17.000000000","message":"have removed it","commit_id":"1514eaf699bfdd468229a80cbb89bda75ba20b30"}],"keystone/receipt/__init__.py":[{"author":{"_account_id":10420,"name":"Adrian Turjak","email":"devs+openstack@uncaught-exceptions.com","username":"adriant"},"change_message_id":"7ea9aa5e40081ca27bfc0e2be63b12e6f54b5835","unresolved":false,"context_lines":[{"line_number":12,"context_line":"# License for the specific language governing permissions and limitations"},{"line_number":13,"context_line":"# under the License."},{"line_number":14,"context_line":""},{"line_number":15,"context_line":"from keystone.receipt import provider  # noqa"}],"source_content_type":"text/x-python","patch_set":1,"id":"3f79a3b5_d4767c41","line":15,"range":{"start_line":15,"start_character":0,"end_line":15,"end_character":45},"updated":"2018-10-17 04:27:00.000000000","message":"according to morgan, pointless import, remove.","commit_id":"2f5a50a44370556d48bc6b215b4814d32446b9fb"},{"author":{"_account_id":8482,"name":"Colleen Murphy","email":"colleen@gazlene.net","username":"krinkle"},"change_message_id":"4d8f332bfdbf58cb4ae1ac310dc8a1fb7e64a31f","unresolved":false,"context_lines":[{"line_number":15,"context_line":"from keystone.receipt import provider"},{"line_number":16,"context_line":""},{"line_number":17,"context_line":""},{"line_number":18,"context_line":"__all__ \u003d ["},{"line_number":19,"context_line":"    \"provider\","},{"line_number":20,"context_line":"]"}],"source_content_type":"text/x-python","patch_set":6,"id":"3f79a3b5_e3a1cea9","line":20,"range":{"start_line":18,"start_character":0,"end_line":20,"end_character":1},"updated":"2018-10-25 13:09:36.000000000","message":"Not sure this is needed, at least keystone/token/__init__.py doesn\u0027t have it","commit_id":"c7fbb0c00ece2698d052f40ad5a2b3b623e246bf"},{"author":{"_account_id":10420,"name":"Adrian Turjak","email":"devs+openstack@uncaught-exceptions.com","username":"adriant"},"change_message_id":"3a3882899e9033644fe8d0df07d924a00abc3a93","unresolved":false,"context_lines":[{"line_number":15,"context_line":"from keystone.receipt import provider"},{"line_number":16,"context_line":""},{"line_number":17,"context_line":""},{"line_number":18,"context_line":"__all__ \u003d ["},{"line_number":19,"context_line":"    \"provider\","},{"line_number":20,"context_line":"]"}],"source_content_type":"text/x-python","patch_set":6,"id":"3f79a3b5_044862b1","line":20,"range":{"start_line":18,"start_character":0,"end_line":20,"end_character":1},"in_reply_to":"3f79a3b5_526f1c28","updated":"2018-10-29 01:22:59.000000000","message":"Not having: \"from keystone.receipt import provider\" threw an error in server.backends:\nAttributeError: \u0027module\u0027 object has no attribute \u0027provider\u0027\n\nWhich is a problem in server.backends as to how we\u0027re doing the imports and then using them.\n\n\n\nnot having the __all__ meant having to do \"# noqa\" on the import line for pep8. __all__ just makes it so we\u0027re explicit about what the import is for technically. Either works really.","commit_id":"c7fbb0c00ece2698d052f40ad5a2b3b623e246bf"},{"author":{"_account_id":10420,"name":"Adrian Turjak","email":"devs+openstack@uncaught-exceptions.com","username":"adriant"},"change_message_id":"ce4f2d0e954b23c0ed8865a1c62363e5dbb8e54f","unresolved":false,"context_lines":[{"line_number":15,"context_line":"from keystone.receipt import provider"},{"line_number":16,"context_line":""},{"line_number":17,"context_line":""},{"line_number":18,"context_line":"__all__ \u003d ["},{"line_number":19,"context_line":"    \"provider\","},{"line_number":20,"context_line":"]"}],"source_content_type":"text/x-python","patch_set":6,"id":"3f79a3b5_526f1c28","line":20,"range":{"start_line":18,"start_character":0,"end_line":20,"end_character":1},"in_reply_to":"3f79a3b5_e3a1cea9","updated":"2018-10-29 01:14:08.000000000","message":"Not having it here threw an error for me at some stage while testing. Will revisit and try and see why.","commit_id":"c7fbb0c00ece2698d052f40ad5a2b3b623e246bf"}],"keystone/receipt/provider.py":[{"author":{"_account_id":2903,"name":"Morgan Fainberg","email":"morgan.fainberg@gmail.com","username":"mdrnstm"},"change_message_id":"faf9e8b05d91e5f803f765c1d64d405d14058b53","unresolved":false,"context_lines":[{"line_number":105,"context_line":"            LOG.debug(\u0027Unable to validate receipt: %s\u0027, e)"},{"line_number":106,"context_line":"            raise exception.ReceiptNotFound()"},{"line_number":107,"context_line":""},{"line_number":108,"context_line":"    @MEMOIZE_RECEIPTS"},{"line_number":109,"context_line":"    def _validate_receipt(self, receipt_id):"},{"line_number":110,"context_line":"        (user_id, methods, issued_at,"},{"line_number":111,"context_line":"            expires_at) \u003d self.driver.validate_receipt(receipt_id)"}],"source_content_type":"text/x-python","patch_set":3,"id":"3f79a3b5_d31bc01a","line":108,"updated":"2018-10-18 23:17:51.000000000","message":"In what cases are we going to invalidate the cache? It seems like you might want to ride in on the same as the token validation cache events.","commit_id":"1514eaf699bfdd468229a80cbb89bda75ba20b30"},{"author":{"_account_id":10420,"name":"Adrian Turjak","email":"devs+openstack@uncaught-exceptions.com","username":"adriant"},"change_message_id":"4fdd97b0e4b80de8385dcae32396aa8d86bf242f","unresolved":false,"context_lines":[{"line_number":105,"context_line":"            LOG.debug(\u0027Unable to validate receipt: %s\u0027, e)"},{"line_number":106,"context_line":"            raise exception.ReceiptNotFound()"},{"line_number":107,"context_line":""},{"line_number":108,"context_line":"    @MEMOIZE_RECEIPTS"},{"line_number":109,"context_line":"    def _validate_receipt(self, receipt_id):"},{"line_number":110,"context_line":"        (user_id, methods, issued_at,"},{"line_number":111,"context_line":"            expires_at) \u003d self.driver.validate_receipt(receipt_id)"}],"source_content_type":"text/x-python","patch_set":3,"id":"3f79a3b5_f2e79aaa","line":108,"in_reply_to":"3f79a3b5_d31bc01a","updated":"2018-10-23 02:01:17.000000000","message":"Done","commit_id":"1514eaf699bfdd468229a80cbb89bda75ba20b30"},{"author":{"_account_id":10420,"name":"Adrian Turjak","email":"devs+openstack@uncaught-exceptions.com","username":"adriant"},"change_message_id":"069f3575e65e5a0771eb95d64f15bb30e602a263","unresolved":false,"context_lines":[{"line_number":41,"context_line":"    region\u003dRECEIPTS_REGION)"},{"line_number":42,"context_line":""},{"line_number":43,"context_line":""},{"line_number":44,"context_line":"def default_expire_time():"},{"line_number":45,"context_line":"    \"\"\"Determine when a fresh receipt should expire."},{"line_number":46,"context_line":""},{"line_number":47,"context_line":"    Expiration time varies based on configuration (see"},{"line_number":48,"context_line":"    ``[receipt] expiration``)."},{"line_number":49,"context_line":""},{"line_number":50,"context_line":"    :returns: a naive UTC datetime.datetime object"},{"line_number":51,"context_line":""},{"line_number":52,"context_line":"    \"\"\""},{"line_number":53,"context_line":"    expire_delta \u003d datetime.timedelta(seconds\u003dCONF.receipt.expiration)"},{"line_number":54,"context_line":"    expires_at \u003d timeutils.utcnow() + expire_delta"},{"line_number":55,"context_line":"    return expires_at.replace(microsecond\u003d0)"},{"line_number":56,"context_line":""},{"line_number":57,"context_line":""},{"line_number":58,"context_line":"class Manager(manager.Manager):"}],"source_content_type":"text/x-python","patch_set":6,"id":"3f79a3b5_4486b361","line":55,"range":{"start_line":44,"start_character":0,"end_line":55,"end_character":44},"updated":"2018-10-24 00:41:06.000000000","message":"duplicate code","commit_id":"c7fbb0c00ece2698d052f40ad5a2b3b623e246bf"},{"author":{"_account_id":10420,"name":"Adrian Turjak","email":"devs+openstack@uncaught-exceptions.com","username":"adriant"},"change_message_id":"069f3575e65e5a0771eb95d64f15bb30e602a263","unresolved":false,"context_lines":[{"line_number":70,"context_line":"        super(Manager, self).__init__(CONF.receipt.provider)"},{"line_number":71,"context_line":"        self._register_callback_listeners()"},{"line_number":72,"context_line":""},{"line_number":73,"context_line":"    def _register_callback_listeners(self):"},{"line_number":74,"context_line":"        callbacks \u003d {"},{"line_number":75,"context_line":"            notifications.ACTIONS.deleted: ["},{"line_number":76,"context_line":"                [\u0027OS-TRUST:trust\u0027, self._drop_receipt_cache],"},{"line_number":77,"context_line":"                [\u0027user\u0027, self._drop_receipt_cache],"},{"line_number":78,"context_line":"                [\u0027domain\u0027, self._drop_receipt_cache],"},{"line_number":79,"context_line":"            ],"},{"line_number":80,"context_line":"            notifications.ACTIONS.disabled: ["},{"line_number":81,"context_line":"                [\u0027user\u0027, self._drop_receipt_cache],"},{"line_number":82,"context_line":"                [\u0027domain\u0027, self._drop_receipt_cache],"},{"line_number":83,"context_line":"                [\u0027project\u0027, self._drop_receipt_cache],"},{"line_number":84,"context_line":"            ],"},{"line_number":85,"context_line":"            notifications.ACTIONS.internal: ["},{"line_number":86,"context_line":"                [notifications.INVALIDATE_TOKEN_CACHE,"},{"line_number":87,"context_line":"                    self._drop_receipt_cache],"},{"line_number":88,"context_line":"            ]"},{"line_number":89,"context_line":"        }"},{"line_number":90,"context_line":""},{"line_number":91,"context_line":"        for event, cb_info in callbacks.items():"},{"line_number":92,"context_line":"            for resource_type, callback_fns in cb_info:"},{"line_number":93,"context_line":"                notifications.register_event_callback(event, resource_type,"},{"line_number":94,"context_line":"                                                      callback_fns)"},{"line_number":95,"context_line":""},{"line_number":96,"context_line":"    def _drop_receipt_cache(self, service, resource_type, operation, payload):"},{"line_number":97,"context_line":"        \"\"\"Invalidate the entire receipt cache."}],"source_content_type":"text/x-python","patch_set":6,"id":"3f79a3b5_04eafb0c","line":94,"range":{"start_line":73,"start_character":4,"end_line":94,"end_character":67},"updated":"2018-10-24 00:41:06.000000000","message":"almost duplicate other than the  callback function","commit_id":"c7fbb0c00ece2698d052f40ad5a2b3b623e246bf"},{"author":{"_account_id":10420,"name":"Adrian Turjak","email":"devs+openstack@uncaught-exceptions.com","username":"adriant"},"change_message_id":"069f3575e65e5a0771eb95d64f15bb30e602a263","unresolved":false,"context_lines":[{"line_number":93,"context_line":"                notifications.register_event_callback(event, resource_type,"},{"line_number":94,"context_line":"                                                      callback_fns)"},{"line_number":95,"context_line":""},{"line_number":96,"context_line":"    def _drop_receipt_cache(self, service, resource_type, operation, payload):"},{"line_number":97,"context_line":"        \"\"\"Invalidate the entire receipt cache."},{"line_number":98,"context_line":""},{"line_number":99,"context_line":"        This is a handy private utility method that should be used when"},{"line_number":100,"context_line":"        consuming notifications that signal invalidating the receipt cache."},{"line_number":101,"context_line":""},{"line_number":102,"context_line":"        \"\"\""},{"line_number":103,"context_line":"        if CONF.receipt.cache_on_issue:"},{"line_number":104,"context_line":"            RECEIPTS_REGION.invalidate()"},{"line_number":105,"context_line":""},{"line_number":106,"context_line":"    def validate_receipt(self, receipt_id, window_seconds\u003d0):"},{"line_number":107,"context_line":"        if not receipt_id:"}],"source_content_type":"text/x-python","patch_set":6,"id":"3f79a3b5_a4ea270a","line":104,"range":{"start_line":96,"start_character":4,"end_line":104,"end_character":40},"updated":"2018-10-24 00:41:06.000000000","message":"duplicate other than cache name","commit_id":"c7fbb0c00ece2698d052f40ad5a2b3b623e246bf"},{"author":{"_account_id":10420,"name":"Adrian Turjak","email":"devs+openstack@uncaught-exceptions.com","username":"adriant"},"change_message_id":"069f3575e65e5a0771eb95d64f15bb30e602a263","unresolved":false,"context_lines":[{"line_number":103,"context_line":"        if CONF.receipt.cache_on_issue:"},{"line_number":104,"context_line":"            RECEIPTS_REGION.invalidate()"},{"line_number":105,"context_line":""},{"line_number":106,"context_line":"    def validate_receipt(self, receipt_id, window_seconds\u003d0):"},{"line_number":107,"context_line":"        if not receipt_id:"},{"line_number":108,"context_line":"            raise exception.ReceiptNotFound(_(\u0027No receipt in the request\u0027))"},{"line_number":109,"context_line":""},{"line_number":110,"context_line":"        try:"},{"line_number":111,"context_line":"            receipt \u003d self._validate_receipt(receipt_id)"},{"line_number":112,"context_line":"            self._is_valid_receipt(receipt, window_seconds\u003dwindow_seconds)"},{"line_number":113,"context_line":"            return receipt"},{"line_number":114,"context_line":"        except exception.Unauthorized as e:"},{"line_number":115,"context_line":"            LOG.debug(\u0027Unable to validate receipt: %s\u0027, e)"},{"line_number":116,"context_line":"            raise exception.ReceiptNotFound()"},{"line_number":117,"context_line":""},{"line_number":118,"context_line":"    @MEMOIZE_RECEIPTS"},{"line_number":119,"context_line":"    def _validate_receipt(self, receipt_id):"}],"source_content_type":"text/x-python","patch_set":6,"id":"3f79a3b5_04d3db60","line":116,"range":{"start_line":106,"start_character":4,"end_line":116,"end_character":45},"updated":"2018-10-24 00:41:06.000000000","message":"Almost duplicate, but not sure how to make generic...","commit_id":"c7fbb0c00ece2698d052f40ad5a2b3b623e246bf"},{"author":{"_account_id":10420,"name":"Adrian Turjak","email":"devs+openstack@uncaught-exceptions.com","username":"adriant"},"change_message_id":"069f3575e65e5a0771eb95d64f15bb30e602a263","unresolved":false,"context_lines":[{"line_number":127,"context_line":"        receipt.mint(receipt_id, issued_at)"},{"line_number":128,"context_line":"        return receipt"},{"line_number":129,"context_line":""},{"line_number":130,"context_line":"    def _is_valid_receipt(self, receipt, window_seconds\u003d0):"},{"line_number":131,"context_line":"        \"\"\"Verify the receipt is valid format and has not expired.\"\"\""},{"line_number":132,"context_line":"        current_time \u003d timeutils.normalize_time(timeutils.utcnow())"},{"line_number":133,"context_line":""},{"line_number":134,"context_line":"        try:"},{"line_number":135,"context_line":"            expiry \u003d timeutils.parse_isotime(receipt.expires_at)"},{"line_number":136,"context_line":"            expiry \u003d timeutils.normalize_time(expiry)"},{"line_number":137,"context_line":""},{"line_number":138,"context_line":"            # add a window in which you can fetch a receipt beyond expiry"},{"line_number":139,"context_line":"            expiry +\u003d datetime.timedelta(seconds\u003dwindow_seconds)"},{"line_number":140,"context_line":""},{"line_number":141,"context_line":"        except Exception:"},{"line_number":142,"context_line":"            LOG.exception(\u0027Unexpected error or malformed receipt \u0027"},{"line_number":143,"context_line":"                          \u0027determining receipt expiry: %s\u0027, receipt)"},{"line_number":144,"context_line":"            raise exception.ReceiptNotFound(_(\u0027Failed to validate receipt\u0027))"},{"line_number":145,"context_line":""},{"line_number":146,"context_line":"        if current_time \u003c expiry:"},{"line_number":147,"context_line":"            return None"},{"line_number":148,"context_line":"        else:"},{"line_number":149,"context_line":"            raise exception.ReceiptNotFound(_(\u0027Failed to validate receipt\u0027))"},{"line_number":150,"context_line":""},{"line_number":151,"context_line":"    def issue_receipt(self, user_id, method_names, expires_at\u003dNone):"},{"line_number":152,"context_line":""}],"source_content_type":"text/x-python","patch_set":6,"id":"3f79a3b5_44b4731d","line":149,"range":{"start_line":130,"start_character":4,"end_line":149,"end_character":76},"updated":"2018-10-24 00:41:06.000000000","message":"pretty much duplicate code","commit_id":"c7fbb0c00ece2698d052f40ad5a2b3b623e246bf"},{"author":{"_account_id":2903,"name":"Morgan Fainberg","email":"morgan.fainberg@gmail.com","username":"mdrnstm"},"change_message_id":"4be67619fe2e42b645db5e86c784c4bc88fa7668","unresolved":false,"context_lines":[{"line_number":137,"context_line":"            expiry \u003d timeutils.normalize_time(expiry)"},{"line_number":138,"context_line":""},{"line_number":139,"context_line":"            # add a window in which you can fetch a receipt beyond expiry"},{"line_number":140,"context_line":"            expiry +\u003d datetime.timedelta(seconds\u003dwindow_seconds)"},{"line_number":141,"context_line":""},{"line_number":142,"context_line":"        except Exception:"},{"line_number":143,"context_line":"            LOG.exception(\u0027Unexpected error or malformed receipt \u0027"}],"source_content_type":"text/x-python","patch_set":12,"id":"3f79a3b5_62d678fb","line":140,"updated":"2018-11-02 16:44:53.000000000","message":"Remove the \"window\" bit from receipts. They do not get a window of expired but valid for validation (fix in followup). There is no external validation of a receipt.","commit_id":"d9e6c1d4dd693143bae3bf9eed6e63ff469586f3"}],"keystone/receipt/providers/base.py":[{"author":{"_account_id":10420,"name":"Adrian Turjak","email":"devs+openstack@uncaught-exceptions.com","username":"adriant"},"change_message_id":"069f3575e65e5a0771eb95d64f15bb30e602a263","unresolved":false,"context_lines":[{"line_number":19,"context_line":"from keystone import exception"},{"line_number":20,"context_line":""},{"line_number":21,"context_line":""},{"line_number":22,"context_line":"@six.add_metaclass(abc.ABCMeta)"},{"line_number":23,"context_line":"class Provider(object):"},{"line_number":24,"context_line":"    \"\"\"Interface description for a Receipt provider.\"\"\""},{"line_number":25,"context_line":""},{"line_number":26,"context_line":"    @abc.abstractmethod"},{"line_number":27,"context_line":"    def validate_receipt(self, receipt_id):"},{"line_number":28,"context_line":"        \"\"\"Validate a given receipt by its ID and return the receipt_data."},{"line_number":29,"context_line":""},{"line_number":30,"context_line":"        :param receipt_id: the unique ID of the receipt"},{"line_number":31,"context_line":"        :type receipt_id: str"},{"line_number":32,"context_line":"        :returns: receipt data as a tuple in the form of:"},{"line_number":33,"context_line":""},{"line_number":34,"context_line":"        (user_id, methods, issued_at, expires_at)"},{"line_number":35,"context_line":""},{"line_number":36,"context_line":"        ``user_id`` is the unique ID of the user as a string"},{"line_number":37,"context_line":"        ``methods`` a list of authentication methods used to obtain the token"},{"line_number":38,"context_line":"        ``issued_at`` a datetime object of when the token was minted"},{"line_number":39,"context_line":"        ``expires_at`` a datetime object of when the token expires"},{"line_number":40,"context_line":""},{"line_number":41,"context_line":"        :raises keystone.exception.ReceiptNotFound: If the token doesn\u0027t exist."},{"line_number":42,"context_line":"        \"\"\""},{"line_number":43,"context_line":""},{"line_number":44,"context_line":"    @abc.abstractmethod"},{"line_number":45,"context_line":"    def generate_id_and_issued_at(self, receipt):"},{"line_number":46,"context_line":"        \"\"\"Generate a receipt based on the information provided."},{"line_number":47,"context_line":""},{"line_number":48,"context_line":"        :param receipt: A receipt object containing information about the"},{"line_number":49,"context_line":"                        authorization context of the request."},{"line_number":50,"context_line":"        :type receipt: `keystone.models.receipt.ReceiptModel`"},{"line_number":51,"context_line":"        :returns: tuple containing an ID for the receipt and the issued at time"},{"line_number":52,"context_line":"                  of the receipt (receipt_id, issued_at)."},{"line_number":53,"context_line":"        \"\"\""},{"line_number":54,"context_line":"        raise exception.NotImplemented()  # pragma: no cover"}],"source_content_type":"text/x-python","patch_set":6,"id":"3f79a3b5_e45b3ff6","line":54,"range":{"start_line":22,"start_character":0,"end_line":54,"end_character":60},"updated":"2018-10-24 00:41:06.000000000","message":"other than the doc strings... these are almost exactly the same as token","commit_id":"c7fbb0c00ece2698d052f40ad5a2b3b623e246bf"}],"keystone/receipt/providers/fernet/__init__.py":[{"author":{"_account_id":2903,"name":"Morgan Fainberg","email":"morgan.fainberg@gmail.com","username":"mdrnstm"},"change_message_id":"faf9e8b05d91e5f803f765c1d64d405d14058b53","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":3,"id":"3f79a3b5_33cb14a5","updated":"2018-10-18 23:17:51.000000000","message":"Since fernet is a backend, typically you\u0027d call this backends/fernet/...","commit_id":"1514eaf699bfdd468229a80cbb89bda75ba20b30"},{"author":{"_account_id":2903,"name":"Morgan Fainberg","email":"morgan.fainberg@gmail.com","username":"mdrnstm"},"change_message_id":"faf9e8b05d91e5f803f765c1d64d405d14058b53","unresolved":false,"context_lines":[{"line_number":12,"context_line":"# License for the specific language governing permissions and limitations"},{"line_number":13,"context_line":"# under the License."},{"line_number":14,"context_line":""},{"line_number":15,"context_line":"from keystone.receipt.providers.fernet.core import *  # noqa"}],"source_content_type":"text/x-python","patch_set":3,"id":"3f79a3b5_53cc90bd","line":15,"range":{"start_line":15,"start_character":0,"end_line":15,"end_character":60},"updated":"2018-10-18 23:17:51.000000000","message":"\u003cNIT\u003e I\u0027d prefer to see us stop doing this all together, it\u0027s a bit sloppy. explicitly assign the values from core you want to expose and use __all__ if you\u0027re going to do this.\n\nE.g.\n\nblah \u003d core.blah\nblah2 \u003d core.blah2\n\n__all__ \u003d [\u0027blah\u0027, \u0027blah2\u0027]","commit_id":"1514eaf699bfdd468229a80cbb89bda75ba20b30"},{"author":{"_account_id":10420,"name":"Adrian Turjak","email":"devs+openstack@uncaught-exceptions.com","username":"adriant"},"change_message_id":"4fdd97b0e4b80de8385dcae32396aa8d86bf242f","unresolved":false,"context_lines":[{"line_number":12,"context_line":"# License for the specific language governing permissions and limitations"},{"line_number":13,"context_line":"# under the License."},{"line_number":14,"context_line":""},{"line_number":15,"context_line":"from keystone.receipt.providers.fernet.core import *  # noqa"}],"source_content_type":"text/x-python","patch_set":3,"id":"3f79a3b5_92fe6637","line":15,"range":{"start_line":15,"start_character":0,"end_line":15,"end_character":60},"in_reply_to":"3f79a3b5_53cc90bd","updated":"2018-10-23 02:01:17.000000000","message":"Done","commit_id":"1514eaf699bfdd468229a80cbb89bda75ba20b30"}],"keystone/receipt/providers/fernet/core.py":[{"author":{"_account_id":5046,"name":"Lance Bragstad","email":"lbragstad@redhat.com","username":"ldbragst"},"change_message_id":"ff87b4cc7a66fc26f4c7cfa811bdcbc01e6555cf","unresolved":false,"context_lines":[{"line_number":30,"context_line":"    def __init__(self, *args, **kwargs):"},{"line_number":31,"context_line":"        super(Provider, self).__init__(*args, **kwargs)"},{"line_number":32,"context_line":""},{"line_number":33,"context_line":"        # NOTE(lbragstad): We add these checks here because if the fernet"},{"line_number":34,"context_line":"        # provider is going to be used and either the `key_repository` is empty"},{"line_number":35,"context_line":"        # or doesn\u0027t exist we should fail, hard. It doesn\u0027t make sense to start"},{"line_number":36,"context_line":"        # keystone and just 500 because we can\u0027t do anything with an empty or"},{"line_number":37,"context_line":"        # non-existant key repository."},{"line_number":38,"context_line":"        if not os.path.exists(CONF.fernet_receipts.key_repository):"},{"line_number":39,"context_line":"            subs \u003d {\u0027key_repo\u0027: CONF.fernet_receipts.key_repository}"},{"line_number":40,"context_line":"            raise SystemExit(_(\u0027%(key_repo)s does not exist\u0027) % subs)"},{"line_number":41,"context_line":"        if not os.listdir(CONF.fernet_receipts.key_repository):"},{"line_number":42,"context_line":"            subs \u003d {\u0027key_repo\u0027: CONF.fernet_receipts.key_repository}"},{"line_number":43,"context_line":"            raise SystemExit(_(\u0027%(key_repo)s does not contain keys, use \u0027"},{"line_number":44,"context_line":"                               \u0027keystone-manage fernet_setup to create \u0027"},{"line_number":45,"context_line":"                               \u0027Fernet keys.\u0027) % subs)"},{"line_number":46,"context_line":""},{"line_number":47,"context_line":"        self.receipt_formatter \u003d tf.ReceiptFormatter()"},{"line_number":48,"context_line":""}],"source_content_type":"text/x-python","patch_set":4,"id":"3f79a3b5_1bcfd828","line":45,"range":{"start_line":33,"start_character":0,"end_line":45,"end_character":54},"updated":"2018-10-22 20:56:20.000000000","message":"This will need to be reworked to be specific to receipts.","commit_id":"58fc38157efbe8e0dde7bbffe09b0c061619be99"},{"author":{"_account_id":10420,"name":"Adrian Turjak","email":"devs+openstack@uncaught-exceptions.com","username":"adriant"},"change_message_id":"069f3575e65e5a0771eb95d64f15bb30e602a263","unresolved":false,"context_lines":[{"line_number":26,"context_line":"CONF \u003d keystone.conf.CONF"},{"line_number":27,"context_line":""},{"line_number":28,"context_line":""},{"line_number":29,"context_line":"class Provider(base.Provider):"},{"line_number":30,"context_line":"    def __init__(self, *args, **kwargs):"},{"line_number":31,"context_line":"        super(Provider, self).__init__(*args, **kwargs)"},{"line_number":32,"context_line":""},{"line_number":33,"context_line":"        # NOTE(lbragstad): We add these checks here because if the fernet"},{"line_number":34,"context_line":"        # provider is going to be used and either the `key_repository` is empty"},{"line_number":35,"context_line":"        # or doesn\u0027t exist we should fail, hard. It doesn\u0027t make sense to start"},{"line_number":36,"context_line":"        # keystone and just 500 because we can\u0027t do anything with an empty or"},{"line_number":37,"context_line":"        # non-existant key repository."},{"line_number":38,"context_line":"        if not os.path.exists(CONF.fernet_receipts.key_repository):"},{"line_number":39,"context_line":"            subs \u003d {\u0027key_repo\u0027: CONF.fernet_receipts.key_repository}"},{"line_number":40,"context_line":"            raise SystemExit(_(\u0027%(key_repo)s does not exist\u0027) % subs)"},{"line_number":41,"context_line":"        if not os.listdir(CONF.fernet_receipts.key_repository):"},{"line_number":42,"context_line":"            subs \u003d {\u0027key_repo\u0027: CONF.fernet_receipts.key_repository}"},{"line_number":43,"context_line":"            raise SystemExit(_(\u0027%(key_repo)s does not contain keys, use \u0027"},{"line_number":44,"context_line":"                               \u0027keystone-manage fernet_setup to create \u0027"},{"line_number":45,"context_line":"                               \u0027Fernet keys.\u0027) % subs)"},{"line_number":46,"context_line":""},{"line_number":47,"context_line":"        self.receipt_formatter \u003d tf.ReceiptFormatter()"},{"line_number":48,"context_line":""},{"line_number":49,"context_line":"    def validate_receipt(self, receipt_id):"},{"line_number":50,"context_line":"        try:"},{"line_number":51,"context_line":"            return self.receipt_formatter.validate_receipt(receipt_id)"},{"line_number":52,"context_line":"        except exception.ValidationError as e:"},{"line_number":53,"context_line":"            raise exception.ReceiptNotFound(e)"},{"line_number":54,"context_line":""},{"line_number":55,"context_line":"    def generate_id_and_issued_at(self, receipt):"},{"line_number":56,"context_line":"        receipt_id \u003d self.receipt_formatter.create_receipt("}],"source_content_type":"text/x-python","patch_set":6,"id":"3f79a3b5_a451c7d7","line":53,"range":{"start_line":29,"start_character":0,"end_line":53,"end_character":46},"updated":"2018-10-24 00:41:06.000000000","message":"pretty much duplicate code","commit_id":"c7fbb0c00ece2698d052f40ad5a2b3b623e246bf"}],"keystone/receipt/receipt_formatters.py":[{"author":{"_account_id":10420,"name":"Adrian Turjak","email":"devs+openstack@uncaught-exceptions.com","username":"adriant"},"change_message_id":"069f3575e65e5a0771eb95d64f15bb30e602a263","unresolved":false,"context_lines":[{"line_number":33,"context_line":"CONF \u003d keystone.conf.CONF"},{"line_number":34,"context_line":"LOG \u003d log.getLogger(__name__)"},{"line_number":35,"context_line":""},{"line_number":36,"context_line":"# Fernet byte indexes as computed by pypi/keyless_fernet and defined in"},{"line_number":37,"context_line":"# https://github.com/fernet/spec"},{"line_number":38,"context_line":"TIMESTAMP_START \u003d 1"},{"line_number":39,"context_line":"TIMESTAMP_END \u003d 9"},{"line_number":40,"context_line":""},{"line_number":41,"context_line":""},{"line_number":42,"context_line":"class ReceiptFormatter(object):"},{"line_number":43,"context_line":"    \"\"\"Packs and unpacks payloads into receipts for transport.\"\"\""},{"line_number":44,"context_line":""},{"line_number":45,"context_line":"    @property"},{"line_number":46,"context_line":"    def crypto(self):"},{"line_number":47,"context_line":"        \"\"\"Return a cryptography instance."},{"line_number":48,"context_line":""},{"line_number":49,"context_line":"        You can extend this class with a custom crypto @property to provide"},{"line_number":50,"context_line":"        your own receipt encoding / decoding. For example, using a different"},{"line_number":51,"context_line":"        cryptography library (e.g. ``python-keyczar``) or to meet arbitrary"},{"line_number":52,"context_line":"        security requirements."},{"line_number":53,"context_line":""},{"line_number":54,"context_line":"        This @property just needs to return an object that implements"},{"line_number":55,"context_line":"        ``encrypt(plaintext)`` and ``decrypt(ciphertext)``."},{"line_number":56,"context_line":""},{"line_number":57,"context_line":"        \"\"\""},{"line_number":58,"context_line":"        fernet_utils \u003d utils.FernetUtils("},{"line_number":59,"context_line":"            CONF.fernet_receipts.key_repository,"},{"line_number":60,"context_line":"            CONF.fernet_receipts.max_active_keys,"},{"line_number":61,"context_line":"            \u0027fernet_receipts\u0027"},{"line_number":62,"context_line":"        )"},{"line_number":63,"context_line":"        keys \u003d fernet_utils.load_keys()"},{"line_number":64,"context_line":""},{"line_number":65,"context_line":"        if not keys:"},{"line_number":66,"context_line":"            raise exception.KeysNotFound()"},{"line_number":67,"context_line":""},{"line_number":68,"context_line":"        fernet_instances \u003d [fernet.Fernet(key) for key in keys]"},{"line_number":69,"context_line":"        return fernet.MultiFernet(fernet_instances)"},{"line_number":70,"context_line":""},{"line_number":71,"context_line":"    def pack(self, payload):"},{"line_number":72,"context_line":"        \"\"\"Pack a payload for transport as a receipt."},{"line_number":73,"context_line":""},{"line_number":74,"context_line":"        :type payload: six.binary_type"},{"line_number":75,"context_line":"        :rtype: six.text_type"},{"line_number":76,"context_line":""},{"line_number":77,"context_line":"        \"\"\""},{"line_number":78,"context_line":"        # base64 padding (if any) is not URL-safe"},{"line_number":79,"context_line":"        return self.crypto.encrypt(payload).rstrip(b\u0027\u003d\u0027).decode(\u0027utf-8\u0027)"},{"line_number":80,"context_line":""},{"line_number":81,"context_line":"    def unpack(self, receipt):"},{"line_number":82,"context_line":"        \"\"\"Unpack a receipt, and validate the payload."},{"line_number":83,"context_line":""},{"line_number":84,"context_line":"        :type receipt: six.text_type"},{"line_number":85,"context_line":"        :rtype: six.binary_type"},{"line_number":86,"context_line":""},{"line_number":87,"context_line":"        \"\"\""},{"line_number":88,"context_line":"        receipt \u003d ReceiptFormatter.restore_padding(receipt)"},{"line_number":89,"context_line":""},{"line_number":90,"context_line":"        try:"},{"line_number":91,"context_line":"            return self.crypto.decrypt(receipt.encode(\u0027utf-8\u0027))"},{"line_number":92,"context_line":"        except fernet.InvalidToken:"},{"line_number":93,"context_line":"            raise exception.ValidationError("},{"line_number":94,"context_line":"                _(\u0027This is not a recognized Fernet receipt %s\u0027) % receipt)"},{"line_number":95,"context_line":""},{"line_number":96,"context_line":"    @classmethod"},{"line_number":97,"context_line":"    def restore_padding(cls, receipt):"},{"line_number":98,"context_line":"        \"\"\"Restore padding based on receipt size."},{"line_number":99,"context_line":""},{"line_number":100,"context_line":"        :param receipt: receipt to restore padding on"},{"line_number":101,"context_line":"        :type receipt: six.text_type"},{"line_number":102,"context_line":"        :returns: receipt with correct padding"},{"line_number":103,"context_line":""},{"line_number":104,"context_line":"        \"\"\""},{"line_number":105,"context_line":"        # Re-inflate the padding"},{"line_number":106,"context_line":"        mod_returned \u003d len(receipt) % 4"},{"line_number":107,"context_line":"        if mod_returned:"},{"line_number":108,"context_line":"            missing_padding \u003d 4 - mod_returned"},{"line_number":109,"context_line":"            receipt +\u003d \u0027\u003d\u0027 * missing_padding"},{"line_number":110,"context_line":"        return receipt"},{"line_number":111,"context_line":""},{"line_number":112,"context_line":"    @classmethod"},{"line_number":113,"context_line":"    def creation_time(cls, fernet_receipt):"},{"line_number":114,"context_line":"        \"\"\"Return the creation time of a valid Fernet receipt."},{"line_number":115,"context_line":""},{"line_number":116,"context_line":"        :type fernet_receipt: six.text_type"},{"line_number":117,"context_line":""},{"line_number":118,"context_line":"        \"\"\""},{"line_number":119,"context_line":"        fernet_receipt \u003d ReceiptFormatter.restore_padding(fernet_receipt)"},{"line_number":120,"context_line":"        # fernet_receipt is six.text_type"},{"line_number":121,"context_line":""},{"line_number":122,"context_line":"        # Fernet receipts are base64 encoded, so we need to unpack them first"},{"line_number":123,"context_line":"        # urlsafe_b64decode() requires six.binary_type"},{"line_number":124,"context_line":"        receipt_bytes \u003d base64.urlsafe_b64decode("},{"line_number":125,"context_line":"            fernet_receipt.encode(\u0027utf-8\u0027))"},{"line_number":126,"context_line":""},{"line_number":127,"context_line":"        # slice into the byte array to get just the timestamp"},{"line_number":128,"context_line":"        timestamp_bytes \u003d receipt_bytes[TIMESTAMP_START:TIMESTAMP_END]"},{"line_number":129,"context_line":""},{"line_number":130,"context_line":"        # convert those bytes to an integer"},{"line_number":131,"context_line":"        # (it\u0027s a 64-bit \"unsigned long long int\" in C)"},{"line_number":132,"context_line":"        timestamp_int \u003d struct.unpack(\"\u003eQ\", timestamp_bytes)[0]"},{"line_number":133,"context_line":""},{"line_number":134,"context_line":"        # and with an integer, it\u0027s trivial to produce a datetime object"},{"line_number":135,"context_line":"        issued_at \u003d datetime.datetime.utcfromtimestamp(timestamp_int)"},{"line_number":136,"context_line":""},{"line_number":137,"context_line":"        return issued_at"},{"line_number":138,"context_line":""},{"line_number":139,"context_line":"    def create_receipt(self, user_id, methods, expires_at):"},{"line_number":140,"context_line":"        \"\"\"Given a set of payload attributes, generate a Fernet receipt.\"\"\""}],"source_content_type":"text/x-python","patch_set":6,"id":"3f79a3b5_84904b98","line":137,"range":{"start_line":36,"start_character":0,"end_line":137,"end_character":24},"updated":"2018-10-24 00:41:06.000000000","message":"Mostly duplicate code we can make generic and extract.","commit_id":"c7fbb0c00ece2698d052f40ad5a2b3b623e246bf"}],"keystone/server/backends.py":[{"author":{"_account_id":2903,"name":"Morgan Fainberg","email":"morgan.fainberg@gmail.com","username":"mdrnstm"},"change_message_id":"faf9e8b05d91e5f803f765c1d64d405d14058b53","unresolved":false,"context_lines":[{"line_number":57,"context_line":"                limit.Manager, oauth1.Manager, policy.Manager,"},{"line_number":58,"context_line":"                resource.Manager, revoke.Manager, assignment.RoleManager,"},{"line_number":59,"context_line":"                trust.Manager, token.provider.Manager,"},{"line_number":60,"context_line":"                receipt.provider.Manager]"},{"line_number":61,"context_line":""},{"line_number":62,"context_line":"    drivers \u003d {d._provides_api: d() for d in managers}"},{"line_number":63,"context_line":""}],"source_content_type":"text/x-python","patch_set":3,"id":"3f79a3b5_139ff8b3","line":60,"range":{"start_line":60,"start_character":16,"end_line":60,"end_character":39},"updated":"2018-10-18 23:17:51.000000000","message":"Please alphabetize, this goes before \"trust.Manager\"","commit_id":"1514eaf699bfdd468229a80cbb89bda75ba20b30"}],"keystone/server/flask/application.py":[{"author":{"_account_id":2903,"name":"Morgan Fainberg","email":"morgan.fainberg@gmail.com","username":"mdrnstm"},"change_message_id":"4be67619fe2e42b645db5e86c784c4bc88fa7668","unresolved":false,"context_lines":[{"line_number":69,"context_line":""},{"line_number":70,"context_line":""},{"line_number":71,"context_line":"def _handle_keystone_exception(error):"},{"line_number":72,"context_line":"    # TODO(adriant): register this with its own specific handler:"},{"line_number":73,"context_line":"    if isinstance(error, exception.InsufficientAuthMethods):"},{"line_number":74,"context_line":"        return receipt_handlers.build_receipt(error)"},{"line_number":75,"context_line":""}],"source_content_type":"text/x-python","patch_set":12,"id":"3f79a3b5_222e40f9","line":72,"range":{"start_line":72,"start_character":3,"end_line":72,"end_character":65},"updated":"2018-11-02 16:44:53.000000000","message":"++ Yep, lets make sure we do that in a followup.","commit_id":"d9e6c1d4dd693143bae3bf9eed6e63ff469586f3"}],"keystone/tests/unit/test_receipt_provider.py":[{"author":{"_account_id":2903,"name":"Morgan Fainberg","email":"morgan.fainberg@gmail.com","username":"mdrnstm"},"change_message_id":"faf9e8b05d91e5f803f765c1d64d405d14058b53","unresolved":false,"context_lines":[{"line_number":37,"context_line":"    \u0027receipt\u0027: {"},{"line_number":38,"context_line":"        \u0027methods\u0027: [\u0027password\u0027],"},{"line_number":39,"context_line":"        \u0027user\u0027: {"},{"line_number":40,"context_line":"            \u0027id\u0027: \u00272c58febd6903463584a75206ee6ea658\u0027,"},{"line_number":41,"context_line":"            \u0027name\u0027: \u0027bbaccf7403fb48c8a726c49d7177d765\u0027,"},{"line_number":42,"context_line":"            \u0027domain\u0027: {"},{"line_number":43,"context_line":"                \u0027id\u0027: \u002770d173f0a41a484d977b71a779836282\u0027,"}],"source_content_type":"text/x-python","patch_set":3,"id":"3f79a3b5_133b789b","line":40,"range":{"start_line":40,"start_character":19,"end_line":40,"end_character":53},"updated":"2018-10-18 23:17:51.000000000","message":"Where possible do not hard code user_ids. we generate them for the most part. If this is not leaning on an explicit user_id built on setup, use something dynamic. It makes sure we can\u0027t fudge it in tests and hard-code responses.","commit_id":"1514eaf699bfdd468229a80cbb89bda75ba20b30"},{"author":{"_account_id":2903,"name":"Morgan Fainberg","email":"morgan.fainberg@gmail.com","username":"mdrnstm"},"change_message_id":"faf9e8b05d91e5f803f765c1d64d405d14058b53","unresolved":false,"context_lines":[{"line_number":38,"context_line":"        \u0027methods\u0027: [\u0027password\u0027],"},{"line_number":39,"context_line":"        \u0027user\u0027: {"},{"line_number":40,"context_line":"            \u0027id\u0027: \u00272c58febd6903463584a75206ee6ea658\u0027,"},{"line_number":41,"context_line":"            \u0027name\u0027: \u0027bbaccf7403fb48c8a726c49d7177d765\u0027,"},{"line_number":42,"context_line":"            \u0027domain\u0027: {"},{"line_number":43,"context_line":"                \u0027id\u0027: \u002770d173f0a41a484d977b71a779836282\u0027,"},{"line_number":44,"context_line":"                \u0027name\u0027: \u0027d99a05d759904d4cb89826e4d83d19be\u0027"}],"source_content_type":"text/x-python","patch_set":3,"id":"3f79a3b5_3340f406","line":41,"range":{"start_line":41,"start_character":21,"end_line":41,"end_character":53},"updated":"2018-10-18 23:17:51.000000000","message":"Same as above.","commit_id":"1514eaf699bfdd468229a80cbb89bda75ba20b30"},{"author":{"_account_id":2903,"name":"Morgan Fainberg","email":"morgan.fainberg@gmail.com","username":"mdrnstm"},"change_message_id":"faf9e8b05d91e5f803f765c1d64d405d14058b53","unresolved":false,"context_lines":[{"line_number":40,"context_line":"            \u0027id\u0027: \u00272c58febd6903463584a75206ee6ea658\u0027,"},{"line_number":41,"context_line":"            \u0027name\u0027: \u0027bbaccf7403fb48c8a726c49d7177d765\u0027,"},{"line_number":42,"context_line":"            \u0027domain\u0027: {"},{"line_number":43,"context_line":"                \u0027id\u0027: \u002770d173f0a41a484d977b71a779836282\u0027,"},{"line_number":44,"context_line":"                \u0027name\u0027: \u0027d99a05d759904d4cb89826e4d83d19be\u0027"},{"line_number":45,"context_line":"            }"},{"line_number":46,"context_line":"        },"}],"source_content_type":"text/x-python","patch_set":3,"id":"3f79a3b5_d344201d","line":43,"range":{"start_line":43,"start_character":23,"end_line":43,"end_character":55},"updated":"2018-10-18 23:17:51.000000000","message":"same","commit_id":"1514eaf699bfdd468229a80cbb89bda75ba20b30"},{"author":{"_account_id":2903,"name":"Morgan Fainberg","email":"morgan.fainberg@gmail.com","username":"mdrnstm"},"change_message_id":"faf9e8b05d91e5f803f765c1d64d405d14058b53","unresolved":false,"context_lines":[{"line_number":41,"context_line":"            \u0027name\u0027: \u0027bbaccf7403fb48c8a726c49d7177d765\u0027,"},{"line_number":42,"context_line":"            \u0027domain\u0027: {"},{"line_number":43,"context_line":"                \u0027id\u0027: \u002770d173f0a41a484d977b71a779836282\u0027,"},{"line_number":44,"context_line":"                \u0027name\u0027: \u0027d99a05d759904d4cb89826e4d83d19be\u0027"},{"line_number":45,"context_line":"            }"},{"line_number":46,"context_line":"        },"},{"line_number":47,"context_line":"        \u0027expires_at\u0027: \u00272018-06-29T02:41:48.000000Z\u0027,"}],"source_content_type":"text/x-python","patch_set":3,"id":"3f79a3b5_f3411c0a","line":44,"range":{"start_line":44,"start_character":25,"end_line":44,"end_character":57},"updated":"2018-10-18 23:17:51.000000000","message":"same","commit_id":"1514eaf699bfdd468229a80cbb89bda75ba20b30"},{"author":{"_account_id":2903,"name":"Morgan Fainberg","email":"morgan.fainberg@gmail.com","username":"mdrnstm"},"change_message_id":"faf9e8b05d91e5f803f765c1d64d405d14058b53","unresolved":false,"context_lines":[{"line_number":44,"context_line":"                \u0027name\u0027: \u0027d99a05d759904d4cb89826e4d83d19be\u0027"},{"line_number":45,"context_line":"            }"},{"line_number":46,"context_line":"        },"},{"line_number":47,"context_line":"        \u0027expires_at\u0027: \u00272018-06-29T02:41:48.000000Z\u0027,"},{"line_number":48,"context_line":"        \u0027issued_at\u0027: \u00272018-06-29T02:36:48.000000Z\u0027"},{"line_number":49,"context_line":"    }"},{"line_number":50,"context_line":"}"}],"source_content_type":"text/x-python","patch_set":3,"id":"3f79a3b5_934ea837","line":47,"range":{"start_line":47,"start_character":22,"end_line":47,"end_character":52},"updated":"2018-10-18 23:17:51.000000000","message":"hard-coded times are tough, recommend using freezegun and generated timestamps on demand.","commit_id":"1514eaf699bfdd468229a80cbb89bda75ba20b30"},{"author":{"_account_id":2903,"name":"Morgan Fainberg","email":"morgan.fainberg@gmail.com","username":"mdrnstm"},"change_message_id":"faf9e8b05d91e5f803f765c1d64d405d14058b53","unresolved":false,"context_lines":[{"line_number":45,"context_line":"            }"},{"line_number":46,"context_line":"        },"},{"line_number":47,"context_line":"        \u0027expires_at\u0027: \u00272018-06-29T02:41:48.000000Z\u0027,"},{"line_number":48,"context_line":"        \u0027issued_at\u0027: \u00272018-06-29T02:36:48.000000Z\u0027"},{"line_number":49,"context_line":"    }"},{"line_number":50,"context_line":"}"},{"line_number":51,"context_line":""}],"source_content_type":"text/x-python","patch_set":3,"id":"3f79a3b5_535a50f5","line":48,"range":{"start_line":48,"start_character":21,"end_line":48,"end_character":50},"updated":"2018-10-18 23:17:51.000000000","message":"See above, re: timestamps.","commit_id":"1514eaf699bfdd468229a80cbb89bda75ba20b30"},{"author":{"_account_id":2903,"name":"Morgan Fainberg","email":"morgan.fainberg@gmail.com","username":"mdrnstm"},"change_message_id":"faf9e8b05d91e5f803f765c1d64d405d14058b53","unresolved":false,"context_lines":[{"line_number":52,"context_line":""},{"line_number":53,"context_line":"def create_v3_receipt():"},{"line_number":54,"context_line":"    receipt \u003d receipt_model.ReceiptModel()"},{"line_number":55,"context_line":"    receipt.user_id \u003d \"70d173f0a41a484d977b71a779836282\""},{"line_number":56,"context_line":"    receipt.methods \u003d []"},{"line_number":57,"context_line":"    receipt.expires_at \u003d utils.isotime(timeutils.utcnow() + FUTURE_DELTA)"},{"line_number":58,"context_line":"    receipt.mint("}],"source_content_type":"text/x-python","patch_set":3,"id":"3f79a3b5_1354d8c5","line":55,"range":{"start_line":55,"start_character":23,"end_line":55,"end_character":55},"updated":"2018-10-18 23:17:51.000000000","message":"generate an ID, don\u0027t hard-code.","commit_id":"1514eaf699bfdd468229a80cbb89bda75ba20b30"},{"author":{"_account_id":2903,"name":"Morgan Fainberg","email":"morgan.fainberg@gmail.com","username":"mdrnstm"},"change_message_id":"faf9e8b05d91e5f803f765c1d64d405d14058b53","unresolved":false,"context_lines":[{"line_number":56,"context_line":"    receipt.methods \u003d []"},{"line_number":57,"context_line":"    receipt.expires_at \u003d utils.isotime(timeutils.utcnow() + FUTURE_DELTA)"},{"line_number":58,"context_line":"    receipt.mint("},{"line_number":59,"context_line":"        \"70d173f0a41a484d977b71a779836282\", \"2013-05-21T00:02:43.941473Z\")"},{"line_number":60,"context_line":"    return receipt"},{"line_number":61,"context_line":""},{"line_number":62,"context_line":""}],"source_content_type":"text/x-python","patch_set":3,"id":"3f79a3b5_3359d4fc","line":59,"range":{"start_line":59,"start_character":8,"end_line":59,"end_character":73},"updated":"2018-10-18 23:17:51.000000000","message":"See above.","commit_id":"1514eaf699bfdd468229a80cbb89bda75ba20b30"},{"author":{"_account_id":2903,"name":"Morgan Fainberg","email":"morgan.fainberg@gmail.com","username":"mdrnstm"},"change_message_id":"faf9e8b05d91e5f803f765c1d64d405d14058b53","unresolved":false,"context_lines":[{"line_number":62,"context_line":""},{"line_number":63,"context_line":"SAMPLE_V3_RECEIPT_EXPIRED \u003d {"},{"line_number":64,"context_line":"    \"receipt\": {"},{"line_number":65,"context_line":"        \"expires_at\": utils.isotime(CURRENT_DATE),"},{"line_number":66,"context_line":"        \"issued_at\": \"2013-05-21T00:02:43.941473Z\","},{"line_number":67,"context_line":"    }"},{"line_number":68,"context_line":"}"},{"line_number":69,"context_line":""}],"source_content_type":"text/x-python","patch_set":3,"id":"3f79a3b5_d36d009b","line":66,"range":{"start_line":65,"start_character":0,"end_line":66,"end_character":51},"updated":"2018-10-18 23:17:51.000000000","message":"See above, re static time(s)","commit_id":"1514eaf699bfdd468229a80cbb89bda75ba20b30"}],"keystone/tests/unit/test_v3_auth.py":[{"author":{"_account_id":2903,"name":"Morgan Fainberg","email":"morgan.fainberg@gmail.com","username":"mdrnstm"},"change_message_id":"faf9e8b05d91e5f803f765c1d64d405d14058b53","unresolved":false,"context_lines":[{"line_number":55,"context_line":"class TestMFARules(test_v3.RestfulTestCase):"},{"line_number":56,"context_line":"    def config_overrides(self):"},{"line_number":57,"context_line":"        super(TestMFARules, self).config_overrides()"},{"line_number":58,"context_line":"        self.config_fixture.config(group\u003d\u0027receipt\u0027, cache_on_issue\u003dFalse)"},{"line_number":59,"context_line":""},{"line_number":60,"context_line":"        self.useFixture("},{"line_number":61,"context_line":"            ksfixtures.KeyRepository("}],"source_content_type":"text/x-python","patch_set":3,"id":"3f79a3b5_53ffb0b0","line":58,"updated":"2018-10-18 23:17:51.000000000","message":"Why are you disabling cache on issue here? the default behavior should be cache on issue. create a new test that explicitly tests with cache disabled (or a subclass with cache disabled as the only change)","commit_id":"1514eaf699bfdd468229a80cbb89bda75ba20b30"},{"author":{"_account_id":10420,"name":"Adrian Turjak","email":"devs+openstack@uncaught-exceptions.com","username":"adriant"},"change_message_id":"4fdd97b0e4b80de8385dcae32396aa8d86bf242f","unresolved":false,"context_lines":[{"line_number":55,"context_line":"class TestMFARules(test_v3.RestfulTestCase):"},{"line_number":56,"context_line":"    def config_overrides(self):"},{"line_number":57,"context_line":"        super(TestMFARules, self).config_overrides()"},{"line_number":58,"context_line":"        self.config_fixture.config(group\u003d\u0027receipt\u0027, cache_on_issue\u003dFalse)"},{"line_number":59,"context_line":""},{"line_number":60,"context_line":"        self.useFixture("},{"line_number":61,"context_line":"            ksfixtures.KeyRepository("}],"source_content_type":"text/x-python","patch_set":3,"id":"3f79a3b5_f29c7a0e","line":58,"in_reply_to":"3f79a3b5_53ffb0b0","updated":"2018-10-23 02:01:17.000000000","message":"I think this is an old leftover from some testing issues...","commit_id":"1514eaf699bfdd468229a80cbb89bda75ba20b30"}],"setup.cfg":[{"author":{"_account_id":5046,"name":"Lance Bragstad","email":"lbragstad@redhat.com","username":"ldbragst"},"change_message_id":"ff87b4cc7a66fc26f4c7cfa811bdcbc01e6555cf","unresolved":false,"context_lines":[{"line_number":145,"context_line":"keystone.token.provider \u003d"},{"line_number":146,"context_line":"    fernet \u003d keystone.token.providers.fernet:Provider"},{"line_number":147,"context_line":""},{"line_number":148,"context_line":"keystone.receipt.provider \u003d"},{"line_number":149,"context_line":"    fernet \u003d keystone.receipt.providers.fernet:Provider"},{"line_number":150,"context_line":""},{"line_number":151,"context_line":"keystone.trust \u003d"}],"source_content_type":"text/x-ttcn-cfg","patch_set":4,"id":"3f79a3b5_7bdfecd6","line":148,"updated":"2018-10-22 20:56:20.000000000","message":"Related to my other comment about pluggability, but do we think it\u0027s worth exposing this initially?","commit_id":"58fc38157efbe8e0dde7bbffe09b0c061619be99"}]}
