)]}'
{"/COMMIT_MSG":[{"author":{"_account_id":7725,"name":"David Stanek","email":"dstanek@dstanek.com","username":"dstanek"},"change_message_id":"d5f78f164cf8f35d643b8a6a670ae3c195379bd8","unresolved":false,"context_lines":[{"line_number":12,"context_line":"* PCI-DSS 8.2.4: Change user passwords/passphrases at least once every"},{"line_number":13,"context_line":"90 days."},{"line_number":14,"context_line":""},{"line_number":15,"context_line":"* PCI-DSS 8.2.5: Do not allow an individual to submit a new"},{"line_number":16,"context_line":"password/phrase that is the same as any of the last four"},{"line_number":17,"context_line":"passwords/phrases he or she has used."},{"line_number":18,"context_line":""}],"source_content_type":"text/x-gerrit-commit-message","patch_set":20,"id":"bab6814e_9d92f69d","line":15,"updated":"2016-05-19 19:49:34.000000000","message":"Is this addressed in this patch?","commit_id":"f7a777d42257f0372a7ad27d31d9dcb09deacf96"},{"author":{"_account_id":7725,"name":"David Stanek","email":"dstanek@dstanek.com","username":"dstanek"},"change_message_id":"b969fd55eb4af8e54ecf6db9235bacf40b2c348c","unresolved":false,"context_lines":[{"line_number":12,"context_line":"* PCI-DSS 8.2.4: Change user passwords/passphrases at least once every"},{"line_number":13,"context_line":"90 days."},{"line_number":14,"context_line":""},{"line_number":15,"context_line":"* PCI-DSS 8.2.5: Do not allow an individual to submit a new"},{"line_number":16,"context_line":"password/phrase that is the same as any of the last four"},{"line_number":17,"context_line":"passwords/phrases he or she has used."},{"line_number":18,"context_line":""}],"source_content_type":"text/x-gerrit-commit-message","patch_set":20,"id":"bab6814e_80456d71","line":15,"in_reply_to":"bab6814e_3d2dca46","updated":"2016-05-19 20:18:34.000000000","message":"I didn\u0027t see any columns that would address this requirement.","commit_id":"f7a777d42257f0372a7ad27d31d9dcb09deacf96"},{"author":{"_account_id":18338,"name":"Ron De Rose","email":"ronald.de.rose@intel.com","username":"derosenet"},"change_message_id":"700c7a113afac47f0bf91c0c3f2ce54a7c8e1cb1","unresolved":false,"context_lines":[{"line_number":12,"context_line":"* PCI-DSS 8.2.4: Change user passwords/passphrases at least once every"},{"line_number":13,"context_line":"90 days."},{"line_number":14,"context_line":""},{"line_number":15,"context_line":"* PCI-DSS 8.2.5: Do not allow an individual to submit a new"},{"line_number":16,"context_line":"password/phrase that is the same as any of the last four"},{"line_number":17,"context_line":"passwords/phrases he or she has used."},{"line_number":18,"context_line":""}],"source_content_type":"text/x-gerrit-commit-message","patch_set":20,"id":"bab6814e_437b88f5","line":15,"in_reply_to":"bab6814e_80456d71","updated":"2016-05-19 23:15:13.000000000","message":"Good point.  I removed this from the commit message.","commit_id":"f7a777d42257f0372a7ad27d31d9dcb09deacf96"},{"author":{"_account_id":18338,"name":"Ron De Rose","email":"ronald.de.rose@intel.com","username":"derosenet"},"change_message_id":"574dc991b23bb7ead7229b878633d504a0a53a59","unresolved":false,"context_lines":[{"line_number":12,"context_line":"* PCI-DSS 8.2.4: Change user passwords/passphrases at least once every"},{"line_number":13,"context_line":"90 days."},{"line_number":14,"context_line":""},{"line_number":15,"context_line":"* PCI-DSS 8.2.5: Do not allow an individual to submit a new"},{"line_number":16,"context_line":"password/phrase that is the same as any of the last four"},{"line_number":17,"context_line":"passwords/phrases he or she has used."},{"line_number":18,"context_line":""}],"source_content_type":"text/x-gerrit-commit-message","patch_set":20,"id":"bab6814e_3d2dca46","line":15,"in_reply_to":"bab6814e_9d92f69d","updated":"2016-05-19 19:52:56.000000000","message":"This is just adding the table columns to support this feature","commit_id":"f7a777d42257f0372a7ad27d31d9dcb09deacf96"},{"author":{"_account_id":5046,"name":"Lance Bragstad","email":"lbragstad@redhat.com","username":"ldbragst"},"change_message_id":"9d7b085d754f21ae236958c03b60a65b79d7718f","unresolved":false,"context_lines":[{"line_number":4,"context_line":"Commit:     Ronald De Rose \u003cronald.de.rose@intel.com\u003e"},{"line_number":5,"context_line":"CommitDate: 2016-05-20 00:21:24 +0000"},{"line_number":6,"context_line":""},{"line_number":7,"context_line":"Add password table columns to meet PCI-DSS change password requirements"},{"line_number":8,"context_line":""},{"line_number":9,"context_line":"This patch creates new password table columns in order to support"},{"line_number":10,"context_line":"PCI-DSS change password requirements:"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":29,"id":"bab6814e_c1391ef4","line":7,"updated":"2016-05-20 09:57:06.000000000","message":"afterthought - maybe we can include a link to the specific PCI-DSS requirements for password changes (or just leave it be since it\u0027s pretty well documented in the spec).","commit_id":"db59100adfcaf3c09ccfa068a648c6d2f63b20b6"},{"author":{"_account_id":18338,"name":"Ron De Rose","email":"ronald.de.rose@intel.com","username":"derosenet"},"change_message_id":"f433ecf90165f0760adca4d6762159242b67133f","unresolved":false,"context_lines":[{"line_number":4,"context_line":"Commit:     Ronald De Rose \u003cronald.de.rose@intel.com\u003e"},{"line_number":5,"context_line":"CommitDate: 2016-05-20 00:21:24 +0000"},{"line_number":6,"context_line":""},{"line_number":7,"context_line":"Add password table columns to meet PCI-DSS change password requirements"},{"line_number":8,"context_line":""},{"line_number":9,"context_line":"This patch creates new password table columns in order to support"},{"line_number":10,"context_line":"PCI-DSS change password requirements:"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":29,"id":"bab6814e_b0c6d465","line":7,"in_reply_to":"bab6814e_c1391ef4","updated":"2016-05-20 14:31:50.000000000","message":"I think it\u0027s pretty well documented in the spec.","commit_id":"db59100adfcaf3c09ccfa068a648c6d2f63b20b6"},{"author":{"_account_id":5046,"name":"Lance Bragstad","email":"lbragstad@redhat.com","username":"ldbragst"},"change_message_id":"956ed259c4934f8fb4698bda978186153b947275","unresolved":false,"context_lines":[{"line_number":13,"context_line":"90 days."},{"line_number":14,"context_line":""},{"line_number":15,"context_line":"* PCI-DSS 8.2.5: Do not allow an individual to submit a new"},{"line_number":16,"context_line":"password/phrase that is the same as any of the last four"},{"line_number":17,"context_line":"passwords/phrases he or she has used."},{"line_number":18,"context_line":""},{"line_number":19,"context_line":"Partially-implements: blueprint pci-dss"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":67,"id":"7aa08908_eb4a2d82","line":16,"updated":"2016-06-13 15:54:28.000000000","message":"Is the number of stored passwords configurable? As an admin I want to be able to set the number of previous passwords a user can\u0027t reuse.","commit_id":"98fcf223b42c985dbcc491aef9c17e1a84a4fa02"},{"author":{"_account_id":18338,"name":"Ron De Rose","email":"ronald.de.rose@intel.com","username":"derosenet"},"change_message_id":"f14b58756d1f6c682ac3f2a33313e31490792583","unresolved":false,"context_lines":[{"line_number":13,"context_line":"90 days."},{"line_number":14,"context_line":""},{"line_number":15,"context_line":"* PCI-DSS 8.2.5: Do not allow an individual to submit a new"},{"line_number":16,"context_line":"password/phrase that is the same as any of the last four"},{"line_number":17,"context_line":"passwords/phrases he or she has used."},{"line_number":18,"context_line":""},{"line_number":19,"context_line":"Partially-implements: blueprint pci-dss"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":67,"id":"7aa08908_76c5848c","line":16,"in_reply_to":"7aa08908_eb4a2d82","updated":"2016-06-13 16:05:15.000000000","message":"Yes, you\u0027ll find it here:\nhttps://github.com/openstack/keystone/blob/master/keystone/common/config.py#L1071","commit_id":"98fcf223b42c985dbcc491aef9c17e1a84a4fa02"}],"keystone/common/sql/migrate_repo/versions/102_add_new_password_columns.py":[{"author":{"_account_id":6482,"name":"Steve Martinelli","email":"s.martinelli@gmail.com","username":"stevemar"},"change_message_id":"4b312c4c5a01de66a015088a55bad7bd169d544c","unresolved":false,"context_lines":[{"line_number":20,"context_line":""},{"line_number":21,"context_line":"    password_table \u003d sql.Table(\u0027password\u0027, meta, autoload\u003dTrue)"},{"line_number":22,"context_line":"    created_at_column \u003d sql.Column(\u0027created_at\u0027, sql.DateTime(),"},{"line_number":23,"context_line":"                                   nullable\u003dFalse, default\u003ddatetime.utcnow,"},{"line_number":24,"context_line":"                                   server_default\u003dsql.func.now())"},{"line_number":25,"context_line":"    created_by_column \u003d sql.Column(\u0027created_by\u0027, sql.String(64), nullable\u003dTrue)"},{"line_number":26,"context_line":"    expires_at_column \u003d sql.Column(\u0027expires_at\u0027, sql.DateTime(), nullable\u003dTrue)"}],"source_content_type":"text/x-python","patch_set":15,"id":"dab17558_0343d013","line":23,"range":{"start_line":23,"start_character":59,"end_line":23,"end_character":74},"updated":"2016-05-11 20:24:43.000000000","message":"this should be: \n\n  datetime.datetime.utcnow()","commit_id":"325f45bf1a22153399832213d537c015448bf70d"},{"author":{"_account_id":18338,"name":"Ron De Rose","email":"ronald.de.rose@intel.com","username":"derosenet"},"change_message_id":"2e32d588f5a39cbdd80b69944b045ad45c0ae0f6","unresolved":false,"context_lines":[{"line_number":20,"context_line":""},{"line_number":21,"context_line":"    password_table \u003d sql.Table(\u0027password\u0027, meta, autoload\u003dTrue)"},{"line_number":22,"context_line":"    created_at_column \u003d sql.Column(\u0027created_at\u0027, sql.DateTime(),"},{"line_number":23,"context_line":"                                   nullable\u003dFalse, default\u003ddatetime.utcnow,"},{"line_number":24,"context_line":"                                   server_default\u003dsql.func.now())"},{"line_number":25,"context_line":"    created_by_column \u003d sql.Column(\u0027created_by\u0027, sql.String(64), nullable\u003dTrue)"},{"line_number":26,"context_line":"    expires_at_column \u003d sql.Column(\u0027expires_at\u0027, sql.DateTime(), nullable\u003dTrue)"}],"source_content_type":"text/x-python","patch_set":15,"id":"dab17558_49c85755","line":23,"range":{"start_line":23,"start_character":59,"end_line":23,"end_character":74},"in_reply_to":"dab17558_0343d013","updated":"2016-05-11 21:27:47.000000000","message":"Done","commit_id":"325f45bf1a22153399832213d537c015448bf70d"},{"author":{"_account_id":6482,"name":"Steve Martinelli","email":"s.martinelli@gmail.com","username":"stevemar"},"change_message_id":"679d573f2a6c1430dadf0a5187f66449d2e8801a","unresolved":false,"context_lines":[{"line_number":22,"context_line":"    created_at_column \u003d sql.Column(\u0027created_at\u0027, sql.DateTime(),"},{"line_number":23,"context_line":"                                   nullable\u003dFalse, default\u003ddatetime.utcnow,"},{"line_number":24,"context_line":"                                   server_default\u003dsql.func.now())"},{"line_number":25,"context_line":"    created_by_column \u003d sql.Column(\u0027created_by\u0027, sql.String(64), nullable\u003dTrue)"},{"line_number":26,"context_line":"    expires_at_column \u003d sql.Column(\u0027expires_at\u0027, sql.DateTime(), nullable\u003dTrue)"},{"line_number":27,"context_line":"    password_table.create_column(created_at_column)"},{"line_number":28,"context_line":"    password_table.create_column(created_by_column)"}],"source_content_type":"text/x-python","patch_set":15,"id":"dab17558_c387085f","line":25,"range":{"start_line":25,"start_character":4,"end_line":25,"end_character":48},"updated":"2016-05-11 20:23:51.000000000","message":"silly question, whats \u0027craeted_by\u0027 and how will that be used in the future?","commit_id":"325f45bf1a22153399832213d537c015448bf70d"},{"author":{"_account_id":18338,"name":"Ron De Rose","email":"ronald.de.rose@intel.com","username":"derosenet"},"change_message_id":"2e32d588f5a39cbdd80b69944b045ad45c0ae0f6","unresolved":false,"context_lines":[{"line_number":22,"context_line":"    created_at_column \u003d sql.Column(\u0027created_at\u0027, sql.DateTime(),"},{"line_number":23,"context_line":"                                   nullable\u003dFalse, default\u003ddatetime.utcnow,"},{"line_number":24,"context_line":"                                   server_default\u003dsql.func.now())"},{"line_number":25,"context_line":"    created_by_column \u003d sql.Column(\u0027created_by\u0027, sql.String(64), nullable\u003dTrue)"},{"line_number":26,"context_line":"    expires_at_column \u003d sql.Column(\u0027expires_at\u0027, sql.DateTime(), nullable\u003dTrue)"},{"line_number":27,"context_line":"    password_table.create_column(created_at_column)"},{"line_number":28,"context_line":"    password_table.create_column(created_by_column)"}],"source_content_type":"text/x-python","patch_set":15,"id":"dab17558_29afd37d","line":25,"range":{"start_line":25,"start_character":4,"end_line":25,"end_character":48},"in_reply_to":"dab17558_c387085f","updated":"2016-05-11 21:27:47.000000000","message":"created_by would be the user.id of the person that created the password.  For example, if an admin updates a password for a user, the created_by would be the admin\u0027s user.id.  And then the user would be required to change the password at the next login.","commit_id":"325f45bf1a22153399832213d537c015448bf70d"},{"author":{"_account_id":6482,"name":"Steve Martinelli","email":"s.martinelli@gmail.com","username":"stevemar"},"change_message_id":"52375445705b5f4892fdc17fa2a3a68b2cb036a0","unresolved":false,"context_lines":[{"line_number":21,"context_line":"    password_table \u003d sql.Table(\u0027password\u0027, meta, autoload\u003dTrue)"},{"line_number":22,"context_line":"    created_at_column \u003d sql.Column(\u0027created_at\u0027, sql.DateTime(),"},{"line_number":23,"context_line":"                                   nullable\u003dFalse,"},{"line_number":24,"context_line":"                                   default\u003ddatetime.datetime.utcnow(),"},{"line_number":25,"context_line":"                                   server_default\u003dsql.func.now())"},{"line_number":26,"context_line":"    created_by_column \u003d sql.Column(\u0027created_by\u0027, sql.String(64), nullable\u003dTrue)"},{"line_number":27,"context_line":"    expires_at_column \u003d sql.Column(\u0027expires_at\u0027, sql.DateTime(), nullable\u003dTrue)"}],"source_content_type":"text/x-python","patch_set":16,"id":"dab17558_2ff7ced3","line":24,"range":{"start_line":24,"start_character":43,"end_line":24,"end_character":70},"updated":"2016-05-12 01:47:43.000000000","message":"whoops, still not right, should be:\n\n  default\u003ddatetime.datetime.utcnow\n\nhttp://stackoverflow.com/questions/13370317/sqlalchemy-default-datetime","commit_id":"ecf516a065fe5beca4e1dc3179be1e40d9bf0540"},{"author":{"_account_id":5046,"name":"Lance Bragstad","email":"lbragstad@redhat.com","username":"ldbragst"},"change_message_id":"f4d03d9a8ee1cd3f2730f92ba27b24c639b5a44f","unresolved":false,"context_lines":[{"line_number":22,"context_line":"    created_at_column \u003d sql.Column(\u0027created_at\u0027, sql.DateTime(),"},{"line_number":23,"context_line":"                                   nullable\u003dTrue)"},{"line_number":24,"context_line":"    created_by_column \u003d sql.Column(\u0027created_by\u0027, sql.String(64), nullable\u003dTrue)"},{"line_number":25,"context_line":"    expires_at_column \u003d sql.Column(\u0027expires_at\u0027, sql.DateTime(), nullable\u003dTrue)"},{"line_number":26,"context_line":"    password_table.create_column(created_at_column)"},{"line_number":27,"context_line":"    password_table.create_column(created_by_column)"},{"line_number":28,"context_line":"    password_table.create_column(expires_at_column)"}],"source_content_type":"text/x-python","patch_set":19,"id":"dab17558_f20c9494","line":25,"updated":"2016-05-17 20:06:24.000000000","message":"With this schema, how do we ensure a user doesn\u0027t use the same password over and over again?","commit_id":"5d8e5669381baae4784f879ccea9e37ecf2d54cf"},{"author":{"_account_id":18338,"name":"Ron De Rose","email":"ronald.de.rose@intel.com","username":"derosenet"},"change_message_id":"1afa5c12e535b8d0e95642f717e6bb4904f04878","unresolved":false,"context_lines":[{"line_number":22,"context_line":"    created_at_column \u003d sql.Column(\u0027created_at\u0027, sql.DateTime(),"},{"line_number":23,"context_line":"                                   nullable\u003dTrue)"},{"line_number":24,"context_line":"    created_by_column \u003d sql.Column(\u0027created_by\u0027, sql.String(64), nullable\u003dTrue)"},{"line_number":25,"context_line":"    expires_at_column \u003d sql.Column(\u0027expires_at\u0027, sql.DateTime(), nullable\u003dTrue)"},{"line_number":26,"context_line":"    password_table.create_column(created_at_column)"},{"line_number":27,"context_line":"    password_table.create_column(created_by_column)"},{"line_number":28,"context_line":"    password_table.create_column(expires_at_column)"}],"source_content_type":"text/x-python","patch_set":19,"id":"dab17558_b8030b0c","line":25,"in_reply_to":"dab17558_f20c9494","updated":"2016-05-17 20:31:40.000000000","message":"Whether a user is allowed to use the same password as a previous password is configurable.  When it is set to where a password cannot be the same as n number of previous passwords, we\u0027ll do that validation as part of updating a user\u0027s password.","commit_id":"5d8e5669381baae4784f879ccea9e37ecf2d54cf"}],"keystone/common/sql/migrate_repo/versions/102_add_password_columns_and_user_activity_table.py":[{"author":{"_account_id":17579,"name":"Elvin Tubillara","email":"edtubill@us.ibm.com","username":"edtubill"},"change_message_id":"170014397e77d0601aec67e157d5f5b475c914ae","unresolved":false,"context_lines":[{"line_number":20,"context_line":"    # add new columns to the password table"},{"line_number":21,"context_line":"    password_table \u003d sql.Table(\u0027password\u0027, meta, autoload\u003dTrue)"},{"line_number":22,"context_line":"    created_at_column \u003d sql.Column(\u0027created_at\u0027, sql.DateTime(), nullable\u003dTrue)"},{"line_number":23,"context_line":"    created_by_column \u003d sql.Column(\u0027created_by\u0027, sql.String(64), nullable\u003dTrue)"},{"line_number":24,"context_line":"    expires_at_column \u003d sql.Column(\u0027expires_at\u0027, sql.DateTime(), nullable\u003dTrue)"},{"line_number":25,"context_line":"    password_table.create_column(created_at_column)"},{"line_number":26,"context_line":"    password_table.create_column(created_by_column)"}],"source_content_type":"text/x-python","patch_set":6,"id":"dab17558_311e6c5f","line":23,"updated":"2016-05-10 15:23:03.000000000","message":"Not sure if required but seems good to have.","commit_id":"2d6d93e62c4271859e381e75ba15bd5e53eca26c"},{"author":{"_account_id":17579,"name":"Elvin Tubillara","email":"edtubill@us.ibm.com","username":"edtubill"},"change_message_id":"2671fbc517f2e034919dcbfea169ed13f359a7a4","unresolved":false,"context_lines":[{"line_number":20,"context_line":"    # add new columns to the password table"},{"line_number":21,"context_line":"    password_table \u003d sql.Table(\u0027password\u0027, meta, autoload\u003dTrue)"},{"line_number":22,"context_line":"    created_at_column \u003d sql.Column(\u0027created_at\u0027, sql.DateTime(), nullable\u003dTrue)"},{"line_number":23,"context_line":"    created_by_column \u003d sql.Column(\u0027created_by\u0027, sql.String(64), nullable\u003dTrue)"},{"line_number":24,"context_line":"    expires_at_column \u003d sql.Column(\u0027expires_at\u0027, sql.DateTime(), nullable\u003dTrue)"},{"line_number":25,"context_line":"    password_table.create_column(created_at_column)"},{"line_number":26,"context_line":"    password_table.create_column(created_by_column)"}],"source_content_type":"text/x-python","patch_set":6,"id":"dab17558_718bd4c3","line":23,"in_reply_to":"dab17558_311e6c5f","updated":"2016-05-10 15:34:24.000000000","message":"^created_by_column","commit_id":"2d6d93e62c4271859e381e75ba15bd5e53eca26c"},{"author":{"_account_id":18338,"name":"Ron De Rose","email":"ronald.de.rose@intel.com","username":"derosenet"},"change_message_id":"43df90ccceb4548b8d6c9c63d0439b5c2f47dc42","unresolved":false,"context_lines":[{"line_number":20,"context_line":"    # add new columns to the password table"},{"line_number":21,"context_line":"    password_table \u003d sql.Table(\u0027password\u0027, meta, autoload\u003dTrue)"},{"line_number":22,"context_line":"    created_at_column \u003d sql.Column(\u0027created_at\u0027, sql.DateTime(), nullable\u003dTrue)"},{"line_number":23,"context_line":"    created_by_column \u003d sql.Column(\u0027created_by\u0027, sql.String(64), nullable\u003dTrue)"},{"line_number":24,"context_line":"    expires_at_column \u003d sql.Column(\u0027expires_at\u0027, sql.DateTime(), nullable\u003dTrue)"},{"line_number":25,"context_line":"    password_table.create_column(created_at_column)"},{"line_number":26,"context_line":"    password_table.create_column(created_by_column)"}],"source_content_type":"text/x-python","patch_set":6,"id":"dab17558_92711647","line":23,"in_reply_to":"dab17558_718bd4c3","updated":"2016-05-10 16:13:58.000000000","message":"Yeah, at the Summit we talked about if an admin creates the password for the user, the user should be required to change the password at the next login.","commit_id":"2d6d93e62c4271859e381e75ba15bd5e53eca26c"},{"author":{"_account_id":17579,"name":"Elvin Tubillara","email":"edtubill@us.ibm.com","username":"edtubill"},"change_message_id":"d321607469b2b26cfd846c590c1ba55c7cf94096","unresolved":false,"context_lines":[{"line_number":20,"context_line":"    # add new columns to the password table"},{"line_number":21,"context_line":"    password_table \u003d sql.Table(\u0027password\u0027, meta, autoload\u003dTrue)"},{"line_number":22,"context_line":"    created_at_column \u003d sql.Column(\u0027created_at\u0027, sql.DateTime(), nullable\u003dTrue)"},{"line_number":23,"context_line":"    created_by_column \u003d sql.Column(\u0027created_by\u0027, sql.String(64), nullable\u003dTrue)"},{"line_number":24,"context_line":"    expires_at_column \u003d sql.Column(\u0027expires_at\u0027, sql.DateTime(), nullable\u003dTrue)"},{"line_number":25,"context_line":"    password_table.create_column(created_at_column)"},{"line_number":26,"context_line":"    password_table.create_column(created_by_column)"}],"source_content_type":"text/x-python","patch_set":6,"id":"dab17558_5fb97214","line":23,"in_reply_to":"dab17558_92711647","updated":"2016-05-10 17:14:52.000000000","message":"oh okay. I\u0027ll add that feature to the etherpad. I guess that should be configurable too?","commit_id":"2d6d93e62c4271859e381e75ba15bd5e53eca26c"},{"author":{"_account_id":17579,"name":"Elvin Tubillara","email":"edtubill@us.ibm.com","username":"edtubill"},"change_message_id":"170014397e77d0601aec67e157d5f5b475c914ae","unresolved":false,"context_lines":[{"line_number":35,"context_line":"        sql.Column(\u0027user_id\u0027, sql.String(64),"},{"line_number":36,"context_line":"                   sql.ForeignKey(user_table.c.id, ondelete\u003d\u0027CASCADE\u0027),"},{"line_number":37,"context_line":"                   nullable\u003dTrue),"},{"line_number":38,"context_line":"        sql.Column(\u0027user_name\u0027, sql.String(255), nullable\u003dTrue),"},{"line_number":39,"context_line":"        sql.Column(\u0027attempted_at\u0027, sql.DateTime(), nullable\u003dFalse),"},{"line_number":40,"context_line":"        sql.Column(\u0027is_success\u0027, sql.Boolean, nullable\u003dFalse),"},{"line_number":41,"context_line":"        sql.Column(\u0027message\u0027, sql.Text(), nullable\u003dTrue))"}],"source_content_type":"text/x-python","patch_set":6,"id":"dab17558_a656a027","line":38,"updated":"2016-05-10 15:23:03.000000000","message":"Can this be grabbed somewhere else? Or is it just easier to access if we store it here?","commit_id":"2d6d93e62c4271859e381e75ba15bd5e53eca26c"},{"author":{"_account_id":17579,"name":"Elvin Tubillara","email":"edtubill@us.ibm.com","username":"edtubill"},"change_message_id":"2671fbc517f2e034919dcbfea169ed13f359a7a4","unresolved":false,"context_lines":[{"line_number":35,"context_line":"        sql.Column(\u0027user_id\u0027, sql.String(64),"},{"line_number":36,"context_line":"                   sql.ForeignKey(user_table.c.id, ondelete\u003d\u0027CASCADE\u0027),"},{"line_number":37,"context_line":"                   nullable\u003dTrue),"},{"line_number":38,"context_line":"        sql.Column(\u0027user_name\u0027, sql.String(255), nullable\u003dTrue),"},{"line_number":39,"context_line":"        sql.Column(\u0027attempted_at\u0027, sql.DateTime(), nullable\u003dFalse),"},{"line_number":40,"context_line":"        sql.Column(\u0027is_success\u0027, sql.Boolean, nullable\u003dFalse),"},{"line_number":41,"context_line":"        sql.Column(\u0027message\u0027, sql.Text(), nullable\u003dTrue))"}],"source_content_type":"text/x-python","patch_set":6,"id":"dab17558_f1bd0469","line":38,"in_reply_to":"dab17558_a656a027","updated":"2016-05-10 15:34:24.000000000","message":"^user_name","commit_id":"2d6d93e62c4271859e381e75ba15bd5e53eca26c"},{"author":{"_account_id":18338,"name":"Ron De Rose","email":"ronald.de.rose@intel.com","username":"derosenet"},"change_message_id":"e1f19b66578d31e1992c9b69623931cc81f8c8cd","unresolved":false,"context_lines":[{"line_number":35,"context_line":"        sql.Column(\u0027user_id\u0027, sql.String(64),"},{"line_number":36,"context_line":"                   sql.ForeignKey(user_table.c.id, ondelete\u003d\u0027CASCADE\u0027),"},{"line_number":37,"context_line":"                   nullable\u003dTrue),"},{"line_number":38,"context_line":"        sql.Column(\u0027user_name\u0027, sql.String(255), nullable\u003dTrue),"},{"line_number":39,"context_line":"        sql.Column(\u0027attempted_at\u0027, sql.DateTime(), nullable\u003dFalse),"},{"line_number":40,"context_line":"        sql.Column(\u0027is_success\u0027, sql.Boolean, nullable\u003dFalse),"},{"line_number":41,"context_line":"        sql.Column(\u0027message\u0027, sql.Text(), nullable\u003dTrue))"}],"source_content_type":"text/x-python","patch_set":6,"id":"dab17558_cbc80025","line":38,"in_reply_to":"dab17558_bf5fbee3","updated":"2016-05-10 18:40:05.000000000","message":"This table was going to be used to support these features:\n* PCI-DSS 8.1.4: Remove/disable inactive user accounts within 90 days.\n* PCI-DSS 8.1.6: Limit repeated access attempts by locking out the user ID after not more than six attempts.","commit_id":"2d6d93e62c4271859e381e75ba15bd5e53eca26c"},{"author":{"_account_id":17579,"name":"Elvin Tubillara","email":"edtubill@us.ibm.com","username":"edtubill"},"change_message_id":"d321607469b2b26cfd846c590c1ba55c7cf94096","unresolved":false,"context_lines":[{"line_number":35,"context_line":"        sql.Column(\u0027user_id\u0027, sql.String(64),"},{"line_number":36,"context_line":"                   sql.ForeignKey(user_table.c.id, ondelete\u003d\u0027CASCADE\u0027),"},{"line_number":37,"context_line":"                   nullable\u003dTrue),"},{"line_number":38,"context_line":"        sql.Column(\u0027user_name\u0027, sql.String(255), nullable\u003dTrue),"},{"line_number":39,"context_line":"        sql.Column(\u0027attempted_at\u0027, sql.DateTime(), nullable\u003dFalse),"},{"line_number":40,"context_line":"        sql.Column(\u0027is_success\u0027, sql.Boolean, nullable\u003dFalse),"},{"line_number":41,"context_line":"        sql.Column(\u0027message\u0027, sql.Text(), nullable\u003dTrue))"}],"source_content_type":"text/x-python","patch_set":6,"id":"dab17558_bf5fbee3","line":38,"in_reply_to":"dab17558_d2e39ed7","updated":"2016-05-10 17:14:52.000000000","message":"for which feature was this going to be used for again? Or is this just for auditing purposes?","commit_id":"2d6d93e62c4271859e381e75ba15bd5e53eca26c"},{"author":{"_account_id":18338,"name":"Ron De Rose","email":"ronald.de.rose@intel.com","username":"derosenet"},"change_message_id":"43df90ccceb4548b8d6c9c63d0439b5c2f47dc42","unresolved":false,"context_lines":[{"line_number":35,"context_line":"        sql.Column(\u0027user_id\u0027, sql.String(64),"},{"line_number":36,"context_line":"                   sql.ForeignKey(user_table.c.id, ondelete\u003d\u0027CASCADE\u0027),"},{"line_number":37,"context_line":"                   nullable\u003dTrue),"},{"line_number":38,"context_line":"        sql.Column(\u0027user_name\u0027, sql.String(255), nullable\u003dTrue),"},{"line_number":39,"context_line":"        sql.Column(\u0027attempted_at\u0027, sql.DateTime(), nullable\u003dFalse),"},{"line_number":40,"context_line":"        sql.Column(\u0027is_success\u0027, sql.Boolean, nullable\u003dFalse),"},{"line_number":41,"context_line":"        sql.Column(\u0027message\u0027, sql.Text(), nullable\u003dTrue))"}],"source_content_type":"text/x-python","patch_set":6,"id":"dab17558_d2e39ed7","line":38,"in_reply_to":"dab17558_f1bd0469","updated":"2016-05-10 16:13:58.000000000","message":"Talking with Dolph, we may not need this table.  We could instead utilize Keystone events and Ceilometer to pull this data.","commit_id":"2d6d93e62c4271859e381e75ba15bd5e53eca26c"},{"author":{"_account_id":17579,"name":"Elvin Tubillara","email":"edtubill@us.ibm.com","username":"edtubill"},"change_message_id":"170014397e77d0601aec67e157d5f5b475c914ae","unresolved":false,"context_lines":[{"line_number":38,"context_line":"        sql.Column(\u0027user_name\u0027, sql.String(255), nullable\u003dTrue),"},{"line_number":39,"context_line":"        sql.Column(\u0027attempted_at\u0027, sql.DateTime(), nullable\u003dFalse),"},{"line_number":40,"context_line":"        sql.Column(\u0027is_success\u0027, sql.Boolean, nullable\u003dFalse),"},{"line_number":41,"context_line":"        sql.Column(\u0027message\u0027, sql.Text(), nullable\u003dTrue))"},{"line_number":42,"context_line":"    user_activity_table.create(migrate_engine, checkfirst\u003dTrue)"}],"source_content_type":"text/x-python","patch_set":6,"id":"dab17558_a62d00aa","line":41,"updated":"2016-05-10 15:23:03.000000000","message":"What kind of message are we storing here?","commit_id":"2d6d93e62c4271859e381e75ba15bd5e53eca26c"},{"author":{"_account_id":18338,"name":"Ron De Rose","email":"ronald.de.rose@intel.com","username":"derosenet"},"change_message_id":"43df90ccceb4548b8d6c9c63d0439b5c2f47dc42","unresolved":false,"context_lines":[{"line_number":38,"context_line":"        sql.Column(\u0027user_name\u0027, sql.String(255), nullable\u003dTrue),"},{"line_number":39,"context_line":"        sql.Column(\u0027attempted_at\u0027, sql.DateTime(), nullable\u003dFalse),"},{"line_number":40,"context_line":"        sql.Column(\u0027is_success\u0027, sql.Boolean, nullable\u003dFalse),"},{"line_number":41,"context_line":"        sql.Column(\u0027message\u0027, sql.Text(), nullable\u003dTrue))"},{"line_number":42,"context_line":"    user_activity_table.create(migrate_engine, checkfirst\u003dTrue)"}],"source_content_type":"text/x-python","patch_set":6,"id":"dab17558_92d636ef","line":41,"in_reply_to":"dab17558_a62d00aa","updated":"2016-05-10 16:13:58.000000000","message":"Not sure, just thought we may want to capture additional info.","commit_id":"2d6d93e62c4271859e381e75ba15bd5e53eca26c"}],"keystone/common/sql/migrate_repo/versions/103_add_new_password_columns.py":[{"author":{"_account_id":5046,"name":"Lance Bragstad","email":"lbragstad@redhat.com","username":"ldbragst"},"change_message_id":"215d6f0d5e21503a1fa256e06c6e018982bfcd0f","unresolved":false,"context_lines":[{"line_number":34,"context_line":""},{"line_number":35,"context_line":"    # update created_at to now and set not nullable"},{"line_number":36,"context_line":"    now \u003d datetime.datetime.utcnow()"},{"line_number":37,"context_line":"    stmt \u003d password_table.update().values(created_at\u003dnow)"},{"line_number":38,"context_line":"    stmt.execute()"},{"line_number":39,"context_line":"    # password_table.c.created_at.alter(nullable\u003dFalse)"}],"source_content_type":"text/x-python","patch_set":29,"id":"bab6814e_a15dfa7a","line":37,"updated":"2016-05-20 09:54:41.000000000","message":"Are we going to treat this migration the same we did for shadow users? I remember those migrations happening in two phases. The first we just created the tables. In the second, we actually migrated the data. This line seems like it should live in the second phase if that is the approach we are taking with the migration.\n\nAlso, why update the create_at at the time of the database migration?","commit_id":"db59100adfcaf3c09ccfa068a648c6d2f63b20b6"},{"author":{"_account_id":18338,"name":"Ron De Rose","email":"ronald.de.rose@intel.com","username":"derosenet"},"change_message_id":"0509a741d0836eab8e268f49272913f8e30ae6ca","unresolved":false,"context_lines":[{"line_number":34,"context_line":""},{"line_number":35,"context_line":"    # update created_at to now and set not nullable"},{"line_number":36,"context_line":"    now \u003d datetime.datetime.utcnow()"},{"line_number":37,"context_line":"    stmt \u003d password_table.update().values(created_at\u003dnow)"},{"line_number":38,"context_line":"    stmt.execute()"},{"line_number":39,"context_line":"    # password_table.c.created_at.alter(nullable\u003dFalse)"}],"source_content_type":"text/x-python","patch_set":29,"id":"bab6814e_3024a45e","line":37,"in_reply_to":"bab6814e_a15dfa7a","updated":"2016-05-20 14:31:11.000000000","message":"Yeah, seemed to make sense to do it all in one since I\u0027m just adding columns, populating the data and then setting the column nullable flag.","commit_id":"db59100adfcaf3c09ccfa068a648c6d2f63b20b6"},{"author":{"_account_id":5046,"name":"Lance Bragstad","email":"lbragstad@redhat.com","username":"ldbragst"},"change_message_id":"215d6f0d5e21503a1fa256e06c6e018982bfcd0f","unresolved":false,"context_lines":[{"line_number":36,"context_line":"    now \u003d datetime.datetime.utcnow()"},{"line_number":37,"context_line":"    stmt \u003d password_table.update().values(created_at\u003dnow)"},{"line_number":38,"context_line":"    stmt.execute()"},{"line_number":39,"context_line":"    # password_table.c.created_at.alter(nullable\u003dFalse)"}],"source_content_type":"text/x-python","patch_set":29,"id":"bab6814e_01fb267a","line":39,"updated":"2016-05-20 09:54:41.000000000","message":"Should this be removed?","commit_id":"db59100adfcaf3c09ccfa068a648c6d2f63b20b6"},{"author":{"_account_id":18338,"name":"Ron De Rose","email":"ronald.de.rose@intel.com","username":"derosenet"},"change_message_id":"0509a741d0836eab8e268f49272913f8e30ae6ca","unresolved":false,"context_lines":[{"line_number":36,"context_line":"    now \u003d datetime.datetime.utcnow()"},{"line_number":37,"context_line":"    stmt \u003d password_table.update().values(created_at\u003dnow)"},{"line_number":38,"context_line":"    stmt.execute()"},{"line_number":39,"context_line":"    # password_table.c.created_at.alter(nullable\u003dFalse)"}],"source_content_type":"text/x-python","patch_set":29,"id":"bab6814e_10e080f9","line":39,"in_reply_to":"bab6814e_01fb267a","updated":"2016-05-20 14:31:11.000000000","message":"The rolling upgrade gate is preventing me from doing this.  Left it here until I figure out a way around it.","commit_id":"db59100adfcaf3c09ccfa068a648c6d2f63b20b6"},{"author":{"_account_id":5046,"name":"Lance Bragstad","email":"lbragstad@redhat.com","username":"ldbragst"},"change_message_id":"d948058132973f318f18c45dc38f1f218bf6e407","unresolved":false,"context_lines":[{"line_number":31,"context_line":"                                server_default\u003d\u00270\u0027, default\u003dFalse)"},{"line_number":32,"context_line":"    change_required_column \u003d sql.Column(\u0027change_required\u0027, sql.Boolean,"},{"line_number":33,"context_line":"                                        nullable\u003dFalse, server_default\u003d\u00270\u0027,"},{"line_number":34,"context_line":"                                        default\u003dFalse)"},{"line_number":35,"context_line":"    password_table.create_column(created_at_column)"},{"line_number":36,"context_line":"    password_table.create_column(created_by_column)"},{"line_number":37,"context_line":"    password_table.create_column(expired_column)"}],"source_content_type":"text/x-python","patch_set":40,"id":"bab6814e_960fc52d","line":34,"updated":"2016-05-24 13:04:53.000000000","message":"Just for my understanding, this would be used if an admin created a user\u0027s password and that user is now required to change it to something else upon login?","commit_id":"6f25ac3427c3eaaf4ad8f5783d326337d1058e02"},{"author":{"_account_id":18338,"name":"Ron De Rose","email":"ronald.de.rose@intel.com","username":"derosenet"},"change_message_id":"72b3fff7a41138760fa36364357cf7b94371aa66","unresolved":false,"context_lines":[{"line_number":31,"context_line":"                                server_default\u003d\u00270\u0027, default\u003dFalse)"},{"line_number":32,"context_line":"    change_required_column \u003d sql.Column(\u0027change_required\u0027, sql.Boolean,"},{"line_number":33,"context_line":"                                        nullable\u003dFalse, server_default\u003d\u00270\u0027,"},{"line_number":34,"context_line":"                                        default\u003dFalse)"},{"line_number":35,"context_line":"    password_table.create_column(created_at_column)"},{"line_number":36,"context_line":"    password_table.create_column(created_by_column)"},{"line_number":37,"context_line":"    password_table.create_column(expired_column)"}],"source_content_type":"text/x-python","patch_set":40,"id":"bab6814e_7e35d3f5","line":34,"in_reply_to":"bab6814e_960fc52d","updated":"2016-05-24 14:47:39.000000000","message":"Yes, correct","commit_id":"6f25ac3427c3eaaf4ad8f5783d326337d1058e02"},{"author":{"_account_id":7725,"name":"David Stanek","email":"dstanek@dstanek.com","username":"dstanek"},"change_message_id":"d13ace1848a65dc6dc169bcc35332e2d08a69381","unresolved":false,"context_lines":[{"line_number":11,"context_line":"# under the License."},{"line_number":12,"context_line":""},{"line_number":13,"context_line":"import datetime"},{"line_number":14,"context_line":"import sqlalchemy as sql"},{"line_number":15,"context_line":""},{"line_number":16,"context_line":""},{"line_number":17,"context_line":"def upgrade(migrate_engine):"}],"source_content_type":"text/x-python","patch_set":46,"id":"9abb7d3a_df10cc5b","line":14,"updated":"2016-05-31 16:47:33.000000000","message":"(nit) should be a space in between these imports.","commit_id":"aea09909d2657911fd3176b1b2612d8b154d1ffa"},{"author":{"_account_id":7725,"name":"David Stanek","email":"dstanek@dstanek.com","username":"dstanek"},"change_message_id":"5e40cf2e1ffb9c2f7edecc5f74720c6a5e881420","unresolved":false,"context_lines":[{"line_number":10,"context_line":"# License for the specific language governing permissions and limitations"},{"line_number":11,"context_line":"# under the License."},{"line_number":12,"context_line":""},{"line_number":13,"context_line":"import datetime"},{"line_number":14,"context_line":"import sqlalchemy as sql"},{"line_number":15,"context_line":""},{"line_number":16,"context_line":""}],"source_content_type":"text/x-python","patch_set":48,"id":"7aa08908_e3bbe90c","line":13,"updated":"2016-06-06 12:15:48.000000000","message":"Needs to follow hacking rules: http://docs.openstack.org/developer/hacking/#import-order-template","commit_id":"10f620999bc1d06b8200dc98166b4fb3005c8b10"},{"author":{"_account_id":18338,"name":"Ron De Rose","email":"ronald.de.rose@intel.com","username":"derosenet"},"change_message_id":"d271bd3e5d4020a926f146ced1d63d16b9677047","unresolved":false,"context_lines":[{"line_number":10,"context_line":"# License for the specific language governing permissions and limitations"},{"line_number":11,"context_line":"# under the License."},{"line_number":12,"context_line":""},{"line_number":13,"context_line":"import datetime"},{"line_number":14,"context_line":"import sqlalchemy as sql"},{"line_number":15,"context_line":""},{"line_number":16,"context_line":""}],"source_content_type":"text/x-python","patch_set":48,"id":"7aa08908_2f6aef80","line":13,"in_reply_to":"7aa08908_e3bbe90c","updated":"2016-06-06 13:50:21.000000000","message":"Done","commit_id":"10f620999bc1d06b8200dc98166b4fb3005c8b10"},{"author":{"_account_id":7725,"name":"David Stanek","email":"dstanek@dstanek.com","username":"dstanek"},"change_message_id":"5e40cf2e1ffb9c2f7edecc5f74720c6a5e881420","unresolved":false,"context_lines":[{"line_number":23,"context_line":"                                   nullable\u003dTrue)"},{"line_number":24,"context_line":"    expired_column \u003d sql.Column(\u0027expired\u0027, sql.Boolean, nullable\u003dFalse,"},{"line_number":25,"context_line":"                                server_default\u003d\u00270\u0027, default\u003dFalse)"},{"line_number":26,"context_line":"    password_table \u003d sql.Table(\u0027password\u0027, meta, autoload\u003dTrue)"},{"line_number":27,"context_line":"    password_table.create_column(created_at_column)"},{"line_number":28,"context_line":"    password_table.create_column(expired_column)"},{"line_number":29,"context_line":""}],"source_content_type":"text/x-python","patch_set":48,"id":"7aa08908_c3206d4c","line":26,"updated":"2016-06-06 12:15:48.000000000","message":"Will all existing rows get the default value?","commit_id":"10f620999bc1d06b8200dc98166b4fb3005c8b10"},{"author":{"_account_id":18338,"name":"Ron De Rose","email":"ronald.de.rose@intel.com","username":"derosenet"},"change_message_id":"d271bd3e5d4020a926f146ced1d63d16b9677047","unresolved":false,"context_lines":[{"line_number":23,"context_line":"                                   nullable\u003dTrue)"},{"line_number":24,"context_line":"    expired_column \u003d sql.Column(\u0027expired\u0027, sql.Boolean, nullable\u003dFalse,"},{"line_number":25,"context_line":"                                server_default\u003d\u00270\u0027, default\u003dFalse)"},{"line_number":26,"context_line":"    password_table \u003d sql.Table(\u0027password\u0027, meta, autoload\u003dTrue)"},{"line_number":27,"context_line":"    password_table.create_column(created_at_column)"},{"line_number":28,"context_line":"    password_table.create_column(expired_column)"},{"line_number":29,"context_line":""}],"source_content_type":"text/x-python","patch_set":48,"id":"7aa08908_2fef8fe9","line":26,"in_reply_to":"7aa08908_c3206d4c","updated":"2016-06-06 13:50:21.000000000","message":"Yes, should default to False.","commit_id":"10f620999bc1d06b8200dc98166b4fb3005c8b10"},{"author":{"_account_id":17860,"name":"Samuel de Medeiros Queiroz","email":"samueldmq@gmail.com","username":"samueldmq"},"change_message_id":"1ee3585a62951b1dd5e337a61d706b4e624bf86b","unresolved":false,"context_lines":[{"line_number":21,"context_line":""},{"line_number":22,"context_line":"    # add new password columns"},{"line_number":23,"context_line":"    created_at_column \u003d sql.Column(\u0027created_at\u0027, sql.DateTime(),"},{"line_number":24,"context_line":"                                   nullable\u003dTrue)"},{"line_number":25,"context_line":"    expired_column \u003d sql.Column(\u0027expired\u0027, sql.Boolean, nullable\u003dFalse,"},{"line_number":26,"context_line":"                                server_default\u003d\u00270\u0027, default\u003dFalse)"},{"line_number":27,"context_line":"    password_table \u003d sql.Table(\u0027password\u0027, meta, autoload\u003dTrue)"}],"source_content_type":"text/x-python","patch_set":51,"id":"7aa08908_5085b357","line":24,"range":{"start_line":24,"start_character":35,"end_line":24,"end_character":48},"updated":"2016-06-08 18:41:01.000000000","message":"why nullable ?","commit_id":"2c17dcfb50be278b8ef854a9f4379bf2b249da14"},{"author":{"_account_id":18338,"name":"Ron De Rose","email":"ronald.de.rose@intel.com","username":"derosenet"},"change_message_id":"48869958733448b783fb38166672dadac2d2588a","unresolved":false,"context_lines":[{"line_number":21,"context_line":""},{"line_number":22,"context_line":"    # add new password columns"},{"line_number":23,"context_line":"    created_at_column \u003d sql.Column(\u0027created_at\u0027, sql.DateTime(),"},{"line_number":24,"context_line":"                                   nullable\u003dTrue)"},{"line_number":25,"context_line":"    expired_column \u003d sql.Column(\u0027expired\u0027, sql.Boolean, nullable\u003dFalse,"},{"line_number":26,"context_line":"                                server_default\u003d\u00270\u0027, default\u003dFalse)"},{"line_number":27,"context_line":"    password_table \u003d sql.Table(\u0027password\u0027, meta, autoload\u003dTrue)"}],"source_content_type":"text/x-python","patch_set":51,"id":"7aa08908_9ad459ec","line":24,"range":{"start_line":24,"start_character":35,"end_line":24,"end_character":48},"in_reply_to":"7aa08908_3a59e535","updated":"2016-06-08 18:53:59.000000000","message":"* a) I cannot add a default date value that is supported among the various databases.","commit_id":"2c17dcfb50be278b8ef854a9f4379bf2b249da14"},{"author":{"_account_id":18338,"name":"Ron De Rose","email":"ronald.de.rose@intel.com","username":"derosenet"},"change_message_id":"c1bb3e37035c284d3e8eaeb2709b25c552ba5893","unresolved":false,"context_lines":[{"line_number":21,"context_line":""},{"line_number":22,"context_line":"    # add new password columns"},{"line_number":23,"context_line":"    created_at_column \u003d sql.Column(\u0027created_at\u0027, sql.DateTime(),"},{"line_number":24,"context_line":"                                   nullable\u003dTrue)"},{"line_number":25,"context_line":"    expired_column \u003d sql.Column(\u0027expired\u0027, sql.Boolean, nullable\u003dFalse,"},{"line_number":26,"context_line":"                                server_default\u003d\u00270\u0027, default\u003dFalse)"},{"line_number":27,"context_line":"    password_table \u003d sql.Table(\u0027password\u0027, meta, autoload\u003dTrue)"}],"source_content_type":"text/x-python","patch_set":51,"id":"7aa08908_3a59e535","line":24,"range":{"start_line":24,"start_character":35,"end_line":24,"end_character":48},"in_reply_to":"7aa08908_5085b357","updated":"2016-06-08 18:49:58.000000000","message":"nullable because:\na) I cannot a default date value that is supported among the various databases.\nb) Rolling upgrades gate prevents altering the column.","commit_id":"2c17dcfb50be278b8ef854a9f4379bf2b249da14"},{"author":{"_account_id":18338,"name":"Ron De Rose","email":"ronald.de.rose@intel.com","username":"derosenet"},"change_message_id":"439f25fd601d62f7b00d1483eb4227ca4905dcf9","unresolved":false,"context_lines":[{"line_number":21,"context_line":""},{"line_number":22,"context_line":"    # add new password columns"},{"line_number":23,"context_line":"    created_at_column \u003d sql.Column(\u0027created_at\u0027, sql.DateTime(),"},{"line_number":24,"context_line":"                                   nullable\u003dTrue)"},{"line_number":25,"context_line":"    expired_column \u003d sql.Column(\u0027expired\u0027, sql.Boolean, nullable\u003dFalse,"},{"line_number":26,"context_line":"                                server_default\u003d\u00270\u0027, default\u003dFalse)"},{"line_number":27,"context_line":"    password_table \u003d sql.Table(\u0027password\u0027, meta, autoload\u003dTrue)"}],"source_content_type":"text/x-python","patch_set":51,"id":"7aa08908_20b9b2cc","line":24,"range":{"start_line":24,"start_character":35,"end_line":24,"end_character":48},"in_reply_to":"7aa08908_5d814bfa","updated":"2016-06-08 19:39:39.000000000","message":"Yeah, like I mentioned in IRC, I tried several ways to implement a default date value, but couldn\u0027t get this to work.  Failed in sqlplus and at the gate.","commit_id":"2c17dcfb50be278b8ef854a9f4379bf2b249da14"},{"author":{"_account_id":17860,"name":"Samuel de Medeiros Queiroz","email":"samueldmq@gmail.com","username":"samueldmq"},"change_message_id":"1c9244d9fd955bc51c827179d0918638e77ed032","unresolved":false,"context_lines":[{"line_number":21,"context_line":""},{"line_number":22,"context_line":"    # add new password columns"},{"line_number":23,"context_line":"    created_at_column \u003d sql.Column(\u0027created_at\u0027, sql.DateTime(),"},{"line_number":24,"context_line":"                                   nullable\u003dTrue)"},{"line_number":25,"context_line":"    expired_column \u003d sql.Column(\u0027expired\u0027, sql.Boolean, nullable\u003dFalse,"},{"line_number":26,"context_line":"                                server_default\u003d\u00270\u0027, default\u003dFalse)"},{"line_number":27,"context_line":"    password_table \u003d sql.Table(\u0027password\u0027, meta, autoload\u003dTrue)"}],"source_content_type":"text/x-python","patch_set":51,"id":"7aa08908_5d814bfa","line":24,"range":{"start_line":24,"start_character":35,"end_line":24,"end_character":48},"in_reply_to":"7aa08908_9ad459ec","updated":"2016-06-08 19:15:22.000000000","message":"I am not getting where is the limitation, at sql_model.py you set the column\u0027s default to be utcnow(), which is fine. So we ensure this column will never be null","commit_id":"2c17dcfb50be278b8ef854a9f4379bf2b249da14"},{"author":{"_account_id":17860,"name":"Samuel de Medeiros Queiroz","email":"samueldmq@gmail.com","username":"samueldmq"},"change_message_id":"1ee3585a62951b1dd5e337a61d706b4e624bf86b","unresolved":false,"context_lines":[{"line_number":22,"context_line":"    # add new password columns"},{"line_number":23,"context_line":"    created_at_column \u003d sql.Column(\u0027created_at\u0027, sql.DateTime(),"},{"line_number":24,"context_line":"                                   nullable\u003dTrue)"},{"line_number":25,"context_line":"    expired_column \u003d sql.Column(\u0027expired\u0027, sql.Boolean, nullable\u003dFalse,"},{"line_number":26,"context_line":"                                server_default\u003d\u00270\u0027, default\u003dFalse)"},{"line_number":27,"context_line":"    password_table \u003d sql.Table(\u0027password\u0027, meta, autoload\u003dTrue)"},{"line_number":28,"context_line":"    password_table.create_column(created_at_column)"}],"source_content_type":"text/x-python","patch_set":51,"id":"7aa08908_50b933cb","line":25,"range":{"start_line":25,"start_character":32,"end_line":25,"end_character":41},"updated":"2016-06-08 18:41:01.000000000","message":"why do we need this column ? we can determine if the password is expired by comparing its created_at against the password_expires_days value from the config file","commit_id":"2c17dcfb50be278b8ef854a9f4379bf2b249da14"},{"author":{"_account_id":18338,"name":"Ron De Rose","email":"ronald.de.rose@intel.com","username":"derosenet"},"change_message_id":"c1bb3e37035c284d3e8eaeb2709b25c552ba5893","unresolved":false,"context_lines":[{"line_number":22,"context_line":"    # add new password columns"},{"line_number":23,"context_line":"    created_at_column \u003d sql.Column(\u0027created_at\u0027, sql.DateTime(),"},{"line_number":24,"context_line":"                                   nullable\u003dTrue)"},{"line_number":25,"context_line":"    expired_column \u003d sql.Column(\u0027expired\u0027, sql.Boolean, nullable\u003dFalse,"},{"line_number":26,"context_line":"                                server_default\u003d\u00270\u0027, default\u003dFalse)"},{"line_number":27,"context_line":"    password_table \u003d sql.Table(\u0027password\u0027, meta, autoload\u003dTrue)"},{"line_number":28,"context_line":"    password_table.create_column(created_at_column)"}],"source_content_type":"text/x-python","patch_set":51,"id":"7aa08908_bab83512","line":25,"range":{"start_line":25,"start_character":32,"end_line":25,"end_character":41},"in_reply_to":"7aa08908_50b933cb","updated":"2016-06-08 18:49:58.000000000","message":"Everytime a user updates their password, it will create a new password record.  From there, I need to be able to distinguish which password is the active password and which ones are expired.","commit_id":"2c17dcfb50be278b8ef854a9f4379bf2b249da14"},{"author":{"_account_id":17860,"name":"Samuel de Medeiros Queiroz","email":"samueldmq@gmail.com","username":"samueldmq"},"change_message_id":"1c9244d9fd955bc51c827179d0918638e77ed032","unresolved":false,"context_lines":[{"line_number":22,"context_line":"    # add new password columns"},{"line_number":23,"context_line":"    created_at_column \u003d sql.Column(\u0027created_at\u0027, sql.DateTime(),"},{"line_number":24,"context_line":"                                   nullable\u003dTrue)"},{"line_number":25,"context_line":"    expired_column \u003d sql.Column(\u0027expired\u0027, sql.Boolean, nullable\u003dFalse,"},{"line_number":26,"context_line":"                                server_default\u003d\u00270\u0027, default\u003dFalse)"},{"line_number":27,"context_line":"    password_table \u003d sql.Table(\u0027password\u0027, meta, autoload\u003dTrue)"},{"line_number":28,"context_line":"    password_table.create_column(created_at_column)"}],"source_content_type":"text/x-python","patch_set":51,"id":"7aa08908_bdbe6fab","line":25,"range":{"start_line":25,"start_character":32,"end_line":25,"end_character":41},"in_reply_to":"7aa08908_bab83512","updated":"2016-06-08 19:15:22.000000000","message":"Expired sounds to me like it has timed out or something like that. If it\u0027s only for the case where a new password has been defined as the old one became stale, what about \u0027enabled\u0027 (we use this everywhere else), so old passwords become disabled.\n\nIn addition, you could still do it without this column. The latest password is the one with more recent created_at value.","commit_id":"2c17dcfb50be278b8ef854a9f4379bf2b249da14"},{"author":{"_account_id":18338,"name":"Ron De Rose","email":"ronald.de.rose@intel.com","username":"derosenet"},"change_message_id":"9327aafc647232f9bf73f3fb6910b7d110fd7aa8","unresolved":false,"context_lines":[{"line_number":22,"context_line":"    # add new password columns"},{"line_number":23,"context_line":"    created_at_column \u003d sql.Column(\u0027created_at\u0027, sql.DateTime(),"},{"line_number":24,"context_line":"                                   nullable\u003dTrue)"},{"line_number":25,"context_line":"    expired_column \u003d sql.Column(\u0027expired\u0027, sql.Boolean, nullable\u003dFalse,"},{"line_number":26,"context_line":"                                server_default\u003d\u00270\u0027, default\u003dFalse)"},{"line_number":27,"context_line":"    password_table \u003d sql.Table(\u0027password\u0027, meta, autoload\u003dTrue)"},{"line_number":28,"context_line":"    password_table.create_column(created_at_column)"}],"source_content_type":"text/x-python","patch_set":51,"id":"7aa08908_e0c7aa61","line":25,"range":{"start_line":25,"start_character":32,"end_line":25,"end_character":41},"in_reply_to":"7aa08908_bdbe6fab","updated":"2016-06-08 19:36:15.000000000","message":"It\u0027s mainly convenience to have the expired flag. And the more I think about it, I like the name expired:\n\"cease to be valid, typically after a fixed period of time\"\n\nWhen the password does actually expire, this makes sense.  And if the user creates a new password, the old password ceases to be valid, so it still applies.","commit_id":"2c17dcfb50be278b8ef854a9f4379bf2b249da14"},{"author":{"_account_id":17860,"name":"Samuel de Medeiros Queiroz","email":"samueldmq@gmail.com","username":"samueldmq"},"change_message_id":"1ee3585a62951b1dd5e337a61d706b4e624bf86b","unresolved":false,"context_lines":[{"line_number":29,"context_line":"    password_table.create_column(expired_column)"},{"line_number":30,"context_line":""},{"line_number":31,"context_line":"    # update created_at to now"},{"line_number":32,"context_line":"    now \u003d datetime.datetime.utcnow()"},{"line_number":33,"context_line":"    stmt \u003d password_table.update().values(created_at\u003dnow)"},{"line_number":34,"context_line":"    stmt.execute()"}],"source_content_type":"text/x-python","patch_set":51,"id":"7aa08908_907b9b7a","line":34,"range":{"start_line":32,"start_character":4,"end_line":34,"end_character":18},"updated":"2016-06-08 18:41:01.000000000","message":"updating all created_at to now ? there is a way to set a default value for the column when defining it (server_default, as you did for expired)","commit_id":"2c17dcfb50be278b8ef854a9f4379bf2b249da14"},{"author":{"_account_id":18338,"name":"Ron De Rose","email":"ronald.de.rose@intel.com","username":"derosenet"},"change_message_id":"c1bb3e37035c284d3e8eaeb2709b25c552ba5893","unresolved":false,"context_lines":[{"line_number":29,"context_line":"    password_table.create_column(expired_column)"},{"line_number":30,"context_line":""},{"line_number":31,"context_line":"    # update created_at to now"},{"line_number":32,"context_line":"    now \u003d datetime.datetime.utcnow()"},{"line_number":33,"context_line":"    stmt \u003d password_table.update().values(created_at\u003dnow)"},{"line_number":34,"context_line":"    stmt.execute()"}],"source_content_type":"text/x-python","patch_set":51,"id":"7aa08908_1a0869d9","line":34,"range":{"start_line":32,"start_character":4,"end_line":34,"end_character":18},"in_reply_to":"7aa08908_907b9b7a","updated":"2016-06-08 18:49:58.000000000","message":"No, tried it. In fact, tried a bunch things and could not get the default to work.","commit_id":"2c17dcfb50be278b8ef854a9f4379bf2b249da14"},{"author":{"_account_id":18338,"name":"Ron De Rose","email":"ronald.de.rose@intel.com","username":"derosenet"},"change_message_id":"a058783b50e0599eac9da560608e2db22b661b2f","unresolved":false,"context_lines":[{"line_number":20,"context_line":"    meta.bind \u003d migrate_engine"},{"line_number":21,"context_line":""},{"line_number":22,"context_line":"    # tried to make create_at not null, but unable to set the default"},{"line_number":23,"context_line":"    # datetime value, doesn\u0027t seem to be supported"},{"line_number":24,"context_line":"    created_at_column \u003d sql.Column(\u0027created_at\u0027, sql.DateTime(),"},{"line_number":25,"context_line":"                                   nullable\u003dTrue)"},{"line_number":26,"context_line":"    expired_column \u003d sql.Column(\u0027expired\u0027, sql.Boolean, nullable\u003dFalse,"}],"source_content_type":"text/x-python","patch_set":52,"id":"7aa08908_757533c9","line":23,"range":{"start_line":23,"start_character":6,"end_line":23,"end_character":14},"updated":"2016-06-08 23:32:08.000000000","message":"I\u0027m pretty sure about this comment. That being said, if you are able to get a datetime default value to work, beer is on me at the mid-cycle.","commit_id":"1fd49dbc8620177b0e6798d035319a0163da070b"},{"author":{"_account_id":18338,"name":"Ron De Rose","email":"ronald.de.rose@intel.com","username":"derosenet"},"change_message_id":"77757b4369bf7042ad48660086c583b7baaf62a1","unresolved":false,"context_lines":[{"line_number":23,"context_line":"    # datetime value, doesn\u0027t seem to be supported"},{"line_number":24,"context_line":"    created_at_column \u003d sql.Column(\u0027created_at\u0027, sql.DateTime(),"},{"line_number":25,"context_line":"                                   nullable\u003dTrue)"},{"line_number":26,"context_line":"    expired_column \u003d sql.Column(\u0027expired\u0027, sql.Boolean, nullable\u003dFalse,"},{"line_number":27,"context_line":"                                server_default\u003d\u00270\u0027, default\u003dFalse)"},{"line_number":28,"context_line":"    password_table \u003d sql.Table(\u0027password\u0027, meta, autoload\u003dTrue)"},{"line_number":29,"context_line":"    password_table.create_column(created_at_column)"}],"source_content_type":"text/x-python","patch_set":52,"id":"7aa08908_15bf8f61","line":26,"range":{"start_line":26,"start_character":4,"end_line":26,"end_character":18},"updated":"2016-06-08 23:30:53.000000000","message":"See Samuel\u0027s comment regarding not needing the expired flag. I have it here for some clarity, but mostly for convenience. However, if others also feel that this should be removed, I\u0027ll take it out.","commit_id":"1fd49dbc8620177b0e6798d035319a0163da070b"},{"author":{"_account_id":4,"name":"Dolph Mathews","email":"dolph.mathews@gmail.com","username":"dolph"},"change_message_id":"6edfab6446fc8c7f895b09845254921318e1700d","unresolved":false,"context_lines":[{"line_number":24,"context_line":"    created_at_column \u003d sql.Column(\u0027created_at\u0027, sql.DateTime(),"},{"line_number":25,"context_line":"                                   nullable\u003dTrue)"},{"line_number":26,"context_line":"    expired_column \u003d sql.Column(\u0027expired\u0027, sql.Boolean, nullable\u003dFalse,"},{"line_number":27,"context_line":"                                server_default\u003d\u00270\u0027, default\u003dFalse)"},{"line_number":28,"context_line":"    password_table \u003d sql.Table(\u0027password\u0027, meta, autoload\u003dTrue)"},{"line_number":29,"context_line":"    password_table.create_column(created_at_column)"},{"line_number":30,"context_line":"    password_table.create_column(expired_column)"}],"source_content_type":"text/x-python","patch_set":52,"id":"7aa08908_356f2bfd","line":27,"updated":"2016-06-08 23:34:28.000000000","message":"Do we specifically care about the creation date? If created_at and expired were reduced to a single expires_at column (or expired_at... granted, the values may be in the future or past), then you A) would only have to do the math to compute expiration once, B) would not have to update a password as being expired because you could simply filter against the current time, and C) we\u0027d gain the ability to administratively extend or reduce the expiration time frame per password.","commit_id":"1fd49dbc8620177b0e6798d035319a0163da070b"},{"author":{"_account_id":18338,"name":"Ron De Rose","email":"ronald.de.rose@intel.com","username":"derosenet"},"change_message_id":"2c7f9803f2435398765017428b90f633d106d6d1","unresolved":false,"context_lines":[{"line_number":24,"context_line":"    created_at_column \u003d sql.Column(\u0027created_at\u0027, sql.DateTime(),"},{"line_number":25,"context_line":"                                   nullable\u003dTrue)"},{"line_number":26,"context_line":"    expired_column \u003d sql.Column(\u0027expired\u0027, sql.Boolean, nullable\u003dFalse,"},{"line_number":27,"context_line":"                                server_default\u003d\u00270\u0027, default\u003dFalse)"},{"line_number":28,"context_line":"    password_table \u003d sql.Table(\u0027password\u0027, meta, autoload\u003dTrue)"},{"line_number":29,"context_line":"    password_table.create_column(created_at_column)"},{"line_number":30,"context_line":"    password_table.create_column(expired_column)"}],"source_content_type":"text/x-python","patch_set":52,"id":"7aa08908_dfece494","line":27,"in_reply_to":"7aa08908_2b850ace","updated":"2016-06-09 13:52:48.000000000","message":"Yeah, but if the expectation is that all passwords should expire in 90 days when I change the config setting, why not just implement that functionality?  \n\nLikewise, if I have a user in the whitelist, where their password doesn\u0027t expire, and then I remove them from the whitelist, operators will also have to run a SQL command.\n\nWhile this may not seem like a big deal, I\u0027m not sure what we are getting out of it, having passwords that have different expiration times. What is the use case for this? I mean, I\u0027ve never been able to log into a system with 2 different passwords.","commit_id":"1fd49dbc8620177b0e6798d035319a0163da070b"},{"author":{"_account_id":18338,"name":"Ron De Rose","email":"ronald.de.rose@intel.com","username":"derosenet"},"change_message_id":"1950dbd15e848e1601ce5bbb5baafd074b24c7b3","unresolved":false,"context_lines":[{"line_number":24,"context_line":"    created_at_column \u003d sql.Column(\u0027created_at\u0027, sql.DateTime(),"},{"line_number":25,"context_line":"                                   nullable\u003dTrue)"},{"line_number":26,"context_line":"    expired_column \u003d sql.Column(\u0027expired\u0027, sql.Boolean, nullable\u003dFalse,"},{"line_number":27,"context_line":"                                server_default\u003d\u00270\u0027, default\u003dFalse)"},{"line_number":28,"context_line":"    password_table \u003d sql.Table(\u0027password\u0027, meta, autoload\u003dTrue)"},{"line_number":29,"context_line":"    password_table.create_column(created_at_column)"},{"line_number":30,"context_line":"    password_table.create_column(expired_column)"}],"source_content_type":"text/x-python","patch_set":52,"id":"7aa08908_b0b84912","line":27,"in_reply_to":"7aa08908_356f2bfd","updated":"2016-06-08 23:46:38.000000000","message":"Hmm... yeah, it\u0027s good point. The only downside that I see is that we\u0027re possibly authenticating against multiple passwords, as opposed to always having a single active password. But I do like the other benefits, and it eliminates the need for created_at and a default datetime value :) Reworking...","commit_id":"1fd49dbc8620177b0e6798d035319a0163da070b"},{"author":{"_account_id":18338,"name":"Ron De Rose","email":"ronald.de.rose@intel.com","username":"derosenet"},"change_message_id":"81c12495f07992d0b5cea25c3869c407680e53bd","unresolved":false,"context_lines":[{"line_number":24,"context_line":"    created_at_column \u003d sql.Column(\u0027created_at\u0027, sql.DateTime(),"},{"line_number":25,"context_line":"                                   nullable\u003dTrue)"},{"line_number":26,"context_line":"    expired_column \u003d sql.Column(\u0027expired\u0027, sql.Boolean, nullable\u003dFalse,"},{"line_number":27,"context_line":"                                server_default\u003d\u00270\u0027, default\u003dFalse)"},{"line_number":28,"context_line":"    password_table \u003d sql.Table(\u0027password\u0027, meta, autoload\u003dTrue)"},{"line_number":29,"context_line":"    password_table.create_column(created_at_column)"},{"line_number":30,"context_line":"    password_table.create_column(expired_column)"}],"source_content_type":"text/x-python","patch_set":52,"id":"7aa08908_d0a99525","line":27,"in_reply_to":"7aa08908_b0b84912","updated":"2016-06-09 00:10:32.000000000","message":"Actually, thinking about this some more, expires_at would get set at password create/update. For existing deployments though, if they turn this on, when would their current passwords expire? Not until the user updates their password, which is not what I would expect. I would expect all passwords at that point to expire after 90 days.","commit_id":"1fd49dbc8620177b0e6798d035319a0163da070b"},{"author":{"_account_id":4,"name":"Dolph Mathews","email":"dolph.mathews@gmail.com","username":"dolph"},"change_message_id":"63ed681b6d19e605a0d3e61209eb7423d65bdfb8","unresolved":false,"context_lines":[{"line_number":24,"context_line":"    created_at_column \u003d sql.Column(\u0027created_at\u0027, sql.DateTime(),"},{"line_number":25,"context_line":"                                   nullable\u003dTrue)"},{"line_number":26,"context_line":"    expired_column \u003d sql.Column(\u0027expired\u0027, sql.Boolean, nullable\u003dFalse,"},{"line_number":27,"context_line":"                                server_default\u003d\u00270\u0027, default\u003dFalse)"},{"line_number":28,"context_line":"    password_table \u003d sql.Table(\u0027password\u0027, meta, autoload\u003dTrue)"},{"line_number":29,"context_line":"    password_table.create_column(created_at_column)"},{"line_number":30,"context_line":"    password_table.create_column(expired_column)"}],"source_content_type":"text/x-python","patch_set":52,"id":"7aa08908_2b850ace","line":27,"in_reply_to":"7aa08908_d0a99525","updated":"2016-06-09 00:46:12.000000000","message":"\u003e we\u0027re possibly authenticating against multiple passwords\n\nYou could avoid that by setting currently-future expires_at to *now* when you do a change password operation, so that they\u0027re immediately expired.\n\nAs for upgrades, it\u0027d be pretty trivial to document a SQL command in the release notes to introduce expiring passwords (update password set expires_at\u003d(+90 days) where expires_at is null)","commit_id":"1fd49dbc8620177b0e6798d035319a0163da070b"}],"keystone/common/sql/migrate_repo/versions/104_add_new_password_columns.py":[{"author":{"_account_id":7725,"name":"David Stanek","email":"dstanek@dstanek.com","username":"dstanek"},"change_message_id":"d5f78f164cf8f35d643b8a6a670ae3c195379bd8","unresolved":false,"context_lines":[{"line_number":21,"context_line":"    # TODO(rderose): make created_at nullable\u003dFalse after data migration"},{"line_number":22,"context_line":"    created_at_column \u003d sql.Column(\u0027created_at\u0027, sql.DateTime(),"},{"line_number":23,"context_line":"                                   nullable\u003dTrue)"},{"line_number":24,"context_line":"    created_by_column \u003d sql.Column(\u0027created_by\u0027, sql.String(64), nullable\u003dTrue)"},{"line_number":25,"context_line":"    expires_at_column \u003d sql.Column(\u0027expires_at\u0027, sql.DateTime(), nullable\u003dTrue)"},{"line_number":26,"context_line":"    password_table.create_column(created_at_column)"},{"line_number":27,"context_line":"    password_table.create_column(created_by_column)"}],"source_content_type":"text/x-python","patch_set":20,"id":"bab6814e_3d830a58","line":24,"updated":"2016-05-19 19:49:34.000000000","message":"Should this be a FK to a user?","commit_id":"f7a777d42257f0372a7ad27d31d9dcb09deacf96"},{"author":{"_account_id":18338,"name":"Ron De Rose","email":"ronald.de.rose@intel.com","username":"derosenet"},"change_message_id":"700c7a113afac47f0bf91c0c3f2ce54a7c8e1cb1","unresolved":false,"context_lines":[{"line_number":21,"context_line":"    # TODO(rderose): make created_at nullable\u003dFalse after data migration"},{"line_number":22,"context_line":"    created_at_column \u003d sql.Column(\u0027created_at\u0027, sql.DateTime(),"},{"line_number":23,"context_line":"                                   nullable\u003dTrue)"},{"line_number":24,"context_line":"    created_by_column \u003d sql.Column(\u0027created_by\u0027, sql.String(64), nullable\u003dTrue)"},{"line_number":25,"context_line":"    expires_at_column \u003d sql.Column(\u0027expires_at\u0027, sql.DateTime(), nullable\u003dTrue)"},{"line_number":26,"context_line":"    password_table.create_column(created_at_column)"},{"line_number":27,"context_line":"    password_table.create_column(created_by_column)"}],"source_content_type":"text/x-python","patch_set":20,"id":"bab6814e_8381f0c5","line":24,"in_reply_to":"bab6814e_3d830a58","updated":"2016-05-19 23:15:13.000000000","message":"Done","commit_id":"f7a777d42257f0372a7ad27d31d9dcb09deacf96"},{"author":{"_account_id":18338,"name":"Ron De Rose","email":"ronald.de.rose@intel.com","username":"derosenet"},"change_message_id":"574dc991b23bb7ead7229b878633d504a0a53a59","unresolved":false,"context_lines":[{"line_number":21,"context_line":"    # TODO(rderose): make created_at nullable\u003dFalse after data migration"},{"line_number":22,"context_line":"    created_at_column \u003d sql.Column(\u0027created_at\u0027, sql.DateTime(),"},{"line_number":23,"context_line":"                                   nullable\u003dTrue)"},{"line_number":24,"context_line":"    created_by_column \u003d sql.Column(\u0027created_by\u0027, sql.String(64), nullable\u003dTrue)"},{"line_number":25,"context_line":"    expires_at_column \u003d sql.Column(\u0027expires_at\u0027, sql.DateTime(), nullable\u003dTrue)"},{"line_number":26,"context_line":"    password_table.create_column(created_at_column)"},{"line_number":27,"context_line":"    password_table.create_column(created_by_column)"}],"source_content_type":"text/x-python","patch_set":20,"id":"bab6814e_9d1cb614","line":24,"in_reply_to":"bab6814e_3d830a58","updated":"2016-05-19 19:52:56.000000000","message":"Yep, this should be.  Good catch.","commit_id":"f7a777d42257f0372a7ad27d31d9dcb09deacf96"}],"keystone/common/sql/migrate_repo/versions/104_add_password_date_columns.py":[{"author":{"_account_id":7725,"name":"David Stanek","email":"dstanek@dstanek.com","username":"dstanek"},"change_message_id":"908aba9f261ba1ace6686c91f817253fe72465e8","unresolved":false,"context_lines":[{"line_number":20,"context_line":"    meta.bind \u003d migrate_engine"},{"line_number":21,"context_line":""},{"line_number":22,"context_line":"    # add new password columns"},{"line_number":23,"context_line":"    created_at_column \u003d sql.Column(\u0027created_at\u0027, sql.DateTime(),"},{"line_number":24,"context_line":"                                   nullable\u003dTrue)"},{"line_number":25,"context_line":"    expires_at_column \u003d sql.Column(\u0027expires_at\u0027, sql.DateTime(),"},{"line_number":26,"context_line":"                                   nullable\u003dTrue)"}],"source_content_type":"text/x-python","patch_set":67,"id":"7aa08908_8b6609b9","line":23,"updated":"2016-06-13 15:44:44.000000000","message":"Any reason why we don\u0027t use a default?","commit_id":"98fcf223b42c985dbcc491aef9c17e1a84a4fa02"},{"author":{"_account_id":18338,"name":"Ron De Rose","email":"ronald.de.rose@intel.com","username":"derosenet"},"change_message_id":"f14b58756d1f6c682ac3f2a33313e31490792583","unresolved":false,"context_lines":[{"line_number":20,"context_line":"    meta.bind \u003d migrate_engine"},{"line_number":21,"context_line":""},{"line_number":22,"context_line":"    # add new password columns"},{"line_number":23,"context_line":"    created_at_column \u003d sql.Column(\u0027created_at\u0027, sql.DateTime(),"},{"line_number":24,"context_line":"                                   nullable\u003dTrue)"},{"line_number":25,"context_line":"    expires_at_column \u003d sql.Column(\u0027expires_at\u0027, sql.DateTime(),"},{"line_number":26,"context_line":"                                   nullable\u003dTrue)"}],"source_content_type":"text/x-python","patch_set":67,"id":"7aa08908_360c9ceb","line":23,"in_reply_to":"7aa08908_8b6609b9","updated":"2016-06-13 16:05:15.000000000","message":"Couldn\u0027t get a datetime default value to work; doesn\u0027t seem to be supported by all of the databases.","commit_id":"98fcf223b42c985dbcc491aef9c17e1a84a4fa02"},{"author":{"_account_id":5046,"name":"Lance Bragstad","email":"lbragstad@redhat.com","username":"ldbragst"},"change_message_id":"588bc47578bca8bb111265b566fc65a909b4d17a","unresolved":false,"context_lines":[{"line_number":22,"context_line":"    # add new password columns"},{"line_number":23,"context_line":"    created_at_column \u003d sql.Column(\u0027created_at\u0027, sql.DateTime(),"},{"line_number":24,"context_line":"                                   nullable\u003dTrue)"},{"line_number":25,"context_line":"    expires_at_column \u003d sql.Column(\u0027expires_at\u0027, sql.DateTime(),"},{"line_number":26,"context_line":"                                   nullable\u003dTrue)"},{"line_number":27,"context_line":"    password_table \u003d sql.Table(\u0027password\u0027, meta, autoload\u003dTrue)"},{"line_number":28,"context_line":"    password_table.create_column(created_at_column)"}],"source_content_type":"text/x-python","patch_set":67,"id":"7aa08908_8bd569e6","line":25,"updated":"2016-06-13 15:52:20.000000000","message":"The sql.DateTime() format might not persist subsecond accuracy in some backends by default (and it might for some others). Do we have any reason to be concerned by those cases? Do we want to override the sql.DateTime class with our own implementation that does an explicit behavior? Something like this - https://review.openstack.org/#/c/315735/2/keystone/common/sql/core.py,unified ?","commit_id":"98fcf223b42c985dbcc491aef9c17e1a84a4fa02"},{"author":{"_account_id":18338,"name":"Ron De Rose","email":"ronald.de.rose@intel.com","username":"derosenet"},"change_message_id":"6a4a785451de38be2d73e473c769cb71a8c7de70","unresolved":false,"context_lines":[{"line_number":22,"context_line":"    # add new password columns"},{"line_number":23,"context_line":"    created_at_column \u003d sql.Column(\u0027created_at\u0027, sql.DateTime(),"},{"line_number":24,"context_line":"                                   nullable\u003dTrue)"},{"line_number":25,"context_line":"    expires_at_column \u003d sql.Column(\u0027expires_at\u0027, sql.DateTime(),"},{"line_number":26,"context_line":"                                   nullable\u003dTrue)"},{"line_number":27,"context_line":"    password_table \u003d sql.Table(\u0027password\u0027, meta, autoload\u003dTrue)"},{"line_number":28,"context_line":"    password_table.create_column(created_at_column)"}],"source_content_type":"text/x-python","patch_set":67,"id":"7aa08908_822c23ad","line":25,"in_reply_to":"7aa08908_6c177045","updated":"2016-06-13 18:50:16.000000000","message":"Not that I can think of for this use case.","commit_id":"98fcf223b42c985dbcc491aef9c17e1a84a4fa02"},{"author":{"_account_id":18338,"name":"Ron De Rose","email":"ronald.de.rose@intel.com","username":"derosenet"},"change_message_id":"f14b58756d1f6c682ac3f2a33313e31490792583","unresolved":false,"context_lines":[{"line_number":22,"context_line":"    # add new password columns"},{"line_number":23,"context_line":"    created_at_column \u003d sql.Column(\u0027created_at\u0027, sql.DateTime(),"},{"line_number":24,"context_line":"                                   nullable\u003dTrue)"},{"line_number":25,"context_line":"    expires_at_column \u003d sql.Column(\u0027expires_at\u0027, sql.DateTime(),"},{"line_number":26,"context_line":"                                   nullable\u003dTrue)"},{"line_number":27,"context_line":"    password_table \u003d sql.Table(\u0027password\u0027, meta, autoload\u003dTrue)"},{"line_number":28,"context_line":"    password_table.create_column(created_at_column)"}],"source_content_type":"text/x-python","patch_set":67,"id":"7aa08908_96a750a6","line":25,"in_reply_to":"7aa08908_8bd569e6","updated":"2016-06-13 16:05:15.000000000","message":"Yeah, I don\u0027t think we need this.","commit_id":"98fcf223b42c985dbcc491aef9c17e1a84a4fa02"},{"author":{"_account_id":5046,"name":"Lance Bragstad","email":"lbragstad@redhat.com","username":"ldbragst"},"change_message_id":"e68fed2d380988820f1ed0f5d9dc6a7f3d7a6742","unresolved":false,"context_lines":[{"line_number":22,"context_line":"    # add new password columns"},{"line_number":23,"context_line":"    created_at_column \u003d sql.Column(\u0027created_at\u0027, sql.DateTime(),"},{"line_number":24,"context_line":"                                   nullable\u003dTrue)"},{"line_number":25,"context_line":"    expires_at_column \u003d sql.Column(\u0027expires_at\u0027, sql.DateTime(),"},{"line_number":26,"context_line":"                                   nullable\u003dTrue)"},{"line_number":27,"context_line":"    password_table \u003d sql.Table(\u0027password\u0027, meta, autoload\u003dTrue)"},{"line_number":28,"context_line":"    password_table.create_column(created_at_column)"}],"source_content_type":"text/x-python","patch_set":67,"id":"7aa08908_6c177045","line":25,"in_reply_to":"7aa08908_96a750a6","updated":"2016-06-13 17:44:04.000000000","message":"We should never have a case where subsecond accuracy matters? Just double checking. This will also be subject to subsecond truncation in certain versions of SQL.","commit_id":"98fcf223b42c985dbcc491aef9c17e1a84a4fa02"},{"author":{"_account_id":4,"name":"Dolph Mathews","email":"dolph.mathews@gmail.com","username":"dolph"},"change_message_id":"6bbdc43c5c505f0223adda42795652ca91c7d19e","unresolved":false,"context_lines":[{"line_number":19,"context_line":"    meta \u003d sql.MetaData()"},{"line_number":20,"context_line":"    meta.bind \u003d migrate_engine"},{"line_number":21,"context_line":""},{"line_number":22,"context_line":"    created_at \u003d sql.Column(\u0027created_at\u0027, sql.DateTime(), nullable\u003dTrue)"},{"line_number":23,"context_line":"    expires_at \u003d sql.Column(\u0027expires_at\u0027, sql.DateTime(), nullable\u003dTrue)"},{"line_number":24,"context_line":"    password_table \u003d sql.Table(\u0027password\u0027, meta, autoload\u003dTrue)"},{"line_number":25,"context_line":"    password_table.create_column(created_at)"}],"source_content_type":"text/x-python","patch_set":84,"id":"7aa08908_c927c761","line":22,"updated":"2016-06-16 15:22:09.000000000","message":"Always nice to see migrations treated uniformly across different databases engines.","commit_id":"c1e583815bd9e8485c11b881eb0e67fa7b8fcbe2"},{"author":{"_account_id":5707,"name":"Henry Nash","email":"henryn@linux.vnet.ibm.com","username":"henry-nash"},"change_message_id":"88a7300b0fb8bfa20cbf871982fe2199397accc7","unresolved":false,"context_lines":[{"line_number":19,"context_line":"    meta \u003d sql.MetaData()"},{"line_number":20,"context_line":"    meta.bind \u003d migrate_engine"},{"line_number":21,"context_line":""},{"line_number":22,"context_line":"    created_at \u003d sql.Column(\u0027created_at\u0027, sql.DateTime(), nullable\u003dTrue)"},{"line_number":23,"context_line":"    expires_at \u003d sql.Column(\u0027expires_at\u0027, sql.DateTime(), nullable\u003dTrue)"},{"line_number":24,"context_line":"    password_table \u003d sql.Table(\u0027password\u0027, meta, autoload\u003dTrue)"},{"line_number":25,"context_line":"    password_table.create_column(created_at)"}],"source_content_type":"text/x-python","patch_set":87,"id":"5a9d85d2_eb3aa9cc","line":22,"range":{"start_line":22,"start_character":58,"end_line":22,"end_character":71},"updated":"2016-06-20 15:04:06.000000000","message":"so this doesn\u0027t match what\u0027s in the sql model...did you mean to update this to be non-nullable at the end of this migration?","commit_id":"40817c54bda7634cc4745b14ea43bd3cfb563abb"},{"author":{"_account_id":5707,"name":"Henry Nash","email":"henryn@linux.vnet.ibm.com","username":"henry-nash"},"change_message_id":"f3af7e35c537d3b4dee140bc6e42985aa59887ad","unresolved":false,"context_lines":[{"line_number":19,"context_line":"    meta \u003d sql.MetaData()"},{"line_number":20,"context_line":"    meta.bind \u003d migrate_engine"},{"line_number":21,"context_line":""},{"line_number":22,"context_line":"    created_at \u003d sql.Column(\u0027created_at\u0027, sql.DateTime(), nullable\u003dTrue)"},{"line_number":23,"context_line":"    expires_at \u003d sql.Column(\u0027expires_at\u0027, sql.DateTime(), nullable\u003dTrue)"},{"line_number":24,"context_line":"    password_table \u003d sql.Table(\u0027password\u0027, meta, autoload\u003dTrue)"},{"line_number":25,"context_line":"    password_table.create_column(created_at)"}],"source_content_type":"text/x-python","patch_set":87,"id":"5a9d85d2_2691889a","line":22,"range":{"start_line":22,"start_character":58,"end_line":22,"end_character":71},"in_reply_to":"5a9d85d2_0b7575f8","updated":"2016-06-20 15:18:26.000000000","message":"So the rolling upgrade test allows you to add migrations to a list of \"migrations that are actually safe but don\u0027t look like they are\" (!) I think this would definitely qualify, if you would prefer to update the column...","commit_id":"40817c54bda7634cc4745b14ea43bd3cfb563abb"},{"author":{"_account_id":18338,"name":"Ron De Rose","email":"ronald.de.rose@intel.com","username":"derosenet"},"change_message_id":"3c2c3015cc24feed3973f474d9eb6c4ba79c2a72","unresolved":false,"context_lines":[{"line_number":19,"context_line":"    meta \u003d sql.MetaData()"},{"line_number":20,"context_line":"    meta.bind \u003d migrate_engine"},{"line_number":21,"context_line":""},{"line_number":22,"context_line":"    created_at \u003d sql.Column(\u0027created_at\u0027, sql.DateTime(), nullable\u003dTrue)"},{"line_number":23,"context_line":"    expires_at \u003d sql.Column(\u0027expires_at\u0027, sql.DateTime(), nullable\u003dTrue)"},{"line_number":24,"context_line":"    password_table \u003d sql.Table(\u0027password\u0027, meta, autoload\u003dTrue)"},{"line_number":25,"context_line":"    password_table.create_column(created_at)"}],"source_content_type":"text/x-python","patch_set":87,"id":"5a9d85d2_0b7575f8","line":22,"range":{"start_line":22,"start_character":58,"end_line":22,"end_character":71},"in_reply_to":"5a9d85d2_eb3aa9cc","updated":"2016-06-20 15:09:38.000000000","message":"Ideally, I would like to change column to be not nullable after the migration. However, the rolling upgrades gate prevents column changes. Thus, this purposely does not match the sql model.","commit_id":"40817c54bda7634cc4745b14ea43bd3cfb563abb"}],"keystone/identity/backends/sql.py":[{"author":{"_account_id":5046,"name":"Lance Bragstad","email":"lbragstad@redhat.com","username":"ldbragst"},"change_message_id":"215d6f0d5e21503a1fa256e06c6e018982bfcd0f","unresolved":false,"context_lines":[{"line_number":133,"context_line":"    local_user_id \u003d sql.Column(sql.Integer, sql.ForeignKey(\u0027local_user.id\u0027,"},{"line_number":134,"context_line":"                               ondelete\u003d\u0027CASCADE\u0027))"},{"line_number":135,"context_line":"    password \u003d sql.Column(sql.String(128))"},{"line_number":136,"context_line":"    created_at \u003d sql.Column(sql.DateTime, nullable\u003dFalse,"},{"line_number":137,"context_line":"                            default\u003ddatetime.datetime.utcnow)"},{"line_number":138,"context_line":"    created_by \u003d sql.Column(sql.String(64), sql.ForeignKey(\u0027user.id\u0027))"},{"line_number":139,"context_line":"    expires_at \u003d sql.Column(sql.DateTime)"}],"source_content_type":"text/x-python","patch_set":29,"id":"bab6814e_a1b97a7b","line":136,"updated":"2016-05-20 09:54:41.000000000","message":"This reminds me - I wonder if we should do something like this (https://review.openstack.org/#/c/315735/2/keystone/common/sql/core.py) with the DateTime object?\n\nProbably something best done in a separate patch but trying to understand the ramifications if we merge this and decide to change it later.","commit_id":"db59100adfcaf3c09ccfa068a648c6d2f63b20b6"},{"author":{"_account_id":18338,"name":"Ron De Rose","email":"ronald.de.rose@intel.com","username":"derosenet"},"change_message_id":"fc7459a69f9daf7460c28a13bb153ee332d4f986","unresolved":false,"context_lines":[{"line_number":133,"context_line":"    local_user_id \u003d sql.Column(sql.Integer, sql.ForeignKey(\u0027local_user.id\u0027,"},{"line_number":134,"context_line":"                               ondelete\u003d\u0027CASCADE\u0027))"},{"line_number":135,"context_line":"    password \u003d sql.Column(sql.String(128))"},{"line_number":136,"context_line":"    created_at \u003d sql.Column(sql.DateTime, nullable\u003dFalse,"},{"line_number":137,"context_line":"                            default\u003ddatetime.datetime.utcnow)"},{"line_number":138,"context_line":"    created_by \u003d sql.Column(sql.String(64), sql.ForeignKey(\u0027user.id\u0027))"},{"line_number":139,"context_line":"    expires_at \u003d sql.Column(sql.DateTime)"}],"source_content_type":"text/x-python","patch_set":29,"id":"9abb7d3a_fc711e0d","line":136,"in_reply_to":"bab6814e_a1b97a7b","updated":"2016-06-01 16:45:47.000000000","message":"Yeah, I suppose we could change it later on.  And I\u0027m not so concerned with datetime rounding issues for this feature.","commit_id":"db59100adfcaf3c09ccfa068a648c6d2f63b20b6"}],"keystone/identity/backends/sql_model.py":[{"author":{"_account_id":7725,"name":"David Stanek","email":"dstanek@dstanek.com","username":"dstanek"},"change_message_id":"d13ace1848a65dc6dc169bcc35332e2d08a69381","unresolved":false,"context_lines":[{"line_number":12,"context_line":"# License for the specific language governing permissions and limitations"},{"line_number":13,"context_line":"# under the License."},{"line_number":14,"context_line":""},{"line_number":15,"context_line":"import datetime"},{"line_number":16,"context_line":"import sqlalchemy"},{"line_number":17,"context_line":"from sqlalchemy.ext.hybrid import hybrid_property"},{"line_number":18,"context_line":"from sqlalchemy import orm"}],"source_content_type":"text/x-python","patch_set":46,"id":"9abb7d3a_3b392bd8","line":15,"updated":"2016-05-31 16:47:33.000000000","message":"Should be a newline after this import.","commit_id":"aea09909d2657911fd3176b1b2612d8b154d1ffa"},{"author":{"_account_id":7725,"name":"David Stanek","email":"dstanek@dstanek.com","username":"dstanek"},"change_message_id":"5e40cf2e1ffb9c2f7edecc5f74720c6a5e881420","unresolved":false,"context_lines":[{"line_number":12,"context_line":"# License for the specific language governing permissions and limitations"},{"line_number":13,"context_line":"# under the License."},{"line_number":14,"context_line":""},{"line_number":15,"context_line":"import datetime"},{"line_number":16,"context_line":"import sqlalchemy"},{"line_number":17,"context_line":"from sqlalchemy.ext.hybrid import hybrid_property"},{"line_number":18,"context_line":"from sqlalchemy import orm"}],"source_content_type":"text/x-python","patch_set":48,"id":"7aa08908_63e25905","line":15,"updated":"2016-06-06 12:15:48.000000000","message":"Needs to follow hacking rules: http://docs.openstack.org/developer/hacking/#import-order-template","commit_id":"10f620999bc1d06b8200dc98166b4fb3005c8b10"},{"author":{"_account_id":18338,"name":"Ron De Rose","email":"ronald.de.rose@intel.com","username":"derosenet"},"change_message_id":"d271bd3e5d4020a926f146ced1d63d16b9677047","unresolved":false,"context_lines":[{"line_number":12,"context_line":"# License for the specific language governing permissions and limitations"},{"line_number":13,"context_line":"# under the License."},{"line_number":14,"context_line":""},{"line_number":15,"context_line":"import datetime"},{"line_number":16,"context_line":"import sqlalchemy"},{"line_number":17,"context_line":"from sqlalchemy.ext.hybrid import hybrid_property"},{"line_number":18,"context_line":"from sqlalchemy import orm"}],"source_content_type":"text/x-python","patch_set":48,"id":"7aa08908_5430b201","line":15,"in_reply_to":"7aa08908_63e25905","updated":"2016-06-06 13:50:21.000000000","message":"Done","commit_id":"10f620999bc1d06b8200dc98166b4fb3005c8b10"},{"author":{"_account_id":7725,"name":"David Stanek","email":"dstanek@dstanek.com","username":"dstanek"},"change_message_id":"5e40cf2e1ffb9c2f7edecc5f74720c6a5e881420","unresolved":false,"context_lines":[{"line_number":129,"context_line":"                               ondelete\u003d\u0027CASCADE\u0027))"},{"line_number":130,"context_line":"    password \u003d sql.Column(sql.String(128))"},{"line_number":131,"context_line":"    created_at \u003d sql.Column(sql.DateTime, nullable\u003dFalse,"},{"line_number":132,"context_line":"                            default\u003ddatetime.datetime.utcnow)"},{"line_number":133,"context_line":"    expired \u003d sql.Column(sql.Boolean, default\u003dFalse)"},{"line_number":134,"context_line":""},{"line_number":135,"context_line":""}],"source_content_type":"text/x-python","patch_set":48,"id":"7aa08908_83994571","line":132,"updated":"2016-06-06 12:15:48.000000000","message":"This doesn\u0027t match the migration. Nullable is False here, but True there.","commit_id":"10f620999bc1d06b8200dc98166b4fb3005c8b10"},{"author":{"_account_id":18338,"name":"Ron De Rose","email":"ronald.de.rose@intel.com","username":"derosenet"},"change_message_id":"d271bd3e5d4020a926f146ced1d63d16b9677047","unresolved":false,"context_lines":[{"line_number":129,"context_line":"                               ondelete\u003d\u0027CASCADE\u0027))"},{"line_number":130,"context_line":"    password \u003d sql.Column(sql.String(128))"},{"line_number":131,"context_line":"    created_at \u003d sql.Column(sql.DateTime, nullable\u003dFalse,"},{"line_number":132,"context_line":"                            default\u003ddatetime.datetime.utcnow)"},{"line_number":133,"context_line":"    expired \u003d sql.Column(sql.Boolean, default\u003dFalse)"},{"line_number":134,"context_line":""},{"line_number":135,"context_line":""}],"source_content_type":"text/x-python","patch_set":48,"id":"7aa08908_5407121c","line":132,"in_reply_to":"7aa08908_83994571","updated":"2016-06-06 13:50:21.000000000","message":"Done","commit_id":"10f620999bc1d06b8200dc98166b4fb3005c8b10"},{"author":{"_account_id":5707,"name":"Henry Nash","email":"henryn@linux.vnet.ibm.com","username":"henry-nash"},"change_message_id":"857bbecd7be10696317cd2790251b141e3d06a33","unresolved":false,"context_lines":[{"line_number":130,"context_line":"    password \u003d sql.Column(sql.String(128))"},{"line_number":131,"context_line":"    created_at \u003d sql.Column(sql.DateTime, nullable\u003dFalse,"},{"line_number":132,"context_line":"                            default\u003ddatetime.datetime.utcnow)"},{"line_number":133,"context_line":"    expired \u003d sql.Column(sql.Boolean, default\u003dFalse)"},{"line_number":134,"context_line":""},{"line_number":135,"context_line":""},{"line_number":136,"context_line":"class FederatedUser(sql.ModelBase, sql.ModelDictMixin):"}],"source_content_type":"text/x-python","patch_set":48,"id":"7aa08908_0691eef0","line":133,"range":{"start_line":133,"start_character":25,"end_line":133,"end_character":52},"updated":"2016-06-06 09:25:28.000000000","message":"in all other examples (where we have added a server default), we have also specified it here....I\u0027ve never been entirely sure if this is required, but that has certainly been our convention.","commit_id":"10f620999bc1d06b8200dc98166b4fb3005c8b10"},{"author":{"_account_id":18338,"name":"Ron De Rose","email":"ronald.de.rose@intel.com","username":"derosenet"},"change_message_id":"d271bd3e5d4020a926f146ced1d63d16b9677047","unresolved":false,"context_lines":[{"line_number":130,"context_line":"    password \u003d sql.Column(sql.String(128))"},{"line_number":131,"context_line":"    created_at \u003d sql.Column(sql.DateTime, nullable\u003dFalse,"},{"line_number":132,"context_line":"                            default\u003ddatetime.datetime.utcnow)"},{"line_number":133,"context_line":"    expired \u003d sql.Column(sql.Boolean, default\u003dFalse)"},{"line_number":134,"context_line":""},{"line_number":135,"context_line":""},{"line_number":136,"context_line":"class FederatedUser(sql.ModelBase, sql.ModelDictMixin):"}],"source_content_type":"text/x-python","patch_set":48,"id":"7aa08908_efc10782","line":133,"range":{"start_line":133,"start_character":25,"end_line":133,"end_character":52},"in_reply_to":"7aa08908_0691eef0","updated":"2016-06-06 13:50:21.000000000","message":"Done","commit_id":"10f620999bc1d06b8200dc98166b4fb3005c8b10"},{"author":{"_account_id":4,"name":"Dolph Mathews","email":"dolph.mathews@gmail.com","username":"dolph"},"change_message_id":"281516ed5eb1e0995d866d038182400f9d967ab7","unresolved":false,"context_lines":[{"line_number":37,"context_line":"                                       lazy\u003d\u0027subquery\u0027,"},{"line_number":38,"context_line":"                                       cascade\u003d\u0027all,delete-orphan\u0027,"},{"line_number":39,"context_line":"                                       backref\u003d\u0027user\u0027)"},{"line_number":40,"context_line":"    nonlocal_users \u003d orm.relationship(\u0027NonLocalUser\u0027,"},{"line_number":41,"context_line":"                                      single_parent\u003dTrue,"},{"line_number":42,"context_line":"                                      lazy\u003d\u0027subquery\u0027,"},{"line_number":43,"context_line":"                                      cascade\u003d\u0027all,delete-orphan\u0027,"}],"source_content_type":"text/x-python","patch_set":67,"id":"7aa08908_d8ff3eff","line":40,"updated":"2016-06-13 20:16:19.000000000","message":"remote? *shrug*","commit_id":"98fcf223b42c985dbcc491aef9c17e1a84a4fa02"},{"author":{"_account_id":18338,"name":"Ron De Rose","email":"ronald.de.rose@intel.com","username":"derosenet"},"change_message_id":"68dd10d823bb473798120ad5801100e76288cd83","unresolved":false,"context_lines":[{"line_number":37,"context_line":"                                       lazy\u003d\u0027subquery\u0027,"},{"line_number":38,"context_line":"                                       cascade\u003d\u0027all,delete-orphan\u0027,"},{"line_number":39,"context_line":"                                       backref\u003d\u0027user\u0027)"},{"line_number":40,"context_line":"    nonlocal_users \u003d orm.relationship(\u0027NonLocalUser\u0027,"},{"line_number":41,"context_line":"                                      single_parent\u003dTrue,"},{"line_number":42,"context_line":"                                      lazy\u003d\u0027subquery\u0027,"},{"line_number":43,"context_line":"                                      cascade\u003d\u0027all,delete-orphan\u0027,"}],"source_content_type":"text/x-python","patch_set":67,"id":"7aa08908_ea74d5fe","line":40,"in_reply_to":"7aa08908_d8ff3eff","updated":"2016-06-14 00:31:28.000000000","message":"Yeah, that was part of shadowing ldap. I struggled to come up with a good table name for not only shadowing ldap, but custom drivers as well.","commit_id":"98fcf223b42c985dbcc491aef9c17e1a84a4fa02"},{"author":{"_account_id":4,"name":"Dolph Mathews","email":"dolph.mathews@gmail.com","username":"dolph"},"change_message_id":"281516ed5eb1e0995d866d038182400f9d967ab7","unresolved":false,"context_lines":[{"line_number":68,"context_line":"    # password properties"},{"line_number":69,"context_line":"    @hybrid_property"},{"line_number":70,"context_line":"    def password_ref(self):"},{"line_number":71,"context_line":"        \"\"\"Return the last password.\"\"\""},{"line_number":72,"context_line":"        if self.local_user and self.local_user.passwords:"},{"line_number":73,"context_line":"            return self.local_user.passwords[-1]"},{"line_number":74,"context_line":"        return None"}],"source_content_type":"text/x-python","patch_set":67,"id":"7aa08908_183ee68a","line":71,"updated":"2016-06-13 20:16:19.000000000","message":"s/last/current/ ?","commit_id":"98fcf223b42c985dbcc491aef9c17e1a84a4fa02"},{"author":{"_account_id":4,"name":"Dolph Mathews","email":"dolph.mathews@gmail.com","username":"dolph"},"change_message_id":"281516ed5eb1e0995d866d038182400f9d967ab7","unresolved":false,"context_lines":[{"line_number":71,"context_line":"        \"\"\"Return the last password.\"\"\""},{"line_number":72,"context_line":"        if self.local_user and self.local_user.passwords:"},{"line_number":73,"context_line":"            return self.local_user.passwords[-1]"},{"line_number":74,"context_line":"        return None"},{"line_number":75,"context_line":""},{"line_number":76,"context_line":"    @hybrid_property"},{"line_number":77,"context_line":"    def password(self):"}],"source_content_type":"text/x-python","patch_set":67,"id":"7aa08908_58c50e8c","line":74,"updated":"2016-06-13 20:16:19.000000000","message":"nit: This return line doesn\u0027t actually do anything in python, as all functions return None by default.","commit_id":"98fcf223b42c985dbcc491aef9c17e1a84a4fa02"},{"author":{"_account_id":7725,"name":"David Stanek","email":"dstanek@dstanek.com","username":"dstanek"},"change_message_id":"908aba9f261ba1ace6686c91f817253fe72465e8","unresolved":false,"context_lines":[{"line_number":87,"context_line":""},{"line_number":88,"context_line":"    @password.setter"},{"line_number":89,"context_line":"    def password(self, value):"},{"line_number":90,"context_line":"        now \u003d datetime.datetime.utcnow()"},{"line_number":91,"context_line":"        if not self.local_user:"},{"line_number":92,"context_line":"            self.local_user \u003d LocalUser()"},{"line_number":93,"context_line":"        # set all previous passwords to be expired"}],"source_content_type":"text/x-python","patch_set":67,"id":"7aa08908_c5c120e6","line":90,"updated":"2016-06-13 15:44:44.000000000","message":"Why are we not letting the database set the default?","commit_id":"98fcf223b42c985dbcc491aef9c17e1a84a4fa02"},{"author":{"_account_id":18338,"name":"Ron De Rose","email":"ronald.de.rose@intel.com","username":"derosenet"},"change_message_id":"f14b58756d1f6c682ac3f2a33313e31490792583","unresolved":false,"context_lines":[{"line_number":87,"context_line":""},{"line_number":88,"context_line":"    @password.setter"},{"line_number":89,"context_line":"    def password(self, value):"},{"line_number":90,"context_line":"        now \u003d datetime.datetime.utcnow()"},{"line_number":91,"context_line":"        if not self.local_user:"},{"line_number":92,"context_line":"            self.local_user \u003d LocalUser()"},{"line_number":93,"context_line":"        # set all previous passwords to be expired"}],"source_content_type":"text/x-python","patch_set":67,"id":"7aa08908_7640e4a5","line":90,"in_reply_to":"7aa08908_c5c120e6","updated":"2016-06-13 16:05:15.000000000","message":"Mentioned this is the previous comment, having a default datetime value is not supported among all of the databases (at least I could not get this to work).","commit_id":"98fcf223b42c985dbcc491aef9c17e1a84a4fa02"},{"author":{"_account_id":5046,"name":"Lance Bragstad","email":"lbragstad@redhat.com","username":"ldbragst"},"change_message_id":"588bc47578bca8bb111265b566fc65a909b4d17a","unresolved":false,"context_lines":[{"line_number":87,"context_line":""},{"line_number":88,"context_line":"    @password.setter"},{"line_number":89,"context_line":"    def password(self, value):"},{"line_number":90,"context_line":"        now \u003d datetime.datetime.utcnow()"},{"line_number":91,"context_line":"        if not self.local_user:"},{"line_number":92,"context_line":"            self.local_user \u003d LocalUser()"},{"line_number":93,"context_line":"        # set all previous passwords to be expired"}],"source_content_type":"text/x-python","patch_set":67,"id":"7aa08908_ab74a5fd","line":90,"in_reply_to":"7aa08908_c5c120e6","updated":"2016-06-13 15:52:20.000000000","message":"You mean letting the database determine the created_at time?","commit_id":"98fcf223b42c985dbcc491aef9c17e1a84a4fa02"},{"author":{"_account_id":4,"name":"Dolph Mathews","email":"dolph.mathews@gmail.com","username":"dolph"},"change_message_id":"6bbdc43c5c505f0223adda42795652ca91c7d19e","unresolved":false,"context_lines":[{"line_number":67,"context_line":""},{"line_number":68,"context_line":"    # password properties"},{"line_number":69,"context_line":"    @hybrid_property"},{"line_number":70,"context_line":"    def password_ref(self):"},{"line_number":71,"context_line":"        \"\"\"Return the current password.\"\"\""},{"line_number":72,"context_line":"        if self.local_user and self.local_user.passwords:"},{"line_number":73,"context_line":"            return self.local_user.passwords[-1]"}],"source_content_type":"text/x-python","patch_set":84,"id":"7aa08908_29948b42","line":70,"updated":"2016-06-16 15:22:09.000000000","message":"nice refactor","commit_id":"c1e583815bd9e8485c11b881eb0e67fa7b8fcbe2"},{"author":{"_account_id":4,"name":"Dolph Mathews","email":"dolph.mathews@gmail.com","username":"dolph"},"change_message_id":"6bbdc43c5c505f0223adda42795652ca91c7d19e","unresolved":false,"context_lines":[{"line_number":95,"context_line":"                ref.expires_at \u003d now"},{"line_number":96,"context_line":"        new_password_ref \u003d Password()"},{"line_number":97,"context_line":"        new_password_ref.password \u003d value"},{"line_number":98,"context_line":"        new_password_ref.created_at \u003d now"},{"line_number":99,"context_line":"        self.local_user.passwords.append(new_password_ref)"},{"line_number":100,"context_line":""},{"line_number":101,"context_line":"    @password.expression"}],"source_content_type":"text/x-python","patch_set":84,"id":"7aa08908_e9fc4374","line":98,"updated":"2016-06-16 15:22:09.000000000","message":"Does oslo.db have a way to manage this column for you?","commit_id":"c1e583815bd9e8485c11b881eb0e67fa7b8fcbe2"},{"author":{"_account_id":4,"name":"Dolph Mathews","email":"dolph.mathews@gmail.com","username":"dolph"},"change_message_id":"e4fd51a533b8f8b5358080a2307aadcef71bc8cd","unresolved":false,"context_lines":[{"line_number":95,"context_line":"                ref.expires_at \u003d now"},{"line_number":96,"context_line":"        new_password_ref \u003d Password()"},{"line_number":97,"context_line":"        new_password_ref.password \u003d value"},{"line_number":98,"context_line":"        new_password_ref.created_at \u003d now"},{"line_number":99,"context_line":"        self.local_user.passwords.append(new_password_ref)"},{"line_number":100,"context_line":""},{"line_number":101,"context_line":"    @password.expression"}],"source_content_type":"text/x-python","patch_set":84,"id":"7aa08908_dbecae94","line":98,"in_reply_to":"7aa08908_bbbba2e3","updated":"2016-06-16 15:36:46.000000000","message":"Conversely, does it need to be set explicitly here / can we not rely on the column\u0027s default?","commit_id":"c1e583815bd9e8485c11b881eb0e67fa7b8fcbe2"},{"author":{"_account_id":5046,"name":"Lance Bragstad","email":"lbragstad@redhat.com","username":"ldbragst"},"change_message_id":"6c8e3fbf139379e9195a00696ff13c15ff688d0c","unresolved":false,"context_lines":[{"line_number":95,"context_line":"                ref.expires_at \u003d now"},{"line_number":96,"context_line":"        new_password_ref \u003d Password()"},{"line_number":97,"context_line":"        new_password_ref.password \u003d value"},{"line_number":98,"context_line":"        new_password_ref.created_at \u003d now"},{"line_number":99,"context_line":"        self.local_user.passwords.append(new_password_ref)"},{"line_number":100,"context_line":""},{"line_number":101,"context_line":"    @password.expression"}],"source_content_type":"text/x-python","patch_set":84,"id":"7aa08908_db482e8d","line":98,"in_reply_to":"7aa08908_dbecae94","updated":"2016-06-16 15:38:58.000000000","message":"I think we could totally rely on the column\u0027s default, but having it set here makes it closer to the expires_at of the previous password. Is that something we need to think about here too?","commit_id":"c1e583815bd9e8485c11b881eb0e67fa7b8fcbe2"},{"author":{"_account_id":18338,"name":"Ron De Rose","email":"ronald.de.rose@intel.com","username":"derosenet"},"change_message_id":"83b0b472c9e53f4322cc4ab6e737609e049c52e8","unresolved":false,"context_lines":[{"line_number":95,"context_line":"                ref.expires_at \u003d now"},{"line_number":96,"context_line":"        new_password_ref \u003d Password()"},{"line_number":97,"context_line":"        new_password_ref.password \u003d value"},{"line_number":98,"context_line":"        new_password_ref.created_at \u003d now"},{"line_number":99,"context_line":"        self.local_user.passwords.append(new_password_ref)"},{"line_number":100,"context_line":""},{"line_number":101,"context_line":"    @password.expression"}],"source_content_type":"text/x-python","patch_set":84,"id":"7aa08908_bbbba2e3","line":98,"in_reply_to":"7aa08908_e9fc4374","updated":"2016-06-16 15:32:04.000000000","message":"Not sure...","commit_id":"c1e583815bd9e8485c11b881eb0e67fa7b8fcbe2"},{"author":{"_account_id":5046,"name":"Lance Bragstad","email":"lbragstad@redhat.com","username":"ldbragst"},"change_message_id":"3e286da8a9e98596a6c867a0e7462f8862dea612","unresolved":false,"context_lines":[{"line_number":155,"context_line":"                               ondelete\u003d\u0027CASCADE\u0027))"},{"line_number":156,"context_line":"    password \u003d sql.Column(sql.String(128))"},{"line_number":157,"context_line":"    created_at \u003d sql.Column(sql.DateTime, nullable\u003dFalse,"},{"line_number":158,"context_line":"                            default\u003ddatetime.datetime.utcnow)"},{"line_number":159,"context_line":"    expires_at \u003d sql.Column(sql.DateTime, nullable\u003dTrue)"},{"line_number":160,"context_line":""},{"line_number":161,"context_line":""}],"source_content_type":"text/x-python","patch_set":84,"id":"7aa08908_bb90c243","line":158,"updated":"2016-06-16 15:32:49.000000000","message":"We could almost add a comment here saying that this is a safe guard against not setting create_at. But totally something that can be done in a follow up patch.","commit_id":"c1e583815bd9e8485c11b881eb0e67fa7b8fcbe2"},{"author":{"_account_id":18338,"name":"Ron De Rose","email":"ronald.de.rose@intel.com","username":"derosenet"},"change_message_id":"f9163a29e553a80b9a4e99310e0728656bbcf9b4","unresolved":false,"context_lines":[{"line_number":155,"context_line":"                               ondelete\u003d\u0027CASCADE\u0027))"},{"line_number":156,"context_line":"    password \u003d sql.Column(sql.String(128))"},{"line_number":157,"context_line":"    created_at \u003d sql.Column(sql.DateTime, nullable\u003dFalse,"},{"line_number":158,"context_line":"                            default\u003ddatetime.datetime.utcnow)"},{"line_number":159,"context_line":"    expires_at \u003d sql.Column(sql.DateTime, nullable\u003dTrue)"},{"line_number":160,"context_line":""},{"line_number":161,"context_line":""}],"source_content_type":"text/x-python","patch_set":84,"id":"7aa08908_1e7c591f","line":158,"in_reply_to":"7aa08908_bb90c243","updated":"2016-06-16 23:59:27.000000000","message":"Done","commit_id":"c1e583815bd9e8485c11b881eb0e67fa7b8fcbe2"}],"keystone/tests/unit/test_sql_upgrade.py":[{"author":{"_account_id":5707,"name":"Henry Nash","email":"henryn@linux.vnet.ibm.com","username":"henry-nash"},"change_message_id":"4648b866f8f322ac58017599890fae33b9721e82","unresolved":false,"context_lines":[{"line_number":1191,"context_line":"                                          autoload\u003dTrue)"},{"line_number":1192,"context_line":"        null_created_at_cnt \u003d ("},{"line_number":1193,"context_line":"            session.query(password_table).filter_by(created_at\u003dNone).count())"},{"line_number":1194,"context_line":"        self.assertTrue(null_created_at_cnt \u003d\u003d 0)"},{"line_number":1195,"context_line":""},{"line_number":1196,"context_line":""},{"line_number":1197,"context_line":"class MySQLOpportunisticUpgradeTestCase(SqlUpgradeTests):"}],"source_content_type":"text/x-python","patch_set":67,"id":"7aa08908_8a8095f8","line":1194,"range":{"start_line":1194,"start_character":8,"end_line":1194,"end_character":49},"updated":"2016-06-14 12:40:05.000000000","message":"do we know if there were any rows in there already? if no rows, then this is kind of guaranteed to be zero....","commit_id":"98fcf223b42c985dbcc491aef9c17e1a84a4fa02"},{"author":{"_account_id":5707,"name":"Henry Nash","email":"henryn@linux.vnet.ibm.com","username":"henry-nash"},"change_message_id":"4c57538fb9245b495b4c3c1d5e659536c0c8fd31","unresolved":false,"context_lines":[{"line_number":1186,"context_line":"                                 \u0027password\u0027,"},{"line_number":1187,"context_line":"                                 \u0027created_at\u0027,"},{"line_number":1188,"context_line":"                                 \u0027expires_at\u0027])"},{"line_number":1189,"context_line":""},{"line_number":1190,"context_line":""},{"line_number":1191,"context_line":"class MySQLOpportunisticUpgradeTestCase(SqlUpgradeTests):"},{"line_number":1192,"context_line":"    FIXTURE \u003d test_base.MySQLOpportunisticFixture"}],"source_content_type":"text/x-python","patch_set":80,"id":"7aa08908_7baf8b2b","line":1189,"updated":"2016-06-16 11:07:54.000000000","message":"I think it would be worth have some rows in here pre-migration and making sure their create_at and expires_at values are as expected.","commit_id":"7794057246753f6ceb57d7dab1b7275a32e082a0"},{"author":{"_account_id":18338,"name":"Ron De Rose","email":"ronald.de.rose@intel.com","username":"derosenet"},"change_message_id":"ba3b3396e304d43affe58028df2b5a685ada534b","unresolved":false,"context_lines":[{"line_number":1186,"context_line":"                                 \u0027password\u0027,"},{"line_number":1187,"context_line":"                                 \u0027created_at\u0027,"},{"line_number":1188,"context_line":"                                 \u0027expires_at\u0027])"},{"line_number":1189,"context_line":""},{"line_number":1190,"context_line":""},{"line_number":1191,"context_line":"class MySQLOpportunisticUpgradeTestCase(SqlUpgradeTests):"},{"line_number":1192,"context_line":"    FIXTURE \u003d test_base.MySQLOpportunisticFixture"}],"source_content_type":"text/x-python","patch_set":80,"id":"5a9d85d2_80466421","line":1189,"in_reply_to":"7aa08908_7baf8b2b","updated":"2016-06-20 14:38:58.000000000","message":"Done","commit_id":"7794057246753f6ceb57d7dab1b7275a32e082a0"},{"author":{"_account_id":4,"name":"Dolph Mathews","email":"dolph.mathews@gmail.com","username":"dolph"},"change_message_id":"6bbdc43c5c505f0223adda42795652ca91c7d19e","unresolved":false,"context_lines":[{"line_number":1191,"context_line":"                                          autoload\u003dTrue)"},{"line_number":1192,"context_line":"        null_created_at_cnt \u003d ("},{"line_number":1193,"context_line":"            session.query(password_table).filter_by(created_at\u003dNone).count())"},{"line_number":1194,"context_line":"        self.assertTrue(null_created_at_cnt \u003d\u003d 0)"},{"line_number":1195,"context_line":""},{"line_number":1196,"context_line":""},{"line_number":1197,"context_line":"class MySQLOpportunisticUpgradeTestCase(SqlUpgradeTests):"}],"source_content_type":"text/x-python","patch_set":84,"id":"7aa08908_4971170c","line":1194,"updated":"2016-06-16 15:22:09.000000000","message":"This would be a stronger test if the table contained some data before the upgrade to 103","commit_id":"c1e583815bd9e8485c11b881eb0e67fa7b8fcbe2"},{"author":{"_account_id":18338,"name":"Ron De Rose","email":"ronald.de.rose@intel.com","username":"derosenet"},"change_message_id":"06304678fe1b19d4e931763c2bfadf10d2287bdb","unresolved":false,"context_lines":[{"line_number":1191,"context_line":"                                          autoload\u003dTrue)"},{"line_number":1192,"context_line":"        null_created_at_cnt \u003d ("},{"line_number":1193,"context_line":"            session.query(password_table).filter_by(created_at\u003dNone).count())"},{"line_number":1194,"context_line":"        self.assertTrue(null_created_at_cnt \u003d\u003d 0)"},{"line_number":1195,"context_line":""},{"line_number":1196,"context_line":""},{"line_number":1197,"context_line":"class MySQLOpportunisticUpgradeTestCase(SqlUpgradeTests):"}],"source_content_type":"text/x-python","patch_set":84,"id":"5a9d85d2_a0260066","line":1194,"in_reply_to":"7aa08908_4971170c","updated":"2016-06-20 14:40:41.000000000","message":"Done","commit_id":"c1e583815bd9e8485c11b881eb0e67fa7b8fcbe2"},{"author":{"_account_id":4,"name":"Dolph Mathews","email":"dolph.mathews@gmail.com","username":"dolph"},"change_message_id":"cb63db3793816fc0cd29a6114f04915528e4950d","unresolved":false,"context_lines":[{"line_number":1413,"context_line":"        password_table \u003d sqlalchemy.Table(password_name, self.metadata,"},{"line_number":1414,"context_line":"                                          autoload\u003dTrue)"},{"line_number":1415,"context_line":"        cnt \u003d session.query(password_table).count()"},{"line_number":1416,"context_line":"        self.assertTrue(cnt \u003e 0)"},{"line_number":1417,"context_line":"        self.metadata.clear()"},{"line_number":1418,"context_line":"        self.upgrade(105)"},{"line_number":1419,"context_line":"        # columns after"}],"source_content_type":"text/x-python","patch_set":92,"id":"3aaa91ec_0b6199d3","line":1416,"updated":"2016-06-23 15:38:50.000000000","message":"Either of these would produce easier to read error messages on failure:\n\n  assertTrue(cnt) # 0 is not true\n  assertGreater(cnt, 0) # 0 is not greater than 0\n\nexample:\n\n  http://cdn.pasteraw.com/7krk5sdd5od6d4uehxtg3vvlhm05k2o","commit_id":"ad0e22ecff808dab58848d4bee3de757a6cf6640"},{"author":{"_account_id":18338,"name":"Ron De Rose","email":"ronald.de.rose@intel.com","username":"derosenet"},"change_message_id":"c3a3cab8702f6b064d3607884cefb0babb77acad","unresolved":false,"context_lines":[{"line_number":1413,"context_line":"        password_table \u003d sqlalchemy.Table(password_name, self.metadata,"},{"line_number":1414,"context_line":"                                          autoload\u003dTrue)"},{"line_number":1415,"context_line":"        cnt \u003d session.query(password_table).count()"},{"line_number":1416,"context_line":"        self.assertTrue(cnt \u003e 0)"},{"line_number":1417,"context_line":"        self.metadata.clear()"},{"line_number":1418,"context_line":"        self.upgrade(105)"},{"line_number":1419,"context_line":"        # columns after"}],"source_content_type":"text/x-python","patch_set":92,"id":"3aaa91ec_b676e8d4","line":1416,"in_reply_to":"3aaa91ec_0b6199d3","updated":"2016-06-23 15:52:04.000000000","message":"Thanks, agree.  Done.","commit_id":"ad0e22ecff808dab58848d4bee3de757a6cf6640"},{"author":{"_account_id":5046,"name":"Lance Bragstad","email":"lbragstad@redhat.com","username":"ldbragst"},"change_message_id":"164129b86880fd97327a258aa729fc4ae4347386","unresolved":false,"context_lines":[{"line_number":1424,"context_line":"                                 \u0027created_at\u0027,"},{"line_number":1425,"context_line":"                                 \u0027expires_at\u0027])"},{"line_number":1426,"context_line":"        password_table \u003d sqlalchemy.Table(password_name, self.metadata,"},{"line_number":1427,"context_line":"                                          autoload\u003dTrue)"},{"line_number":1428,"context_line":"        # verify created_at is not null"},{"line_number":1429,"context_line":"        null_created_at_cnt \u003d ("},{"line_number":1430,"context_line":"            session.query(password_table).filter_by(created_at\u003dNone).count())"}],"source_content_type":"text/x-python","patch_set":92,"id":"3aaa91ec_7085a805","line":1427,"updated":"2016-06-23 15:28:16.000000000","message":"Do we have to redefine `password_table` because the schema changed? It was already defined on line 1413.","commit_id":"ad0e22ecff808dab58848d4bee3de757a6cf6640"},{"author":{"_account_id":18338,"name":"Ron De Rose","email":"ronald.de.rose@intel.com","username":"derosenet"},"change_message_id":"37ce0be0c7a2d3eebf02d22abba316b0cea0131d","unresolved":false,"context_lines":[{"line_number":1424,"context_line":"                                 \u0027created_at\u0027,"},{"line_number":1425,"context_line":"                                 \u0027expires_at\u0027])"},{"line_number":1426,"context_line":"        password_table \u003d sqlalchemy.Table(password_name, self.metadata,"},{"line_number":1427,"context_line":"                                          autoload\u003dTrue)"},{"line_number":1428,"context_line":"        # verify created_at is not null"},{"line_number":1429,"context_line":"        null_created_at_cnt \u003d ("},{"line_number":1430,"context_line":"            session.query(password_table).filter_by(created_at\u003dNone).count())"}],"source_content_type":"text/x-python","patch_set":92,"id":"3aaa91ec_8ba3c9ff","line":1427,"in_reply_to":"3aaa91ec_7085a805","updated":"2016-06-23 15:32:55.000000000","message":"Yes, because the schema changed.","commit_id":"ad0e22ecff808dab58848d4bee3de757a6cf6640"},{"author":{"_account_id":4,"name":"Dolph Mathews","email":"dolph.mathews@gmail.com","username":"dolph"},"change_message_id":"cb63db3793816fc0cd29a6114f04915528e4950d","unresolved":false,"context_lines":[{"line_number":1428,"context_line":"        # verify created_at is not null"},{"line_number":1429,"context_line":"        null_created_at_cnt \u003d ("},{"line_number":1430,"context_line":"            session.query(password_table).filter_by(created_at\u003dNone).count())"},{"line_number":1431,"context_line":"        self.assertTrue(null_created_at_cnt \u003d\u003d 0)"},{"line_number":1432,"context_line":"        # verify expires_at is null"},{"line_number":1433,"context_line":"        null_expires_at_cnt \u003d ("},{"line_number":1434,"context_line":"            session.query(password_table).filter_by(expires_at\u003dNone).count())"}],"source_content_type":"text/x-python","patch_set":92,"id":"3aaa91ec_ebf7ed56","line":1431,"updated":"2016-06-23 15:38:50.000000000","message":"assertEqual","commit_id":"ad0e22ecff808dab58848d4bee3de757a6cf6640"},{"author":{"_account_id":18338,"name":"Ron De Rose","email":"ronald.de.rose@intel.com","username":"derosenet"},"change_message_id":"c3a3cab8702f6b064d3607884cefb0babb77acad","unresolved":false,"context_lines":[{"line_number":1428,"context_line":"        # verify created_at is not null"},{"line_number":1429,"context_line":"        null_created_at_cnt \u003d ("},{"line_number":1430,"context_line":"            session.query(password_table).filter_by(created_at\u003dNone).count())"},{"line_number":1431,"context_line":"        self.assertTrue(null_created_at_cnt \u003d\u003d 0)"},{"line_number":1432,"context_line":"        # verify expires_at is null"},{"line_number":1433,"context_line":"        null_expires_at_cnt \u003d ("},{"line_number":1434,"context_line":"            session.query(password_table).filter_by(expires_at\u003dNone).count())"}],"source_content_type":"text/x-python","patch_set":92,"id":"3aaa91ec_16809c8a","line":1431,"in_reply_to":"3aaa91ec_ebf7ed56","updated":"2016-06-23 15:52:04.000000000","message":"Done","commit_id":"ad0e22ecff808dab58848d4bee3de757a6cf6640"},{"author":{"_account_id":4,"name":"Dolph Mathews","email":"dolph.mathews@gmail.com","username":"dolph"},"change_message_id":"cb63db3793816fc0cd29a6114f04915528e4950d","unresolved":false,"context_lines":[{"line_number":1432,"context_line":"        # verify expires_at is null"},{"line_number":1433,"context_line":"        null_expires_at_cnt \u003d ("},{"line_number":1434,"context_line":"            session.query(password_table).filter_by(expires_at\u003dNone).count())"},{"line_number":1435,"context_line":"        self.assertTrue(null_expires_at_cnt \u003e 0)"},{"line_number":1436,"context_line":""},{"line_number":1437,"context_line":""},{"line_number":1438,"context_line":"class MySQLOpportunisticUpgradeTestCase(SqlUpgradeTests):"}],"source_content_type":"text/x-python","patch_set":92,"id":"3aaa91ec_6ba2dd4c","line":1435,"updated":"2016-06-23 15:38:50.000000000","message":"assertGreater","commit_id":"ad0e22ecff808dab58848d4bee3de757a6cf6640"},{"author":{"_account_id":18338,"name":"Ron De Rose","email":"ronald.de.rose@intel.com","username":"derosenet"},"change_message_id":"c3a3cab8702f6b064d3607884cefb0babb77acad","unresolved":false,"context_lines":[{"line_number":1432,"context_line":"        # verify expires_at is null"},{"line_number":1433,"context_line":"        null_expires_at_cnt \u003d ("},{"line_number":1434,"context_line":"            session.query(password_table).filter_by(expires_at\u003dNone).count())"},{"line_number":1435,"context_line":"        self.assertTrue(null_expires_at_cnt \u003e 0)"},{"line_number":1436,"context_line":""},{"line_number":1437,"context_line":""},{"line_number":1438,"context_line":"class MySQLOpportunisticUpgradeTestCase(SqlUpgradeTests):"}],"source_content_type":"text/x-python","patch_set":92,"id":"3aaa91ec_f67cf0b6","line":1435,"in_reply_to":"3aaa91ec_6ba2dd4c","updated":"2016-06-23 15:52:04.000000000","message":"Done","commit_id":"ad0e22ecff808dab58848d4bee3de757a6cf6640"}]}
