mirror of
				https://github.com/open-metadata/OpenMetadata.git
				synced 2025-10-31 10:39:30 +00:00 
			
		
		
		
	Fix Ldap Issue on Login
This commit is contained in:
		
							parent
							
								
									fe2681f022
								
							
						
					
					
						commit
						5a2fa9abcc
					
				| @ -454,6 +454,7 @@ public class OpenMetadataApplication extends Application<OpenMetadataApplication | |||||||
|             connectionType, |             connectionType, | ||||||
|             conf.getMigrationConfiguration().getExtensionPath(), |             conf.getMigrationConfiguration().getExtensionPath(), | ||||||
|             conf.getPipelineServiceClientConfiguration(), |             conf.getPipelineServiceClientConfiguration(), | ||||||
|  |             conf.getAuthenticationConfiguration(), | ||||||
|             false); |             false); | ||||||
|     migrationWorkflow.loadMigrations(); |     migrationWorkflow.loadMigrations(); | ||||||
|     migrationWorkflow.validateMigrationsForServer(); |     migrationWorkflow.validateMigrationsForServer(); | ||||||
|  | |||||||
| @ -9,6 +9,7 @@ import java.util.Map; | |||||||
| import lombok.Getter; | import lombok.Getter; | ||||||
| import lombok.extern.slf4j.Slf4j; | import lombok.extern.slf4j.Slf4j; | ||||||
| import org.jdbi.v3.core.Handle; | import org.jdbi.v3.core.Handle; | ||||||
|  | import org.openmetadata.schema.api.security.AuthenticationConfiguration; | ||||||
| import org.openmetadata.sdk.PipelineServiceClientInterface; | import org.openmetadata.sdk.PipelineServiceClientInterface; | ||||||
| import org.openmetadata.service.clients.pipeline.PipelineServiceClientFactory; | import org.openmetadata.service.clients.pipeline.PipelineServiceClientFactory; | ||||||
| import org.openmetadata.service.jdbi3.CollectionDAO; | import org.openmetadata.service.jdbi3.CollectionDAO; | ||||||
| @ -24,6 +25,7 @@ public class MigrationProcessImpl implements MigrationProcess { | |||||||
|   protected CollectionDAO collectionDAO; |   protected CollectionDAO collectionDAO; | ||||||
|   protected Handle handle; |   protected Handle handle; | ||||||
|   protected PipelineServiceClientInterface pipelineServiceClient; |   protected PipelineServiceClientInterface pipelineServiceClient; | ||||||
|  |   protected AuthenticationConfiguration authenticationConfiguration; | ||||||
|   private final MigrationFile migrationFile; |   private final MigrationFile migrationFile; | ||||||
| 
 | 
 | ||||||
|   public @Getter MigrationContext context; |   public @Getter MigrationContext context; | ||||||
| @ -40,6 +42,7 @@ public class MigrationProcessImpl implements MigrationProcess { | |||||||
|     this.pipelineServiceClient = |     this.pipelineServiceClient = | ||||||
|         PipelineServiceClientFactory.createPipelineServiceClient( |         PipelineServiceClientFactory.createPipelineServiceClient( | ||||||
|             this.migrationFile.pipelineServiceClientConfiguration); |             this.migrationFile.pipelineServiceClientConfiguration); | ||||||
|  |     this.authenticationConfiguration = migrationFile.authenticationConfiguration; | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   @Override |   @Override | ||||||
|  | |||||||
| @ -18,6 +18,7 @@ import org.jdbi.v3.core.Handle; | |||||||
| import org.jdbi.v3.core.Jdbi; | import org.jdbi.v3.core.Jdbi; | ||||||
| import org.json.JSONObject; | import org.json.JSONObject; | ||||||
| import org.openmetadata.schema.api.configuration.pipelineServiceClient.PipelineServiceClientConfiguration; | import org.openmetadata.schema.api.configuration.pipelineServiceClient.PipelineServiceClientConfiguration; | ||||||
|  | import org.openmetadata.schema.api.security.AuthenticationConfiguration; | ||||||
| import org.openmetadata.service.jdbi3.MigrationDAO; | import org.openmetadata.service.jdbi3.MigrationDAO; | ||||||
| import org.openmetadata.service.jdbi3.locator.ConnectionType; | import org.openmetadata.service.jdbi3.locator.ConnectionType; | ||||||
| import org.openmetadata.service.migration.QueryStatus; | import org.openmetadata.service.migration.QueryStatus; | ||||||
| @ -35,6 +36,7 @@ public class MigrationWorkflow { | |||||||
|   private final ConnectionType connectionType; |   private final ConnectionType connectionType; | ||||||
|   private final String extensionSQLScriptRootPath; |   private final String extensionSQLScriptRootPath; | ||||||
|   @Getter private final PipelineServiceClientConfiguration pipelineServiceClientConfiguration; |   @Getter private final PipelineServiceClientConfiguration pipelineServiceClientConfiguration; | ||||||
|  |   @Getter private final AuthenticationConfiguration authenticationConfiguration; | ||||||
|   private final MigrationDAO migrationDAO; |   private final MigrationDAO migrationDAO; | ||||||
|   private final Jdbi jdbi; |   private final Jdbi jdbi; | ||||||
|   private final boolean forceMigrations; |   private final boolean forceMigrations; | ||||||
| @ -47,6 +49,7 @@ public class MigrationWorkflow { | |||||||
|       ConnectionType connectionType, |       ConnectionType connectionType, | ||||||
|       String extensionSQLScriptRootPath, |       String extensionSQLScriptRootPath, | ||||||
|       PipelineServiceClientConfiguration pipelineServiceClientConfiguration, |       PipelineServiceClientConfiguration pipelineServiceClientConfiguration, | ||||||
|  |       AuthenticationConfiguration authenticationConfiguration, | ||||||
|       boolean forceMigrations) { |       boolean forceMigrations) { | ||||||
|     this.jdbi = jdbi; |     this.jdbi = jdbi; | ||||||
|     this.migrationDAO = jdbi.onDemand(MigrationDAO.class); |     this.migrationDAO = jdbi.onDemand(MigrationDAO.class); | ||||||
| @ -55,6 +58,7 @@ public class MigrationWorkflow { | |||||||
|     this.connectionType = connectionType; |     this.connectionType = connectionType; | ||||||
|     this.extensionSQLScriptRootPath = extensionSQLScriptRootPath; |     this.extensionSQLScriptRootPath = extensionSQLScriptRootPath; | ||||||
|     this.pipelineServiceClientConfiguration = pipelineServiceClientConfiguration; |     this.pipelineServiceClientConfiguration = pipelineServiceClientConfiguration; | ||||||
|  |     this.authenticationConfiguration = authenticationConfiguration; | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   public void loadMigrations() { |   public void loadMigrations() { | ||||||
| @ -64,7 +68,8 @@ public class MigrationWorkflow { | |||||||
|             nativeSQLScriptRootPath, |             nativeSQLScriptRootPath, | ||||||
|             connectionType, |             connectionType, | ||||||
|             extensionSQLScriptRootPath, |             extensionSQLScriptRootPath, | ||||||
|             pipelineServiceClientConfiguration); |             pipelineServiceClientConfiguration, | ||||||
|  |             authenticationConfiguration); | ||||||
|     // Filter Migrations to Be Run |     // Filter Migrations to Be Run | ||||||
|     this.migrations = filterAndGetMigrationsToRun(availableMigrations); |     this.migrations = filterAndGetMigrationsToRun(availableMigrations); | ||||||
|   } |   } | ||||||
| @ -83,10 +88,15 @@ public class MigrationWorkflow { | |||||||
|       String nativeSQLScriptRootPath, |       String nativeSQLScriptRootPath, | ||||||
|       ConnectionType connectionType, |       ConnectionType connectionType, | ||||||
|       String extensionSQLScriptRootPath, |       String extensionSQLScriptRootPath, | ||||||
|       PipelineServiceClientConfiguration pipelineServiceClientConfiguration) { |       PipelineServiceClientConfiguration pipelineServiceClientConfiguration, | ||||||
|  |       AuthenticationConfiguration authenticationConfiguration) { | ||||||
|     List<MigrationFile> availableOMNativeMigrations = |     List<MigrationFile> availableOMNativeMigrations = | ||||||
|         getMigrationFilesFromPath( |         getMigrationFilesFromPath( | ||||||
|             nativeSQLScriptRootPath, connectionType, pipelineServiceClientConfiguration, false); |             nativeSQLScriptRootPath, | ||||||
|  |             connectionType, | ||||||
|  |             pipelineServiceClientConfiguration, | ||||||
|  |             authenticationConfiguration, | ||||||
|  |             false); | ||||||
| 
 | 
 | ||||||
|     // If we only have OM migrations, return them |     // If we only have OM migrations, return them | ||||||
|     if (extensionSQLScriptRootPath == null || extensionSQLScriptRootPath.isEmpty()) { |     if (extensionSQLScriptRootPath == null || extensionSQLScriptRootPath.isEmpty()) { | ||||||
| @ -96,7 +106,11 @@ public class MigrationWorkflow { | |||||||
|     // Otherwise, fetch the extension migrations and sort the executions |     // Otherwise, fetch the extension migrations and sort the executions | ||||||
|     List<MigrationFile> availableExtensionMigrations = |     List<MigrationFile> availableExtensionMigrations = | ||||||
|         getMigrationFilesFromPath( |         getMigrationFilesFromPath( | ||||||
|             extensionSQLScriptRootPath, connectionType, pipelineServiceClientConfiguration, true); |             extensionSQLScriptRootPath, | ||||||
|  |             connectionType, | ||||||
|  |             pipelineServiceClientConfiguration, | ||||||
|  |             authenticationConfiguration, | ||||||
|  |             true); | ||||||
| 
 | 
 | ||||||
|     /* |     /* | ||||||
|      If we create migrations version as: |      If we create migrations version as: | ||||||
| @ -114,6 +128,7 @@ public class MigrationWorkflow { | |||||||
|       String path, |       String path, | ||||||
|       ConnectionType connectionType, |       ConnectionType connectionType, | ||||||
|       PipelineServiceClientConfiguration pipelineServiceClientConfiguration, |       PipelineServiceClientConfiguration pipelineServiceClientConfiguration, | ||||||
|  |       AuthenticationConfiguration authenticationConfiguration, | ||||||
|       Boolean isExtension) { |       Boolean isExtension) { | ||||||
|     return Arrays.stream(Objects.requireNonNull(new File(path).listFiles(File::isDirectory))) |     return Arrays.stream(Objects.requireNonNull(new File(path).listFiles(File::isDirectory))) | ||||||
|         .map( |         .map( | ||||||
| @ -123,6 +138,7 @@ public class MigrationWorkflow { | |||||||
|                     migrationDAO, |                     migrationDAO, | ||||||
|                     connectionType, |                     connectionType, | ||||||
|                     pipelineServiceClientConfiguration, |                     pipelineServiceClientConfiguration, | ||||||
|  |                     authenticationConfiguration, | ||||||
|                     isExtension)) |                     isExtension)) | ||||||
|         .sorted() |         .sorted() | ||||||
|         .toList(); |         .toList(); | ||||||
|  | |||||||
| @ -0,0 +1,21 @@ | |||||||
|  | package org.openmetadata.service.migration.mysql.v155; | ||||||
|  | 
 | ||||||
|  | import static org.openmetadata.service.migration.utils.v155.MigrationUtil.updateUserNameToEmailPrefixForLdapAuthProvider; | ||||||
|  | 
 | ||||||
|  | import lombok.SneakyThrows; | ||||||
|  | import org.openmetadata.service.migration.api.MigrationProcessImpl; | ||||||
|  | import org.openmetadata.service.migration.utils.MigrationFile; | ||||||
|  | 
 | ||||||
|  | public class Migration extends MigrationProcessImpl { | ||||||
|  | 
 | ||||||
|  |   public Migration(MigrationFile migrationFile) { | ||||||
|  |     super(migrationFile); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   @Override | ||||||
|  |   @SneakyThrows | ||||||
|  |   public void runDataMigration() { | ||||||
|  |     updateUserNameToEmailPrefixForLdapAuthProvider( | ||||||
|  |         handle, collectionDAO, authenticationConfiguration, false); | ||||||
|  |   } | ||||||
|  | } | ||||||
| @ -0,0 +1,21 @@ | |||||||
|  | package org.openmetadata.service.migration.postgres.v155; | ||||||
|  | 
 | ||||||
|  | import static org.openmetadata.service.migration.utils.v155.MigrationUtil.updateUserNameToEmailPrefixForLdapAuthProvider; | ||||||
|  | 
 | ||||||
|  | import lombok.SneakyThrows; | ||||||
|  | import org.openmetadata.service.migration.api.MigrationProcessImpl; | ||||||
|  | import org.openmetadata.service.migration.utils.MigrationFile; | ||||||
|  | 
 | ||||||
|  | public class Migration extends MigrationProcessImpl { | ||||||
|  | 
 | ||||||
|  |   public Migration(MigrationFile migrationFile) { | ||||||
|  |     super(migrationFile); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   @Override | ||||||
|  |   @SneakyThrows | ||||||
|  |   public void runDataMigration() { | ||||||
|  |     updateUserNameToEmailPrefixForLdapAuthProvider( | ||||||
|  |         handle, collectionDAO, authenticationConfiguration, true); | ||||||
|  |   } | ||||||
|  | } | ||||||
| @ -14,6 +14,7 @@ import org.flywaydb.core.internal.resource.filesystem.FileSystemResource; | |||||||
| import org.flywaydb.core.internal.sqlscript.SqlStatementIterator; | import org.flywaydb.core.internal.sqlscript.SqlStatementIterator; | ||||||
| import org.flywaydb.database.mysql.MySQLParser; | import org.flywaydb.database.mysql.MySQLParser; | ||||||
| import org.openmetadata.schema.api.configuration.pipelineServiceClient.PipelineServiceClientConfiguration; | import org.openmetadata.schema.api.configuration.pipelineServiceClient.PipelineServiceClientConfiguration; | ||||||
|  | import org.openmetadata.schema.api.security.AuthenticationConfiguration; | ||||||
| import org.openmetadata.service.jdbi3.MigrationDAO; | import org.openmetadata.service.jdbi3.MigrationDAO; | ||||||
| import org.openmetadata.service.jdbi3.locator.ConnectionType; | import org.openmetadata.service.jdbi3.locator.ConnectionType; | ||||||
| import org.openmetadata.service.util.EntityUtil; | import org.openmetadata.service.util.EntityUtil; | ||||||
| @ -23,6 +24,8 @@ public class MigrationFile implements Comparable<MigrationFile> { | |||||||
|   public final String version; |   public final String version; | ||||||
|   public final ConnectionType connectionType; |   public final ConnectionType connectionType; | ||||||
|   public final PipelineServiceClientConfiguration pipelineServiceClientConfiguration; |   public final PipelineServiceClientConfiguration pipelineServiceClientConfiguration; | ||||||
|  |   public final AuthenticationConfiguration authenticationConfiguration; | ||||||
|  | 
 | ||||||
|   public final File dir; |   public final File dir; | ||||||
|   public final Boolean isExtension; |   public final Boolean isExtension; | ||||||
|   public final String dbPackageName; |   public final String dbPackageName; | ||||||
| @ -38,6 +41,7 @@ public class MigrationFile implements Comparable<MigrationFile> { | |||||||
|       MigrationDAO migrationDAO, |       MigrationDAO migrationDAO, | ||||||
|       ConnectionType connectionType, |       ConnectionType connectionType, | ||||||
|       PipelineServiceClientConfiguration pipelineServiceClientConfiguration, |       PipelineServiceClientConfiguration pipelineServiceClientConfiguration, | ||||||
|  |       AuthenticationConfiguration authenticationConfiguration, | ||||||
|       Boolean isExtension) { |       Boolean isExtension) { | ||||||
|     this.dir = dir; |     this.dir = dir; | ||||||
|     this.isExtension = isExtension; |     this.isExtension = isExtension; | ||||||
| @ -45,6 +49,7 @@ public class MigrationFile implements Comparable<MigrationFile> { | |||||||
|     this.connectionType = connectionType; |     this.connectionType = connectionType; | ||||||
|     this.migrationDAO = migrationDAO; |     this.migrationDAO = migrationDAO; | ||||||
|     this.pipelineServiceClientConfiguration = pipelineServiceClientConfiguration; |     this.pipelineServiceClientConfiguration = pipelineServiceClientConfiguration; | ||||||
|  |     this.authenticationConfiguration = authenticationConfiguration; | ||||||
|     this.dbPackageName = connectionType == ConnectionType.MYSQL ? "mysql" : "postgres"; |     this.dbPackageName = connectionType == ConnectionType.MYSQL ? "mysql" : "postgres"; | ||||||
|     versionNumbers = convertToNumber(version); |     versionNumbers = convertToNumber(version); | ||||||
|     schemaChanges = new ArrayList<>(); |     schemaChanges = new ArrayList<>(); | ||||||
|  | |||||||
| @ -0,0 +1,60 @@ | |||||||
|  | package org.openmetadata.service.migration.utils.v155; | ||||||
|  | 
 | ||||||
|  | import java.util.List; | ||||||
|  | import lombok.extern.slf4j.Slf4j; | ||||||
|  | import org.jdbi.v3.core.Handle; | ||||||
|  | import org.openmetadata.schema.api.security.AuthenticationConfiguration; | ||||||
|  | import org.openmetadata.schema.entity.teams.User; | ||||||
|  | import org.openmetadata.schema.services.connections.metadata.AuthProvider; | ||||||
|  | import org.openmetadata.schema.utils.EntityInterfaceUtil; | ||||||
|  | import org.openmetadata.service.jdbi3.CollectionDAO; | ||||||
|  | import org.openmetadata.service.util.JsonUtils; | ||||||
|  | 
 | ||||||
|  | @Slf4j | ||||||
|  | public class MigrationUtil { | ||||||
|  |   public static void updateUserNameToEmailPrefixForLdapAuthProvider( | ||||||
|  |       Handle handle, | ||||||
|  |       CollectionDAO daoCollection, | ||||||
|  |       AuthenticationConfiguration config, | ||||||
|  |       boolean postgres) { | ||||||
|  |     if (config.getProvider().equals(AuthProvider.LDAP)) { | ||||||
|  |       LOG.info("Starting migration username -> email prefix"); | ||||||
|  |       int total = daoCollection.userDAO().listTotalCount(); | ||||||
|  |       int offset = 0; | ||||||
|  |       int limit = 200; | ||||||
|  |       while (offset < total) { | ||||||
|  |         List<String> userEntities = daoCollection.userDAO().listAfterWithOffset(limit, offset); | ||||||
|  |         for (String json : userEntities) { | ||||||
|  |           User userEntity = JsonUtils.readValue(json, User.class); | ||||||
|  |           String email = userEntity.getEmail(); | ||||||
|  |           String emailPrefix = email.substring(0, email.indexOf("@")); | ||||||
|  |           userEntity.setFullyQualifiedName(EntityInterfaceUtil.quoteName(emailPrefix)); | ||||||
|  |           userEntity.setName(emailPrefix); | ||||||
|  | 
 | ||||||
|  |           daoCollection.userDAO().update(userEntity); | ||||||
|  |         } | ||||||
|  |         offset = offset + limit; | ||||||
|  |       } | ||||||
|  | 
 | ||||||
|  |       updateUserEntityNameHash(handle, postgres); | ||||||
|  |       LOG.info("Completed migrating username -> email prefix"); | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   public static void updateUserEntityNameHash(Handle handle, boolean postgres) { | ||||||
|  |     String updateNameHashSql; | ||||||
|  |     if (postgres) { | ||||||
|  |       updateNameHashSql = "UPDATE user_entity SET nameHash = MD5(json ->> 'fullyQualifiedName');"; | ||||||
|  |     } else { | ||||||
|  |       updateNameHashSql = | ||||||
|  |           "UPDATE user_entity SET nameHash = MD5(JSON_UNQUOTE(JSON_EXTRACT(json, '$.fullyQualifiedName')));"; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     try { | ||||||
|  |       handle.execute(updateNameHashSql); | ||||||
|  |       LOG.info("Successfully updated nameHash for all user entities."); | ||||||
|  |     } catch (Exception e) { | ||||||
|  |       LOG.error("Error updating nameHash field", e); | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | } | ||||||
| @ -33,13 +33,13 @@ public interface AuthenticatorHandler { | |||||||
| 
 | 
 | ||||||
|   void checkIfLoginBlocked(String userName); |   void checkIfLoginBlocked(String userName); | ||||||
| 
 | 
 | ||||||
|   void recordFailedLoginAttempt(String providedIdentity, User user) |   void recordFailedLoginAttempt(String email, String userName) | ||||||
|       throws TemplateException, IOException; |       throws TemplateException, IOException; | ||||||
| 
 | 
 | ||||||
|   void validatePassword(String providedIdentity, User storedUser, String reqPassword) |   void validatePassword(String providedIdentity, String reqPassword, User omUser) | ||||||
|       throws TemplateException, IOException; |       throws TemplateException, IOException; | ||||||
| 
 | 
 | ||||||
|   User lookUserInProvider(String userName); |   User lookUserInProvider(String email, String pwd) throws TemplateException, IOException; | ||||||
| 
 | 
 | ||||||
|   default User registerUser(RegistrationRequest registrationRequest) { |   default User registerUser(RegistrationRequest registrationRequest) { | ||||||
|     throw new CustomExceptionMessage( |     throw new CustomExceptionMessage( | ||||||
|  | |||||||
| @ -83,6 +83,7 @@ import org.openmetadata.service.security.AuthenticationException; | |||||||
| import org.openmetadata.service.security.SecurityUtil; | import org.openmetadata.service.security.SecurityUtil; | ||||||
| import org.openmetadata.service.security.jwt.JWTTokenGenerator; | import org.openmetadata.service.security.jwt.JWTTokenGenerator; | ||||||
| import org.openmetadata.service.util.EmailUtil; | import org.openmetadata.service.util.EmailUtil; | ||||||
|  | import org.openmetadata.service.util.EmailUtil; | ||||||
| import org.openmetadata.service.util.EntityUtil; | import org.openmetadata.service.util.EntityUtil; | ||||||
| import org.openmetadata.service.util.JsonUtils; | import org.openmetadata.service.util.JsonUtils; | ||||||
| import org.openmetadata.service.util.PasswordUtil; | import org.openmetadata.service.util.PasswordUtil; | ||||||
| @ -261,7 +262,7 @@ public class BasicAuthenticator implements AuthenticatorHandler { | |||||||
| 
 | 
 | ||||||
|     // Update user about Password Change |     // Update user about Password Change | ||||||
|     try { |     try { | ||||||
|       EmailUtil.sendAccountStatus(storedUser, "Update Password", "Change Successful"); |       EmailUtil.sendAccountStatus(storedUser.getName(), storedUser.getEmail(), "Update Password", "Change Successful"); | ||||||
|     } catch (TemplateException ex) { |     } catch (TemplateException ex) { | ||||||
|       LOG.error("Error in sending Password Change Mail to User. Reason : " + ex.getMessage(), ex); |       LOG.error("Error in sending Password Change Mail to User. Reason : " + ex.getMessage(), ex); | ||||||
|       throw new CustomExceptionMessage(424, FAILED_SEND_EMAIL, EMAIL_SENDING_ISSUE); |       throw new CustomExceptionMessage(424, FAILED_SEND_EMAIL, EMAIL_SENDING_ISSUE); | ||||||
| @ -466,28 +467,29 @@ public class BasicAuthenticator implements AuthenticatorHandler { | |||||||
| 
 | 
 | ||||||
|   @Override |   @Override | ||||||
|   public JwtResponse loginUser(LoginRequest loginRequest) throws IOException, TemplateException { |   public JwtResponse loginUser(LoginRequest loginRequest) throws IOException, TemplateException { | ||||||
|     String userName = loginRequest.getEmail(); |     String email = loginRequest.getEmail(); | ||||||
|     checkIfLoginBlocked(userName); |     checkIfLoginBlocked(email); | ||||||
|     User storedUser = lookUserInProvider(userName); |     User storedUser = lookUserInProvider(email, loginRequest.getPassword()); | ||||||
|     validatePassword(userName, storedUser, loginRequest.getPassword()); |     validatePassword(email, loginRequest.getPassword(), storedUser); | ||||||
|     return getJwtResponse(storedUser, SecurityUtil.getLoginConfiguration().getJwtTokenExpiryTime()); |     return getJwtResponse(storedUser, SecurityUtil.getLoginConfiguration().getJwtTokenExpiryTime()); | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   @Override |   @Override | ||||||
|   public void checkIfLoginBlocked(String userName) { |   public void checkIfLoginBlocked(String email) { | ||||||
|     if (loginAttemptCache.isLoginBlocked(userName)) { |     if (loginAttemptCache.isLoginBlocked(email)) { | ||||||
|       throw new AuthenticationException(MAX_FAILED_LOGIN_ATTEMPT); |       throw new AuthenticationException(MAX_FAILED_LOGIN_ATTEMPT); | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   @Override |   @Override | ||||||
|   public void recordFailedLoginAttempt(String providedIdentity, User storedUser) |   public void recordFailedLoginAttempt(String email, String userName) | ||||||
|       throws TemplateException, IOException { |       throws TemplateException, IOException { | ||||||
|     loginAttemptCache.recordFailedLogin(providedIdentity); |     loginAttemptCache.recordFailedLogin(email); | ||||||
|     int failedLoginAttempt = loginAttemptCache.getUserFailedLoginCount(providedIdentity); |     int failedLoginAttempt = loginAttemptCache.getUserFailedLoginCount(email); | ||||||
|     if (failedLoginAttempt == SecurityUtil.getLoginConfiguration().getMaxLoginFailAttempts()) { |     if (failedLoginAttempt == SecurityUtil.getLoginConfiguration().getMaxLoginFailAttempts()) { | ||||||
|       EmailUtil.sendAccountStatus( |         EmailUtil.sendAccountStatus( | ||||||
|           storedUser, |           userName, | ||||||
|  |           email, | ||||||
|           "Multiple Failed Login Attempts.", |           "Multiple Failed Login Attempts.", | ||||||
|           String.format( |           String.format( | ||||||
|               "Someone is trying to access your account. Login is Blocked for %s minutes. Please change your password.", |               "Someone is trying to access your account. Login is Blocked for %s minutes. Please change your password.", | ||||||
| @ -495,35 +497,35 @@ public class BasicAuthenticator implements AuthenticatorHandler { | |||||||
|     } |     } | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   public void validatePassword(String providedIdentity, User storedUser, String reqPassword) |   public void validatePassword(String providedIdentity, String reqPassword, User omUser) | ||||||
|       throws TemplateException, IOException { |       throws TemplateException, IOException { | ||||||
|     // when basic auth is enabled and the user is created through the API without password, the |     // when basic auth is enabled and the user is created through the API without password, the | ||||||
|     // stored auth mechanism |     // stored auth mechanism | ||||||
|     // for the user is null |     // for the user is null | ||||||
|     if (storedUser.getAuthenticationMechanism() == null) { |     if (omUser.getAuthenticationMechanism() == null) { | ||||||
|       throw new AuthenticationException(INVALID_USERNAME_PASSWORD); |       throw new AuthenticationException(INVALID_USERNAME_PASSWORD); | ||||||
|     } |     } | ||||||
|     @SuppressWarnings("unchecked") |     @SuppressWarnings("unchecked") | ||||||
|     LinkedHashMap<String, String> storedData = |     LinkedHashMap<String, String> storedData = | ||||||
|         (LinkedHashMap<String, String>) storedUser.getAuthenticationMechanism().getConfig(); |         (LinkedHashMap<String, String>) omUser.getAuthenticationMechanism().getConfig(); | ||||||
|     String storedHashPassword = storedData.get("password"); |     String storedHashPassword = storedData.get("password"); | ||||||
|     if (!BCrypt.verifyer().verify(reqPassword.toCharArray(), storedHashPassword).verified) { |     if (!BCrypt.verifyer().verify(reqPassword.toCharArray(), storedHashPassword).verified) { | ||||||
|       // record Failed Login Attempts |       // record Failed Login Attempts | ||||||
|       recordFailedLoginAttempt(providedIdentity, storedUser); |       recordFailedLoginAttempt(omUser.getEmail(), omUser.getName()); | ||||||
|       throw new AuthenticationException(INVALID_USERNAME_PASSWORD); |       throw new AuthenticationException(INVALID_USERNAME_PASSWORD); | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   @Override |   @Override | ||||||
|   public User lookUserInProvider(String userName) { |   public User lookUserInProvider(String email, String pwd) { | ||||||
|     User storedUser = null; |     User storedUser = null; | ||||||
|     try { |     try { | ||||||
|       if (userName.contains("@")) { |       if (email.contains("@")) { | ||||||
|         // lookup by User Email |         // lookup by User Email | ||||||
|         storedUser = |         storedUser = | ||||||
|             userRepository.getByEmail( |             userRepository.getByEmail( | ||||||
|                 null, |                 null, | ||||||
|                 userName, |                 email, | ||||||
|                 new EntityUtil.Fields( |                 new EntityUtil.Fields( | ||||||
|                     Set.of(USER_PROTECTED_FIELDS, "roles"), "authenticationMechanism,roles")); |                     Set.of(USER_PROTECTED_FIELDS, "roles"), "authenticationMechanism,roles")); | ||||||
|       } |       } | ||||||
|  | |||||||
| @ -12,6 +12,8 @@ import static org.openmetadata.service.exception.CatalogExceptionMessage.LDAP_MI | |||||||
| import static org.openmetadata.service.exception.CatalogExceptionMessage.MAX_FAILED_LOGIN_ATTEMPT; | import static org.openmetadata.service.exception.CatalogExceptionMessage.MAX_FAILED_LOGIN_ATTEMPT; | ||||||
| import static org.openmetadata.service.exception.CatalogExceptionMessage.MULTIPLE_EMAIL_ENTRIES; | import static org.openmetadata.service.exception.CatalogExceptionMessage.MULTIPLE_EMAIL_ENTRIES; | ||||||
| import static org.openmetadata.service.exception.CatalogExceptionMessage.PASSWORD_RESET_TOKEN_EXPIRED; | import static org.openmetadata.service.exception.CatalogExceptionMessage.PASSWORD_RESET_TOKEN_EXPIRED; | ||||||
|  | import static org.openmetadata.service.exception.CatalogExceptionMessage.SELF_SIGNUP_DISABLED_MESSAGE; | ||||||
|  | import static org.openmetadata.service.exception.CatalogExceptionMessage.SELF_SIGNUP_NOT_ENABLED; | ||||||
| import static org.openmetadata.service.util.UserUtil.getRoleListFromUser; | import static org.openmetadata.service.util.UserUtil.getRoleListFromUser; | ||||||
| 
 | 
 | ||||||
| import com.fasterxml.jackson.core.JsonProcessingException; | import com.fasterxml.jackson.core.JsonProcessingException; | ||||||
| @ -86,6 +88,7 @@ public class LdapAuthenticator implements AuthenticatorHandler { | |||||||
|   private LoginAttemptCache loginAttemptCache; |   private LoginAttemptCache loginAttemptCache; | ||||||
|   private LdapConfiguration ldapConfiguration; |   private LdapConfiguration ldapConfiguration; | ||||||
|   private LDAPConnectionPool ldapLookupConnectionPool; |   private LDAPConnectionPool ldapLookupConnectionPool; | ||||||
|  |   private boolean isSelfSignUpEnabled; | ||||||
| 
 | 
 | ||||||
|   @Override |   @Override | ||||||
|   public void init(OpenMetadataApplicationConfig config) { |   public void init(OpenMetadataApplicationConfig config) { | ||||||
| @ -101,6 +104,7 @@ public class LdapAuthenticator implements AuthenticatorHandler { | |||||||
|     this.tokenRepository = Entity.getTokenRepository(); |     this.tokenRepository = Entity.getTokenRepository(); | ||||||
|     this.ldapConfiguration = config.getAuthenticationConfiguration().getLdapConfiguration(); |     this.ldapConfiguration = config.getAuthenticationConfiguration().getLdapConfiguration(); | ||||||
|     this.loginAttemptCache = new LoginAttemptCache(); |     this.loginAttemptCache = new LoginAttemptCache(); | ||||||
|  |     this.isSelfSignUpEnabled = config.getAuthenticationConfiguration().getEnableSelfSignup(); | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   private LDAPConnectionPool getLdapConnectionPool(LdapConfiguration ldapConfiguration) { |   private LDAPConnectionPool getLdapConnectionPool(LdapConfiguration ldapConfiguration) { | ||||||
| @ -139,10 +143,9 @@ public class LdapAuthenticator implements AuthenticatorHandler { | |||||||
| 
 | 
 | ||||||
|   @Override |   @Override | ||||||
|   public JwtResponse loginUser(LoginRequest loginRequest) throws IOException, TemplateException { |   public JwtResponse loginUser(LoginRequest loginRequest) throws IOException, TemplateException { | ||||||
|     checkIfLoginBlocked(loginRequest.getEmail()); |     String email = loginRequest.getEmail(); | ||||||
|     User storedUser = lookUserInProvider(loginRequest.getEmail()); |     checkIfLoginBlocked(email); | ||||||
|     validatePassword(storedUser.getEmail(), storedUser, loginRequest.getPassword()); |     User omUser = lookUserInProvider(email, loginRequest.getPassword()); | ||||||
|     User omUser = checkAndCreateUser(storedUser.getEmail(), storedUser.getName()); |  | ||||||
|     return getJwtResponse(omUser, SecurityUtil.getLoginConfiguration().getJwtTokenExpiryTime()); |     return getJwtResponse(omUser, SecurityUtil.getLoginConfiguration().getJwtTokenExpiryTime()); | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
| @ -150,28 +153,25 @@ public class LdapAuthenticator implements AuthenticatorHandler { | |||||||
|    * Check if the user exists in database by userName, if user exist, reassign roles for user according to it's ldap |    * Check if the user exists in database by userName, if user exist, reassign roles for user according to it's ldap | ||||||
|    * group else, create a new user and assign roles according to it's ldap group |    * group else, create a new user and assign roles according to it's ldap group | ||||||
|    * |    * | ||||||
|    * @param email email address of user |    * @param userDn userDn from LDAP | ||||||
|    * @param name userName of user |    * @param email Email of the User | ||||||
|    * @return user info |    * @return user info | ||||||
|    * @author Eric Wen@2023-07-16 17:06:43 |    * @author Eric Wen@2023-07-16 17:06:43 | ||||||
|    */ |    */ | ||||||
|   private User checkAndCreateUser(String email, String name) throws IOException { |   private User checkAndCreateUser(String userDn, String email, String userName) throws IOException { | ||||||
|     // Check if the user exists in OM Database |     // Check if the user exists in OM Database | ||||||
|     try { |     try { | ||||||
|       User omUser = |       User omUser = | ||||||
|           userRepository.getByName(null, name, userRepository.getFields("id,name,email,roles")); |           userRepository.getByEmail(null, email, userRepository.getFields("id,name,email,roles")); | ||||||
|       getRoleForLdap(omUser, Boolean.TRUE); |       getRoleForLdap(userDn, omUser, Boolean.TRUE); | ||||||
|       return omUser; |       return omUser; | ||||||
|     } catch (EntityNotFoundException ex) { |     } catch (EntityNotFoundException ex) { | ||||||
|       // User does not exist |       if (isSelfSignUpEnabled) { | ||||||
|       return userRepository.create(null, getUserForLdap(email, name)); |         return userRepository.create(null, getUserForLdap(userDn, email, userName)); | ||||||
|     } catch (LDAPException e) { |       } else { | ||||||
|       LOG.error( |         throw new CustomExceptionMessage( | ||||||
|           "An error occurs when reassigning roles for an LDAP user({}): {}", |             INTERNAL_SERVER_ERROR, SELF_SIGNUP_NOT_ENABLED, SELF_SIGNUP_DISABLED_MESSAGE); | ||||||
|           name, |       } | ||||||
|           e.getMessage(), |  | ||||||
|           e); |  | ||||||
|       throw new UnhandledServerException(e.getMessage()); |  | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
| @ -183,13 +183,14 @@ public class LdapAuthenticator implements AuthenticatorHandler { | |||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   @Override |   @Override | ||||||
|   public void recordFailedLoginAttempt(String providedIdentity, User storedUser) |   public void recordFailedLoginAttempt(String email, String userName) | ||||||
|       throws TemplateException, IOException { |       throws TemplateException, IOException { | ||||||
|     loginAttemptCache.recordFailedLogin(providedIdentity); |     loginAttemptCache.recordFailedLogin(email); | ||||||
|     int failedLoginAttempt = loginAttemptCache.getUserFailedLoginCount(providedIdentity); |     int failedLoginAttempt = loginAttemptCache.getUserFailedLoginCount(email); | ||||||
|     if (failedLoginAttempt == SecurityUtil.getLoginConfiguration().getMaxLoginFailAttempts()) { |     if (failedLoginAttempt == SecurityUtil.getLoginConfiguration().getMaxLoginFailAttempts()) { | ||||||
|       EmailUtil.sendAccountStatus( |       EmailUtil.sendAccountStatus( | ||||||
|           storedUser, |           userName, | ||||||
|  |           email, | ||||||
|           "Multiple Failed Login Attempts.", |           "Multiple Failed Login Attempts.", | ||||||
|           String.format( |           String.format( | ||||||
|               "Someone is tried accessing your account. Login is Blocked for %s seconds.", |               "Someone is tried accessing your account. Login is Blocked for %s seconds.", | ||||||
| @ -198,12 +199,12 @@ public class LdapAuthenticator implements AuthenticatorHandler { | |||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   @Override |   @Override | ||||||
|   public void validatePassword(String providedIdentity, User storedUser, String reqPassword) |   public void validatePassword(String userDn, String reqPassword, User dummy) | ||||||
|       throws TemplateException, IOException { |       throws TemplateException, IOException { | ||||||
|     // performed in LDAP , the storedUser's name set as DN of the User in Ldap |     // performed in LDAP , the storedUser's name set as DN of the User in Ldap | ||||||
|     BindResult bindingResult = null; |     BindResult bindingResult = null; | ||||||
|     try { |     try { | ||||||
|       bindingResult = ldapLookupConnectionPool.bind(storedUser.getName(), reqPassword); |       bindingResult = ldapLookupConnectionPool.bind(userDn, reqPassword); | ||||||
|       if (Objects.equals(bindingResult.getResultCode().getName(), ResultCode.SUCCESS.getName())) { |       if (Objects.equals(bindingResult.getResultCode().getName(), ResultCode.SUCCESS.getName())) { | ||||||
|         return; |         return; | ||||||
|       } |       } | ||||||
| @ -211,7 +212,7 @@ public class LdapAuthenticator implements AuthenticatorHandler { | |||||||
|       if (bindingResult != null |       if (bindingResult != null | ||||||
|           && Objects.equals( |           && Objects.equals( | ||||||
|               bindingResult.getResultCode().getName(), ResultCode.INVALID_CREDENTIALS.getName())) { |               bindingResult.getResultCode().getName(), ResultCode.INVALID_CREDENTIALS.getName())) { | ||||||
|         recordFailedLoginAttempt(providedIdentity, storedUser); |         recordFailedLoginAttempt(dummy.getEmail(), dummy.getName()); | ||||||
|         throw new CustomExceptionMessage( |         throw new CustomExceptionMessage( | ||||||
|             UNAUTHORIZED, INVALID_USER_OR_PASSWORD, INVALID_EMAIL_PASSWORD); |             UNAUTHORIZED, INVALID_USER_OR_PASSWORD, INVALID_EMAIL_PASSWORD); | ||||||
|       } |       } | ||||||
| @ -226,7 +227,20 @@ public class LdapAuthenticator implements AuthenticatorHandler { | |||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   @Override |   @Override | ||||||
|   public User lookUserInProvider(String email) { |   public User lookUserInProvider(String email, String pwd) throws TemplateException, IOException { | ||||||
|  |     String userDN = getUserDnFromLdap(email); | ||||||
|  | 
 | ||||||
|  |     if (!nullOrEmpty(userDN)) { | ||||||
|  |       User dummy = getUserForLdap(email); | ||||||
|  |       validatePassword(userDN, pwd, dummy); | ||||||
|  |       return checkAndCreateUser(userDN, email, dummy.getName()); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     throw new CustomExceptionMessage( | ||||||
|  |         INTERNAL_SERVER_ERROR, INVALID_USER_OR_PASSWORD, INVALID_EMAIL_PASSWORD); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   private String getUserDnFromLdap(String email) { | ||||||
|     try { |     try { | ||||||
|       Filter emailFilter = |       Filter emailFilter = | ||||||
|           Filter.createEqualityFilter(ldapConfiguration.getMailAttributeName(), email); |           Filter.createEqualityFilter(ldapConfiguration.getMailAttributeName(), email); | ||||||
| @ -245,8 +259,10 @@ public class LdapAuthenticator implements AuthenticatorHandler { | |||||||
|         Attribute emailAttr = |         Attribute emailAttr = | ||||||
|             searchResultEntry.getAttribute(ldapConfiguration.getMailAttributeName()); |             searchResultEntry.getAttribute(ldapConfiguration.getMailAttributeName()); | ||||||
| 
 | 
 | ||||||
|         if (!CommonUtil.nullOrEmpty(userDN) && emailAttr != null) { |         if (!CommonUtil.nullOrEmpty(userDN) | ||||||
|           return getUserForLdap(email).withName(userDN.toLowerCase()); |             && emailAttr != null | ||||||
|  |             && email.equalsIgnoreCase(emailAttr.getValue())) { | ||||||
|  |           return userDN; | ||||||
|         } else { |         } else { | ||||||
|           throw new CustomExceptionMessage(FORBIDDEN, INVALID_USER_OR_PASSWORD, LDAP_MISSING_ATTR); |           throw new CustomExceptionMessage(FORBIDDEN, INVALID_USER_OR_PASSWORD, LDAP_MISSING_ATTR); | ||||||
|         } |         } | ||||||
| @ -255,7 +271,7 @@ public class LdapAuthenticator implements AuthenticatorHandler { | |||||||
|             INTERNAL_SERVER_ERROR, MULTIPLE_EMAIL_ENTRIES, MULTIPLE_EMAIL_ENTRIES); |             INTERNAL_SERVER_ERROR, MULTIPLE_EMAIL_ENTRIES, MULTIPLE_EMAIL_ENTRIES); | ||||||
|       } else { |       } else { | ||||||
|         throw new CustomExceptionMessage( |         throw new CustomExceptionMessage( | ||||||
|             INTERNAL_SERVER_ERROR, MULTIPLE_EMAIL_ENTRIES, INVALID_EMAIL_PASSWORD); |             INTERNAL_SERVER_ERROR, INVALID_USER_OR_PASSWORD, INVALID_EMAIL_PASSWORD); | ||||||
|       } |       } | ||||||
|     } catch (LDAPException ex) { |     } catch (LDAPException ex) { | ||||||
|       throw new CustomExceptionMessage(INTERNAL_SERVER_ERROR, "LDAP_ERROR", ex.getMessage()); |       throw new CustomExceptionMessage(INTERNAL_SERVER_ERROR, "LDAP_ERROR", ex.getMessage()); | ||||||
| @ -270,15 +286,15 @@ public class LdapAuthenticator implements AuthenticatorHandler { | |||||||
|         .withAuthenticationMechanism(null); |         .withAuthenticationMechanism(null); | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   private User getUserForLdap(String email, String userName) { |   private User getUserForLdap(String ldapUserDn, String email, String userName) { | ||||||
|     User user = |     User user = | ||||||
|         UserUtil.getUser( |         UserUtil.getUser( | ||||||
|                 userName, new CreateUser().withName(userName).withEmail(email).withIsBot(false)) |                 userName, new CreateUser().withName(userName).withEmail(email).withIsBot(false)) | ||||||
|             .withIsEmailVerified(false) |             .withIsEmailVerified(false) | ||||||
|             .withAuthenticationMechanism(null); |             .withAuthenticationMechanism(null); | ||||||
|     try { |     try { | ||||||
|       getRoleForLdap(user, false); |       getRoleForLdap(ldapUserDn, user, false); | ||||||
|     } catch (LDAPException | JsonProcessingException e) { |     } catch (JsonProcessingException e) { | ||||||
|       LOG.error( |       LOG.error( | ||||||
|           "Failed to assign roles from LDAP to OpenMetadata for the user {} due to {}", |           "Failed to assign roles from LDAP to OpenMetadata for the user {} due to {}", | ||||||
|           user.getName(), |           user.getName(), | ||||||
| @ -294,8 +310,8 @@ public class LdapAuthenticator implements AuthenticatorHandler { | |||||||
|    * @param reAssign flag to decide whether to reassign roles |    * @param reAssign flag to decide whether to reassign roles | ||||||
|    * @author Eric Wen@2023-07-16 17:23:57 |    * @author Eric Wen@2023-07-16 17:23:57 | ||||||
|    */ |    */ | ||||||
|   private void getRoleForLdap(User user, Boolean reAssign) |   private void getRoleForLdap(String userDn, User user, Boolean reAssign) | ||||||
|       throws LDAPException, JsonProcessingException { |       throws JsonProcessingException { | ||||||
|     // Get user's groups from LDAP server using the DN of the user |     // Get user's groups from LDAP server using the DN of the user | ||||||
|     try { |     try { | ||||||
|       Filter groupFilter = |       Filter groupFilter = | ||||||
| @ -303,8 +319,7 @@ public class LdapAuthenticator implements AuthenticatorHandler { | |||||||
|               ldapConfiguration.getGroupAttributeName(), |               ldapConfiguration.getGroupAttributeName(), | ||||||
|               ldapConfiguration.getGroupAttributeValue()); |               ldapConfiguration.getGroupAttributeValue()); | ||||||
|       Filter groupMemberAttr = |       Filter groupMemberAttr = | ||||||
|           Filter.createEqualityFilter( |           Filter.createEqualityFilter(ldapConfiguration.getGroupMemberAttributeName(), userDn); | ||||||
|               ldapConfiguration.getGroupMemberAttributeName(), user.getName()); |  | ||||||
|       Filter groupAndMemberFilter = Filter.createANDFilter(groupFilter, groupMemberAttr); |       Filter groupAndMemberFilter = Filter.createANDFilter(groupFilter, groupMemberAttr); | ||||||
|       SearchRequest searchRequest = |       SearchRequest searchRequest = | ||||||
|           new SearchRequest( |           new SearchRequest( | ||||||
|  | |||||||
| @ -33,7 +33,7 @@ public class NoopAuthenticator implements AuthenticatorHandler { | |||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   @Override |   @Override | ||||||
|   public void recordFailedLoginAttempt(String providedIdentity, User user) { |   public void recordFailedLoginAttempt(String providedIdentity, String userName) { | ||||||
|     throw new CustomExceptionMessage( |     throw new CustomExceptionMessage( | ||||||
|         Response.Status.FORBIDDEN, |         Response.Status.FORBIDDEN, | ||||||
|         AUTHENTICATOR_OPERATION_NOT_SUPPORTED, |         AUTHENTICATOR_OPERATION_NOT_SUPPORTED, | ||||||
| @ -41,7 +41,7 @@ public class NoopAuthenticator implements AuthenticatorHandler { | |||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   @Override |   @Override | ||||||
|   public void validatePassword(String providedIdentity, User storedUser, String reqPassword) { |   public void validatePassword(String providedIdentity, String reqPassword, User storedUser) { | ||||||
|     throw new CustomExceptionMessage( |     throw new CustomExceptionMessage( | ||||||
|         Response.Status.FORBIDDEN, |         Response.Status.FORBIDDEN, | ||||||
|         AUTHENTICATOR_OPERATION_NOT_SUPPORTED, |         AUTHENTICATOR_OPERATION_NOT_SUPPORTED, | ||||||
| @ -49,7 +49,7 @@ public class NoopAuthenticator implements AuthenticatorHandler { | |||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   @Override |   @Override | ||||||
|   public User lookUserInProvider(String userName) { |   public User lookUserInProvider(String email, String pwd) { | ||||||
|     throw new CustomExceptionMessage( |     throw new CustomExceptionMessage( | ||||||
|         Response.Status.FORBIDDEN, |         Response.Status.FORBIDDEN, | ||||||
|         AUTHENTICATOR_OPERATION_NOT_SUPPORTED, |         AUTHENTICATOR_OPERATION_NOT_SUPPORTED, | ||||||
|  | |||||||
| @ -135,23 +135,23 @@ public class EmailUtil { | |||||||
|     return null; |     return null; | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   public static void sendAccountStatus(User user, String action, String status) |   public static void sendAccountStatus(String userName, String email, String action, String status) | ||||||
|       throws IOException, TemplateException { |       throws IOException, TemplateException { | ||||||
|     if (Boolean.TRUE.equals(getSmtpSettings().getEnableSmtpServer())) { |     if (Boolean.TRUE.equals(getSmtpSettings().getEnableSmtpServer())) { | ||||||
|       Map<String, Object> templatePopulator = new HashMap<>(); |       Map<String, Object> templatePopulator = new HashMap<>(); | ||||||
|       templatePopulator.put(ENTITY, getEmailingEntity()); |       templatePopulator.put(ENTITY, getEmailingEntity()); | ||||||
|       templatePopulator.put(SUPPORT_URL, getSupportUrl()); |       templatePopulator.put(SUPPORT_URL, getSupportUrl()); | ||||||
|       templatePopulator.put(USERNAME, user.getName()); |       templatePopulator.put(USERNAME, userName); | ||||||
|       templatePopulator.put(ACTION_KEY, action); |       templatePopulator.put(ACTION_KEY, action); | ||||||
|       templatePopulator.put(ACTION_STATUS_KEY, status); |       templatePopulator.put(ACTION_STATUS_KEY, status); | ||||||
|       sendMail( |       sendMail( | ||||||
|           getAccountStatusChangeSubject(), |           getAccountStatusChangeSubject(), | ||||||
|           templatePopulator, |           templatePopulator, | ||||||
|           user.getEmail(), |               email, | ||||||
|           ACCOUNT_STATUS_TEMPLATE_FILE, |           ACCOUNT_STATUS_TEMPLATE_FILE, | ||||||
|           true); |           true); | ||||||
|     } else { |     } else { | ||||||
|       LOG.warn(EMAIL_IGNORE_MSG, user.getEmail()); |       LOG.warn(EMAIL_IGNORE_MSG, email); | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -618,6 +618,7 @@ public class OpenMetadataOperations implements Callable<Integer> { | |||||||
|             connType, |             connType, | ||||||
|             extensionSQLScriptRootPath, |             extensionSQLScriptRootPath, | ||||||
|             config.getPipelineServiceClientConfiguration(), |             config.getPipelineServiceClientConfiguration(), | ||||||
|  |             config.getAuthenticationConfiguration(), | ||||||
|             force); |             force); | ||||||
|     workflow.loadMigrations(); |     workflow.loadMigrations(); | ||||||
|     workflow.printMigrationInfo(); |     workflow.printMigrationInfo(); | ||||||
|  | |||||||
| @ -48,6 +48,7 @@ import org.junit.jupiter.api.BeforeAll; | |||||||
| import org.junit.jupiter.api.TestInstance; | import org.junit.jupiter.api.TestInstance; | ||||||
| import org.openmetadata.common.utils.CommonUtil; | import org.openmetadata.common.utils.CommonUtil; | ||||||
| import org.openmetadata.schema.api.configuration.pipelineServiceClient.PipelineServiceClientConfiguration; | import org.openmetadata.schema.api.configuration.pipelineServiceClient.PipelineServiceClientConfiguration; | ||||||
|  | import org.openmetadata.schema.api.security.AuthenticationConfiguration; | ||||||
| import org.openmetadata.schema.service.configuration.elasticsearch.ElasticSearchConfiguration; | import org.openmetadata.schema.service.configuration.elasticsearch.ElasticSearchConfiguration; | ||||||
| import org.openmetadata.schema.type.IndexMappingLanguage; | import org.openmetadata.schema.type.IndexMappingLanguage; | ||||||
| import org.openmetadata.service.jdbi3.CollectionDAO; | import org.openmetadata.service.jdbi3.CollectionDAO; | ||||||
| @ -208,6 +209,7 @@ public abstract class OpenMetadataApplicationTest { | |||||||
|         nativeMigrationScriptsLocation, |         nativeMigrationScriptsLocation, | ||||||
|         extensionMigrationScripsLocation, |         extensionMigrationScripsLocation, | ||||||
|         null, |         null, | ||||||
|  |         null, | ||||||
|         false); |         false); | ||||||
|     createIndices(); |     createIndices(); | ||||||
|     APP.before(); |     APP.before(); | ||||||
| @ -221,6 +223,7 @@ public abstract class OpenMetadataApplicationTest { | |||||||
|       String nativeMigrationSQLPath, |       String nativeMigrationSQLPath, | ||||||
|       String extensionSQLScriptRootPath, |       String extensionSQLScriptRootPath, | ||||||
|       PipelineServiceClientConfiguration pipelineServiceClientConfiguration, |       PipelineServiceClientConfiguration pipelineServiceClientConfiguration, | ||||||
|  |       AuthenticationConfiguration authenticationConfiguration, | ||||||
|       boolean forceMigrations) { |       boolean forceMigrations) { | ||||||
|     DatasourceConfig.initialize(connType.label); |     DatasourceConfig.initialize(connType.label); | ||||||
|     MigrationWorkflow workflow = |     MigrationWorkflow workflow = | ||||||
| @ -230,6 +233,7 @@ public abstract class OpenMetadataApplicationTest { | |||||||
|             connType, |             connType, | ||||||
|             extensionSQLScriptRootPath, |             extensionSQLScriptRootPath, | ||||||
|             pipelineServiceClientConfiguration, |             pipelineServiceClientConfiguration, | ||||||
|  |             authenticationConfiguration, | ||||||
|             forceMigrations); |             forceMigrations); | ||||||
|     // Initialize search repository |     // Initialize search repository | ||||||
|     SearchRepository searchRepository = |     SearchRepository searchRepository = | ||||||
|  | |||||||
| @ -28,7 +28,7 @@ public class MigrationWorkflowTest extends OpenMetadataApplicationTest { | |||||||
|     migrationWorkflow = |     migrationWorkflow = | ||||||
|         spy( |         spy( | ||||||
|             new MigrationWorkflow( |             new MigrationWorkflow( | ||||||
|                 jdbi, "nativePath", ConnectionType.MYSQL, "extensionPath", null, false)); |                 jdbi, "nativePath", ConnectionType.MYSQL, "extensionPath", null, null, false)); | ||||||
| 
 | 
 | ||||||
|     omMigrationList = |     omMigrationList = | ||||||
|         List.of( |         List.of( | ||||||
| @ -37,18 +37,21 @@ public class MigrationWorkflowTest extends OpenMetadataApplicationTest { | |||||||
|                 null, |                 null, | ||||||
|                 ConnectionType.MYSQL, |                 ConnectionType.MYSQL, | ||||||
|                 migrationWorkflow.getPipelineServiceClientConfiguration(), |                 migrationWorkflow.getPipelineServiceClientConfiguration(), | ||||||
|  |                 migrationWorkflow.getAuthenticationConfiguration(), | ||||||
|                 false), |                 false), | ||||||
|             new MigrationFile( |             new MigrationFile( | ||||||
|                 new File("/bootstrap/sql/migrations/native/1.2.0"), |                 new File("/bootstrap/sql/migrations/native/1.2.0"), | ||||||
|                 null, |                 null, | ||||||
|                 ConnectionType.MYSQL, |                 ConnectionType.MYSQL, | ||||||
|                 migrationWorkflow.getPipelineServiceClientConfiguration(), |                 migrationWorkflow.getPipelineServiceClientConfiguration(), | ||||||
|  |                 migrationWorkflow.getAuthenticationConfiguration(), | ||||||
|                 false), |                 false), | ||||||
|             new MigrationFile( |             new MigrationFile( | ||||||
|                 new File("/bootstrap/sql/migrations/native/1.2.1"), |                 new File("/bootstrap/sql/migrations/native/1.2.1"), | ||||||
|                 null, |                 null, | ||||||
|                 ConnectionType.MYSQL, |                 ConnectionType.MYSQL, | ||||||
|                 migrationWorkflow.getPipelineServiceClientConfiguration(), |                 migrationWorkflow.getPipelineServiceClientConfiguration(), | ||||||
|  |                 migrationWorkflow.getAuthenticationConfiguration(), | ||||||
|                 false)); |                 false)); | ||||||
| 
 | 
 | ||||||
|     collateMigrationList = |     collateMigrationList = | ||||||
| @ -58,12 +61,14 @@ public class MigrationWorkflowTest extends OpenMetadataApplicationTest { | |||||||
|                 null, |                 null, | ||||||
|                 ConnectionType.MYSQL, |                 ConnectionType.MYSQL, | ||||||
|                 migrationWorkflow.getPipelineServiceClientConfiguration(), |                 migrationWorkflow.getPipelineServiceClientConfiguration(), | ||||||
|  |                 migrationWorkflow.getAuthenticationConfiguration(), | ||||||
|                 true), |                 true), | ||||||
|             new MigrationFile( |             new MigrationFile( | ||||||
|                 new File("/bootstrap-collate/sql/migrations/native/1.2.2-collate"), |                 new File("/bootstrap-collate/sql/migrations/native/1.2.2-collate"), | ||||||
|                 null, |                 null, | ||||||
|                 ConnectionType.MYSQL, |                 ConnectionType.MYSQL, | ||||||
|                 migrationWorkflow.getPipelineServiceClientConfiguration(), |                 migrationWorkflow.getPipelineServiceClientConfiguration(), | ||||||
|  |                 migrationWorkflow.getAuthenticationConfiguration(), | ||||||
|                 true)); |                 true)); | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
| @ -72,18 +77,19 @@ public class MigrationWorkflowTest extends OpenMetadataApplicationTest { | |||||||
|     Mockito.doReturn(omMigrationList) |     Mockito.doReturn(omMigrationList) | ||||||
|         .when(migrationWorkflow) |         .when(migrationWorkflow) | ||||||
|         .getMigrationFilesFromPath( |         .getMigrationFilesFromPath( | ||||||
|             eq("nativePath"), any(ConnectionType.class), eq(null), eq(false)); |             eq("nativePath"), any(ConnectionType.class), eq(null), eq(null), eq(false)); | ||||||
|     Mockito.doReturn(collateMigrationList) |     Mockito.doReturn(collateMigrationList) | ||||||
|         .when(migrationWorkflow) |         .when(migrationWorkflow) | ||||||
|         .getMigrationFilesFromPath( |         .getMigrationFilesFromPath( | ||||||
|             eq("extensionPath"), any(ConnectionType.class), eq(null), eq(true)); |             eq("extensionPath"), any(ConnectionType.class), eq(null), eq(null), eq(true)); | ||||||
| 
 | 
 | ||||||
|     List<MigrationFile> foundList = |     List<MigrationFile> foundList = | ||||||
|         migrationWorkflow.getMigrationFiles( |         migrationWorkflow.getMigrationFiles( | ||||||
|             "nativePath", |             "nativePath", | ||||||
|             ConnectionType.MYSQL, |             ConnectionType.MYSQL, | ||||||
|             "extensionPath", |             "extensionPath", | ||||||
|             migrationWorkflow.getPipelineServiceClientConfiguration()); |             migrationWorkflow.getPipelineServiceClientConfiguration(), | ||||||
|  |             migrationWorkflow.getAuthenticationConfiguration()); | ||||||
| 
 | 
 | ||||||
|     assertEquals( |     assertEquals( | ||||||
|         List.of("1.1.0", "1.1.0-collate", "1.2.0", "1.2.1", "1.2.2-collate"), |         List.of("1.1.0", "1.1.0-collate", "1.2.0", "1.2.1", "1.2.2-collate"), | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Siddhant
						Siddhant