You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@syncope.apache.org by GitBox <gi...@apache.org> on 2022/06/22 09:43:31 UTC

[GitHub] [syncope] github-code-scanning[bot] commented on a diff in pull request #355: [SYNCOPE-1682] Introducing AttrRepo entity for AttrReleasePolicy

github-code-scanning[bot] commented on code in PR #355:
URL: https://github.com/apache/syncope/pull/355#discussion_r903522152


##########
wa/bootstrap/src/main/java/org/apache/syncope/wa/bootstrap/WAPropertySourceLocator.java:
##########
@@ -471,37 +603,53 @@
         Map<String, Object> properties = new TreeMap<>();
 
         syncopeClient.getService(AuthModuleService.class).list().forEach(authModuleTO -> {
-            AuthModuleConf authConf = authModuleTO.getConf();
+            AuthModuleConf conf = authModuleTO.getConf();
             LOG.debug("Mapping auth module {} ", authModuleTO.getKey());
 
-            if (authConf instanceof LDAPAuthModuleConf) {
-                properties.putAll(mapAuthModule(authModuleTO.getKey(), (LDAPAuthModuleConf) authConf));
-            } else if (authConf instanceof StaticAuthModuleConf) {
-                properties.putAll(mapAuthModule(authModuleTO.getKey(), (StaticAuthModuleConf) authConf));
-            } else if (authConf instanceof SyncopeAuthModuleConf) {
-                properties.putAll(mapAuthModule(authModuleTO.getKey(),
-                        (SyncopeAuthModuleConf) authConf, syncopeClient.getAddress()));
-            } else if (authConf instanceof GoogleMfaAuthModuleConf) {
-                properties.putAll(mapAuthModule(authModuleTO.getKey(), (GoogleMfaAuthModuleConf) authConf));
-            } else if (authConf instanceof SimpleMfaAuthModuleConf) {
-                properties.putAll(mapAuthModule(authModuleTO.getKey(), (SimpleMfaAuthModuleConf) authConf));
-            } else if (authConf instanceof DuoMfaAuthModuleConf) {
-                properties.putAll(mapAuthModule(authModuleTO.getKey(), (DuoMfaAuthModuleConf) authConf));
-            } else if (authConf instanceof JaasAuthModuleConf) {
-                properties.putAll(mapAuthModule(authModuleTO.getKey(), (JaasAuthModuleConf) authConf));
-            } else if (authConf instanceof JDBCAuthModuleConf) {
-                properties.putAll(mapAuthModule(authModuleTO.getKey(), (JDBCAuthModuleConf) authConf));
-            } else if (authConf instanceof OIDCAuthModuleConf) {
-                properties.putAll(mapAuthModule(authModuleTO.getKey(), (OIDCAuthModuleConf) authConf));
-            } else if (authConf instanceof SAML2IdPAuthModuleConf) {
-                properties.putAll(mapAuthModule(authModuleTO.getKey(), (SAML2IdPAuthModuleConf) authConf));
-            } else if (authConf instanceof U2FAuthModuleConf) {
-                properties.putAll(mapAuthModule(authModuleTO.getKey(), (U2FAuthModuleConf) authConf));
+            if (conf instanceof StaticAuthModuleConf) {

Review Comment:
   ## Chain of 'instanceof' tests
   
   This if block performs a chain of 11 type tests - consider alternatives, e.g. polymorphism or the visitor pattern.
   
   [Show more details](https://github.com/apache/syncope/security/code-scanning/1045)



##########
common/am/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/AttrRepoService.java:
##########
@@ -0,0 +1,122 @@
+/*
+ * 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.syncope.common.rest.api.service;
+
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.enums.ParameterIn;
+import io.swagger.v3.oas.annotations.headers.Header;
+import io.swagger.v3.oas.annotations.media.Schema;
+import io.swagger.v3.oas.annotations.responses.ApiResponse;
+import io.swagger.v3.oas.annotations.responses.ApiResponses;
+import io.swagger.v3.oas.annotations.security.SecurityRequirement;
+import io.swagger.v3.oas.annotations.security.SecurityRequirements;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import java.util.List;
+import javax.validation.constraints.NotNull;
+import javax.ws.rs.Consumes;
+import javax.ws.rs.DELETE;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import org.apache.syncope.common.lib.to.AttrRepoTO;
+import org.apache.syncope.common.rest.api.RESTHeaders;
+
+/**
+ * REST operations for attribute repositories.
+ */
+@Tag(name = "AttrRepos")
+@SecurityRequirements({
+    @SecurityRequirement(name = "BasicAuthentication"),
+    @SecurityRequirement(name = "Bearer") })
+@Path("attrRepos")
+public interface AttrRepoService extends JAXRSService {

Review Comment:
   ## Constant interface anti-pattern
   
   Type AttrRepoService implements constant interface [JAXRSService](1).
   
   [Show more details](https://github.com/apache/syncope/security/code-scanning/1046)



##########
common/am/lib/src/main/java/org/apache/syncope/common/lib/policy/DefaultAttrReleasePolicyConf.java:
##########
@@ -20,13 +20,91 @@
 
 import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper;
 import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
+import java.io.Serializable;
 import java.util.ArrayList;
 import java.util.List;
+import java.util.concurrent.TimeUnit;
 
 public class DefaultAttrReleasePolicyConf implements AttrReleasePolicyConf {
 
     private static final long serialVersionUID = -1969836661359025380L;
 
+    public enum PrincipalAttrRepoMergingStrategy {
+        /**
+         * Replace attributes. Overwrites existing attribute values, if any.
+         */
+        REPLACE,
+        /**
+         * Add attributes.
+         * Retains existing attribute values if any, and ignores values from subsequent sources in the resolution chain.
+         */
+        ADD,
+        /**
+         * No merging.
+         * Doesn't merge attributes, ignores attributes from non-authentication attribute repositories.
+         */
+        NONE,
+        /**
+         * Multivalued attributes.
+         * Combines all values into a single attribute, essentially creating a multi-valued attribute.
+         */
+        MULTIVALUED;
+
+    }
+
+    public static class PrincipalAttrRepoConf implements Serializable {
+
+        private static final long serialVersionUID = 6369987956789092057L;
+
+        private PrincipalAttrRepoMergingStrategy mergingStrategy = PrincipalAttrRepoMergingStrategy.MULTIVALUED;
+
+        private boolean ignoreResolvedAttributes;
+
+        private long expiration;
+
+        private TimeUnit timeUnit = TimeUnit.HOURS;
+
+        private final List<String> attrRepos = new ArrayList<>();
+
+        public PrincipalAttrRepoMergingStrategy getMergingStrategy() {
+            return mergingStrategy;
+        }
+
+        public void setMergingStrategy(final PrincipalAttrRepoMergingStrategy mergingStrategy) {
+            this.mergingStrategy = mergingStrategy;
+        }
+
+        public boolean isIgnoreResolvedAttributes() {
+            return ignoreResolvedAttributes;
+        }
+
+        public void setIgnoreResolvedAttributes(final boolean ignoreResolvedAttributes) {
+            this.ignoreResolvedAttributes = ignoreResolvedAttributes;
+        }
+
+        public long getExpiration() {
+            return expiration;
+        }
+
+        public void setExpiration(final long expiration) {
+            this.expiration = expiration;
+        }
+
+        public TimeUnit getTimeUnit() {
+            return timeUnit;
+        }
+
+        public void setTimeUnit(final TimeUnit timeUnit) {
+            this.timeUnit = timeUnit;
+        }
+
+        @JacksonXmlElementWrapper(localName = "attrRepos")
+        @JacksonXmlProperty(localName = "attrRepo")
+        public List<String> getAttrRepos() {

Review Comment:
   ## Exposing internal representation
   
   getAttrRepos exposes the internal representation stored in field attrRepos. The value may be modified [after this call to getAttrRepos](1).
   
   [Show more details](https://github.com/apache/syncope/security/code-scanning/1050)



##########
common/am/lib/src/main/java/org/apache/syncope/common/lib/attr/JDBCAttrRepoConf.java:
##########
@@ -0,0 +1,233 @@
+/*
+ * 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.syncope.common.lib.attr;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public class JDBCAttrRepoConf implements AttrRepoConf {
+
+    private static final long serialVersionUID = -4474060002361453868L;
+
+    public enum CaseCanonicalizationMode {
+
+        LOWER,
+        UPPER,
+        NONE;
+
+    }
+
+    public enum QueryType {
+        AND,
+        OR
+
+    }
+
+    /**
+     * SQL query to execute. Example: {@code SELECT * FROM table WHERE name=?}.
+     */
+    private String sql;
+
+    /**
+     * The database dialect is a configuration setting for platform independent software (JPA, Hibernate, etc)
+     * which allows such software to translate its generic SQL statements into vendor specific DDL, DML.
+     */
+    private String dialect = "org.hibernate.dialect.H2Dialect";
+
+    /**
+     * The JDBC driver used to connect to the database.
+     */
+    private String driverClass = "org.h2.Driver";
+
+    /**
+     * The database connection URL.
+     */
+    private String url = "jdbc:h2:tcp://localhost:9092/mem:authdb;DB_CLOSE_DELAY=-1";
+
+    /**
+     * The database user.
+     * <p>
+     * The database user must have sufficient permissions to be able to handle
+     * schema changes and updates, when needed.
+     */
+    private String user = "sa";
+
+    /**
+     * The database connection password.
+     */
+    private String password = "sa";
+
+    /**
+     * Designed to work against a table where there is a mapping of one row to one user.
+     */
+    private boolean singleRow = true;
+
+    /**
+     * If the SQL should only be run if all attributes listed in the mappings exist in the query.
+     */
+    private boolean requireAllAttributes = true;
+
+    /**
+     * When constructing the final person object from the attribute repository,
+     * indicate how the username should be canonicalized.
+     */
+    private CaseCanonicalizationMode caseCanonicalization = CaseCanonicalizationMode.NONE;
+
+    /**
+     * Indicates how multiple attributes in a query should be concatenated together.
+     */
+    private QueryType queryType = QueryType.AND;
+
+    /**
+     * Used only when there is a mapping of many rows to one user.
+     * This is done using a key-value structure where the key is the
+     * name of the "attribute name" column the value is the name of the "attribute value" column.
+     */
+    private final Map<String, String> columnMappings = new HashMap<>(0);
+
+    /**
+     * Username attribute(s) to use when running the SQL query.
+     */
+    private final List<String> username = new ArrayList<>(0);
+
+    /**
+     * Map of attributes to fetch from the database.
+     * Attributes are defined using a key-value structure
+     * where CAS allows the attribute name/key to be renamed virtually
+     * to a different attribute. The key is the attribute fetched
+     * from the data source and the value is the attribute name CAS should
+     * use for virtual renames.
+     */
+    private final Map<String, String> attributes = new HashMap<>(0);
+
+    /**
+     * Collection of attributes, used to build the SQL query, that should go through
+     * a case canonicalization process defined as {@code key->value}.
+     */
+    private final List<String> caseInsensitiveQueryAttributes = new ArrayList<>(0);
+
+    /**
+     * Define a {@code Map} of query attribute names to data-layer attribute names to use when building the query.
+     * The key is always the name of the query attribute that is defined by CAS and passed internally,
+     * and the value is the database column that should map.
+     */
+    private final Map<String, String> queryAttributes = new HashMap<>(0);
+
+    public String getSql() {
+        return sql;
+    }
+
+    public void setSql(final String sql) {
+        this.sql = sql;
+    }
+
+    public String getDialect() {
+        return dialect;
+    }
+
+    public void setDialect(final String dialect) {
+        this.dialect = dialect;
+    }
+
+    public String getDriverClass() {
+        return driverClass;
+    }
+
+    public void setDriverClass(final String driverClass) {
+        this.driverClass = driverClass;
+    }
+
+    public String getUrl() {
+        return url;
+    }
+
+    public void setUrl(final String url) {
+        this.url = url;
+    }
+
+    public String getUser() {
+        return user;
+    }
+
+    public void setUser(final String user) {
+        this.user = user;
+    }
+
+    public String getPassword() {
+        return password;
+    }
+
+    public void setPassword(final String password) {
+        this.password = password;
+    }
+
+    public boolean isSingleRow() {
+        return singleRow;
+    }
+
+    public void setSingleRow(final boolean singleRow) {
+        this.singleRow = singleRow;
+    }
+
+    public boolean isRequireAllAttributes() {
+        return requireAllAttributes;
+    }
+
+    public void setRequireAllAttributes(final boolean requireAllAttributes) {
+        this.requireAllAttributes = requireAllAttributes;
+    }
+
+    public CaseCanonicalizationMode getCaseCanonicalization() {
+        return caseCanonicalization;
+    }
+
+    public void setCaseCanonicalization(final CaseCanonicalizationMode caseCanonicalization) {
+        this.caseCanonicalization = caseCanonicalization;
+    }
+
+    public QueryType getQueryType() {
+        return queryType;
+    }
+
+    public void setQueryType(final QueryType queryType) {
+        this.queryType = queryType;
+    }
+
+    public Map<String, String> getColumnMappings() {
+        return columnMappings;
+    }
+
+    public List<String> getUsername() {

Review Comment:
   ## Exposing internal representation
   
   getUsername exposes the internal representation stored in field username. The value may be modified [after this call to getUsername](1).
   
   [Show more details](https://github.com/apache/syncope/security/code-scanning/1048)



##########
common/am/lib/src/main/java/org/apache/syncope/common/lib/to/AttrRepoTO.java:
##########
@@ -0,0 +1,121 @@
+/*
+ * 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.syncope.common.lib.to;
+
+import java.util.ArrayList;
+import java.util.List;
+import javax.ws.rs.PathParam;
+import org.apache.commons.lang3.builder.EqualsBuilder;
+import org.apache.commons.lang3.builder.HashCodeBuilder;
+import org.apache.syncope.common.lib.attr.AttrRepoConf;
+import org.apache.syncope.common.lib.types.AttrRepoState;
+
+public class AttrRepoTO implements EntityTO {
+
+    private static final long serialVersionUID = -7490425997956703057L;
+
+    private String key;
+
+    private String description;
+
+    private AttrRepoState state;
+
+    private int order;
+
+    private final List<ItemTO> items = new ArrayList<>();
+
+    private AttrRepoConf conf;
+
+    @Override
+    public String getKey() {
+        return key;
+    }
+
+    @PathParam("key")
+    @Override
+    public void setKey(final String key) {
+        this.key = key;
+    }
+
+    public String getDescription() {
+        return description;
+    }
+
+    public void setDescription(final String description) {
+        this.description = description;
+    }
+
+    public AttrRepoState getState() {
+        return state;
+    }
+
+    public void setState(final AttrRepoState state) {
+        this.state = state;
+    }
+
+    public int getOrder() {
+        return order;
+    }
+
+    public void setOrder(final int order) {
+        this.order = order;
+    }
+
+    public List<ItemTO> getItems() {

Review Comment:
   ## Exposing internal representation
   
   getItems exposes the internal representation stored in field items. The value may be modified [after this call to getItems](1).
   getItems exposes the internal representation stored in field items. The value may be modified [after this call to getItems](2).
   getItems exposes the internal representation stored in field items. The value may be modified [after this call to getItems](3).
   
   [Show more details](https://github.com/apache/syncope/security/code-scanning/1052)



##########
common/am/lib/src/main/java/org/apache/syncope/common/lib/attr/JDBCAttrRepoConf.java:
##########
@@ -0,0 +1,233 @@
+/*
+ * 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.syncope.common.lib.attr;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public class JDBCAttrRepoConf implements AttrRepoConf {
+
+    private static final long serialVersionUID = -4474060002361453868L;
+
+    public enum CaseCanonicalizationMode {
+
+        LOWER,
+        UPPER,
+        NONE;
+
+    }
+
+    public enum QueryType {
+        AND,
+        OR
+
+    }
+
+    /**
+     * SQL query to execute. Example: {@code SELECT * FROM table WHERE name=?}.
+     */
+    private String sql;
+
+    /**
+     * The database dialect is a configuration setting for platform independent software (JPA, Hibernate, etc)
+     * which allows such software to translate its generic SQL statements into vendor specific DDL, DML.
+     */
+    private String dialect = "org.hibernate.dialect.H2Dialect";
+
+    /**
+     * The JDBC driver used to connect to the database.
+     */
+    private String driverClass = "org.h2.Driver";
+
+    /**
+     * The database connection URL.
+     */
+    private String url = "jdbc:h2:tcp://localhost:9092/mem:authdb;DB_CLOSE_DELAY=-1";
+
+    /**
+     * The database user.
+     * <p>
+     * The database user must have sufficient permissions to be able to handle
+     * schema changes and updates, when needed.
+     */
+    private String user = "sa";
+
+    /**
+     * The database connection password.
+     */
+    private String password = "sa";
+
+    /**
+     * Designed to work against a table where there is a mapping of one row to one user.
+     */
+    private boolean singleRow = true;
+
+    /**
+     * If the SQL should only be run if all attributes listed in the mappings exist in the query.
+     */
+    private boolean requireAllAttributes = true;
+
+    /**
+     * When constructing the final person object from the attribute repository,
+     * indicate how the username should be canonicalized.
+     */
+    private CaseCanonicalizationMode caseCanonicalization = CaseCanonicalizationMode.NONE;
+
+    /**
+     * Indicates how multiple attributes in a query should be concatenated together.
+     */
+    private QueryType queryType = QueryType.AND;
+
+    /**
+     * Used only when there is a mapping of many rows to one user.
+     * This is done using a key-value structure where the key is the
+     * name of the "attribute name" column the value is the name of the "attribute value" column.
+     */
+    private final Map<String, String> columnMappings = new HashMap<>(0);
+
+    /**
+     * Username attribute(s) to use when running the SQL query.
+     */
+    private final List<String> username = new ArrayList<>(0);
+
+    /**
+     * Map of attributes to fetch from the database.
+     * Attributes are defined using a key-value structure
+     * where CAS allows the attribute name/key to be renamed virtually
+     * to a different attribute. The key is the attribute fetched
+     * from the data source and the value is the attribute name CAS should
+     * use for virtual renames.
+     */
+    private final Map<String, String> attributes = new HashMap<>(0);
+
+    /**
+     * Collection of attributes, used to build the SQL query, that should go through
+     * a case canonicalization process defined as {@code key->value}.
+     */
+    private final List<String> caseInsensitiveQueryAttributes = new ArrayList<>(0);
+
+    /**
+     * Define a {@code Map} of query attribute names to data-layer attribute names to use when building the query.
+     * The key is always the name of the query attribute that is defined by CAS and passed internally,
+     * and the value is the database column that should map.
+     */
+    private final Map<String, String> queryAttributes = new HashMap<>(0);
+
+    public String getSql() {
+        return sql;
+    }
+
+    public void setSql(final String sql) {
+        this.sql = sql;
+    }
+
+    public String getDialect() {
+        return dialect;
+    }
+
+    public void setDialect(final String dialect) {
+        this.dialect = dialect;
+    }
+
+    public String getDriverClass() {
+        return driverClass;
+    }
+
+    public void setDriverClass(final String driverClass) {
+        this.driverClass = driverClass;
+    }
+
+    public String getUrl() {
+        return url;
+    }
+
+    public void setUrl(final String url) {
+        this.url = url;
+    }
+
+    public String getUser() {
+        return user;
+    }
+
+    public void setUser(final String user) {
+        this.user = user;
+    }
+
+    public String getPassword() {
+        return password;
+    }
+
+    public void setPassword(final String password) {
+        this.password = password;
+    }
+
+    public boolean isSingleRow() {
+        return singleRow;
+    }
+
+    public void setSingleRow(final boolean singleRow) {
+        this.singleRow = singleRow;
+    }
+
+    public boolean isRequireAllAttributes() {
+        return requireAllAttributes;
+    }
+
+    public void setRequireAllAttributes(final boolean requireAllAttributes) {
+        this.requireAllAttributes = requireAllAttributes;
+    }
+
+    public CaseCanonicalizationMode getCaseCanonicalization() {
+        return caseCanonicalization;
+    }
+
+    public void setCaseCanonicalization(final CaseCanonicalizationMode caseCanonicalization) {
+        this.caseCanonicalization = caseCanonicalization;
+    }
+
+    public QueryType getQueryType() {
+        return queryType;
+    }
+
+    public void setQueryType(final QueryType queryType) {
+        this.queryType = queryType;
+    }
+
+    public Map<String, String> getColumnMappings() {
+        return columnMappings;
+    }
+
+    public List<String> getUsername() {
+        return username;
+    }
+
+    public Map<String, String> getAttributes() {
+        return attributes;
+    }
+
+    public List<String> getCaseInsensitiveQueryAttributes() {
+        return caseInsensitiveQueryAttributes;
+    }
+
+    public Map<String, String> getQueryAttributes() {

Review Comment:
   ## Exposing internal representation
   
   getQueryAttributes exposes the internal representation stored in field queryAttributes. The value may be modified [after this call to getQueryAttributes](1).
   
   [Show more details](https://github.com/apache/syncope/security/code-scanning/1047)



##########
common/am/lib/src/main/java/org/apache/syncope/common/lib/attr/StubAttrRepoConf.java:
##########
@@ -0,0 +1,38 @@
+/*
+ * 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.syncope.common.lib.attr;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public class StubAttrRepoConf implements AttrRepoConf {
+
+    private static final long serialVersionUID = 835890230066546723L;
+
+    /**
+     * Static attributes that need to be mapped to a hardcoded value belong here.
+     * The structure follows a key-value pair where key is the attribute name
+     * and value is the attribute value.
+     */
+    private final Map<String, String> attributes = new HashMap<>(0);
+
+    public Map<String, String> getAttributes() {

Review Comment:
   ## Exposing internal representation
   
   getAttributes exposes the internal representation stored in field attributes. The value may be modified [after this call to getAttributes](1).
   getAttributes exposes the internal representation stored in field attributes. The value may be modified [after this call to getAttributes](2).
   getAttributes exposes the internal representation stored in field attributes. The value may be modified [after this call to getAttributes](3).
   getAttributes exposes the internal representation stored in field attributes. The value may be modified [after this call to getAttributes](4).
   getAttributes exposes the internal representation stored in field attributes. The value may be modified [after this call to getAttributes](5).
   getAttributes exposes the internal representation stored in field attributes. The value may be modified [after this call to getAttributes](6).
   
   [Show more details](https://github.com/apache/syncope/security/code-scanning/1049)



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: dev-unsubscribe@syncope.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org