Procházet zdrojové kódy

AMBARI-5953 - Views: instancedata should be ambari user scoped

tbeerbower před 11 roky
rodič
revize
31b7da9983

+ 75 - 1
ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ViewInstanceDataEntity.java

@@ -50,6 +50,13 @@ public class ViewInstanceDataEntity {
   @Column(name = "name", nullable = false, insertable = true, updatable = false)
   private String name;
 
+  /**
+   * The user.
+   */
+  @Id
+  @Column(name = "user_name", nullable = false, insertable = true, updatable = false)
+  private String user;
+
   /**
    * The property value.
    */
@@ -64,43 +71,110 @@ public class ViewInstanceDataEntity {
   })
   private ViewInstanceEntity viewInstance;
 
-
+  /**
+   * Get the view name.
+   *
+   * @return the view name
+   */
   public String getViewName() {
     return viewName;
   }
 
+  /**
+   * Set the view name.
+   *
+   * @param viewName  the view name
+   */
   public void setViewName(String viewName) {
     this.viewName = viewName;
   }
 
+  /**
+   * Get the instance name.
+   *
+   * @return the instance name
+   */
   public String getViewInstanceName() {
     return viewInstanceName;
   }
 
+  /**
+   * Set the instance name.
+   *
+   * @param viewInstanceName  the instance name
+   */
   public void setViewInstanceName(String viewInstanceName) {
     this.viewInstanceName = viewInstanceName;
   }
 
+  /**
+   * Get the data key.
+   *
+   * @return the data key
+   */
   public String getName() {
     return name;
   }
 
+  /**
+   * Set the data key.
+   *
+   * @param name  the data key
+   */
   public void setName(String name) {
     this.name = name;
   }
 
+  /**
+   * Get the user.
+   *
+   * @return the user
+   */
+  public String getUser() {
+    return user;
+  }
+
+  /**
+   * Set the user.
+   *
+   * @param user  the user
+   */
+  public void setUser(String user) {
+    this.user = user;
+  }
+
+  /**
+   * Get the data value.
+   *
+   * @return the data value
+   */
   public String getValue() {
     return value;
   }
 
+  /**
+   * Set the data value.
+   *
+   * @param value  the data value
+   */
   public void setValue(String value) {
     this.value = value;
   }
 
+  /**
+   * Get the view instance.
+   *
+   * @return  the view instance
+   */
   public ViewInstanceEntity getViewInstanceEntity() {
     return viewInstance;
   }
 
+  /**
+   * Set the view instance
+   *
+   * @param viewInstance  the view instance
+   */
   public void setViewInstanceEntity(ViewInstanceEntity viewInstance) {
     this.viewInstance = viewInstance;
   }

+ 38 - 4
ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ViewInstanceDataEntityPK.java

