)]}'
{"keystone/common/sql/migrate_repo/versions/109_add_password_self_service_column.py":[{"author":{"_account_id":7725,"name":"David Stanek","email":"dstanek@dstanek.com","username":"dstanek"},"change_message_id":"527526a9239d0ba181ead60be8c4f0135b92f3fe","unresolved":false,"context_lines":[{"line_number":18,"context_line":"    meta.bind \u003d migrate_engine"},{"line_number":19,"context_line":""},{"line_number":20,"context_line":"    self_service_column \u003d sql.Column(\u0027self_service\u0027, sql.Boolean,"},{"line_number":21,"context_line":"                                     nullable\u003dFalse, server_default\u003d\u00270\u0027,"},{"line_number":22,"context_line":"                                     default\u003dFalse)"},{"line_number":23,"context_line":"    password_table \u003d sql.Table(\u0027password\u0027, meta, autoload\u003dTrue)"},{"line_number":24,"context_line":"    password_table.create_column(self_service_column)"}],"source_content_type":"text/x-python","patch_set":46,"id":"5ac665da_a5b59ed1","line":21,"updated":"2016-08-13 16:39:38.000000000","message":"Using \u00270\u0027 here doesn\u0027t seem intuitive. Should this actually be False?","commit_id":"bec68c841e9cd43ce7eb2b1e962b15f3fa7e4aee"},{"author":{"_account_id":18338,"name":"Ron De Rose","email":"ronald.de.rose@intel.com","username":"derosenet"},"change_message_id":"a69b24889118af9c0fdd21f81f7ddd2399a4cc9a","unresolved":false,"context_lines":[{"line_number":18,"context_line":"    meta.bind \u003d migrate_engine"},{"line_number":19,"context_line":""},{"line_number":20,"context_line":"    self_service_column \u003d sql.Column(\u0027self_service\u0027, sql.Boolean,"},{"line_number":21,"context_line":"                                     nullable\u003dFalse, server_default\u003d\u00270\u0027,"},{"line_number":22,"context_line":"                                     default\u003dFalse)"},{"line_number":23,"context_line":"    password_table \u003d sql.Table(\u0027password\u0027, meta, autoload\u003dTrue)"},{"line_number":24,"context_line":"    password_table.create_column(self_service_column)"}],"source_content_type":"text/x-python","patch_set":46,"id":"3ac371cc_7a1dd372","line":21,"in_reply_to":"5ac665da_a5b59ed1","updated":"2016-08-15 16:41:32.000000000","message":"From my research, for server_default to work across databases, you need to use basic string or integer defaults, which is how we\u0027ve done handled this in the past:\nhttps://github.com/openstack/keystone/blob/master/keystone/common/sql/migrate_repo/versions/074_add_is_domain_project.py#L26","commit_id":"bec68c841e9cd43ce7eb2b1e962b15f3fa7e4aee"}],"keystone/conf/security_compliance.py":[{"author":{"_account_id":5046,"name":"Lance Bragstad","email":"lbragstad@redhat.com","username":"ldbragst"},"change_message_id":"7a3b113efdbcb3507e00ca537b9dbed12b6ac9d9","unresolved":false,"context_lines":[{"line_number":85,"context_line":"The number of days that a password must be used before the user can change it."},{"line_number":86,"context_line":"This prevents users from changing their passwords immediately in order to wipe"},{"line_number":87,"context_line":"out their password history and reuse an old password. This feature does not"},{"line_number":88,"context_line":"prevent admin password resets. It is disabled by default and allows for"},{"line_number":89,"context_line":"immediate password changes. This feature depends on the `sql` backend for the"},{"line_number":90,"context_line":"`[identity] driver`. Note: If `[security_compliance] password_expires_days` is"},{"line_number":91,"context_line":"set, then the value for this option should be less than the"}],"source_content_type":"text/x-python","patch_set":36,"id":"bacf61ea_b436b04e","line":88,"updated":"2016-08-05 15:14:48.000000000","message":"nit: \n\n  This feature does not prevent administrators from manually resetting\n  passwords for locked accounts.","commit_id":"d0183aae5192e82843c75dbb532572681dad8001"},{"author":{"_account_id":18338,"name":"Ron De Rose","email":"ronald.de.rose@intel.com","username":"derosenet"},"change_message_id":"0f2a4a2cd403324439a5ebc4240aa3bd03c3019e","unresolved":false,"context_lines":[{"line_number":85,"context_line":"The number of days that a password must be used before the user can change it."},{"line_number":86,"context_line":"This prevents users from changing their passwords immediately in order to wipe"},{"line_number":87,"context_line":"out their password history and reuse an old password. This feature does not"},{"line_number":88,"context_line":"prevent admin password resets. It is disabled by default and allows for"},{"line_number":89,"context_line":"immediate password changes. This feature depends on the `sql` backend for the"},{"line_number":90,"context_line":"`[identity] driver`. Note: If `[security_compliance] password_expires_days` is"},{"line_number":91,"context_line":"set, then the value for this option should be less than the"}],"source_content_type":"text/x-python","patch_set":36,"id":"bacf61ea_95a3a6b1","line":88,"in_reply_to":"bacf61ea_b436b04e","updated":"2016-08-05 15:53:17.000000000","message":"Why for locked accounts?  I mean I just want to say that users may not be able to change their passwords, but the admin still can.","commit_id":"d0183aae5192e82843c75dbb532572681dad8001"},{"author":{"_account_id":8482,"name":"Colleen Murphy","email":"colleen@gazlene.net","username":"krinkle"},"change_message_id":"1c30b13214373194fd143e716499c873eeffa35f","unresolved":false,"context_lines":[{"line_number":82,"context_line":"    default\u003dNone,"},{"line_number":83,"context_line":"    min\u003d1,"},{"line_number":84,"context_line":"    help\u003dutils.fmt(\"\"\""},{"line_number":85,"context_line":"The number of days that a password must be used before the user can change it."},{"line_number":86,"context_line":"This prevents users from changing their passwords immediately in order to wipe"},{"line_number":87,"context_line":"out their password history and reuse an old password. This feature does not"},{"line_number":88,"context_line":"prevent administrators from manually resetting passwords. It is disabled by"}],"source_content_type":"text/x-python","patch_set":39,"id":"bacf61ea_794c1e9e","line":85,"updated":"2016-08-05 22:43:35.000000000","message":"I\u0027m curious why the unit is set in days and whether that\u0027s a documented standard? Is there a use case where someone might want to set it in minutes or hours? A 1-day minimum password age is likely to cause frequent support requests for password resets while a 1-hour minimum age would be effective at ratelimiting password changes while being short enough that a user who made a mistake can wait it out to fix it.","commit_id":"b26bbd502aeba8b6a5435ee2549464fd082d1969"},{"author":{"_account_id":18338,"name":"Ron De Rose","email":"ronald.de.rose@intel.com","username":"derosenet"},"change_message_id":"1c04b127c5c251ad3f91b13d51cdff6ad5ae6333","unresolved":false,"context_lines":[{"line_number":82,"context_line":"    default\u003dNone,"},{"line_number":83,"context_line":"    min\u003d1,"},{"line_number":84,"context_line":"    help\u003dutils.fmt(\"\"\""},{"line_number":85,"context_line":"The number of days that a password must be used before the user can change it."},{"line_number":86,"context_line":"This prevents users from changing their passwords immediately in order to wipe"},{"line_number":87,"context_line":"out their password history and reuse an old password. This feature does not"},{"line_number":88,"context_line":"prevent administrators from manually resetting passwords. It is disabled by"}],"source_content_type":"text/x-python","patch_set":39,"id":"bacf61ea_d23cff30","line":85,"in_reply_to":"bacf61ea_794c1e9e","updated":"2016-08-06 00:32:27.000000000","message":"I used days as it seemed to be the standard unit for this type of feature. I\u0027m not sure hours would be a big enough deterrent. However, we could always change this later on should operators have a valid use case requiring more flexibility.","commit_id":"b26bbd502aeba8b6a5435ee2549464fd082d1969"},{"author":{"_account_id":5046,"name":"Lance Bragstad","email":"lbragstad@redhat.com","username":"ldbragst"},"change_message_id":"68da4af854a4a52a49c1427acf977ff5f9628dea","unresolved":false,"context_lines":[{"line_number":82,"context_line":"    default\u003dNone,"},{"line_number":83,"context_line":"    min\u003d1,"},{"line_number":84,"context_line":"    help\u003dutils.fmt(\"\"\""},{"line_number":85,"context_line":"The number of days that a password must be used before the user can change it."},{"line_number":86,"context_line":"This prevents users from changing their passwords immediately in order to wipe"},{"line_number":87,"context_line":"out their password history and reuse an old password. This feature does not"},{"line_number":88,"context_line":"prevent administrators from manually resetting passwords. It is disabled by"}],"source_content_type":"text/x-python","patch_set":39,"id":"9ad45d7e_05cc5734","line":85,"in_reply_to":"bacf61ea_d23cff30","updated":"2016-08-08 16:20:13.000000000","message":"I guess one thing we can consider as a benefit here is that we advertise the ability for the user to contact an administrator - which can ultimately override this check. So, in the event a user *really* needs to reset their password, they can always do so through an admin (versus requiring the granularity of hours).","commit_id":"b26bbd502aeba8b6a5435ee2549464fd082d1969"},{"author":{"_account_id":7725,"name":"David Stanek","email":"dstanek@dstanek.com","username":"dstanek"},"change_message_id":"527526a9239d0ba181ead60be8c4f0135b92f3fe","unresolved":false,"context_lines":[{"line_number":68,"context_line":"\"\"\"))"},{"line_number":69,"context_line":""},{"line_number":70,"context_line":"unique_last_password_count \u003d cfg.IntOpt("},{"line_number":71,"context_line":"    \u0027unique_last_password_count\u0027,"},{"line_number":72,"context_line":"    default\u003d1,"},{"line_number":73,"context_line":"    min\u003d1,"},{"line_number":74,"context_line":"    help\u003dutils.fmt(\"\"\""}],"source_content_type":"text/x-python","patch_set":46,"id":"5ac665da_85ba22bf","side":"PARENT","line":71,"updated":"2016-08-13 16:39:38.000000000","message":"I don\u0027t think we\u0027d want to rename the option since (to me) is matches what it is supposed to do.","commit_id":"d082fb29ce0dea56c3bc3781d6931b0c68a3d268"},{"author":{"_account_id":18338,"name":"Ron De Rose","email":"ronald.de.rose@intel.com","username":"derosenet"},"change_message_id":"a69b24889118af9c0fdd21f81f7ddd2399a4cc9a","unresolved":false,"context_lines":[{"line_number":68,"context_line":"\"\"\"))"},{"line_number":69,"context_line":""},{"line_number":70,"context_line":"unique_last_password_count \u003d cfg.IntOpt("},{"line_number":71,"context_line":"    \u0027unique_last_password_count\u0027,"},{"line_number":72,"context_line":"    default\u003d1,"},{"line_number":73,"context_line":"    min\u003d1,"},{"line_number":74,"context_line":"    help\u003dutils.fmt(\"\"\""}],"source_content_type":"text/x-python","patch_set":46,"id":"3ac371cc_6091a499","side":"PARENT","line":71,"in_reply_to":"5ac665da_85ba22bf","updated":"2016-08-15 16:41:32.000000000","message":"I\u0027m not renaming this??","commit_id":"d082fb29ce0dea56c3bc3781d6931b0c68a3d268"},{"author":{"_account_id":6482,"name":"Steve Martinelli","email":"s.martinelli@gmail.com","username":"stevemar"},"change_message_id":"bed103d86302409ff29cca27bec4d73049e9f0b4","unresolved":false,"context_lines":[{"line_number":55,"context_line":"driver`."},{"line_number":56,"context_line":"\"\"\"))"},{"line_number":57,"context_line":""},{"line_number":58,"context_line":"password_expires_days \u003d cfg.IntOpt("},{"line_number":59,"context_line":"    \u0027password_expires_days\u0027,"},{"line_number":60,"context_line":"    default\u003dNone,"},{"line_number":61,"context_line":"    min\u003d1,"}],"source_content_type":"text/x-python","patch_set":46,"id":"9ad45d7e_3f98f6bf","line":58,"range":{"start_line":58,"start_character":0,"end_line":58,"end_character":21},"updated":"2016-08-10 22:49:43.000000000","message":"rename to maximum_password_age? (in a different patch)","commit_id":"bec68c841e9cd43ce7eb2b1e962b15f3fa7e4aee"},{"author":{"_account_id":4,"name":"Dolph Mathews","email":"dolph.mathews@gmail.com","username":"dolph"},"change_message_id":"d5d7991f3349a105b7d5dca59b588067d3ed546d","unresolved":false,"context_lines":[{"line_number":55,"context_line":"driver`."},{"line_number":56,"context_line":"\"\"\"))"},{"line_number":57,"context_line":""},{"line_number":58,"context_line":"password_expires_days \u003d cfg.IntOpt("},{"line_number":59,"context_line":"    \u0027password_expires_days\u0027,"},{"line_number":60,"context_line":"    default\u003dNone,"},{"line_number":61,"context_line":"    min\u003d1,"}],"source_content_type":"text/x-python","patch_set":46,"id":"9ad45d7e_228e9f27","line":58,"in_reply_to":"9ad45d7e_3f98f6bf","updated":"2016-08-12 21:19:48.000000000","message":"Rename the configuration option, or rename the variable (which should probably match the config var name)?","commit_id":"bec68c841e9cd43ce7eb2b1e962b15f3fa7e4aee"},{"author":{"_account_id":7725,"name":"David Stanek","email":"dstanek@dstanek.com","username":"dstanek"},"change_message_id":"527526a9239d0ba181ead60be8c4f0135b92f3fe","unresolved":false,"context_lines":[{"line_number":81,"context_line":""},{"line_number":82,"context_line":"minimum_password_age \u003d cfg.IntOpt("},{"line_number":83,"context_line":"    \u0027minimum_password_age\u0027,"},{"line_number":84,"context_line":"    default\u003dNone,"},{"line_number":85,"context_line":"    min\u003d1,"},{"line_number":86,"context_line":"    help\u003dutils.fmt(\"\"\""},{"line_number":87,"context_line":"The number of days that a password must be used before the user can change it."}],"source_content_type":"text/x-python","patch_set":46,"id":"5ac665da_e5af967b","line":84,"updated":"2016-08-13 16:39:38.000000000","message":"++","commit_id":"bec68c841e9cd43ce7eb2b1e962b15f3fa7e4aee"},{"author":{"_account_id":4,"name":"Dolph Mathews","email":"dolph.mathews@gmail.com","username":"dolph"},"change_message_id":"d5d7991f3349a105b7d5dca59b588067d3ed546d","unresolved":false,"context_lines":[{"line_number":81,"context_line":""},{"line_number":82,"context_line":"minimum_password_age \u003d cfg.IntOpt("},{"line_number":83,"context_line":"    \u0027minimum_password_age\u0027,"},{"line_number":84,"context_line":"    default\u003dNone,"},{"line_number":85,"context_line":"    min\u003d1,"},{"line_number":86,"context_line":"    help\u003dutils.fmt(\"\"\""},{"line_number":87,"context_line":"The number of days that a password must be used before the user can change it."}],"source_content_type":"text/x-python","patch_set":46,"id":"7ac969e8_e91f7159","line":84,"updated":"2016-08-12 21:19:48.000000000","message":"If this was default\u003d0, min\u003d0 like it was before, then you wouldn\u0027t have to conditionally check to see whether the value is non-null before proceeding to do the math, and we\u0027d have one code path to test instead of 2+. Further, default\u003d0 would also be reasonable default for production environments without forcing an opt in to any new behaviors.","commit_id":"bec68c841e9cd43ce7eb2b1e962b15f3fa7e4aee"},{"author":{"_account_id":18338,"name":"Ron De Rose","email":"ronald.de.rose@intel.com","username":"derosenet"},"change_message_id":"a69b24889118af9c0fdd21f81f7ddd2399a4cc9a","unresolved":false,"context_lines":[{"line_number":81,"context_line":""},{"line_number":82,"context_line":"minimum_password_age \u003d cfg.IntOpt("},{"line_number":83,"context_line":"    \u0027minimum_password_age\u0027,"},{"line_number":84,"context_line":"    default\u003dNone,"},{"line_number":85,"context_line":"    min\u003d1,"},{"line_number":86,"context_line":"    help\u003dutils.fmt(\"\"\""},{"line_number":87,"context_line":"The number of days that a password must be used before the user can change it."}],"source_content_type":"text/x-python","patch_set":46,"id":"3ac371cc_c0f858e8","line":84,"in_reply_to":"5ac665da_e5af967b","updated":"2016-08-15 16:41:32.000000000","message":"It would be more elegant.","commit_id":"bec68c841e9cd43ce7eb2b1e962b15f3fa7e4aee"}],"keystone/identity/backends/base.py":[{"author":{"_account_id":4,"name":"Dolph Mathews","email":"dolph.mathews@gmail.com","username":"dolph"},"change_message_id":"d5d7991f3349a105b7d5dca59b588067d3ed546d","unresolved":false,"context_lines":[{"line_number":273,"context_line":""},{"line_number":274,"context_line":"    @abc.abstractmethod"},{"line_number":275,"context_line":"    def change_password(self, user_id, new_password):"},{"line_number":276,"context_line":"        \"\"\"Self service password change."},{"line_number":277,"context_line":""},{"line_number":278,"context_line":"        :param str user_id: User ID."},{"line_number":279,"context_line":"        :param str new_password: New password."}],"source_content_type":"text/x-python","patch_set":46,"id":"9ad45d7e_252509ae","line":276,"updated":"2016-08-12 21:19:48.000000000","message":"nit: Self-service should be hyphenated.","commit_id":"bec68c841e9cd43ce7eb2b1e962b15f3fa7e4aee"}],"keystone/identity/backends/ldap/core.py":[{"author":{"_account_id":7725,"name":"David Stanek","email":"dstanek@dstanek.com","username":"dstanek"},"change_message_id":"527526a9239d0ba181ead60be8c4f0135b92f3fe","unresolved":false,"context_lines":[{"line_number":116,"context_line":"        self.user.update(user_id, user, old_obj)"},{"line_number":117,"context_line":"        return self.user.get_filtered(user_id)"},{"line_number":118,"context_line":""},{"line_number":119,"context_line":"    def change_password(self, user_id, new_password):"},{"line_number":120,"context_line":"        user \u003d {\u0027password\u0027: new_password}"},{"line_number":121,"context_line":"        self.update_user(user_id, user)"},{"line_number":122,"context_line":""}],"source_content_type":"text/x-python","patch_set":46,"id":"5ac665da_45aaea71","line":119,"updated":"2016-08-13 16:39:38.000000000","message":"++ on not needing real logic here. since this is required by the interface we\u0027ll need to define the method and maybe raise a NotImplemented?","commit_id":"bec68c841e9cd43ce7eb2b1e962b15f3fa7e4aee"},{"author":{"_account_id":6482,"name":"Steve Martinelli","email":"s.martinelli@gmail.com","username":"stevemar"},"change_message_id":"bed103d86302409ff29cca27bec4d73049e9f0b4","unresolved":false,"context_lines":[{"line_number":116,"context_line":"        self.user.update(user_id, user, old_obj)"},{"line_number":117,"context_line":"        return self.user.get_filtered(user_id)"},{"line_number":118,"context_line":""},{"line_number":119,"context_line":"    def change_password(self, user_id, new_password):"},{"line_number":120,"context_line":"        user \u003d {\u0027password\u0027: new_password}"},{"line_number":121,"context_line":"        self.update_user(user_id, user)"},{"line_number":122,"context_line":""}],"source_content_type":"text/x-python","patch_set":46,"id":"9ad45d7e_bc32340e","line":119,"range":{"start_line":119,"start_character":8,"end_line":119,"end_character":23},"updated":"2016-08-10 22:49:43.000000000","message":"probably didn\u0027t need this, we don\u0027t want to add to r/w support for LDAP","commit_id":"bec68c841e9cd43ce7eb2b1e962b15f3fa7e4aee"},{"author":{"_account_id":18338,"name":"Ron De Rose","email":"ronald.de.rose@intel.com","username":"derosenet"},"change_message_id":"a69b24889118af9c0fdd21f81f7ddd2399a4cc9a","unresolved":false,"context_lines":[{"line_number":116,"context_line":"        self.user.update(user_id, user, old_obj)"},{"line_number":117,"context_line":"        return self.user.get_filtered(user_id)"},{"line_number":118,"context_line":""},{"line_number":119,"context_line":"    def change_password(self, user_id, new_password):"},{"line_number":120,"context_line":"        user \u003d {\u0027password\u0027: new_password}"},{"line_number":121,"context_line":"        self.update_user(user_id, user)"},{"line_number":122,"context_line":""}],"source_content_type":"text/x-python","patch_set":46,"id":"3ac371cc_3d18751d","line":119,"in_reply_to":"5ac665da_45aaea71","updated":"2016-08-15 16:41:32.000000000","message":"Okay, keep in mind though, that this functionality is supported today and the purpose of this patch wasn\u0027t necessarily to remove this from the LDAP implementation.","commit_id":"bec68c841e9cd43ce7eb2b1e962b15f3fa7e4aee"},{"author":{"_account_id":4,"name":"Dolph Mathews","email":"dolph.mathews@gmail.com","username":"dolph"},"change_message_id":"d5d7991f3349a105b7d5dca59b588067d3ed546d","unresolved":false,"context_lines":[{"line_number":116,"context_line":"        self.user.update(user_id, user, old_obj)"},{"line_number":117,"context_line":"        return self.user.get_filtered(user_id)"},{"line_number":118,"context_line":""},{"line_number":119,"context_line":"    def change_password(self, user_id, new_password):"},{"line_number":120,"context_line":"        user \u003d {\u0027password\u0027: new_password}"},{"line_number":121,"context_line":"        self.update_user(user_id, user)"},{"line_number":122,"context_line":""}],"source_content_type":"text/x-python","patch_set":46,"id":"9ad45d7e_6556e107","line":119,"in_reply_to":"9ad45d7e_bc32340e","updated":"2016-08-12 21:19:48.000000000","message":"I agree with Steve; R/W support is deprecated, so we should explicitly leave this unimplemented in LDAP and test that the method is unimplemented in unit tests.","commit_id":"bec68c841e9cd43ce7eb2b1e962b15f3fa7e4aee"}],"keystone/identity/backends/sql.py":[{"author":{"_account_id":17862,"name":"Kseniya Tychkova","email":"kseniya.tychkova@gmail.com","username":"ktychkova"},"change_message_id":"c5be00dc05aa04e88dae780024ba1ecf85b9105a","unresolved":false,"context_lines":[{"line_number":111,"context_line":"    def update_user(self, user_id, user, self_service):"},{"line_number":112,"context_line":"        with sql.session_for_write() as session:"},{"line_number":113,"context_line":"            user_ref \u003d self._get_user(session, user_id)"},{"line_number":114,"context_line":"            if \u0027password\u0027 in user and self_service:"},{"line_number":115,"context_line":"                self._validate_password_can_change(user_ref)"},{"line_number":116,"context_line":"            old_user_dict \u003d user_ref.to_dict()"},{"line_number":117,"context_line":"            user \u003d utils.hash_user_password(user)"}],"source_content_type":"text/x-python","patch_set":15,"id":"dada55a8_d3eace73","line":114,"updated":"2016-07-25 10:08:46.000000000","message":"This \u0027if\u0027 is also validates that password can be changes. Is it better to move it into _validate_password_can_change?","commit_id":"80a3da136b88159f3ca41ea74809fb262c76d779"},{"author":{"_account_id":18338,"name":"Ron De Rose","email":"ronald.de.rose@intel.com","username":"derosenet"},"change_message_id":"1176a5c42b2766f1f0f6fc74e6376585d03b0272","unresolved":false,"context_lines":[{"line_number":111,"context_line":"    def update_user(self, user_id, user, self_service):"},{"line_number":112,"context_line":"        with sql.session_for_write() as session:"},{"line_number":113,"context_line":"            user_ref \u003d self._get_user(session, user_id)"},{"line_number":114,"context_line":"            if \u0027password\u0027 in user and self_service:"},{"line_number":115,"context_line":"                self._validate_password_can_change(user_ref)"},{"line_number":116,"context_line":"            old_user_dict \u003d user_ref.to_dict()"},{"line_number":117,"context_line":"            user \u003d utils.hash_user_password(user)"}],"source_content_type":"text/x-python","patch_set":15,"id":"dada55a8_6ff673fa","line":114,"in_reply_to":"dada55a8_d3eace73","updated":"2016-07-25 20:52:22.000000000","message":"Well, I\u0027m only validating if a password can change if the user is attempting to update their password. So I don\u0027t think the if statements needs to move.","commit_id":"80a3da136b88159f3ca41ea74809fb262c76d779"},{"author":{"_account_id":17862,"name":"Kseniya Tychkova","email":"kseniya.tychkova@gmail.com","username":"ktychkova"},"change_message_id":"c5be00dc05aa04e88dae780024ba1ecf85b9105a","unresolved":false,"context_lines":[{"line_number":125,"context_line":"            return base.filter_user("},{"line_number":126,"context_line":"                user_ref.to_dict(include_extra_dict\u003dTrue))"},{"line_number":127,"context_line":""},{"line_number":128,"context_line":"    def _validate_password_can_change(self, user_ref):"},{"line_number":129,"context_line":"        min_age_days \u003d CONF.security_compliance.minimum_password_age"},{"line_number":130,"context_line":"        if min_age_days and user_ref.password_created_at:"},{"line_number":131,"context_line":"            expires_days \u003d CONF.security_compliance.password_expires_days"}],"source_content_type":"text/x-python","patch_set":15,"id":"dada55a8_8e014907","line":128,"updated":"2016-07-25 10:08:46.000000000","message":"in \u0027ldap\u0027 we have method self.user.check_allow_update()\nMaybe it is better to have here the same and call _validate_password_can_change from it? Are you going to add more validation in future?","commit_id":"80a3da136b88159f3ca41ea74809fb262c76d779"},{"author":{"_account_id":18338,"name":"Ron De Rose","email":"ronald.de.rose@intel.com","username":"derosenet"},"change_message_id":"1176a5c42b2766f1f0f6fc74e6376585d03b0272","unresolved":false,"context_lines":[{"line_number":125,"context_line":"            return base.filter_user("},{"line_number":126,"context_line":"                user_ref.to_dict(include_extra_dict\u003dTrue))"},{"line_number":127,"context_line":""},{"line_number":128,"context_line":"    def _validate_password_can_change(self, user_ref):"},{"line_number":129,"context_line":"        min_age_days \u003d CONF.security_compliance.minimum_password_age"},{"line_number":130,"context_line":"        if min_age_days and user_ref.password_created_at:"},{"line_number":131,"context_line":"            expires_days \u003d CONF.security_compliance.password_expires_days"}],"source_content_type":"text/x-python","patch_set":15,"id":"dada55a8_6fb313ea","line":128,"in_reply_to":"dada55a8_8e014907","updated":"2016-07-25 20:52:22.000000000","message":"The implementation for check_allow_update() is in the common module for LDAP. We don\u0027t have a common module for the SQL backend. I think this is fine here for now, but it\u0027s a good point should we add more validation specific to the SQL backend. I\u0027ll keep this in mind.","commit_id":"80a3da136b88159f3ca41ea74809fb262c76d779"},{"author":{"_account_id":13063,"name":"WEI CHEN","email":"dave.jungler@gmail.com","username":"wei.d.chen"},"change_message_id":"82695eb5e96fd38542ce1e72170d438ba892afff","unresolved":false,"context_lines":[{"line_number":137,"context_line":"                LOG.error(msg)"},{"line_number":138,"context_line":"                detail \u003d _(\u0027Unable to validate minimum password age due to \u0027"},{"line_number":139,"context_line":"                           \u0027invalid configuration\u0027)"},{"line_number":140,"context_line":"                raise exception.PasswordValidationError(detail\u003ddetail)"},{"line_number":141,"context_line":"            min_age \u003d (user_ref.password_created_at +"},{"line_number":142,"context_line":"                       datetime.timedelta(days\u003dmin_age_days)).date()"},{"line_number":143,"context_line":"            if datetime.datetime.utcnow().date() \u003c min_age:"}],"source_content_type":"text/x-python","patch_set":15,"id":"dada55a8_c594c4e9","line":140,"range":{"start_line":140,"start_character":56,"end_line":140,"end_character":69},"updated":"2016-07-25 09:44:38.000000000","message":"I think the `msg` above is more detail than this one, fine with as it is.","commit_id":"80a3da136b88159f3ca41ea74809fb262c76d779"},{"author":{"_account_id":18338,"name":"Ron De Rose","email":"ronald.de.rose@intel.com","username":"derosenet"},"change_message_id":"1176a5c42b2766f1f0f6fc74e6376585d03b0272","unresolved":false,"context_lines":[{"line_number":137,"context_line":"                LOG.error(msg)"},{"line_number":138,"context_line":"                detail \u003d _(\u0027Unable to validate minimum password age due to \u0027"},{"line_number":139,"context_line":"                           \u0027invalid configuration\u0027)"},{"line_number":140,"context_line":"                raise exception.PasswordValidationError(detail\u003ddetail)"},{"line_number":141,"context_line":"            min_age \u003d (user_ref.password_created_at +"},{"line_number":142,"context_line":"                       datetime.timedelta(days\u003dmin_age_days)).date()"},{"line_number":143,"context_line":"            if datetime.datetime.utcnow().date() \u003c min_age:"}],"source_content_type":"text/x-python","patch_set":15,"id":"dada55a8_0fdc1711","line":140,"range":{"start_line":140,"start_character":56,"end_line":140,"end_character":69},"in_reply_to":"dada55a8_c594c4e9","updated":"2016-07-25 20:52:22.000000000","message":"Yeah, and that was my intent, that the user would receive a more generic message, and the detailed message would be logged.","commit_id":"80a3da136b88159f3ca41ea74809fb262c76d779"},{"author":{"_account_id":13063,"name":"WEI CHEN","email":"dave.jungler@gmail.com","username":"wei.d.chen"},"change_message_id":"82695eb5e96fd38542ce1e72170d438ba892afff","unresolved":false,"context_lines":[{"line_number":141,"context_line":"            min_age \u003d (user_ref.password_created_at +"},{"line_number":142,"context_line":"                       datetime.timedelta(days\u003dmin_age_days)).date()"},{"line_number":143,"context_line":"            if datetime.datetime.utcnow().date() \u003c min_age:"},{"line_number":144,"context_line":"                detail \u003d _(\u0027The password cannot be changed at this time \u0027"},{"line_number":145,"context_line":"                           \u0027due to the minimum password age.\u0027)"},{"line_number":146,"context_line":"                raise exception.PasswordValidationError(detail\u003ddetail)"},{"line_number":147,"context_line":""},{"line_number":148,"context_line":"    def add_user_to_group(self, user_id, group_id):"}],"source_content_type":"text/x-python","patch_set":15,"id":"dada55a8_45b0d48b","line":145,"range":{"start_line":144,"start_character":16,"end_line":145,"end_character":62},"updated":"2016-07-25 09:44:38.000000000","message":"Any value to log these information too?","commit_id":"80a3da136b88159f3ca41ea74809fb262c76d779"},{"author":{"_account_id":18338,"name":"Ron De Rose","email":"ronald.de.rose@intel.com","username":"derosenet"},"change_message_id":"dd5b3d8d1dbab1c9341a9dd91967523cccd28a2f","unresolved":false,"context_lines":[{"line_number":141,"context_line":"            min_age \u003d (user_ref.password_created_at +"},{"line_number":142,"context_line":"                       datetime.timedelta(days\u003dmin_age_days)).date()"},{"line_number":143,"context_line":"            if datetime.datetime.utcnow().date() \u003c min_age:"},{"line_number":144,"context_line":"                detail \u003d _(\u0027The password cannot be changed at this time \u0027"},{"line_number":145,"context_line":"                           \u0027due to the minimum password age.\u0027)"},{"line_number":146,"context_line":"                raise exception.PasswordValidationError(detail\u003ddetail)"},{"line_number":147,"context_line":""},{"line_number":148,"context_line":"    def add_user_to_group(self, user_id, group_id):"}],"source_content_type":"text/x-python","patch_set":15,"id":"dada55a8_61ab3a1e","line":145,"range":{"start_line":144,"start_character":16,"end_line":145,"end_character":62},"in_reply_to":"dada55a8_45b0d48b","updated":"2016-07-25 15:29:23.000000000","message":"No, I don\u0027t think it\u0027s appropriate to log this message. I log the above message because that is unexpected behavior.","commit_id":"80a3da136b88159f3ca41ea74809fb262c76d779"},{"author":{"_account_id":7725,"name":"David Stanek","email":"dstanek@dstanek.com","username":"dstanek"},"change_message_id":"29cc7dc38d9cc3d28e2546eea433f5bf2e58ff8d","unresolved":false,"context_lines":[{"line_number":130,"context_line":"        if min_age_days and user_ref.password_created_at:"},{"line_number":131,"context_line":"            expires_days \u003d CONF.security_compliance.password_expires_days"},{"line_number":132,"context_line":"            if expires_days and (expires_days \u003c\u003d min_age_days):"},{"line_number":133,"context_line":"                msg \u003d _LE(\u0027Unable to validate the minimum password age, the \u0027"},{"line_number":134,"context_line":"                          \u0027configuration `[security_compliance] \u0027"},{"line_number":135,"context_line":"                          \u0027minimum_password_age` must be less than \u0027"},{"line_number":136,"context_line":"                          \u0027`[security_compliance] password_expires_days`\u0027)"}],"source_content_type":"text/x-python","patch_set":21,"id":"bacf61ea_abca4318","line":133,"updated":"2016-07-28 20:14:06.000000000","message":"Can\u0027t we check this earlier? It seems like something a cloud provider should know immediately instead of getting evaluated for each password change.","commit_id":"7bb2df9925d13fdd3fb04d508b6509a247a7520d"},{"author":{"_account_id":18338,"name":"Ron De Rose","email":"ronald.de.rose@intel.com","username":"derosenet"},"change_message_id":"8b1ce3dd1abc5240e7e0283f533d648252c04896","unresolved":false,"context_lines":[{"line_number":130,"context_line":"        if min_age_days and user_ref.password_created_at:"},{"line_number":131,"context_line":"            expires_days \u003d CONF.security_compliance.password_expires_days"},{"line_number":132,"context_line":"            if expires_days and (expires_days \u003c\u003d min_age_days):"},{"line_number":133,"context_line":"                msg \u003d _LE(\u0027Unable to validate the minimum password age, the \u0027"},{"line_number":134,"context_line":"                          \u0027configuration `[security_compliance] \u0027"},{"line_number":135,"context_line":"                          \u0027minimum_password_age` must be less than \u0027"},{"line_number":136,"context_line":"                          \u0027`[security_compliance] password_expires_days`\u0027)"}],"source_content_type":"text/x-python","patch_set":21,"id":"bacf61ea_f6f37e08","line":133,"in_reply_to":"bacf61ea_abca4318","updated":"2016-07-28 20:33:29.000000000","message":"Where would you suggest?","commit_id":"7bb2df9925d13fdd3fb04d508b6509a247a7520d"},{"author":{"_account_id":7725,"name":"David Stanek","email":"dstanek@dstanek.com","username":"dstanek"},"change_message_id":"29cc7dc38d9cc3d28e2546eea433f5bf2e58ff8d","unresolved":false,"context_lines":[{"line_number":142,"context_line":"                       datetime.timedelta(days\u003dmin_age_days)).date()"},{"line_number":143,"context_line":"            if datetime.datetime.utcnow().date() \u003c min_age:"},{"line_number":144,"context_line":"                detail \u003d _(\u0027The password cannot be changed at this time \u0027"},{"line_number":145,"context_line":"                           \u0027due to the minimum password age.\u0027)"},{"line_number":146,"context_line":"                raise exception.PasswordValidationError(detail\u003ddetail)"},{"line_number":147,"context_line":""},{"line_number":148,"context_line":"    def add_user_to_group(self, user_id, group_id):"}],"source_content_type":"text/x-python","patch_set":21,"id":"bacf61ea_4bdc67e4","line":145,"updated":"2016-07-28 20:14:06.000000000","message":"Should we tell them how long they need to wait or the total length of the min days?","commit_id":"7bb2df9925d13fdd3fb04d508b6509a247a7520d"},{"author":{"_account_id":7725,"name":"David Stanek","email":"dstanek@dstanek.com","username":"dstanek"},"change_message_id":"16e6c913aaf0190c70b6b20942ef01eae20caaec","unresolved":false,"context_lines":[{"line_number":155,"context_line":"                           \u0027due to the minimum password age. Once you \u0027"},{"line_number":156,"context_line":"                           \u0027change your password, it must be used for \u0027"},{"line_number":157,"context_line":"                           \u0027%(min_age_days)d day(s) before you can change it \u0027"},{"line_number":158,"context_line":"                           \u0027again.\u0027) % {\u0027min_age_days\u0027: min_age_days}"},{"line_number":159,"context_line":"                raise exception.PasswordValidationError(detail\u003ddetail)"},{"line_number":160,"context_line":""},{"line_number":161,"context_line":"    def add_user_to_group(self, user_id, group_id):"}],"source_content_type":"text/x-python","patch_set":34,"id":"bacf61ea_5e86bcdb","line":158,"updated":"2016-08-04 11:23:01.000000000","message":"What would be cool is to actually show the date when the password can change. So instead of saying you must wait 10 day it would say you must wait until Wed, Feb 29..... This might be difficult due to locale?","commit_id":"e7795330c8ea9f38fd437bc3649c6ec226194e4a"},{"author":{"_account_id":18338,"name":"Ron De Rose","email":"ronald.de.rose@intel.com","username":"derosenet"},"change_message_id":"10dc85b0704c6b5167601f5df7afc7bf4b16eebc","unresolved":false,"context_lines":[{"line_number":155,"context_line":"                           \u0027due to the minimum password age. Once you \u0027"},{"line_number":156,"context_line":"                           \u0027change your password, it must be used for \u0027"},{"line_number":157,"context_line":"                           \u0027%(min_age_days)d day(s) before you can change it \u0027"},{"line_number":158,"context_line":"                           \u0027again.\u0027) % {\u0027min_age_days\u0027: min_age_days}"},{"line_number":159,"context_line":"                raise exception.PasswordValidationError(detail\u003ddetail)"},{"line_number":160,"context_line":""},{"line_number":161,"context_line":"    def add_user_to_group(self, user_id, group_id):"}],"source_content_type":"text/x-python","patch_set":34,"id":"bacf61ea_67b68cfa","line":158,"in_reply_to":"bacf61ea_5e86bcdb","updated":"2016-08-04 14:13:08.000000000","message":"I did the \u0027try again in X days\u0027 approach.","commit_id":"e7795330c8ea9f38fd437bc3649c6ec226194e4a"},{"author":{"_account_id":5046,"name":"Lance Bragstad","email":"lbragstad@redhat.com","username":"ldbragst"},"change_message_id":"7a3b113efdbcb3507e00ca537b9dbed12b6ac9d9","unresolved":false,"context_lines":[{"line_number":204,"context_line":"                           \u0027to the minimum password age. Once you change your \u0027"},{"line_number":205,"context_line":"                           \u0027password, it must be used for %(min_age_days)d \u0027"},{"line_number":206,"context_line":"                           \u0027day(s) before it can be changed. Please try again \u0027"},{"line_number":207,"context_line":"                           \u0027in %(days_left)d day(s).\u0027) % ("},{"line_number":208,"context_line":"                               {\u0027min_age_days\u0027: min_age_days,"},{"line_number":209,"context_line":"                                \u0027days_left\u0027: days_left})"},{"line_number":210,"context_line":"                raise exception.PasswordValidationError(detail\u003ddetail)"}],"source_content_type":"text/x-python","patch_set":36,"id":"bacf61ea_542e54a5","line":207,"updated":"2016-08-05 15:14:48.000000000","message":"They can also talk to their administrator, right?","commit_id":"d0183aae5192e82843c75dbb532572681dad8001"},{"author":{"_account_id":18338,"name":"Ron De Rose","email":"ronald.de.rose@intel.com","username":"derosenet"},"change_message_id":"0f2a4a2cd403324439a5ebc4240aa3bd03c3019e","unresolved":false,"context_lines":[{"line_number":204,"context_line":"                           \u0027to the minimum password age. Once you change your \u0027"},{"line_number":205,"context_line":"                           \u0027password, it must be used for %(min_age_days)d \u0027"},{"line_number":206,"context_line":"                           \u0027day(s) before it can be changed. Please try again \u0027"},{"line_number":207,"context_line":"                           \u0027in %(days_left)d day(s).\u0027) % ("},{"line_number":208,"context_line":"                               {\u0027min_age_days\u0027: min_age_days,"},{"line_number":209,"context_line":"                                \u0027days_left\u0027: days_left})"},{"line_number":210,"context_line":"                raise exception.PasswordValidationError(detail\u003ddetail)"}],"source_content_type":"text/x-python","patch_set":36,"id":"bacf61ea_950726c9","line":207,"in_reply_to":"bacf61ea_542e54a5","updated":"2016-08-05 15:53:17.000000000","message":"Talk to their admin to change their password for them?  I don\u0027t think that would be common, right? I mean I imagine they would just wait.","commit_id":"d0183aae5192e82843c75dbb532572681dad8001"},{"author":{"_account_id":18338,"name":"Ron De Rose","email":"ronald.de.rose@intel.com","username":"derosenet"},"change_message_id":"2e56e231ab6db9136fe8e5e9857c1d8e7d2772a1","unresolved":false,"context_lines":[{"line_number":204,"context_line":"                           \u0027to the minimum password age. Once you change your \u0027"},{"line_number":205,"context_line":"                           \u0027password, it must be used for %(min_age_days)d \u0027"},{"line_number":206,"context_line":"                           \u0027day(s) before it can be changed. Please try again \u0027"},{"line_number":207,"context_line":"                           \u0027in %(days_left)d day(s).\u0027) % ("},{"line_number":208,"context_line":"                               {\u0027min_age_days\u0027: min_age_days,"},{"line_number":209,"context_line":"                                \u0027days_left\u0027: days_left})"},{"line_number":210,"context_line":"                raise exception.PasswordValidationError(detail\u003ddetail)"}],"source_content_type":"text/x-python","patch_set":36,"id":"bacf61ea_2aded8dc","line":207,"in_reply_to":"bacf61ea_950726c9","updated":"2016-08-05 16:18:33.000000000","message":"Nevermind, I see your point.  I\u0027ve reworded this.  Done.","commit_id":"d0183aae5192e82843c75dbb532572681dad8001"},{"author":{"_account_id":5046,"name":"Lance Bragstad","email":"lbragstad@redhat.com","username":"ldbragst"},"change_message_id":"68da4af854a4a52a49c1427acf977ff5f9628dea","unresolved":false,"context_lines":[{"line_number":205,"context_line":"                           \u0027password, it must be used for %(min_age_days)d \u0027"},{"line_number":206,"context_line":"                           \u0027day(s) before it can be changed. Please try again \u0027"},{"line_number":207,"context_line":"                           \u0027in %(days_left)d day(s) or contact your \u0027"},{"line_number":208,"context_line":"                           \u0027administrator.\u0027) % ("},{"line_number":209,"context_line":"                               {\u0027min_age_days\u0027: min_age_days,"},{"line_number":210,"context_line":"                                \u0027days_left\u0027: days_left})"},{"line_number":211,"context_line":"                raise exception.PasswordValidationError(detail\u003ddetail)"}],"source_content_type":"text/x-python","patch_set":39,"id":"9ad45d7e_656d5304","line":208,"updated":"2016-08-08 16:20:13.000000000","message":"nit: \n\n    or contact your administrator to assist with manual password resets.\n\n?\n\nI\u0027m just trying to think of ways were we can give the user a little more information about what exactly they need to contact the administrator about.","commit_id":"b26bbd502aeba8b6a5435ee2549464fd082d1969"},{"author":{"_account_id":18338,"name":"Ron De Rose","email":"ronald.de.rose@intel.com","username":"derosenet"},"change_message_id":"2b1ef98264141314e5f2b44de19ad4a4e54c04a8","unresolved":false,"context_lines":[{"line_number":205,"context_line":"                           \u0027password, it must be used for %(min_age_days)d \u0027"},{"line_number":206,"context_line":"                           \u0027day(s) before it can be changed. Please try again \u0027"},{"line_number":207,"context_line":"                           \u0027in %(days_left)d day(s) or contact your \u0027"},{"line_number":208,"context_line":"                           \u0027administrator.\u0027) % ("},{"line_number":209,"context_line":"                               {\u0027min_age_days\u0027: min_age_days,"},{"line_number":210,"context_line":"                                \u0027days_left\u0027: days_left})"},{"line_number":211,"context_line":"                raise exception.PasswordValidationError(detail\u003ddetail)"}],"source_content_type":"text/x-python","patch_set":39,"id":"9ad45d7e_aba4d6a5","line":208,"in_reply_to":"9ad45d7e_656d5304","updated":"2016-08-10 09:31:24.000000000","message":"Done","commit_id":"b26bbd502aeba8b6a5435ee2549464fd082d1969"},{"author":{"_account_id":7725,"name":"David Stanek","email":"dstanek@dstanek.com","username":"dstanek"},"change_message_id":"527526a9239d0ba181ead60be8c4f0135b92f3fe","unresolved":false,"context_lines":[{"line_number":188,"context_line":"                               \u0027%(unique_cnt)d\u0027) % {\u0027unique_cnt\u0027: unique_cnt}"},{"line_number":189,"context_line":"                    raise exception.PasswordValidationError(detail\u003ddetail)"},{"line_number":190,"context_line":""},{"line_number":191,"context_line":"    def change_password(self, user_id, new_password):"},{"line_number":192,"context_line":"        with sql.session_for_write() as session:"},{"line_number":193,"context_line":"            user_ref \u003d session.query(model.User).get(user_id)"},{"line_number":194,"context_line":"            if user_ref.password_ref and user_ref.password_ref.self_service:"}],"source_content_type":"text/x-python","patch_set":46,"id":"5ac665da_05a0f28f","line":191,"updated":"2016-08-13 16:39:38.000000000","message":"Would the intent be more clear if this were named \u0027self_service_change_password\u0027?","commit_id":"bec68c841e9cd43ce7eb2b1e962b15f3fa7e4aee"},{"author":{"_account_id":18338,"name":"Ron De Rose","email":"ronald.de.rose@intel.com","username":"derosenet"},"change_message_id":"a69b24889118af9c0fdd21f81f7ddd2399a4cc9a","unresolved":false,"context_lines":[{"line_number":188,"context_line":"                               \u0027%(unique_cnt)d\u0027) % {\u0027unique_cnt\u0027: unique_cnt}"},{"line_number":189,"context_line":"                    raise exception.PasswordValidationError(detail\u003ddetail)"},{"line_number":190,"context_line":""},{"line_number":191,"context_line":"    def change_password(self, user_id, new_password):"},{"line_number":192,"context_line":"        with sql.session_for_write() as session:"},{"line_number":193,"context_line":"            user_ref \u003d session.query(model.User).get(user_id)"},{"line_number":194,"context_line":"            if user_ref.password_ref and user_ref.password_ref.self_service:"}],"source_content_type":"text/x-python","patch_set":46,"id":"3ac371cc_fd79bd30","line":191,"in_reply_to":"5ac665da_05a0f28f","updated":"2016-08-15 16:41:32.000000000","message":"True, however it is consistent with the other high level classes (manager, controller, API) where the method name is change_password and self-service is implied.","commit_id":"bec68c841e9cd43ce7eb2b1e962b15f3fa7e4aee"},{"author":{"_account_id":4,"name":"Dolph Mathews","email":"dolph.mathews@gmail.com","username":"dolph"},"change_message_id":"d5d7991f3349a105b7d5dca59b588067d3ed546d","unresolved":false,"context_lines":[{"line_number":198,"context_line":""},{"line_number":199,"context_line":"    def _validate_minimum_password_age(self, user_ref):"},{"line_number":200,"context_line":"        min_age_days \u003d CONF.security_compliance.minimum_password_age"},{"line_number":201,"context_line":"        if min_age_days:"},{"line_number":202,"context_line":"            min_age \u003d (user_ref.password_created_at +"},{"line_number":203,"context_line":"                       datetime.timedelta(days\u003dmin_age_days)).date()"},{"line_number":204,"context_line":"            if datetime.datetime.utcnow().date() \u003c min_age:"}],"source_content_type":"text/x-python","patch_set":46,"id":"7ac969e8_093e4db8","line":201,"updated":"2016-08-12 21:19:48.000000000","message":"You wouldn\u0027t need this conditional if min_password_days defaulted to 0 instead of a useless null value (which would break the timedelta code below.","commit_id":"bec68c841e9cd43ce7eb2b1e962b15f3fa7e4aee"},{"author":{"_account_id":18338,"name":"Ron De Rose","email":"ronald.de.rose@intel.com","username":"derosenet"},"change_message_id":"a69b24889118af9c0fdd21f81f7ddd2399a4cc9a","unresolved":false,"context_lines":[{"line_number":198,"context_line":""},{"line_number":199,"context_line":"    def _validate_minimum_password_age(self, user_ref):"},{"line_number":200,"context_line":"        min_age_days \u003d CONF.security_compliance.minimum_password_age"},{"line_number":201,"context_line":"        if min_age_days:"},{"line_number":202,"context_line":"            min_age \u003d (user_ref.password_created_at +"},{"line_number":203,"context_line":"                       datetime.timedelta(days\u003dmin_age_days)).date()"},{"line_number":204,"context_line":"            if datetime.datetime.utcnow().date() \u003c min_age:"}],"source_content_type":"text/x-python","patch_set":46,"id":"3ac371cc_3d74f533","line":201,"in_reply_to":"7ac969e8_093e4db8","updated":"2016-08-15 16:41:32.000000000","message":"++","commit_id":"bec68c841e9cd43ce7eb2b1e962b15f3fa7e4aee"},{"author":{"_account_id":4,"name":"Dolph Mathews","email":"dolph.mathews@gmail.com","username":"dolph"},"change_message_id":"d5d7991f3349a105b7d5dca59b588067d3ed546d","unresolved":false,"context_lines":[{"line_number":201,"context_line":"        if min_age_days:"},{"line_number":202,"context_line":"            min_age \u003d (user_ref.password_created_at +"},{"line_number":203,"context_line":"                       datetime.timedelta(days\u003dmin_age_days)).date()"},{"line_number":204,"context_line":"            if datetime.datetime.utcnow().date() \u003c min_age:"},{"line_number":205,"context_line":"                days_left \u003d (min_age - datetime.datetime.utcnow().date()).days"},{"line_number":206,"context_line":"                detail \u003d _(\u0027You cannot change your password at this time due \u0027"},{"line_number":207,"context_line":"                           \u0027to the minimum password age. Once you change your \u0027"}],"source_content_type":"text/x-python","patch_set":46,"id":"9ad45d7e_452abd2d","line":204,"updated":"2016-08-12 21:19:48.000000000","message":"Why do you have to do .date() on both of these? Intentional loss of precision?","commit_id":"bec68c841e9cd43ce7eb2b1e962b15f3fa7e4aee"},{"author":{"_account_id":18338,"name":"Ron De Rose","email":"ronald.de.rose@intel.com","username":"derosenet"},"change_message_id":"a69b24889118af9c0fdd21f81f7ddd2399a4cc9a","unresolved":false,"context_lines":[{"line_number":201,"context_line":"        if min_age_days:"},{"line_number":202,"context_line":"            min_age \u003d (user_ref.password_created_at +"},{"line_number":203,"context_line":"                       datetime.timedelta(days\u003dmin_age_days)).date()"},{"line_number":204,"context_line":"            if datetime.datetime.utcnow().date() \u003c min_age:"},{"line_number":205,"context_line":"                days_left \u003d (min_age - datetime.datetime.utcnow().date()).days"},{"line_number":206,"context_line":"                detail \u003d _(\u0027You cannot change your password at this time due \u0027"},{"line_number":207,"context_line":"                           \u0027to the minimum password age. Once you change your \u0027"}],"source_content_type":"text/x-python","patch_set":46,"id":"3ac371cc_dde7a1e2","line":204,"in_reply_to":"9ad45d7e_452abd2d","updated":"2016-08-15 16:41:32.000000000","message":"True, loss of precision, however I\u0027m only concerned about days; not minutes or seconds.","commit_id":"bec68c841e9cd43ce7eb2b1e962b15f3fa7e4aee"},{"author":{"_account_id":4,"name":"Dolph Mathews","email":"dolph.mathews@gmail.com","username":"dolph"},"change_message_id":"d5d7991f3349a105b7d5dca59b588067d3ed546d","unresolved":false,"context_lines":[{"line_number":203,"context_line":"                       datetime.timedelta(days\u003dmin_age_days)).date()"},{"line_number":204,"context_line":"            if datetime.datetime.utcnow().date() \u003c min_age:"},{"line_number":205,"context_line":"                days_left \u003d (min_age - datetime.datetime.utcnow().date()).days"},{"line_number":206,"context_line":"                detail \u003d _(\u0027You cannot change your password at this time due \u0027"},{"line_number":207,"context_line":"                           \u0027to the minimum password age. Once you change your \u0027"},{"line_number":208,"context_line":"                           \u0027password, it must be used for %(min_age_days)d \u0027"},{"line_number":209,"context_line":"                           \u0027day(s) before it can be changed. Please try again \u0027"}],"source_content_type":"text/x-python","patch_set":46,"id":"9ad45d7e_45863d14","line":206,"updated":"2016-08-12 21:19:48.000000000","message":"Seems like this help text should really be defined in a dedicated exception class, rather than being defined in the SQl driver and passed up to a generic exception.","commit_id":"bec68c841e9cd43ce7eb2b1e962b15f3fa7e4aee"}],"keystone/identity/backends/sql_model.py":[{"author":{"_account_id":4,"name":"Dolph Mathews","email":"dolph.mathews@gmail.com","username":"dolph"},"change_message_id":"d5d7991f3349a105b7d5dca59b588067d3ed546d","unresolved":false,"context_lines":[{"line_number":237,"context_line":"                            default\u003ddatetime.datetime.utcnow)"},{"line_number":238,"context_line":"    expires_at \u003d sql.Column(sql.DateTime, nullable\u003dTrue)"},{"line_number":239,"context_line":"    self_service \u003d sql.Column(sql.Boolean, default\u003dFalse, nullable\u003dFalse,"},{"line_number":240,"context_line":"                              server_default\u003d\u00270\u0027)"},{"line_number":241,"context_line":""},{"line_number":242,"context_line":""},{"line_number":243,"context_line":"class FederatedUser(sql.ModelBase, sql.ModelDictMixin):"}],"source_content_type":"text/x-python","patch_set":46,"id":"7ac969e8_66c44e40","line":240,"updated":"2016-08-12 21:19:48.000000000","message":"Why is this a string? Does that actually work?\n\n  server_default\u003dFalse","commit_id":"bec68c841e9cd43ce7eb2b1e962b15f3fa7e4aee"},{"author":{"_account_id":18338,"name":"Ron De Rose","email":"ronald.de.rose@intel.com","username":"derosenet"},"change_message_id":"a69b24889118af9c0fdd21f81f7ddd2399a4cc9a","unresolved":false,"context_lines":[{"line_number":237,"context_line":"                            default\u003ddatetime.datetime.utcnow)"},{"line_number":238,"context_line":"    expires_at \u003d sql.Column(sql.DateTime, nullable\u003dTrue)"},{"line_number":239,"context_line":"    self_service \u003d sql.Column(sql.Boolean, default\u003dFalse, nullable\u003dFalse,"},{"line_number":240,"context_line":"                              server_default\u003d\u00270\u0027)"},{"line_number":241,"context_line":""},{"line_number":242,"context_line":""},{"line_number":243,"context_line":"class FederatedUser(sql.ModelBase, sql.ModelDictMixin):"}],"source_content_type":"text/x-python","patch_set":46,"id":"3ac371cc_3d4cf5c6","line":240,"in_reply_to":"7ac969e8_66c44e40","updated":"2016-08-15 16:41:32.000000000","message":"From my research, for server_default to work across databases, you need to use basic string or integer defaults, which is how we\u0027ve done handled this in the past:\nhttps://github.com/openstack/keystone/blob/master/keystone/common/sql/migrate_repo/versions/074_add_is_domain_project.py#L26","commit_id":"bec68c841e9cd43ce7eb2b1e962b15f3fa7e4aee"}],"keystone/identity/core.py":[{"author":{"_account_id":13063,"name":"WEI CHEN","email":"dave.jungler@gmail.com","username":"wei.d.chen"},"change_message_id":"82695eb5e96fd38542ce1e72170d438ba892afff","unresolved":false,"context_lines":[{"line_number":933,"context_line":""},{"line_number":934,"context_line":"    @domains_configured"},{"line_number":935,"context_line":"    @exception_translated(\u0027user\u0027)"},{"line_number":936,"context_line":"    def update_user(self, user_id, user_ref, initiator\u003dNone,"},{"line_number":937,"context_line":"                    self_service\u003dFalse):"},{"line_number":938,"context_line":"        old_user_ref \u003d self.get_user(user_id)"},{"line_number":939,"context_line":"        user \u003d user_ref.copy()"},{"line_number":940,"context_line":"        if \u0027password\u0027 in user:"}],"source_content_type":"text/x-python","patch_set":15,"id":"dada55a8_e2df3e38","line":937,"range":{"start_line":936,"start_character":0,"end_line":937,"end_character":40},"updated":"2016-07-25 09:44:38.000000000","message":"There is no testcase to test update user with `self_service` default to False, so that we know it\u0027s different with updating user\u0027s password.","commit_id":"80a3da136b88159f3ca41ea74809fb262c76d779"},{"author":{"_account_id":18338,"name":"Ron De Rose","email":"ronald.de.rose@intel.com","username":"derosenet"},"change_message_id":"1176a5c42b2766f1f0f6fc74e6376585d03b0272","unresolved":false,"context_lines":[{"line_number":933,"context_line":""},{"line_number":934,"context_line":"    @domains_configured"},{"line_number":935,"context_line":"    @exception_translated(\u0027user\u0027)"},{"line_number":936,"context_line":"    def update_user(self, user_id, user_ref, initiator\u003dNone,"},{"line_number":937,"context_line":"                    self_service\u003dFalse):"},{"line_number":938,"context_line":"        old_user_ref \u003d self.get_user(user_id)"},{"line_number":939,"context_line":"        user \u003d user_ref.copy()"},{"line_number":940,"context_line":"        if \u0027password\u0027 in user:"}],"source_content_type":"text/x-python","patch_set":15,"id":"dada55a8_2a8bc91f","line":937,"range":{"start_line":936,"start_character":0,"end_line":937,"end_character":40},"in_reply_to":"dada55a8_e2df3e38","updated":"2016-07-25 20:52:22.000000000","message":"I\u0027ve added test cases to test_base. The test methods in test_backend_sql tests the validation logic.","commit_id":"80a3da136b88159f3ca41ea74809fb262c76d779"},{"author":{"_account_id":17862,"name":"Kseniya Tychkova","email":"kseniya.tychkova@gmail.com","username":"ktychkova"},"change_message_id":"c5be00dc05aa04e88dae780024ba1ecf85b9105a","unresolved":false,"context_lines":[{"line_number":1234,"context_line":"        validators.validate_password(new_password)"},{"line_number":1235,"context_line":""},{"line_number":1236,"context_line":"        update_dict \u003d {\u0027password\u0027: new_password}"},{"line_number":1237,"context_line":"        self.update_user(user_id, update_dict, self_service\u003dTrue)"},{"line_number":1238,"context_line":""},{"line_number":1239,"context_line":"    @MEMOIZE"},{"line_number":1240,"context_line":"    def _shadow_nonlocal_user(self, user):"}],"source_content_type":"text/x-python","patch_set":15,"id":"dada55a8_85c80c76","line":1237,"updated":"2016-07-25 10:08:46.000000000","message":"Why self_service is always True here? Is it mean, that change_password method is called only by owner?","commit_id":"80a3da136b88159f3ca41ea74809fb262c76d779"},{"author":{"_account_id":13063,"name":"WEI CHEN","email":"dave.jungler@gmail.com","username":"wei.d.chen"},"change_message_id":"fdadfc373ca022f92a7a3e505920052b737dc293","unresolved":false,"context_lines":[{"line_number":1234,"context_line":"        validators.validate_password(new_password)"},{"line_number":1235,"context_line":""},{"line_number":1236,"context_line":"        update_dict \u003d {\u0027password\u0027: new_password}"},{"line_number":1237,"context_line":"        self.update_user(user_id, update_dict, self_service\u003dTrue)"},{"line_number":1238,"context_line":""},{"line_number":1239,"context_line":"    @MEMOIZE"},{"line_number":1240,"context_line":"    def _shadow_nonlocal_user(self, user):"}],"source_content_type":"text/x-python","patch_set":15,"id":"dada55a8_5c288133","line":1237,"in_reply_to":"dada55a8_5c1edd63","updated":"2016-07-26 02:59:57.000000000","message":"It\u0027s could be admin or owner, check the policy here.\n\"identity:change_password\": \"rule:admin_or_owner\", but I agree the owner is more appropriate than admin here.","commit_id":"80a3da136b88159f3ca41ea74809fb262c76d779"},{"author":{"_account_id":18338,"name":"Ron De Rose","email":"ronald.de.rose@intel.com","username":"derosenet"},"change_message_id":"ca0d669a9e1c76849f19ad33744472d1c4eff988","unresolved":false,"context_lines":[{"line_number":1234,"context_line":"        validators.validate_password(new_password)"},{"line_number":1235,"context_line":""},{"line_number":1236,"context_line":"        update_dict \u003d {\u0027password\u0027: new_password}"},{"line_number":1237,"context_line":"        self.update_user(user_id, update_dict, self_service\u003dTrue)"},{"line_number":1238,"context_line":""},{"line_number":1239,"context_line":"    @MEMOIZE"},{"line_number":1240,"context_line":"    def _shadow_nonlocal_user(self, user):"}],"source_content_type":"text/x-python","patch_set":15,"id":"dada55a8_d7d263d0","line":1237,"in_reply_to":"dada55a8_5c288133","updated":"2016-07-26 16:58:09.000000000","message":"True, but admins shouldn\u0027t know a user\u0027s original password; thus, this is intended for self service password changes. Admins would perform an administrative password reset if needed.","commit_id":"80a3da136b88159f3ca41ea74809fb262c76d779"},{"author":{"_account_id":18338,"name":"Ron De Rose","email":"ronald.de.rose@intel.com","username":"derosenet"},"change_message_id":"dd5b3d8d1dbab1c9341a9dd91967523cccd28a2f","unresolved":false,"context_lines":[{"line_number":1234,"context_line":"        validators.validate_password(new_password)"},{"line_number":1235,"context_line":""},{"line_number":1236,"context_line":"        update_dict \u003d {\u0027password\u0027: new_password}"},{"line_number":1237,"context_line":"        self.update_user(user_id, update_dict, self_service\u003dTrue)"},{"line_number":1238,"context_line":""},{"line_number":1239,"context_line":"    @MEMOIZE"},{"line_number":1240,"context_line":"    def _shadow_nonlocal_user(self, user):"}],"source_content_type":"text/x-python","patch_set":15,"id":"dada55a8_5c1edd63","line":1237,"in_reply_to":"dada55a8_85c80c76","updated":"2016-07-25 15:29:23.000000000","message":"Yes, that it is my understanding.","commit_id":"80a3da136b88159f3ca41ea74809fb262c76d779"},{"author":{"_account_id":17862,"name":"Kseniya Tychkova","email":"kseniya.tychkova@gmail.com","username":"ktychkova"},"change_message_id":"7d0de4d07e4ee063d8fb05b49e3ab56034e6e68a","unresolved":false,"context_lines":[{"line_number":1239,"context_line":"        validators.validate_password(new_password)"},{"line_number":1240,"context_line":""},{"line_number":1241,"context_line":"        update_dict \u003d {\u0027password\u0027: new_password}"},{"line_number":1242,"context_line":"        self.update_user(user_id, update_dict, self_service\u003dTrue)"},{"line_number":1243,"context_line":""},{"line_number":1244,"context_line":"    @MEMOIZE"},{"line_number":1245,"context_line":"    def _shadow_nonlocal_user(self, user):"}],"source_content_type":"text/x-python","patch_set":17,"id":"dada55a8_318e8b79","line":1242,"updated":"2016-07-26 08:46:23.000000000","message":"Policy file controls who can \u0027change password\u0027 for users.\nAnd it is not just \u0027admin or owner\u0027. You can set any rule you want.\nThis is not going to work.\nYou have to find way to get rid of \"self_service\" flag and compare current user id and id of user in request.","commit_id":"397007683aa0390a766772d8aa59ff4a7c15fa4a"},{"author":{"_account_id":13063,"name":"WEI CHEN","email":"dave.jungler@gmail.com","username":"wei.d.chen"},"change_message_id":"7332c3cb865b3b95d91d058148495c2773bf3a35","unresolved":false,"context_lines":[{"line_number":1239,"context_line":"        validators.validate_password(new_password)"},{"line_number":1240,"context_line":""},{"line_number":1241,"context_line":"        update_dict \u003d {\u0027password\u0027: new_password}"},{"line_number":1242,"context_line":"        self.update_user(user_id, update_dict, self_service\u003dTrue)"},{"line_number":1243,"context_line":""},{"line_number":1244,"context_line":"    @MEMOIZE"},{"line_number":1245,"context_line":"    def _shadow_nonlocal_user(self, user):"}],"source_content_type":"text/x-python","patch_set":17,"id":"dada55a8_47fa5c44","line":1242,"in_reply_to":"dada55a8_318e8b79","updated":"2016-07-26 09:52:23.000000000","message":"++","commit_id":"397007683aa0390a766772d8aa59ff4a7c15fa4a"},{"author":{"_account_id":18338,"name":"Ron De Rose","email":"ronald.de.rose@intel.com","username":"derosenet"},"change_message_id":"e327d1ffbada068c54f0e1097c6a91a9184e86c8","unresolved":false,"context_lines":[{"line_number":1239,"context_line":"        validators.validate_password(new_password)"},{"line_number":1240,"context_line":""},{"line_number":1241,"context_line":"        update_dict \u003d {\u0027password\u0027: new_password}"},{"line_number":1242,"context_line":"        self.update_user(user_id, update_dict, self_service\u003dTrue)"},{"line_number":1243,"context_line":""},{"line_number":1244,"context_line":"    @MEMOIZE"},{"line_number":1245,"context_line":"    def _shadow_nonlocal_user(self, user):"}],"source_content_type":"text/x-python","patch_set":17,"id":"dada55a8_38701972","line":1242,"in_reply_to":"dada55a8_318e8b79","updated":"2016-07-26 14:09:20.000000000","message":"The intent of change password is for it to be self service, the API requires the original password, which an admin should not know. You can also see this in the unit test name UserSelfServiceChangingPasswordsTestCase:\nhttps://github.com/openstack/keystone/blob/master/keystone/tests/unit/test_v3_identity.py#L720\n\nSo I think we can rely on change password being self service and this should work.","commit_id":"397007683aa0390a766772d8aa59ff4a7c15fa4a"},{"author":{"_account_id":5046,"name":"Lance Bragstad","email":"lbragstad@redhat.com","username":"ldbragst"},"change_message_id":"7a3b113efdbcb3507e00ca537b9dbed12b6ac9d9","unresolved":false,"context_lines":[{"line_number":1241,"context_line":"            self._get_domain_driver_and_entity_id(user_id))"},{"line_number":1242,"context_line":"        driver.change_password(user_id, new_password)"},{"line_number":1243,"context_line":"        notifications.Audit.updated(self._USER, user_id)"},{"line_number":1244,"context_line":"        self.emit_invalidate_user_token_persistence(user_id)"},{"line_number":1245,"context_line":""},{"line_number":1246,"context_line":"    @MEMOIZE"},{"line_number":1247,"context_line":"    def _shadow_nonlocal_user(self, user):"}],"source_content_type":"text/x-python","patch_set":36,"id":"bacf61ea_6fa0e5f4","line":1244,"updated":"2016-08-05 15:14:48.000000000","message":"This bit seems new - was this not done before?\n\nhttps://github.com/openstack/keystone/blob/910e6e0a124676f49092b114c00fe8ee8456e3b1/keystone/token/provider.py#L161","commit_id":"d0183aae5192e82843c75dbb532572681dad8001"},{"author":{"_account_id":18338,"name":"Ron De Rose","email":"ronald.de.rose@intel.com","username":"derosenet"},"change_message_id":"0f2a4a2cd403324439a5ebc4240aa3bd03c3019e","unresolved":false,"context_lines":[{"line_number":1241,"context_line":"            self._get_domain_driver_and_entity_id(user_id))"},{"line_number":1242,"context_line":"        driver.change_password(user_id, new_password)"},{"line_number":1243,"context_line":"        notifications.Audit.updated(self._USER, user_id)"},{"line_number":1244,"context_line":"        self.emit_invalidate_user_token_persistence(user_id)"},{"line_number":1245,"context_line":""},{"line_number":1246,"context_line":"    @MEMOIZE"},{"line_number":1247,"context_line":"    def _shadow_nonlocal_user(self, user):"}],"source_content_type":"text/x-python","patch_set":36,"id":"bacf61ea_35d59ae4","line":1244,"in_reply_to":"bacf61ea_6fa0e5f4","updated":"2016-08-05 15:53:17.000000000","message":"This was done before as part of update_user for changing passwords:\nhttps://github.com/openstack/keystone/blob/master/keystone/identity/core.py#L979","commit_id":"d0183aae5192e82843c75dbb532572681dad8001"},{"author":{"_account_id":13478,"name":"Boris Bobrov","email":"b.bobrov@sap.com","username":"bbobrov"},"change_message_id":"4951b1d29afc7310dd0612e7cce5673e15fd3caa","unresolved":false,"context_lines":[{"line_number":1239,"context_line":""},{"line_number":1240,"context_line":"        domain_id, driver, entity_id \u003d ("},{"line_number":1241,"context_line":"            self._get_domain_driver_and_entity_id(user_id))"},{"line_number":1242,"context_line":"        driver.change_password(user_id, new_password)"},{"line_number":1243,"context_line":"        notifications.Audit.updated(self._USER, user_id)"},{"line_number":1244,"context_line":"        self.emit_invalidate_user_token_persistence(user_id)"},{"line_number":1245,"context_line":""}],"source_content_type":"text/x-python","patch_set":49,"id":"3ac371cc_983b2c38","line":1242,"range":{"start_line":1242,"start_character":31,"end_line":1242,"end_character":38},"updated":"2016-08-16 21:44:24.000000000","message":"this should be entity_id. user_id is a public id and might not be understood by the driver.","commit_id":"124c6853e53ba47b81f7fea0b5640b0cadbf608c"},{"author":{"_account_id":18338,"name":"Ron De Rose","email":"ronald.de.rose@intel.com","username":"derosenet"},"change_message_id":"8223dc43586fbfcbc1024401a27b2bc0517b44af","unresolved":false,"context_lines":[{"line_number":1239,"context_line":""},{"line_number":1240,"context_line":"        domain_id, driver, entity_id \u003d ("},{"line_number":1241,"context_line":"            self._get_domain_driver_and_entity_id(user_id))"},{"line_number":1242,"context_line":"        driver.change_password(user_id, new_password)"},{"line_number":1243,"context_line":"        notifications.Audit.updated(self._USER, user_id)"},{"line_number":1244,"context_line":"        self.emit_invalidate_user_token_persistence(user_id)"},{"line_number":1245,"context_line":""}],"source_content_type":"text/x-python","patch_set":49,"id":"3ac371cc_f33521da","line":1242,"range":{"start_line":1242,"start_character":31,"end_line":1242,"end_character":38},"in_reply_to":"3ac371cc_983b2c38","updated":"2016-08-16 21:48:38.000000000","message":"Good catch Boris, thanks :)","commit_id":"124c6853e53ba47b81f7fea0b5640b0cadbf608c"}],"keystone/tests/unit/identity/backends/test_base.py":[{"author":{"_account_id":13063,"name":"WEI CHEN","email":"dave.jungler@gmail.com","username":"wei.d.chen"},"change_message_id":"82695eb5e96fd38542ce1e72170d438ba892afff","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":15,"id":"dada55a8_e85c3d7f","updated":"2016-07-25 09:44:38.000000000","message":"If default value of self_service set to False in driver level, there is no need to update all of these testcases.","commit_id":"80a3da136b88159f3ca41ea74809fb262c76d779"},{"author":{"_account_id":13063,"name":"WEI CHEN","email":"dave.jungler@gmail.com","username":"wei.d.chen"},"change_message_id":"035d63314bb7cc3a62728fbc987e2687dad42b99","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":15,"id":"dada55a8_f19b21c7","in_reply_to":"dada55a8_5bb06743","updated":"2016-07-27 03:26:40.000000000","message":"I cannot catch it, I think all you need is change the default value to `False` in backend driver, it works for me.\n\nAnd even if ABC signature changed, cannot we give the default value for the parameter in ABC method?\n\ndiff --git a/keystone/identity/backends/sql.py b/keystone/identity/backends/sql.py\nindex 4abc649..2af1816 100644\n--- a/keystone/identity/backends/sql.py\n+++ b/keystone/identity/backends/sql.py\n@@ -108,7 +108,7 @@ class Identity(base.IdentityDriverV8):\n             return base.filter_user(user_ref.to_dict())\n\n     @sql.handle_conflicts(conflict_type\u003d\u0027user\u0027)\n-    def update_user(self, user_id, user, self_service):\n+    def update_user(self, user_id, user, self_service\u003dFalse):","commit_id":"80a3da136b88159f3ca41ea74809fb262c76d779"},{"author":{"_account_id":18338,"name":"Ron De Rose","email":"ronald.de.rose@intel.com","username":"derosenet"},"change_message_id":"ffb73a77492168b97b27e7280b89fecb114e0a3b","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":15,"id":"dada55a8_5bb06743","in_reply_to":"dada55a8_e85c3d7f","updated":"2016-07-26 14:22:55.000000000","message":"Actually, because the abstract base class method signature change, I do need to provide the self_service attribute.","commit_id":"80a3da136b88159f3ca41ea74809fb262c76d779"},{"author":{"_account_id":18338,"name":"Ron De Rose","email":"ronald.de.rose@intel.com","username":"derosenet"},"change_message_id":"1176a5c42b2766f1f0f6fc74e6376585d03b0272","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":15,"id":"dada55a8_ca7cad22","in_reply_to":"dada55a8_e85c3d7f","updated":"2016-07-25 20:52:22.000000000","message":"Ah, good point.","commit_id":"80a3da136b88159f3ca41ea74809fb262c76d779"},{"author":{"_account_id":13063,"name":"WEI CHEN","email":"dave.jungler@gmail.com","username":"wei.d.chen"},"change_message_id":"de6f5ce5c8768da927d4ebfb707e5531d9f3a5e2","unresolved":false,"context_lines":[{"line_number":236,"context_line":"        self.assertRaises(exception.Conflict, self.driver.update_user,"},{"line_number":237,"context_line":"                          user[\u0027id\u0027], user_mod)"},{"line_number":238,"context_line":""},{"line_number":239,"context_line":"    def test_update_user_password(self):"},{"line_number":240,"context_line":"        if not self.allows_name_update:"},{"line_number":241,"context_line":"            self.skipTest(\"Backend doesn\u0027t allow name update.\")"},{"line_number":242,"context_line":"        # create user"}],"source_content_type":"text/x-python","patch_set":16,"id":"dada55a8_9cae792c","line":239,"range":{"start_line":239,"start_character":4,"end_line":239,"end_character":40},"updated":"2016-07-26 02:58:25.000000000","message":"Ah, this is not what I meant, sorry for my bad description. What I meant for what you did in patchset15 is as an end-user who might be a admin or owner.\n\n1. call rest API update user, self-service is default to False, so that there is no check for this feature at all.\n2. call rest API update user\u0027s password, self-service is default ot True, the feature to minimum password age is enabled by default.\n\nI think there should be testcases to show this difference since all your testcases in patchset15 is about password updating.","commit_id":"c5c2771132eaa89da2027404e2605d8ef64e3ae8"},{"author":{"_account_id":18338,"name":"Ron De Rose","email":"ronald.de.rose@intel.com","username":"derosenet"},"change_message_id":"22df14ff32f4cf01b07c5689ac076fbc95005ea1","unresolved":false,"context_lines":[{"line_number":236,"context_line":"        self.assertRaises(exception.Conflict, self.driver.update_user,"},{"line_number":237,"context_line":"                          user[\u0027id\u0027], user_mod)"},{"line_number":238,"context_line":""},{"line_number":239,"context_line":"    def test_update_user_password(self):"},{"line_number":240,"context_line":"        if not self.allows_name_update:"},{"line_number":241,"context_line":"            self.skipTest(\"Backend doesn\u0027t allow name update.\")"},{"line_number":242,"context_line":"        # create user"}],"source_content_type":"text/x-python","patch_set":16,"id":"dada55a8_f20a151f","line":239,"range":{"start_line":239,"start_character":4,"end_line":239,"end_character":40},"in_reply_to":"dada55a8_9cae792c","updated":"2016-07-26 17:03:02.000000000","message":"Just so we are clear, there isn\u0027t a self_service param in the API call. Only the driver interface has changed; not the API. That being said, I\u0027ve added a couple of new tests to the API (test_v3_identity):\n* test_admin_password_reset_with_min_password_age_enabled\n* test_changing_password_with_min_password_age\n\nself_service would be False for admin password reset and True for self service password changes.","commit_id":"c5c2771132eaa89da2027404e2605d8ef64e3ae8"},{"author":{"_account_id":7725,"name":"David Stanek","email":"dstanek@dstanek.com","username":"dstanek"},"change_message_id":"527526a9239d0ba181ead60be8c4f0135b92f3fe","unresolved":false,"context_lines":[{"line_number":239,"context_line":""},{"line_number":240,"context_line":"    def test_change_password(self):"},{"line_number":241,"context_line":"        if not self.allows_name_update:"},{"line_number":242,"context_line":"            self.skipTest(\"Backend doesn\u0027t allow name update.\")"},{"line_number":243,"context_line":"        # create user"},{"line_number":244,"context_line":"        password \u003d uuid.uuid4().hex"},{"line_number":245,"context_line":"        domain_id \u003d uuid.uuid4().hex"}],"source_content_type":"text/x-python","patch_set":46,"id":"5ac665da_65ad6688","line":242,"updated":"2016-08-13 16:39:38.000000000","message":"I\u0027m assuming that it\u0027s to block the R/O driver tests from running this, but it would be nice to fix/comment either way.","commit_id":"bec68c841e9cd43ce7eb2b1e962b15f3fa7e4aee"},{"author":{"_account_id":4,"name":"Dolph Mathews","email":"dolph.mathews@gmail.com","username":"dolph"},"change_message_id":"d5d7991f3349a105b7d5dca59b588067d3ed546d","unresolved":false,"context_lines":[{"line_number":239,"context_line":""},{"line_number":240,"context_line":"    def test_change_password(self):"},{"line_number":241,"context_line":"        if not self.allows_name_update:"},{"line_number":242,"context_line":"            self.skipTest(\"Backend doesn\u0027t allow name update.\")"},{"line_number":243,"context_line":"        # create user"},{"line_number":244,"context_line":"        password \u003d uuid.uuid4().hex"},{"line_number":245,"context_line":"        domain_id \u003d uuid.uuid4().hex"}],"source_content_type":"text/x-python","patch_set":46,"id":"7ac969e8_66772e03","line":242,"updated":"2016-08-12 21:19:48.000000000","message":"Why is this appropriate for a password change method? Copy pasta?","commit_id":"bec68c841e9cd43ce7eb2b1e962b15f3fa7e4aee"},{"author":{"_account_id":18338,"name":"Ron De Rose","email":"ronald.de.rose@intel.com","username":"derosenet"},"change_message_id":"a69b24889118af9c0fdd21f81f7ddd2399a4cc9a","unresolved":false,"context_lines":[{"line_number":239,"context_line":""},{"line_number":240,"context_line":"    def test_change_password(self):"},{"line_number":241,"context_line":"        if not self.allows_name_update:"},{"line_number":242,"context_line":"            self.skipTest(\"Backend doesn\u0027t allow name update.\")"},{"line_number":243,"context_line":"        # create user"},{"line_number":244,"context_line":"        password \u003d uuid.uuid4().hex"},{"line_number":245,"context_line":"        domain_id \u003d uuid.uuid4().hex"}],"source_content_type":"text/x-python","patch_set":46,"id":"3ac371cc_bda46557","line":242,"in_reply_to":"5ac665da_65ad6688","updated":"2016-08-15 16:41:32.000000000","message":"Misunderstood this, I thought it was to check if the driver was read-only and would therefore, skip the test.","commit_id":"bec68c841e9cd43ce7eb2b1e962b15f3fa7e4aee"}],"keystone/tests/unit/identity/test_backend_sql.py":[{"author":{"_account_id":13063,"name":"WEI CHEN","email":"dave.jungler@gmail.com","username":"wei.d.chen"},"change_message_id":"82695eb5e96fd38542ce1e72170d438ba892afff","unresolved":false,"context_lines":[{"line_number":220,"context_line":"                      self.log_info.output)"},{"line_number":221,"context_line":""},{"line_number":222,"context_line":"    def _create_new_user(self, password):"},{"line_number":223,"context_line":"        user \u003d {"},{"line_number":224,"context_line":"            \u0027name\u0027: uuid.uuid4().hex,"},{"line_number":225,"context_line":"            \u0027domain_id\u0027: CONF.identity.default_domain_id,"},{"line_number":226,"context_line":"            \u0027enabled\u0027: True,"},{"line_number":227,"context_line":"            \u0027password\u0027: password"},{"line_number":228,"context_line":"        }"},{"line_number":229,"context_line":"        return self.identity_api.create_user(user)"},{"line_number":230,"context_line":""},{"line_number":231,"context_line":"    def _update_user(self, user_id, password_create_at):"}],"source_content_type":"text/x-python","patch_set":15,"id":"dada55a8_e27e1e69","line":228,"range":{"start_line":223,"start_character":0,"end_line":228,"end_character":9},"updated":"2016-07-25 09:44:38.000000000","message":"use unit.new_user_ref(...) instead, fine with as it is.","commit_id":"80a3da136b88159f3ca41ea74809fb262c76d779"},{"author":{"_account_id":18338,"name":"Ron De Rose","email":"ronald.de.rose@intel.com","username":"derosenet"},"change_message_id":"1176a5c42b2766f1f0f6fc74e6376585d03b0272","unresolved":false,"context_lines":[{"line_number":220,"context_line":"                      self.log_info.output)"},{"line_number":221,"context_line":""},{"line_number":222,"context_line":"    def _create_new_user(self, password):"},{"line_number":223,"context_line":"        user \u003d {"},{"line_number":224,"context_line":"            \u0027name\u0027: uuid.uuid4().hex,"},{"line_number":225,"context_line":"            \u0027domain_id\u0027: CONF.identity.default_domain_id,"},{"line_number":226,"context_line":"            \u0027enabled\u0027: True,"},{"line_number":227,"context_line":"            \u0027password\u0027: password"},{"line_number":228,"context_line":"        }"},{"line_number":229,"context_line":"        return self.identity_api.create_user(user)"},{"line_number":230,"context_line":""},{"line_number":231,"context_line":"    def _update_user(self, user_id, password_create_at):"}],"source_content_type":"text/x-python","patch_set":15,"id":"dada55a8_eaed31b8","line":228,"range":{"start_line":223,"start_character":0,"end_line":228,"end_character":9},"in_reply_to":"dada55a8_e27e1e69","updated":"2016-07-25 20:52:22.000000000","message":"new_user_ref has attributes that I don\u0027t want, such as email and id, but see your point.","commit_id":"80a3da136b88159f3ca41ea74809fb262c76d779"},{"author":{"_account_id":5046,"name":"Lance Bragstad","email":"lbragstad@redhat.com","username":"ldbragst"},"change_message_id":"7a3b113efdbcb3507e00ca537b9dbed12b6ac9d9","unresolved":false,"context_lines":[{"line_number":411,"context_line":""},{"line_number":412,"context_line":"    def test_user_can_change_password_after_min_age(self):"},{"line_number":413,"context_line":"        # set password_created_at so that the min age has past"},{"line_number":414,"context_line":"        password_created_at \u003d ("},{"line_number":415,"context_line":"            datetime.datetime.utcnow() -"},{"line_number":416,"context_line":"            datetime.timedelta("},{"line_number":417,"context_line":"                days\u003dCONF.security_compliance.minimum_password_age + 1))"}],"source_content_type":"text/x-python","patch_set":36,"id":"bacf61ea_cfdbd14d","line":414,"updated":"2016-08-05 15:14:48.000000000","message":"Do we still want to go the freezegun route?","commit_id":"d0183aae5192e82843c75dbb532572681dad8001"},{"author":{"_account_id":18338,"name":"Ron De Rose","email":"ronald.de.rose@intel.com","username":"derosenet"},"change_message_id":"0f2a4a2cd403324439a5ebc4240aa3bd03c3019e","unresolved":false,"context_lines":[{"line_number":411,"context_line":""},{"line_number":412,"context_line":"    def test_user_can_change_password_after_min_age(self):"},{"line_number":413,"context_line":"        # set password_created_at so that the min age has past"},{"line_number":414,"context_line":"        password_created_at \u003d ("},{"line_number":415,"context_line":"            datetime.datetime.utcnow() -"},{"line_number":416,"context_line":"            datetime.timedelta("},{"line_number":417,"context_line":"                days\u003dCONF.security_compliance.minimum_password_age + 1))"}],"source_content_type":"text/x-python","patch_set":36,"id":"bacf61ea_f5adc231","line":414,"in_reply_to":"bacf61ea_cfdbd14d","updated":"2016-08-05 15:53:17.000000000","message":"Thus far, I\u0027ve only been successful using freezegun when moving time ahead in seconds. Strange things happen when I try to move time ahead in days. And while freezegun would be more elegant here, I do believe this is providing good test coverage.","commit_id":"d0183aae5192e82843c75dbb532572681dad8001"},{"author":{"_account_id":5046,"name":"Lance Bragstad","email":"lbragstad@redhat.com","username":"ldbragst"},"change_message_id":"56d029757a679b29167c5a72d1e81ed1f5cca5da","unresolved":false,"context_lines":[{"line_number":411,"context_line":""},{"line_number":412,"context_line":"    def test_user_can_change_password_after_min_age(self):"},{"line_number":413,"context_line":"        # set password_created_at so that the min age has past"},{"line_number":414,"context_line":"        password_created_at \u003d ("},{"line_number":415,"context_line":"            datetime.datetime.utcnow() -"},{"line_number":416,"context_line":"            datetime.timedelta("},{"line_number":417,"context_line":"                days\u003dCONF.security_compliance.minimum_password_age + 1))"}],"source_content_type":"text/x-python","patch_set":36,"id":"9ad45d7e_f878c691","line":414,"in_reply_to":"bacf61ea_f5adc231","updated":"2016-08-08 16:19:42.000000000","message":"++ yeah - we can come back to do that later.","commit_id":"d0183aae5192e82843c75dbb532572681dad8001"},{"author":{"_account_id":4,"name":"Dolph Mathews","email":"dolph.mathews@gmail.com","username":"dolph"},"change_message_id":"d5d7991f3349a105b7d5dca59b588067d3ed546d","unresolved":false,"context_lines":[{"line_number":482,"context_line":"        self.assertValidChangePassword(self.user[\u0027id\u0027], self.initial_password,"},{"line_number":483,"context_line":"                                       new_password)"},{"line_number":484,"context_line":"        # user cannot change password before min age"},{"line_number":485,"context_line":"        self.assertRaises(exception.PasswordValidationError,"},{"line_number":486,"context_line":"                          self.identity_api.change_password,"},{"line_number":487,"context_line":"                          self.make_request(),"},{"line_number":488,"context_line":"                          user_id\u003dself.user[\u0027id\u0027],"}],"source_content_type":"text/x-python","patch_set":46,"id":"7ac969e8_86cb4a1e","line":485,"updated":"2016-08-12 21:19:48.000000000","message":"A more specific exception type would be nice for this test - because you could expect this generic exception on this method call for any number of reasons.","commit_id":"bec68c841e9cd43ce7eb2b1e962b15f3fa7e4aee"},{"author":{"_account_id":18338,"name":"Ron De Rose","email":"ronald.de.rose@intel.com","username":"derosenet"},"change_message_id":"a69b24889118af9c0fdd21f81f7ddd2399a4cc9a","unresolved":false,"context_lines":[{"line_number":482,"context_line":"        self.assertValidChangePassword(self.user[\u0027id\u0027], self.initial_password,"},{"line_number":483,"context_line":"                                       new_password)"},{"line_number":484,"context_line":"        # user cannot change password before min age"},{"line_number":485,"context_line":"        self.assertRaises(exception.PasswordValidationError,"},{"line_number":486,"context_line":"                          self.identity_api.change_password,"},{"line_number":487,"context_line":"                          self.make_request(),"},{"line_number":488,"context_line":"                          user_id\u003dself.user[\u0027id\u0027],"}],"source_content_type":"text/x-python","patch_set":46,"id":"3ac371cc_606364dd","line":485,"in_reply_to":"7ac969e8_86cb4a1e","updated":"2016-08-15 16:41:32.000000000","message":"Good point ++","commit_id":"bec68c841e9cd43ce7eb2b1e962b15f3fa7e4aee"},{"author":{"_account_id":4,"name":"Dolph Mathews","email":"dolph.mathews@gmail.com","username":"dolph"},"change_message_id":"d5d7991f3349a105b7d5dca59b588067d3ed546d","unresolved":false,"context_lines":[{"line_number":499,"context_line":"            datetime.datetime.utcnow() -"},{"line_number":500,"context_line":"            datetime.timedelta("},{"line_number":501,"context_line":"                days\u003dCONF.security_compliance.minimum_password_age + 1))"},{"line_number":502,"context_line":"        self._update_user(self.user[\u0027id\u0027], password_created_at)"},{"line_number":503,"context_line":"        # user can change their password after min password age has past"},{"line_number":504,"context_line":"        self.assertValidChangePassword(self.user[\u0027id\u0027], new_password,"},{"line_number":505,"context_line":"                                       uuid.uuid4().hex)"}],"source_content_type":"text/x-python","patch_set":46,"id":"7ac969e8_06ad9a31","line":502,"updated":"2016-08-12 21:19:48.000000000","message":"This is a strange method call. I wouldn\u0027t expect \"password_created_at\" to be the first argument after a user ID for a method called _update_user. Manipulating time with timeutils and/or freezegun would illustrate this behavior a lot more clearly -- assuming this isn\u0027t dependent on the time according to sqlite.","commit_id":"bec68c841e9cd43ce7eb2b1e962b15f3fa7e4aee"},{"author":{"_account_id":18338,"name":"Ron De Rose","email":"ronald.de.rose@intel.com","username":"derosenet"},"change_message_id":"a69b24889118af9c0fdd21f81f7ddd2399a4cc9a","unresolved":false,"context_lines":[{"line_number":499,"context_line":"            datetime.datetime.utcnow() -"},{"line_number":500,"context_line":"            datetime.timedelta("},{"line_number":501,"context_line":"                days\u003dCONF.security_compliance.minimum_password_age + 1))"},{"line_number":502,"context_line":"        self._update_user(self.user[\u0027id\u0027], password_created_at)"},{"line_number":503,"context_line":"        # user can change their password after min password age has past"},{"line_number":504,"context_line":"        self.assertValidChangePassword(self.user[\u0027id\u0027], new_password,"},{"line_number":505,"context_line":"                                       uuid.uuid4().hex)"}],"source_content_type":"text/x-python","patch_set":46,"id":"3ac371cc_80794096","line":502,"in_reply_to":"7ac969e8_06ad9a31","updated":"2016-08-15 16:41:32.000000000","message":"Freezegun works great when moving the time in seconds, however strange things happen when moving time in days. I\u0027ll change to freezegun when I figure the root cause. In the meantime, this should provide adequate test coverage.","commit_id":"bec68c841e9cd43ce7eb2b1e962b15f3fa7e4aee"},{"author":{"_account_id":13478,"name":"Boris Bobrov","email":"b.bobrov@sap.com","username":"bbobrov"},"change_message_id":"4951b1d29afc7310dd0612e7cce5673e15fd3caa","unresolved":false,"context_lines":[{"line_number":147,"context_line":"            session.add(user_ref)"},{"line_number":148,"context_line":"            return base.filter_user(user_ref.to_dict())"},{"line_number":149,"context_line":""},{"line_number":150,"context_line":"    def _update_user_last_active_at(self, user_id, last_active_at):"},{"line_number":151,"context_line":"        with sql.session_for_write() as session:"},{"line_number":152,"context_line":"            user_ref \u003d session.query(model.User).get(user_id)"},{"line_number":153,"context_line":"            user_ref.last_active_at \u003d last_active_at"}],"source_content_type":"text/x-python","patch_set":49,"id":"3ac371cc_d873e413","line":150,"range":{"start_line":150,"start_character":20,"end_line":150,"end_character":35},"updated":"2016-08-16 21:44:24.000000000","message":"this change looks unrelated. I suggest to move it out to another patch.","commit_id":"124c6853e53ba47b81f7fea0b5640b0cadbf608c"},{"author":{"_account_id":4,"name":"Dolph Mathews","email":"dolph.mathews@gmail.com","username":"dolph"},"change_message_id":"6eeb190e53276f7181c9a7438164a51a704c7f80","unresolved":false,"context_lines":[{"line_number":147,"context_line":"            session.add(user_ref)"},{"line_number":148,"context_line":"            return base.filter_user(user_ref.to_dict())"},{"line_number":149,"context_line":""},{"line_number":150,"context_line":"    def _update_user_last_active_at(self, user_id, last_active_at):"},{"line_number":151,"context_line":"        with sql.session_for_write() as session:"},{"line_number":152,"context_line":"            user_ref \u003d session.query(model.User).get(user_id)"},{"line_number":153,"context_line":"            user_ref.last_active_at \u003d last_active_at"}],"source_content_type":"text/x-python","patch_set":49,"id":"3ac371cc_bf44d5b6","line":150,"in_reply_to":"3ac371cc_181c5c76","updated":"2016-08-17 18:37:24.000000000","message":"It is only related in that this patch used to introduce a second _update_user() method -- now called _update_password_created_at() in this patchset -- and the two of them behaved completely differently, despite sharing the exact same name. They\u0027re now both name to reflect what they actually do.\n\nI don\u0027t have a preference on whether it lands together or separately, but it should be be named more accurately.","commit_id":"124c6853e53ba47b81f7fea0b5640b0cadbf608c"},{"author":{"_account_id":18338,"name":"Ron De Rose","email":"ronald.de.rose@intel.com","username":"derosenet"},"change_message_id":"4381ffad7e3a82514750e22248a71baf600cc1ac","unresolved":false,"context_lines":[{"line_number":147,"context_line":"            session.add(user_ref)"},{"line_number":148,"context_line":"            return base.filter_user(user_ref.to_dict())"},{"line_number":149,"context_line":""},{"line_number":150,"context_line":"    def _update_user_last_active_at(self, user_id, last_active_at):"},{"line_number":151,"context_line":"        with sql.session_for_write() as session:"},{"line_number":152,"context_line":"            user_ref \u003d session.query(model.User).get(user_id)"},{"line_number":153,"context_line":"            user_ref.last_active_at \u003d last_active_at"}],"source_content_type":"text/x-python","patch_set":49,"id":"3ac371cc_5fb4c180","line":150,"in_reply_to":"3ac371cc_bf44d5b6","updated":"2016-08-17 18:42:12.000000000","message":"++ I was thinking the parameter names would help describe the method\u0027s behavior, but agree with the change and would prefer that it go with this patch.","commit_id":"124c6853e53ba47b81f7fea0b5640b0cadbf608c"},{"author":{"_account_id":18338,"name":"Ron De Rose","email":"ronald.de.rose@intel.com","username":"derosenet"},"change_message_id":"8223dc43586fbfcbc1024401a27b2bc0517b44af","unresolved":false,"context_lines":[{"line_number":147,"context_line":"            session.add(user_ref)"},{"line_number":148,"context_line":"            return base.filter_user(user_ref.to_dict())"},{"line_number":149,"context_line":""},{"line_number":150,"context_line":"    def _update_user_last_active_at(self, user_id, last_active_at):"},{"line_number":151,"context_line":"        with sql.session_for_write() as session:"},{"line_number":152,"context_line":"            user_ref \u003d session.query(model.User).get(user_id)"},{"line_number":153,"context_line":"            user_ref.last_active_at \u003d last_active_at"}],"source_content_type":"text/x-python","patch_set":49,"id":"3ac371cc_181c5c76","line":150,"range":{"start_line":150,"start_character":20,"end_line":150,"end_character":35},"in_reply_to":"3ac371cc_d873e413","updated":"2016-08-16 21:48:38.000000000","message":"It is unrelated, Dolph wanted to make this small change. It should be okay.","commit_id":"124c6853e53ba47b81f7fea0b5640b0cadbf608c"}],"keystone/tests/unit/test_v3_identity.py":[{"author":{"_account_id":13063,"name":"WEI CHEN","email":"dave.jungler@gmail.com","username":"wei.d.chen"},"change_message_id":"d10f0afb2353cadbd366d869e6b117c6fa3ca337","unresolved":false,"context_lines":[{"line_number":445,"context_line":"            password\u003dnew_password)"},{"line_number":446,"context_line":"        self.v3_create_token(new_password_auth)"},{"line_number":447,"context_line":""},{"line_number":448,"context_line":"    def test_admin_password_reset_with_min_password_age_enabled(self):"},{"line_number":449,"context_line":"        # enable minimum_password_age, this should have no effect on admin"},{"line_number":450,"context_line":"        # password reset"},{"line_number":451,"context_line":"        self.config_fixture.config(group\u003d\u0027security_compliance\u0027,"}],"source_content_type":"text/x-python","patch_set":21,"id":"dada55a8_24be14ae","line":448,"range":{"start_line":448,"start_character":13,"end_line":448,"end_character":27},"updated":"2016-07-27 03:28:57.000000000","message":"what does admin_password mean here?","commit_id":"7bb2df9925d13fdd3fb04d508b6509a247a7520d"},{"author":{"_account_id":18338,"name":"Ron De Rose","email":"ronald.de.rose@intel.com","username":"derosenet"},"change_message_id":"0ce71ce88f6990e4944032aa9396f70797446e8b","unresolved":false,"context_lines":[{"line_number":445,"context_line":"            password\u003dnew_password)"},{"line_number":446,"context_line":"        self.v3_create_token(new_password_auth)"},{"line_number":447,"context_line":""},{"line_number":448,"context_line":"    def test_admin_password_reset_with_min_password_age_enabled(self):"},{"line_number":449,"context_line":"        # enable minimum_password_age, this should have no effect on admin"},{"line_number":450,"context_line":"        # password reset"},{"line_number":451,"context_line":"        self.config_fixture.config(group\u003d\u0027security_compliance\u0027,"}],"source_content_type":"text/x-python","patch_set":21,"id":"dada55a8_e4ad1c32","line":448,"range":{"start_line":448,"start_character":13,"end_line":448,"end_character":27},"in_reply_to":"dada55a8_24be14ae","updated":"2016-07-27 03:46:20.000000000","message":"\u0027admin_password_reset\u0027 means an administrative password reset, where an admin user changes a user\u0027s password.  I used the same naming as the previous method in this class.","commit_id":"7bb2df9925d13fdd3fb04d508b6509a247a7520d"},{"author":{"_account_id":13063,"name":"WEI CHEN","email":"dave.jungler@gmail.com","username":"wei.d.chen"},"change_message_id":"d10f0afb2353cadbd366d869e6b117c6fa3ca337","unresolved":false,"context_lines":[{"line_number":446,"context_line":"        self.v3_create_token(new_password_auth)"},{"line_number":447,"context_line":""},{"line_number":448,"context_line":"    def test_admin_password_reset_with_min_password_age_enabled(self):"},{"line_number":449,"context_line":"        # enable minimum_password_age, this should have no effect on admin"},{"line_number":450,"context_line":"        # password reset"},{"line_number":451,"context_line":"        self.config_fixture.config(group\u003d\u0027security_compliance\u0027,"},{"line_number":452,"context_line":"                                   minimum_password_age\u003d1)"},{"line_number":453,"context_line":"        # create user"}],"source_content_type":"text/x-python","patch_set":21,"id":"dada55a8_24d574e4","line":450,"range":{"start_line":449,"start_character":69,"end_line":450,"end_character":24},"updated":"2016-07-27 03:28:57.000000000","message":"Actually, this case will pass with anyone that call update user, why it should be admin password? and where it shows this is admin password?","commit_id":"7bb2df9925d13fdd3fb04d508b6509a247a7520d"},{"author":{"_account_id":18338,"name":"Ron De Rose","email":"ronald.de.rose@intel.com","username":"derosenet"},"change_message_id":"0ce71ce88f6990e4944032aa9396f70797446e8b","unresolved":false,"context_lines":[{"line_number":446,"context_line":"        self.v3_create_token(new_password_auth)"},{"line_number":447,"context_line":""},{"line_number":448,"context_line":"    def test_admin_password_reset_with_min_password_age_enabled(self):"},{"line_number":449,"context_line":"        # enable minimum_password_age, this should have no effect on admin"},{"line_number":450,"context_line":"        # password reset"},{"line_number":451,"context_line":"        self.config_fixture.config(group\u003d\u0027security_compliance\u0027,"},{"line_number":452,"context_line":"                                   minimum_password_age\u003d1)"},{"line_number":453,"context_line":"        # create user"}],"source_content_type":"text/x-python","patch_set":21,"id":"dada55a8_a7a6860c","line":450,"range":{"start_line":449,"start_character":69,"end_line":450,"end_character":24},"in_reply_to":"dada55a8_24d574e4","updated":"2016-07-27 03:46:20.000000000","message":"This tests that the minimum_password_age does not have an impact on administrative password resets. Thus, when an admin changes the password for a user, minimum password age should be ignored.","commit_id":"7bb2df9925d13fdd3fb04d508b6509a247a7520d"},{"author":{"_account_id":7725,"name":"David Stanek","email":"dstanek@dstanek.com","username":"dstanek"},"change_message_id":"29cc7dc38d9cc3d28e2546eea433f5bf2e58ff8d","unresolved":false,"context_lines":[{"line_number":786,"context_line":"        self.get_request_token(new_password,"},{"line_number":787,"context_line":"                               expected_status\u003dhttp_client.CREATED)"},{"line_number":788,"context_line":""},{"line_number":789,"context_line":"    def test_changing_password_with_min_password_age(self):"},{"line_number":790,"context_line":"        new_password \u003d uuid.uuid4().hex"},{"line_number":791,"context_line":"        # enable minimum_password_age and attempt to change password"},{"line_number":792,"context_line":"        self.config_fixture.config(group\u003d\u0027security_compliance\u0027,"}],"source_content_type":"text/x-python","patch_set":21,"id":"bacf61ea_8b301f03","line":789,"updated":"2016-07-28 20:14:06.000000000","message":"I think this is doing admin requests to change the password and that\u0027s why it\u0027s working. I would expect this to fail since I don\u0027t see a controller change that sets the new boolean on update_user.","commit_id":"7bb2df9925d13fdd3fb04d508b6509a247a7520d"},{"author":{"_account_id":18338,"name":"Ron De Rose","email":"ronald.de.rose@intel.com","username":"derosenet"},"change_message_id":"8b1ce3dd1abc5240e7e0283f533d648252c04896","unresolved":false,"context_lines":[{"line_number":786,"context_line":"        self.get_request_token(new_password,"},{"line_number":787,"context_line":"                               expected_status\u003dhttp_client.CREATED)"},{"line_number":788,"context_line":""},{"line_number":789,"context_line":"    def test_changing_password_with_min_password_age(self):"},{"line_number":790,"context_line":"        new_password \u003d uuid.uuid4().hex"},{"line_number":791,"context_line":"        # enable minimum_password_age and attempt to change password"},{"line_number":792,"context_line":"        self.config_fixture.config(group\u003d\u0027security_compliance\u0027,"}],"source_content_type":"text/x-python","patch_set":21,"id":"bacf61ea_b174709c","line":789,"in_reply_to":"bacf61ea_8b301f03","updated":"2016-07-28 20:33:29.000000000","message":"If you make the following change password API call, the change_password(...) method in the identity manager gets called and sets the self_service boolean to true for update_user:\n* /v3/users/{user_id}/password","commit_id":"7bb2df9925d13fdd3fb04d508b6509a247a7520d"},{"author":{"_account_id":5046,"name":"Lance Bragstad","email":"lbragstad@redhat.com","username":"ldbragst"},"change_message_id":"7a3b113efdbcb3507e00ca537b9dbed12b6ac9d9","unresolved":false,"context_lines":[{"line_number":452,"context_line":"                                   minimum_password_age\u003d1)"},{"line_number":453,"context_line":"        # create user"},{"line_number":454,"context_line":"        user_ref \u003d unit.create_user(self.identity_api,"},{"line_number":455,"context_line":"                                    domain_id\u003dself.domain[\u0027id\u0027])"},{"line_number":456,"context_line":"        # administrative password reset"},{"line_number":457,"context_line":"        new_password \u003d uuid.uuid4().hex"},{"line_number":458,"context_line":"        r \u003d self.patch(\u0027/users/%s\u0027 % user_ref[\u0027id\u0027],"}],"source_content_type":"text/x-python","patch_set":36,"id":"bacf61ea_af83fd01","line":455,"updated":"2016-08-05 15:14:48.000000000","message":"We could assert that the user can\u0027t actually change their password before the administrative password reset is made.","commit_id":"d0183aae5192e82843c75dbb532572681dad8001"},{"author":{"_account_id":18338,"name":"Ron De Rose","email":"ronald.de.rose@intel.com","username":"derosenet"},"change_message_id":"0f2a4a2cd403324439a5ebc4240aa3bd03c3019e","unresolved":false,"context_lines":[{"line_number":452,"context_line":"                                   minimum_password_age\u003d1)"},{"line_number":453,"context_line":"        # create user"},{"line_number":454,"context_line":"        user_ref \u003d unit.create_user(self.identity_api,"},{"line_number":455,"context_line":"                                    domain_id\u003dself.domain[\u0027id\u0027])"},{"line_number":456,"context_line":"        # administrative password reset"},{"line_number":457,"context_line":"        new_password \u003d uuid.uuid4().hex"},{"line_number":458,"context_line":"        r \u003d self.patch(\u0027/users/%s\u0027 % user_ref[\u0027id\u0027],"}],"source_content_type":"text/x-python","patch_set":36,"id":"bacf61ea_e76cf9d1","line":455,"in_reply_to":"bacf61ea_af83fd01","updated":"2016-08-05 15:53:17.000000000","message":"Done","commit_id":"d0183aae5192e82843c75dbb532572681dad8001"},{"author":{"_account_id":18338,"name":"Ron De Rose","email":"ronald.de.rose@intel.com","username":"derosenet"},"change_message_id":"44386441387d57852b1d6d293c086a839e93349b","unresolved":false,"context_lines":[{"line_number":452,"context_line":"                                   minimum_password_age\u003d1)"},{"line_number":453,"context_line":"        # create user"},{"line_number":454,"context_line":"        user_ref \u003d unit.create_user(self.identity_api,"},{"line_number":455,"context_line":"                                    domain_id\u003dself.domain[\u0027id\u0027])"},{"line_number":456,"context_line":"        # administrative password reset"},{"line_number":457,"context_line":"        new_password \u003d uuid.uuid4().hex"},{"line_number":458,"context_line":"        r \u003d self.patch(\u0027/users/%s\u0027 % user_ref[\u0027id\u0027],"}],"source_content_type":"text/x-python","patch_set":36,"id":"bacf61ea_ca273c61","line":455,"in_reply_to":"bacf61ea_e76cf9d1","updated":"2016-08-05 16:12:17.000000000","message":"* We could, however this test is specifically testing that admin password resets still work. And testing that a user cannot actually change their password is covered by the test below (test_changing_password_with_min_password_age).","commit_id":"d0183aae5192e82843c75dbb532572681dad8001"}],"releasenotes/notes/identity_driver_new_change_password_method-e8c0e06795bca2d8.yaml":[{"author":{"_account_id":6482,"name":"Steve Martinelli","email":"s.martinelli@gmail.com","username":"stevemar"},"change_message_id":"bed103d86302409ff29cca27bec4d73049e9f0b4","unresolved":false,"context_lines":[{"line_number":1,"context_line":"---"},{"line_number":2,"context_line":"upgrade:"},{"line_number":3,"context_line":"- The identity backend driver interface has changed."},{"line_number":4,"context_line":"  We\u0027ve added a new change_password method for"},{"line_number":5,"context_line":"  self service password changes. If you have a"},{"line_number":6,"context_line":"  custom implementation for the identity driver,"},{"line_number":7,"context_line":"  you will need to add this new method. Otherwise,"},{"line_number":8,"context_line":"  you can ignore this."}],"source_content_type":"text/x-yaml","patch_set":46,"id":"9ad45d7e_1cc3808a","line":8,"range":{"start_line":3,"start_character":0,"end_line":8,"end_character":22},"updated":"2016-08-10 22:49:43.000000000","message":"use all 72 or 80 characters per line","commit_id":"bec68c841e9cd43ce7eb2b1e962b15f3fa7e4aee"},{"author":{"_account_id":6482,"name":"Steve Martinelli","email":"s.martinelli@gmail.com","username":"stevemar"},"change_message_id":"92dd2d37008825fea88aa549ec29951b5230a682","unresolved":false,"context_lines":[{"line_number":5,"context_line":"  self service password changes. If you have a"},{"line_number":6,"context_line":"  custom implementation for the identity driver,"},{"line_number":7,"context_line":"  you will need to add this new method. Otherwise,"},{"line_number":8,"context_line":"  you can ignore this."}],"source_content_type":"text/x-yaml","patch_set":46,"id":"7ac969e8_4974c5fc","line":8,"in_reply_to":"7ac969e8_c97275ad","updated":"2016-08-12 21:36:24.000000000","message":"72 is the initial git commit message, my bad.","commit_id":"bec68c841e9cd43ce7eb2b1e962b15f3fa7e4aee"},{"author":{"_account_id":4,"name":"Dolph Mathews","email":"dolph.mathews@gmail.com","username":"dolph"},"change_message_id":"d5d7991f3349a105b7d5dca59b588067d3ed546d","unresolved":false,"context_lines":[{"line_number":5,"context_line":"  self service password changes. If you have a"},{"line_number":6,"context_line":"  custom implementation for the identity driver,"},{"line_number":7,"context_line":"  you will need to add this new method. Otherwise,"},{"line_number":8,"context_line":"  you can ignore this."}],"source_content_type":"text/x-yaml","patch_set":46,"id":"7ac969e8_c97275ad","line":8,"in_reply_to":"9ad45d7e_1cc3808a","updated":"2016-08-12 21:19:48.000000000","message":"Where does 72 chars come from? Always use 79 plus a line break.","commit_id":"bec68c841e9cd43ce7eb2b1e962b15f3fa7e4aee"}]}
