Tony CHEMIT pushed to branch develop at ultreiaio / ird-observe Commits: 175475b0 by tchemit at 2019-06-28T15:50:09Z L'assistant migration via serveur pourrait refuser de continuer si l'utilisateur n'est pas assez acrédité - Closes #1145 Assistant création de base PG échoue - Closes #1331 - - - - - 15 changed files: - client-core/src/main/i18n/getters/java.getter - client-core/src/main/java/fr/ird/observe/client/db/ObserveDataSourcesManager.java - client-core/src/main/java/fr/ird/observe/client/db/ObserveSwingDataSource.java - client-core/src/main/java/fr/ird/observe/client/ui/actions/storage/presets/TestRemoteUIAction.java - client-core/src/main/java/fr/ird/observe/client/ui/actions/storage/presets/TestServerUIAction.java - client-core/src/main/java/fr/ird/observe/client/ui/admin/config/ConfigModel.java - client-core/src/main/java/fr/ird/observe/client/ui/storage/StorageUIHandler.java - client-core/src/main/java/fr/ird/observe/client/ui/storage/StorageUIModel.java - observe-i18n/src/main/i18n/translations/observe_en_GB.properties - observe-i18n/src/main/i18n/translations/observe_es_ES.properties - observe-i18n/src/main/i18n/translations/observe_fr_FR.properties - pom.xml - server-core/src/main/filtered-resources/mapping - services-local/src/main/java/fr/ird/observe/services/local/service/DataSourceServiceLocal.java - services/src/main/java/fr/ird/observe/services/service/DataSourceService.java Changes: ===================================== client-core/src/main/i18n/getters/java.getter ===================================== @@ -910,6 +910,7 @@ observe.storage.error.rest.user.required observe.storage.error.rest.user.unknown observe.storage.error.serverVersionMismatch observe.storage.error.serverVersionModelMismatch +observe.storage.error.user.not.owner observe.storage.internalDump.last.modified observe.storage.internalDump.not.exist observe.storage.label.data.import.db ===================================== client-core/src/main/java/fr/ird/observe/client/db/ObserveDataSourcesManager.java ===================================== @@ -125,7 +125,9 @@ public class ObserveDataSourcesManager implements Closeable { dataSource = newDataSource(configuration); break; } - + if (model.getDataSourceInformation() != null) { + dataSource.setOwner(model.getDataSourceInformation().isOwner()); + } return dataSource; } @@ -293,8 +295,8 @@ public class ObserveDataSourcesManager implements Closeable { try { - ObserveDataSourceInformation dataSourceInformation = dataSource.checkCanConnect(); - + ObserveDataSourceInformation dataSourceInformation = dataSource.checkCanConnect(false); + dataSource.setOwner(dataSourceInformation.isOwner()); dataSource.migrateDataIfPossible(dataSourceInformation, config.getModelVersion()); // la source sera utilisée dans les ui @@ -360,7 +362,8 @@ public class ObserveDataSourcesManager implements Closeable { try { - ObserveDataSourceInformation dataSourceInformation = dataSource.checkCanConnect(); + ObserveDataSourceInformation dataSourceInformation = dataSource.checkCanConnect(false); + dataSource.setOwner(dataSourceInformation.isOwner()); dataSource.migrateData(dataSourceInformation, config.getModelVersion()); ===================================== client-core/src/main/java/fr/ird/observe/client/db/ObserveSwingDataSource.java ===================================== @@ -151,6 +151,7 @@ public class ObserveSwingDataSource extends AbstractSerializableBean implements // indique si une modification a été effectuéé sur la base depuis son ouverture private boolean modified; + private boolean owner; public ObserveSwingDataSource(ObserveDataSourceConfiguration configuration) { this.configuration = configuration; @@ -223,7 +224,7 @@ public class ObserveSwingDataSource extends AbstractSerializableBean implements canWriteReferential(), canReadData(), canWriteData(), - getVersion(), + isOwner(), getVersion(), getVersion(), ImmutableList.of()); } @@ -395,6 +396,10 @@ public class ObserveSwingDataSource extends AbstractSerializableBean implements } + public boolean isOwner() { + return owner; + } + void migrateDataIfPossible(ObserveDataSourceInformation dataSourceInformation, Version targetVersion) { checkIsNotOpen(); @@ -445,10 +450,10 @@ public class ObserveSwingDataSource extends AbstractSerializableBean implements return connection != null; } - public ObserveDataSourceInformation checkCanConnect() throws DatabaseConnexionNotAuthorizedException, DatabaseNotFoundException { + public ObserveDataSourceInformation checkCanConnect(boolean canBeEmpty) throws DatabaseConnexionNotAuthorizedException, DatabaseNotFoundException { checkIsNotAlreadyOpen(); DataSourceService dataSourceService = servicesProvider.getDataSourceService(); - return dataSourceService.checkCanConnect(configuration); + return canBeEmpty ? dataSourceService.checkCanConnectOrBeEmpty(configuration) : dataSourceService.checkCanConnect(configuration); } public boolean isLocal() { @@ -828,4 +833,12 @@ public class ObserveSwingDataSource extends AbstractSerializableBean implements public void setProgressModel(ProgressModel progressModel) { this.progressModel = progressModel; } + + public void setOwner(boolean owner) { + this.owner = owner; + } + + public boolean getOwner() { + return owner; + } } ===================================== client-core/src/main/java/fr/ird/observe/client/ui/actions/storage/presets/TestRemoteUIAction.java ===================================== @@ -67,7 +67,8 @@ public class TestRemoteUIAction extends PresetsUIActionSupport { ObserveSwingDataSource dataSource = ObserveSwingApplicationContext.get().getDataSourcesManager().newDataSource(config); try { - ObserveDataSourceInformation dataSourceInformation = dataSource.checkCanConnect(); + ObserveDataSourceInformation dataSourceInformation = dataSource.checkCanConnect(false); + dataSource.setOwner(dataSourceInformation.isOwner()); Version versionDataSource = dataSourceInformation.getVersion(); ===================================== client-core/src/main/java/fr/ird/observe/client/ui/actions/storage/presets/TestServerUIAction.java ===================================== @@ -102,7 +102,7 @@ public class TestServerUIAction extends PresetsUIActionSupport { } if (connexionStatusError == null) { - ObserveDataSourceInformation dataSourceInformation = dataSource.checkCanConnect(); + ObserveDataSourceInformation dataSourceInformation = dataSource.checkCanConnect(false); Version versionDataSource = dataSourceInformation.getVersion(); ===================================== client-core/src/main/java/fr/ird/observe/client/ui/admin/config/ConfigModel.java ===================================== @@ -651,7 +651,7 @@ public class ConfigModel extends AdminActionModel { try { - localSourceInformation = localSource.checkCanConnect(); + localSourceInformation = localSource.checkCanConnect(false); } catch (Exception e) { //FIXME ! il faut faire quelque chose dans ce cas précis, au moins avertir l'utilisateur ===================================== client-core/src/main/java/fr/ird/observe/client/ui/storage/StorageUIHandler.java ===================================== @@ -554,8 +554,8 @@ public class StorageUIHandler implements UIHandler<StorageUI> { // si on utilise la base local on lance une migration de la base si necessaire if (DbMode.USE_LOCAL.equals((model.getDbMode()))) { - ObserveDataSourceInformation dataSourceInformation = currentDataSource.checkCanConnect(); - + ObserveDataSourceInformation dataSourceInformation = currentDataSource.checkCanConnect(false); + currentDataSource.setOwner(dataSourceInformation.isOwner()); progressModel.incrementsCurrentStep(); currentDataSource.migrateData(dataSourceInformation, config.getModelVersion()); ===================================== client-core/src/main/java/fr/ird/observe/client/ui/storage/StorageUIModel.java ===================================== @@ -1665,12 +1665,14 @@ public class StorageUIModel extends WizardModel<StorageStep> { if (!error) { - dataSourceInformation = dataSource.checkCanConnect(); + boolean createAction = ObstunaAdminAction.CREATE.equals(adminAction); + dataSourceInformation = dataSource.checkCanConnect(createAction); + dataSource.setOwner(dataSourceInformation.isOwner()); Version versionDataSource = dataSourceInformation.getVersion(); // en mise a jour de la base on ne test pas la version - if (getModelVersion().equals(versionDataSource) || isCanMigrate() || ObstunaAdminAction.CREATE.equals(adminAction)) { + if (isCanMigrate() || createAction || getModelVersion().equals(versionDataSource)) { setConnexionStatus(ConnexionStatus.SUCCESS); @@ -1738,6 +1740,16 @@ public class StorageUIModel extends WizardModel<StorageStep> { setBusy(false); } + if (result && dataSourceInformation != null && adminAction != null) { + + // must be owner of database to perform a such action + if (!dataSourceInformation.isOwner()) { + connexionStatusError = t("observe.storage.error.user.not.owner"); + log.error(connexionStatusError); + setConnexionStatus(ConnexionStatus.FAILED); + result = false; + } + } return result; } @@ -1949,7 +1961,7 @@ public class StorageUIModel extends WizardModel<StorageStep> { if (h2DataSourceInformation == null && localStorageExist) { ObserveSwingDataSource dataSource = ObserveSwingApplicationContext.get().getDataSourcesManager().newDataSource(h2Config); try { - h2DataSourceInformation = dataSource.checkCanConnect(); + h2DataSourceInformation = dataSource.checkCanConnect(false); } catch (Exception e) { if (log.isDebugEnabled()) { log.debug("error on load data source information for local storage", e); ===================================== observe-i18n/src/main/i18n/translations/observe_en_GB.properties ===================================== @@ -3049,6 +3049,7 @@ observe.storage.error.rest.user.required=User login is mandatory observe.storage.error.rest.user.unknown=User "%s" is not defined on server observe.storage.error.serverVersionMismatch=Remote server version (%s) is not compliant with the client version (%s) observe.storage.error.serverVersionModelMismatch=Remote server model version (%s) is not compliant with the client model version (%s) +observe.storage.error.user.not.owner=User must be owner of database to perform this action\! observe.storage.import.data.fromBackup=Import data from a backup of a local database (*.sql.gz) observe.storage.import.data.fromRemoteStorage=Import data from a remote database observe.storage.import.data.fromServerStorage=Import data from a remove server ===================================== observe-i18n/src/main/i18n/translations/observe_es_ES.properties ===================================== @@ -3049,6 +3049,7 @@ observe.storage.error.rest.user.required=El usuario es obligatorio observe.storage.error.rest.user.unknown=El usuario "%s" no es conocido del servidor observe.storage.error.serverVersionMismatch=La versión del servidor remoto (%s) no es compatible con la versión del modelo (%s) observe.storage.error.serverVersionModelMismatch=La version du modèle du serveur distant (%s) n'est pas compatible avec la version du modèle du client (%s) \#TODO +observe.storage.error.user.not.owner=User must be owner of database to perform this action\! \#TODO observe.storage.import.data.fromBackup=Importar los datos de una copia de seguridad de una base local (*.sql.gz) observe.storage.import.data.fromRemoteStorage=Importar los datos de una base remota observe.storage.import.data.fromServerStorage=Importar los datos de un servidor remoto ===================================== observe-i18n/src/main/i18n/translations/observe_fr_FR.properties ===================================== @@ -3049,6 +3049,7 @@ observe.storage.error.rest.user.required=L'utilisateur est obligatoire observe.storage.error.rest.user.unknown=L'utilisateur "%s" est inconnu sur le serveur observe.storage.error.serverVersionMismatch=La version du serveur distant (%s) n'est pas compatible avec la version du client (%s) observe.storage.error.serverVersionModelMismatch=La version du modèle du serveur distant (%s) n'est pas compatible avec la version du modèle du client (%s) +observe.storage.error.user.not.owner=L'utilisateur doit être le propriétaire de la base pour effectuer cette opération \! observe.storage.import.data.fromBackup=Importer les données depuis une sauvegarde de base locale (*.sql.gz) observe.storage.import.data.fromRemoteStorage=Importer les données depuis une base distante observe.storage.import.data.fromServerStorage=Importer les données depuis un serveur distant ===================================== pom.xml ===================================== @@ -26,7 +26,7 @@ <parent> <groupId>io.ultreia.maven</groupId> <artifactId>pom</artifactId> - <version>2019.8.22</version> + <version>2019.8.23</version> </parent> <groupId>fr.ird.observe</groupId> @@ -156,7 +156,7 @@ <maven.build.timestamp.format>dd/MM/yyyy HH:mm z</maven.build.timestamp.format> <buildDate>${maven.build.timestamp}</buildDate> - <observeToolkitVersion>4.13</observeToolkitVersion> + <observeToolkitVersion>4.14-SNAPSHOT</observeToolkitVersion> <lib.version.nuiton.validation>3.1</lib.version.nuiton.validation> <!--can't use 1.4.197 (date has changed + blob also)--> <lib.version.h2>1.4.196</lib.version.h2> ===================================== server-core/src/main/filtered-resources/mapping ===================================== @@ -56,6 +56,7 @@ GET /admin/configuration/resetAuthenticationTokens ConfigurationCo GET /api/v1/DataSourceService/applySecurity v1.DataSourceServiceRestApi.applySecurity GET /api/v1/DataSourceService/backup v1.DataSourceServiceRestApi.backup GET /api/v1/DataSourceService/checkCanConnect v1.DataSourceServiceRestApi.checkCanConnect +GET /api/v1/DataSourceService/checkCanConnectOrBeEmpty v1.DataSourceServiceRestApi.checkCanConnectOrBeEmpty GET /api/v1/DataSourceService/close v1.DataSourceServiceRestApi.close GET /api/v1/DataSourceService/create v1.DataSourceServiceRestApi.create GET /api/v1/DataSourceService/destroy v1.DataSourceServiceRestApi.destroy ===================================== services-local/src/main/java/fr/ird/observe/services/local/service/DataSourceServiceLocal.java ===================================== @@ -27,12 +27,12 @@ import com.google.common.collect.ImmutableSet; import fr.ird.observe.dto.ObserveDbRole; import fr.ird.observe.dto.db.ObserveDbUserDto; import fr.ird.observe.dto.reference.ReferentialDtoReference; -import fr.ird.observe.entities.referential.ObserveReferentialEntity; import fr.ird.observe.entities.ObserveEntityEnum; import fr.ird.observe.entities.ObserveTopiaApplicationContext; import fr.ird.observe.entities.ObserveTopiaConfiguration; import fr.ird.observe.entities.ObserveTopiaConfigurationFactory; import fr.ird.observe.entities.migration.ObserveTopiaMigrationServiceAskUserToMigrate; +import fr.ird.observe.entities.referential.ObserveReferentialEntity; import fr.ird.observe.services.configuration.DataSourceCreateConfigurationDto; import fr.ird.observe.services.configuration.DataSourceCreateWithNoReferentialImportException; import fr.ird.observe.services.configuration.IncompatibleDataSourceCreateConfigurationException; @@ -53,8 +53,8 @@ import fr.ird.observe.services.service.DatabaseNotFoundException; import fr.ird.observe.services.service.sql.AddSqlScriptProducerRequest; import fr.ird.observe.services.service.sql.SqlScriptProducerService; import fr.ird.observe.spi.DbModelHelper; -import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; import org.nuiton.topia.persistence.jdbc.JdbcHelper; import org.nuiton.topia.persistence.jdbc.JdbcPostgresHelper; import org.nuiton.topia.persistence.metadata.TopiaMetadataEntity; @@ -71,6 +71,7 @@ import java.io.File; import java.io.IOException; import java.nio.file.Files; import java.util.LinkedHashSet; +import java.util.Objects; import java.util.Optional; import java.util.Set; import java.util.UUID; @@ -98,6 +99,96 @@ public class DataSourceServiceLocal extends ObserveServiceLocal implements DataS return privileges != null && !privileges.isEmpty(); } + private static boolean isOwner(ObserveDataSourceConfigurationTopiaSupport dataSourceConfiguration, JdbcPostgresHelper jdbcHelper) { + if (dataSourceConfiguration.isH2Database()) { + return true; + } + String ownerName = jdbcHelper.runSelectOnString("SELECT pg_catalog.pg_get_userbyid(d.datdba) FROM pg_catalog.pg_database d WHERE d.datname = (SELECT current_database())\n"); + return Objects.equals(dataSourceConfiguration.getUsername(), ownerName); + } + + @Override + public ObserveDataSourceInformation checkCanConnectOrBeEmpty(ObserveDataSourceConfiguration dataSourceConfiguration) throws DatabaseNotFoundException, DatabaseConnexionNotAuthorizedException { + Preconditions.checkState(dataSourceConfiguration instanceof ObserveDataSourceConfigurationTopiaSupport); + ObserveDataSourceConfigurationTopiaSupport dataSourceConfigurationTopiaSupport = (ObserveDataSourceConfigurationTopiaSupport) dataSourceConfiguration; + + ObserveDataSourceInformation dataSourceInformation; + + if (dataSourceConfigurationTopiaSupport.isH2Database()) { + + ObserveDataSourceConfigurationTopiaH2 h2DataSourceConfiguration = (ObserveDataSourceConfigurationTopiaH2) dataSourceConfigurationTopiaSupport; + + // On vérifie que le fichier de la base existe + File databaseFile = h2DataSourceConfiguration.getDatabaseFile(); + + if (!databaseFile.exists()) { + + String message = l(getApplicationLocale(), "observe.services.topia.error.h2.database.notFound"); + throw new DatabaseNotFoundException(message, dataSourceConfiguration); + + } + + // On vérifier que la base n'est pas déjà en cours d'utilisation + File databaseLockFile = h2DataSourceConfiguration.getLockFile(); + if (databaseLockFile.exists()) { + + String message = l(getApplicationLocale(), "observe.services.topia.error.h2.database.locked"); + if (log.isWarnEnabled()) { + log.warn(message); + } + // FIXME even if file is lock we still authorize to connect, + //throw new DatabaseConnexionNotAuthorizedException(message, dataSourceConfiguration); + } + + // On tente une connection à la base + ObserveTopiaConfiguration topiaConfiguration = ObserveTopiaConfigurationFactory.forH2Database(h2DataSourceConfiguration.getDirectory(), + h2DataSourceConfiguration.getDbName(), + h2DataSourceConfiguration.getUsername(), + new String(h2DataSourceConfiguration.getPassword()), + false, + false); + + + try { + new JdbcHelper(topiaConfiguration).runSelectOnString("SELECT 1;"); + } catch (Exception e) { + + // Authentification refusée + String message = l(getApplicationLocale(), "observe.services.topia.error.h2.database.badAuthentication"); + throw new DatabaseConnexionNotAuthorizedException(message, e, dataSourceConfiguration); + + } + + dataSourceInformation = getDataSourceInformation(h2DataSourceConfiguration, topiaConfiguration, false); + + + } else { + + ObserveDataSourceConfigurationTopiaPG pgDataSourceConfiguration = (ObserveDataSourceConfigurationTopiaPG) dataSourceConfigurationTopiaSupport; + // On tente une connexion au serveur + ObserveTopiaConfiguration topiaConfiguration = ObserveTopiaConfigurationFactory.forPostgresqlDatabase(pgDataSourceConfiguration.getJdbcUrl(), + pgDataSourceConfiguration.getUsername(), + new String(pgDataSourceConfiguration.getPassword()), + false, + false); + + try { + new JdbcHelper(topiaConfiguration).runSelectOnString("SELECT 1;"); + } catch (Exception e) { + + throw new DatabaseConnexionNotAuthorizedException(e.getMessage(), e, dataSourceConfiguration); + + } + + dataSourceInformation = getDataSourceInformation(pgDataSourceConfiguration, topiaConfiguration, true); + + } + + return dataSourceInformation; + + } + + @Override public ObserveDataSourceInformation checkCanConnect(ObserveDataSourceConfiguration dataSourceConfiguration) throws DatabaseNotFoundException, DatabaseConnexionNotAuthorizedException { @@ -151,7 +242,7 @@ public class DataSourceServiceLocal extends ObserveServiceLocal implements DataS } - dataSourceInformation = getDataSourceInformation(h2DataSourceConfiguration, topiaConfiguration); + dataSourceInformation = getDataSourceInformation(h2DataSourceConfiguration, topiaConfiguration, false); } else { @@ -172,7 +263,7 @@ public class DataSourceServiceLocal extends ObserveServiceLocal implements DataS } - dataSourceInformation = getDataSourceInformation(pgDataSourceConfiguration, topiaConfiguration); + dataSourceInformation = getDataSourceInformation(pgDataSourceConfiguration, topiaConfiguration, false); } @@ -359,7 +450,7 @@ public class DataSourceServiceLocal extends ObserveServiceLocal implements DataS } - ObserveDataSourceInformation dataSourceInformation = getDataSourceInformation((ObserveDataSourceConfigurationTopiaSupport) dataSourceConfiguration, topiaApplicationContext.getConfiguration()); + ObserveDataSourceInformation dataSourceInformation = getDataSourceInformation((ObserveDataSourceConfigurationTopiaSupport) dataSourceConfiguration, topiaApplicationContext.getConfiguration(), false); return createDataSourceConnection(dataSourceInformation, topiaApplicationContext.getAuthenticationToken()); @@ -529,7 +620,7 @@ public class DataSourceServiceLocal extends ObserveServiceLocal implements DataS dataSourceInformation.getVersion()); } - private ObserveDataSourceInformation getDataSourceInformation(ObserveDataSourceConfigurationTopiaSupport dataSourceConfiguration, ObserveTopiaConfiguration topiaConfiguration) { + private ObserveDataSourceInformation getDataSourceInformation(ObserveDataSourceConfigurationTopiaSupport dataSourceConfiguration, ObserveTopiaConfiguration topiaConfiguration, boolean canBeEmpty) { boolean writeReferential; boolean readData; @@ -538,8 +629,37 @@ public class DataSourceServiceLocal extends ObserveServiceLocal implements DataS Version version; JdbcPostgresHelper jdbcHelper = new JdbcPostgresHelper(topiaConfiguration); + boolean owner = isOwner(dataSourceConfiguration, jdbcHelper); - version = TMSVersionHibernateDao.getVersion(jdbcHelper, "tms_version").map(TMSVersion::toVersion).orElse(Version.VZERO); + try { + version = TMSVersionHibernateDao.getVersion(jdbcHelper, "tms_version").map(TMSVersion::toVersion).orElse(Version.VZERO); + } catch (Exception e) { + if (!canBeEmpty) { + throw e; + } + if (dataSourceConfiguration.isH2Database()) { + + // Sur une base H2, on a le droit de tout lire, mais uniquement d'écrire les données + writeReferential = false; + readData = true; + writeData = true; + owner = true; + + } else { + writeReferential = true; + readData = true; + writeData = true; + } + return new ObserveDataSourceInformation( + true, + writeReferential, + readData, + writeData, + owner, + ObserveTopiaMigrationServiceAskUserToMigrate.getMinimumVersion(), + null, + null); + } if (dataSourceConfiguration.isH2Database()) { @@ -591,6 +711,7 @@ public class DataSourceServiceLocal extends ObserveServiceLocal implements DataS writeReferential, readData, writeData, + owner, ObserveTopiaMigrationServiceAskUserToMigrate.getMinimumVersion(), version, observeMigrationConfigurationProvider.getVersionsAfter(version)); ===================================== services/src/main/java/fr/ird/observe/services/service/DataSourceService.java ===================================== @@ -47,6 +47,9 @@ public interface DataSourceService extends ObserveService, Closeable { @Get(addAuthtoken = false) ObserveDataSourceInformation checkCanConnect(ObserveDataSourceConfiguration dataSourceConfiguration) throws DatabaseNotFoundException, DatabaseConnexionNotAuthorizedException; + @Get(addAuthtoken = false) + ObserveDataSourceInformation checkCanConnectOrBeEmpty(ObserveDataSourceConfiguration dataSourceConfiguration) throws DatabaseNotFoundException, DatabaseConnexionNotAuthorizedException; + @Get(addAuthtoken = false) ObserveDataSourceConnection create(ObserveDataSourceConfiguration dataSourceConfiguration, DataSourceCreateConfigurationDto dataSourceCreateConfiguration) throws IncompatibleDataSourceCreateConfigurationException, DataSourceCreateWithNoReferentialImportException, View it on GitLab: https://gitlab.com/ultreiaio/ird-observe/commit/175475b05d24bab72165a29e2e15... -- View it on GitLab: https://gitlab.com/ultreiaio/ird-observe/commit/175475b05d24bab72165a29e2e15... You're receiving this email because of your account on gitlab.com.