@@ -38,6 +38,10 @@ public class ViewInstanceDataEntityPK {
   @Column(name = "name", nullable = false, insertable = true, updatable = false, length = 100)
   private String name;
 
+  @Id
+  @Column(name = "user_name", nullable = false, insertable = true, updatable = false, length = 100)
+  private String user;
+
   /**
    * Get the name of the associated view.
    *
@@ -56,16 +60,26 @@ public class ViewInstanceDataEntityPK {
     this.viewName = viewName;
   }
 
+  /**
+   * Get the view instance name.
+   *
+   * @return the view instance name
+   */
   public String getViewInstanceName() {
     return viewInstanceName;
   }
 
+  /**
+   * Set the view instance name.
+   *
+   * @param viewInstanceName  the view instance name
+   */
   public void setViewInstanceName(String viewInstanceName) {
     this.viewInstanceName = viewInstanceName;
   }
 
   /**
-   * Get the name of the host group.
+   * Get the name of the data entry.
    *
    * @return host group name
    */
@@ -74,7 +88,7 @@ public class ViewInstanceDataEntityPK {
   }
 
   /**
-   * Set the name of the host group.
+   * Set the name of the data entry.
    *
    * @param name  host group name
    */
@@ -82,6 +96,24 @@ public class ViewInstanceDataEntityPK {
     this.name = name;
   }
 
+  /**
+   * Get the associated user.
+   *
+   * @return the user
+   */
+  public String getUser() {
+    return user;
+  }
+
+  /**
+   * Set the user.
+   *
+   * @param user  the user
+   */
+  public void setUser(String user) {
+    this.user = user;
+  }
+
   @Override
   public boolean equals(Object o) {
     if (this == o) return true;
@@ -91,11 +123,13 @@ public class ViewInstanceDataEntityPK {
 
     return this.viewName.equals(that.viewName) &&
         this.viewInstanceName.equals(that.viewInstanceName) &&
-        this.name.equals(that.name);
+        this.name.equals(that.name) &&
+        this.user.equals(that.user);
   }
 
   @Override
   public int hashCode() {
-    return 31 * viewName.hashCode() + viewInstanceName.hashCode() + name.hashCode();
+    return 31 * viewName.hashCode() + viewInstanceName.hashCode() +
+        name.hashCode() + user.hashCode();
   }
 }

+ 71 - 4
ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ViewInstanceEntity.java

@@ -23,7 +23,10 @@ import org.apache.ambari.server.view.configuration.InstanceConfig;
 import org.apache.ambari.view.ResourceProvider;
 import org.apache.ambari.view.ViewDefinition;
 import org.apache.ambari.view.ViewInstanceDefinition;
-import org.apache.ambari.view.events.Listener;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.context.SecurityContext;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.security.core.userdetails.UserDetails;
 
 import javax.persistence.CascadeType;
 import javax.persistence.Column;
@@ -111,6 +114,12 @@ public class ViewInstanceEntity implements ViewInstanceDefinition {
   @Transient
   private final Map<String, Object> services = new HashMap<String, Object>();
 
+  /**
+   * Helper class.
+   */
+  @Transient
+  private UserNameProvider userNameProvider = new UserNameProvider();
+
 
   // ----- Constructors ------------------------------------------------------
 
@@ -171,8 +180,12 @@ public class ViewInstanceEntity implements ViewInstanceDefinition {
   public Map<String, String> getInstanceDataMap() {
     Map<String, String> applicationData = new HashMap<String, String>();
 
+    String user = getCurrentUserName();
+
     for (ViewInstanceDataEntity viewInstanceDataEntity : data) {
-      applicationData.put(viewInstanceDataEntity.getName(), viewInstanceDataEntity.getValue());
+      if (viewInstanceDataEntity.getUser().equals(user)) {
+        applicationData.put(viewInstanceDataEntity.getName(), viewInstanceDataEntity.getValue());
+      }
     }
     return applicationData;
   }
@@ -227,7 +240,7 @@ public class ViewInstanceEntity implements ViewInstanceDefinition {
    * @param value  the property value
    */
   public void putProperty(String key, String value) {
-    removeInstanceData(key);
+    removeProperty(key);
     ViewInstancePropertyEntity viewInstancePropertyEntity = new ViewInstancePropertyEntity();
     viewInstancePropertyEntity.setViewName(viewName);
     viewInstancePropertyEntity.setViewInstanceName(name);
@@ -322,6 +335,7 @@ public class ViewInstanceEntity implements ViewInstanceDefinition {
     viewInstanceDataEntity.setViewName(viewName);
     viewInstanceDataEntity.setViewInstanceName(name);
     viewInstanceDataEntity.setName(key);
+    viewInstanceDataEntity.setUser(getCurrentUserName());
     viewInstanceDataEntity.setValue(value);
     viewInstanceDataEntity.setViewInstanceEntity(this);
     data.add(viewInstanceDataEntity);
@@ -347,8 +361,11 @@ public class ViewInstanceEntity implements ViewInstanceDefinition {
    * @return the instance data entity associated with the given key
    */
   public ViewInstanceDataEntity getInstanceData(String key) {
+    String user = getCurrentUserName();
+
     for (ViewInstanceDataEntity viewInstanceDataEntity : data) {
-      if (viewInstanceDataEntity.getName().equals(key)) {
+      if (viewInstanceDataEntity.getName().equals(key) &&
+          viewInstanceDataEntity.getUser().equals(user)) {
         return viewInstanceDataEntity;
       }
     }
@@ -456,4 +473,54 @@ public class ViewInstanceEntity implements ViewInstanceDefinition {
   public static String getContextPath(String viewName, String version, String viewInstanceName) {
     return VIEWS_CONTEXT_PATH_PREFIX + viewName + "/" + version + "/" + viewInstanceName;
   }
+
+  /**
+   * Get the current user name.
+   *
+   * @return the current user name; empty String if user is not known
+   */
+  public String getUsername() {
+    return userNameProvider.getUsername();
+  }
+
+  // ----- helper methods ----------------------------------------------------
+
+  // get the current user name
+  private String getCurrentUserName() {
+    String currentUserName = getUsername();
+
+    return currentUserName == null || currentUserName.length() == 0 ?
+        " " : currentUserName;
+  }
+
+  /**
+   * Set the user name provider helper.
+   *
+   * @param userNameProvider  the helper
+   */
+  protected void setUserNameProvider(UserNameProvider userNameProvider) {
+    this.userNameProvider = userNameProvider;
+  }
+
+
+  // ----- inner class : UserNameProvider ----------------------------------
+
+  /**
+   * User name provider helper class.
+   */
+  protected static class UserNameProvider {
+    public String getUsername() {
+      SecurityContext ctx = SecurityContextHolder.getContext();
+      Authentication authentication = ctx == null ? null : ctx.getAuthentication();
+      Object principal = authentication == null ? null : authentication.getPrincipal();
+
+      String username;
+      if (principal instanceof UserDetails) {
+        username = ((UserDetails)principal).getUsername();
+      } else {
+        username = principal == null ? "" :principal.toString();
+      }
+      return username;
+    }
+  }
 }

+ 6 - 0
ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog161.java

@@ -27,6 +27,7 @@ import javax.persistence.TypedQuery;
 
 import org.apache.ambari.server.AmbariException;
 import org.apache.ambari.server.configuration.Configuration;
+import org.apache.ambari.server.orm.DBAccessor;
 import org.apache.ambari.server.orm.DBAccessor.DBColumnInfo;
 import org.apache.ambari.server.orm.entities.ClusterEntity;
 import org.apache.ambari.server.state.State;
@@ -73,6 +74,11 @@ public class UpgradeCatalog161 extends AbstractUpgradeCatalog {
 
     dbAccessor.createTable("requestoperationlevel", columns, "operation_level_id");
 
+    //=========================================================================
+    // Add columns
+    dbAccessor.addColumn("viewinstancedata",
+        new DBAccessor.DBColumnInfo("user_name", String.class, 255, " ", false));
+
     // ========================================================================
     // Add constraints
     dbAccessor.addFKConstraint("requestoperationlevel", "FK_req_op_level_req_id",

+ 1 - 15
ambari-server/src/main/java/org/apache/ambari/server/view/ViewContextImpl.java

@@ -35,10 +35,6 @@ import org.apache.ambari.view.ViewDefinition;
 import org.apache.ambari.view.ViewInstanceDefinition;
 import org.apache.ambari.view.events.Event;
 import org.apache.ambari.view.events.Listener;
-import org.springframework.security.core.Authentication;
-import org.springframework.security.core.context.SecurityContext;
-import org.springframework.security.core.context.SecurityContextHolder;
-import org.springframework.security.core.userdetails.UserDetails;
 
 import java.io.IOException;
 import java.io.InputStream;
@@ -175,17 +171,7 @@ public class ViewContextImpl implements ViewContext, ViewController {
 
   @Override
   public String getUsername() {
-    SecurityContext ctx = SecurityContextHolder.getContext();
-    Authentication authentication = ctx == null ? null : ctx.getAuthentication();
-    Object principal = authentication == null ? null : authentication.getPrincipal();
-
-    String username;
-    if (principal instanceof UserDetails) {
-      username = ((UserDetails)principal).getUsername();
-    } else {
-      username = principal == null ? "" :principal.toString();
-    }
-    return username;
+    return viewInstanceEntity.getUsername();
   }
 
   @Override

+ 1 - 1
ambari-server/src/main/resources/Ambari-DDL-MySQL-CREATE.sql

@@ -63,7 +63,7 @@ CREATE TABLE hostgroup_component (blueprint_name VARCHAR(255) NOT NULL, hostgrou
 CREATE TABLE blueprint_configuration (blueprint_name VARCHAR(255) NOT NULL, type_name VARCHAR(255) NOT NULL, config_data VARCHAR(32000) NOT NULL , PRIMARY KEY(blueprint_name, type_name));
 CREATE TABLE hostgroup_configuration (blueprint_name VARCHAR(255) NOT NULL, hostgroup_name VARCHAR(255) NOT NULL, type_name VARCHAR(255) NOT NULL, config_data TEXT NOT NULL, PRIMARY KEY(blueprint_name, hostgroup_name, type_name));
 CREATE TABLE viewmain (view_name VARCHAR(255) NOT NULL, label VARCHAR(255), version VARCHAR(255), archive VARCHAR(255), PRIMARY KEY(view_name));
-CREATE TABLE viewinstancedata (view_name VARCHAR(255) NOT NULL, view_instance_name VARCHAR(255) NOT NULL, name VARCHAR(255) NOT NULL, value VARCHAR(2000) NOT NULL, PRIMARY KEY(view_name, view_instance_name, name));
+CREATE TABLE viewinstancedata (view_name VARCHAR(255) NOT NULL, view_instance_name VARCHAR(255) NOT NULL, name VARCHAR(255) NOT NULL, user_name VARCHAR(255) NOT NULL, value VARCHAR(2000) NOT NULL, PRIMARY KEY(view_name, view_instance_name, name, user_name));
 CREATE TABLE viewinstance (view_name VARCHAR(255) NOT NULL, name VARCHAR(255) NOT NULL, PRIMARY KEY(view_name, name));
 CREATE TABLE viewinstanceproperty (view_name VARCHAR(255) NOT NULL, view_instance_name VARCHAR(255) NOT NULL, name VARCHAR(255) NOT NULL, value VARCHAR(2000) NOT NULL, PRIMARY KEY(view_name, view_instance_name, name));
 CREATE TABLE viewparameter (view_name VARCHAR(255) NOT NULL, name VARCHAR(255) NOT NULL, description VARCHAR(255), required CHAR(1), PRIMARY KEY(view_name, name));

+ 1 - 1
ambari-server/src/main/resources/Ambari-DDL-Oracle-CREATE.sql

@@ -53,7 +53,7 @@ CREATE TABLE hostgroup_component (blueprint_name VARCHAR2(255) NOT NULL, hostgro
 CREATE TABLE blueprint_configuration (blueprint_name VARCHAR2(255) NOT NULL, type_name VARCHAR2(255) NOT NULL, config_data CLOB NOT NULL , PRIMARY KEY(blueprint_name, type_name));
 CREATE TABLE hostgroup_configuration (blueprint_name VARCHAR2(255) NOT NULL, hostgroup_name VARCHAR2(255) NOT NULL, type_name VARCHAR2(255) NOT NULL, config_data CLOB NOT NULL, PRIMARY KEY(blueprint_name, hostgroup_name, type_name));
 CREATE TABLE viewmain (view_name VARCHAR(255) NOT NULL, label VARCHAR(255), version VARCHAR(255), archive VARCHAR(255), PRIMARY KEY(view_name));
-CREATE TABLE viewinstancedata (view_name VARCHAR(255) NOT NULL, view_instance_name VARCHAR(255) NOT NULL, name VARCHAR(255) NOT NULL, value VARCHAR(2000) NOT NULL, PRIMARY KEY(view_name, view_instance_name, name));
+CREATE TABLE viewinstancedata (view_name VARCHAR(255) NOT NULL, view_instance_name VARCHAR(255) NOT NULL, name VARCHAR(255) NOT NULL, user_name VARCHAR(255) NOT NULL, value VARCHAR(2000) NOT NULL, PRIMARY KEY(view_name, view_instance_name, name, user_name));
 CREATE TABLE viewinstance (view_name VARCHAR(255) NOT NULL, name VARCHAR(255) NOT NULL, PRIMARY KEY(view_name, name));
 CREATE TABLE viewinstanceproperty (view_name VARCHAR(255) NOT NULL, view_instance_name VARCHAR(255) NOT NULL, name VARCHAR(255) NOT NULL, value VARCHAR(2000) NOT NULL, PRIMARY KEY(view_name, view_instance_name, name));
 CREATE TABLE viewparameter (view_name VARCHAR(255) NOT NULL, name VARCHAR(255) NOT NULL, description VARCHAR(255), required CHAR(1), PRIMARY KEY(view_name, name));

+ 1 - 1
ambari-server/src/main/resources/Ambari-DDL-Postgres-CREATE.sql

@@ -86,7 +86,7 @@ CREATE TABLE blueprint_configuration (blueprint_name varchar(255) NOT NULL, type
 CREATE TABLE hostgroup_configuration (blueprint_name VARCHAR(255) NOT NULL, hostgroup_name VARCHAR(255) NOT NULL, type_name VARCHAR(255) NOT NULL, config_data TEXT NOT NULL, PRIMARY KEY(blueprint_name, hostgroup_name, type_name));
 
 CREATE TABLE viewmain (view_name VARCHAR(255) NOT NULL, label VARCHAR(255), version VARCHAR(255), archive VARCHAR(255), PRIMARY KEY(view_name));
-CREATE TABLE viewinstancedata (view_name VARCHAR(255) NOT NULL, view_instance_name VARCHAR(255) NOT NULL, name VARCHAR(255) NOT NULL, value VARCHAR(2000) NOT NULL, PRIMARY KEY(view_name, view_instance_name, name));
+CREATE TABLE viewinstancedata (view_name VARCHAR(255) NOT NULL, view_instance_name VARCHAR(255) NOT NULL, name VARCHAR(255) NOT NULL, user_name VARCHAR(255) NOT NULL, value VARCHAR(2000) NOT NULL, PRIMARY KEY(view_name, view_instance_name, name, user_name));
 CREATE TABLE viewinstance (view_name VARCHAR(255) NOT NULL, name VARCHAR(255) NOT NULL, PRIMARY KEY(view_name, name));
 CREATE TABLE viewinstanceproperty (view_name VARCHAR(255) NOT NULL, view_instance_name VARCHAR(255) NOT NULL, name VARCHAR(255) NOT NULL, value VARCHAR(2000) NOT NULL, PRIMARY KEY(view_name, view_instance_name, name));
 CREATE TABLE viewparameter (view_name VARCHAR(255) NOT NULL, name VARCHAR(255) NOT NULL, description VARCHAR(255), required CHAR(1), PRIMARY KEY(view_name, name));

+ 1 - 1
ambari-server/src/main/resources/Ambari-DDL-Postgres-EMBEDDED-CREATE.sql

@@ -133,7 +133,7 @@ GRANT ALL PRIVILEGES ON TABLE ambari.blueprint_configuration TO :username;
 GRANT ALL PRIVILEGES ON TABLE ambari.hostgroup_configuration TO :username;
 
 CREATE TABLE ambari.viewmain (view_name VARCHAR(255) NOT NULL, label VARCHAR(255), version VARCHAR(255), archive VARCHAR(255), PRIMARY KEY(view_name));
-CREATE TABLE ambari.viewinstancedata (view_name VARCHAR(255) NOT NULL, view_instance_name VARCHAR(255) NOT NULL, name VARCHAR(255) NOT NULL, value VARCHAR(2000) NOT NULL, PRIMARY KEY(view_name, view_instance_name, name));
+CREATE TABLE ambari.viewinstancedata (view_name VARCHAR(255) NOT NULL, view_instance_name VARCHAR(255) NOT NULL, name VARCHAR(255) NOT NULL, user_name VARCHAR(255) NOT NULL, value VARCHAR(2000) NOT NULL, PRIMARY KEY(view_name, view_instance_name, name, user_name));
 CREATE TABLE ambari.viewinstance (view_name VARCHAR(255) NOT NULL, name VARCHAR(255) NOT NULL, PRIMARY KEY(view_name, name));
 CREATE TABLE ambari.viewinstanceproperty (view_name VARCHAR(255) NOT NULL, view_instance_name VARCHAR(255) NOT NULL, name VARCHAR(255) NOT NULL, value VARCHAR(2000) NOT NULL, PRIMARY KEY(view_name, view_instance_name, name));
 CREATE TABLE ambari.viewparameter (view_name VARCHAR(255) NOT NULL, name VARCHAR(255) NOT NULL, description VARCHAR(255), required CHAR(1), PRIMARY KEY(view_name, name));

+ 89 - 0
ambari-server/src/test/java/org/apache/ambari/server/orm/entities/ViewInstanceEntityTest.java

@@ -113,9 +113,98 @@ public class ViewInstanceEntityTest {
         viewInstanceDefinition.getContextPath());
   }
 
+  @Test
+  public void testInstanceData() throws Exception {
+    TestUserNameProvider userNameProvider = new TestUserNameProvider("user1");
+
+    ViewInstanceEntity viewInstanceDefinition = getViewInstanceEntity(userNameProvider);
+
+    viewInstanceDefinition.putInstanceData("key1", "foo");
+
+    ViewInstanceDataEntity dataEntity = viewInstanceDefinition.getInstanceData("key1");
+
+    Assert.assertNotNull(dataEntity);
+
+    Assert.assertEquals("foo", dataEntity.getValue());
+    Assert.assertEquals("user1", dataEntity.getUser());
+
+    viewInstanceDefinition.putInstanceData("key2", "bar");
+    viewInstanceDefinition.putInstanceData("key3", "baz");
+    viewInstanceDefinition.putInstanceData("key4", "monkey");
+    viewInstanceDefinition.putInstanceData("key5", "runner");
+
+    Map<String, String> dataMap = viewInstanceDefinition.getInstanceDataMap();
+
+    Assert.assertEquals(5, dataMap.size());
+
+    Assert.assertEquals("foo", dataMap.get("key1"));
+    Assert.assertEquals("bar", dataMap.get("key2"));
+    Assert.assertEquals("baz", dataMap.get("key3"));
+    Assert.assertEquals("monkey", dataMap.get("key4"));
+    Assert.assertEquals("runner", dataMap.get("key5"));
+
+    viewInstanceDefinition.removeInstanceData("key3");
+    dataMap = viewInstanceDefinition.getInstanceDataMap();
+    Assert.assertEquals(4, dataMap.size());
+    Assert.assertFalse(dataMap.containsKey("key3"));
+
+    userNameProvider.setUser("user2");
+
+    dataMap = viewInstanceDefinition.getInstanceDataMap();
+    Assert.assertTrue(dataMap.isEmpty());
+
+    viewInstanceDefinition.putInstanceData("key1", "aaa");
+    viewInstanceDefinition.putInstanceData("key2", "bbb");
+    viewInstanceDefinition.putInstanceData("key3", "ccc");
+
+    dataMap = viewInstanceDefinition.getInstanceDataMap();
+
+    Assert.assertEquals(3, dataMap.size());
+
+    Assert.assertEquals("aaa", dataMap.get("key1"));
+    Assert.assertEquals("bbb", dataMap.get("key2"));
+    Assert.assertEquals("ccc", dataMap.get("key3"));
+
+    userNameProvider.setUser("user1");
+
+    dataMap = viewInstanceDefinition.getInstanceDataMap();
+    Assert.assertEquals(4, dataMap.size());
+
+    Assert.assertEquals("foo", dataMap.get("key1"));
+    Assert.assertEquals("bar", dataMap.get("key2"));
+    Assert.assertNull(dataMap.get("key3"));
+    Assert.assertEquals("monkey", dataMap.get("key4"));
+    Assert.assertEquals("runner", dataMap.get("key5"));
+  }
+
   public static ViewInstanceEntity getViewInstanceEntity() throws Exception {
     InstanceConfig instanceConfig = InstanceConfigTest.getInstanceConfigs().get(0);
     ViewEntity viewDefinition = ViewEntityTest.getViewEntity();
     return new ViewInstanceEntity(viewDefinition, instanceConfig);
   }
+
+  public static ViewInstanceEntity getViewInstanceEntity(ViewInstanceEntity.UserNameProvider userNameProvider)
+      throws Exception {
+    ViewInstanceEntity viewInstanceEntity = getViewInstanceEntity();
+    viewInstanceEntity.setUserNameProvider(userNameProvider);
+    return viewInstanceEntity;
+  }
+
+  protected static class TestUserNameProvider extends ViewInstanceEntity.UserNameProvider {
+
+    private String user;
+
+    public TestUserNameProvider(String user) {
+      this.user = user;
+    }
+
+    public void setUser(String user) {
+      this.user = user;
+    }
+
+    @Override
+    public String getUsername() {
+      return user;
+    }
+  }
 }