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 2022/11/30 22:07:11 UTC

[streampipes] branch SP-822 created (now 41b64ca56)

This is an automated email from the ASF dual-hosted git repository.

riemer pushed a change to branch SP-822
in repository https://gitbox.apache.org/repos/asf/streampipes.git


      at 41b64ca56 Ignore case when fetching users from database (#822)

This branch includes the following new commits:

     new 41b64ca56 Ignore case when fetching users from database (#822)

The 1 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.



[streampipes] 01/01: Ignore case when fetching users from database (#822)

Posted by ri...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

riemer pushed a commit to branch SP-822
in repository https://gitbox.apache.org/repos/asf/streampipes.git

commit 41b64ca56924b47ac4598a253ca4a55d605f8eac
Author: Dominik Riemer <do...@gmail.com>
AuthorDate: Wed Nov 30 23:06:42 2022 +0100

    Ignore case when fetching users from database (#822)
---
 .../backend/migrations/AvailableMigrations.java    |  4 +-
 .../v090/UpdateUsernameViewMigration.java          | 61 +++++++++++++++++
 .../manager/setup/CouchDbInstallationStep.java     | 53 ++-------------
 .../manager/setup/design/DesignDocumentUtils.java  | 24 +++----
 .../manager/setup/design/UserDesignDocument.java   | 79 ++++++++++++++++++++++
 .../apache/streampipes/rest/impl/UserResource.java |  5 +-
 .../storage/couchdb/impl/UserStorage.java          |  4 +-
 7 files changed, 162 insertions(+), 68 deletions(-)

diff --git a/streampipes-backend/src/main/java/org/apache/streampipes/backend/migrations/AvailableMigrations.java b/streampipes-backend/src/main/java/org/apache/streampipes/backend/migrations/AvailableMigrations.java
index 5b26d793e..8d8a8b085 100644
--- a/streampipes-backend/src/main/java/org/apache/streampipes/backend/migrations/AvailableMigrations.java
+++ b/streampipes-backend/src/main/java/org/apache/streampipes/backend/migrations/AvailableMigrations.java
@@ -22,6 +22,7 @@ package org.apache.streampipes.backend.migrations;
 import org.apache.streampipes.backend.migrations.v070.CreateAssetLinkTypeMigration;
 import org.apache.streampipes.backend.migrations.v070.CreateDefaultAssetMigration;
 import org.apache.streampipes.backend.migrations.v070.CreateFileAssetTypeMigration;
+import org.apache.streampipes.backend.migrations.v090.UpdateUsernameViewMigration;
 
 import java.util.Arrays;
 import java.util.List;
@@ -32,7 +33,8 @@ public class AvailableMigrations {
     return Arrays.asList(
       new CreateAssetLinkTypeMigration(),
       new CreateDefaultAssetMigration(),
-      new CreateFileAssetTypeMigration()
+      new CreateFileAssetTypeMigration(),
+      new UpdateUsernameViewMigration()
     );
   }
 }
diff --git a/streampipes-backend/src/main/java/org/apache/streampipes/backend/migrations/v090/UpdateUsernameViewMigration.java b/streampipes-backend/src/main/java/org/apache/streampipes/backend/migrations/v090/UpdateUsernameViewMigration.java
new file mode 100644
index 000000000..3e6c6bf5c
--- /dev/null
+++ b/streampipes-backend/src/main/java/org/apache/streampipes/backend/migrations/v090/UpdateUsernameViewMigration.java
@@ -0,0 +1,61 @@
+/*
+ * 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.backend.migrations.v090;
+
+import org.apache.streampipes.backend.migrations.Migration;
+import org.apache.streampipes.manager.setup.design.UserDesignDocument;
+import org.apache.streampipes.storage.couchdb.utils.Utils;
+import org.lightcouch.Response;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class UpdateUsernameViewMigration implements Migration {
+
+  private static final Logger LOG = LoggerFactory.getLogger(UpdateUsernameViewMigration.class);
+  private static final String DOC_NAME = "_design/users";
+
+  @Override
+  public boolean shouldExecute() {
+    var designDoc = Utils.getCouchDbUserClient().design().getFromDb(DOC_NAME);
+    var viewKey = UserDesignDocument.USERNAME_KEY;
+    var viewMapFunction = UserDesignDocument.USERNAME_MAP_FUNCTION;
+    var views = designDoc.getViews();
+
+    if (views.containsKey(viewKey)) {
+      return !(views.get(viewKey).getMap().equals(viewMapFunction));
+    } else {
+      return true;
+    }
+  }
+
+  @Override
+  public void executeMigration() {
+    var userDocument = new UserDesignDocument().make();
+    Response resp = Utils.getCouchDbUserClient().design().synchronizeWithDb(userDocument);
+
+    if (resp.getError() != null) {
+      LOG.warn("Could not update user design document with reason {}", resp.getReason());
+    }
+  }
+
+  @Override
+  public String getDescription() {
+    return "Lowercase all keys in user database design document";
+  }
+}
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 f204ab247..50646f4bf 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
@@ -18,6 +18,7 @@
 
 package org.apache.streampipes.manager.setup;
 
+import org.apache.streampipes.manager.setup.design.UserDesignDocument;
 import org.apache.streampipes.manager.setup.tasks.CreateAssetLinkTypeTask;
 import org.apache.streampipes.manager.setup.tasks.CreateDefaultAssetTask;
 import org.apache.streampipes.model.client.endpoint.ExtensionsServiceEndpoint;
@@ -29,6 +30,8 @@ import org.lightcouch.Response;
 
 import java.util.*;
 
+import static org.apache.streampipes.manager.setup.design.DesignDocumentUtils.prepareDocument;
+
 public class CouchDbInstallationStep extends InstallationStep {
 
   private static final String initRdfEndpointHost = "http://localhost:";
@@ -173,48 +176,7 @@ public class CouchDbInstallationStep extends InstallationStep {
 
   private void addUserView() {
     try {
-      DesignDocument userDocument = prepareDocument("_design/users");
-      Map<String, MapReduce> views = new HashMap<>();
-
-      MapReduce passwordFunction = new MapReduce();
-      passwordFunction.setMap("function(doc) { if(doc.properties.username && doc.properties.principalType === 'USER_ACCOUNT' && doc.properties.password) { emit(doc.properties.username, doc.properties.password); } }");
-
-      MapReduce usernameFunction = new MapReduce();
-      usernameFunction.setMap("function(doc) { if(doc.properties.username) { emit(doc.properties.username, doc); } }");
-
-      MapReduce permissionFunction = new MapReduce();
-      permissionFunction.setMap("function(doc) { if(doc.$type === 'permission') { emit(doc._id, doc); } }");
-
-      MapReduce groupFunction = new MapReduce();
-      groupFunction.setMap("function(doc) { if(doc.$type === 'group') { emit(doc._id, doc); } }");
-
-      MapReduce tokenFunction = new MapReduce();
-      tokenFunction.setMap("function(doc) { if (doc.properties.userApiTokens) { doc.properties.userApiTokens.forEach(function(token) { emit(token.properties.hashedToken, doc.properties.email); });}}");
-
-      MapReduce userPermissionFunction = new MapReduce();
-      userPermissionFunction.setMap("function(doc) { if (doc.$type === 'permission') {emit(doc.ownerSid, doc); for(var i = 0; i < doc.grantedAuthorities.length; i++) {emit(doc.grantedAuthorities[i].sid,doc)}}}");
-
-      MapReduce objectPermissionFunction = new MapReduce();
-      objectPermissionFunction.setMap("function(doc) { if (doc.$type === 'permission') {emit(doc.objectInstanceId, doc);}}");
-
-      MapReduce userActivationFunction = new MapReduce();
-      userActivationFunction.setMap("function(doc) { if (doc.$type === 'user-activation') {emit(doc._id, doc);}}");
-
-      MapReduce passwordRecoveryFunction = new MapReduce();
-      passwordRecoveryFunction.setMap("function(doc) { if (doc.$type === 'password-recovery') {emit(doc._id, doc);}}");
-
-
-      views.put("password", passwordFunction);
-      views.put("username", usernameFunction);
-      views.put("groups", groupFunction);
-      views.put("permissions", permissionFunction);
-      views.put("token", tokenFunction);
-      views.put("userpermissions", userPermissionFunction);
-      views.put("objectpermissions", objectPermissionFunction);
-      views.put("user-activation", userActivationFunction);
-      views.put("password-recovery", passwordRecoveryFunction);
-
-      userDocument.setViews(views);
+      var userDocument = new UserDesignDocument().make();
       Response resp = Utils.getCouchDbUserClient().design().synchronizeWithDb(userDocument);
 
       if (resp.getError() != null) {
@@ -274,10 +236,5 @@ public class CouchDbInstallationStep extends InstallationStep {
     }
   }
 
-  private DesignDocument prepareDocument(String id) {
-    DesignDocument doc = new DesignDocument();
-    doc.setLanguage("javascript");
-    doc.setId(id);
-    return doc;
-  }
+
 }
diff --git a/streampipes-backend/src/main/java/org/apache/streampipes/backend/migrations/AvailableMigrations.java b/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/setup/design/DesignDocumentUtils.java
similarity index 57%
copy from streampipes-backend/src/main/java/org/apache/streampipes/backend/migrations/AvailableMigrations.java
copy to streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/setup/design/DesignDocumentUtils.java
index 5b26d793e..45ec27fc8 100644
--- a/streampipes-backend/src/main/java/org/apache/streampipes/backend/migrations/AvailableMigrations.java
+++ b/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/setup/design/DesignDocumentUtils.java
@@ -13,26 +13,18 @@
  * 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.design;
 
-package org.apache.streampipes.backend.migrations;
-
-import org.apache.streampipes.backend.migrations.v070.CreateAssetLinkTypeMigration;
-import org.apache.streampipes.backend.migrations.v070.CreateDefaultAssetMigration;
-import org.apache.streampipes.backend.migrations.v070.CreateFileAssetTypeMigration;
-
-import java.util.Arrays;
-import java.util.List;
+import org.lightcouch.DesignDocument;
 
-public class AvailableMigrations {
+public class DesignDocumentUtils {
 
-  public List<Migration> getAvailableMigrations() {
-    return Arrays.asList(
-      new CreateAssetLinkTypeMigration(),
-      new CreateDefaultAssetMigration(),
-      new CreateFileAssetTypeMigration()
-    );
+  public static 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/design/UserDesignDocument.java b/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/setup/design/UserDesignDocument.java
new file mode 100644
index 000000000..28808d263
--- /dev/null
+++ b/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/setup/design/UserDesignDocument.java
@@ -0,0 +1,79 @@
+/*
+ * 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.design;
+
+import org.lightcouch.DesignDocument;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import static org.apache.streampipes.manager.setup.design.DesignDocumentUtils.prepareDocument;
+
+public class UserDesignDocument {
+
+  public static final String USERNAME_KEY = "username";
+  public static final String USERNAME_MAP_FUNCTION =
+      "function(doc) { if(doc.properties.username) { emit(doc.properties.username.toLowerCase(), doc); } }";
+
+  public DesignDocument make() {
+    DesignDocument userDocument = prepareDocument("_design/users");
+    Map<String, DesignDocument.MapReduce> views = new HashMap<>();
+
+    DesignDocument.MapReduce passwordFunction = new DesignDocument.MapReduce();
+    passwordFunction.setMap("function(doc) { if(doc.properties.username && doc.properties.principalType === 'USER_ACCOUNT' && doc.properties.password) { emit(doc.properties.username.toLowerCase(), doc.properties.password); } }");
+
+    DesignDocument.MapReduce usernameFunction = new DesignDocument.MapReduce();
+    usernameFunction.setMap(USERNAME_MAP_FUNCTION);
+
+    DesignDocument.MapReduce permissionFunction = new DesignDocument.MapReduce();
+    permissionFunction.setMap("function(doc) { if(doc.$type === 'permission') { emit(doc._id, doc); } }");
+
+    DesignDocument.MapReduce groupFunction = new DesignDocument.MapReduce();
+    groupFunction.setMap("function(doc) { if(doc.$type === 'group') { emit(doc._id, doc); } }");
+
+    DesignDocument.MapReduce tokenFunction = new DesignDocument.MapReduce();
+    tokenFunction.setMap("function(doc) { if (doc.properties.userApiTokens) { doc.properties.userApiTokens.forEach(function(token) { emit(token.properties.hashedToken, doc.properties.email); });}}");
+
+    DesignDocument.MapReduce userPermissionFunction = new DesignDocument.MapReduce();
+    userPermissionFunction.setMap("function(doc) { if (doc.$type === 'permission') {emit(doc.ownerSid, doc); for(var i = 0; i < doc.grantedAuthorities.length; i++) {emit(doc.grantedAuthorities[i].sid,doc)}}}");
+
+    DesignDocument.MapReduce objectPermissionFunction = new DesignDocument.MapReduce();
+    objectPermissionFunction.setMap("function(doc) { if (doc.$type === 'permission') {emit(doc.objectInstanceId, doc);}}");
+
+    DesignDocument.MapReduce userActivationFunction = new DesignDocument.MapReduce();
+    userActivationFunction.setMap("function(doc) { if (doc.$type === 'user-activation') {emit(doc._id, doc);}}");
+
+    DesignDocument.MapReduce passwordRecoveryFunction = new DesignDocument.MapReduce();
+    passwordRecoveryFunction.setMap("function(doc) { if (doc.$type === 'password-recovery') {emit(doc._id, doc);}}");
+
+
+    views.put("password", passwordFunction);
+    views.put(USERNAME_KEY, usernameFunction);
+    views.put("groups", groupFunction);
+    views.put("permissions", permissionFunction);
+    views.put("token", tokenFunction);
+    views.put("userpermissions", userPermissionFunction);
+    views.put("objectpermissions", objectPermissionFunction);
+    views.put("user-activation", userActivationFunction);
+    views.put("password-recovery", passwordRecoveryFunction);
+
+    userDocument.setViews(views);
+
+    return userDocument;
+  }
+}
diff --git a/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/UserResource.java b/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/UserResource.java
index 7ee83dd18..9d82cd91c 100644
--- a/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/UserResource.java
+++ b/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/UserResource.java
@@ -208,7 +208,10 @@ public class UserResource extends AbstractAuthGuardedRestResource {
       try {
         if (PasswordUtil.validatePassword(user.getPassword(), existingUser.getPassword())) {
           existingUser.setUsername(user.getUsername());
-          if (getUserStorage().getAllUserAccounts().stream().noneMatch(u -> u.getUsername().equals(user.getUsername()))) {
+          if (getUserStorage()
+              .getAllUserAccounts()
+              .stream()
+              .noneMatch(u -> u.getUsername().equalsIgnoreCase(user.getUsername()))) {
             updateUser(existingUser, user, isAdmin(), existingUser.getPassword());
             getUserStorage().updateUser(existingUser);
             return ok();
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 3d8650fac..3f8da673a 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
@@ -68,7 +68,7 @@ public class UserStorage extends CrudViewDao implements IUserStorage {
 
   @Override
   public Principal getUser(String username) {
-    List<Principal> users = findByKey(viewName, username, Principal.class);
+    List<Principal> users = findByKey(viewName, username.toLowerCase(), Principal.class);
     if (users.size() != 1) {
       LOG.error("None or to many users with matching username");
     }
@@ -101,7 +101,7 @@ public class UserStorage extends CrudViewDao implements IUserStorage {
    */
   @Override
   public boolean checkUser(String username) {
-    List<Principal> users = findByKey(viewName, username, Principal.class);
+    List<Principal> users = findByKey(viewName, username.toLowerCase(), Principal.class);
 
     return users.size() == 1;
   }