)]}'
{"/COMMIT_MSG":[{"author":{"_account_id":4,"name":"Dolph Mathews","email":"dolph.mathews@gmail.com","username":"dolph"},"change_message_id":"8a24a2d5d44a2de6ee0063cc1fa6c147d299b4ee","unresolved":false,"context_lines":[{"line_number":15,"context_line":"and be required to reset their password."},{"line_number":16,"context_line":""},{"line_number":17,"context_line":"Note: In a subsequent patch I\u0027ll expose password_expires_at to the API,"},{"line_number":18,"context_line":"so that clients can alert users before their password expires."},{"line_number":19,"context_line":""},{"line_number":20,"context_line":"Partially-implements: blueprint pci-dss"},{"line_number":21,"context_line":""}],"source_content_type":"text/x-gerrit-commit-message","patch_set":23,"id":"3aaa91ec_a5c94928","line":18,"updated":"2016-06-30 16:56:44.000000000","message":"Don\u0027t forget to propose the keystone-spec/api change first!","commit_id":"36500700b3fa0c1a6c560d6d173e00f2fce4ec76"},{"author":{"_account_id":18338,"name":"Ron De Rose","email":"ronald.de.rose@intel.com","username":"derosenet"},"change_message_id":"23cd7389f524ac007b84eb82bb63d7eaea0df036","unresolved":false,"context_lines":[{"line_number":15,"context_line":"and be required to reset their password."},{"line_number":16,"context_line":""},{"line_number":17,"context_line":"Note: In a subsequent patch I\u0027ll expose password_expires_at to the API,"},{"line_number":18,"context_line":"so that clients can alert users before their password expires."},{"line_number":19,"context_line":""},{"line_number":20,"context_line":"Partially-implements: blueprint pci-dss"},{"line_number":21,"context_line":""}],"source_content_type":"text/x-gerrit-commit-message","patch_set":23,"id":"3aaa91ec_2676f505","line":18,"in_reply_to":"3aaa91ec_0f54b7c7","updated":"2016-06-30 21:17:35.000000000","message":"Docs are actually in api-site.  I created a separate patch for the documentation changes:\nhttps://review.openstack.org/#/c/336292/","commit_id":"36500700b3fa0c1a6c560d6d173e00f2fce4ec76"},{"author":{"_account_id":18338,"name":"Ron De Rose","email":"ronald.de.rose@intel.com","username":"derosenet"},"change_message_id":"6997aef3ee0660e32b2e04223701ca3c98602898","unresolved":false,"context_lines":[{"line_number":15,"context_line":"and be required to reset their password."},{"line_number":16,"context_line":""},{"line_number":17,"context_line":"Note: In a subsequent patch I\u0027ll expose password_expires_at to the API,"},{"line_number":18,"context_line":"so that clients can alert users before their password expires."},{"line_number":19,"context_line":""},{"line_number":20,"context_line":"Partially-implements: blueprint pci-dss"},{"line_number":21,"context_line":""}],"source_content_type":"text/x-gerrit-commit-message","patch_set":23,"id":"3aaa91ec_0f54b7c7","line":18,"in_reply_to":"3aaa91ec_a5c94928","updated":"2016-06-30 19:28:16.000000000","message":"As we discussed, I\u0027ll make the api change in this patch instead.","commit_id":"36500700b3fa0c1a6c560d6d173e00f2fce4ec76"},{"author":{"_account_id":4,"name":"Dolph Mathews","email":"dolph.mathews@gmail.com","username":"dolph"},"change_message_id":"e2a026d51c16b4fecfe63342c5165f9e35f09da8","unresolved":false,"context_lines":[{"line_number":17,"context_line":"Note: this changes the API, adding a new user response attribute,"},{"line_number":18,"context_line":"password_expires_at. API documentation changes can be found here:"},{"line_number":19,"context_line":"https://review.openstack.org/336318"},{"line_number":20,"context_line":"https://review.openstack.org/340964"},{"line_number":21,"context_line":""},{"line_number":22,"context_line":"Partially-implements: blueprint pci-dss"},{"line_number":23,"context_line":""}],"source_content_type":"text/x-gerrit-commit-message","patch_set":33,"id":"1aa78d24_b23208f0","line":20,"updated":"2016-07-13 14:03:46.000000000","message":"Document and enforce this dependency with:\n\n  Depends-On: I07c10de627898d6ac79578dc24292ded4a2190f1\n\nAlternatively, this patch should depend directly on the api-ref changes, which should already have the Depends-On above. This helps us enforce a single source of truth for the API and ensures that all of our API-impacting features are properly documented.","commit_id":"6cc0b00a67f805a05902fcb27722ab8b44f456ad"},{"author":{"_account_id":18338,"name":"Ron De Rose","email":"ronald.de.rose@intel.com","username":"derosenet"},"change_message_id":"48d5cbe840456c904644c03398abc3353a203799","unresolved":false,"context_lines":[{"line_number":17,"context_line":"Note: this changes the API, adding a new user response attribute,"},{"line_number":18,"context_line":"password_expires_at. API documentation changes can be found here:"},{"line_number":19,"context_line":"https://review.openstack.org/336318"},{"line_number":20,"context_line":"https://review.openstack.org/340964"},{"line_number":21,"context_line":""},{"line_number":22,"context_line":"Partially-implements: blueprint pci-dss"},{"line_number":23,"context_line":""}],"source_content_type":"text/x-gerrit-commit-message","patch_set":33,"id":"1aa78d24_832d0091","line":20,"in_reply_to":"1aa78d24_b23208f0","updated":"2016-07-13 14:46:46.000000000","message":"Done","commit_id":"6cc0b00a67f805a05902fcb27722ab8b44f456ad"},{"author":{"_account_id":4,"name":"Dolph Mathews","email":"dolph.mathews@gmail.com","username":"dolph"},"change_message_id":"d20d9c518399b73f219bdf146f251251caf68e78","unresolved":false,"context_lines":[{"line_number":18,"context_line":""},{"line_number":19,"context_line":"Partially-implements: blueprint pci-dss"},{"line_number":20,"context_line":""},{"line_number":21,"context_line":"Change-Id: If8979dbfc202bc354b1537a5962143bb7b3be28e"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":35,"id":"dada55a8_825ae781","line":21,"updated":"2016-07-18 16:59:22.000000000","message":"Just a side note, the whitespace between the footer lines is unnecessary.","commit_id":"241c87093a5c27eef8c0c0c18caeed207d80f05f"},{"author":{"_account_id":7725,"name":"David Stanek","email":"dstanek@dstanek.com","username":"dstanek"},"change_message_id":"826877e7c26e18e84f53b1340a04411b1083e599","unresolved":false,"context_lines":[{"line_number":11,"context_line":"* PCI-DSS 8.2.4: Change user passwords/passphrases at least once every"},{"line_number":12,"context_line":"90 days."},{"line_number":13,"context_line":""},{"line_number":14,"context_line":"Once a user\u0027s passord is expired, they will not be able to authenticate"},{"line_number":15,"context_line":"and be required to reset their password. This patch adds a new"},{"line_number":16,"context_line":"password_expires_at attribute to the user response."},{"line_number":17,"context_line":""}],"source_content_type":"text/x-gerrit-commit-message","patch_set":43,"id":"bacf61ea_16ca926e","line":14,"updated":"2016-07-28 20:31:31.000000000","message":"password","commit_id":"b729a651e661f944fc592715ad13c837f1065038"},{"author":{"_account_id":18338,"name":"Ron De Rose","email":"ronald.de.rose@intel.com","username":"derosenet"},"change_message_id":"c85c120be130704db495ab702dd6b399c93d9a45","unresolved":false,"context_lines":[{"line_number":11,"context_line":"* PCI-DSS 8.2.4: Change user passwords/passphrases at least once every"},{"line_number":12,"context_line":"90 days."},{"line_number":13,"context_line":""},{"line_number":14,"context_line":"Once a user\u0027s passord is expired, they will not be able to authenticate"},{"line_number":15,"context_line":"and be required to reset their password. This patch adds a new"},{"line_number":16,"context_line":"password_expires_at attribute to the user response."},{"line_number":17,"context_line":""}],"source_content_type":"text/x-gerrit-commit-message","patch_set":43,"id":"bacf61ea_d770f4de","line":14,"in_reply_to":"bacf61ea_16ca926e","updated":"2016-07-28 21:38:30.000000000","message":"Done","commit_id":"b729a651e661f944fc592715ad13c837f1065038"}],"keystone/common/controller.py":[{"author":{"_account_id":5046,"name":"Lance Bragstad","email":"lbragstad@redhat.com","username":"ldbragst"},"change_message_id":"653c09de0dd4312cda94ce356a75f14a31a5bad2","unresolved":false,"context_lines":[{"line_number":322,"context_line":"                del ref[\u0027tenantId\u0027]"},{"line_number":323,"context_line":""},{"line_number":324,"context_line":"        def _filter_password_expires_at(ref):"},{"line_number":325,"context_line":"            \"\"\"Remove password_expires_at from v2 calls.\"\"\""},{"line_number":326,"context_line":"            ref.pop(\u0027password_expires_at\u0027, None)"},{"line_number":327,"context_line":"            return ref"},{"line_number":328,"context_line":""}],"source_content_type":"text/x-python","patch_set":39,"id":"dada55a8_44333214","line":325,"updated":"2016-07-27 13:53:40.000000000","message":"Are all other PCI-DSS changes v3 only?","commit_id":"9f78b63427273c97eb6b23c1a4993b55ad7eadb2"},{"author":{"_account_id":5046,"name":"Lance Bragstad","email":"lbragstad@redhat.com","username":"ldbragst"},"change_message_id":"4cb4c6e8218e64c748ef54c80c8aa8b9f3783e89","unresolved":false,"context_lines":[{"line_number":322,"context_line":"                del ref[\u0027tenantId\u0027]"},{"line_number":323,"context_line":""},{"line_number":324,"context_line":"        def _filter_password_expires_at(ref):"},{"line_number":325,"context_line":"            \"\"\"Remove password_expires_at from v2 calls.\"\"\""},{"line_number":326,"context_line":"            ref.pop(\u0027password_expires_at\u0027, None)"},{"line_number":327,"context_line":"            return ref"},{"line_number":328,"context_line":""}],"source_content_type":"text/x-python","patch_set":39,"id":"bacf61ea_90169cef","line":325,"in_reply_to":"bacf61ea_ddd507ba","updated":"2016-07-28 18:38:01.000000000","message":"++ I would agree with this since the v2.0 API is deprecated. In the past we\u0027ve talked about only continuing to support authentication on v2.0 and this doesn\u0027t seem critical to that case.","commit_id":"9f78b63427273c97eb6b23c1a4993b55ad7eadb2"},{"author":{"_account_id":18338,"name":"Ron De Rose","email":"ronald.de.rose@intel.com","username":"derosenet"},"change_message_id":"c82a2148dd09c3b0064abeea823818c5000ca2bf","unresolved":false,"context_lines":[{"line_number":322,"context_line":"                del ref[\u0027tenantId\u0027]"},{"line_number":323,"context_line":""},{"line_number":324,"context_line":"        def _filter_password_expires_at(ref):"},{"line_number":325,"context_line":"            \"\"\"Remove password_expires_at from v2 calls.\"\"\""},{"line_number":326,"context_line":"            ref.pop(\u0027password_expires_at\u0027, None)"},{"line_number":327,"context_line":"            return ref"},{"line_number":328,"context_line":""}],"source_content_type":"text/x-python","patch_set":39,"id":"bacf61ea_ddd507ba","line":325,"in_reply_to":"dada55a8_44333214","updated":"2016-07-27 15:58:30.000000000","message":"Not necessarily, but we didn\u0027t want to change the API for v2 by adding the password_expires_at attribute.","commit_id":"9f78b63427273c97eb6b23c1a4993b55ad7eadb2"},{"author":{"_account_id":5046,"name":"Lance Bragstad","email":"lbragstad@redhat.com","username":"ldbragst"},"change_message_id":"8a65c94052489874260740de14d39fda1c7fdbfa","unresolved":false,"context_lines":[{"line_number":329,"context_line":"        def _normalize_and_filter_user_properties(ref):"},{"line_number":330,"context_line":"            \"\"\"Run through the various filter/normalization methods.\"\"\""},{"line_number":331,"context_line":"            _format_default_project_id(ref)"},{"line_number":332,"context_line":"            _filter_password_expires_at(ref)"},{"line_number":333,"context_line":"            V2Controller.filter_domain(ref)"},{"line_number":334,"context_line":"            V2Controller.filter_domain_id(ref)"},{"line_number":335,"context_line":"            V2Controller.normalize_username_in_response(ref)"}],"source_content_type":"text/x-python","patch_set":42,"id":"bacf61ea_b007601b","line":332,"updated":"2016-07-28 14:38:56.000000000","message":"We should be sure to add a test for this.","commit_id":"51e0b88399458ac510309d357a2c33e688872335"},{"author":{"_account_id":18338,"name":"Ron De Rose","email":"ronald.de.rose@intel.com","username":"derosenet"},"change_message_id":"e45047597e9640be3d9d77b3cd76586b6414500f","unresolved":false,"context_lines":[{"line_number":329,"context_line":"        def _normalize_and_filter_user_properties(ref):"},{"line_number":330,"context_line":"            \"\"\"Run through the various filter/normalization methods.\"\"\""},{"line_number":331,"context_line":"            _format_default_project_id(ref)"},{"line_number":332,"context_line":"            _filter_password_expires_at(ref)"},{"line_number":333,"context_line":"            V2Controller.filter_domain(ref)"},{"line_number":334,"context_line":"            V2Controller.filter_domain_id(ref)"},{"line_number":335,"context_line":"            V2Controller.normalize_username_in_response(ref)"}],"source_content_type":"text/x-python","patch_set":42,"id":"bacf61ea_d663ec3f","line":332,"in_reply_to":"bacf61ea_b007601b","updated":"2016-07-28 14:59:19.000000000","message":"There is:\nhttps://review.openstack.org/#/c/333360/42/keystone/tests/unit/test_v3_identity.py","commit_id":"51e0b88399458ac510309d357a2c33e688872335"},{"author":{"_account_id":4,"name":"Dolph Mathews","email":"dolph.mathews@gmail.com","username":"dolph"},"change_message_id":"a13c686ff25e6fd9fac4387d7fd31d489cc9c554","unresolved":false,"context_lines":[{"line_number":304,"context_line":""},{"line_number":305,"context_line":"        * v2.0 users are not domain aware, and should have domain_id removed"},{"line_number":306,"context_line":"        * v2.0 users expect the use of tenantId instead of default_project_id"},{"line_number":307,"context_line":"        * v2.0 users have a username attribute"},{"line_number":308,"context_line":""},{"line_number":309,"context_line":"        If ref is a list type, we will iterate through each element and do the"},{"line_number":310,"context_line":"        conversion."}],"source_content_type":"text/x-python","patch_set":46,"id":"bacf61ea_4dbc49dc","side":"PARENT","line":307,"updated":"2016-07-29 17:57:05.000000000","message":"You should amend this list as well.","commit_id":"96af93d36151b04fc82c5c1db3615311bfda544e"},{"author":{"_account_id":18338,"name":"Ron De Rose","email":"ronald.de.rose@intel.com","username":"derosenet"},"change_message_id":"5e0fe54a7af473cfa2021fb1749cb8fd6b3bc7ea","unresolved":false,"context_lines":[{"line_number":304,"context_line":""},{"line_number":305,"context_line":"        * v2.0 users are not domain aware, and should have domain_id removed"},{"line_number":306,"context_line":"        * v2.0 users expect the use of tenantId instead of default_project_id"},{"line_number":307,"context_line":"        * v2.0 users have a username attribute"},{"line_number":308,"context_line":""},{"line_number":309,"context_line":"        If ref is a list type, we will iterate through each element and do the"},{"line_number":310,"context_line":"        conversion."}],"source_content_type":"text/x-python","patch_set":46,"id":"bacf61ea_a1995b7b","side":"PARENT","line":307,"in_reply_to":"bacf61ea_4dbc49dc","updated":"2016-08-05 13:14:49.000000000","message":"Done","commit_id":"96af93d36151b04fc82c5c1db3615311bfda544e"},{"author":{"_account_id":4,"name":"Dolph Mathews","email":"dolph.mathews@gmail.com","username":"dolph"},"change_message_id":"a13c686ff25e6fd9fac4387d7fd31d489cc9c554","unresolved":false,"context_lines":[{"line_number":329,"context_line":"        def _normalize_and_filter_user_properties(ref):"},{"line_number":330,"context_line":"            \"\"\"Run through the various filter/normalization methods.\"\"\""},{"line_number":331,"context_line":"            _format_default_project_id(ref)"},{"line_number":332,"context_line":"            _filter_password_expires_at(ref)"},{"line_number":333,"context_line":"            V2Controller.filter_domain(ref)"},{"line_number":334,"context_line":"            V2Controller.filter_domain_id(ref)"},{"line_number":335,"context_line":"            V2Controller.normalize_username_in_response(ref)"}],"source_content_type":"text/x-python","patch_set":46,"id":"bacf61ea_cde959e8","line":332,"updated":"2016-07-29 17:57:05.000000000","message":"Do you really need a dedicated method for a one liner that\u0027s not used anywhere else?","commit_id":"4eff51da89b8300c84b85f400e76a7dd2f5d010e"},{"author":{"_account_id":18338,"name":"Ron De Rose","email":"ronald.de.rose@intel.com","username":"derosenet"},"change_message_id":"5e0fe54a7af473cfa2021fb1749cb8fd6b3bc7ea","unresolved":false,"context_lines":[{"line_number":329,"context_line":"        def _normalize_and_filter_user_properties(ref):"},{"line_number":330,"context_line":"            \"\"\"Run through the various filter/normalization methods.\"\"\""},{"line_number":331,"context_line":"            _format_default_project_id(ref)"},{"line_number":332,"context_line":"            _filter_password_expires_at(ref)"},{"line_number":333,"context_line":"            V2Controller.filter_domain(ref)"},{"line_number":334,"context_line":"            V2Controller.filter_domain_id(ref)"},{"line_number":335,"context_line":"            V2Controller.normalize_username_in_response(ref)"}],"source_content_type":"text/x-python","patch_set":46,"id":"bacf61ea_e18d1332","line":332,"in_reply_to":"bacf61ea_cde959e8","updated":"2016-08-05 13:14:49.000000000","message":"Done","commit_id":"4eff51da89b8300c84b85f400e76a7dd2f5d010e"},{"author":{"_account_id":6482,"name":"Steve Martinelli","email":"s.martinelli@gmail.com","username":"stevemar"},"change_message_id":"810fcaba3cf65ff055fbc06d4d5e06e49a055759","unresolved":false,"context_lines":[{"line_number":325,"context_line":"        def _normalize_and_filter_user_properties(ref):"},{"line_number":326,"context_line":"            \"\"\"Run through the various filter/normalization methods.\"\"\""},{"line_number":327,"context_line":"            _format_default_project_id(ref)"},{"line_number":328,"context_line":"            ref.pop(\u0027password_expires_at\u0027, None)"},{"line_number":329,"context_line":"            V2Controller.filter_domain(ref)"},{"line_number":330,"context_line":"            V2Controller.filter_domain_id(ref)"},{"line_number":331,"context_line":"            V2Controller.normalize_username_in_response(ref)"}],"source_content_type":"text/x-python","patch_set":51,"id":"9ad45d7e_f7a3959c","line":328,"range":{"start_line":328,"start_character":12,"end_line":328,"end_character":48},"updated":"2016-08-09 08:04:56.000000000","message":"i don\u0027t know if we want to remove this from the v2 representation of a user. from an API point of view, they can still change their password in v2.0, and turning on PCI support doesn\u0027t depend on v3. not going to block this, but something to keep in mind.","commit_id":"041f53f2f6bad661ffd9946932005bf19dbccc9c"}],"keystone/conf/security_compliance.py":[{"author":{"_account_id":4,"name":"Dolph Mathews","email":"dolph.mathews@gmail.com","username":"dolph"},"change_message_id":"8a24a2d5d44a2de6ee0063cc1fa6c147d299b4ee","unresolved":false,"context_lines":[{"line_number":49,"context_line":"via the SQL backend driver for identity."},{"line_number":50,"context_line":"\"\"\"))"},{"line_number":51,"context_line":""},{"line_number":52,"context_line":"password_expires_ignore_list \u003d cfg.StrOpt("},{"line_number":53,"context_line":"    \u0027password_expires_ignore_list\u0027,"},{"line_number":54,"context_line":"    default\u003dNone,"},{"line_number":55,"context_line":"    help\u003dutils.fmt(\"\"\""}],"source_content_type":"text/x-python","patch_set":23,"id":"3aaa91ec_e59d110b","line":52,"updated":"2016-06-30 16:56:44.000000000","message":"ListOpt","commit_id":"36500700b3fa0c1a6c560d6d173e00f2fce4ec76"},{"author":{"_account_id":7725,"name":"David Stanek","email":"dstanek@dstanek.com","username":"dstanek"},"change_message_id":"e290b3d67b53106586162e8c89f577e157596319","unresolved":false,"context_lines":[{"line_number":49,"context_line":"via the SQL backend driver for identity."},{"line_number":50,"context_line":"\"\"\"))"},{"line_number":51,"context_line":""},{"line_number":52,"context_line":"password_expires_ignore_list \u003d cfg.StrOpt("},{"line_number":53,"context_line":"    \u0027password_expires_ignore_list\u0027,"},{"line_number":54,"context_line":"    default\u003dNone,"},{"line_number":55,"context_line":"    help\u003dutils.fmt(\"\"\""}],"source_content_type":"text/x-python","patch_set":23,"id":"3aaa91ec_45522536","line":52,"updated":"2016-06-30 16:58:07.000000000","message":"Should this be a List?","commit_id":"36500700b3fa0c1a6c560d6d173e00f2fce4ec76"},{"author":{"_account_id":18338,"name":"Ron De Rose","email":"ronald.de.rose@intel.com","username":"derosenet"},"change_message_id":"6997aef3ee0660e32b2e04223701ca3c98602898","unresolved":false,"context_lines":[{"line_number":49,"context_line":"via the SQL backend driver for identity."},{"line_number":50,"context_line":"\"\"\"))"},{"line_number":51,"context_line":""},{"line_number":52,"context_line":"password_expires_ignore_list \u003d cfg.StrOpt("},{"line_number":53,"context_line":"    \u0027password_expires_ignore_list\u0027,"},{"line_number":54,"context_line":"    default\u003dNone,"},{"line_number":55,"context_line":"    help\u003dutils.fmt(\"\"\""}],"source_content_type":"text/x-python","patch_set":23,"id":"3aaa91ec_cfa58fa2","line":52,"in_reply_to":"3aaa91ec_45522536","updated":"2016-06-30 19:28:16.000000000","message":"Yes, it should be a list.  Changed it in the latest patch.","commit_id":"36500700b3fa0c1a6c560d6d173e00f2fce4ec76"},{"author":{"_account_id":18338,"name":"Ron De Rose","email":"ronald.de.rose@intel.com","username":"derosenet"},"change_message_id":"6997aef3ee0660e32b2e04223701ca3c98602898","unresolved":false,"context_lines":[{"line_number":49,"context_line":"via the SQL backend driver for identity."},{"line_number":50,"context_line":"\"\"\"))"},{"line_number":51,"context_line":""},{"line_number":52,"context_line":"password_expires_ignore_list \u003d cfg.StrOpt("},{"line_number":53,"context_line":"    \u0027password_expires_ignore_list\u0027,"},{"line_number":54,"context_line":"    default\u003dNone,"},{"line_number":55,"context_line":"    help\u003dutils.fmt(\"\"\""}],"source_content_type":"text/x-python","patch_set":23,"id":"3aaa91ec_8f80a7f8","line":52,"in_reply_to":"3aaa91ec_e59d110b","updated":"2016-06-30 19:28:16.000000000","message":"Done","commit_id":"36500700b3fa0c1a6c560d6d173e00f2fce4ec76"},{"author":{"_account_id":4,"name":"Dolph Mathews","email":"dolph.mathews@gmail.com","username":"dolph"},"change_message_id":"8a24a2d5d44a2de6ee0063cc1fa6c147d299b4ee","unresolved":false,"context_lines":[{"line_number":51,"context_line":""},{"line_number":52,"context_line":"password_expires_ignore_list \u003d cfg.StrOpt("},{"line_number":53,"context_line":"    \u0027password_expires_ignore_list\u0027,"},{"line_number":54,"context_line":"    default\u003dNone,"},{"line_number":55,"context_line":"    help\u003dutils.fmt(\"\"\""},{"line_number":56,"context_line":"Comma separated list of user IDs to be ignored when checking if a password"},{"line_number":57,"context_line":"is expired. Thus, new passwords will not expire for users entered here."}],"source_content_type":"text/x-python","patch_set":23,"id":"3aaa91ec_a0013707","line":54,"updated":"2016-06-30 16:56:44.000000000","message":"default\u003d[]","commit_id":"36500700b3fa0c1a6c560d6d173e00f2fce4ec76"},{"author":{"_account_id":18338,"name":"Ron De Rose","email":"ronald.de.rose@intel.com","username":"derosenet"},"change_message_id":"6997aef3ee0660e32b2e04223701ca3c98602898","unresolved":false,"context_lines":[{"line_number":51,"context_line":""},{"line_number":52,"context_line":"password_expires_ignore_list \u003d cfg.StrOpt("},{"line_number":53,"context_line":"    \u0027password_expires_ignore_list\u0027,"},{"line_number":54,"context_line":"    default\u003dNone,"},{"line_number":55,"context_line":"    help\u003dutils.fmt(\"\"\""},{"line_number":56,"context_line":"Comma separated list of user IDs to be ignored when checking if a password"},{"line_number":57,"context_line":"is expired. Thus, new passwords will not expire for users entered here."}],"source_content_type":"text/x-python","patch_set":23,"id":"3aaa91ec_6f83bb03","line":54,"in_reply_to":"3aaa91ec_a0013707","updated":"2016-06-30 19:28:16.000000000","message":"Done","commit_id":"36500700b3fa0c1a6c560d6d173e00f2fce4ec76"},{"author":{"_account_id":5046,"name":"Lance Bragstad","email":"lbragstad@redhat.com","username":"ldbragst"},"change_message_id":"f49113d986aec86cd0656bb8dc8701bab38b43dc","unresolved":false,"context_lines":[{"line_number":54,"context_line":"    default\u003d[],"},{"line_number":55,"context_line":"    help\u003dutils.fmt(\"\"\""},{"line_number":56,"context_line":"Comma separated list of user IDs to be ignored when checking if a password"},{"line_number":57,"context_line":"is expired. Thus, new passwords will not expire for users entered here."},{"line_number":58,"context_line":"This feature will only be enabled if password_expires_days is set."},{"line_number":59,"context_line":"\"\"\"))"},{"line_number":60,"context_line":""}],"source_content_type":"text/x-python","patch_set":28,"id":"1aa78d24_aa52ff64","line":57,"updated":"2016-07-11 19:37:38.000000000","message":"Just new passwords or passwords in general won\u0027t expire here?","commit_id":"63ce5268ea14b1c2ad39229fd16b2be6da4cc498"},{"author":{"_account_id":5046,"name":"Lance Bragstad","email":"lbragstad@redhat.com","username":"ldbragst"},"change_message_id":"653c09de0dd4312cda94ce356a75f14a31a5bad2","unresolved":false,"context_lines":[{"line_number":68,"context_line":"    default\u003d[],"},{"line_number":69,"context_line":"    help\u003dutils.fmt(\"\"\""},{"line_number":70,"context_line":"Comma separated list of user IDs to be ignored when checking if a password"},{"line_number":71,"context_line":"is expired. Thus, new passwords will not expire for users entered here."},{"line_number":72,"context_line":"This feature will only be enabled if password_expires_days is set."},{"line_number":73,"context_line":"\"\"\"))"},{"line_number":74,"context_line":""}],"source_content_type":"text/x-python","patch_set":39,"id":"dada55a8_041f7ab7","line":71,"updated":"2016-07-27 13:53:40.000000000","message":"s/new//\n\nPasswords for users in this list won\u0027t expire regardless if they are new or old.","commit_id":"9f78b63427273c97eb6b23c1a4993b55ad7eadb2"},{"author":{"_account_id":18338,"name":"Ron De Rose","email":"ronald.de.rose@intel.com","username":"derosenet"},"change_message_id":"c82a2148dd09c3b0064abeea823818c5000ca2bf","unresolved":false,"context_lines":[{"line_number":68,"context_line":"    default\u003d[],"},{"line_number":69,"context_line":"    help\u003dutils.fmt(\"\"\""},{"line_number":70,"context_line":"Comma separated list of user IDs to be ignored when checking if a password"},{"line_number":71,"context_line":"is expired. Thus, new passwords will not expire for users entered here."},{"line_number":72,"context_line":"This feature will only be enabled if password_expires_days is set."},{"line_number":73,"context_line":"\"\"\"))"},{"line_number":74,"context_line":""}],"source_content_type":"text/x-python","patch_set":39,"id":"bacf61ea_ef5bf22c","line":71,"in_reply_to":"dada55a8_041f7ab7","updated":"2016-07-27 15:58:30.000000000","message":"Done","commit_id":"9f78b63427273c97eb6b23c1a4993b55ad7eadb2"},{"author":{"_account_id":7725,"name":"David Stanek","email":"dstanek@dstanek.com","username":"dstanek"},"change_message_id":"826877e7c26e18e84f53b1340a04411b1083e599","unresolved":false,"context_lines":[{"line_number":56,"context_line":"password_expires_days \u003d cfg.IntOpt("},{"line_number":57,"context_line":"    \u0027password_expires_days\u0027,"},{"line_number":58,"context_line":"    default\u003dNone,"},{"line_number":59,"context_line":"    min\u003d1,"},{"line_number":60,"context_line":"    help\u003dutils.fmt(\"\"\""},{"line_number":61,"context_line":"The number of days which a password will be considered valid before requiring"},{"line_number":62,"context_line":"the user to change it. Setting the value to zero (the default) disables this"}],"source_content_type":"text/x-python","patch_set":43,"id":"bacf61ea_56a9aa7a","line":59,"updated":"2016-07-28 20:31:31.000000000","message":"Does this mean that password have to expire? Or is there a way to turn it off?","commit_id":"b729a651e661f944fc592715ad13c837f1065038"},{"author":{"_account_id":18338,"name":"Ron De Rose","email":"ronald.de.rose@intel.com","username":"derosenet"},"change_message_id":"2bb27190b46f136419203d8727a9bc4f3bc21dcd","unresolved":false,"context_lines":[{"line_number":56,"context_line":"password_expires_days \u003d cfg.IntOpt("},{"line_number":57,"context_line":"    \u0027password_expires_days\u0027,"},{"line_number":58,"context_line":"    default\u003dNone,"},{"line_number":59,"context_line":"    min\u003d1,"},{"line_number":60,"context_line":"    help\u003dutils.fmt(\"\"\""},{"line_number":61,"context_line":"The number of days which a password will be considered valid before requiring"},{"line_number":62,"context_line":"the user to change it. Setting the value to zero (the default) disables this"}],"source_content_type":"text/x-python","patch_set":43,"id":"bacf61ea_f1354846","line":59,"in_reply_to":"bacf61ea_56a9aa7a","updated":"2016-07-28 20:54:35.000000000","message":"This means that the minimum value has to be 1 or greater. A one would indicate that newly created passwords would expire in one day. To turn this off, you would remove this config option. However, any password that have an expires_at value would still be validated.","commit_id":"b729a651e661f944fc592715ad13c837f1065038"},{"author":{"_account_id":8119,"name":"Eric Brown","email":"eric_wade_brown@yahoo.com","username":"ericwb"},"change_message_id":"1e3e79ff66bd9d70ac3dd93662e06263d910bcbd","unresolved":false,"context_lines":[{"line_number":59,"context_line":"    min\u003d1,"},{"line_number":60,"context_line":"    help\u003dutils.fmt(\"\"\""},{"line_number":61,"context_line":"The number of days which a password will be considered valid before requiring"},{"line_number":62,"context_line":"the user to change it. Setting the value to zero (the default) disables this"},{"line_number":63,"context_line":"feature. This feature depends on the `sql` backend for the `[identity] driver`."},{"line_number":64,"context_line":"\"\"\"))"},{"line_number":65,"context_line":""}],"source_content_type":"text/x-python","patch_set":44,"id":"bacf61ea_299ad863","line":62,"range":{"start_line":62,"start_character":44,"end_line":62,"end_character":62},"updated":"2016-07-28 21:57:42.000000000","message":"This isn\u0027t true now with the changes above.","commit_id":"dd63b5aeeebd12a39e2497425220d77b9b9f4306"},{"author":{"_account_id":18338,"name":"Ron De Rose","email":"ronald.de.rose@intel.com","username":"derosenet"},"change_message_id":"65ac91f2f772eb38660e6472f7448f2fa9f78ca3","unresolved":false,"context_lines":[{"line_number":59,"context_line":"    min\u003d1,"},{"line_number":60,"context_line":"    help\u003dutils.fmt(\"\"\""},{"line_number":61,"context_line":"The number of days which a password will be considered valid before requiring"},{"line_number":62,"context_line":"the user to change it. Setting the value to zero (the default) disables this"},{"line_number":63,"context_line":"feature. This feature depends on the `sql` backend for the `[identity] driver`."},{"line_number":64,"context_line":"\"\"\"))"},{"line_number":65,"context_line":""}],"source_content_type":"text/x-python","patch_set":44,"id":"bacf61ea_cc922a4b","line":62,"range":{"start_line":62,"start_character":44,"end_line":62,"end_character":62},"in_reply_to":"bacf61ea_299ad863","updated":"2016-07-28 22:23:26.000000000","message":"Done","commit_id":"dd63b5aeeebd12a39e2497425220d77b9b9f4306"},{"author":{"_account_id":4,"name":"Dolph Mathews","email":"dolph.mathews@gmail.com","username":"dolph"},"change_message_id":"a13c686ff25e6fd9fac4387d7fd31d489cc9c554","unresolved":false,"context_lines":[{"line_number":60,"context_line":"    help\u003dutils.fmt(\"\"\""},{"line_number":61,"context_line":"The number of days for which a password will be considered valid"},{"line_number":62,"context_line":"before requiring it to be changed. This feature is disabled by default. If"},{"line_number":63,"context_line":"enabled, newly created passwords will have an expired date, however existing"},{"line_number":64,"context_line":"passwords would not be impacted. This feature depends on the `sql` backend for"},{"line_number":65,"context_line":"the `[identity] driver`."},{"line_number":66,"context_line":"\"\"\"))"}],"source_content_type":"text/x-python","patch_set":46,"id":"bacf61ea_4da3a9b2","line":63,"updated":"2016-07-29 17:57:05.000000000","message":"I know what you mean by \"newly created passwords\", but an end user might not realize that this also includes updated passwords.\n\nexpiration* date","commit_id":"4eff51da89b8300c84b85f400e76a7dd2f5d010e"},{"author":{"_account_id":18338,"name":"Ron De Rose","email":"ronald.de.rose@intel.com","username":"derosenet"},"change_message_id":"5e0fe54a7af473cfa2021fb1749cb8fd6b3bc7ea","unresolved":false,"context_lines":[{"line_number":60,"context_line":"    help\u003dutils.fmt(\"\"\""},{"line_number":61,"context_line":"The number of days for which a password will be considered valid"},{"line_number":62,"context_line":"before requiring it to be changed. This feature is disabled by default. If"},{"line_number":63,"context_line":"enabled, newly created passwords will have an expired date, however existing"},{"line_number":64,"context_line":"passwords would not be impacted. This feature depends on the `sql` backend for"},{"line_number":65,"context_line":"the `[identity] driver`."},{"line_number":66,"context_line":"\"\"\"))"}],"source_content_type":"text/x-python","patch_set":46,"id":"bacf61ea_2100cb65","line":63,"in_reply_to":"bacf61ea_4da3a9b2","updated":"2016-08-05 13:14:49.000000000","message":"Done","commit_id":"4eff51da89b8300c84b85f400e76a7dd2f5d010e"},{"author":{"_account_id":4,"name":"Dolph Mathews","email":"dolph.mathews@gmail.com","username":"dolph"},"change_message_id":"a13c686ff25e6fd9fac4387d7fd31d489cc9c554","unresolved":false,"context_lines":[{"line_number":66,"context_line":"\"\"\"))"},{"line_number":67,"context_line":""},{"line_number":68,"context_line":"password_expires_ignore_list \u003d cfg.ListOpt("},{"line_number":69,"context_line":"    \u0027password_expires_ignore_list\u0027,"},{"line_number":70,"context_line":"    default\u003d[],"},{"line_number":71,"context_line":"    help\u003dutils.fmt(\"\"\""},{"line_number":72,"context_line":"Comma separated list of user IDs to be ignored when checking if a password"}],"source_content_type":"text/x-python","patch_set":46,"id":"bacf61ea_cda5d9a2","line":69,"updated":"2016-07-29 17:57:05.000000000","message":"I still don\u0027t really understand this use case for this one. It\u0027s also an anti-pattern to have to drop user IDs into configuration files after keystone has already been deployed. I\u0027d suggest ripping this feature out and proposing it as a discrete patch so that this use case can be discussed in isolation.\n\nRealistically, either people are going to enable this feature because they need to be compliant, or they\u0027re not going to enable it. I can\u0027t imagine anyone will be able to justify a partially PCI compliant deployment as being useful.","commit_id":"4eff51da89b8300c84b85f400e76a7dd2f5d010e"},{"author":{"_account_id":18338,"name":"Ron De Rose","email":"ronald.de.rose@intel.com","username":"derosenet"},"change_message_id":"5e0fe54a7af473cfa2021fb1749cb8fd6b3bc7ea","unresolved":false,"context_lines":[{"line_number":66,"context_line":"\"\"\"))"},{"line_number":67,"context_line":""},{"line_number":68,"context_line":"password_expires_ignore_list \u003d cfg.ListOpt("},{"line_number":69,"context_line":"    \u0027password_expires_ignore_list\u0027,"},{"line_number":70,"context_line":"    default\u003d[],"},{"line_number":71,"context_line":"    help\u003dutils.fmt(\"\"\""},{"line_number":72,"context_line":"Comma separated list of user IDs to be ignored when checking if a password"}],"source_content_type":"text/x-python","patch_set":46,"id":"bacf61ea_613da32a","line":69,"in_reply_to":"bacf61ea_cda5d9a2","updated":"2016-08-05 13:14:49.000000000","message":"Took this out and will create a separate patch for this.","commit_id":"4eff51da89b8300c84b85f400e76a7dd2f5d010e"}],"keystone/exception.py":[{"author":{"_account_id":4,"name":"Dolph Mathews","email":"dolph.mathews@gmail.com","username":"dolph"},"change_message_id":"a13c686ff25e6fd9fac4387d7fd31d489cc9c554","unresolved":false,"context_lines":[{"line_number":204,"context_line":""},{"line_number":205,"context_line":""},{"line_number":206,"context_line":"class PasswordExpired(Unauthorized):"},{"line_number":207,"context_line":"    message_format \u003d _(\"The password is expired for user: %(user_id)s\")"},{"line_number":208,"context_line":""},{"line_number":209,"context_line":""},{"line_number":210,"context_line":"class AuthPluginException(Unauthorized):"}],"source_content_type":"text/x-python","patch_set":46,"id":"bacf61ea_2de475df","line":207,"updated":"2016-07-29 17:57:05.000000000","message":"You could also include something helpful for end users to resolve the situation - like suggest that the password needs to be reset by an administrator.","commit_id":"4eff51da89b8300c84b85f400e76a7dd2f5d010e"},{"author":{"_account_id":18338,"name":"Ron De Rose","email":"ronald.de.rose@intel.com","username":"derosenet"},"change_message_id":"5e0fe54a7af473cfa2021fb1749cb8fd6b3bc7ea","unresolved":false,"context_lines":[{"line_number":204,"context_line":""},{"line_number":205,"context_line":""},{"line_number":206,"context_line":"class PasswordExpired(Unauthorized):"},{"line_number":207,"context_line":"    message_format \u003d _(\"The password is expired for user: %(user_id)s\")"},{"line_number":208,"context_line":""},{"line_number":209,"context_line":""},{"line_number":210,"context_line":"class AuthPluginException(Unauthorized):"}],"source_content_type":"text/x-python","patch_set":46,"id":"bacf61ea_21ea8b74","line":207,"in_reply_to":"bacf61ea_2de475df","updated":"2016-08-05 13:14:49.000000000","message":"Done","commit_id":"4eff51da89b8300c84b85f400e76a7dd2f5d010e"}],"keystone/identity/backends/base.py":[{"author":{"_account_id":4,"name":"Dolph Mathews","email":"dolph.mathews@gmail.com","username":"dolph"},"change_message_id":"8a24a2d5d44a2de6ee0063cc1fa6c147d299b4ee","unresolved":false,"context_lines":[{"line_number":44,"context_line":"            # ok to not have extra in the user_ref."},{"line_number":45,"context_line":"            pass"},{"line_number":46,"context_line":"        if \u0027password_expires_at\u0027 not in user_ref:"},{"line_number":47,"context_line":"            user_ref[\u0027password_expires_at\u0027] \u003d None"},{"line_number":48,"context_line":"    return user_ref"},{"line_number":49,"context_line":""},{"line_number":50,"context_line":""}],"source_content_type":"text/x-python","patch_set":23,"id":"3aaa91ec_e06cdfd1","line":47,"updated":"2016-06-30 16:56:44.000000000","message":"-2 without a spec proposal: This is exposing a new attribute to the API!","commit_id":"36500700b3fa0c1a6c560d6d173e00f2fce4ec76"},{"author":{"_account_id":4,"name":"Dolph Mathews","email":"dolph.mathews@gmail.com","username":"dolph"},"change_message_id":"8a24a2d5d44a2de6ee0063cc1fa6c147d299b4ee","unresolved":false,"context_lines":[{"line_number":62,"context_line":"    * the domain_id should not be returned in user / group refs. They\u0027ll be"},{"line_number":63,"context_line":"      overwritten."},{"line_number":64,"context_line":""},{"line_number":65,"context_line":"    The password_expires_at in the user schema is a read-only attribte,"},{"line_number":66,"context_line":"    meaning that it is expected in the response, but not in the request."},{"line_number":67,"context_line":""},{"line_number":68,"context_line":"    User schema (if driver is domain aware)::"}],"source_content_type":"text/x-python","patch_set":23,"id":"3aaa91ec_e0a33ffe","line":65,"updated":"2016-06-30 16:56:44.000000000","message":"attribute","commit_id":"36500700b3fa0c1a6c560d6d173e00f2fce4ec76"},{"author":{"_account_id":18338,"name":"Ron De Rose","email":"ronald.de.rose@intel.com","username":"derosenet"},"change_message_id":"6997aef3ee0660e32b2e04223701ca3c98602898","unresolved":false,"context_lines":[{"line_number":62,"context_line":"    * the domain_id should not be returned in user / group refs. They\u0027ll be"},{"line_number":63,"context_line":"      overwritten."},{"line_number":64,"context_line":""},{"line_number":65,"context_line":"    The password_expires_at in the user schema is a read-only attribte,"},{"line_number":66,"context_line":"    meaning that it is expected in the response, but not in the request."},{"line_number":67,"context_line":""},{"line_number":68,"context_line":"    User schema (if driver is domain aware)::"}],"source_content_type":"text/x-python","patch_set":23,"id":"3aaa91ec_95a0b491","line":65,"in_reply_to":"3aaa91ec_e0a33ffe","updated":"2016-06-30 19:28:16.000000000","message":"Done","commit_id":"36500700b3fa0c1a6c560d6d173e00f2fce4ec76"}],"keystone/identity/backends/sql.py":[{"author":{"_account_id":5707,"name":"Henry Nash","email":"henryn@linux.vnet.ibm.com","username":"henry-nash"},"change_message_id":"678c71a99e02e7d5b4127179a1c07bd138871e6b","unresolved":false,"context_lines":[{"line_number":113,"context_line":"                old_user_dict[k] \u003d user[k]"},{"line_number":114,"context_line":"            new_user \u003d model.User.from_dict(old_user_dict)"},{"line_number":115,"context_line":"            for attr in model.User.attributes:"},{"line_number":116,"context_line":"                if attr !\u003d \u0027id\u0027 and attr not in model.User.readonly_attributes:"},{"line_number":117,"context_line":"                    setattr(user_ref, attr, getattr(new_user, attr))"},{"line_number":118,"context_line":"            user_ref.extra \u003d new_user.extra"},{"line_number":119,"context_line":"            return base.filter_user("}],"source_content_type":"text/x-python","patch_set":33,"id":"1aa78d24_22c38139","line":116,"range":{"start_line":116,"start_character":32,"end_line":116,"end_character":78},"updated":"2016-07-13 07:27:12.000000000","message":"so we are silent if I try and set my password_expires_at? That seems odd...unless we have decided that is how we should treat all readonly attributes (in which case this is fine)","commit_id":"6cc0b00a67f805a05902fcb27722ab8b44f456ad"},{"author":{"_account_id":18338,"name":"Ron De Rose","email":"ronald.de.rose@intel.com","username":"derosenet"},"change_message_id":"7a180ca4753cd4bee554e9ed58dd86584e931520","unresolved":false,"context_lines":[{"line_number":113,"context_line":"                old_user_dict[k] \u003d user[k]"},{"line_number":114,"context_line":"            new_user \u003d model.User.from_dict(old_user_dict)"},{"line_number":115,"context_line":"            for attr in model.User.attributes:"},{"line_number":116,"context_line":"                if attr !\u003d \u0027id\u0027 and attr not in model.User.readonly_attributes:"},{"line_number":117,"context_line":"                    setattr(user_ref, attr, getattr(new_user, attr))"},{"line_number":118,"context_line":"            user_ref.extra \u003d new_user.extra"},{"line_number":119,"context_line":"            return base.filter_user("}],"source_content_type":"text/x-python","patch_set":33,"id":"dada55a8_048fdecc","line":116,"range":{"start_line":116,"start_character":32,"end_line":116,"end_character":78},"in_reply_to":"1aa78d24_22c38139","updated":"2016-07-25 20:11:44.000000000","message":"Validating user input is handled in higher level code. However, this is needed here because when to_dict(...) is called, it will add the read-only attributes, which we want to ignore.","commit_id":"6cc0b00a67f805a05902fcb27722ab8b44f456ad"},{"author":{"_account_id":4,"name":"Dolph Mathews","email":"dolph.mathews@gmail.com","username":"dolph"},"change_message_id":"a13c686ff25e6fd9fac4387d7fd31d489cc9c554","unresolved":false,"context_lines":[{"line_number":113,"context_line":"                old_user_dict[k] \u003d user[k]"},{"line_number":114,"context_line":"            new_user \u003d model.User.from_dict(old_user_dict)"},{"line_number":115,"context_line":"            for attr in model.User.attributes:"},{"line_number":116,"context_line":"                if attr !\u003d \u0027id\u0027 and attr not in model.User.readonly_attributes:"},{"line_number":117,"context_line":"                    setattr(user_ref, attr, getattr(new_user, attr))"},{"line_number":118,"context_line":"            user_ref.extra \u003d new_user.extra"},{"line_number":119,"context_line":"            return base.filter_user("}],"source_content_type":"text/x-python","patch_set":46,"id":"bacf61ea_adf7c589","line":116,"updated":"2016-07-29 17:57:05.000000000","message":"should id just be in the list of readonly attributes too?\n\nBut more importantly, if these readonly attributes are in the request, then I\u0027d expect a 400 response, not for parts of the request to be silently ignored.","commit_id":"4eff51da89b8300c84b85f400e76a7dd2f5d010e"},{"author":{"_account_id":18338,"name":"Ron De Rose","email":"ronald.de.rose@intel.com","username":"derosenet"},"change_message_id":"5e0fe54a7af473cfa2021fb1749cb8fd6b3bc7ea","unresolved":false,"context_lines":[{"line_number":113,"context_line":"                old_user_dict[k] \u003d user[k]"},{"line_number":114,"context_line":"            new_user \u003d model.User.from_dict(old_user_dict)"},{"line_number":115,"context_line":"            for attr in model.User.attributes:"},{"line_number":116,"context_line":"                if attr !\u003d \u0027id\u0027 and attr not in model.User.readonly_attributes:"},{"line_number":117,"context_line":"                    setattr(user_ref, attr, getattr(new_user, attr))"},{"line_number":118,"context_line":"            user_ref.extra \u003d new_user.extra"},{"line_number":119,"context_line":"            return base.filter_user("}],"source_content_type":"text/x-python","patch_set":46,"id":"bacf61ea_fc9bf8c6","line":116,"in_reply_to":"bacf61ea_adf7c589","updated":"2016-08-05 13:14:49.000000000","message":"I added \u0027id\u0027 to the read-only attributes. This doesn\u0027t mean that the read-only attributes are in the request. This for loop is simply iterating through all of the User attributes and setting them.","commit_id":"4eff51da89b8300c84b85f400e76a7dd2f5d010e"}],"keystone/identity/backends/sql_model.py":[{"author":{"_account_id":4,"name":"Dolph Mathews","email":"dolph.mathews@gmail.com","username":"dolph"},"change_message_id":"8a24a2d5d44a2de6ee0063cc1fa6c147d299b4ee","unresolved":false,"context_lines":[{"line_number":14,"context_line":""},{"line_number":15,"context_line":"import datetime"},{"line_number":16,"context_line":""},{"line_number":17,"context_line":"from oslo_config import cfg"},{"line_number":18,"context_line":"from oslo_log import log"},{"line_number":19,"context_line":"import sqlalchemy"},{"line_number":20,"context_line":"from sqlalchemy.ext.hybrid import hybrid_property"}],"source_content_type":"text/x-python","patch_set":23,"id":"3aaa91ec_a0ebf711","line":17,"updated":"2016-06-30 16:56:44.000000000","message":"keystone.conf etc","commit_id":"36500700b3fa0c1a6c560d6d173e00f2fce4ec76"},{"author":{"_account_id":18338,"name":"Ron De Rose","email":"ronald.de.rose@intel.com","username":"derosenet"},"change_message_id":"6997aef3ee0660e32b2e04223701ca3c98602898","unresolved":false,"context_lines":[{"line_number":14,"context_line":""},{"line_number":15,"context_line":"import datetime"},{"line_number":16,"context_line":""},{"line_number":17,"context_line":"from oslo_config import cfg"},{"line_number":18,"context_line":"from oslo_log import log"},{"line_number":19,"context_line":"import sqlalchemy"},{"line_number":20,"context_line":"from sqlalchemy.ext.hybrid import hybrid_property"}],"source_content_type":"text/x-python","patch_set":23,"id":"3aaa91ec_35c90027","line":17,"in_reply_to":"3aaa91ec_a0ebf711","updated":"2016-06-30 19:28:16.000000000","message":"Done","commit_id":"36500700b3fa0c1a6c560d6d173e00f2fce4ec76"},{"author":{"_account_id":7725,"name":"David Stanek","email":"dstanek@dstanek.com","username":"dstanek"},"change_message_id":"e290b3d67b53106586162e8c89f577e157596319","unresolved":false,"context_lines":[{"line_number":148,"context_line":"    def from_dict(cls, user_dict):"},{"line_number":149,"context_line":"        for attribute in cls.readonly_attributes:"},{"line_number":150,"context_line":"            if attribute in user_dict:"},{"line_number":151,"context_line":"                del user_dict[attribute]"},{"line_number":152,"context_line":"        return super(User, cls).from_dict(user_dict)"},{"line_number":153,"context_line":""},{"line_number":154,"context_line":""}],"source_content_type":"text/x-python","patch_set":23,"id":"3aaa91ec_80eebb1f","line":151,"updated":"2016-06-30 16:58:07.000000000","message":"Should we make a copy of this dict before we edit it?","commit_id":"36500700b3fa0c1a6c560d6d173e00f2fce4ec76"},{"author":{"_account_id":18338,"name":"Ron De Rose","email":"ronald.de.rose@intel.com","username":"derosenet"},"change_message_id":"6997aef3ee0660e32b2e04223701ca3c98602898","unresolved":false,"context_lines":[{"line_number":148,"context_line":"    def from_dict(cls, user_dict):"},{"line_number":149,"context_line":"        for attribute in cls.readonly_attributes:"},{"line_number":150,"context_line":"            if attribute in user_dict:"},{"line_number":151,"context_line":"                del user_dict[attribute]"},{"line_number":152,"context_line":"        return super(User, cls).from_dict(user_dict)"},{"line_number":153,"context_line":""},{"line_number":154,"context_line":""}],"source_content_type":"text/x-python","patch_set":23,"id":"3aaa91ec_80b4f481","line":151,"in_reply_to":"3aaa91ec_80eebb1f","updated":"2016-06-30 19:28:16.000000000","message":"Done","commit_id":"36500700b3fa0c1a6c560d6d173e00f2fce4ec76"},{"author":{"_account_id":5046,"name":"Lance Bragstad","email":"lbragstad@redhat.com","username":"ldbragst"},"change_message_id":"5f96f2db44b92814102f9728e4428b0bb87ac662","unresolved":false,"context_lines":[{"line_number":244,"context_line":"    def get(cls, user_id, created_at):"},{"line_number":245,"context_line":"        if not cls._is_in_ignore_list(user_id):"},{"line_number":246,"context_line":"            expires_days \u003d CONF.security_compliance.password_expires_days"},{"line_number":247,"context_line":"            if expires_days and expires_days \u003e 0:"},{"line_number":248,"context_line":"                expired_date \u003d ("},{"line_number":249,"context_line":"                    created_at + datetime.timedelta(days\u003dexpires_days))"},{"line_number":250,"context_line":"                return expired_date.replace(microsecond\u003d0)"}],"source_content_type":"text/x-python","patch_set":23,"id":"3aaa91ec_8fae9ce5","line":247,"updated":"2016-06-27 20:15:15.000000000","message":"would we just be able to validate this with: \n\n    if expires_days \u003e 0:\n\n?","commit_id":"36500700b3fa0c1a6c560d6d173e00f2fce4ec76"},{"author":{"_account_id":7725,"name":"David Stanek","email":"dstanek@dstanek.com","username":"dstanek"},"change_message_id":"e290b3d67b53106586162e8c89f577e157596319","unresolved":false,"context_lines":[{"line_number":244,"context_line":"    def get(cls, user_id, created_at):"},{"line_number":245,"context_line":"        if not cls._is_in_ignore_list(user_id):"},{"line_number":246,"context_line":"            expires_days \u003d CONF.security_compliance.password_expires_days"},{"line_number":247,"context_line":"            if expires_days and expires_days \u003e 0:"},{"line_number":248,"context_line":"                expired_date \u003d ("},{"line_number":249,"context_line":"                    created_at + datetime.timedelta(days\u003dexpires_days))"},{"line_number":250,"context_line":"                return expired_date.replace(microsecond\u003d0)"}],"source_content_type":"text/x-python","patch_set":23,"id":"3aaa91ec_606bcf85","line":247,"in_reply_to":"3aaa91ec_2a24b6ad","updated":"2016-06-30 16:58:07.000000000","message":"Yes, \"if expires_dates:\" would work","commit_id":"36500700b3fa0c1a6c560d6d173e00f2fce4ec76"},{"author":{"_account_id":18338,"name":"Ron De Rose","email":"ronald.de.rose@intel.com","username":"derosenet"},"change_message_id":"6997aef3ee0660e32b2e04223701ca3c98602898","unresolved":false,"context_lines":[{"line_number":244,"context_line":"    def get(cls, user_id, created_at):"},{"line_number":245,"context_line":"        if not cls._is_in_ignore_list(user_id):"},{"line_number":246,"context_line":"            expires_days \u003d CONF.security_compliance.password_expires_days"},{"line_number":247,"context_line":"            if expires_days and expires_days \u003e 0:"},{"line_number":248,"context_line":"                expired_date \u003d ("},{"line_number":249,"context_line":"                    created_at + datetime.timedelta(days\u003dexpires_days))"},{"line_number":250,"context_line":"                return expired_date.replace(microsecond\u003d0)"}],"source_content_type":"text/x-python","patch_set":23,"id":"3aaa91ec_dbb70d1f","line":247,"in_reply_to":"3aaa91ec_606bcf85","updated":"2016-06-30 19:28:16.000000000","message":"Done","commit_id":"36500700b3fa0c1a6c560d6d173e00f2fce4ec76"},{"author":{"_account_id":18338,"name":"Ron De Rose","email":"ronald.de.rose@intel.com","username":"derosenet"},"change_message_id":"8efda77cbff2722d3fcf785c194278e1b6049d38","unresolved":false,"context_lines":[{"line_number":244,"context_line":"    def get(cls, user_id, created_at):"},{"line_number":245,"context_line":"        if not cls._is_in_ignore_list(user_id):"},{"line_number":246,"context_line":"            expires_days \u003d CONF.security_compliance.password_expires_days"},{"line_number":247,"context_line":"            if expires_days and expires_days \u003e 0:"},{"line_number":248,"context_line":"                expired_date \u003d ("},{"line_number":249,"context_line":"                    created_at + datetime.timedelta(days\u003dexpires_days))"},{"line_number":250,"context_line":"                return expired_date.replace(microsecond\u003d0)"}],"source_content_type":"text/x-python","patch_set":23,"id":"3aaa91ec_2a24b6ad","line":247,"in_reply_to":"3aaa91ec_8fae9ce5","updated":"2016-06-27 20:32:45.000000000","message":"I think now we could even just say \"if expires_days\" because in the config, we have a minimum set to 1. I\u0027ll refactor this if I create another patch.","commit_id":"36500700b3fa0c1a6c560d6d173e00f2fce4ec76"},{"author":{"_account_id":7725,"name":"David Stanek","email":"dstanek@dstanek.com","username":"dstanek"},"change_message_id":"e290b3d67b53106586162e8c89f577e157596319","unresolved":false,"context_lines":[{"line_number":255,"context_line":"        ignore_str \u003d CONF.security_compliance.password_expires_ignore_list"},{"line_number":256,"context_line":"        if ignore_str:"},{"line_number":257,"context_line":"            try:"},{"line_number":258,"context_line":"                ignore_list \u003d ignore_str.split(\u0027,\u0027)"},{"line_number":259,"context_line":"                return user_id in ignore_list"},{"line_number":260,"context_line":"            except Exception:"},{"line_number":261,"context_line":"                LOG.warning("}],"source_content_type":"text/x-python","patch_set":23,"id":"3aaa91ec_404fb333","line":258,"updated":"2016-06-30 16:58:07.000000000","message":"do you need to strip possible spaces?","commit_id":"36500700b3fa0c1a6c560d6d173e00f2fce4ec76"},{"author":{"_account_id":18338,"name":"Ron De Rose","email":"ronald.de.rose@intel.com","username":"derosenet"},"change_message_id":"6997aef3ee0660e32b2e04223701ca3c98602898","unresolved":false,"context_lines":[{"line_number":255,"context_line":"        ignore_str \u003d CONF.security_compliance.password_expires_ignore_list"},{"line_number":256,"context_line":"        if ignore_str:"},{"line_number":257,"context_line":"            try:"},{"line_number":258,"context_line":"                ignore_list \u003d ignore_str.split(\u0027,\u0027)"},{"line_number":259,"context_line":"                return user_id in ignore_list"},{"line_number":260,"context_line":"            except Exception:"},{"line_number":261,"context_line":"                LOG.warning("}],"source_content_type":"text/x-python","patch_set":23,"id":"3aaa91ec_5b595dfc","line":258,"in_reply_to":"3aaa91ec_404fb333","updated":"2016-06-30 19:28:16.000000000","message":"Replaced this by using the ListOpt from the config.","commit_id":"36500700b3fa0c1a6c560d6d173e00f2fce4ec76"},{"author":{"_account_id":4,"name":"Dolph Mathews","email":"dolph.mathews@gmail.com","username":"dolph"},"change_message_id":"8a24a2d5d44a2de6ee0063cc1fa6c147d299b4ee","unresolved":false,"context_lines":[{"line_number":256,"context_line":"        if ignore_str:"},{"line_number":257,"context_line":"            try:"},{"line_number":258,"context_line":"                ignore_list \u003d ignore_str.split(\u0027,\u0027)"},{"line_number":259,"context_line":"                return user_id in ignore_list"},{"line_number":260,"context_line":"            except Exception:"},{"line_number":261,"context_line":"                LOG.warning("},{"line_number":262,"context_line":"                    _LW(\u0027Invalid config setting: \u0027"}],"source_content_type":"text/x-python","patch_set":23,"id":"3aaa91ec_c0ac43a1","line":259,"updated":"2016-06-30 16:56:44.000000000","message":"This would be the only line left in this method","commit_id":"36500700b3fa0c1a6c560d6d173e00f2fce4ec76"},{"author":{"_account_id":18338,"name":"Ron De Rose","email":"ronald.de.rose@intel.com","username":"derosenet"},"change_message_id":"6997aef3ee0660e32b2e04223701ca3c98602898","unresolved":false,"context_lines":[{"line_number":256,"context_line":"        if ignore_str:"},{"line_number":257,"context_line":"            try:"},{"line_number":258,"context_line":"                ignore_list \u003d ignore_str.split(\u0027,\u0027)"},{"line_number":259,"context_line":"                return user_id in ignore_list"},{"line_number":260,"context_line":"            except Exception:"},{"line_number":261,"context_line":"                LOG.warning("},{"line_number":262,"context_line":"                    _LW(\u0027Invalid config setting: \u0027"}],"source_content_type":"text/x-python","patch_set":23,"id":"3aaa91ec_bb74c167","line":259,"in_reply_to":"3aaa91ec_c0ac43a1","updated":"2016-06-30 19:28:16.000000000","message":"Done","commit_id":"36500700b3fa0c1a6c560d6d173e00f2fce4ec76"},{"author":{"_account_id":5046,"name":"Lance Bragstad","email":"lbragstad@redhat.com","username":"ldbragst"},"change_message_id":"653c09de0dd4312cda94ce356a75f14a31a5bad2","unresolved":false,"context_lines":[{"line_number":183,"context_line":"        return super(User, cls).from_dict(new_dict)"},{"line_number":184,"context_line":""},{"line_number":185,"context_line":""},{"line_number":186,"context_line":"def get_password_expires_at(user_id, created_at):"},{"line_number":187,"context_line":"    expires_days \u003d CONF.security_compliance.password_expires_days"},{"line_number":188,"context_line":"    ignore_list \u003d CONF.security_compliance.password_expires_ignore_list"},{"line_number":189,"context_line":"    if expires_days and (user_id not in ignore_list):"}],"source_content_type":"text/x-python","patch_set":39,"id":"dada55a8_0492daf5","line":186,"updated":"2016-07-27 13:53:40.000000000","message":"This could just be a private method of User since it isn\u0027t used anywhere else.","commit_id":"9f78b63427273c97eb6b23c1a4993b55ad7eadb2"},{"author":{"_account_id":18338,"name":"Ron De Rose","email":"ronald.de.rose@intel.com","username":"derosenet"},"change_message_id":"c82a2148dd09c3b0064abeea823818c5000ca2bf","unresolved":false,"context_lines":[{"line_number":183,"context_line":"        return super(User, cls).from_dict(new_dict)"},{"line_number":184,"context_line":""},{"line_number":185,"context_line":""},{"line_number":186,"context_line":"def get_password_expires_at(user_id, created_at):"},{"line_number":187,"context_line":"    expires_days \u003d CONF.security_compliance.password_expires_days"},{"line_number":188,"context_line":"    ignore_list \u003d CONF.security_compliance.password_expires_ignore_list"},{"line_number":189,"context_line":"    if expires_days and (user_id not in ignore_list):"}],"source_content_type":"text/x-python","patch_set":39,"id":"bacf61ea_4f3afece","line":186,"in_reply_to":"dada55a8_0492daf5","updated":"2016-07-27 15:58:30.000000000","message":"Done","commit_id":"9f78b63427273c97eb6b23c1a4993b55ad7eadb2"},{"author":{"_account_id":5046,"name":"Lance Bragstad","email":"lbragstad@redhat.com","username":"ldbragst"},"change_message_id":"8a65c94052489874260740de14d39fda1c7fdbfa","unresolved":false,"context_lines":[{"line_number":183,"context_line":"        return super(User, cls).from_dict(new_dict)"},{"line_number":184,"context_line":""},{"line_number":185,"context_line":""},{"line_number":186,"context_line":"def _get_password_expires_at(user_id, created_at):"},{"line_number":187,"context_line":"    expires_days \u003d CONF.security_compliance.password_expires_days"},{"line_number":188,"context_line":"    ignore_list \u003d CONF.security_compliance.password_expires_ignore_list"},{"line_number":189,"context_line":"    if expires_days and (user_id not in ignore_list):"}],"source_content_type":"text/x-python","patch_set":42,"id":"bacf61ea_509f0450","line":186,"updated":"2016-07-28 14:38:56.000000000","message":"Sorry - when I meant \"private method of User\" I meant we could probably include in the in actual User class:\n\n    def _get_password_expires_at(self, user_id, created_at):\n        ....","commit_id":"51e0b88399458ac510309d357a2c33e688872335"},{"author":{"_account_id":18338,"name":"Ron De Rose","email":"ronald.de.rose@intel.com","username":"derosenet"},"change_message_id":"9db0e7159586931fab678788f096572a67da1bcb","unresolved":false,"context_lines":[{"line_number":183,"context_line":"        return super(User, cls).from_dict(new_dict)"},{"line_number":184,"context_line":""},{"line_number":185,"context_line":""},{"line_number":186,"context_line":"def _get_password_expires_at(user_id, created_at):"},{"line_number":187,"context_line":"    expires_days \u003d CONF.security_compliance.password_expires_days"},{"line_number":188,"context_line":"    ignore_list \u003d CONF.security_compliance.password_expires_ignore_list"},{"line_number":189,"context_line":"    if expires_days and (user_id not in ignore_list):"}],"source_content_type":"text/x-python","patch_set":42,"id":"bacf61ea_64088a2e","line":186,"in_reply_to":"bacf61ea_509f0450","updated":"2016-07-28 15:54:03.000000000","message":"Ah, good suggestion.  Done","commit_id":"51e0b88399458ac510309d357a2c33e688872335"},{"author":{"_account_id":7725,"name":"David Stanek","email":"dstanek@dstanek.com","username":"dstanek"},"change_message_id":"826877e7c26e18e84f53b1340a04411b1083e599","unresolved":false,"context_lines":[{"line_number":20,"context_line":"from sqlalchemy import orm"},{"line_number":21,"context_line":""},{"line_number":22,"context_line":"from keystone.common import sql"},{"line_number":23,"context_line":"import keystone.conf"},{"line_number":24,"context_line":""},{"line_number":25,"context_line":""},{"line_number":26,"context_line":"CONF \u003d keystone.conf.CONF"}],"source_content_type":"text/x-python","patch_set":43,"id":"bacf61ea_d6011a6c","line":23,"updated":"2016-07-28 20:31:31.000000000","message":"If you are going to use keystone.conf you should remove the oslo_config usage too.","commit_id":"b729a651e661f944fc592715ad13c837f1065038"},{"author":{"_account_id":18338,"name":"Ron De Rose","email":"ronald.de.rose@intel.com","username":"derosenet"},"change_message_id":"c85c120be130704db495ab702dd6b399c93d9a45","unresolved":false,"context_lines":[{"line_number":20,"context_line":"from sqlalchemy import orm"},{"line_number":21,"context_line":""},{"line_number":22,"context_line":"from keystone.common import sql"},{"line_number":23,"context_line":"import keystone.conf"},{"line_number":24,"context_line":""},{"line_number":25,"context_line":""},{"line_number":26,"context_line":"CONF \u003d keystone.conf.CONF"}],"source_content_type":"text/x-python","patch_set":43,"id":"bacf61ea_d7d474be","line":23,"in_reply_to":"bacf61ea_d6011a6c","updated":"2016-07-28 21:38:30.000000000","message":"How the heck did I miss that.","commit_id":"b729a651e661f944fc592715ad13c837f1065038"},{"author":{"_account_id":7725,"name":"David Stanek","email":"dstanek@dstanek.com","username":"dstanek"},"change_message_id":"826877e7c26e18e84f53b1340a04411b1083e599","unresolved":false,"context_lines":[{"line_number":179,"context_line":"        new_dict \u003d user_dict.copy()"},{"line_number":180,"context_line":"        for attribute in cls.readonly_attributes:"},{"line_number":181,"context_line":"            if attribute in user_dict:"},{"line_number":182,"context_line":"                del new_dict[attribute]"},{"line_number":183,"context_line":"        return super(User, cls).from_dict(new_dict)"},{"line_number":184,"context_line":""},{"line_number":185,"context_line":"    def _get_password_expires_at(self, created_at):"}],"source_content_type":"text/x-python","patch_set":43,"id":"bacf61ea_96f1626d","line":182,"updated":"2016-07-28 20:31:31.000000000","message":"Should we 400 instead since the user is doing something they shouldn\u0027t be doing?","commit_id":"b729a651e661f944fc592715ad13c837f1065038"},{"author":{"_account_id":18338,"name":"Ron De Rose","email":"ronald.de.rose@intel.com","username":"derosenet"},"change_message_id":"a9a2a2c8e35579e03a54a6ccaa4e057b2ab67106","unresolved":false,"context_lines":[{"line_number":179,"context_line":"        new_dict \u003d user_dict.copy()"},{"line_number":180,"context_line":"        for attribute in cls.readonly_attributes:"},{"line_number":181,"context_line":"            if attribute in user_dict:"},{"line_number":182,"context_line":"                del new_dict[attribute]"},{"line_number":183,"context_line":"        return super(User, cls).from_dict(new_dict)"},{"line_number":184,"context_line":""},{"line_number":185,"context_line":"    def _get_password_expires_at(self, created_at):"}],"source_content_type":"text/x-python","patch_set":43,"id":"bacf61ea_1c50f35d","line":182,"in_reply_to":"bacf61ea_96f1626d","updated":"2016-07-28 21:05:53.000000000","message":"Hmm... I don\u0027t think that validation belongs here. However, I do want to prevent read-only attributes from causing an error, even if you are calling from_dict, but not performing a write operation.","commit_id":"b729a651e661f944fc592715ad13c837f1065038"},{"author":{"_account_id":8119,"name":"Eric Brown","email":"eric_wade_brown@yahoo.com","username":"ericwb"},"change_message_id":"1e3e79ff66bd9d70ac3dd93662e06263d910bcbd","unresolved":false,"context_lines":[{"line_number":184,"context_line":"        if expires_days and (self.id not in ignore_list):"},{"line_number":185,"context_line":"            expired_date \u003d (created_at + datetime.timedelta(days\u003dexpires_days))"},{"line_number":186,"context_line":"            return expired_date.replace(microsecond\u003d0)"},{"line_number":187,"context_line":"        return None"},{"line_number":188,"context_line":""},{"line_number":189,"context_line":""},{"line_number":190,"context_line":"class LocalUser(sql.ModelBase, sql.DictBase):"}],"source_content_type":"text/x-python","patch_set":44,"id":"bacf61ea_8945c4b4","line":187,"updated":"2016-07-28 21:57:42.000000000","message":"This statement is redundant. Python default return is None","commit_id":"dd63b5aeeebd12a39e2497425220d77b9b9f4306"},{"author":{"_account_id":4,"name":"Dolph Mathews","email":"dolph.mathews@gmail.com","username":"dolph"},"change_message_id":"a13c686ff25e6fd9fac4387d7fd31d489cc9c554","unresolved":false,"context_lines":[{"line_number":29,"context_line":"    __tablename__ \u003d \u0027user\u0027"},{"line_number":30,"context_line":"    attributes \u003d [\u0027id\u0027, \u0027name\u0027, \u0027domain_id\u0027, \u0027password\u0027, \u0027enabled\u0027,"},{"line_number":31,"context_line":"                  \u0027default_project_id\u0027, \u0027password_expires_at\u0027]"},{"line_number":32,"context_line":"    readonly_attributes \u003d [\u0027password_expires_at\u0027]"},{"line_number":33,"context_line":"    id \u003d sql.Column(sql.String(64), primary_key\u003dTrue)"},{"line_number":34,"context_line":"    _enabled \u003d sql.Column(\u0027enabled\u0027, sql.Boolean)"},{"line_number":35,"context_line":"    extra \u003d sql.Column(sql.JsonBlob())"}],"source_content_type":"text/x-python","patch_set":46,"id":"bacf61ea_0d4891cb","line":32,"updated":"2016-07-29 17:57:05.000000000","message":"id is also readonly -- and so is domain_id, if the configuration is set that way.","commit_id":"4eff51da89b8300c84b85f400e76a7dd2f5d010e"},{"author":{"_account_id":18338,"name":"Ron De Rose","email":"ronald.de.rose@intel.com","username":"derosenet"},"change_message_id":"5e0fe54a7af473cfa2021fb1749cb8fd6b3bc7ea","unresolved":false,"context_lines":[{"line_number":29,"context_line":"    __tablename__ \u003d \u0027user\u0027"},{"line_number":30,"context_line":"    attributes \u003d [\u0027id\u0027, \u0027name\u0027, \u0027domain_id\u0027, \u0027password\u0027, \u0027enabled\u0027,"},{"line_number":31,"context_line":"                  \u0027default_project_id\u0027, \u0027password_expires_at\u0027]"},{"line_number":32,"context_line":"    readonly_attributes \u003d [\u0027password_expires_at\u0027]"},{"line_number":33,"context_line":"    id \u003d sql.Column(sql.String(64), primary_key\u003dTrue)"},{"line_number":34,"context_line":"    _enabled \u003d sql.Column(\u0027enabled\u0027, sql.Boolean)"},{"line_number":35,"context_line":"    extra \u003d sql.Column(sql.JsonBlob())"}],"source_content_type":"text/x-python","patch_set":46,"id":"bacf61ea_bc8d007e","line":32,"in_reply_to":"bacf61ea_0d4891cb","updated":"2016-08-05 13:14:49.000000000","message":"Added id to readonly","commit_id":"4eff51da89b8300c84b85f400e76a7dd2f5d010e"},{"author":{"_account_id":4,"name":"Dolph Mathews","email":"dolph.mathews@gmail.com","username":"dolph"},"change_message_id":"a13c686ff25e6fd9fac4387d7fd31d489cc9c554","unresolved":false,"context_lines":[{"line_number":171,"context_line":"        return d"},{"line_number":172,"context_line":""},{"line_number":173,"context_line":"    @classmethod"},{"line_number":174,"context_line":"    def from_dict(cls, user_dict):"},{"line_number":175,"context_line":"        new_dict \u003d user_dict.copy()"},{"line_number":176,"context_line":"        for attribute in cls.readonly_attributes:"},{"line_number":177,"context_line":"            if attribute in user_dict:"}],"source_content_type":"text/x-python","patch_set":46,"id":"bacf61ea_2d80f5bf","line":174,"updated":"2016-07-29 17:57:05.000000000","message":"A doctstr explaining why you need to override this would be nice.","commit_id":"4eff51da89b8300c84b85f400e76a7dd2f5d010e"},{"author":{"_account_id":18338,"name":"Ron De Rose","email":"ronald.de.rose@intel.com","username":"derosenet"},"change_message_id":"5e0fe54a7af473cfa2021fb1749cb8fd6b3bc7ea","unresolved":false,"context_lines":[{"line_number":171,"context_line":"        return d"},{"line_number":172,"context_line":""},{"line_number":173,"context_line":"    @classmethod"},{"line_number":174,"context_line":"    def from_dict(cls, user_dict):"},{"line_number":175,"context_line":"        new_dict \u003d user_dict.copy()"},{"line_number":176,"context_line":"        for attribute in cls.readonly_attributes:"},{"line_number":177,"context_line":"            if attribute in user_dict:"}],"source_content_type":"text/x-python","patch_set":46,"id":"bacf61ea_dceef420","line":174,"in_reply_to":"bacf61ea_2d80f5bf","updated":"2016-08-05 13:14:49.000000000","message":"Done","commit_id":"4eff51da89b8300c84b85f400e76a7dd2f5d010e"}],"keystone/tests/unit/identity/backends/test_base.py":[{"author":{"_account_id":4,"name":"Dolph Mathews","email":"dolph.mathews@gmail.com","username":"dolph"},"change_message_id":"a13c686ff25e6fd9fac4387d7fd31d489cc9c554","unresolved":false,"context_lines":[{"line_number":111,"context_line":"        if self.driver.is_domain_aware():"},{"line_number":112,"context_line":"            user[\u0027domain_id\u0027] \u003d uuid.uuid4().hex"},{"line_number":113,"context_line":"        ret \u003d self.driver.create_user(user_id, user)"},{"line_number":114,"context_line":"        del ret[\u0027password_expires_at\u0027]"},{"line_number":115,"context_line":"        exp_user \u003d user.copy()"},{"line_number":116,"context_line":"        del exp_user[\u0027password\u0027]"},{"line_number":117,"context_line":"        self.assertEqual(exp_user, ret)"}],"source_content_type":"text/x-python","patch_set":46,"id":"bacf61ea_cd56795b","line":114,"updated":"2016-07-29 17:57:05.000000000","message":"How about adding password_expires_at to the expected user, instead of ignoring the value?","commit_id":"4eff51da89b8300c84b85f400e76a7dd2f5d010e"},{"author":{"_account_id":18338,"name":"Ron De Rose","email":"ronald.de.rose@intel.com","username":"derosenet"},"change_message_id":"5e0fe54a7af473cfa2021fb1749cb8fd6b3bc7ea","unresolved":false,"context_lines":[{"line_number":111,"context_line":"        if self.driver.is_domain_aware():"},{"line_number":112,"context_line":"            user[\u0027domain_id\u0027] \u003d uuid.uuid4().hex"},{"line_number":113,"context_line":"        ret \u003d self.driver.create_user(user_id, user)"},{"line_number":114,"context_line":"        del ret[\u0027password_expires_at\u0027]"},{"line_number":115,"context_line":"        exp_user \u003d user.copy()"},{"line_number":116,"context_line":"        del exp_user[\u0027password\u0027]"},{"line_number":117,"context_line":"        self.assertEqual(exp_user, ret)"}],"source_content_type":"text/x-python","patch_set":46,"id":"bacf61ea_3cdab04b","line":114,"in_reply_to":"bacf61ea_cd56795b","updated":"2016-08-05 13:14:49.000000000","message":"Done","commit_id":"4eff51da89b8300c84b85f400e76a7dd2f5d010e"}],"keystone/tests/unit/identity/test_backend_sql.py":[{"author":{"_account_id":5046,"name":"Lance Bragstad","email":"lbragstad@redhat.com","username":"ldbragst"},"change_message_id":"8a65c94052489874260740de14d39fda1c7fdbfa","unresolved":false,"context_lines":[{"line_number":203,"context_line":"                                                  user_id\u003duser[\u0027id\u0027],"},{"line_number":204,"context_line":"                                                  password\u003dself.password)"},{"line_number":205,"context_line":"        self.assertEqual(user[\u0027id\u0027], user_ret[\u0027id\u0027])"},{"line_number":206,"context_line":""},{"line_number":207,"context_line":"    def _get_test_user_dict(self, password):"},{"line_number":208,"context_line":"        test_user_dict \u003d {"},{"line_number":209,"context_line":"            \u0027id\u0027: uuid.uuid4().hex,"}],"source_content_type":"text/x-python","patch_set":42,"id":"bacf61ea_734cd242","line":206,"updated":"2016-07-28 14:38:56.000000000","message":"We should add one more test case: \n\n- Create a new user\n- Ensure the v2.0 API doesn\u0027t return the password_expires_at attribute when listing the user\n- Forward the clock to expire the password\n- Verify that the user gets a PasswordExpired exception when authenticating with the v2.0 auth endpoint.\n\nJust want to make sure the code that we are adding to keystone.common.controller is tests as well. It\u0027s also kind of a weird user-experience to have for people using v2.0 when PCI has been enabled but we can\u0027t really change the v2.0 API for this case (this test would also be a good place to document that reasoning incase we ever get asked about it).","commit_id":"51e0b88399458ac510309d357a2c33e688872335"},{"author":{"_account_id":18338,"name":"Ron De Rose","email":"ronald.de.rose@intel.com","username":"derosenet"},"change_message_id":"9db0e7159586931fab678788f096572a67da1bcb","unresolved":false,"context_lines":[{"line_number":203,"context_line":"                                                  user_id\u003duser[\u0027id\u0027],"},{"line_number":204,"context_line":"                                                  password\u003dself.password)"},{"line_number":205,"context_line":"        self.assertEqual(user[\u0027id\u0027], user_ret[\u0027id\u0027])"},{"line_number":206,"context_line":""},{"line_number":207,"context_line":"    def _get_test_user_dict(self, password):"},{"line_number":208,"context_line":"        test_user_dict \u003d {"},{"line_number":209,"context_line":"            \u0027id\u0027: uuid.uuid4().hex,"}],"source_content_type":"text/x-python","patch_set":42,"id":"bacf61ea_4a83cf04","line":206,"in_reply_to":"bacf61ea_734cd242","updated":"2016-07-28 15:54:03.000000000","message":"I added a test_authenticate_with_expired_password_v2 test here. It\u0027s not exactly what you describe, but it\u0027s close and I think satisfies the intent.","commit_id":"51e0b88399458ac510309d357a2c33e688872335"},{"author":{"_account_id":5046,"name":"Lance Bragstad","email":"lbragstad@redhat.com","username":"ldbragst"},"change_message_id":"4e934c527c8a6c6ac80297439251589dfee79e7d","unresolved":false,"context_lines":[{"line_number":167,"context_line":"        # set password created_at so that the password will expire"},{"line_number":168,"context_line":"        password_created_at \u003d ("},{"line_number":169,"context_line":"            datetime.datetime.utcnow() -"},{"line_number":170,"context_line":"            datetime.timedelta(days\u003dself.password_expires_days + 1)"},{"line_number":171,"context_line":"        )"},{"line_number":172,"context_line":"        user \u003d self._create_user(self.user_dict, password_created_at)"},{"line_number":173,"context_line":"        self.assertRaises(exception.PasswordExpired,"}],"source_content_type":"text/x-python","patch_set":43,"id":"bacf61ea_026ff4c5","line":170,"updated":"2016-07-28 18:41:10.000000000","message":"We could have a follow on patch to convert all these to use freezegun instead.","commit_id":"b729a651e661f944fc592715ad13c837f1065038"},{"author":{"_account_id":18338,"name":"Ron De Rose","email":"ronald.de.rose@intel.com","username":"derosenet"},"change_message_id":"c85c120be130704db495ab702dd6b399c93d9a45","unresolved":false,"context_lines":[{"line_number":167,"context_line":"        # set password created_at so that the password will expire"},{"line_number":168,"context_line":"        password_created_at \u003d ("},{"line_number":169,"context_line":"            datetime.datetime.utcnow() -"},{"line_number":170,"context_line":"            datetime.timedelta(days\u003dself.password_expires_days + 1)"},{"line_number":171,"context_line":"        )"},{"line_number":172,"context_line":"        user \u003d self._create_user(self.user_dict, password_created_at)"},{"line_number":173,"context_line":"        self.assertRaises(exception.PasswordExpired,"}],"source_content_type":"text/x-python","patch_set":43,"id":"bacf61ea_7794a8e1","line":170,"in_reply_to":"bacf61ea_026ff4c5","updated":"2016-07-28 21:38:30.000000000","message":"Agree","commit_id":"b729a651e661f944fc592715ad13c837f1065038"},{"author":{"_account_id":4,"name":"Dolph Mathews","email":"dolph.mathews@gmail.com","username":"dolph"},"change_message_id":"a13c686ff25e6fd9fac4387d7fd31d489cc9c554","unresolved":false,"context_lines":[{"line_number":158,"context_line":"        super(PasswordExpiresValidationTests, self).setUp()"},{"line_number":159,"context_line":"        self.password \u003d uuid.uuid4().hex"},{"line_number":160,"context_line":"        self.user_dict \u003d self._get_test_user_dict(self.password)"},{"line_number":161,"context_line":"        self.password_expires_days \u003d 90"},{"line_number":162,"context_line":"        self.config_fixture.config("},{"line_number":163,"context_line":"            group\u003d\u0027security_compliance\u0027,"},{"line_number":164,"context_line":"            password_expires_days\u003dself.password_expires_days)"}],"source_content_type":"text/x-python","patch_set":46,"id":"bacf61ea_6dd4adbc","line":161,"updated":"2016-07-29 17:57:05.000000000","message":"Same as the other patch - not sure why this needs to be an instance attribute.","commit_id":"4eff51da89b8300c84b85f400e76a7dd2f5d010e"},{"author":{"_account_id":18338,"name":"Ron De Rose","email":"ronald.de.rose@intel.com","username":"derosenet"},"change_message_id":"5e0fe54a7af473cfa2021fb1749cb8fd6b3bc7ea","unresolved":false,"context_lines":[{"line_number":158,"context_line":"        super(PasswordExpiresValidationTests, self).setUp()"},{"line_number":159,"context_line":"        self.password \u003d uuid.uuid4().hex"},{"line_number":160,"context_line":"        self.user_dict \u003d self._get_test_user_dict(self.password)"},{"line_number":161,"context_line":"        self.password_expires_days \u003d 90"},{"line_number":162,"context_line":"        self.config_fixture.config("},{"line_number":163,"context_line":"            group\u003d\u0027security_compliance\u0027,"},{"line_number":164,"context_line":"            password_expires_days\u003dself.password_expires_days)"}],"source_content_type":"text/x-python","patch_set":46,"id":"bacf61ea_1c37ec4d","line":161,"in_reply_to":"bacf61ea_6dd4adbc","updated":"2016-08-05 13:14:49.000000000","message":"Removed the instance attribute","commit_id":"4eff51da89b8300c84b85f400e76a7dd2f5d010e"},{"author":{"_account_id":4,"name":"Dolph Mathews","email":"dolph.mathews@gmail.com","username":"dolph"},"change_message_id":"a13c686ff25e6fd9fac4387d7fd31d489cc9c554","unresolved":false,"context_lines":[{"line_number":167,"context_line":"        # set password created_at so that the password will expire"},{"line_number":168,"context_line":"        password_created_at \u003d ("},{"line_number":169,"context_line":"            datetime.datetime.utcnow() -"},{"line_number":170,"context_line":"            datetime.timedelta(days\u003dself.password_expires_days + 1)"},{"line_number":171,"context_line":"        )"},{"line_number":172,"context_line":"        user \u003d self._create_user(self.user_dict, password_created_at)"},{"line_number":173,"context_line":"        # test password is expired"}],"source_content_type":"text/x-python","patch_set":46,"id":"bacf61ea_adda25e6","line":170,"updated":"2016-07-29 17:57:05.000000000","message":"Just read this value from CONF","commit_id":"4eff51da89b8300c84b85f400e76a7dd2f5d010e"},{"author":{"_account_id":18338,"name":"Ron De Rose","email":"ronald.de.rose@intel.com","username":"derosenet"},"change_message_id":"5e0fe54a7af473cfa2021fb1749cb8fd6b3bc7ea","unresolved":false,"context_lines":[{"line_number":167,"context_line":"        # set password created_at so that the password will expire"},{"line_number":168,"context_line":"        password_created_at \u003d ("},{"line_number":169,"context_line":"            datetime.datetime.utcnow() -"},{"line_number":170,"context_line":"            datetime.timedelta(days\u003dself.password_expires_days + 1)"},{"line_number":171,"context_line":"        )"},{"line_number":172,"context_line":"        user \u003d self._create_user(self.user_dict, password_created_at)"},{"line_number":173,"context_line":"        # test password is expired"}],"source_content_type":"text/x-python","patch_set":46,"id":"bacf61ea_7c40a8a5","line":170,"in_reply_to":"bacf61ea_adda25e6","updated":"2016-08-05 13:14:49.000000000","message":"Done","commit_id":"4eff51da89b8300c84b85f400e76a7dd2f5d010e"},{"author":{"_account_id":4,"name":"Dolph Mathews","email":"dolph.mathews@gmail.com","username":"dolph"},"change_message_id":"a13c686ff25e6fd9fac4387d7fd31d489cc9c554","unresolved":false,"context_lines":[{"line_number":226,"context_line":"        test_user_dict \u003d {"},{"line_number":227,"context_line":"            \u0027id\u0027: uuid.uuid4().hex,"},{"line_number":228,"context_line":"            \u0027name\u0027: uuid.uuid4().hex,"},{"line_number":229,"context_line":"            \u0027domain_id\u0027: \u0027default\u0027,"},{"line_number":230,"context_line":"            \u0027enabled\u0027: True,"},{"line_number":231,"context_line":"            \u0027password\u0027: password"},{"line_number":232,"context_line":"        }"}],"source_content_type":"text/x-python","patch_set":46,"id":"bacf61ea_8db48182","line":229,"updated":"2016-07-29 17:57:05.000000000","message":"Read this from CONF -- \u0027default\u0027 is not a magic value.","commit_id":"4eff51da89b8300c84b85f400e76a7dd2f5d010e"},{"author":{"_account_id":18338,"name":"Ron De Rose","email":"ronald.de.rose@intel.com","username":"derosenet"},"change_message_id":"5e0fe54a7af473cfa2021fb1749cb8fd6b3bc7ea","unresolved":false,"context_lines":[{"line_number":226,"context_line":"        test_user_dict \u003d {"},{"line_number":227,"context_line":"            \u0027id\u0027: uuid.uuid4().hex,"},{"line_number":228,"context_line":"            \u0027name\u0027: uuid.uuid4().hex,"},{"line_number":229,"context_line":"            \u0027domain_id\u0027: \u0027default\u0027,"},{"line_number":230,"context_line":"            \u0027enabled\u0027: True,"},{"line_number":231,"context_line":"            \u0027password\u0027: password"},{"line_number":232,"context_line":"        }"}],"source_content_type":"text/x-python","patch_set":46,"id":"bacf61ea_5c6b241e","line":229,"in_reply_to":"bacf61ea_8db48182","updated":"2016-08-05 13:14:49.000000000","message":"Done","commit_id":"4eff51da89b8300c84b85f400e76a7dd2f5d010e"},{"author":{"_account_id":4,"name":"Dolph Mathews","email":"dolph.mathews@gmail.com","username":"dolph"},"change_message_id":"a13c686ff25e6fd9fac4387d7fd31d489cc9c554","unresolved":false,"context_lines":[{"line_number":240,"context_line":"            user_ref.password_ref.expires_at \u003d ("},{"line_number":241,"context_line":"                user_ref._get_password_expires_at(password_created_at))"},{"line_number":242,"context_line":"            session.add(user_ref)"},{"line_number":243,"context_line":"            return base.filter_user(user_ref.to_dict())"}],"source_content_type":"text/x-python","patch_set":46,"id":"bacf61ea_cd8b19c2","line":243,"updated":"2016-07-29 17:57:05.000000000","message":"Does the return need to be within the context manager? It looks like the function will return None at first glance, which doesn\u0027t seem to be the intent (or the case).","commit_id":"4eff51da89b8300c84b85f400e76a7dd2f5d010e"},{"author":{"_account_id":18338,"name":"Ron De Rose","email":"ronald.de.rose@intel.com","username":"derosenet"},"change_message_id":"5e0fe54a7af473cfa2021fb1749cb8fd6b3bc7ea","unresolved":false,"context_lines":[{"line_number":240,"context_line":"            user_ref.password_ref.expires_at \u003d ("},{"line_number":241,"context_line":"                user_ref._get_password_expires_at(password_created_at))"},{"line_number":242,"context_line":"            session.add(user_ref)"},{"line_number":243,"context_line":"            return base.filter_user(user_ref.to_dict())"}],"source_content_type":"text/x-python","patch_set":46,"id":"bacf61ea_7cdc28e4","line":243,"in_reply_to":"bacf61ea_cd8b19c2","updated":"2016-08-05 13:14:49.000000000","message":"No, it doesn\u0027t. Done","commit_id":"4eff51da89b8300c84b85f400e76a7dd2f5d010e"}],"keystone/tests/unit/identity/test_backends.py":[{"author":{"_account_id":5046,"name":"Lance Bragstad","email":"lbragstad@redhat.com","username":"ldbragst"},"change_message_id":"f49113d986aec86cd0656bb8dc8701bab38b43dc","unresolved":false,"context_lines":[{"line_number":123,"context_line":"        self.assertIn(\u0027id\u0027, user_ref)"},{"line_number":124,"context_line":"        self.assertIn(\u0027name\u0027, user_ref)"},{"line_number":125,"context_line":"        self.assertIn(\u0027enabled\u0027, user_ref)"},{"line_number":126,"context_line":"        self.assertIn(\u0027password_expires_at\u0027, user_ref)"},{"line_number":127,"context_line":""},{"line_number":128,"context_line":"    @unit.skip_if_cache_disabled(\u0027identity\u0027)"},{"line_number":129,"context_line":"    def test_cache_layer_get_user(self):"}],"source_content_type":"text/x-python","patch_set":28,"id":"1aa78d24_95b12404","line":126,"updated":"2016-07-11 19:37:38.000000000","message":"is domain id required?","commit_id":"63ce5268ea14b1c2ad39229fd16b2be6da4cc498"}],"keystone/tests/unit/identity/test_core.py":[{"author":{"_account_id":4,"name":"Dolph Mathews","email":"dolph.mathews@gmail.com","username":"dolph"},"change_message_id":"a13c686ff25e6fd9fac4387d7fd31d489cc9c554","unresolved":false,"context_lines":[{"line_number":195,"context_line":"        )"},{"line_number":196,"context_line":"        self.assertIsNotNone(user[\u0027id\u0027])"},{"line_number":197,"context_line":"        self.assertEqual(4, len(user.keys()))"},{"line_number":198,"context_line":"        self.assertIsNotNone(user[\u0027name\u0027])"},{"line_number":199,"context_line":"        self.assertIsNone(user[\u0027domain_id\u0027])"},{"line_number":200,"context_line":"        self.assertEqual(True, user[\u0027enabled\u0027])"},{"line_number":201,"context_line":""}],"source_content_type":"text/x-python","patch_set":46,"id":"bacf61ea_0d80918a","side":"PARENT","line":198,"updated":"2016-07-29 17:57:05.000000000","message":"and assertIsNone(user[\u0027password_expires_at\u0027]) ?","commit_id":"96af93d36151b04fc82c5c1db3615311bfda544e"},{"author":{"_account_id":18338,"name":"Ron De Rose","email":"ronald.de.rose@intel.com","username":"derosenet"},"change_message_id":"5e0fe54a7af473cfa2021fb1749cb8fd6b3bc7ea","unresolved":false,"context_lines":[{"line_number":195,"context_line":"        )"},{"line_number":196,"context_line":"        self.assertIsNotNone(user[\u0027id\u0027])"},{"line_number":197,"context_line":"        self.assertEqual(4, len(user.keys()))"},{"line_number":198,"context_line":"        self.assertIsNotNone(user[\u0027name\u0027])"},{"line_number":199,"context_line":"        self.assertIsNone(user[\u0027domain_id\u0027])"},{"line_number":200,"context_line":"        self.assertEqual(True, user[\u0027enabled\u0027])"},{"line_number":201,"context_line":""}],"source_content_type":"text/x-python","patch_set":46,"id":"bacf61ea_bc9060ee","side":"PARENT","line":198,"in_reply_to":"bacf61ea_0d80918a","updated":"2016-08-05 13:14:49.000000000","message":"Done","commit_id":"96af93d36151b04fc82c5c1db3615311bfda544e"}],"keystone/tests/unit/test_v3_identity.py":[{"author":{"_account_id":4,"name":"Dolph Mathews","email":"dolph.mathews@gmail.com","username":"dolph"},"change_message_id":"a13c686ff25e6fd9fac4387d7fd31d489cc9c554","unresolved":false,"context_lines":[{"line_number":690,"context_line":"            name\u003duser_id,"},{"line_number":691,"context_line":"            project_id\u003dproject_id,"},{"line_number":692,"context_line":"            domain_id\u003dCONF.identity.default_domain_id,"},{"line_number":693,"context_line":"            password_expires_at\u003d\u00272016-11-06T15:32:17.000000\u0027)"},{"line_number":694,"context_line":""},{"line_number":695,"context_line":"        # Expected result if the user is meant to have a tenantId element"},{"line_number":696,"context_line":"        self.expected_user \u003d {\u0027id\u0027: user_id,"}],"source_content_type":"text/x-python","patch_set":46,"id":"bacf61ea_6d3e6ddb","line":693,"updated":"2016-07-29 17:57:05.000000000","message":"Is this supposed to be an ISO8601 formatted datetime? It\u0027s missing the timezone.","commit_id":"4eff51da89b8300c84b85f400e76a7dd2f5d010e"},{"author":{"_account_id":18338,"name":"Ron De Rose","email":"ronald.de.rose@intel.com","username":"derosenet"},"change_message_id":"5e0fe54a7af473cfa2021fb1749cb8fd6b3bc7ea","unresolved":false,"context_lines":[{"line_number":690,"context_line":"            name\u003duser_id,"},{"line_number":691,"context_line":"            project_id\u003dproject_id,"},{"line_number":692,"context_line":"            domain_id\u003dCONF.identity.default_domain_id,"},{"line_number":693,"context_line":"            password_expires_at\u003d\u00272016-11-06T15:32:17.000000\u0027)"},{"line_number":694,"context_line":""},{"line_number":695,"context_line":"        # Expected result if the user is meant to have a tenantId element"},{"line_number":696,"context_line":"        self.expected_user \u003d {\u0027id\u0027: user_id,"}],"source_content_type":"text/x-python","patch_set":46,"id":"bacf61ea_bc55001f","line":693,"in_reply_to":"bacf61ea_6d3e6ddb","updated":"2016-08-05 13:14:49.000000000","message":"I actually don\u0027t need a default value here; only validating that the attribute is included.","commit_id":"4eff51da89b8300c84b85f400e76a7dd2f5d010e"}]}
