You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@streampipes.apache.org by ri...@apache.org on 2021/10/01 17:56:12 UTC
[incubator-streampipes] branch STREAMPIPES-426 updated:
[STREAMPIPES-434] Add auto-setup and service account model
This is an automated email from the ASF dual-hosted git repository.
riemer pushed a commit to branch STREAMPIPES-426
in repository https://gitbox.apache.org/repos/asf/incubator-streampipes.git
The following commit(s) were added to refs/heads/STREAMPIPES-426 by this push:
new a35c731 [STREAMPIPES-434] Add auto-setup and service account model
a35c731 is described below
commit a35c73185c5421bcc50f05bade1c1a1e11661b76
Author: Dominik Riemer <ri...@fzi.de>
AuthorDate: Fri Oct 1 19:56:02 2021 +0200
[STREAMPIPES-434] Add auto-setup and service account model
---
pom.xml | 23 +-
.../backend/StreamPipesBackendApplication.java | 21 ++
.../apache/streampipes/commons/constants/Envs.java | 11 +-
.../commons/constants/InstallationConstants.java | 25 +-
.../streampipes/config/backend/BackendConfig.java | 10 +
.../config/backend/BackendConfigKeys.java | 1 +
streampipes-model-client/pom.xml | 4 +
.../model/client/setup/InitialSettings.java | 46 ++-
.../streampipes/model/client/user/Authc.java | 44 ---
.../streampipes/model/client/user/Authz.java | 47 ---
.../apache/streampipes/model/client/user/Info.java | 51 ---
...uthenticationRequest.java => LoginRequest.java} | 6 +-
.../streampipes/model/client/user/Principal.java | 188 +++++++++--
.../user/{Credentials.java => PrincipalType.java} | 20 +-
.../model/client/user/ServiceAccount.java | 68 ++++
.../client/user/ShiroAuthenticationResponse.java | 65 ----
.../user/ShiroAuthenticationResponseFactory.java | 40 ---
.../apache/streampipes/model/client/user/User.java | 266 ----------------
.../streampipes/model/client/user/UserAccount.java | 185 +++++++++++
.../manager/setup/AutoInstallation.java | 119 +++++++
.../manager/setup/CouchDbInstallationStep.java | 346 +++++++++++----------
.../manager/setup/InstallationConfiguration.java | 8 +-
.../manager/setup/InstallationStep.java | 33 +-
.../streampipes/manager/setup/Installer.java | 52 ----
.../setup/PipelineElementInstallationStep.java | 19 +-
.../setup/UserRegistrationInstallationStep.java | 52 +++-
.../manager/storage/UserManagementService.java | 8 +-
.../streampipes/manager/storage/UserService.java | 79 ++---
.../rest/filter/TokenAuthenticationFilter.java | 3 +-
.../streampipes/rest/impl/Authentication.java | 7 +-
.../org/apache/streampipes/rest/impl/Setup.java | 23 +-
.../apache/streampipes/rest/impl/UserProfile.java | 13 +-
streampipes-security-jwt/pom.xml | 34 ++
.../streampipes/security/jwt/JwtTokenUtils.java | 78 +++++
.../serializers/json/GsonSerializer.java | 14 +-
.../serializers/json/PrincipalDeserializer.java | 67 ++++
.../streampipes/storage/api/IUserStorage.java | 20 +-
.../storage/couchdb/impl/UserStorage.java | 55 +++-
.../streampipes/storage/couchdb/utils/Utils.java | 10 +-
streampipes-user-management/pom.xml | 5 +
.../user/management/jwt/JwtTokenProvider.java | 46 +--
.../user/management/model/LocalUser.java | 82 -----
.../management/service/SpUserDetailsService.java | 6 +-
.../user/management/service/TokenService.java | 24 +-
.../app/core-model/gen/streampipes-model-client.ts | 97 ++++--
.../apis/pipeline-template.service.ts | 4 +-
.../profile/components/basic-profile-settings.ts | 4 +-
ui/src/app/profile/profile.module.ts | 2 +
ui/src/app/profile/profile.service.ts | 8 +-
49 files changed, 1315 insertions(+), 1124 deletions(-)
diff --git a/pom.xml b/pom.xml
index 43a8c62..859d485 100644
--- a/pom.xml
+++ b/pom.xml
@@ -102,6 +102,7 @@
<spark.version>2.1.2</spark.version>
<spring.version>5.3.10</spring.version>
<spring-boot.version>2.5.5</spring-boot.version>
+ <spring-security.version>5.5.2</spring-security.version>
<swagger.version>2.1.6</swagger.version>
<type-parser.version>0.6.0</type-parser.version>
<underscore.version>1.47</underscore.version>
@@ -200,7 +201,7 @@
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
- <version>2.8.7</version>
+ <version>2.8.8</version>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
@@ -683,6 +684,11 @@
<version>${spring.version}</version>
</dependency>
<dependency>
+ <groupId>org.springframework.security</groupId>
+ <artifactId>spring-security-core</artifactId>
+ <version>${spring-security.version}</version>
+ </dependency>
+ <dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>${spring.version}</version>
@@ -832,12 +838,14 @@
<module>streampipes-commons</module>
<module>streampipes-config</module>
<module>streampipes-connect</module>
+ <module>streampipes-connect-api</module>
<module>streampipes-connect-container-master</module>
<module>streampipes-connect-container-worker</module>
<module>streampipes-container</module>
<module>streampipes-container-base</module>
<module>streampipes-container-extensions</module>
<module>streampipes-container-standalone</module>
+ <module>streampipes-data-explorer</module>
<module>streampipes-dataformat</module>
<module>streampipes-dataformat-cbor</module>
<module>streampipes-dataformat-fst</module>
@@ -858,9 +866,15 @@
<module>streampipes-pipeline-management</module>
<module>streampipes-sources</module>
<module>streampipes-rest</module>
+ <module>streampipes-rest-core-base</module>
<module>streampipes-rest-shared</module>
<module>streampipes-sdk</module>
+ <module>streampipes-security-jwt</module>
<module>streampipes-serializers-json</module>
+ <module>streampipes-service-discovery</module>
+ <module>streampipes-service-discovery-consul</module>
+ <module>streampipes-service-discovery-api</module>
+ <module>streampipes-service-extensions-base</module>
<module>streampipes-storage-api</module>
<module>streampipes-storage-management</module>
<module>streampipes-storage-couchdb</module>
@@ -875,13 +889,6 @@
<module>streampipes-wrapper-siddhi</module>
<module>streampipes-wrapper-spark</module>
<module>streampipes-wrapper-standalone</module>
- <module>streampipes-data-explorer</module>
- <module>streampipes-service-discovery</module>
- <module>streampipes-service-discovery-consul</module>
- <module>streampipes-service-discovery-api</module>
- <module>streampipes-connect-api</module>
- <module>streampipes-service-extensions-base</module>
- <module>streampipes-rest-core-base</module>
</modules>
<profiles>
diff --git a/streampipes-backend/src/main/java/org/apache/streampipes/backend/StreamPipesBackendApplication.java b/streampipes-backend/src/main/java/org/apache/streampipes/backend/StreamPipesBackendApplication.java
index 3ece3e7..721c159 100644
--- a/streampipes-backend/src/main/java/org/apache/streampipes/backend/StreamPipesBackendApplication.java
+++ b/streampipes-backend/src/main/java/org/apache/streampipes/backend/StreamPipesBackendApplication.java
@@ -17,10 +17,12 @@
*/
package org.apache.streampipes.backend;
+import org.apache.streampipes.config.backend.BackendConfig;
import org.apache.streampipes.container.base.BaseNetworkingConfig;
import org.apache.streampipes.container.base.StreamPipesServiceBase;
import org.apache.streampipes.manager.health.PipelineHealthCheck;
import org.apache.streampipes.manager.operations.Operations;
+import org.apache.streampipes.manager.setup.AutoInstallation;
import org.apache.streampipes.model.pipeline.Pipeline;
import org.apache.streampipes.model.pipeline.PipelineOperationStatus;
import org.apache.streampipes.rest.notifications.NotificationListener;
@@ -90,12 +92,31 @@ public class StreamPipesBackendApplication extends StreamPipesServiceBase {
this.executorService = Executors.newSingleThreadScheduledExecutor();
this.healthCheckExecutorService = Executors.newSingleThreadScheduledExecutor();
+ if (!isConfigured()) {
+ doInitialSetup();
+ }
+
+ new NotificationListener().contextInitialized(null);
executorService.schedule(this::startAllPreviouslyStoppedPipelines, 5, TimeUnit.SECONDS);
LOG.info("Pipeline health check will run every {} seconds", HEALTH_CHECK_INTERVAL);
healthCheckExecutorService.scheduleAtFixedRate(new PipelineHealthCheck(),
HEALTH_CHECK_INTERVAL,
HEALTH_CHECK_INTERVAL,
HEALTH_CHECK_UNIT);
+
+ }
+
+ private boolean isConfigured() {
+ return BackendConfig.INSTANCE.isConfigured();
+ }
+
+ private void doInitialSetup() {
+ LOG.info("\n\n**********\n\nWelcome to Apache StreamPipes!\n\n**********\n\n");
+ LOG.info("We will perform the initial setup, grab some coffee and cross your fingers ;-)...");
+
+ BackendConfig.INSTANCE.updateSetupStatus(true);
+ new AutoInstallation().startAutoInstallation();
+ BackendConfig.INSTANCE.updateSetupStatus(false);
}
private void schedulePipelineStart(Pipeline pipeline, boolean restartOnReboot) {
diff --git a/streampipes-commons/src/main/java/org/apache/streampipes/commons/constants/Envs.java b/streampipes-commons/src/main/java/org/apache/streampipes/commons/constants/Envs.java
index edae3de..785282b 100644
--- a/streampipes-commons/src/main/java/org/apache/streampipes/commons/constants/Envs.java
+++ b/streampipes-commons/src/main/java/org/apache/streampipes/commons/constants/Envs.java
@@ -23,7 +23,12 @@ public enum Envs {
SP_PORT("SP_PORT"),
SP_CONSUL_LOCATION("CONSUL_LOCATION"),
SP_KAFKA_RETENTION_MS("SP_KAFKA_RETENTION_MS"),
- SP_JWT_SECRET("JWT_SECRET");
+ SP_JWT_SECRET("JWT_SECRET"),
+ SP_INITIAL_ADMIN_USER("SP_INITIAL_ADMIN_USER"),
+ SP_INITIAL_ADMIN_PASSWORD("SP_INITIAL_ADMIN_PASSWORD"),
+ SP_INITIAL_CLIENT_USER("SP_INITIAL_SERVICE_USER"),
+ SP_INITIAL_CLIENT_SECRET("SP_INITIAL_CLIENT_SECRET"),
+ SP_SETUP_INSTALL_PIPELINE_ELEMENTS("SP_SETUP_INSTALL_PIPELINE_ELEMENTS");
private final String envVariableName;
@@ -47,4 +52,8 @@ public enum Envs {
return CustomEnvs.getEnvAsBoolean(this.envVariableName);
}
+ public String getEnvVariableName() {
+ return envVariableName;
+ }
+
}
diff --git a/streampipes-model-client/src/main/java/org/apache/streampipes/model/client/user/Credentials.java b/streampipes-commons/src/main/java/org/apache/streampipes/commons/constants/InstallationConstants.java
similarity index 63%
copy from streampipes-model-client/src/main/java/org/apache/streampipes/model/client/user/Credentials.java
copy to streampipes-commons/src/main/java/org/apache/streampipes/commons/constants/InstallationConstants.java
index 90956bf..42effdc 100644
--- a/streampipes-model-client/src/main/java/org/apache/streampipes/model/client/user/Credentials.java
+++ b/streampipes-commons/src/main/java/org/apache/streampipes/commons/constants/InstallationConstants.java
@@ -15,24 +15,13 @@
* limitations under the License.
*
*/
+package org.apache.streampipes.commons.constants;
-package org.apache.streampipes.model.client.user;
+public class InstallationConstants {
-public class Credentials {
-
- private String email;
-
- public Credentials(String email) {
- super();
- this.email = email;
- }
-
- public String getEmail() {
- return email;
- }
- public void setEmail(String email) {
- this.email = email;
- }
-
-
+ public static final String INITIAL_ADMIN_USER_DEFAULT = "admin";
+ public static final String INITIAL_ADMIN_PW_DEFAULT = "admin";
+ public static final String INITIAL_CLIENT_USER_DEFAULT = "sp-service-client";
+ public static final String INITIAL_CLIENT_SECRET_DEFAULT = "my-apache-streampipes-secret-key-change-me";
+ public static final boolean INSTALL_PIPELINE_ELEMENTS = true;
}
diff --git a/streampipes-config/src/main/java/org/apache/streampipes/config/backend/BackendConfig.java b/streampipes-config/src/main/java/org/apache/streampipes/config/backend/BackendConfig.java
index bb0f678..52765cb 100644
--- a/streampipes-config/src/main/java/org/apache/streampipes/config/backend/BackendConfig.java
+++ b/streampipes-config/src/main/java/org/apache/streampipes/config/backend/BackendConfig.java
@@ -56,6 +56,8 @@ public enum BackendConfig {
config.register(BackendConfigKeys.ELASTICSEARCH_PROTOCOL, "http", "Protocol the elasticsearch service");
config.register(BackendConfigKeys.IS_CONFIGURED, false, "Boolean that indicates whether streampipes is " +
"already configured or not");
+ config.register(BackendConfigKeys.IS_SETUP_RUNNING, false, "Boolean that indicates whether the initial setup " +
+ "is currently running");
config.register(BackendConfigKeys.ASSETS_DIR, makeAssetLocation(), "The directory where " +
"pipeline element assets are stored.");
config.register(BackendConfigKeys.FILES_DIR, makeFileLocation(), "The directory where " +
@@ -236,6 +238,14 @@ public enum BackendConfig {
return config.getObject(BackendConfigKeys.LOCAL_AUTH_CONFIG, LocalAuthConfig.class, LocalAuthConfig.fromDefaults(getJwtSecret()));
}
+ public boolean isSetupRunning() {
+ return config.getBoolean(BackendConfigKeys.IS_SETUP_RUNNING);
+ }
+
+ public void updateSetupStatus(boolean status) {
+ config.setBoolean(BackendConfigKeys.IS_SETUP_RUNNING, status);
+ }
+
private String getJwtSecret() {
if (Envs.SP_JWT_SECRET.exists()) {
return Envs.SP_JWT_SECRET.getValue();
diff --git a/streampipes-config/src/main/java/org/apache/streampipes/config/backend/BackendConfigKeys.java b/streampipes-config/src/main/java/org/apache/streampipes/config/backend/BackendConfigKeys.java
index 0aec6c8..9dbcc89 100644
--- a/streampipes-config/src/main/java/org/apache/streampipes/config/backend/BackendConfigKeys.java
+++ b/streampipes-config/src/main/java/org/apache/streampipes/config/backend/BackendConfigKeys.java
@@ -33,6 +33,7 @@ public class BackendConfigKeys {
public static final String ELASTICSEARCH_PORT = "SP_ELASTICSEARCH_PORT";
public static final String ELASTICSEARCH_PROTOCOL = "SP_ELASTICSEARCH_PROTOCOL";
public static final String IS_CONFIGURED = "SP_IS_CONFIGURED";
+ public static final String IS_SETUP_RUNNING = "SP_IS_SETUP_RUNNING";
public static final String KAFKA_REST_HOST = "SP_KAFKA_REST_HOST";
public static final String KAFKA_REST_PORT = "SP_KAFKA_REST_PORT";
public static final String ASSETS_DIR = "SP_ASSETS_DIR";
diff --git a/streampipes-model-client/pom.xml b/streampipes-model-client/pom.xml
index ef47910..658078e 100644
--- a/streampipes-model-client/pom.xml
+++ b/streampipes-model-client/pom.xml
@@ -48,6 +48,10 @@
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</dependency>
+ <dependency>
+ <groupId>org.springframework.security</groupId>
+ <artifactId>spring-security-core</artifactId>
+ </dependency>
</dependencies>
<build>
diff --git a/streampipes-model-client/src/main/java/org/apache/streampipes/model/client/setup/InitialSettings.java b/streampipes-model-client/src/main/java/org/apache/streampipes/model/client/setup/InitialSettings.java
index cfb6aa1..c79c09c 100644
--- a/streampipes-model-client/src/main/java/org/apache/streampipes/model/client/setup/InitialSettings.java
+++ b/streampipes-model-client/src/main/java/org/apache/streampipes/model/client/setup/InitialSettings.java
@@ -20,36 +20,24 @@ package org.apache.streampipes.model.client.setup;
public class InitialSettings {
-
- private String adminEmail;
+ private String adminUser;
private String adminPassword;
+ private String initialServiceAccountName;
+ private String initialServiceAccountSecret;
private Boolean installPipelineElements;
- public InitialSettings(String adminEmail, String adminPassword, Boolean installPipelineElements) {
- this.adminEmail = adminEmail;
- this.adminPassword = adminPassword;
- this.installPipelineElements = installPipelineElements;
- }
-
public InitialSettings() {
- // TODO Auto-generated constructor stub
+
}
public String getAdminPassword() {
return adminPassword;
}
+
public void setAdminPassword(String adminPassword) {
this.adminPassword = adminPassword;
}
- public String getAdminEmail() {
- return adminEmail;
- }
-
- public void setAdminEmail(String adminEmail) {
- this.adminEmail = adminEmail;
- }
-
public Boolean getInstallPipelineElements() {
return installPipelineElements;
}
@@ -57,4 +45,28 @@ public class InitialSettings {
public void setInstallPipelineElements(Boolean installPipelineElements) {
this.installPipelineElements = installPipelineElements;
}
+
+ public String getAdminUser() {
+ return adminUser;
+ }
+
+ public void setAdminUser(String adminUser) {
+ this.adminUser = adminUser;
+ }
+
+ public String getInitialServiceAccountName() {
+ return initialServiceAccountName;
+ }
+
+ public void setInitialServiceAccountName(String initialServiceAccountName) {
+ this.initialServiceAccountName = initialServiceAccountName;
+ }
+
+ public String getInitialServiceAccountSecret() {
+ return initialServiceAccountSecret;
+ }
+
+ public void setInitialServiceAccountSecret(String initialServiceAccountSecret) {
+ this.initialServiceAccountSecret = initialServiceAccountSecret;
+ }
}
diff --git a/streampipes-model-client/src/main/java/org/apache/streampipes/model/client/user/Authc.java b/streampipes-model-client/src/main/java/org/apache/streampipes/model/client/user/Authc.java
deleted file mode 100644
index 3e0be15..0000000
--- a/streampipes-model-client/src/main/java/org/apache/streampipes/model/client/user/Authc.java
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-package org.apache.streampipes.model.client.user;
-
-public class Authc {
-
- private Principal principal;
- private Credentials credentials;
-
- public Authc(Principal principal, Credentials credentials) {
- super();
- this.principal = principal;
- this.credentials = credentials;
- }
-
- public Principal getPrincipal() {
- return principal;
- }
- public void setPrincipal(Principal principal) {
- this.principal = principal;
- }
- public Credentials getCredentials() {
- return credentials;
- }
- public void setCredentials(Credentials credentials) {
- this.credentials = credentials;
- }
-}
diff --git a/streampipes-model-client/src/main/java/org/apache/streampipes/model/client/user/Authz.java b/streampipes-model-client/src/main/java/org/apache/streampipes/model/client/user/Authz.java
deleted file mode 100644
index 587681d..0000000
--- a/streampipes-model-client/src/main/java/org/apache/streampipes/model/client/user/Authz.java
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-package org.apache.streampipes.model.client.user;
-
-import java.util.List;
-
-public class Authz {
-
- private List<String> roles;
- private List<String> permissions;
-
- public Authz(List<String> roles, List<String> permissions) {
- super();
- this.roles = roles;
- this.permissions = permissions;
- }
-
- public List<String> getRoles() {
- return roles;
- }
- public void setRoles(List<String> roles) {
- this.roles = roles;
- }
- public List<String> getPermissions() {
- return permissions;
- }
- public void setPermissions(List<String> permissions) {
- this.permissions = permissions;
- }
-
-}
diff --git a/streampipes-model-client/src/main/java/org/apache/streampipes/model/client/user/Info.java b/streampipes-model-client/src/main/java/org/apache/streampipes/model/client/user/Info.java
deleted file mode 100644
index b934c50..0000000
--- a/streampipes-model-client/src/main/java/org/apache/streampipes/model/client/user/Info.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-package org.apache.streampipes.model.client.user;
-
-public class Info {
-
- private Authc authc;
- private Authz authz;
-
- public Info(Authc authc, Authz authz) {
- super();
- this.authc = authc;
- this.authz = authz;
- }
-
- public Info() {
- // TODO Auto-generated constructor stub
- }
-
- public Authc getAuthc() {
- return authc;
- }
-
- public void setAuthc(Authc authc) {
- this.authc = authc;
- }
-
- public Authz getAuthz() {
- return authz;
- }
-
- public void setAuthz(Authz authz) {
- this.authz = authz;
- }
-}
diff --git a/streampipes-model-client/src/main/java/org/apache/streampipes/model/client/user/ShiroAuthenticationRequest.java b/streampipes-model-client/src/main/java/org/apache/streampipes/model/client/user/LoginRequest.java
similarity index 89%
rename from streampipes-model-client/src/main/java/org/apache/streampipes/model/client/user/ShiroAuthenticationRequest.java
rename to streampipes-model-client/src/main/java/org/apache/streampipes/model/client/user/LoginRequest.java
index cd620a5..9394859 100644
--- a/streampipes-model-client/src/main/java/org/apache/streampipes/model/client/user/ShiroAuthenticationRequest.java
+++ b/streampipes-model-client/src/main/java/org/apache/streampipes/model/client/user/LoginRequest.java
@@ -18,16 +18,16 @@
package org.apache.streampipes.model.client.user;
-public class ShiroAuthenticationRequest {
+public class LoginRequest {
private String username;
private String password;
- public ShiroAuthenticationRequest() {
+ public LoginRequest() {
}
- public ShiroAuthenticationRequest(String username, String password) {
+ public LoginRequest(String username, String password) {
super();
this.username = username;
this.password = password;
diff --git a/streampipes-model-client/src/main/java/org/apache/streampipes/model/client/user/Principal.java b/streampipes-model-client/src/main/java/org/apache/streampipes/model/client/user/Principal.java
index fc07425..29d20e0 100644
--- a/streampipes-model-client/src/main/java/org/apache/streampipes/model/client/user/Principal.java
+++ b/streampipes-model-client/src/main/java/org/apache/streampipes/model/client/user/Principal.java
@@ -18,31 +18,183 @@
package org.apache.streampipes.model.client.user;
-public class Principal {
+import com.google.gson.annotations.SerializedName;
+import org.springframework.security.core.userdetails.UserDetails;
- private String email;
- private String apiKey;
-
- public Principal(String email, String apiKey) {
- super();
- this.email = email;
- this.apiKey = apiKey;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+public abstract class Principal implements UserDetails {
+
+ protected @SerializedName("_id") String principalId;
+ protected @SerializedName("_rev") String rev;
+
+ private boolean accountEnabled;
+ private boolean accountLocked;
+ private boolean accountExpired;
+
+ private String principalName;
+
+ protected List<Element> ownSources;
+ protected List<Element> ownSepas;
+ protected List<Element> ownActions;
+
+ protected Set<Role> roles;
+
+ private PrincipalType principalType;
+
+ public Principal(PrincipalType principalType) {
+ this.principalType = principalType;
+ this.ownActions = new ArrayList<>();
+ this.ownSepas = new ArrayList<>();
+ this.ownSources = new ArrayList<>();
+ this.roles = new HashSet<>();
+ }
+
+ public List<Element> getOwnSources() {
+ return ownSources;
+ }
+
+ public void addOwnSource(String source, boolean publicElement) {
+ if (this.ownSources == null) this.ownSources = new ArrayList<>();
+ this.ownSources.add(new Element(source, publicElement));
+ }
+
+ public List<Element> getOwnSepas() {
+ return ownSepas;
+ }
+
+ public void addOwnSepa(String sepa, boolean publicElement) {
+ if (this.ownSepas == null) this.ownSepas = new ArrayList<>();
+ this.ownSepas.add(new Element(sepa, publicElement));
+ }
+
+ public List<Element> getOwnActions() {
+ return ownActions;
}
-
- public String getApiKey() {
- return apiKey;
+ public void addOwnAction(String action, boolean publicElement) {
+ this.ownActions.add(new Element(action, publicElement));
}
- public void setApiKey(String apiKey) {
- this.apiKey = apiKey;
+
+ public void removeAction(String action) {
+ this.ownActions.remove(find(action, ownActions));
+ }
+
+ public void removeSepa(String sepa) {
+ this.ownSepas.remove(find(sepa, ownSepas));
+ }
+
+ public void removeSource(String source) {
+ this.ownSources.remove(find(source, ownSources));
+ }
+
+ public String getRev() {
+ return rev;
+ }
+
+ public void setRev(String rev) {
+ this.rev = rev;
}
- public String getEmail() {
- return email;
+ public String getPrincipalId() {
+ return principalId;
}
- public void setEmail(String email) {
- this.email = email;
+ public void setPrincipalId(String principalId) {
+ this.principalId = principalId;
}
-
+
+ private Element find(String elementId, List<Element> source) {
+ return source.stream().filter(f -> f.getElementId().equals(elementId)).findFirst().orElseThrow(IllegalArgumentException::new);
+ }
+
+ public boolean isAccountEnabled() {
+ return accountEnabled;
+ }
+
+ public void setAccountEnabled(boolean accountEnabled) {
+ this.accountEnabled = accountEnabled;
+ }
+
+ public boolean isAccountLocked() {
+ return accountLocked;
+ }
+
+ public void setAccountLocked(boolean accountLocked) {
+ this.accountLocked = accountLocked;
+ }
+
+ public boolean isAccountExpired() {
+ return accountExpired;
+ }
+
+ public void setAccountExpired(boolean accountExpired) {
+ this.accountExpired = accountExpired;
+ }
+
+ public String getPrincipalName() {
+ return principalName;
+ }
+
+ public void setPrincipalName(String principalName) {
+ this.principalName = principalName;
+ }
+
+ public void setOwnSources(List<Element> ownSources) {
+ this.ownSources = ownSources;
+ }
+
+ public void setOwnSepas(List<Element> ownSepas) {
+ this.ownSepas = ownSepas;
+ }
+
+ public void setOwnActions(List<Element> ownActions) {
+ this.ownActions = ownActions;
+ }
+
+ public Set<Role> getRoles() {
+ return roles;
+ }
+
+ public void setRoles(Set<Role> roles) {
+ this.roles = roles;
+ }
+
+ public PrincipalType getPrincipalType() {
+ return principalType;
+ }
+
+ public void setPrincipalType(PrincipalType principalType) {
+ this.principalType = principalType;
+ }
+
+ @Override
+ public boolean isAccountNonExpired() {
+ return !this.isAccountExpired();
+ }
+
+ @Override
+ public boolean isAccountNonLocked() {
+ return !this.isAccountLocked();
+ }
+
+ @Override
+ public boolean isCredentialsNonExpired() {
+ return true;
+ }
+
+ @Override
+ public boolean isEnabled() {
+ return this.isAccountEnabled();
+ }
+
+ @Override
+ public String getUsername() {
+ return principalName;
+ }
+
+
}
diff --git a/streampipes-model-client/src/main/java/org/apache/streampipes/model/client/user/Credentials.java b/streampipes-model-client/src/main/java/org/apache/streampipes/model/client/user/PrincipalType.java
similarity index 78%
rename from streampipes-model-client/src/main/java/org/apache/streampipes/model/client/user/Credentials.java
rename to streampipes-model-client/src/main/java/org/apache/streampipes/model/client/user/PrincipalType.java
index 90956bf..be84b20 100644
--- a/streampipes-model-client/src/main/java/org/apache/streampipes/model/client/user/Credentials.java
+++ b/streampipes-model-client/src/main/java/org/apache/streampipes/model/client/user/PrincipalType.java
@@ -15,24 +15,10 @@
* limitations under the License.
*
*/
-
package org.apache.streampipes.model.client.user;
-public class Credentials {
+public enum PrincipalType {
- private String email;
-
- public Credentials(String email) {
- super();
- this.email = email;
- }
-
- public String getEmail() {
- return email;
- }
- public void setEmail(String email) {
- this.email = email;
- }
-
-
+ USER_ACCOUNT,
+ SERVICE_ACCOUNT
}
diff --git a/streampipes-model-client/src/main/java/org/apache/streampipes/model/client/user/ServiceAccount.java b/streampipes-model-client/src/main/java/org/apache/streampipes/model/client/user/ServiceAccount.java
new file mode 100644
index 0000000..7fafdb5
--- /dev/null
+++ b/streampipes-model-client/src/main/java/org/apache/streampipes/model/client/user/ServiceAccount.java
@@ -0,0 +1,68 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.streampipes.model.client.user;
+
+import org.springframework.security.core.GrantedAuthority;
+
+import java.util.Collection;
+import java.util.Set;
+
+public class ServiceAccount extends Principal {
+
+ private String clientSecret;
+
+ public static ServiceAccount from(String serviceAccountName,
+ String clientSecret,
+ Set<Role> roles) {
+ ServiceAccount account = new ServiceAccount();
+ account.setPrincipalName(serviceAccountName);
+ account.setClientSecret(clientSecret);
+ account.setRoles(roles);
+ account.setAccountEnabled(true);
+ account.setAccountLocked(false);
+
+ return account;
+ }
+
+ public ServiceAccount() {
+ super(PrincipalType.SERVICE_ACCOUNT);
+ }
+
+ public String getClientSecret() {
+ return clientSecret;
+ }
+
+ public void setClientSecret(String clientSecret) {
+ this.clientSecret = clientSecret;
+ }
+
+ @Override
+ public Collection<? extends GrantedAuthority> getAuthorities() {
+ return null;
+ }
+
+ @Override
+ public String getPassword() {
+ return null;
+ }
+
+ @Override
+ public String getUsername() {
+ return null;
+ }
+}
diff --git a/streampipes-model-client/src/main/java/org/apache/streampipes/model/client/user/ShiroAuthenticationResponse.java b/streampipes-model-client/src/main/java/org/apache/streampipes/model/client/user/ShiroAuthenticationResponse.java
deleted file mode 100644
index 5f09b30..0000000
--- a/streampipes-model-client/src/main/java/org/apache/streampipes/model/client/user/ShiroAuthenticationResponse.java
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-package org.apache.streampipes.model.client.user;
-
-public class ShiroAuthenticationResponse {
-
- private Info info;
- private boolean success;
- private String callbackUrl;
- private String token;
-
- public ShiroAuthenticationResponse(Info info) {
- super();
- this.info = info;
- this.success = true;
- }
-
- public Info getInfo() {
- return info;
- }
-
- public void setInfo(Info info) {
- this.info = info;
- }
-
- public boolean isSuccess() {
- return success;
- }
-
- public void setSuccess(boolean success) {
- this.success = success;
- }
-
- public String getCallbackUrl() {
- return callbackUrl;
- }
-
- public void setCallbackUrl(String callbackUrl) {
- this.callbackUrl = callbackUrl;
- }
-
- public String getToken() {
- return token;
- }
-
- public void setToken(String token) {
- this.token = token;
- }
-}
diff --git a/streampipes-model-client/src/main/java/org/apache/streampipes/model/client/user/ShiroAuthenticationResponseFactory.java b/streampipes-model-client/src/main/java/org/apache/streampipes/model/client/user/ShiroAuthenticationResponseFactory.java
deleted file mode 100644
index 57a8fcf..0000000
--- a/streampipes-model-client/src/main/java/org/apache/streampipes/model/client/user/ShiroAuthenticationResponseFactory.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-package org.apache.streampipes.model.client.user;
-
-import java.util.ArrayList;
-import java.util.List;
-
-public class ShiroAuthenticationResponseFactory {
-
- public static ShiroAuthenticationResponse create(User user)
- {
- Authc authc = new Authc(new Principal(user.getEmail(), ""), new Credentials(user.getEmail()));
- List<String> roles = new ArrayList<>();
- user.getRoles().forEach(r -> roles.add(r.toString()));
- Authz authz = new Authz(roles, new ArrayList<>());
-
- Info info = new Info();
- info.setAuthc(authc);
- info.setAuthz(authz);
- ShiroAuthenticationResponse response = new ShiroAuthenticationResponse(info);
-
- return response;
- }
-}
diff --git a/streampipes-model-client/src/main/java/org/apache/streampipes/model/client/user/User.java b/streampipes-model-client/src/main/java/org/apache/streampipes/model/client/user/User.java
deleted file mode 100644
index aa76714..0000000
--- a/streampipes-model-client/src/main/java/org/apache/streampipes/model/client/user/User.java
+++ /dev/null
@@ -1,266 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-package org.apache.streampipes.model.client.user;
-
-import com.google.gson.annotations.SerializedName;
-import org.apache.streampipes.model.shared.annotation.TsModel;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Set;
-
-@TsModel
-public class User {
-
- protected @SerializedName("_id") String userId;
- protected @SerializedName("_rev") String rev;
- protected String email;
-
- protected String username;
- protected String fullName;
- protected String password;
-
- protected List<Element> ownSources;
- protected List<Element> ownSepas;
- protected List<Element> ownActions;
-
- protected List<String> preferredSources;
- protected List<String> preferredSepas;
- protected List<String> preferredActions;
-
- protected List<UserApiToken> userApiTokens;
-
- protected boolean hideTutorial;
- protected boolean darkMode = false;
-
- protected Set<Role> roles;
-
- public User() {
- this.hideTutorial = false;
- this.userApiTokens = new ArrayList<>();
- }
-
- public User(String email, String password, Set<Role> roles, List<Element> ownSources, List<Element> ownSepas, List<Element> ownActions) {
- super();
- this.email = email;
-
- this.password = password;
- this.roles = roles;
-
- this.ownSources = ownSources;
- this.ownSepas = ownSepas;
- this.ownActions = ownActions;
-
- this.hideTutorial = false;
- }
-
- public User(String email, String password, Set<Role> roles)
- {
- this.email = email;
- this.password = password;
- this.roles = roles;
-
- this.ownActions = new ArrayList<>();
- this.ownSepas = new ArrayList<>();
- this.ownSources = new ArrayList<>();
-
- this.preferredActions = new ArrayList<>();
- this.preferredSepas = new ArrayList<>();
- this.preferredSources = new ArrayList<>();
-
- this.hideTutorial = false;
- }
-
- public String getEmail() {
- return email;
- }
-
- public void setEmail(String email) {
- this.email = email;
- }
-
- public String getPassword() {
- return password;
- }
-
- public void setPassword(String password) {
- this.password = password;
- }
-
- public Set<Role> getRoles() {
- return roles;
- }
-
- public void setRoles(Set<Role> roles) {
- this.roles = roles;
- }
-
- public String getUserId() {
- return userId;
- }
-
- public void setUserId(String userId) {
- this.userId = userId;
- }
-
- public List<Element> getOwnSources() {
- return ownSources;
- }
-
- public void addOwnSource(String source, boolean publicElement) {
- if (this.ownSources == null) this.ownSources = new ArrayList<>();
- this.ownSources.add(new Element(source, publicElement));
- }
-
- public List<Element> getOwnSepas() {
- return ownSepas;
- }
-
- public void addOwnSepa(String sepa, boolean publicElement) {
- if (this.ownSepas == null) this.ownSepas = new ArrayList<>();
- this.ownSepas.add(new Element(sepa, publicElement));
- }
-
- public List<Element> getOwnActions() {
- return ownActions;
- }
-
- public void addOwnAction(String action, boolean publicElement) {
- this.ownActions.add(new Element(action, publicElement));
- }
-
- public void removeAction(String action) {
- this.ownActions.remove(find(action, ownActions));
- }
-
- public void removeSepa(String sepa) {
- this.ownSepas.remove(find(sepa, ownSepas));
- }
-
- public void removeSource(String source) {
- this.ownSources.remove(find(source, ownSources));
- }
-
- public List<String> getPreferredSources() {
- return preferredSources;
- }
-
- public void setPreferredSources(List<String> preferredSources) {
- this.preferredSources = preferredSources;
- }
-
- public List<String> getPreferredSepas() {
- return preferredSepas;
- }
-
- public void setPreferredSepas(List<String> preferredSepas) {
- this.preferredSepas = preferredSepas;
- }
-
- public List<String> getPreferredActions() {
- return preferredActions;
- }
-
- public void setPreferredActions(List<String> preferredActions) {
- this.preferredActions = preferredActions;
- }
-
- public void addPreferredSource(String elementId)
- {
- this.preferredSources.add(elementId);
- }
-
- public void addPreferredSepa(String elementId)
- {
- this.preferredSepas.add(elementId);
- }
-
- public void addPreferredAction(String elementId)
- {
- this.preferredActions.add(elementId);
- }
-
- public void removePreferredSource(String elementId)
- {
- this.preferredSources.remove(elementId);
- }
-
- public void removePreferredSepa(String elementId)
- {
- this.preferredSepas.remove(elementId);
- }
-
- public void removePreferredAction(String elementId)
- {
- this.preferredActions.remove(elementId);
- }
-
- public String getUsername() {
- return username;
- }
-
- public void setUsername(String username) {
- this.username = username;
- }
-
- public String getFullName() {
- return fullName;
- }
-
- public void setFullName(String fullName) {
- this.fullName = fullName;
- }
-
- public List<UserApiToken> getUserApiTokens() {
- return userApiTokens;
- }
-
- public void setUserApiTokens(List<UserApiToken> userApiTokens) {
- this.userApiTokens = userApiTokens;
- }
-
- private Element find(String elementId, List<Element> source)
- {
- return source.stream().filter(f -> f.getElementId().equals(elementId)).findFirst().orElseThrow(IllegalArgumentException::new);
- }
-
- public boolean isHideTutorial() {
- return hideTutorial;
- }
-
- public void setHideTutorial(boolean hideTutorial) {
- this.hideTutorial = hideTutorial;
- }
-
- public String getRev() {
- return rev;
- }
-
- public void setRev(String rev) {
- this.rev = rev;
- }
-
- public boolean isDarkMode() {
- return darkMode;
- }
-
- public void setDarkMode(boolean darkMode) {
- this.darkMode = darkMode;
- }
-}
diff --git a/streampipes-model-client/src/main/java/org/apache/streampipes/model/client/user/UserAccount.java b/streampipes-model-client/src/main/java/org/apache/streampipes/model/client/user/UserAccount.java
new file mode 100644
index 0000000..c082dd6
--- /dev/null
+++ b/streampipes-model-client/src/main/java/org/apache/streampipes/model/client/user/UserAccount.java
@@ -0,0 +1,185 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.streampipes.model.client.user;
+
+import org.apache.streampipes.model.shared.annotation.TsModel;
+import org.springframework.security.core.GrantedAuthority;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.Set;
+
+@TsModel
+public class UserAccount extends Principal {
+
+ protected String email;
+ protected String fullName;
+ protected String username;
+ protected String password;
+
+ protected List<String> preferredDataStreams;
+ protected List<String> preferredDataProcessors;
+ protected List<String> preferredDataSinks;
+
+ protected List<UserApiToken> userApiTokens;
+
+ protected boolean hideTutorial;
+ protected boolean darkMode = false;
+
+ public static UserAccount from(String username,
+ String encryptedPassword,
+ Set<Role> roles) {
+ UserAccount account = new UserAccount();
+ account.setPrincipalName(username);
+ account.setPassword(encryptedPassword);
+ account.setRoles(roles);
+ account.setAccountEnabled(true);
+ account.setAccountLocked(false);
+
+ return account;
+ }
+
+ public UserAccount() {
+ super(PrincipalType.USER_ACCOUNT);
+ this.hideTutorial = false;
+ this.userApiTokens = new ArrayList<>();
+ this.preferredDataProcessors = new ArrayList<>();
+ this.preferredDataSinks = new ArrayList<>();
+ this.preferredDataStreams = new ArrayList<>();
+ }
+
+ public String getEmail() {
+ return email;
+ }
+
+ public void setEmail(String email) {
+ this.email = email;
+ }
+
+ public void setPassword(String password) {
+ this.password = password;
+ }
+
+ public Set<Role> getRoles() {
+ return roles;
+ }
+
+ public void setRoles(Set<Role> roles) {
+ this.roles = roles;
+ }
+
+ public List<String> getPreferredDataStreams() {
+ return preferredDataStreams;
+ }
+
+ public void setPreferredDataStreams(List<String> preferredDataStreams) {
+ this.preferredDataStreams = preferredDataStreams;
+ }
+
+ public List<String> getPreferredDataProcessors() {
+ return preferredDataProcessors;
+ }
+
+ public void setPreferredDataProcessors(List<String> preferredDataProcessors) {
+ this.preferredDataProcessors = preferredDataProcessors;
+ }
+
+ public List<String> getPreferredDataSinks() {
+ return preferredDataSinks;
+ }
+
+ public void setPreferredDataSinks(List<String> preferredDataSinks) {
+ this.preferredDataSinks = preferredDataSinks;
+ }
+
+ public void addPreferredDataStream(String elementId)
+ {
+ this.preferredDataStreams.add(elementId);
+ }
+
+ public void addPreferredDataProcessor(String elementId)
+ {
+ this.preferredDataProcessors.add(elementId);
+ }
+
+ public void addPreferredDataSink(String elementId)
+ {
+ this.preferredDataSinks.add(elementId);
+ }
+
+ public void removePreferredDataStream(String elementId) {
+ this.preferredDataStreams.remove(elementId);
+ }
+
+ public void removePreferredDataProcessor(String elementId)
+ {
+ this.preferredDataProcessors.remove(elementId);
+ }
+
+ public void removePreferredDataSink(String elementId)
+ {
+ this.preferredDataSinks.remove(elementId);
+ }
+
+ public String getFullName() {
+ return fullName;
+ }
+
+ public void setFullName(String fullName) {
+ this.fullName = fullName;
+ }
+
+ public List<UserApiToken> getUserApiTokens() {
+ return userApiTokens;
+ }
+
+ public void setUserApiTokens(List<UserApiToken> userApiTokens) {
+ this.userApiTokens = userApiTokens;
+ }
+
+ public boolean isHideTutorial() {
+ return hideTutorial;
+ }
+
+ public void setHideTutorial(boolean hideTutorial) {
+ this.hideTutorial = hideTutorial;
+ }
+
+
+ public boolean isDarkMode() {
+ return darkMode;
+ }
+
+ public void setDarkMode(boolean darkMode) {
+ this.darkMode = darkMode;
+ }
+
+ @Override
+ public Collection<? extends GrantedAuthority> getAuthorities() {
+ return null;
+ }
+
+ @Override
+ public String getPassword() {
+ return password;
+ }
+
+
+}
diff --git a/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/setup/AutoInstallation.java b/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/setup/AutoInstallation.java
new file mode 100644
index 0000000..a331027
--- /dev/null
+++ b/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/setup/AutoInstallation.java
@@ -0,0 +1,119 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.streampipes.manager.setup;
+
+import org.apache.streampipes.commons.constants.CustomEnvs;
+import org.apache.streampipes.commons.constants.Envs;
+import org.apache.streampipes.commons.constants.InstallationConstants;
+import org.apache.streampipes.config.backend.BackendConfig;
+import org.apache.streampipes.model.client.setup.InitialSettings;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.List;
+import java.util.concurrent.atomic.AtomicInteger;
+
+public class AutoInstallation {
+
+ private static final Logger LOG = LoggerFactory.getLogger(AutoInstallation.class);
+
+ public void startAutoInstallation() {
+ InitialSettings settings = collectInitialSettings();
+
+ List<InstallationStep> steps = InstallationConfiguration.getInstallationSteps(settings);
+ AtomicInteger errorCount = new AtomicInteger();
+
+ steps.forEach(step -> {
+ step.install();
+ errorCount.addAndGet(step.getErrorCount());
+ });
+ if (errorCount.get() > 0) {
+ LOG.error("{} errors occurred during the setup process", errorCount);
+ } else {
+ BackendConfig.INSTANCE.setIsConfigured(true);
+ LOG.info("Initial setup completed successfully - you can now open the login page in the browser.");
+ }
+ LOG.info("\n\n**********\n\nAuto-Setup finished\n\n**********\n\n");
+ }
+
+ private InitialSettings collectInitialSettings() {
+ InitialSettings settings = new InitialSettings();
+ settings.setInstallPipelineElements(autoInstallPipelineElements());
+ settings.setAdminUser(findAdminUser());
+ settings.setAdminPassword(findAdminPassword());
+ settings.setInitialServiceAccountName(findServiceAccountName());
+ settings.setInitialServiceAccountSecret(findServiceAccountSecret());
+
+ return settings;
+ }
+
+ private boolean autoInstallPipelineElements() {
+ if (Envs.SP_SETUP_INSTALL_PIPELINE_ELEMENTS.exists()) {
+ return Envs.SP_SETUP_INSTALL_PIPELINE_ELEMENTS.getValueAsBoolean();
+ } else {
+ return InstallationConstants.INSTALL_PIPELINE_ELEMENTS;
+ }
+ }
+
+ private String findServiceAccountSecret() {
+ return getStringOrDefault(
+ Envs.SP_INITIAL_CLIENT_SECRET.getEnvVariableName(),
+ InstallationConstants.INITIAL_CLIENT_SECRET_DEFAULT
+ );
+ }
+
+ private String findServiceAccountName() {
+ return getStringOrDefault(
+ Envs.SP_INITIAL_CLIENT_USER.getEnvVariableName(),
+ InstallationConstants.INITIAL_CLIENT_USER_DEFAULT
+ );
+ }
+
+ private String findAdminUser() {
+ return getStringOrDefault(
+ Envs.SP_INITIAL_ADMIN_USER.getEnvVariableName(),
+ InstallationConstants.INITIAL_ADMIN_USER_DEFAULT
+ );
+ }
+
+ private String findAdminPassword() {
+ return getStringOrDefault(
+ Envs.SP_INITIAL_ADMIN_PASSWORD.getEnvVariableName(),
+ InstallationConstants.INITIAL_ADMIN_PW_DEFAULT
+ );
+ }
+
+ private String getStringOrDefault(String envVariable, String defaultValue) {
+ boolean exists = exists(envVariable);
+ if (exists) {
+ LOG.info("Using provided environment variable {}", envVariable);
+ return getString(envVariable);
+ } else {
+ LOG.info("Environment variable {} not found, using default value {}", envVariable, defaultValue);
+ return defaultValue;
+ }
+ }
+
+ private boolean exists(String envVariable) {
+ return CustomEnvs.exists(envVariable);
+ }
+
+ private String getString(String envVariable) {
+ return CustomEnvs.getEnv(envVariable);
+ }
+}
diff --git a/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/setup/CouchDbInstallationStep.java b/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/setup/CouchDbInstallationStep.java
index e481c14..7dbe871 100644
--- a/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/setup/CouchDbInstallationStep.java
+++ b/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/setup/CouchDbInstallationStep.java
@@ -19,201 +19,209 @@
package org.apache.streampipes.manager.setup;
import org.apache.streampipes.model.client.endpoint.ExtensionsServiceEndpoint;
-import org.apache.streampipes.model.message.Message;
-import org.apache.streampipes.model.message.Notifications;
import org.apache.streampipes.storage.couchdb.impl.ExtensionsServiceEndpointStorageImpl;
import org.apache.streampipes.storage.couchdb.utils.Utils;
import org.lightcouch.DesignDocument;
import org.lightcouch.DesignDocument.MapReduce;
import org.lightcouch.Response;
-import java.util.*;
-
-public class CouchDbInstallationStep implements InstallationStep {
-
- private static List<String> initRdfEndpointPorts =
- Collections.singletonList("8099/api/v1/master/sources/");
- private static final String initRdfEndpointHost = "http://localhost:";
-
- private static final String PREPARING_NOTIFICATIONS_TEXT = "Preparing database " +
- "'notifications'...";
- private static final String PREPARING_USERS_TEXT = "Preparing database 'users'...";
-
- public CouchDbInstallationStep() {
-
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public class CouchDbInstallationStep extends InstallationStep {
+
+ private static final String initRdfEndpointHost = "http://localhost:";
+ private static final String PREPARING_NOTIFICATIONS_TEXT = "Preparing database " +
+ "'notifications'...";
+ private static final String PREPARING_USERS_TEXT = "Preparing database 'users'...";
+ private static List<String> initRdfEndpointPorts =
+ Collections.singletonList("8099/api/v1/master/sources/");
+
+ public CouchDbInstallationStep() {
+
+ }
+
+ @Override
+ public void install() {
+ createDatabases();
+ createViews();
+ addRdfEndpoints();
+ }
+
+ @Override
+ public String getTitle() {
+ return "Creating databases...";
+ }
+
+ private void createDatabases() {
+ try {
+ // Set up couchdb internal databases
+ Utils.getCouchDbInternalUsersClient();
+ Utils.getCouchDbReplicatorClient();
+ Utils.getCouchDbGlobalChangesClient();
+
+ // Set up streampipes internal databases
+ Utils.getCouchDbUserClient();
+ Utils.getCouchDbMonitoringClient();
+ Utils.getCouchDbPipelineClient();
+ Utils.getCouchDbConnectionClient();
+ Utils.getCouchDbNotificationClient();
+ Utils.getCouchDbPipelineCategoriesClient();
+ Utils.getCouchDbVisualizationClient();
+ Utils.getCouchDbRdfEndpointClient();
+ Utils.getCouchDbDashboardClient();
+ Utils.getCouchDbDashboardWidgetClient();
+ Utils.getCouchDbLabelClient();
+ Utils.getCouchDbCategoryClient();
+
+ logSuccess(getTitle());
+ } catch (Exception e) {
+ logFailure(getTitle(), e);
}
-
- @Override
- public List<Message> install() {
- List<Message> msgs = new ArrayList<>();
- msgs.addAll(createDatabases());
- msgs.addAll(createViews());
- msgs.add(addRdfEndpoints());
- return msgs;
+ }
+
+ private void createViews() {
+ addUserView();
+ addConnectionView();
+ addNotificationView();
+ addLabelView();
+ }
+
+ private void addRdfEndpoints() {
+ ExtensionsServiceEndpointStorageImpl rdfEndpointStorage = new ExtensionsServiceEndpointStorageImpl();
+ initRdfEndpointPorts
+ .forEach(p -> rdfEndpointStorage
+ .addExtensionsServiceEndpoint(new ExtensionsServiceEndpoint(initRdfEndpointHost + p)));
+
+ logSuccess("Discovering pipeline element endpoints...");
+ }
+
+ private void addNotificationView() {
+ try {
+ DesignDocument userDocument = prepareDocument("_design/notificationtypes");
+ DesignDocument notificationCountDocument = prepareDocument("_design/unread");
+
+ Map<String, MapReduce> notificationTypeViews = new HashMap<>();
+ MapReduce notificationTypeFunction = new MapReduce();
+ notificationTypeFunction.setMap("function (doc) { var vizName = doc.title.replace(/\\s/g, '-'); var indexName = doc.correspondingPipelineId + '-' + vizName; emit([indexName, doc.createdAtTimestamp], doc);}");
+ notificationTypeViews.put("notificationtypes", notificationTypeFunction);
+ userDocument.setViews(notificationTypeViews);
+ Response resp = Utils.getCouchDbNotificationClient().design().synchronizeWithDb(userDocument);
+
+ Map<String, MapReduce> notificationCountTypeViews = new HashMap<>();
+ MapReduce countFunction = new MapReduce();
+ countFunction.setMap("function (doc) {\n" +
+ " var user = doc.targetedAt; \n" +
+ " if (!doc.read) {\n" +
+ " emit(user, 1);\n" +
+ " }\n" +
+ "}");
+ countFunction.setReduce("function (keys, values, rereduce) {\n" +
+ " if (rereduce) {\n" +
+ " return sum(values);\n" +
+ " } else {\n" +
+ " return values.length;\n" +
+ " }\n" +
+ "}");
+ notificationCountTypeViews.put("unread", countFunction);
+ notificationCountDocument.setViews(notificationCountTypeViews);
+ Response countResp =
+ Utils.getCouchDbNotificationClient().design().synchronizeWithDb(notificationCountDocument);
+
+ if (resp.getError() != null && countResp != null) {
+ logFailure(PREPARING_NOTIFICATIONS_TEXT);
+ } else {
+ logSuccess(PREPARING_NOTIFICATIONS_TEXT);
+ }
+ } catch (Exception e) {
+ logFailure(PREPARING_NOTIFICATIONS_TEXT, e);
}
+ }
- @Override
- public String getTitle() {
- return "Creating databases...";
- }
+ private void addUserView() {
+ try {
+ DesignDocument userDocument = prepareDocument("_design/users");
+ Map<String, MapReduce> views = new HashMap<>();
- private List<Message> createDatabases() {
- try {
- // Set up couchdb internal databases
- Utils.getCouchDbInternalUsersClient();
- Utils.getCouchDbReplicatorClient();
- Utils.getCouchDbGlobalChangesClient();
-
- // Set up streampipes internal databases
- Utils.getCouchDbUserClient();
- Utils.getCouchDbMonitoringClient();
- Utils.getCouchDbPipelineClient();
- Utils.getCouchDbConnectionClient();
- Utils.getCouchDbNotificationClient();
- Utils.getCouchDbPipelineCategoriesClient();
- Utils.getCouchDbVisualizationClient();
- Utils.getCouchDbRdfEndpointClient();
- Utils.getCouchDbDashboardClient();
- Utils.getCouchDbDashboardWidgetClient();
- Utils.getCouchDbLabelClient();
- Utils.getCouchDbCategoryClient();
-
- return Collections.singletonList(Notifications.success(getTitle()));
- } catch (Exception e) {
- return Collections.singletonList(Notifications.error(getTitle()));
- }
- }
+ MapReduce passwordFunction = new MapReduce();
+ passwordFunction.setMap("function(doc) { if(doc.principalName && doc.principalType === 'USER_ACCOUNT' && doc.password) { emit(doc.principalName, doc.password); } }");
- private List<Message> createViews() {
- List<Message> result = new ArrayList<>();
- result.add(addUserView());
- result.add(addConnectionView());
- result.add(addNotificationView());
- result.add(addLabelView());
- return result;
- }
+ MapReduce usernameFunction = new MapReduce();
+ usernameFunction.setMap("function(doc) { if(doc.principalName) { emit(doc.principalName, doc); } }");
- private Message addRdfEndpoints() {
- ExtensionsServiceEndpointStorageImpl rdfEndpointStorage = new ExtensionsServiceEndpointStorageImpl();
- initRdfEndpointPorts
- .forEach(p -> rdfEndpointStorage
- .addExtensionsServiceEndpoint(new ExtensionsServiceEndpoint(initRdfEndpointHost + p)));
+ MapReduce tokenFunction = new MapReduce();
+ tokenFunction.setMap("function(doc) { if (doc.userApiTokens) { doc.userApiTokens.forEach(function(token) { emit(token.hashedToken, doc.email); });}}");
- return Notifications.success("Discovering pipeline element endpoints...");
- }
+ views.put("password", passwordFunction);
+ views.put("username", usernameFunction);
+ views.put("token", tokenFunction);
- private Message addNotificationView() {
- try {
- DesignDocument userDocument = prepareDocument("_design/notificationtypes");
- DesignDocument notificationCountDocument = prepareDocument("_design/unread");
-
- Map<String, MapReduce> notificationTypeViews = new HashMap<>();
- MapReduce notificationTypeFunction = new MapReduce();
- notificationTypeFunction.setMap("function (doc) { var vizName = doc.title.replace(/\\s/g, '-'); var indexName = doc.correspondingPipelineId + '-' + vizName; emit([indexName, doc.createdAtTimestamp], doc);}");
- notificationTypeViews.put("notificationtypes", notificationTypeFunction);
- userDocument.setViews(notificationTypeViews);
- Response resp = Utils.getCouchDbNotificationClient().design().synchronizeWithDb(userDocument);
-
- Map<String, MapReduce> notificationCountTypeViews = new HashMap<>();
- MapReduce countFunction = new MapReduce();
- countFunction.setMap("function (doc) {\n" +
- " var user = doc.targetedAt; \n" +
- " if (!doc.read) {\n" +
- " emit(user, 1);\n" +
- " }\n" +
- "}");
- countFunction.setReduce("function (keys, values, rereduce) {\n" +
- " if (rereduce) {\n" +
- " return sum(values);\n" +
- " } else {\n" +
- " return values.length;\n" +
- " }\n" +
- "}");
- notificationCountTypeViews.put("unread", countFunction);
- notificationCountDocument.setViews(notificationCountTypeViews);
- Response countResp =
- Utils.getCouchDbNotificationClient().design().synchronizeWithDb(notificationCountDocument);
-
- if (resp.getError() != null && countResp != null) return Notifications.error(PREPARING_NOTIFICATIONS_TEXT);
- else return Notifications.success(PREPARING_NOTIFICATIONS_TEXT);
- } catch (Exception e) {
- return Notifications.error(PREPARING_NOTIFICATIONS_TEXT);
- }
- }
-
- private Message addUserView() {
- try {
- DesignDocument userDocument = prepareDocument("_design/users");
- Map<String, MapReduce> views = new HashMap<>();
-
- MapReduce passwordFunction = new MapReduce();
- passwordFunction.setMap("function(doc) { if(doc.email&& doc.password) { emit(doc.email, doc.password); } }");
-
- MapReduce usernameFunction = new MapReduce();
- usernameFunction.setMap("function(doc) { if(doc.email) { emit(doc.email, doc); } }");
-
- MapReduce tokenFunction = new MapReduce();
- tokenFunction.setMap("function(doc) { if (doc.userApiTokens) { doc.userApiTokens.forEach(function(token) { emit(token.hashedToken, doc.email); });}}");
+ userDocument.setViews(views);
+ Response resp = Utils.getCouchDbUserClient().design().synchronizeWithDb(userDocument);
- views.put("password", passwordFunction);
- views.put("username", usernameFunction);
- views.put("token", tokenFunction);
-
- userDocument.setViews(views);
- Response resp = Utils.getCouchDbUserClient().design().synchronizeWithDb(userDocument);
-
- if (resp.getError() != null) return Notifications.error(PREPARING_USERS_TEXT);
- else return Notifications.success(PREPARING_USERS_TEXT);
- } catch (Exception e) {
- return Notifications.error(PREPARING_USERS_TEXT);
- }
+ if (resp.getError() != null) {
+ logFailure(PREPARING_USERS_TEXT);
+ } else {
+ logSuccess(PREPARING_USERS_TEXT);
+ }
+ } catch (Exception e) {
+ logFailure(PREPARING_USERS_TEXT, e);
}
+ }
- private Message addLabelView() {
- try {
- DesignDocument labelDocument = prepareDocument("_design/categoryId");
- Map<String, MapReduce> views = new HashMap<>();
+ private void addLabelView() {
+ try {
+ DesignDocument labelDocument = prepareDocument("_design/categoryId");
+ Map<String, MapReduce> views = new HashMap<>();
- MapReduce categoryIdFunction = new MapReduce();
- categoryIdFunction.setMap("function(doc) { if(doc.categoryId) { emit(doc.categoryId, doc); } }");
+ MapReduce categoryIdFunction = new MapReduce();
+ categoryIdFunction.setMap("function(doc) { if(doc.categoryId) { emit(doc.categoryId, doc); } }");
- views.put("categoryId", categoryIdFunction);
+ views.put("categoryId", categoryIdFunction);
- labelDocument.setViews(views);
- Response resp = Utils.getCouchDbLabelClient().design().synchronizeWithDb(labelDocument);
+ labelDocument.setViews(views);
+ Response resp = Utils.getCouchDbLabelClient().design().synchronizeWithDb(labelDocument);
- if (resp.getError() != null) return Notifications.error(PREPARING_USERS_TEXT);
- else return Notifications.success(PREPARING_USERS_TEXT);
- } catch (Exception e) {
- return Notifications.error(PREPARING_USERS_TEXT);
- }
+ if (resp.getError() != null) {
+ logFailure(PREPARING_USERS_TEXT);
+ } else {
+ logSuccess(PREPARING_USERS_TEXT);
+ }
+ } catch (Exception e) {
+ logFailure(PREPARING_USERS_TEXT, e);
}
+ }
- private Message addConnectionView() {
- try {
- DesignDocument connectionDocument = prepareDocument("_design/connection");
- Map<String, MapReduce> views = new HashMap<>();
+ private void addConnectionView() {
+ try {
+ DesignDocument connectionDocument = prepareDocument("_design/connection");
+ Map<String, MapReduce> views = new HashMap<>();
- MapReduce frequentFunction = new MapReduce();
- frequentFunction.setMap("function(doc) { if(doc.from && doc.to) { emit([doc.from, doc.to] , 1 ); } }");
- frequentFunction.setReduce("function (key, values) { return sum(values); }");
+ MapReduce frequentFunction = new MapReduce();
+ frequentFunction.setMap("function(doc) { if(doc.from && doc.to) { emit([doc.from, doc.to] , 1 ); } }");
+ frequentFunction.setReduce("function (key, values) { return sum(values); }");
- views.put("frequent", frequentFunction);
+ views.put("frequent", frequentFunction);
- connectionDocument.setViews(views);
- Response resp = Utils.getCouchDbConnectionClient().design().synchronizeWithDb(connectionDocument);
-
- if (resp.getError() != null) return Notifications.error("Preparing database 'connection'...");
- else return Notifications.success("Preparing database 'connection'...");
- } catch (Exception e) {
- return Notifications.error("Preparing database 'connection'...");
- }
- }
+ connectionDocument.setViews(views);
+ Response resp = Utils.getCouchDbConnectionClient().design().synchronizeWithDb(connectionDocument);
- private DesignDocument prepareDocument(String id) {
- DesignDocument doc = new DesignDocument();
- doc.setLanguage("javascript");
- doc.setId(id);
- return doc;
+ if (resp.getError() != null) {
+ logFailure("Preparing database 'connection'...");
+ } else {
+ logSuccess("Preparing database 'connection'...");
+ }
+ } catch (Exception e) {
+ logFailure("Preparing database 'connection'...", e);
}
+ }
+
+ private DesignDocument prepareDocument(String id) {
+ DesignDocument doc = new DesignDocument();
+ doc.setLanguage("javascript");
+ doc.setId(id);
+ return doc;
+ }
}
diff --git a/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/setup/InstallationConfiguration.java b/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/setup/InstallationConfiguration.java
index d6ad3e4..308d377 100644
--- a/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/setup/InstallationConfiguration.java
+++ b/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/setup/InstallationConfiguration.java
@@ -32,11 +32,15 @@ public class InstallationConfiguration {
List<InstallationStep> steps = new ArrayList<>();
steps.add(new CouchDbInstallationStep());
- steps.add(new UserRegistrationInstallationStep(settings.getAdminEmail(), settings.getAdminPassword()));
+ steps.add(new UserRegistrationInstallationStep(
+ settings.getAdminUser(),
+ settings.getAdminPassword(),
+ settings.getInitialServiceAccountName(),
+ settings.getInitialServiceAccountSecret()));
if (settings.getInstallPipelineElements()) {
for(ExtensionsServiceEndpoint endpoint : new EndpointFetcher().getEndpoints()) {
- steps.add(new PipelineElementInstallationStep(endpoint, settings.getAdminEmail()));
+ steps.add(new PipelineElementInstallationStep(endpoint, settings.getAdminUser()));
}
}
diff --git a/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/setup/InstallationStep.java b/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/setup/InstallationStep.java
index 3f22826..fba1813 100644
--- a/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/setup/InstallationStep.java
+++ b/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/setup/InstallationStep.java
@@ -18,13 +18,36 @@
package org.apache.streampipes.manager.setup;
-import org.apache.streampipes.model.message.Message;
-import java.util.List;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
-public interface InstallationStep {
+public abstract class InstallationStep {
- List<Message> install();
+ public static final Logger LOG = LoggerFactory.getLogger(InstallationStep.class);
+
+ private int errorCount = 0;
+
+ public abstract void install();
+
+ public abstract String getTitle();
+
+ public void logSuccess(String info) {
+ LOG.info(info);
+ }
+
+ public void logFailure(String error) {
+ errorCount++;
+ LOG.error(error);
+ }
+
+ public void logFailure(String error, Exception e) {
+ errorCount++;
+ LOG.error(error, e);
+ }
+
+ public int getErrorCount() {
+ return errorCount;
+ }
- String getTitle();
}
diff --git a/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/setup/Installer.java b/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/setup/Installer.java
deleted file mode 100644
index 504bcfd..0000000
--- a/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/setup/Installer.java
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-package org.apache.streampipes.manager.setup;
-
-import org.apache.streampipes.config.backend.BackendConfig;
-import org.apache.streampipes.model.message.Message;
-import org.apache.streampipes.model.message.SetupStatusMessage;
-import org.apache.streampipes.model.client.setup.InitialSettings;
-
-import java.util.ArrayList;
-import java.util.List;
-
-public class Installer {
-
- private List<InstallationStep> installationSteps;
-
- public Installer(InitialSettings settings) {
- this.installationSteps = InstallationConfiguration.getInstallationSteps(settings);
- }
-
- public SetupStatusMessage install(Integer currentInstallationStepIndex) {
- String nextInstallationStepTitle = "";
- InstallationStep currentInstallationStep = installationSteps.get(currentInstallationStepIndex);
- List<Message> result = new ArrayList<>();
- result.addAll(currentInstallationStep.install());
-
- if (currentInstallationStepIndex == (this.installationSteps.size() - 1)) {
- BackendConfig.INSTANCE.setIsConfigured(true);
- } else {
- nextInstallationStepTitle = installationSteps.get(currentInstallationStepIndex +1).getTitle();
- }
-
- return new SetupStatusMessage(currentInstallationStepIndex, installationSteps.size(), result, nextInstallationStepTitle);
- }
-
-}
diff --git a/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/setup/PipelineElementInstallationStep.java b/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/setup/PipelineElementInstallationStep.java
index 109bc69..67fa355 100644
--- a/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/setup/PipelineElementInstallationStep.java
+++ b/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/setup/PipelineElementInstallationStep.java
@@ -22,39 +22,36 @@ import org.apache.streampipes.manager.operations.Operations;
import org.apache.streampipes.model.client.endpoint.ExtensionsServiceEndpoint;
import org.apache.streampipes.model.client.endpoint.ExtensionsServiceEndpointItem;
import org.apache.streampipes.model.message.Message;
-import org.apache.streampipes.model.message.Notifications;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
-public class PipelineElementInstallationStep implements InstallationStep {
+public class PipelineElementInstallationStep extends InstallationStep {
private ExtensionsServiceEndpoint endpoint;
- private String userEmail;
+ private String principalName;
- public PipelineElementInstallationStep(ExtensionsServiceEndpoint endpoint, String userEmail) {
+ public PipelineElementInstallationStep(ExtensionsServiceEndpoint endpoint, String principalName) {
this.endpoint = endpoint;
- this.userEmail = userEmail;
+ this.principalName = principalName;
}
@Override
- public List<Message> install() {
+ public void install() {
List<Message> statusMessages = new ArrayList<>();
List<ExtensionsServiceEndpointItem> items = Operations.getEndpointUriContents(Collections.singletonList(endpoint));
for(ExtensionsServiceEndpointItem item : items) {
statusMessages.add(new EndpointItemParser().parseAndAddEndpointItem(item.getUri(),
- userEmail, true, false));
+ principalName, true, false));
}
- Message installMessage;
if (statusMessages.stream().allMatch(Message::isSuccess)) {
- installMessage = Notifications.success(getTitle());
+ logSuccess(getTitle());
} else {
- installMessage = Notifications.error(getTitle());
+ logFailure(getTitle());
}
- return Collections.singletonList(installMessage);
}
@Override
diff --git a/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/setup/UserRegistrationInstallationStep.java b/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/setup/UserRegistrationInstallationStep.java
index 85f85b6..90e70f5 100644
--- a/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/setup/UserRegistrationInstallationStep.java
+++ b/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/setup/UserRegistrationInstallationStep.java
@@ -18,47 +18,65 @@
package org.apache.streampipes.manager.setup;
-import org.apache.streampipes.model.message.Message;
-import org.apache.streampipes.model.message.Notifications;
+import org.apache.streampipes.model.client.user.Principal;
import org.apache.streampipes.model.client.user.Role;
-import org.apache.streampipes.model.client.user.User;
+import org.apache.streampipes.model.client.user.ServiceAccount;
+import org.apache.streampipes.model.client.user.UserAccount;
import org.apache.streampipes.storage.management.StorageDispatcher;
import org.apache.streampipes.user.management.util.PasswordUtil;
import java.security.NoSuchAlgorithmException;
import java.security.spec.InvalidKeySpecException;
-import java.util.Arrays;
import java.util.HashSet;
-import java.util.List;
import java.util.Set;
-public class UserRegistrationInstallationStep implements InstallationStep {
+public class UserRegistrationInstallationStep extends InstallationStep {
- private String adminEmail;
- private String adminPassword;
- private Set<Role> roles;
+ private final String adminEmail;
+ private final String adminPassword;
+ private final String initialServiceAccountName;
+ private final String initialServiceAccountSecret;
+ private final Set<Role> roles;
- public UserRegistrationInstallationStep(String adminEmail, String adminPassword) {
+ public UserRegistrationInstallationStep(String adminEmail,
+ String adminPassword,
+ String initialServiceAccountName,
+ String initialServiceAccountSecret) {
this.adminEmail = adminEmail;
this.adminPassword = adminPassword;
+ this.initialServiceAccountName = initialServiceAccountName;
+ this.initialServiceAccountSecret = initialServiceAccountSecret;
roles = new HashSet<>();
roles.add(Role.SYSTEM_ADMINISTRATOR);
roles.add(Role.USER_DEMO);
}
@Override
- public List<Message> install() {
+ public void install() {
try {
- String encryptedPassword = PasswordUtil.encryptPassword(adminPassword);
- StorageDispatcher.INSTANCE.getNoSqlStore().getUserStorageAPI().storeUser(new User(adminEmail,
- encryptedPassword, roles));
- return Arrays.asList(Notifications.success(getTitle()));
+ addAdminUser();
+ addServiceUser();
+
+ logSuccess(getTitle());
} catch (NoSuchAlgorithmException | InvalidKeySpecException e) {
- e.printStackTrace();
- return Arrays.asList(Notifications.error("Could not encrypt password"));
+ logFailure("Could not encrypt password");
}
+ }
+
+ private void addAdminUser() throws NoSuchAlgorithmException, InvalidKeySpecException {
+ String encryptedPassword = PasswordUtil.encryptPassword(adminPassword);
+ UserAccount user = UserAccount.from(adminEmail, encryptedPassword, roles);
+ storePrincipal(user);
+ }
+
+ private void addServiceUser() {
+ ServiceAccount serviceAccount = ServiceAccount.from(initialServiceAccountName, initialServiceAccountSecret, roles);
+ storePrincipal(serviceAccount);
+ }
+ private void storePrincipal(Principal principal) {
+ StorageDispatcher.INSTANCE.getNoSqlStore().getUserStorageAPI().storeUser(principal);
}
@Override
diff --git a/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/storage/UserManagementService.java b/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/storage/UserManagementService.java
index 3ad9f16..26cbe88 100644
--- a/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/storage/UserManagementService.java
+++ b/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/storage/UserManagementService.java
@@ -20,7 +20,7 @@ package org.apache.streampipes.manager.storage;
import org.apache.streampipes.model.client.user.RegistrationData;
import org.apache.streampipes.model.client.user.Role;
-import org.apache.streampipes.model.client.user.User;
+import org.apache.streampipes.model.client.user.UserAccount;
import org.apache.streampipes.storage.api.IUserStorage;
import org.apache.streampipes.storage.management.StorageDispatcher;
import org.apache.streampipes.user.management.util.PasswordUtil;
@@ -32,10 +32,10 @@ import java.util.Set;
public class UserManagementService {
public Boolean registerUser(RegistrationData data, Set<Role> roles) {
- User user = new User(data.getEmail(), data.getPassword(), roles);
try {
String encryptedPassword = PasswordUtil.encryptPassword(data.getPassword());
+ UserAccount user = UserAccount.from(data.getEmail(), encryptedPassword, roles);
user.setPassword(encryptedPassword);
getUserStorage().storeUser(user);
} catch (NoSuchAlgorithmException | InvalidKeySpecException e) {
@@ -45,9 +45,9 @@ public class UserManagementService {
return true;
}
- public static void setHideTutorial(String email, boolean hideTutorial) {
+ public static void setHideTutorial(String principalName, boolean hideTutorial) {
IUserStorage userService = getUserStorage();
- User user = userService.getUser(email);
+ UserAccount user = userService.getUserAccount(principalName);
user.setHideTutorial(hideTutorial);
userService.updateUser(user);
}
diff --git a/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/storage/UserService.java b/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/storage/UserService.java
index c388461..fbb51c2 100644
--- a/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/storage/UserService.java
+++ b/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/storage/UserService.java
@@ -18,14 +18,15 @@
package org.apache.streampipes.manager.storage;
-import org.lightcouch.CouchDbClient;
import org.apache.streampipes.commons.exceptions.ElementNotFoundException;
+import org.apache.streampipes.model.client.user.Principal;
+import org.apache.streampipes.model.client.user.UserAccount;
import org.apache.streampipes.model.pipeline.Pipeline;
-import org.apache.streampipes.model.client.user.User;
import org.apache.streampipes.storage.api.INoSqlStorage;
import org.apache.streampipes.storage.api.IUserStorage;
import org.apache.streampipes.storage.couchdb.utils.Utils;
import org.apache.streampipes.storage.management.StorageDispatcher;
+import org.lightcouch.CouchDbClient;
import java.util.ArrayList;
import java.util.List;
@@ -77,7 +78,7 @@ public class UserService {
if (!checkUser(username)) {
return;
}
- User user = userStorage.getUser(username);
+ Principal user = getPrincipal(username);
user.addOwnSource(elementId, publicElement);
userStorage.updateUser(user);
}
@@ -86,7 +87,7 @@ public class UserService {
if (!checkUser(username)) {
return;
}
- User user = userStorage.getUser(username);
+ Principal user = getPrincipal(username);
user.addOwnAction(elementId, publicElement);
userStorage.updateUser(user);
}
@@ -95,14 +96,14 @@ public class UserService {
if (!checkUser(username)) {
return;
}
- User user = userStorage.getUser(username);
+ Principal user = getPrincipal(username);
user.addOwnSepa(elementId, publicElement);
userStorage.updateUser(user);
}
public void deleteOwnAction(String username, String actionId) {
if (checkUser(username)) {
- User user = userStorage.getUser(username);
+ Principal user = getPrincipal(username);
user.getOwnActions().removeIf(a -> a.getElementId().equals(actionId));
userStorage.updateUser(user);
//TODO remove actions from other users
@@ -111,7 +112,7 @@ public class UserService {
public void deleteOwnSource(String username, String sourceId) {
if (checkUser(username)) {
- User user = userStorage.getUser(username);
+ Principal user = getPrincipal(username);
user.getOwnSources().removeIf(a -> a.getElementId().equals(sourceId));
userStorage.updateUser(user);
}
@@ -119,7 +120,7 @@ public class UserService {
public void deleteOwnSepa(String username, String sepaId) {
if (checkUser(username)) {
- User user = userStorage.getUser(username);
+ Principal user = getPrincipal(username);
user.getOwnSepas().removeIf(a -> a.getElementId().equals(sepaId));
userStorage.updateUser(user);
}
@@ -133,8 +134,8 @@ public class UserService {
if (!checkUser(username)) {
return;
}
- User user = userStorage.getUser(username);
- user.addPreferredSepa(elementId);
+ UserAccount user = getUserAccount(username);
+ user.addPreferredDataProcessor(elementId);
userStorage.updateUser(user);
}
@@ -142,8 +143,8 @@ public class UserService {
if (!checkUser(username)) {
return;
}
- User user = userStorage.getUser(username);
- user.addPreferredAction(elementId);
+ UserAccount user = getUserAccount(username);
+ user.addPreferredDataSink(elementId);
userStorage.updateUser(user);
}
@@ -151,8 +152,8 @@ public class UserService {
if (!checkUser(username)) {
return;
}
- User user = userStorage.getUser(username);
- user.addPreferredSource(elementId);
+ UserAccount user = getUserAccount(username);
+ user.addPreferredDataStream(elementId);
userStorage.updateUser(user);
}
@@ -161,8 +162,8 @@ public class UserService {
if (!checkUser(username)) {
return;
}
- User user = userStorage.getUser(username);
- user.removePreferredSepa(elementId);
+ UserAccount user = getUserAccount(username);
+ user.removePreferredDataProcessor(elementId);
dbClient.update(user);
dbClient.shutdown();
}
@@ -172,8 +173,8 @@ public class UserService {
if (!checkUser(username)) {
return;
}
- User user = userStorage.getUser(username);
- user.removePreferredAction(elementId);
+ UserAccount user = getUserAccount(username);
+ user.removePreferredDataSink(elementId);
dbClient.update(user);
dbClient.shutdown();
}
@@ -183,8 +184,8 @@ public class UserService {
if (!checkUser(username)) {
return;
}
- User user = userStorage.getUser(username);
- user.removePreferredSource(elementId);
+ UserAccount user = getUserAccount(username);
+ user.removePreferredDataStream(elementId);
dbClient.update(user);
dbClient.shutdown();
}
@@ -198,35 +199,35 @@ public class UserService {
}
public List<String> getFavoriteActionUris(String username) {
- return userStorage.getUser(username).getPreferredActions();
+ return getUserAccount(username).getPreferredDataSinks();
}
- public List<String> getAvailableActionUris(String email) {
- List<String> actions = new ArrayList<>(getOwnActionUris(email));
+ public List<String> getAvailableActionUris(String principalName) {
+ List<String> actions = new ArrayList<>(getOwnActionUris(principalName));
userStorage
.getAllUsers()
.stream()
- .filter(u -> !(u.getEmail().equals(email)))
+ .filter(u -> !(u.getPrincipalName().equals(principalName)))
.map(u -> u.getOwnActions().stream().filter(p -> p.isPublicElement()).map(p -> p.getElementId()).collect(Collectors.toList())).forEach(actions::addAll);
return actions;
}
- public List<String> getOwnSepaUris(String email) {
- return userStorage.getUser(email).getOwnSepas().stream().map(r -> r.getElementId()).collect(Collectors.toList());
+ public List<String> getOwnSepaUris(String username) {
+ return userStorage.getUser(username).getOwnSepas().stream().map(r -> r.getElementId()).collect(Collectors.toList());
}
- public List<String> getAvailableSepaUris(String email) {
- List<String> sepas = new ArrayList<>(getOwnSepaUris(email));
+ public List<String> getAvailableSepaUris(String principalName) {
+ List<String> sepas = new ArrayList<>(getOwnSepaUris(principalName));
userStorage
.getAllUsers()
.stream()
- .filter(u -> !(u.getEmail().equals(email)))
+ .filter(u -> !(u.getPrincipalName().equals(principalName)))
.map(u -> u.getOwnSepas().stream().filter(p -> p.isPublicElement()).map(p -> p.getElementId()).collect(Collectors.toList())).forEach(sepas::addAll);
return sepas;
}
- public List<String> getFavoriteSepaUris(String email) {
- return userStorage.getUser(email).getPreferredSepas();
+ public List<String> getFavoriteSepaUris(String principalName) {
+ return getUserAccount(principalName).getPreferredDataProcessors();
}
public List<String> getOwnSourceUris(String email) {
@@ -238,12 +239,12 @@ public class UserService {
.collect(Collectors.toList());
}
- public List<String> getAvailableSourceUris(String email) {
- List<String> sources = new ArrayList<>(getOwnSepaUris(email));
+ public List<String> getAvailableSourceUris(String principalName) {
+ List<String> sources = new ArrayList<>(getOwnSepaUris(principalName));
userStorage
.getAllUsers()
.stream()
- .filter(u -> !(u.getEmail().equals(email)))
+ .filter(u -> !(u.getPrincipalName().equals(principalName)))
.map(u -> u.getOwnSources()
.stream()
.filter(p -> p.isPublicElement())
@@ -254,7 +255,15 @@ public class UserService {
}
public List<String> getFavoriteSourceUris(String username) {
- return userStorage.getUser(username).getPreferredSources();
+ return getUserAccount(username).getPreferredDataStreams();
+ }
+
+ public UserAccount getUserAccount(String principalName) {
+ return (UserAccount) getPrincipal(principalName);
+ }
+
+ private Principal getPrincipal(String principalName) {
+ return userStorage.getUser(principalName);
}
private IUserStorage userStorage() {
diff --git a/streampipes-rest/src/main/java/org/apache/streampipes/rest/filter/TokenAuthenticationFilter.java b/streampipes-rest/src/main/java/org/apache/streampipes/rest/filter/TokenAuthenticationFilter.java
index 04a3692..d9dc16d 100644
--- a/streampipes-rest/src/main/java/org/apache/streampipes/rest/filter/TokenAuthenticationFilter.java
+++ b/streampipes-rest/src/main/java/org/apache/streampipes/rest/filter/TokenAuthenticationFilter.java
@@ -3,7 +3,6 @@ package org.apache.streampipes.rest.filter;
import org.apache.streampipes.storage.api.IUserStorage;
import org.apache.streampipes.storage.management.StorageDispatcher;
import org.apache.streampipes.user.management.jwt.JwtTokenProvider;
-import org.apache.streampipes.user.management.model.LocalUser;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
@@ -43,7 +42,7 @@ public class TokenAuthenticationFilter extends OncePerRequestFilter {
if (StringUtils.hasText(jwt) && tokenProvider.validateJwtToken(jwt)) {
String username = tokenProvider.getUserIdFromToken(jwt);
- UserDetails userDetails = new LocalUser(userStorage.getUser(username));
+ UserDetails userDetails = userStorage.getUser(username);
UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
diff --git a/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/Authentication.java b/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/Authentication.java
index 433f0c2..fdd0824 100644
--- a/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/Authentication.java
+++ b/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/Authentication.java
@@ -28,7 +28,6 @@ import org.apache.streampipes.rest.core.base.impl.AbstractRestResource;
import org.apache.streampipes.rest.shared.annotation.GsonWithIds;
import org.apache.streampipes.rest.shared.annotation.JacksonSerialized;
import org.apache.streampipes.user.management.jwt.JwtTokenProvider;
-import org.apache.streampipes.user.management.model.LocalUser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.BadCredentialsException;
@@ -52,7 +51,7 @@ public class Authentication extends AbstractRestResource {
@JacksonSerialized
@POST
@Path("/login")
- public Response doLogin(ShiroAuthenticationRequest token) {
+ public Response doLogin(LoginRequest token) {
try {
org.springframework.security.core.Authentication authentication = authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(token.getUsername(), token.getPassword()));
SecurityContextHolder.getContext().setAuthentication(authentication);
@@ -97,11 +96,11 @@ public class Authentication extends AbstractRestResource {
private JwtAuthenticationResponse makeJwtResponse(org.springframework.security.core.Authentication auth) {
String jwt = new JwtTokenProvider().createToken(auth);
- LocalUser localUser = (LocalUser) auth.getPrincipal();
+ UserAccount localUser = (UserAccount) auth.getPrincipal();
return JwtAuthenticationResponse.from(jwt, toUserInfo(localUser));
}
- private UserInfo toUserInfo(LocalUser localUser) {
+ private UserInfo toUserInfo(UserAccount localUser) {
UserInfo userInfo = new UserInfo();
userInfo.setUserId("id");
userInfo.setEmail(localUser.getEmail());
diff --git a/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/Setup.java b/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/Setup.java
index 8f028b6..5b89102 100644
--- a/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/Setup.java
+++ b/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/Setup.java
@@ -20,16 +20,15 @@ package org.apache.streampipes.rest.impl;
import com.google.gson.JsonObject;
import org.apache.streampipes.config.backend.BackendConfig;
-import org.apache.streampipes.manager.setup.Installer;
import org.apache.streampipes.model.client.setup.InitialSettings;
import org.apache.streampipes.model.message.Notifications;
-import org.apache.streampipes.model.message.SetupStatusMessage;
import org.apache.streampipes.rest.core.base.impl.AbstractRestResource;
-import org.apache.streampipes.rest.notifications.NotificationListener;
import org.apache.streampipes.rest.shared.annotation.GsonWithIds;
-import org.apache.streampipes.rest.shared.annotation.JacksonSerialized;
-import javax.ws.rs.*;
+import javax.ws.rs.GET;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
@@ -46,23 +45,11 @@ public class Setup extends AbstractRestResource {
return ok(obj.toString());
} else {
obj.addProperty("configured", false);
+ obj.addProperty("setupRunning", BackendConfig.INSTANCE.isConfigured());
return ok(obj.toString());
}
}
- @POST
- @Path("/install/{currentInstallationStep}")
- @JacksonSerialized
- @Consumes(MediaType.APPLICATION_JSON)
- @Produces(MediaType.APPLICATION_JSON)
- public Response configure(InitialSettings settings, @PathParam("currentInstallationStep") Integer currentInstallationStep) {
- SetupStatusMessage message = new Installer(settings).install(currentInstallationStep);
- if (currentInstallationStep == (message.getInstallationStepCount() - 1)) {
- new NotificationListener().contextInitialized(null);
- }
- return ok(message);
- }
-
@PUT
@Path("/configuration")
@GsonWithIds
diff --git a/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/UserProfile.java b/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/UserProfile.java
index 5a67aca..cb50c1d 100644
--- a/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/UserProfile.java
+++ b/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/UserProfile.java
@@ -19,6 +19,7 @@
package org.apache.streampipes.rest.impl;
import org.apache.streampipes.model.client.user.RawUserApiToken;
+import org.apache.streampipes.model.client.user.UserAccount;
import org.apache.streampipes.model.message.Notifications;
import org.apache.streampipes.rest.core.base.impl.AbstractAuthGuardedRestResource;
import org.apache.streampipes.rest.shared.annotation.JacksonSerialized;
@@ -35,7 +36,7 @@ public class UserProfile extends AbstractAuthGuardedRestResource {
@GET
@Produces(MediaType.APPLICATION_JSON)
public Response getUserDetails() {
- org.apache.streampipes.model.client.user.User user = getUser(getAuthenticatedUsername());
+ UserAccount user = getUser(getAuthenticatedUsername());
user.setPassword("");
if (user != null) {
@@ -51,7 +52,7 @@ public class UserProfile extends AbstractAuthGuardedRestResource {
public Response updateAppearanceMode(@PathParam("darkMode") boolean darkMode) {
String authenticatedUserId = getAuthenticatedUsername();
if (authenticatedUserId != null) {
- org.apache.streampipes.model.client.user.User user = getUser(authenticatedUserId);
+ UserAccount user = getUser(authenticatedUserId);
user.setDarkMode(darkMode);
getUserStorage().updateUser(user);
@@ -64,10 +65,10 @@ public class UserProfile extends AbstractAuthGuardedRestResource {
@PUT
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
- public Response updateUserDetails(org.apache.streampipes.model.client.user.User user) {
+ public Response updateUserDetails(UserAccount user) {
String authenticatedUserId = getAuthenticatedUsername();
if (user != null && authenticatedUserId.equals(user.getEmail())) {
- org.apache.streampipes.model.client.user.User existingUser = getUser(user.getEmail());
+ UserAccount existingUser = getUser(user.getEmail());
user.setPassword(existingUser.getPassword());
user.setUserApiTokens(existingUser
.getUserApiTokens()
@@ -86,8 +87,8 @@ public class UserProfile extends AbstractAuthGuardedRestResource {
}
}
- private org.apache.streampipes.model.client.user.User getUser(String email) {
- return getUserStorage().getUser(email);
+ private UserAccount getUser(String email) {
+ return getUserStorage().getUserAccount(email);
}
@POST
diff --git a/streampipes-security-jwt/pom.xml b/streampipes-security-jwt/pom.xml
new file mode 100644
index 0000000..78f8d87
--- /dev/null
+++ b/streampipes-security-jwt/pom.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <parent>
+ <artifactId>streampipes-parent</artifactId>
+ <groupId>org.apache.streampipes</groupId>
+ <version>0.69.0-SNAPSHOT</version>
+ </parent>
+ <modelVersion>4.0.0</modelVersion>
+
+ <artifactId>streampipes-security-jwt</artifactId>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.streampipes</groupId>
+ <artifactId>streampipes-commons</artifactId>
+ <version>0.69.0-SNAPSHOT</version>
+ </dependency>
+ <dependency>
+ <groupId>io.jsonwebtoken</groupId>
+ <artifactId>jjwt-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>io.jsonwebtoken</groupId>
+ <artifactId>jjwt-impl</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>io.jsonwebtoken</groupId>
+ <artifactId>jjwt-jackson</artifactId>
+ </dependency>
+ </dependencies>
+
+</project>
diff --git a/streampipes-security-jwt/src/main/java/org/apache/streampipes/security/jwt/JwtTokenUtils.java b/streampipes-security-jwt/src/main/java/org/apache/streampipes/security/jwt/JwtTokenUtils.java
new file mode 100644
index 0000000..81035d4
--- /dev/null
+++ b/streampipes-security-jwt/src/main/java/org/apache/streampipes/security/jwt/JwtTokenUtils.java
@@ -0,0 +1,78 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.streampipes.security.jwt;
+
+import io.jsonwebtoken.*;
+import io.jsonwebtoken.security.Keys;
+import io.jsonwebtoken.security.WeakKeyException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.crypto.SecretKey;
+import java.nio.charset.StandardCharsets;
+import java.util.Date;
+
+public class JwtTokenUtils {
+
+ private static final Logger LOG = LoggerFactory.getLogger(JwtTokenUtils.class);
+
+ public static String makeJwtToken(String subject,
+ String tokenSecret,
+ Date expirationDate) {
+
+ SecretKey key = Keys.hmacShaKeyFor(tokenSecret.getBytes(StandardCharsets.UTF_8));
+
+ return Jwts
+ .builder()
+ .setSubject(subject)
+ .setIssuedAt(new Date())
+ .setExpiration(expirationDate)
+ .signWith(key).compact();
+ }
+
+ public static String getUserIdFromToken(String tokenSecret,
+ String token) {
+ Claims claims = jwtParser(tokenSecret).parseClaimsJws(token).getBody();
+ return claims.getSubject();
+ }
+
+ private static JwtParser jwtParser(String tokenSecret) {
+ return Jwts.parserBuilder()
+ .setSigningKey(tokenSecret.getBytes(StandardCharsets.UTF_8))
+ .build();
+ }
+
+ public static boolean validateJwtToken(String tokenSecret,
+ String jwtToken) {
+ try {
+ jwtParser(tokenSecret).parseClaimsJws(jwtToken);
+ return true;
+ } catch (MalformedJwtException ex) {
+ LOG.error("Invalid JWT token");
+ } catch (ExpiredJwtException ex) {
+ LOG.error("Expired JWT token");
+ } catch (UnsupportedJwtException ex) {
+ LOG.error("Unsupported JWT token");
+ } catch (IllegalArgumentException ex) {
+ LOG.error("JWT claims are empty.");
+ } catch (WeakKeyException ex) {
+ LOG.error("Weak Key");
+ }
+ return false;
+ }
+}
diff --git a/streampipes-serializers-json/src/main/java/org/apache/streampipes/serializers/json/GsonSerializer.java b/streampipes-serializers-json/src/main/java/org/apache/streampipes/serializers/json/GsonSerializer.java
index bde286b..081a300 100644
--- a/streampipes-serializers-json/src/main/java/org/apache/streampipes/serializers/json/GsonSerializer.java
+++ b/streampipes-serializers-json/src/main/java/org/apache/streampipes/serializers/json/GsonSerializer.java
@@ -23,18 +23,19 @@ import com.google.gson.FieldAttributes;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import org.apache.streampipes.model.*;
-import org.apache.streampipes.model.connect.rules.value.*;
-import org.apache.streampipes.model.message.Message;
+import org.apache.streampipes.model.client.user.Principal;
import org.apache.streampipes.model.connect.adapter.*;
+import org.apache.streampipes.model.connect.rules.TransformationRuleDescription;
import org.apache.streampipes.model.connect.rules.schema.CreateNestedRuleDescription;
import org.apache.streampipes.model.connect.rules.schema.DeleteRuleDescription;
import org.apache.streampipes.model.connect.rules.schema.MoveRuleDescription;
import org.apache.streampipes.model.connect.rules.schema.RenameRuleDescription;
import org.apache.streampipes.model.connect.rules.stream.EventRateTransformationRuleDescription;
import org.apache.streampipes.model.connect.rules.stream.RemoveDuplicatesTransformationRuleDescription;
-import org.apache.streampipes.model.connect.rules.TransformationRuleDescription;
+import org.apache.streampipes.model.connect.rules.value.*;
import org.apache.streampipes.model.grounding.TopicDefinition;
import org.apache.streampipes.model.grounding.TransportProtocol;
+import org.apache.streampipes.model.message.Message;
import org.apache.streampipes.model.output.OutputStrategy;
import org.apache.streampipes.model.quality.EventPropertyQualityDefinition;
import org.apache.streampipes.model.quality.EventStreamQualityDefinition;
@@ -57,6 +58,13 @@ public class GsonSerializer {
return builder;
}
+ public static GsonBuilder getPrincipalGsonBuilder() {
+ GsonBuilder builder = getGsonBuilder();
+ builder.registerTypeHierarchyAdapter(Principal.class, new PrincipalDeserializer());
+
+ return builder;
+ }
+
public static Gson getAdapterGson() {
return getAdapterGsonBuilder().create();
}
diff --git a/streampipes-serializers-json/src/main/java/org/apache/streampipes/serializers/json/PrincipalDeserializer.java b/streampipes-serializers-json/src/main/java/org/apache/streampipes/serializers/json/PrincipalDeserializer.java
new file mode 100644
index 0000000..83cf3c9
--- /dev/null
+++ b/streampipes-serializers-json/src/main/java/org/apache/streampipes/serializers/json/PrincipalDeserializer.java
@@ -0,0 +1,67 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.streampipes.serializers.json;
+
+import com.google.gson.*;
+import org.apache.streampipes.model.client.user.Principal;
+
+import java.lang.reflect.MalformedParameterizedTypeException;
+import java.lang.reflect.Type;
+
+public class PrincipalDeserializer implements JsonDeserializer<Principal>, JsonSerializer<Principal> {
+ @Override
+ public Principal deserialize(JsonElement json, Type typeInfo, JsonDeserializationContext context) throws JsonParseException {
+ JsonObject jsonObject = json.getAsJsonObject();
+ String type = jsonObject.get("field_type").getAsString();
+ JsonElement element = jsonObject.get("properties");
+ JsonObject tmp = element.getAsJsonObject();
+ if (jsonObject.has("_id")) {
+ tmp.addProperty("_id", jsonObject.get("_id").getAsString());
+ }
+ if (jsonObject.has("_rev")) {
+ tmp.addProperty("_rev", jsonObject.get("_rev").getAsString());
+ }
+
+ try {
+ return (Principal) GsonSerializer.getGson().fromJson(element, Class.forName(type));
+ } catch (ClassNotFoundException cnfe) {
+ throw new JsonParseException("Unknown element type: " + type, cnfe);
+ }
+ }
+
+ @Override
+ public JsonElement serialize(Principal src, Type type, JsonSerializationContext context) {
+ JsonObject result = new JsonObject();
+ try {
+ // Both types are required to deserialize adapters correctly
+ result.add("type", new JsonPrimitive(src.getClass().getCanonicalName()));
+ result.add("field_type", new JsonPrimitive(src.getClass().getCanonicalName()));
+ result.add("properties", GsonSerializer.getGson().toJsonTree(src));
+ if (src.getPrincipalId() != null) {
+ result.add("_id", new JsonPrimitive(src.getPrincipalId()));
+ }
+ if (src.getRev() != null) {
+ result.add("_rev", new JsonPrimitive(src.getRev()));
+ }
+ } catch (MalformedParameterizedTypeException e) {
+ e.printStackTrace();
+ }
+
+ return result;
+ }
+}
diff --git a/streampipes-storage-api/src/main/java/org/apache/streampipes/storage/api/IUserStorage.java b/streampipes-storage-api/src/main/java/org/apache/streampipes/storage/api/IUserStorage.java
index 25e4c84..4f1c7f8 100644
--- a/streampipes-storage-api/src/main/java/org/apache/streampipes/storage/api/IUserStorage.java
+++ b/streampipes-storage-api/src/main/java/org/apache/streampipes/storage/api/IUserStorage.java
@@ -17,18 +17,28 @@
*/
package org.apache.streampipes.storage.api;
-import org.apache.streampipes.model.client.user.User;
+import org.apache.streampipes.model.client.user.Principal;
+import org.apache.streampipes.model.client.user.ServiceAccount;
+import org.apache.streampipes.model.client.user.UserAccount;
import java.util.List;
public interface IUserStorage {
- List<User> getAllUsers();
+ List<Principal> getAllUsers();
- User getUser(String email);
+ List<UserAccount> getAllUserAccounts();
- void storeUser(User user);
+ List<ServiceAccount> getAllServiceAccounts();
- void updateUser(User user);
+ Principal getUser(String principalName);
+
+ UserAccount getUserAccount(String principalName);
+
+ ServiceAccount getServiceAccount(String principalName);
+
+ void storeUser(Principal user);
+
+ void updateUser(Principal user);
boolean emailExists(String email);
diff --git a/streampipes-storage-couchdb/src/main/java/org/apache/streampipes/storage/couchdb/impl/UserStorage.java b/streampipes-storage-couchdb/src/main/java/org/apache/streampipes/storage/couchdb/impl/UserStorage.java
index e560b6e..c4b6d7f 100644
--- a/streampipes-storage-couchdb/src/main/java/org/apache/streampipes/storage/couchdb/impl/UserStorage.java
+++ b/streampipes-storage-couchdb/src/main/java/org/apache/streampipes/storage/couchdb/impl/UserStorage.java
@@ -18,7 +18,9 @@
package org.apache.streampipes.storage.couchdb.impl;
-import org.apache.streampipes.model.client.user.User;
+import org.apache.streampipes.model.client.user.Principal;
+import org.apache.streampipes.model.client.user.ServiceAccount;
+import org.apache.streampipes.model.client.user.UserAccount;
import org.apache.streampipes.storage.api.IUserStorage;
import org.apache.streampipes.storage.couchdb.dao.AbstractDao;
import org.apache.streampipes.storage.couchdb.utils.Utils;
@@ -28,6 +30,7 @@ import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.List;
+import java.util.stream.Collectors;
/**
* User Storage.
@@ -35,26 +38,44 @@ import java.util.List;
*
*
*/
-public class UserStorage extends AbstractDao<User> implements IUserStorage {
+public class UserStorage extends AbstractDao<Principal> implements IUserStorage {
Logger LOG = LoggerFactory.getLogger(UserStorage.class);
public UserStorage() {
- super(Utils::getCouchDbUserClient, User.class);
+ super(Utils::getCouchDbUserClient, Principal.class);
}
@Override
- public List<User> getAllUsers()
+ public List<Principal> getAllUsers()
{
- List<User> users = findAll();
+ List<Principal> users = findAll();
return new ArrayList<>(users);
}
@Override
- public User getUser(String email) {
+ public List<UserAccount> getAllUserAccounts() {
+ return findAll()
+ .stream()
+ .filter(u -> u instanceof UserAccount)
+ .map(u -> (UserAccount) u)
+ .collect(Collectors.toList());
+ }
+
+ @Override
+ public List<ServiceAccount> getAllServiceAccounts() {
+ return findAll()
+ .stream()
+ .filter(u -> u instanceof ServiceAccount)
+ .map(u -> (ServiceAccount) u)
+ .collect(Collectors.toList());
+ }
+
+ @Override
+ public Principal getUser(String principalName) {
// TODO improve
CouchDbClient couchDbClient = couchDbClientSupplier.get();
- List<User> users = couchDbClient.view("users/username").key(email).includeDocs(true).query(User.class);
+ List<Principal> users = couchDbClient.view("users/username").key(principalName).includeDocs(true).query(Principal.class);
if (users.size() != 1) {
LOG.error("None or to many users with matching username");
}
@@ -62,19 +83,29 @@ public class UserStorage extends AbstractDao<User> implements IUserStorage {
}
@Override
- public void storeUser(User user) {
+ public UserAccount getUserAccount(String principalName) {
+ return (UserAccount) getUser(principalName);
+ }
+
+ @Override
+ public ServiceAccount getServiceAccount(String principalName) {
+ return (ServiceAccount) getUser(principalName);
+ }
+
+ @Override
+ public void storeUser(Principal user) {
persist(user);
}
@Override
- public void updateUser(User user) {
+ public void updateUser(Principal user) {
update(user);
}
@Override
public boolean emailExists(String email)
{
- List<User> users = findAll();
+ List<UserAccount> users = getAllUserAccounts();
return users
.stream()
.filter(u -> u.getEmail() != null)
@@ -88,12 +119,12 @@ public class UserStorage extends AbstractDao<User> implements IUserStorage {
*/
@Override
public boolean checkUser(String username) {
- List<User> users = couchDbClientSupplier
+ List<Principal> users = couchDbClientSupplier
.get()
.view("users/username")
.key(username)
.includeDocs(true)
- .query(User.class);
+ .query(Principal.class);
return users.size() == 1;
}
diff --git a/streampipes-storage-couchdb/src/main/java/org/apache/streampipes/storage/couchdb/utils/Utils.java b/streampipes-storage-couchdb/src/main/java/org/apache/streampipes/storage/couchdb/utils/Utils.java
index bbfd343..ba2aba5 100644
--- a/streampipes-storage-couchdb/src/main/java/org/apache/streampipes/storage/couchdb/utils/Utils.java
+++ b/streampipes-storage-couchdb/src/main/java/org/apache/streampipes/storage/couchdb/utils/Utils.java
@@ -18,9 +18,9 @@
package org.apache.streampipes.storage.couchdb.utils;
+import org.apache.streampipes.serializers.json.GsonSerializer;
import org.lightcouch.CouchDbClient;
import org.lightcouch.CouchDbProperties;
-import org.apache.streampipes.serializers.json.GsonSerializer;
public class Utils {
@@ -111,7 +111,7 @@ public class Utils {
}
public static CouchDbClient getCouchDbUserClient() {
- return getCouchDbGsonClient("users");
+ return getCouchDbPrincipalClient("users");
}
public static CouchDbClient getCouchDbInternalUsersClient() {
@@ -152,6 +152,12 @@ public class Utils {
return dbClient;
}
+ private static CouchDbClient getCouchDbPrincipalClient(String dbname) {
+ CouchDbClient dbClient = new CouchDbClient(props(dbname));
+ dbClient.setGsonBuilder(GsonSerializer.getPrincipalGsonBuilder());
+ return dbClient;
+ }
+
private static CouchDbClient getCouchDbAdapterClient(String dbname) {
CouchDbClient dbClient = new CouchDbClient(props(dbname));
dbClient.setGsonBuilder(GsonSerializer.getAdapterGsonBuilder());
diff --git a/streampipes-user-management/pom.xml b/streampipes-user-management/pom.xml
index 6e39373..779eb0f 100644
--- a/streampipes-user-management/pom.xml
+++ b/streampipes-user-management/pom.xml
@@ -41,6 +41,11 @@
</dependency>
<dependency>
<groupId>org.apache.streampipes</groupId>
+ <artifactId>streampipes-security-jwt</artifactId>
+ <version>0.69.0-SNAPSHOT</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.streampipes</groupId>
<artifactId>streampipes-storage-management</artifactId>
<version>0.69.0-SNAPSHOT</version>
</dependency>
diff --git a/streampipes-user-management/src/main/java/org/apache/streampipes/user/management/jwt/JwtTokenProvider.java b/streampipes-user-management/src/main/java/org/apache/streampipes/user/management/jwt/JwtTokenProvider.java
index 1a90e14..773a63d 100644
--- a/streampipes-user-management/src/main/java/org/apache/streampipes/user/management/jwt/JwtTokenProvider.java
+++ b/streampipes-user-management/src/main/java/org/apache/streampipes/user/management/jwt/JwtTokenProvider.java
@@ -1,22 +1,15 @@
package org.apache.streampipes.user.management.jwt;
-import io.jsonwebtoken.*;
-import io.jsonwebtoken.security.Keys;
-import io.jsonwebtoken.security.WeakKeyException;
import org.apache.streampipes.config.backend.BackendConfig;
import org.apache.streampipes.config.backend.model.LocalAuthConfig;
-import org.apache.streampipes.user.management.model.LocalUser;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
+import org.apache.streampipes.model.client.user.Principal;
+import org.apache.streampipes.security.jwt.JwtTokenUtils;
import org.springframework.security.core.Authentication;
-import javax.crypto.SecretKey;
-import java.nio.charset.StandardCharsets;
import java.util.Date;
public class JwtTokenProvider {
- private static final Logger LOG = LoggerFactory.getLogger(JwtTokenProvider.class);
private BackendConfig config;
public JwtTokenProvider() {
@@ -24,45 +17,18 @@ public class JwtTokenProvider {
}
public String createToken(Authentication authentication) {
- LocalUser userPrincipal = (LocalUser) authentication.getPrincipal();
+ Principal userPrincipal = (Principal) authentication.getPrincipal();
Date tokenExpirationDate = makeExpirationDate();
- SecretKey key = Keys.hmacShaKeyFor(tokenSecret().getBytes(StandardCharsets.UTF_8));
- return Jwts
- .builder()
- .setSubject(userPrincipal.getEmail())
- .setIssuedAt(new Date())
- .setExpiration(tokenExpirationDate)
- .signWith(key).compact();
+ return JwtTokenUtils.makeJwtToken(userPrincipal.getPrincipalName(), tokenSecret(), tokenExpirationDate);
}
public String getUserIdFromToken(String token) {
- Claims claims = jwtParser().parseClaimsJws(token).getBody();
- return claims.getSubject();
+ return JwtTokenUtils.getUserIdFromToken(tokenSecret(), token);
}
public boolean validateJwtToken(String jwtToken) {
- try {
- jwtParser().parseClaimsJws(jwtToken);
- return true;
- } catch (MalformedJwtException ex) {
- LOG.error("Invalid JWT token");
- } catch (ExpiredJwtException ex) {
- LOG.error("Expired JWT token");
- } catch (UnsupportedJwtException ex) {
- LOG.error("Unsupported JWT token");
- } catch (IllegalArgumentException ex) {
- LOG.error("JWT claims are empty.");
- } catch (WeakKeyException ex) {
- LOG.error("Weak Key");
- }
- return false;
- }
-
- private JwtParser jwtParser() {
- return Jwts.parserBuilder()
- .setSigningKey(tokenSecret().getBytes(StandardCharsets.UTF_8))
- .build();
+ return JwtTokenUtils.validateJwtToken(tokenSecret(), jwtToken);
}
private String tokenSecret() {
diff --git a/streampipes-user-management/src/main/java/org/apache/streampipes/user/management/model/LocalUser.java b/streampipes-user-management/src/main/java/org/apache/streampipes/user/management/model/LocalUser.java
deleted file mode 100644
index d7aeffd..0000000
--- a/streampipes-user-management/src/main/java/org/apache/streampipes/user/management/model/LocalUser.java
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-package org.apache.streampipes.user.management.model;
-
-import org.apache.streampipes.model.client.user.User;
-import org.springframework.security.core.GrantedAuthority;
-import org.springframework.security.core.userdetails.UserDetails;
-
-import java.util.Collection;
-import java.util.Collections;
-
-public class LocalUser extends User implements UserDetails {
-
- public LocalUser(User user) {
- this.username = user.getUsername();
- this.email = user.getEmail();
- this.ownSepas = user.getOwnSepas();
- this.ownActions = user.getOwnActions();
- this.darkMode = user.isDarkMode();
- this.hideTutorial = user.isHideTutorial();
- this.fullName = user.getFullName();
- this.ownSources = user.getOwnSources();
- this.preferredActions = user.getPreferredActions();
- this.preferredSepas = user.getPreferredSepas();
- this.preferredSources = user.getPreferredSources();
- this.password = user.getPassword();
- this.rev = user.getRev();
- this.userId = user.getUserId();
- this.roles= user.getRoles();
- this.userApiTokens = user.getUserApiTokens();
- }
-
- @Override
- public Collection<? extends GrantedAuthority> getAuthorities() {
- return Collections.emptyList();
- }
-
- @Override
- public String getPassword() {
- return password;
- }
-
- @Override
- public String getUsername() {
- return email;
- }
-
- @Override
- public boolean isAccountNonExpired() {
- return true;
- }
-
- @Override
- public boolean isAccountNonLocked() {
- return true;
- }
-
- @Override
- public boolean isCredentialsNonExpired() {
- return true;
- }
-
- @Override
- public boolean isEnabled() {
- return true;
- }
-}
diff --git a/streampipes-user-management/src/main/java/org/apache/streampipes/user/management/service/SpUserDetailsService.java b/streampipes-user-management/src/main/java/org/apache/streampipes/user/management/service/SpUserDetailsService.java
index dd6fff1..7bf27af 100644
--- a/streampipes-user-management/src/main/java/org/apache/streampipes/user/management/service/SpUserDetailsService.java
+++ b/streampipes-user-management/src/main/java/org/apache/streampipes/user/management/service/SpUserDetailsService.java
@@ -17,9 +17,7 @@
*/
package org.apache.streampipes.user.management.service;
-import org.apache.streampipes.model.client.user.User;
import org.apache.streampipes.storage.management.StorageDispatcher;
-import org.apache.streampipes.user.management.model.LocalUser;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
@@ -28,8 +26,6 @@ public class SpUserDetailsService implements UserDetailsService {
@Override
public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {
- User user = StorageDispatcher.INSTANCE.getNoSqlStore().getUserStorageAPI().getUser(s);
- LocalUser localUser = new LocalUser(user);
- return new LocalUser(localUser);
+ return StorageDispatcher.INSTANCE.getNoSqlStore().getUserStorageAPI().getUser(s);
}
}
diff --git a/streampipes-user-management/src/main/java/org/apache/streampipes/user/management/service/TokenService.java b/streampipes-user-management/src/main/java/org/apache/streampipes/user/management/service/TokenService.java
index a6eea99..d183c4c 100644
--- a/streampipes-user-management/src/main/java/org/apache/streampipes/user/management/service/TokenService.java
+++ b/streampipes-user-management/src/main/java/org/apache/streampipes/user/management/service/TokenService.java
@@ -17,29 +17,24 @@
*/
package org.apache.streampipes.user.management.service;
-import com.google.gson.JsonObject;
import org.apache.streampipes.model.client.user.RawUserApiToken;
-import org.apache.streampipes.model.client.user.User;
+import org.apache.streampipes.model.client.user.UserAccount;
import org.apache.streampipes.storage.api.IUserStorage;
-import org.apache.streampipes.storage.couchdb.utils.Utils;
import org.apache.streampipes.storage.management.StorageDispatcher;
import org.apache.streampipes.user.management.util.TokenUtil;
-import org.lightcouch.CouchDbClient;
-
-import java.nio.file.attribute.UserPrincipalNotFoundException;
-import java.util.List;
public class TokenService {
- public RawUserApiToken createAndStoreNewToken(String email, RawUserApiToken baseToken) {
- User user = getUserStorage().getUser(email);
+ public RawUserApiToken createAndStoreNewToken(String email,
+ RawUserApiToken baseToken) {
+ UserAccount user = getUserStorage().getUserAccount(email);
RawUserApiToken generatedToken = TokenUtil.createToken(baseToken.getTokenName());
storeToken(user, generatedToken);
generatedToken.setHashedToken("");
return generatedToken;
}
- private void storeToken(User user, RawUserApiToken generatedToken) {
+ private void storeToken(UserAccount user, RawUserApiToken generatedToken) {
user.getUserApiTokens().add(TokenUtil.toUserToken(generatedToken));
getUserStorage().updateUser(user);
}
@@ -49,13 +44,4 @@ public class TokenService {
.getNoSqlStore()
.getUserStorageAPI();
}
-
- public User findUserForToken(String token) throws UserPrincipalNotFoundException {
- CouchDbClient dbClient = Utils.getCouchDbUserClient();
- List<JsonObject> users = dbClient.view("users/token").key(token).includeDocs(true).query(JsonObject.class);
- if (users.size() != 1) {
- throw new UserPrincipalNotFoundException("None or too many users with matching token");
- }
- return getUserStorage().getUser(users.get(0).get("email").getAsString());
- }
}
diff --git a/ui/src/app/core-model/gen/streampipes-model-client.ts b/ui/src/app/core-model/gen/streampipes-model-client.ts
index 98b0297..f6b10b4 100644
--- a/ui/src/app/core-model/gen/streampipes-model-client.ts
+++ b/ui/src/app/core-model/gen/streampipes-model-client.ts
@@ -16,11 +16,10 @@
*
*/
-
/* tslint:disable */
/* eslint-disable */
// @ts-nocheck
-// Generated using typescript-generator version 2.27.744 on 2021-09-30 14:45:03.
+// Generated using typescript-generator version 2.27.744 on 2021-10-01 13:23:19.
export class Element {
elementId: string;
@@ -99,6 +98,10 @@ export class FileMetadata {
}
}
+export interface GrantedAuthority {
+ authority: string;
+}
+
export class MatchingResultMessage {
description: string;
matchingSuccessful: boolean;
@@ -122,6 +125,51 @@ export class MatchingResultMessage {
}
}
+export class Principal implements UserDetails {
+ accountEnabled: boolean;
+ accountExpired: boolean;
+ accountLocked: boolean;
+ accountNonExpired: boolean;
+ accountNonLocked: boolean;
+ authorities: GrantedAuthority[];
+ credentialsNonExpired: boolean;
+ enabled: boolean;
+ ownActions: Element[];
+ ownSepas: Element[];
+ ownSources: Element[];
+ password: string;
+ principalId: string;
+ principalName: string;
+ rev: string;
+ roles: Role[];
+ username: string;
+
+ static fromData(data: Principal, target?: Principal): Principal {
+ if (!data) {
+ return data;
+ }
+ const instance = target || new Principal();
+ instance.enabled = data.enabled;
+ instance.password = data.password;
+ instance.username = data.username;
+ instance.authorities = __getCopyArrayFn(__identity<GrantedAuthority>())(data.authorities);
+ instance.accountNonExpired = data.accountNonExpired;
+ instance.credentialsNonExpired = data.credentialsNonExpired;
+ instance.accountNonLocked = data.accountNonLocked;
+ instance.principalId = data.principalId;
+ instance.rev = data.rev;
+ instance.accountEnabled = data.accountEnabled;
+ instance.accountLocked = data.accountLocked;
+ instance.accountExpired = data.accountExpired;
+ instance.principalName = data.principalName;
+ instance.ownSources = __getCopyArrayFn(Element.fromData)(data.ownSources);
+ instance.ownSepas = __getCopyArrayFn(Element.fromData)(data.ownSepas);
+ instance.ownActions = __getCopyArrayFn(Element.fromData)(data.ownActions);
+ instance.roles = __getCopyArrayFn(__identity<Role>())(data.roles);
+ return instance;
+ }
+}
+
export class RawUserApiToken {
hashedToken: string;
rawToken: string;
@@ -141,45 +189,30 @@ export class RawUserApiToken {
}
}
-export class User {
+export class UserAccount extends Principal {
darkMode: boolean;
email: string;
fullName: string;
hideTutorial: boolean;
- ownActions: Element[];
- ownSepas: Element[];
- ownSources: Element[];
- password: string;
- preferredActions: string[];
- preferredSepas: string[];
- preferredSources: string[];
- rev: string;
- roles: Role[];
+ preferredDataProcessors: string[];
+ preferredDataSinks: string[];
+ preferredDataStreams: string[];
userApiTokens: UserApiToken[];
- userId: string;
- username: string;
- static fromData(data: User, target?: User): User {
+ static fromData(data: UserAccount, target?: UserAccount): UserAccount {
if (!data) {
return data;
}
- const instance = target || new User();
- instance.userId = data.userId;
- instance.rev = data.rev;
+ const instance = target || new UserAccount();
+ super.fromData(data, instance);
instance.email = data.email;
- instance.username = data.username;
instance.fullName = data.fullName;
- instance.password = data.password;
- instance.ownSources = __getCopyArrayFn(Element.fromData)(data.ownSources);
- instance.ownSepas = __getCopyArrayFn(Element.fromData)(data.ownSepas);
- instance.ownActions = __getCopyArrayFn(Element.fromData)(data.ownActions);
- instance.preferredSources = __getCopyArrayFn(__identity<string>())(data.preferredSources);
- instance.preferredSepas = __getCopyArrayFn(__identity<string>())(data.preferredSepas);
- instance.preferredActions = __getCopyArrayFn(__identity<string>())(data.preferredActions);
+ instance.preferredDataStreams = __getCopyArrayFn(__identity<string>())(data.preferredDataStreams);
+ instance.preferredDataProcessors = __getCopyArrayFn(__identity<string>())(data.preferredDataProcessors);
+ instance.preferredDataSinks = __getCopyArrayFn(__identity<string>())(data.preferredDataSinks);
instance.userApiTokens = __getCopyArrayFn(UserApiToken.fromData)(data.userApiTokens);
instance.hideTutorial = data.hideTutorial;
instance.darkMode = data.darkMode;
- instance.roles = __getCopyArrayFn(__identity<Role>())(data.roles);
return instance;
}
}
@@ -199,6 +232,16 @@ export class UserApiToken {
}
}
+export interface UserDetails {
+ accountNonExpired: boolean;
+ accountNonLocked: boolean;
+ authorities: GrantedAuthority[];
+ credentialsNonExpired: boolean;
+ enabled: boolean;
+ password: string;
+ username: string;
+}
+
export class UserInfo {
darkMode: boolean;
displayName: string;
diff --git a/ui/src/app/platform-services/apis/pipeline-template.service.ts b/ui/src/app/platform-services/apis/pipeline-template.service.ts
index 57fea33..1f9536b 100644
--- a/ui/src/app/platform-services/apis/pipeline-template.service.ts
+++ b/ui/src/app/platform-services/apis/pipeline-template.service.ts
@@ -18,7 +18,6 @@
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
-import { AuthStatusService } from '../../services/auth-status.service';
import {
FreeTextStaticProperty,
PipelineOperationStatus,
@@ -32,8 +31,7 @@ import { Observable } from 'rxjs';
export class PipelineTemplateService {
constructor(
- private http: HttpClient,
- private authStatusService: AuthStatusService
+ private http: HttpClient
) {
}
diff --git a/ui/src/app/profile/components/basic-profile-settings.ts b/ui/src/app/profile/components/basic-profile-settings.ts
index 5e98d6b..cb9cc33 100644
--- a/ui/src/app/profile/components/basic-profile-settings.ts
+++ b/ui/src/app/profile/components/basic-profile-settings.ts
@@ -17,7 +17,7 @@
*/
import { ProfileService } from '../profile.service';
-import { User } from '../../core-model/gen/streampipes-model-client';
+import { UserAccount } from '../../core-model/gen/streampipes-model-client';
import { Directive } from '@angular/core';
import { AppConstants } from '../../services/app.constants';
import { JwtTokenStorageService } from '../../services/jwt-token-storage.service';
@@ -25,7 +25,7 @@ import { JwtTokenStorageService } from '../../services/jwt-token-storage.service
@Directive()
export abstract class BasicProfileSettings {
- userData: User;
+ userData: UserAccount;
profileLoaded = false;
profileUpdating = false;
errorMessage: string;
diff --git a/ui/src/app/profile/profile.module.ts b/ui/src/app/profile/profile.module.ts
index f6242d5..273bf9f 100644
--- a/ui/src/app/profile/profile.module.ts
+++ b/ui/src/app/profile/profile.module.ts
@@ -28,6 +28,7 @@ import {TokenManagementSettingsComponent} from "./components/token/token-managem
import {GeneralProfileSettingsComponent} from "./components/general/general-profile-settings.component";
import {ProfileService} from "./profile.service";
import {MatDividerModule} from "@angular/material/divider";
+import { ClipboardModule } from '@angular/cdk/clipboard';
@NgModule({
imports: [
@@ -38,6 +39,7 @@ import {MatDividerModule} from "@angular/material/divider";
MatButtonModule,
CustomMaterialModule,
CommonModule,
+ ClipboardModule,
],
declarations: [
GeneralProfileSettingsComponent,
diff --git a/ui/src/app/profile/profile.service.ts b/ui/src/app/profile/profile.service.ts
index d77ec18..262e89c 100644
--- a/ui/src/app/profile/profile.service.ts
+++ b/ui/src/app/profile/profile.service.ts
@@ -19,7 +19,7 @@
import { Injectable } from '@angular/core';
import { PlatformServicesCommons } from '../platform-services/apis/commons.service';
import { HttpClient } from '@angular/common/http';
-import { RawUserApiToken, User } from '../core-model/gen/streampipes-model-client';
+import { RawUserApiToken, UserAccount } from '../core-model/gen/streampipes-model-client';
import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';
import { Message } from '../core-model/gen/streampipes-model';
@@ -32,13 +32,13 @@ export class ProfileService {
}
- getUserProfile(): Observable<User> {
+ getUserProfile(): Observable<UserAccount> {
return this.http.get(this.profilePath).pipe(map(response => {
- return User.fromData(response as any);
+ return UserAccount.fromData(response as any);
}));
}
- updateUserProfile(userData: User): Observable<Message> {
+ updateUserProfile(userData: UserAccount): Observable<Message> {
return this.http.put(this.profilePath, userData).pipe(map(response => {
return Message.fromData(response as any);
}));