diff options
author | Sandor Molnar <smolnar@apache.org> | 2018-06-05 15:29:08 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-06-05 15:29:08 +0200 |
commit | 3876e39fbd8fca4f2d346b8f5ca419fc82b1c592 (patch) | |
tree | fba4ceb8fbbea7b7e4a8834d21c2b6e6244e9173 | |
parent | 5f113f2bea9cad7d8f0ed8d308e5f73ad673b102 (diff) |
[AMBARI-23996] Changing column type from timestamp to long in users.create_time and user_authentication.[create|update]_time (#1456)
* AMBARI-23396. Changing column type from timstamp to long in users.create_time and user_authentication.[create|update]_time
* AMBARI-23996. Covering the upgrade path
17 files changed, 172 insertions, 66 deletions
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/UserAuthenticationSourceResourceProvider.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/UserAuthenticationSourceResourceProvider.java index 6a5f528836..6a099f3772 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/UserAuthenticationSourceResourceProvider.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/UserAuthenticationSourceResourceProvider.java @@ -18,6 +18,7 @@ package org.apache.ambari.server.controller.internal; import java.util.Collection; +import java.util.Date; import java.util.EnumSet; import java.util.HashSet; import java.util.List; @@ -388,8 +389,8 @@ public class UserAuthenticationSourceResourceProvider extends AbstractAuthorized entity.getUserAuthenticationId(), entity.getAuthenticationType(), entity.getAuthenticationKey(), - entity.getCreateTime(), - entity.getUpdateTime()); + new Date(entity.getCreateTime()), + new Date(entity.getUpdateTime())); } diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/UserResourceProvider.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/UserResourceProvider.java index 2141327f89..1177b57300 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/UserResourceProvider.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/UserResourceProvider.java @@ -18,6 +18,7 @@ package org.apache.ambari.server.controller.internal; import java.text.NumberFormat; +import java.util.Date; import java.util.EnumSet; import java.util.HashSet; import java.util.LinkedHashMap; @@ -692,7 +693,7 @@ public class UserResourceProvider extends AbstractControllerResourceProvider imp userEntity.getActive(), isAdmin, userEntity.getConsecutiveFailures(), - userEntity.getCreateTime()); + new Date(userEntity.getCreateTime())); userResponse.setGroups(groups); return userResponse; } diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/UserAuthenticationEntity.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/UserAuthenticationEntity.java index 262c8ac407..e90949481d 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/UserAuthenticationEntity.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/UserAuthenticationEntity.java @@ -17,8 +17,6 @@ */ package org.apache.ambari.server.orm.entities; -import java.util.Date; - import javax.persistence.Basic; import javax.persistence.Column; import javax.persistence.Entity; @@ -36,8 +34,6 @@ import javax.persistence.PrePersist; import javax.persistence.PreUpdate; import javax.persistence.Table; import javax.persistence.TableGenerator; -import javax.persistence.Temporal; -import javax.persistence.TemporalType; import org.apache.ambari.server.security.authorization.UserAuthenticationType; import org.apache.commons.lang.builder.EqualsBuilder; @@ -78,13 +74,11 @@ public class UserAuthenticationEntity { @Column(name = "create_time", nullable = false) @Basic - @Temporal(value = TemporalType.TIMESTAMP) - private Date createTime = new Date(); + private long createTime; @Column(name = "update_time", nullable = false) @Basic - @Temporal(value = TemporalType.TIMESTAMP) - private Date updateTime = new Date(); + private long updateTime ; @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "user_id", referencedColumnName = "user_id", nullable = false) @@ -114,11 +108,11 @@ public class UserAuthenticationEntity { this.authenticationKey = authenticationKey; } - public Date getCreateTime() { + public long getCreateTime() { return createTime; } - public Date getUpdateTime() { + public long getUpdateTime() { return updateTime; } @@ -145,8 +139,9 @@ public class UserAuthenticationEntity { */ @PrePersist protected void onCreate() { - createTime = new Date(); - updateTime = new Date(); + final long now = System.currentTimeMillis(); + createTime = now; + updateTime = now; } /** @@ -154,7 +149,7 @@ public class UserAuthenticationEntity { */ @PreUpdate protected void onUpdate() { - updateTime = new Date(); + updateTime = System.currentTimeMillis(); } @Override diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/UserEntity.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/UserEntity.java index c679fff7aa..1621389f1c 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/UserEntity.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/UserEntity.java @@ -18,7 +18,6 @@ package org.apache.ambari.server.orm.entities; import java.util.ArrayList; -import java.util.Date; import java.util.HashSet; import java.util.List; import java.util.Set; @@ -37,10 +36,9 @@ import javax.persistence.NamedQueries; import javax.persistence.NamedQuery; import javax.persistence.OneToMany; import javax.persistence.OneToOne; +import javax.persistence.PrePersist; import javax.persistence.Table; import javax.persistence.TableGenerator; -import javax.persistence.Temporal; -import javax.persistence.TemporalType; import javax.persistence.UniqueConstraint; import javax.persistence.Version; @@ -71,8 +69,7 @@ public class UserEntity { @Column(name = "create_time", nullable = false) @Basic - @Temporal(value = TemporalType.TIMESTAMP) - private Date createTime = new Date(); + private long createTime; @Column(name = "active", nullable = false) private Integer active = 1; @@ -211,11 +208,11 @@ public class UserEntity { this.localUsername = localUsername; } - public Date getCreateTime() { + public long getCreateTime() { return createTime; } - public void setCreateTime(Date createTime) { + public void setCreateTime(long createTime) { this.createTime = createTime; } @@ -308,6 +305,14 @@ public class UserEntity { } } + /** + * Ensure the create time is set properly when the record is created. + */ + @PrePersist + protected void onCreate() { + createTime = System.currentTimeMillis(); + } + // ----- Object overrides -------------------------------------------------- @Override diff --git a/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/User.java b/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/User.java index a418451ae9..4be2a9c91d 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/User.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/User.java @@ -48,7 +48,7 @@ public class User { public User(UserEntity userEntity) { userId = userEntity.getUserId(); userName = userEntity.getUserName(); - createTime = userEntity.getCreateTime(); + createTime = new Date(userEntity.getCreateTime()); active = userEntity.getActive(); groups = new ArrayList<>(); diff --git a/ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog270.java b/ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog270.java index 2fd79c8109..d28b77374f 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog270.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog270.java @@ -22,8 +22,11 @@ import java.io.IOException; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Paths; +import java.sql.PreparedStatement; +import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Timestamp; +import java.sql.Types; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; @@ -323,6 +326,7 @@ public class UpgradeCatalog270 extends AbstractUpgradeCatalog { * @see #updateUsersTable() */ protected void upgradeUserTables() throws SQLException { + convertUserCreationTimeToLong(); createUserAuthenticationTable(); updateGroupMembershipRecords(); updateAdminPrivilegeRecords(); @@ -550,6 +554,65 @@ public class UpgradeCatalog270 extends AbstractUpgradeCatalog { } /** + * In order to save the epoch equivalent of users.create_time we need to convert data in this column as follows: + * <ol> + * <li>creating a temporary column where we store the numeric representation of + * the timestamp + * <li>populating data in the temporary column + * <li>removing original column column + * <li>renaming the temporary column to the original column + * </ol> + * + * @throws SQLException + * if an error occurs while executing SQL statements + * + */ + private void convertUserCreationTimeToLong() throws SQLException { + if (!isUserCreationTimeMigrated()) { + LOG.info("Converting user creation times..."); + final String temporaryColumnName = USERS_CREATE_TIME_COLUMN + "_numeric"; + if (!dbAccessor.tableHasColumn(USERS_TABLE, temporaryColumnName)) { + final DBAccessor.DBColumnInfo tempColumnInfo = new DBAccessor.DBColumnInfo(temporaryColumnName, Long.class); + dbAccessor.addColumn(USERS_TABLE, tempColumnInfo); + } + + if (dbAccessor.tableHasColumn(USERS_TABLE, USERS_CREATE_TIME_COLUMN)) { + final Map<Integer, Timestamp> currentUserCreateTimes = fetchCurrentUserCreateTimesNotYetMigrated(temporaryColumnName); + for (Map.Entry<Integer, Timestamp> currentUserCreateTime : currentUserCreateTimes.entrySet()) { + dbAccessor.updateTable(USERS_TABLE, temporaryColumnName, currentUserCreateTime.getValue().getTime(), + "WHERE " + USERS_USER_ID_COLUMN + "=" + currentUserCreateTime.getKey()); + } + + dbAccessor.dropColumn(USERS_TABLE, USERS_CREATE_TIME_COLUMN); + } + + final DBAccessor.DBColumnInfo usersCreateTimeColumnInfo = new DBAccessor.DBColumnInfo(USERS_CREATE_TIME_COLUMN, Long.class, null, null, false); + dbAccessor.renameColumn(USERS_TABLE, temporaryColumnName, usersCreateTimeColumnInfo); + LOG.info("Converted user creation times"); + } else { + LOG.info("Already converted user creation timestamps to EPOCH representation"); + } + } + + private boolean isUserCreationTimeMigrated() throws SQLException { + final int columnType = dbAccessor.getColumnType(USERS_TABLE, USERS_CREATE_TIME_COLUMN); + LOG.info(USERS_TABLE + "." + USERS_CREATE_TIME_COLUMN + "'s type = " + columnType); + return columnType != Types.DATE && columnType != Types.TIMESTAMP; + } + + private Map<Integer, Timestamp> fetchCurrentUserCreateTimesNotYetMigrated(String temporaryColumnName) throws SQLException { + final Map<Integer, Timestamp> currentUserCreateTimes = new HashMap<>(); + try ( + PreparedStatement pstmt = dbAccessor.getConnection().prepareStatement("SELECT " + USERS_USER_ID_COLUMN + ", " + USERS_CREATE_TIME_COLUMN + " FROM " + USERS_TABLE + " WHERE " + temporaryColumnName + " IS NULL ORDER BY " + USERS_USER_ID_COLUMN); + ResultSet rs = pstmt.executeQuery()) { + while (rs.next()) { + currentUserCreateTimes.put(rs.getInt(1), rs.getTimestamp(2)); + } + } + return currentUserCreateTimes; + } + + /** * If the <code>users</code> table has not yet been migrated, create the <code>user_authentication</code> * table and generate relevant records for that table based on data in the <code>users</code> table. * <p> @@ -570,8 +633,8 @@ public class UpgradeCatalog270 extends AbstractUpgradeCatalog { columns.add(new DBAccessor.DBColumnInfo(USER_AUTHENTICATION_USER_ID_COLUMN, Integer.class, null, null, false)); columns.add(new DBAccessor.DBColumnInfo(USER_AUTHENTICATION_AUTHENTICATION_TYPE_COLUMN, String.class, 50, null, false)); columns.add(new DBAccessor.DBColumnInfo(USER_AUTHENTICATION_AUTHENTICATION_KEY_COLUMN, String.class, 2048, null, true)); - columns.add(new DBAccessor.DBColumnInfo(USER_AUTHENTICATION_CREATE_TIME_COLUMN, Timestamp.class, null, null, true)); - columns.add(new DBAccessor.DBColumnInfo(USER_AUTHENTICATION_UPDATE_TIME_COLUMN, Timestamp.class, null, null, true)); + columns.add(new DBAccessor.DBColumnInfo(USER_AUTHENTICATION_CREATE_TIME_COLUMN, Long.class, null, null, true)); + columns.add(new DBAccessor.DBColumnInfo(USER_AUTHENTICATION_UPDATE_TIME_COLUMN, Long.class, null, null, true)); // Make sure the temporary table does not exist dbAccessor.dropTable(temporaryTable); diff --git a/ambari-server/src/main/resources/Ambari-DDL-Derby-CREATE.sql b/ambari-server/src/main/resources/Ambari-DDL-Derby-CREATE.sql index 2c5bc3b973..66f4701404 100644 --- a/ambari-server/src/main/resources/Ambari-DDL-Derby-CREATE.sql +++ b/ambari-server/src/main/resources/Ambari-DDL-Derby-CREATE.sql @@ -301,7 +301,7 @@ CREATE TABLE users ( active_widget_layouts VARCHAR(1024) DEFAULT NULL, display_name VARCHAR(255) NOT NULL, local_username VARCHAR(255) NOT NULL, - create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + create_time BIGINT NOT NULL, version BIGINT NOT NULL DEFAULT 0, CONSTRAINT PK_users PRIMARY KEY (user_id), CONSTRAINT FK_users_principal_id FOREIGN KEY (principal_id) REFERENCES adminprincipal(principal_id), @@ -312,8 +312,8 @@ CREATE TABLE user_authentication ( user_id INTEGER NOT NULL, authentication_type VARCHAR(50) NOT NULL, authentication_key VARCHAR(2048), - create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP, - update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + create_time BIGINT NOT NULL, + update_time BIGINT NOT NULL, CONSTRAINT PK_user_authentication PRIMARY KEY (user_authentication_id), CONSTRAINT FK_user_authentication_users FOREIGN KEY (user_id) REFERENCES users (user_id)); @@ -1270,12 +1270,12 @@ INSERT INTO adminprincipal (principal_id, principal_type_id) -- Insert the default administrator user. insert into users(user_id, principal_id, user_name, display_name, local_username, create_time) - SELECT 1, 1, 'admin', 'Administrator', 'admin', CURRENT_TIMESTAMP FROM SYSIBM.SYSDUMMY1; + SELECT 1, 1, 'admin', 'Administrator', 'admin', 0 FROM SYSIBM.SYSDUMMY1; -- Insert the LOCAL authentication data for the default administrator user. -- The authentication_key value is the salted digest of the password: admin insert into user_authentication(user_authentication_id, user_id, authentication_type, authentication_key, create_time, update_time) - SELECT 1, 1, 'LOCAL', '538916f8943ec225d97a9a86a2c6ec0818c1cd400e09e03b660fdaaec4af29ddbb6f2b1033b81b00', CURRENT_TIMESTAMP, CURRENT_TIMESTAMP FROM SYSIBM.SYSDUMMY1; + SELECT 1, 1, 'LOCAL', '538916f8943ec225d97a9a86a2c6ec0818c1cd400e09e03b660fdaaec4af29ddbb6f2b1033b81b00', 0, 0 FROM SYSIBM.SYSDUMMY1; insert into adminpermission(permission_id, permission_name, resource_type_id, permission_label, principal_id, sort_order) SELECT 1, 'AMBARI.ADMINISTRATOR', 1, 'Ambari Administrator', 7, 1 FROM SYSIBM.SYSDUMMY1 diff --git a/ambari-server/src/main/resources/Ambari-DDL-MySQL-CREATE.sql b/ambari-server/src/main/resources/Ambari-DDL-MySQL-CREATE.sql index 7e7c4d0721..af6414293b 100644 --- a/ambari-server/src/main/resources/Ambari-DDL-MySQL-CREATE.sql +++ b/ambari-server/src/main/resources/Ambari-DDL-MySQL-CREATE.sql @@ -321,7 +321,7 @@ CREATE TABLE users ( active_widget_layouts VARCHAR(1024) DEFAULT NULL, display_name VARCHAR(255) NOT NULL, local_username VARCHAR(255) NOT NULL, - create_time TIMESTAMP DEFAULT NOW(), + create_time BIGINT NOT NULL, version BIGINT NOT NULL DEFAULT 0, CONSTRAINT PK_users PRIMARY KEY (user_id), CONSTRAINT FK_users_principal_id FOREIGN KEY (principal_id) REFERENCES adminprincipal(principal_id), @@ -332,8 +332,8 @@ CREATE TABLE user_authentication ( user_id INTEGER NOT NULL, authentication_type VARCHAR(50) NOT NULL, authentication_key VARCHAR(2048), - create_time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, - update_time TIMESTAMP DEFAULT NOW(), + create_time BIGINT NOT NULL, + update_time BIGINT NOT NULL, CONSTRAINT PK_user_authentication PRIMARY KEY (user_authentication_id), CONSTRAINT FK_user_authentication_users FOREIGN KEY (user_id) REFERENCES users (user_id) ); @@ -1219,12 +1219,12 @@ INSERT INTO adminprincipal (principal_id, principal_type_id) VALUES -- Insert the default administrator user. INSERT INTO users(user_id, principal_id, user_name, display_name, local_username, create_time) - SELECT 1, 1, 'admin', 'Administrator', 'admin', NOW(); + SELECT 1, 1, 'admin', 'Administrator', 'admin', UNIX_TIMESTAMP() * 1000; -- Insert the LOCAL authentication data for the default administrator user. -- The authentication_key value is the salted digest of the password: admin INSERT INTO user_authentication(user_authentication_id, user_id, authentication_type, authentication_key, create_time, update_time) - SELECT 1, 1, 'LOCAL', '538916f8943ec225d97a9a86a2c6ec0818c1cd400e09e03b660fdaaec4af29ddbb6f2b1033b81b00', NOW(), NOW(); + SELECT 1, 1, 'LOCAL', '538916f8943ec225d97a9a86a2c6ec0818c1cd400e09e03b660fdaaec4af29ddbb6f2b1033b81b00', UNIX_TIMESTAMP() * 1000, UNIX_TIMESTAMP() * 1000; INSERT INTO adminpermission(permission_id, permission_name, resource_type_id, permission_label, principal_id, sort_order) SELECT 1, 'AMBARI.ADMINISTRATOR', 1, 'Ambari Administrator', 7, 1 UNION ALL diff --git a/ambari-server/src/main/resources/Ambari-DDL-Oracle-CREATE.sql b/ambari-server/src/main/resources/Ambari-DDL-Oracle-CREATE.sql index 80e7aac559..3a54f33357 100644 --- a/ambari-server/src/main/resources/Ambari-DDL-Oracle-CREATE.sql +++ b/ambari-server/src/main/resources/Ambari-DDL-Oracle-CREATE.sql @@ -301,7 +301,7 @@ CREATE TABLE users ( active_widget_layouts VARCHAR2(1024) DEFAULT NULL, display_name VARCHAR2(255) NOT NULL, local_username VARCHAR2(255) NOT NULL, - create_time TIMESTAMP NULL, + create_time NUMBER(19) NOT NULL, version NUMBER(19) DEFAULT 0 NOT NULL, CONSTRAINT PK_users PRIMARY KEY (user_id), CONSTRAINT FK_users_principal_id FOREIGN KEY (principal_id) REFERENCES adminprincipal(principal_id), @@ -312,8 +312,8 @@ CREATE TABLE user_authentication ( user_id NUMBER(10) NOT NULL, authentication_type VARCHAR(50) NOT NULL, authentication_key VARCHAR(2048), - create_time TIMESTAMP NULL, - update_time TIMESTAMP NULL, + create_time NUMBER(19) NOT NULL, + update_time NUMBER(19) NOT NULL, CONSTRAINT PK_user_authentication PRIMARY KEY (user_authentication_id), CONSTRAINT FK_user_authentication_users FOREIGN KEY (user_id) REFERENCES users (user_id) ); @@ -1211,12 +1211,12 @@ insert into adminprincipal (principal_id, principal_type_id) -- Insert the default administrator user. insert into users(user_id, principal_id, user_name, display_name, local_username, create_time) - SELECT 1, 1, 'admin', 'Administrator', 'admin', CURRENT_TIMESTAMP from dual; + SELECT 1, 1, 'admin', 'Administrator', 'admin', (SYSDATE - DATE '1970-01-01') * 86400000 from dual; -- Insert the LOCAL authentication data for the default administrator user. -- The authentication_key value is the salted digest of the password: admin insert into user_authentication(user_authentication_id, user_id, authentication_type, authentication_key, create_time, update_time) - SELECT 1, 1, 'LOCAL', '538916f8943ec225d97a9a86a2c6ec0818c1cd400e09e03b660fdaaec4af29ddbb6f2b1033b81b00', CURRENT_TIMESTAMP, CURRENT_TIMESTAMP from dual; + SELECT 1, 1, 'LOCAL', '538916f8943ec225d97a9a86a2c6ec0818c1cd400e09e03b660fdaaec4af29ddbb6f2b1033b81b00', (SYSDATE - DATE '1970-01-01') * 86400000, (SYSDATE - DATE '1970-01-01') * 86400000 from dual; insert into adminpermission(permission_id, permission_name, resource_type_id, permission_label, principal_id, sort_order) select 1, 'AMBARI.ADMINISTRATOR', 1, 'Ambari Administrator', 7, 1 from dual diff --git a/ambari-server/src/main/resources/Ambari-DDL-Postgres-CREATE.sql b/ambari-server/src/main/resources/Ambari-DDL-Postgres-CREATE.sql index 42387a30a3..1611130d03 100644 --- a/ambari-server/src/main/resources/Ambari-DDL-Postgres-CREATE.sql +++ b/ambari-server/src/main/resources/Ambari-DDL-Postgres-CREATE.sql @@ -303,7 +303,7 @@ CREATE TABLE users ( active_widget_layouts VARCHAR(1024) DEFAULT NULL, display_name VARCHAR(255) NOT NULL, local_username VARCHAR(255) NOT NULL, - create_time TIMESTAMP DEFAULT NOW(), + create_time BIGINT NOT NULL, version BIGINT DEFAULT 0 NOT NULL, CONSTRAINT PK_users PRIMARY KEY (user_id), CONSTRAINT FK_users_principal_id FOREIGN KEY (principal_id) REFERENCES adminprincipal(principal_id), @@ -314,8 +314,8 @@ CREATE TABLE user_authentication ( user_id INTEGER NOT NULL, authentication_type VARCHAR(50) NOT NULL, authentication_key VARCHAR(2048), - create_time TIMESTAMP DEFAULT NOW(), - update_time TIMESTAMP DEFAULT NOW(), + create_time BIGINT NOT NULL, + update_time BIGINT NOT NULL, CONSTRAINT PK_user_authentication PRIMARY KEY (user_authentication_id), CONSTRAINT FK_user_authentication_users FOREIGN KEY (user_id) REFERENCES users (user_id)); @@ -1201,12 +1201,12 @@ INSERT INTO adminprincipal (principal_id, principal_type_id) VALUES -- Insert the default administrator user. INSERT INTO users(user_id, principal_id, user_name, display_name, local_username, create_time) - SELECT 1, 1, 'admin', 'Administrator', 'admin', NOW(); + SELECT 1, 1, 'admin', 'Administrator', 'admin', CAST (extract(epoch FROM CURRENT_TIMESTAMP) AS bigint) * 1000; -- Insert the LOCAL authentication data for the default administrator user. -- The authentication_key value is the salted digest of the password: admin INSERT INTO user_authentication(user_authentication_id, user_id, authentication_type, authentication_key, create_time, update_time) - SELECT 1, 1, 'LOCAL', '538916f8943ec225d97a9a86a2c6ec0818c1cd400e09e03b660fdaaec4af29ddbb6f2b1033b81b00', NOW(), NOW(); + SELECT 1, 1, 'LOCAL', '538916f8943ec225d97a9a86a2c6ec0818c1cd400e09e03b660fdaaec4af29ddbb6f2b1033b81b00', CAST (extract(epoch FROM CURRENT_TIMESTAMP) AS bigint) * 1000, CAST (extract(epoch FROM CURRENT_TIMESTAMP) AS bigint) * 1000; INSERT INTO adminpermission(permission_id, permission_name, resource_type_id, permission_label, principal_id, sort_order) SELECT 1, 'AMBARI.ADMINISTRATOR', 1, 'Ambari Administrator', 7, 1 UNION ALL diff --git a/ambari-server/src/main/resources/Ambari-DDL-SQLAnywhere-CREATE.sql b/ambari-server/src/main/resources/Ambari-DDL-SQLAnywhere-CREATE.sql index fd5f50a556..bf6f63df62 100644 --- a/ambari-server/src/main/resources/Ambari-DDL-SQLAnywhere-CREATE.sql +++ b/ambari-server/src/main/resources/Ambari-DDL-SQLAnywhere-CREATE.sql @@ -299,7 +299,7 @@ CREATE TABLE users ( active_widget_layouts VARCHAR(1024) DEFAULT NULL, display_name VARCHAR(255) NOT NULL, local_username VARCHAR(255) NOT NULL, - create_time TIMESTAMP DEFAULT NOW(), + create_time NUMERIC(19) NOT NULL, version NUMERIC(19) NOT NULL DEFAULT 0, CONSTRAINT PK_users PRIMARY KEY (user_id), CONSTRAINT FK_users_principal_id FOREIGN KEY (principal_id) REFERENCES adminprincipal(principal_id), @@ -310,8 +310,8 @@ CREATE TABLE user_authentication ( user_id INTEGER NOT NULL, authentication_type VARCHAR(50) NOT NULL, authentication_key VARCHAR(2048), - create_time TIMESTAMP DEFAULT NOW(), - update_time TIMESTAMP DEFAULT NOW(), + create_time NUMERIC(19) NOT NULL, + update_time NUMERIC(19) NOT NULL, CONSTRAINT PK_user_authentication PRIMARY KEY (user_authentication_id), CONSTRAINT FK_user_authentication_users FOREIGN KEY (user_id) REFERENCES users (user_id) ); @@ -1208,12 +1208,12 @@ insert into adminprincipal (principal_id, principal_type_id) -- Insert the default administrator user. insert into users(user_id, principal_id, user_name, display_name, local_username, create_time) - SELECT 1, 1, 'admin', 'Administrator', 'admin', NOW(); + SELECT 1, 1, 'admin', 'Administrator', 'admin', 0; -- Insert the LOCAL authentication data for the default administrator user. -- The authentication_key value is the salted digest of the password: admin insert into user_authentication(user_authentication_id, user_id, authentication_type, authentication_key, create_time, update_time) - SELECT 1, 1, 'LOCAL', '538916f8943ec225d97a9a86a2c6ec0818c1cd400e09e03b660fdaaec4af29ddbb6f2b1033b81b00', NOW(), NOW(); + SELECT 1, 1, 'LOCAL', '538916f8943ec225d97a9a86a2c6ec0818c1cd400e09e03b660fdaaec4af29ddbb6f2b1033b81b00', 0, 0; insert into adminpermission(permission_id, permission_name, resource_type_id, permission_label, principal_id, sort_order) diff --git a/ambari-server/src/main/resources/Ambari-DDL-SQLServer-CREATE.sql b/ambari-server/src/main/resources/Ambari-DDL-SQLServer-CREATE.sql index 2b4a504ad2..03fe222f83 100644 --- a/ambari-server/src/main/resources/Ambari-DDL-SQLServer-CREATE.sql +++ b/ambari-server/src/main/resources/Ambari-DDL-SQLServer-CREATE.sql @@ -305,7 +305,7 @@ CREATE TABLE users ( active_widget_layouts VARCHAR(1024) DEFAULT NULL, display_name VARCHAR(255) NOT NULL, local_username VARCHAR(255) NOT NULL, - create_time DATETIME DEFAULT GETDATE(), + create_time BIGINT NOT NULL, version BIGINT NOT NULL DEFAULT 0, CONSTRAINT PK_users PRIMARY KEY (user_id), CONSTRAINT FK_users_principal_id FOREIGN KEY (principal_id) REFERENCES adminprincipal(principal_id), @@ -316,8 +316,8 @@ CREATE TABLE user_authentication ( user_id INTEGER NOT NULL, authentication_type VARCHAR(50) NOT NULL, authentication_key VARCHAR(2048), - create_time DATETIME DEFAULT GETDATE(), - update_time DATETIME DEFAULT GETDATE(), + create_time BIGINT NOT NULL, + update_time BIGINT NOT NULL, CONSTRAINT PK_user_authentication PRIMARY KEY (user_authentication_id), CONSTRAINT FK_user_authentication_users FOREIGN KEY (user_id) REFERENCES users (user_id) ); @@ -1227,12 +1227,12 @@ BEGIN TRANSACTION -- Insert the default administrator user. insert into users(user_id, principal_id, user_name, display_name, local_username, create_time) - select 1, 1, 'admin', 'Administrator', 'admin', GETDATE(); + select 1, 1, 'admin', 'Administrator', 'admin', CAST(DATEDIFF(s, '1970-01-01T00:00:00Z', GETDATE()) as BIGINT) * 1000; -- Insert the LOCAL authentication data for the default administrator user. -- The authentication_key value is the salted digest of the password: admin insert into user_authentication(user_authentication_id, user_id, authentication_type, authentication_key, create_time, update_time) - select 1, 1, 'LOCAL', '538916f8943ec225d97a9a86a2c6ec0818c1cd400e09e03b660fdaaec4af29ddbb6f2b1033b81b00', GETDATE(), GETDATE(); + select 1, 1, 'LOCAL', '538916f8943ec225d97a9a86a2c6ec0818c1cd400e09e03b660fdaaec4af29ddbb6f2b1033b81b00', CAST(DATEDIFF(s, '1970-01-01T00:00:00Z', GETDATE()) as BIGINT) * 1000, CAST(DATEDIFF(s, '1970-01-01T00:00:00Z', GETDATE()) as BIGINT) * 1000; insert into adminpermission(permission_id, permission_name, resource_type_id, permission_label, principal_id, sort_order) diff --git a/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/UserAuthenticationSourceResourceProviderTest.java b/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/UserAuthenticationSourceResourceProviderTest.java index c1dba1be23..c1a5f54419 100644 --- a/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/UserAuthenticationSourceResourceProviderTest.java +++ b/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/UserAuthenticationSourceResourceProviderTest.java @@ -23,7 +23,6 @@ import static org.easymock.EasyMock.expectLastCall; import java.util.ArrayList; import java.util.Calendar; -import java.util.Date; import java.util.HashMap; import java.util.HashSet; import java.util.LinkedHashMap; @@ -73,8 +72,8 @@ import com.google.inject.Injector; */ public class UserAuthenticationSourceResourceProviderTest extends EasyMockSupport { - private static final Date CREATE_TIME = Calendar.getInstance().getTime(); - private static final Date UPDATE_TIME = Calendar.getInstance().getTime(); + private static final long CREATE_TIME = Calendar.getInstance().getTime().getTime(); + private static final long UPDATE_TIME = Calendar.getInstance().getTime().getTime(); @Before public void resetMocks() { diff --git a/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/UserResourceProviderTest.java b/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/UserResourceProviderTest.java index 2bc3f47461..42fac4ebf0 100644 --- a/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/UserResourceProviderTest.java +++ b/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/UserResourceProviderTest.java @@ -29,7 +29,6 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Calendar; import java.util.Collections; -import java.util.Date; import java.util.HashMap; import java.util.HashSet; import java.util.LinkedHashMap; @@ -129,7 +128,7 @@ import com.google.inject.assistedinject.FactoryModuleBuilder; */ public class UserResourceProviderTest extends EasyMockSupport { - private static final Date CREATE_TIME = Calendar.getInstance().getTime(); + private static final long CREATE_TIME = Calendar.getInstance().getTime().getTime(); @Before public void resetMocks() { diff --git a/ambari-server/src/test/java/org/apache/ambari/server/security/authentication/jwt/AmbariJwtAuthenticationFilterTest.java b/ambari-server/src/test/java/org/apache/ambari/server/security/authentication/jwt/AmbariJwtAuthenticationFilterTest.java index ba4eb74d19..2c88d9fad0 100644 --- a/ambari-server/src/test/java/org/apache/ambari/server/security/authentication/jwt/AmbariJwtAuthenticationFilterTest.java +++ b/ambari-server/src/test/java/org/apache/ambari/server/security/authentication/jwt/AmbariJwtAuthenticationFilterTest.java @@ -409,7 +409,7 @@ public class AmbariJwtAuthenticationFilterTest extends EasyMockSupport { expect(userEntity.getActive()).andReturn(true).atLeastOnce(); expect(userEntity.getUserId()).andReturn(1).atLeastOnce(); expect(userEntity.getUserName()).andReturn("username").atLeastOnce(); - expect(userEntity.getCreateTime()).andReturn(new Date()).atLeastOnce(); + expect(userEntity.getCreateTime()).andReturn(new Date().getTime()).atLeastOnce(); expect(userEntity.getMemberEntities()).andReturn(Collections.emptySet()).atLeastOnce(); expect(userEntity.getAuthenticationEntities()).andReturn(Collections.singletonList(userAuthenticationEntity)).atLeastOnce(); expect(userEntity.getPrincipal()).andReturn(principal).atLeastOnce(); diff --git a/ambari-server/src/test/java/org/apache/ambari/server/security/ldap/AmbariLdapDataPopulatorTest.java b/ambari-server/src/test/java/org/apache/ambari/server/security/ldap/AmbariLdapDataPopulatorTest.java index 7d502be62a..a015b18c39 100644 --- a/ambari-server/src/test/java/org/apache/ambari/server/security/ldap/AmbariLdapDataPopulatorTest.java +++ b/ambari-server/src/test/java/org/apache/ambari/server/security/ldap/AmbariLdapDataPopulatorTest.java @@ -37,7 +37,6 @@ import static org.junit.Assert.assertEquals; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; -import java.util.Date; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; @@ -2041,7 +2040,7 @@ public class AmbariLdapDataPopulatorTest { final UserEntity userEntity = new UserEntity(); userEntity.setUserId(userIdCounter++); userEntity.setUserName(UserName.fromString(name).toString()); - userEntity.setCreateTime(new Date()); + userEntity.setCreateTime(0); userEntity.setActive(true); userEntity.setMemberEntities(new HashSet<>()); diff --git a/ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeCatalog270Test.java b/ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeCatalog270Test.java index 8b2f98c270..38f2db1111 100644 --- a/ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeCatalog270Test.java +++ b/ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeCatalog270Test.java @@ -96,6 +96,7 @@ import static org.apache.ambari.server.upgrade.UpgradeCatalog270.STAGE_TABLE; import static org.apache.ambari.server.upgrade.UpgradeCatalog270.UNIQUE_USERS_0_INDEX; import static org.apache.ambari.server.upgrade.UpgradeCatalog270.UNI_KKP; import static org.apache.ambari.server.upgrade.UpgradeCatalog270.USERS_CONSECUTIVE_FAILURES_COLUMN; +import static org.apache.ambari.server.upgrade.UpgradeCatalog270.USERS_CREATE_TIME_COLUMN; import static org.apache.ambari.server.upgrade.UpgradeCatalog270.USERS_DISPLAY_NAME_COLUMN; import static org.apache.ambari.server.upgrade.UpgradeCatalog270.USERS_LDAP_USER_COLUMN; import static org.apache.ambari.server.upgrade.UpgradeCatalog270.USERS_LOCAL_USERNAME_COLUMN; @@ -136,14 +137,18 @@ import static org.hamcrest.core.Is.is; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertThat; import static org.junit.Assert.assertTrue; +import static org.mockito.Matchers.anyInt; import java.io.File; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.sql.Timestamp; +import java.sql.Types; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; @@ -424,6 +429,10 @@ public class UpgradeCatalog270Test { dbAccessor.addPKConstraint(AMBARI_CONFIGURATION_TABLE, "PK_ambari_configuration", AMBARI_CONFIGURATION_CATEGORY_NAME_COLUMN, AMBARI_CONFIGURATION_PROPERTY_NAME_COLUMN); expectLastCall().once(); + //upgradeUserTable - converting users.create_time to long + Capture<DBAccessor.DBColumnInfo> temporaryColumnCreationCapture = newCapture(CaptureType.ALL); + Capture<DBAccessor.DBColumnInfo> temporaryColumnRenameCapture = newCapture(CaptureType.ALL); + // upgradeUserTable - create user_authentication table Capture<List<DBAccessor.DBColumnInfo>> createUserAuthenticationTableCaptures = newCapture(CaptureType.ALL); Capture<List<DBAccessor.DBColumnInfo>> createMembersTableCaptures = newCapture(CaptureType.ALL); @@ -443,6 +452,7 @@ public class UpgradeCatalog270Test { // Any return value will work here as long as a SQLException is not thrown. expect(dbAccessor.getColumnType(USERS_TABLE, USERS_USER_TYPE_COLUMN)).andReturn(0).anyTimes(); + prepareConvertingUsersCreationTime(dbAccessor, temporaryColumnCreationCapture, temporaryColumnRenameCapture); prepareCreateUserAuthenticationTable(dbAccessor, createUserAuthenticationTableCaptures); prepareUpdateGroupMembershipRecords(dbAccessor, createMembersTableCaptures); prepareUpdateAdminPrivilegeRecords(dbAccessor, createAdminPrincipalTableCaptures); @@ -555,6 +565,7 @@ public class UpgradeCatalog270Test { Assert.assertEquals(State.UNKNOWN, capturedLastValidColumn.getDefaultValue()); Assert.assertEquals(String.class, capturedLastValidColumn.getType()); + validateConvertingUserCreationTime(temporaryColumnCreationCapture,temporaryColumnRenameCapture); validateCreateUserAuthenticationTable(createUserAuthenticationTableCaptures); validateUpdateGroupMembershipRecords(createMembersTableCaptures); validateUpdateAdminPrivilegeRecords(createAdminPrincipalTableCaptures); @@ -609,6 +620,33 @@ public class UpgradeCatalog270Test { return module; } + private void prepareConvertingUsersCreationTime(DBAccessor dbAccessor, Capture<DBAccessor.DBColumnInfo> temporaryColumnCreationCapture, + Capture<DBAccessor.DBColumnInfo> temporaryColumnRenameCapture) throws SQLException { + expect(dbAccessor.getColumnType(USERS_TABLE, USERS_CREATE_TIME_COLUMN)).andReturn(Types.TIMESTAMP).once(); + final String temporaryColumnName = USERS_CREATE_TIME_COLUMN + "_numeric"; + expect(dbAccessor.tableHasColumn(USERS_TABLE, temporaryColumnName)).andReturn(Boolean.FALSE); + dbAccessor.addColumn(eq(USERS_TABLE), capture(temporaryColumnCreationCapture)); + expect(dbAccessor.tableHasColumn(USERS_TABLE, USERS_CREATE_TIME_COLUMN)).andReturn(Boolean.TRUE); + + final Connection connectionMock = niceMock(Connection.class); + expect(dbAccessor.getConnection()).andReturn(connectionMock).once(); + final PreparedStatement preparedStatementMock = niceMock(PreparedStatement.class); + expect(connectionMock.prepareStatement(anyString())).andReturn(preparedStatementMock); + final ResultSet resultSetMock = niceMock(ResultSet.class); + expect(preparedStatementMock.executeQuery()).andReturn(resultSetMock); + expect(resultSetMock.next()).andReturn(Boolean.TRUE).once(); + expect(resultSetMock.getInt(1)).andReturn(1); + expect(resultSetMock.getTimestamp(2)).andReturn(new Timestamp(1l)); + replay(connectionMock, preparedStatementMock, resultSetMock); + + expect(dbAccessor.updateTable(eq(USERS_TABLE), eq(temporaryColumnName), eq(1l), anyString())).andReturn(anyInt()); + + dbAccessor.dropColumn(USERS_TABLE, USERS_CREATE_TIME_COLUMN); + expectLastCall().once(); + + dbAccessor.renameColumn(eq(USERS_TABLE), eq(temporaryColumnName), capture(temporaryColumnRenameCapture)); + } + private void prepareCreateUserAuthenticationTable(DBAccessor dbAccessor, Capture<List<DBAccessor.DBColumnInfo>> capturedData) throws SQLException { @@ -632,6 +670,12 @@ public class UpgradeCatalog270Test { expect(dbAccessor.executeUpdate(startsWith("insert into " + USER_AUTHENTICATION_TABLE))).andReturn(1).once(); } + private void validateConvertingUserCreationTime(Capture<DBAccessor.DBColumnInfo> temporaryColumnCreationCapture, Capture<DBAccessor.DBColumnInfo> temporaryColumnRenameCapture) { + Assert.assertTrue(temporaryColumnCreationCapture.hasCaptured()); + Assert.assertTrue(temporaryColumnRenameCapture.hasCaptured()); + assertEquals(new DBAccessor.DBColumnInfo(USERS_CREATE_TIME_COLUMN, Long.class, null, null, false), temporaryColumnRenameCapture.getValue()); + } + private void validateCreateUserAuthenticationTable(Capture<List<DBAccessor.DBColumnInfo>> capturedData) { Assert.assertTrue(capturedData.hasCaptured()); List<List<DBAccessor.DBColumnInfo>> capturedValues = capturedData.getValues(); @@ -643,8 +687,8 @@ public class UpgradeCatalog270Test { new DBAccessor.DBColumnInfo(USER_AUTHENTICATION_USER_ID_COLUMN, Integer.class, null, null, false), new DBAccessor.DBColumnInfo(USER_AUTHENTICATION_AUTHENTICATION_TYPE_COLUMN, String.class, 50, null, false), new DBAccessor.DBColumnInfo(USER_AUTHENTICATION_AUTHENTICATION_KEY_COLUMN, String.class, 2048, null, true), - new DBAccessor.DBColumnInfo(USER_AUTHENTICATION_CREATE_TIME_COLUMN, Timestamp.class, null, null, true), - new DBAccessor.DBColumnInfo(USER_AUTHENTICATION_UPDATE_TIME_COLUMN, Timestamp.class, null, null, true) + new DBAccessor.DBColumnInfo(USER_AUTHENTICATION_CREATE_TIME_COLUMN, Long.class, null, null, true), + new DBAccessor.DBColumnInfo(USER_AUTHENTICATION_UPDATE_TIME_COLUMN, Long.class, null, null, true) ) ); } |