UNOMI-487 Add profile alias management to REST API and GraphQL API (#403)
* UNOMI-487 Add profile alias management to REST API and GraphQL API
* UNOMI-487 Add profile alias management to REST API and GraphQL API
diff --git a/api/src/main/java/org/apache/unomi/api/services/ProfileService.java b/api/src/main/java/org/apache/unomi/api/services/ProfileService.java
index b2698c4..e510919 100644
--- a/api/src/main/java/org/apache/unomi/api/services/ProfileService.java
+++ b/api/src/main/java/org/apache/unomi/api/services/ProfileService.java
@@ -108,9 +108,39 @@
*/
Profile save(Profile profile);
+ /**
+ * Adds the alias to the profile.
+ *
+ * @param profileID the identifier of the profile
+ * @param alias the alias which should be linked with of the profile
+ * @param clientID the identifier of the client
+ */
void addAliasToProfile(String profileID, String alias, String clientID);
/**
+ * Removes the alias from the profile.
+ *
+ * @param profileID the identifier of the profile
+ * @param alias the alias which should be unlinked from the profile
+ * @param clientID the identifier of the client
+ */
+ ProfileAlias removeAliasFromProfile(String profileID, String alias, String clientID);
+
+ /**
+ * Find profile aliases which have the specified property with the specified value, ordered according to the specified {@code sortBy} String and paged: only
+ * {@code size} of them are retrieved, starting with the {@code offset}-th one.
+ *
+ * @param profileId the identifier of the profile
+ * @param offset zero or a positive integer specifying the position of the first profile in the total ordered collection of matching profiles
+ * @param size a positive integer specifying how many matching profiles should be retrieved or {@code -1} if all of them should be retrieved
+ * @param sortBy an optional ({@code null} if no sorting is required) String of comma ({@code ,}) separated property names on which ordering should be performed, ordering elements according to the property order in
+ * the String, considering each in turn and moving on to the next one in case of equality of all preceding ones. Each property name is optionally
+ * followed by a column ({@code :}) and an order specifier: {@code asc} or {@code desc}.
+ * @return a {@link PartialList} of matching profiles
+ */
+ PartialList<ProfileAlias> findProfileAliases(String profileId, int offset, int size, String sortBy);
+
+ /**
* Merge the specified profile properties in an existing profile,or save new profile if it does not exist yet
*
* @param profile the profile to be saved
diff --git a/graphql/cxs-impl/src/main/java/org/apache/unomi/graphql/commands/AddAliasToProfileCommand.java b/graphql/cxs-impl/src/main/java/org/apache/unomi/graphql/commands/AddAliasToProfileCommand.java
new file mode 100644
index 0000000..4ba18d5
--- /dev/null
+++ b/graphql/cxs-impl/src/main/java/org/apache/unomi/graphql/commands/AddAliasToProfileCommand.java
@@ -0,0 +1,66 @@
+/*
+ * 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.unomi.graphql.commands;
+
+import org.apache.unomi.api.ProfileAlias;
+import org.apache.unomi.api.services.ProfileService;
+import org.apache.unomi.graphql.types.input.CDPProfileAliasInput;
+import org.apache.unomi.graphql.types.output.CDPProfileAlias;
+import org.apache.unomi.persistence.spi.PersistenceService;
+
+public class AddAliasToProfileCommand extends BaseCommand<CDPProfileAlias> {
+
+ private final CDPProfileAliasInput profileAliasInput;
+
+ public AddAliasToProfileCommand(Builder builder) {
+ super(builder);
+ this.profileAliasInput = builder.profileAliasInput;
+ }
+
+ @Override
+ public CDPProfileAlias execute() {
+ ProfileService profileService = serviceManager.getService(ProfileService.class);
+
+ profileService.addAliasToProfile(
+ profileAliasInput.getProfileID().getId(),
+ profileAliasInput.getAlias(),
+ profileAliasInput.getProfileID().getClient().getId());
+
+ PersistenceService persistenceService = serviceManager.getService(PersistenceService.class);
+ persistenceService.refreshIndex(ProfileAlias.class, null);
+
+ return new CDPProfileAlias(persistenceService.load(profileAliasInput.getAlias(), ProfileAlias.class));
+ }
+
+ public static Builder create() {
+ return new Builder();
+ }
+
+ public static class Builder extends BaseCommand.Builder<Builder> {
+
+ private CDPProfileAliasInput profileAliasInput;
+
+ public Builder profileAliasInput(CDPProfileAliasInput profileAliasInput) {
+ this.profileAliasInput = profileAliasInput;
+ return this;
+ }
+
+ public AddAliasToProfileCommand build() {
+ return new AddAliasToProfileCommand(this);
+ }
+ }
+}
diff --git a/graphql/cxs-impl/src/main/java/org/apache/unomi/graphql/commands/RemoveAliasFromProfileCommand.java b/graphql/cxs-impl/src/main/java/org/apache/unomi/graphql/commands/RemoveAliasFromProfileCommand.java
new file mode 100644
index 0000000..63aa065
--- /dev/null
+++ b/graphql/cxs-impl/src/main/java/org/apache/unomi/graphql/commands/RemoveAliasFromProfileCommand.java
@@ -0,0 +1,69 @@
+/*
+ * 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.unomi.graphql.commands;
+
+import org.apache.unomi.api.ProfileAlias;
+import org.apache.unomi.api.services.ProfileService;
+import org.apache.unomi.graphql.types.input.CDPProfileIDInput;
+import org.apache.unomi.graphql.types.output.CDPProfileAlias;
+
+public class RemoveAliasFromProfileCommand extends BaseCommand<CDPProfileAlias> {
+
+ private final String alias;
+
+ private final CDPProfileIDInput profileIDInput;
+
+ private RemoveAliasFromProfileCommand(Builder builder) {
+ super(builder);
+ this.alias = builder.alias;
+ this.profileIDInput = builder.profileIDInput;
+ }
+
+ @Override
+ public CDPProfileAlias execute() {
+ ProfileService profileService = serviceManager.getService(ProfileService.class);
+
+ ProfileAlias profileAlias = profileService.removeAliasFromProfile(profileIDInput.getId(), alias, profileIDInput.getClient().getId());
+
+ return profileAlias != null ? new CDPProfileAlias(profileAlias) : null;
+ }
+
+ public static Builder create() {
+ return new Builder();
+ }
+
+ public static class Builder extends BaseCommand.Builder<Builder> {
+
+ private String alias;
+
+ private CDPProfileIDInput profileIDInput;
+
+ public Builder setAlias(String alias) {
+ this.alias = alias;
+ return this;
+ }
+
+ public Builder setProfileIDInput(CDPProfileIDInput profileIDInput) {
+ this.profileIDInput = profileIDInput;
+ return this;
+ }
+
+ public RemoveAliasFromProfileCommand build() {
+ return new RemoveAliasFromProfileCommand(this);
+ }
+ }
+}
diff --git a/graphql/cxs-impl/src/main/java/org/apache/unomi/graphql/condition/factories/ProfileAliasConditionFactory.java b/graphql/cxs-impl/src/main/java/org/apache/unomi/graphql/condition/factories/ProfileAliasConditionFactory.java
new file mode 100644
index 0000000..28c6340
--- /dev/null
+++ b/graphql/cxs-impl/src/main/java/org/apache/unomi/graphql/condition/factories/ProfileAliasConditionFactory.java
@@ -0,0 +1,77 @@
+/*
+ * 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.unomi.graphql.condition.factories;
+
+import graphql.schema.DataFetchingEnvironment;
+import org.apache.unomi.api.conditions.Condition;
+import org.apache.unomi.graphql.types.input.CDPProfileAliasFilterInput;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+public class ProfileAliasConditionFactory extends ConditionFactory {
+
+ private static ProfileAliasConditionFactory instance;
+
+ public static synchronized ProfileAliasConditionFactory get(final DataFetchingEnvironment environment) {
+ if (instance == null) {
+ instance = new ProfileAliasConditionFactory(environment);
+ }
+
+ return instance;
+ }
+
+ private ProfileAliasConditionFactory(final DataFetchingEnvironment environment) {
+ super("profileAliasesPropertyCondition", environment);
+ }
+
+ @SuppressWarnings("unchecked")
+ public Condition filterInputCondition(final CDPProfileAliasFilterInput filterInput, final Map<String, Object> filterInputAsMap) {
+ if (filterInput == null) {
+ return matchAllCondition();
+ }
+
+ final List<Condition> rootSubConditions = new ArrayList<>();
+
+ if (filterInput.getAlias_equals() != null) {
+ rootSubConditions.add(propertyCondition("itemId", filterInput.getAlias_equals()));
+ }
+
+ if (filterInput.getProfileID_equals() != null) {
+ rootSubConditions.add(propertyCondition("profileID.keyword", filterInput.getProfileID_equals()));
+ }
+
+ if (filterInput.getClientID_equals() != null) {
+ rootSubConditions.add(propertyCondition("clientID.keyword", filterInput.getClientID_equals()));
+ }
+
+ if (filterInputAsMap.get("and") != null) {
+ final List<Map<String, Object>> andFilterInputAsMap = (List<Map<String, Object>>) filterInputAsMap.get("and");
+
+ rootSubConditions.add(filtersToCondition(filterInput.getAnd(), andFilterInputAsMap, this::filterInputCondition, "and"));
+ }
+
+ if (filterInputAsMap.get("or") != null) {
+ final List<Map<String, Object>> orFilterInputAsMap = (List<Map<String, Object>>) filterInputAsMap.get("or");
+
+ rootSubConditions.add(filtersToCondition(filterInput.getOr(), orFilterInputAsMap, this::filterInputCondition, "or"));
+ }
+
+ return booleanCondition("and", rootSubConditions);
+ }
+}
diff --git a/graphql/cxs-impl/src/main/java/org/apache/unomi/graphql/fetchers/profile/FindProfileAliasConnectionDataFetcher.java b/graphql/cxs-impl/src/main/java/org/apache/unomi/graphql/fetchers/profile/FindProfileAliasConnectionDataFetcher.java
new file mode 100644
index 0000000..e6dea60
--- /dev/null
+++ b/graphql/cxs-impl/src/main/java/org/apache/unomi/graphql/fetchers/profile/FindProfileAliasConnectionDataFetcher.java
@@ -0,0 +1,71 @@
+/*
+ * 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.unomi.graphql.fetchers.profile;
+
+import graphql.schema.DataFetchingEnvironment;
+import org.apache.unomi.api.PartialList;
+import org.apache.unomi.api.ProfileAlias;
+import org.apache.unomi.api.conditions.Condition;
+import org.apache.unomi.api.query.Query;
+import org.apache.unomi.graphql.condition.factories.ProfileAliasConditionFactory;
+import org.apache.unomi.graphql.fetchers.BaseConnectionDataFetcher;
+import org.apache.unomi.graphql.fetchers.ConnectionParams;
+import org.apache.unomi.graphql.services.ServiceManager;
+import org.apache.unomi.graphql.types.input.CDPOrderByInput;
+import org.apache.unomi.graphql.types.input.CDPProfileAliasFilterInput;
+import org.apache.unomi.graphql.types.output.CDPPageInfo;
+import org.apache.unomi.graphql.types.output.CDPProfileAliasConnection;
+import org.apache.unomi.graphql.types.output.CDPProfileAliasEdge;
+import org.apache.unomi.persistence.spi.PersistenceService;
+
+import java.util.List;
+import java.util.stream.Collectors;
+
+public class FindProfileAliasConnectionDataFetcher extends BaseConnectionDataFetcher<CDPProfileAliasConnection> {
+
+ private final CDPProfileAliasFilterInput filterInput;
+
+ private final List<CDPOrderByInput> orderByInput;
+
+ public FindProfileAliasConnectionDataFetcher(
+ final CDPProfileAliasFilterInput filterInput, final List<CDPOrderByInput> orderByInput) {
+ this.filterInput = filterInput;
+ this.orderByInput = orderByInput;
+ }
+
+ @Override
+ public CDPProfileAliasConnection get(DataFetchingEnvironment environment) throws Exception {
+ final ServiceManager serviceManager = environment.getContext();
+
+ final PersistenceService persistenceService = serviceManager.getService(PersistenceService.class);
+
+ final ConnectionParams params = parseConnectionParams(environment);
+
+ final Query query = buildQuery(createCondition(environment), orderByInput, params);
+
+ final PartialList<ProfileAlias> partialList = persistenceService.query(
+ query.getCondition(), query.getSortby(), ProfileAlias.class, query.getOffset(), query.getLimit());
+
+ final List<CDPProfileAliasEdge> edges = partialList.getList().stream().map(CDPProfileAliasEdge::new).collect(Collectors.toList());
+
+ return new CDPProfileAliasConnection(edges, new CDPPageInfo(), partialList.getTotalSize());
+ }
+
+ private Condition createCondition(final DataFetchingEnvironment environment) {
+ return ProfileAliasConditionFactory.get(environment).filterInputCondition(filterInput, environment.getArgument("filter"));
+ }
+}
diff --git a/graphql/cxs-impl/src/main/java/org/apache/unomi/graphql/fetchers/profile/GetProfileAliasesDataFetcher.java b/graphql/cxs-impl/src/main/java/org/apache/unomi/graphql/fetchers/profile/GetProfileAliasesDataFetcher.java
new file mode 100644
index 0000000..0b14d3d
--- /dev/null
+++ b/graphql/cxs-impl/src/main/java/org/apache/unomi/graphql/fetchers/profile/GetProfileAliasesDataFetcher.java
@@ -0,0 +1,47 @@
+/*
+ * 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.unomi.graphql.fetchers.profile;
+
+import graphql.schema.DataFetcher;
+import graphql.schema.DataFetchingEnvironment;
+import org.apache.unomi.api.PartialList;
+import org.apache.unomi.api.ProfileAlias;
+import org.apache.unomi.api.services.ProfileService;
+import org.apache.unomi.graphql.services.ServiceManager;
+import org.apache.unomi.graphql.types.output.CDPProfileAlias;
+
+import java.util.List;
+import java.util.stream.Collectors;
+
+public class GetProfileAliasesDataFetcher implements DataFetcher<List<CDPProfileAlias>> {
+
+ private final String profileId;
+
+ public GetProfileAliasesDataFetcher(final String profileId) {
+ this.profileId = profileId;
+ }
+
+ @Override
+ public List<CDPProfileAlias> get(final DataFetchingEnvironment environment) throws Exception {
+ ServiceManager serviceManager = environment.getContext();
+
+ ProfileService profileService = serviceManager.getService(ProfileService.class);
+ PartialList<ProfileAlias> partialList = profileService.findProfileAliases(profileId, 0, 100, null);
+
+ return partialList.getList().stream().map(CDPProfileAlias::new).collect(Collectors.toList());
+ }
+}
diff --git a/graphql/cxs-impl/src/main/java/org/apache/unomi/graphql/fetchers/profile/ProfileAliasDataFetcher.java b/graphql/cxs-impl/src/main/java/org/apache/unomi/graphql/fetchers/profile/ProfileAliasDataFetcher.java
new file mode 100644
index 0000000..fd99e06
--- /dev/null
+++ b/graphql/cxs-impl/src/main/java/org/apache/unomi/graphql/fetchers/profile/ProfileAliasDataFetcher.java
@@ -0,0 +1,41 @@
+/*
+ * 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.unomi.graphql.fetchers.profile;
+
+import graphql.schema.DataFetcher;
+import graphql.schema.DataFetchingEnvironment;
+import org.apache.unomi.api.ProfileAlias;
+import org.apache.unomi.graphql.services.ServiceManager;
+import org.apache.unomi.graphql.types.output.CDPProfileAlias;
+import org.apache.unomi.persistence.spi.PersistenceService;
+
+public class ProfileAliasDataFetcher implements DataFetcher<CDPProfileAlias> {
+
+ private final String alias;
+
+ public ProfileAliasDataFetcher(final String alias) {
+ this.alias = alias;
+ }
+
+ @Override
+ public CDPProfileAlias get(final DataFetchingEnvironment environment) throws Exception {
+ ServiceManager serviceManager = environment.getContext();
+ PersistenceService persistenceService = serviceManager.getService(PersistenceService.class);
+ ProfileAlias profileAlias = persistenceService.load(alias, ProfileAlias.class);
+ return profileAlias != null ? new CDPProfileAlias(profileAlias) : null;
+ }
+}
diff --git a/graphql/cxs-impl/src/main/java/org/apache/unomi/graphql/types/input/CDPProfileAliasFilterInput.java b/graphql/cxs-impl/src/main/java/org/apache/unomi/graphql/types/input/CDPProfileAliasFilterInput.java
new file mode 100644
index 0000000..ace6800
--- /dev/null
+++ b/graphql/cxs-impl/src/main/java/org/apache/unomi/graphql/types/input/CDPProfileAliasFilterInput.java
@@ -0,0 +1,83 @@
+/*
+ * 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.unomi.graphql.types.input;
+
+import graphql.annotations.annotationTypes.GraphQLField;
+import graphql.annotations.annotationTypes.GraphQLName;
+
+import java.util.List;
+
+import static org.apache.unomi.graphql.types.input.CDPProfileAliasFilterInput.TYPE_NAME;
+
+@GraphQLName(TYPE_NAME)
+public class CDPProfileAliasFilterInput {
+
+ public static final String TYPE_NAME = "CDP_ProfileAliasFilterInput";
+
+ @GraphQLField
+ @GraphQLName("and")
+ private final List<CDPProfileAliasFilterInput> and;
+
+ @GraphQLField
+ @GraphQLName("or")
+ private final List<CDPProfileAliasFilterInput> or;
+
+ @GraphQLField
+ @GraphQLName("alias_equals")
+ private final String alias_equals;
+
+ @GraphQLField
+ @GraphQLName("profileID_equals")
+ private final String profileID_equals;
+
+ @GraphQLField
+ @GraphQLName("clientID_equals")
+ private final String clientID_equals;
+
+ public CDPProfileAliasFilterInput(
+ @GraphQLName("and") List<CDPProfileAliasFilterInput> and,
+ @GraphQLName("or") List<CDPProfileAliasFilterInput> or,
+ @GraphQLName("alias_equals") String alias_equals,
+ @GraphQLName("profileID_equals") String profileID_equals,
+ @GraphQLName("clientID_equals") String clientID_equals) {
+ this.and = and;
+ this.or = or;
+ this.alias_equals = alias_equals;
+ this.profileID_equals = profileID_equals;
+ this.clientID_equals = clientID_equals;
+ }
+
+ public List<CDPProfileAliasFilterInput> getAnd() {
+ return and;
+ }
+
+ public List<CDPProfileAliasFilterInput> getOr() {
+ return or;
+ }
+
+ public String getAlias_equals() {
+ return alias_equals;
+ }
+
+ public String getProfileID_equals() {
+ return profileID_equals;
+ }
+
+ public String getClientID_equals() {
+ return clientID_equals;
+ }
+}
diff --git a/graphql/cxs-impl/src/main/java/org/apache/unomi/graphql/types/input/CDPProfileAliasInput.java b/graphql/cxs-impl/src/main/java/org/apache/unomi/graphql/types/input/CDPProfileAliasInput.java
new file mode 100644
index 0000000..1351a8c
--- /dev/null
+++ b/graphql/cxs-impl/src/main/java/org/apache/unomi/graphql/types/input/CDPProfileAliasInput.java
@@ -0,0 +1,53 @@
+/*
+ * 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.unomi.graphql.types.input;
+
+import graphql.annotations.annotationTypes.GraphQLField;
+import graphql.annotations.annotationTypes.GraphQLID;
+import graphql.annotations.annotationTypes.GraphQLName;
+import graphql.annotations.annotationTypes.GraphQLNonNull;
+
+import static org.apache.unomi.graphql.types.input.CDPProfileAliasInput.TYPE_NAME;
+
+@GraphQLName(TYPE_NAME)
+public class CDPProfileAliasInput {
+
+ public static final String TYPE_NAME = "CDP_ProfileAliasInput";
+
+ @GraphQLID
+ @GraphQLField
+ @GraphQLNonNull
+ private final String alias;
+
+ @GraphQLField
+ @GraphQLNonNull
+ private final CDPProfileIDInput profileID;
+
+ public CDPProfileAliasInput(@GraphQLID @GraphQLNonNull @GraphQLName("alias") String alias,
+ @GraphQLNonNull @GraphQLName("profileID") CDPProfileIDInput profileID) {
+ this.alias = alias;
+ this.profileID = profileID;
+ }
+
+ public String getAlias() {
+ return alias;
+ }
+
+ public CDPProfileIDInput getProfileID() {
+ return profileID;
+ }
+}
diff --git a/graphql/cxs-impl/src/main/java/org/apache/unomi/graphql/types/output/CDPMutation.java b/graphql/cxs-impl/src/main/java/org/apache/unomi/graphql/types/output/CDPMutation.java
index ee1cdeb..26f88bd 100644
--- a/graphql/cxs-impl/src/main/java/org/apache/unomi/graphql/types/output/CDPMutation.java
+++ b/graphql/cxs-impl/src/main/java/org/apache/unomi/graphql/types/output/CDPMutation.java
@@ -21,6 +21,7 @@
import graphql.annotations.annotationTypes.GraphQLName;
import graphql.annotations.annotationTypes.GraphQLNonNull;
import graphql.schema.DataFetchingEnvironment;
+import org.apache.unomi.graphql.commands.AddAliasToProfileCommand;
import org.apache.unomi.graphql.commands.CreateOrUpdatePersonaCommand;
import org.apache.unomi.graphql.commands.CreateOrUpdateProfilePropertiesCommand;
import org.apache.unomi.graphql.commands.CreateOrUpdateSourceCommand;
@@ -33,6 +34,7 @@
import org.apache.unomi.graphql.commands.DeleteTopicCommand;
import org.apache.unomi.graphql.commands.DeleteViewCommand;
import org.apache.unomi.graphql.commands.ProcessEventsCommand;
+import org.apache.unomi.graphql.commands.RemoveAliasFromProfileCommand;
import org.apache.unomi.graphql.commands.list.AddProfileToListCommand;
import org.apache.unomi.graphql.commands.list.CreateOrUpdateListCommand;
import org.apache.unomi.graphql.commands.list.DeleteListCommand;
@@ -43,6 +45,7 @@
import org.apache.unomi.graphql.types.input.CDPEventInput;
import org.apache.unomi.graphql.types.input.CDPListInput;
import org.apache.unomi.graphql.types.input.CDPPersonaInput;
+import org.apache.unomi.graphql.types.input.CDPProfileAliasInput;
import org.apache.unomi.graphql.types.input.CDPProfileIDInput;
import org.apache.unomi.graphql.types.input.CDPPropertyInput;
import org.apache.unomi.graphql.types.input.CDPSegmentInput;
@@ -265,4 +268,28 @@
.execute();
}
+ @GraphQLField
+ public CDPProfileAlias addAliasToProfile(
+ final @GraphQLNonNull @GraphQLName("profileAlias") CDPProfileAliasInput profileAliasInput,
+ final DataFetchingEnvironment environment) {
+ return AddAliasToProfileCommand.create()
+ .profileAliasInput(profileAliasInput)
+ .setEnvironment(environment)
+ .build()
+ .execute();
+ }
+
+ @GraphQLField
+ public CDPProfileAlias removeAliasFromProfile(
+ final @GraphQLID @GraphQLNonNull @GraphQLName("alias") String alias,
+ final @GraphQLName("profileID") CDPProfileIDInput profileIDInput,
+ final DataFetchingEnvironment environment
+ ) {
+ return RemoveAliasFromProfileCommand.create()
+ .setAlias(alias)
+ .setProfileIDInput(profileIDInput)
+ .setEnvironment(environment)
+ .build()
+ .execute();
+ }
}
diff --git a/graphql/cxs-impl/src/main/java/org/apache/unomi/graphql/types/output/CDPProfileAlias.java b/graphql/cxs-impl/src/main/java/org/apache/unomi/graphql/types/output/CDPProfileAlias.java
new file mode 100644
index 0000000..cf2b3bb
--- /dev/null
+++ b/graphql/cxs-impl/src/main/java/org/apache/unomi/graphql/types/output/CDPProfileAlias.java
@@ -0,0 +1,66 @@
+/*
+ * 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.unomi.graphql.types.output;
+
+import graphql.annotations.annotationTypes.GraphQLDescription;
+import graphql.annotations.annotationTypes.GraphQLField;
+import graphql.annotations.annotationTypes.GraphQLName;
+import org.apache.unomi.api.ProfileAlias;
+
+import java.time.OffsetDateTime;
+import java.time.ZoneId;
+
+import static org.apache.unomi.graphql.types.output.CDPProfileAlias.TYPE_NAME;
+
+@GraphQLName(TYPE_NAME)
+@GraphQLDescription("Alias for Profile.")
+public class CDPProfileAlias {
+ public static final String TYPE_NAME = "CDP_ProfileAlias";
+
+ private final ProfileAlias profileAlias;
+
+ public CDPProfileAlias(final ProfileAlias profileAlias) {
+ this.profileAlias = profileAlias;
+ }
+
+ @GraphQLField
+ public String alias() {
+ return profileAlias != null ? profileAlias.getItemId() : null;
+ }
+
+ @GraphQLField
+ public CDPProfileID profileID() {
+ if (profileAlias != null) {
+ CDPProfileID profileID = new CDPProfileID(profileAlias.getProfileID());
+ if (profileAlias.getClientID() != null) {
+ profileID.setClient(new CDPClient(profileAlias.getClientID(), profileAlias.getClientID()));
+ }
+ return profileID;
+ }
+ return null;
+ }
+
+ @GraphQLField
+ public OffsetDateTime creationTime() {
+ return profileAlias != null ? profileAlias.getCreationTime().toInstant().atZone(ZoneId.systemDefault()).toOffsetDateTime() : null;
+ }
+
+ @GraphQLField
+ public OffsetDateTime modifiedTime() {
+ return profileAlias != null ? profileAlias.getModifiedTime().toInstant().atZone(ZoneId.systemDefault()).toOffsetDateTime() : null;
+ }
+}
diff --git a/graphql/cxs-impl/src/main/java/org/apache/unomi/graphql/types/output/CDPProfileAliasConnection.java b/graphql/cxs-impl/src/main/java/org/apache/unomi/graphql/types/output/CDPProfileAliasConnection.java
new file mode 100644
index 0000000..a6a9459
--- /dev/null
+++ b/graphql/cxs-impl/src/main/java/org/apache/unomi/graphql/types/output/CDPProfileAliasConnection.java
@@ -0,0 +1,66 @@
+/*
+ * 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.unomi.graphql.types.output;
+
+import graphql.annotations.annotationTypes.GraphQLField;
+import graphql.annotations.annotationTypes.GraphQLName;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import static org.apache.unomi.graphql.types.output.CDPProfileAliasConnection.TYPE_NAME;
+
+@GraphQLName(TYPE_NAME)
+public class CDPProfileAliasConnection {
+
+ public static final String TYPE_NAME = "CDP_ProfileAliasConnection";
+
+ private final List<CDPProfileAliasEdge> edges;
+
+ private final CDPPageInfo pageInfo;
+
+ private final Long totalCount;
+
+ public CDPProfileAliasConnection() {
+ this(new ArrayList<>(), new CDPPageInfo(), 0L);
+ }
+
+ public CDPProfileAliasConnection(
+ final List<CDPProfileAliasEdge> edges, final CDPPageInfo pageInfo, final Long totalCount) {
+ this.edges = edges;
+ this.pageInfo = pageInfo;
+ this.totalCount = totalCount;
+ }
+
+ @GraphQLField
+ @GraphQLName("edges")
+ public List<CDPProfileAliasEdge> edges() {
+ return edges;
+ }
+
+ @GraphQLField
+ @GraphQLName("pageInfo")
+ public CDPPageInfo pageInfo() {
+ return pageInfo;
+ }
+
+ @GraphQLField
+ @GraphQLName("totalCount")
+ public Long totalCount() {
+ return totalCount;
+ }
+}
diff --git a/graphql/cxs-impl/src/main/java/org/apache/unomi/graphql/types/output/CDPProfileAliasEdge.java b/graphql/cxs-impl/src/main/java/org/apache/unomi/graphql/types/output/CDPProfileAliasEdge.java
new file mode 100644
index 0000000..293b767
--- /dev/null
+++ b/graphql/cxs-impl/src/main/java/org/apache/unomi/graphql/types/output/CDPProfileAliasEdge.java
@@ -0,0 +1,49 @@
+/*
+ * 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.unomi.graphql.types.output;
+
+import graphql.annotations.annotationTypes.GraphQLField;
+import graphql.annotations.annotationTypes.GraphQLName;
+import graphql.annotations.annotationTypes.GraphQLNonNull;
+import graphql.schema.DataFetchingEnvironment;
+import org.apache.unomi.api.ProfileAlias;
+
+import static org.apache.unomi.graphql.types.output.CDPProfileAliasEdge.TYPE_NAME;
+
+@GraphQLName(TYPE_NAME)
+public class CDPProfileAliasEdge {
+
+ public static final String TYPE_NAME = "CDP_ProfileAliasEdge";
+
+ private final ProfileAlias profileAlias;
+
+ public CDPProfileAliasEdge(final ProfileAlias profileAlias) {
+ this.profileAlias = profileAlias;
+ }
+
+ @GraphQLField
+ @GraphQLName("node")
+ public CDPProfileAlias node(final DataFetchingEnvironment environment) {
+ return new CDPProfileAlias(profileAlias);
+ }
+
+ @GraphQLNonNull
+ @GraphQLField
+ public String cursor() {
+ return profileAlias != null ? profileAlias.getItemId() : null;
+ }
+}
diff --git a/graphql/cxs-impl/src/main/java/org/apache/unomi/graphql/types/output/CDPQuery.java b/graphql/cxs-impl/src/main/java/org/apache/unomi/graphql/types/output/CDPQuery.java
index e723fcf..2b7ba0d 100644
--- a/graphql/cxs-impl/src/main/java/org/apache/unomi/graphql/types/output/CDPQuery.java
+++ b/graphql/cxs-impl/src/main/java/org/apache/unomi/graphql/types/output/CDPQuery.java
@@ -16,7 +16,11 @@
*/
package org.apache.unomi.graphql.types.output;
-import graphql.annotations.annotationTypes.*;
+import graphql.annotations.annotationTypes.GraphQLDescription;
+import graphql.annotations.annotationTypes.GraphQLField;
+import graphql.annotations.annotationTypes.GraphQLID;
+import graphql.annotations.annotationTypes.GraphQLName;
+import graphql.annotations.annotationTypes.GraphQLNonNull;
import graphql.schema.DataFetchingEnvironment;
import org.apache.unomi.graphql.fetchers.FindTopicsConnectionDataFetcher;
import org.apache.unomi.graphql.fetchers.SourceDataFetcher;
@@ -26,7 +30,10 @@
import org.apache.unomi.graphql.fetchers.event.FindEventsConnectionDataFetcher;
import org.apache.unomi.graphql.fetchers.list.GetListDataFetcher;
import org.apache.unomi.graphql.fetchers.list.ListConnectionDataFetcher;
+import org.apache.unomi.graphql.fetchers.profile.FindProfileAliasConnectionDataFetcher;
import org.apache.unomi.graphql.fetchers.profile.FindProfilesConnectionDataFetcher;
+import org.apache.unomi.graphql.fetchers.profile.GetProfileAliasesDataFetcher;
+import org.apache.unomi.graphql.fetchers.profile.ProfileAliasDataFetcher;
import org.apache.unomi.graphql.fetchers.profile.ProfileDataFetcher;
import org.apache.unomi.graphql.fetchers.profile.PropertiesConnectionDataFetcher;
import org.apache.unomi.graphql.fetchers.segment.FindSegmentsConnectionDataFetcher;
@@ -35,6 +42,7 @@
import org.apache.unomi.graphql.types.input.CDPEventFilterInput;
import org.apache.unomi.graphql.types.input.CDPListFilterInput;
import org.apache.unomi.graphql.types.input.CDPOrderByInput;
+import org.apache.unomi.graphql.types.input.CDPProfileAliasFilterInput;
import org.apache.unomi.graphql.types.input.CDPProfileFilterInput;
import org.apache.unomi.graphql.types.input.CDPProfileIDInput;
import org.apache.unomi.graphql.types.input.CDPSegmentFilterInput;
@@ -174,4 +182,30 @@
return new ListConnectionDataFetcher(filterInput, orderByInput).get(environment);
}
+ @GraphQLField
+ public CDPProfileAlias getProfileAlias(
+ final @GraphQLID @GraphQLNonNull @GraphQLName("alias") String alias,
+ final DataFetchingEnvironment environment) throws Exception {
+ return new ProfileAliasDataFetcher(alias).get(environment);
+ }
+
+ @GraphQLField
+ public List<CDPProfileAlias> getProfileAliases(
+ final @GraphQLID @GraphQLName("profileID") @GraphQLNonNull String profileID,
+ final DataFetchingEnvironment environment) throws Exception {
+ return new GetProfileAliasesDataFetcher(profileID).get(environment);
+ }
+
+ @GraphQLField
+ public CDPProfileAliasConnection findProfileAliases(
+ final @GraphQLName("filter") CDPProfileAliasFilterInput filterInput,
+ final @GraphQLName("orderBy") List<CDPOrderByInput> orderByInput,
+ final @GraphQLName("first") Integer first,
+ final @GraphQLName("after") String after,
+ final @GraphQLName("last") Integer last,
+ final @GraphQLName("before") String before,
+ final DataFetchingEnvironment environment
+ ) throws Exception {
+ return new FindProfileAliasConnectionDataFetcher(filterInput, orderByInput).get(environment);
+ }
}
diff --git a/itests/src/test/java/org/apache/unomi/itests/AllITs.java b/itests/src/test/java/org/apache/unomi/itests/AllITs.java
index b198a93..70230bf 100644
--- a/itests/src/test/java/org/apache/unomi/itests/AllITs.java
+++ b/itests/src/test/java/org/apache/unomi/itests/AllITs.java
@@ -59,7 +59,8 @@
GraphQLProfilePropertiesIT.class,
GraphQLSegmentIT.class,
GraphQLWebSocketIT.class,
- JSONSchemaIT.class
+ JSONSchemaIT.class,
+ GraphQLProfileAliasesIT.class
})
public class AllITs {
}
diff --git a/itests/src/test/java/org/apache/unomi/itests/ProfileServiceIT.java b/itests/src/test/java/org/apache/unomi/itests/ProfileServiceIT.java
index e9bf221..b91aec2 100644
--- a/itests/src/test/java/org/apache/unomi/itests/ProfileServiceIT.java
+++ b/itests/src/test/java/org/apache/unomi/itests/ProfileServiceIT.java
@@ -29,6 +29,8 @@
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.fail;
+
+import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.Before;
@@ -44,6 +46,7 @@
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
+import java.util.UUID;
import java.util.stream.IntStream;
import javax.inject.Inject;
@@ -179,7 +182,8 @@
@Test
public void testLoadProfileByAlias() throws Exception {
- String profileID = "profileID_testLoadProfileByAlias";
+ String profileID = UUID.randomUUID().toString();
+
try {
Profile profile = new Profile();
profile.setItemId(profileID);
@@ -189,7 +193,7 @@
IntStream.range(1, 3).forEach(index -> {
final String profileAlias = profileID + "_alias_" + index;
- profileService.addAliasToProfile(profileID, profileAlias, "clientID");
+ profileService.addAliasToProfile(profileID, profileAlias, "clientID" + index);
});
refreshPersistence();
@@ -205,13 +209,16 @@
storedProfile = profileService.load(profileID + "_alias_2");
assertNotNull(storedProfile);
assertEquals(profileID, storedProfile.getItemId());
- } finally {
- profileService.delete(profileID, false);
+ PartialList<ProfileAlias> aliasList = profileService.findProfileAliases(profileID, 0, 10, null);
+ assertEquals(2, aliasList.size());
+ } finally {
IntStream.range(1, 3).forEach(index -> {
final String profileAlias = profileID + "_alias_" + index;
- persistenceService.remove(profileAlias, ProfileAlias.class);
+ profileService.removeAliasFromProfile(profileID, profileAlias, "clientID" + index);
});
+
+ profileService.delete(profileID, false);
}
}
diff --git a/itests/src/test/java/org/apache/unomi/itests/graphql/GraphQLProfileAliasesIT.java b/itests/src/test/java/org/apache/unomi/itests/graphql/GraphQLProfileAliasesIT.java
new file mode 100644
index 0000000..6cd6275
--- /dev/null
+++ b/itests/src/test/java/org/apache/unomi/itests/graphql/GraphQLProfileAliasesIT.java
@@ -0,0 +1,104 @@
+/*
+ * 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.unomi.itests.graphql;
+
+import org.apache.http.client.methods.CloseableHttpResponse;
+import org.apache.unomi.api.Profile;
+import org.apache.unomi.api.ProfileAlias;
+import org.apache.unomi.api.services.ProfileService;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.ops4j.pax.exam.util.Filter;
+
+import javax.inject.Inject;
+
+public class GraphQLProfileAliasesIT extends BaseGraphQLIT {
+
+ @Inject
+ @Filter(timeout = 600000)
+ protected ProfileService profileService;
+
+ @Before
+ public void setUp() throws InterruptedException {
+ removeItems(ProfileAlias.class);
+ removeItems(Profile.class);
+ }
+
+ @Test
+ public void lifecycle() throws Exception {
+ final Profile profile = new Profile("f6c1c5a0-eff3-42b7-b375-44da5d01f2a6");
+ profileService.save(profile);
+
+ // test adding an alias to a profile
+ try (CloseableHttpResponse response = post("graphql/profileAlias/addAliasToProfile.json")) {
+ final ResponseContext context = ResponseContext.parse(response.getEntity());
+
+ Assert.assertNotNull(context.getValue("data.cdp.addAliasToProfile"));
+ Assert.assertEquals("myAlias", context.getValue("data.cdp.addAliasToProfile.alias"));
+ Assert.assertNotNull(context.getValue("data.cdp.addAliasToProfile.profileID"));
+ Assert.assertEquals("f6c1c5a0-eff3-42b7-b375-44da5d01f2a6",
+ context.getValue("data.cdp.addAliasToProfile.profileID.id"));
+ Assert.assertNotNull(context.getValue("data.cdp.addAliasToProfile.profileID.client"));
+ Assert.assertEquals("facebook", context.getValue("data.cdp.addAliasToProfile.profileID.client.ID"));
+ }
+
+ // test fetching a profile by an alias
+ try (CloseableHttpResponse response = post("graphql/profileAlias/getProfileAlias.json")) {
+ final ResponseContext context = ResponseContext.parse(response.getEntity());
+
+ Assert.assertNotNull(context.getValue("data.cdp.getProfileAlias"));
+ Assert.assertEquals("myAlias", context.getValue("data.cdp.getProfileAlias.alias"));
+ Assert.assertNotNull(context.getValue("data.cdp.getProfileAlias.profileID"));
+ Assert.assertEquals("f6c1c5a0-eff3-42b7-b375-44da5d01f2a6",
+ context.getValue("data.cdp.getProfileAlias.profileID.id"));
+ }
+
+ // test fetching a profile's aliases
+ try (CloseableHttpResponse response = post("graphql/profileAlias/getProfileAliases.json")) {
+ final ResponseContext context = ResponseContext.parse(response.getEntity());
+
+ Assert.assertNotNull(context.getValue("data.cdp.getProfileAliases"));
+ Assert.assertEquals("myAlias", context.getValue("data.cdp.getProfileAliases[0].alias"));
+ Assert.assertNotNull(context.getValue("data.cdp.getProfileAliases[0].profileID"));
+ Assert.assertEquals("f6c1c5a0-eff3-42b7-b375-44da5d01f2a6",
+ context.getValue("data.cdp.getProfileAliases[0].profileID.id"));
+ }
+
+ // test filtering a profile aliases by criteria
+ try (CloseableHttpResponse response = post("graphql/profileAlias/findProfileAliases.json")) {
+ final ResponseContext context = ResponseContext.parse(response.getEntity());
+
+ Assert.assertNotNull(context.getValue("data.cdp.findProfileAliases"));
+ Assert.assertEquals("myAlias", context.getValue("data.cdp.findProfileAliases.edges[0].node.alias"));
+ Assert.assertNotNull(context.getValue("data.cdp.findProfileAliases.edges[0].node.profileID"));
+ Assert.assertEquals("f6c1c5a0-eff3-42b7-b375-44da5d01f2a6",
+ context.getValue("data.cdp.findProfileAliases.edges[0].node.profileID.id"));
+ }
+
+ // test removing an alias from a profile
+ try (CloseableHttpResponse response = post("graphql/profileAlias/removeAliasFromProfile.json")) {
+ final ResponseContext context = ResponseContext.parse(response.getEntity());
+
+ Assert.assertNotNull(context.getValue("data.cdp.removeAliasFromProfile"));
+ Assert.assertEquals("myAlias", context.getValue("data.cdp.removeAliasFromProfile.alias"));
+ Assert.assertNotNull(context.getValue("data.cdp.removeAliasFromProfile.profileID"));
+ Assert.assertEquals("f6c1c5a0-eff3-42b7-b375-44da5d01f2a6",
+ context.getValue("data.cdp.removeAliasFromProfile.profileID.id"));
+ }
+ }
+}
diff --git a/itests/src/test/resources/graphql/profileAlias/addAliasToProfile.json b/itests/src/test/resources/graphql/profileAlias/addAliasToProfile.json
new file mode 100644
index 0000000..81a2f7e
--- /dev/null
+++ b/itests/src/test/resources/graphql/profileAlias/addAliasToProfile.json
@@ -0,0 +1,16 @@
+{
+ "operationName": "addAliasToProfile",
+ "variables": {
+ "profileAlias": {
+ "alias": "myAlias",
+ "profileID": {
+ "id": "f6c1c5a0-eff3-42b7-b375-44da5d01f2a6",
+ "client": {
+ "id": "facebook",
+ "title": "Facebook"
+ }
+ }
+ }
+ },
+ "query": "mutation addAliasToProfile($profileAlias: CDP_ProfileAliasInput!) {\n cdp {\n addAliasToProfile(profileAlias: $profileAlias) {\n alias\n profileID {\n client {\n ID\n title\n }\n id\n }\n }\n }\n}\n"
+}
diff --git a/itests/src/test/resources/graphql/profileAlias/findProfileAliases.json b/itests/src/test/resources/graphql/profileAlias/findProfileAliases.json
new file mode 100644
index 0000000..5e4abdd
--- /dev/null
+++ b/itests/src/test/resources/graphql/profileAlias/findProfileAliases.json
@@ -0,0 +1,8 @@
+{
+ "operationName": null,
+ "variables": {
+ "alias": "myAlias",
+ "clientID": "facebook"
+ },
+ "query": "query ($alias: String, $clientID: String) {\n cdp {\n findProfileAliases(filter: {and: [{alias_equals: $alias}, {clientID_equals: $clientID}]}) {\n totalCount\n edges {\n cursor\n node {\n alias\n profileID {\n id\n client {\n ID\n }\n }\n }\n }\n }\n }\n}\n"
+}
diff --git a/itests/src/test/resources/graphql/profileAlias/getProfileAlias.json b/itests/src/test/resources/graphql/profileAlias/getProfileAlias.json
new file mode 100644
index 0000000..8c97290
--- /dev/null
+++ b/itests/src/test/resources/graphql/profileAlias/getProfileAlias.json
@@ -0,0 +1,5 @@
+{
+ "operationName": null,
+ "variables": {},
+ "query": "{\n cdp {\n getProfileAlias(alias: \"myAlias\") {\n alias\n creationTime\n modifiedTime\n profileID {\n id\n }\n }\n }\n}\n"
+}
diff --git a/itests/src/test/resources/graphql/profileAlias/getProfileAliases.json b/itests/src/test/resources/graphql/profileAlias/getProfileAliases.json
new file mode 100644
index 0000000..32f4a78
--- /dev/null
+++ b/itests/src/test/resources/graphql/profileAlias/getProfileAliases.json
@@ -0,0 +1,5 @@
+{
+ "operationName": null,
+ "variables": {},
+ "query": "{\n cdp {\n getProfileAliases(profileID: \"f6c1c5a0-eff3-42b7-b375-44da5d01f2a6\") {\n alias\n creationTime\n modifiedTime\n profileID {\n client {\n ID\n title\n }\n id\n }\n }\n }\n}\n"
+}
diff --git a/itests/src/test/resources/graphql/profileAlias/removeAliasFromProfile.json b/itests/src/test/resources/graphql/profileAlias/removeAliasFromProfile.json
new file mode 100644
index 0000000..915dba2
--- /dev/null
+++ b/itests/src/test/resources/graphql/profileAlias/removeAliasFromProfile.json
@@ -0,0 +1,13 @@
+{
+ "operationName": "removeAliasFromProfile",
+ "variables": {
+ "alias": "myAlias",
+ "profileID": {
+ "id": "f6c1c5a0-eff3-42b7-b375-44da5d01f2a6",
+ "client": {
+ "id": "facebook"
+ }
+ }
+ },
+ "query": "mutation removeAliasFromProfile($alias: ID!, $profileID: CDP_ProfileIDInput!) {\n cdp {\n removeAliasFromProfile(alias: $alias, profileID: $profileID) {\n alias\n creationTime\n modifiedTime\n profileID {\n id\n client {\n ID\n title\n }\n }\n }\n }\n}\n"
+}
diff --git a/persistence-elasticsearch/core/src/main/resources/META-INF/cxs/mappings/profileAlias.json b/persistence-elasticsearch/core/src/main/resources/META-INF/cxs/mappings/profileAlias.json
new file mode 100644
index 0000000..6d2f54d
--- /dev/null
+++ b/persistence-elasticsearch/core/src/main/resources/META-INF/cxs/mappings/profileAlias.json
@@ -0,0 +1,28 @@
+{
+ "dynamic_templates": [
+ {
+ "all": {
+ "match": "*",
+ "match_mapping_type": "string",
+ "mapping": {
+ "type": "text",
+ "analyzer": "folding",
+ "fields": {
+ "keyword": {
+ "type": "keyword",
+ "ignore_above": 256
+ }
+ }
+ }
+ }
+ }
+ ],
+ "properties": {
+ "creationTime": {
+ "type": "date"
+ },
+ "modifiedTime": {
+ "type": "date"
+ }
+ }
+}
diff --git a/rest/src/main/java/org/apache/unomi/rest/endpoints/ProfileServiceEndPoint.java b/rest/src/main/java/org/apache/unomi/rest/endpoints/ProfileServiceEndPoint.java
index db6aa93..86b50b7 100644
--- a/rest/src/main/java/org/apache/unomi/rest/endpoints/ProfileServiceEndPoint.java
+++ b/rest/src/main/java/org/apache/unomi/rest/endpoints/ProfileServiceEndPoint.java
@@ -622,4 +622,31 @@
public PartialList<Session> searchSession(Query query) {
return profileService.searchSessions(query);
}
+
+ @POST
+ @Path("/{profileId}/aliases/{aliasId}")
+ public void addAliasToProfile(final @PathParam("profileId") String profileId,
+ final @PathParam("aliasId") String aliasId,
+ final @HeaderParam("X-Unomi-ClientId") String headerClientID) {
+ String clientId = headerClientID != null ? headerClientID : "defaultClientId";
+ profileService.addAliasToProfile(profileId, aliasId, clientId);
+ }
+
+ @DELETE
+ @Path("/{profileId}/aliases/{aliasId}")
+ public void removeAliasFromProfile(final @PathParam("profileId") String profileId,
+ final @PathParam("aliasId") String aliasId,
+ final @HeaderParam("X-Unomi-ClientId") String headerClientID) {
+ String clientId = headerClientID != null ? headerClientID : "defaultClientId";
+ profileService.removeAliasFromProfile(profileId, aliasId, clientId);
+ }
+
+ @GET
+ @Path("/{profileId}/aliases")
+ public PartialList<ProfileAlias> listAliasesByProfileId(final @PathParam("profileId") String profileId,
+ @QueryParam("offset") @DefaultValue("0") int offset,
+ @QueryParam("size") @DefaultValue("50") int size,
+ @QueryParam("sort") String sortBy) {
+ return profileService.findProfileAliases(profileId, offset, size, sortBy);
+ }
}
diff --git a/services/src/main/java/org/apache/unomi/services/impl/profiles/ProfileServiceImpl.java b/services/src/main/java/org/apache/unomi/services/impl/profiles/ProfileServiceImpl.java
index 148a98d..4903074 100644
--- a/services/src/main/java/org/apache/unomi/services/impl/profiles/ProfileServiceImpl.java
+++ b/services/src/main/java/org/apache/unomi/services/impl/profiles/ProfileServiceImpl.java
@@ -581,6 +581,51 @@
}
}
+ @Override
+ public ProfileAlias removeAliasFromProfile(String profileID, String alias, String clientID) {
+ Condition profileIDCondition = new Condition(definitionsService.getConditionType("profileAliasesPropertyCondition"));
+ profileIDCondition.setParameter("propertyName", "profileID.keyword");
+ profileIDCondition.setParameter("comparisonOperator", "equals");
+ profileIDCondition.setParameter("propertyValue", profileID);
+
+ Condition clientIDCondition = new Condition(definitionsService.getConditionType("profileAliasesPropertyCondition"));
+ clientIDCondition.setParameter("propertyName", "clientID.keyword");
+ clientIDCondition.setParameter("comparisonOperator", "equals");
+ clientIDCondition.setParameter("propertyValue", clientID);
+
+ Condition aliasCondition = new Condition(definitionsService.getConditionType("profileAliasesPropertyCondition"));
+ aliasCondition.setParameter("propertyName", "itemId");
+ aliasCondition.setParameter("comparisonOperator", "equals");
+ aliasCondition.setParameter("propertyValue", alias);
+
+ List<Condition> conditions = new ArrayList<>();
+ conditions.add(profileIDCondition);
+ conditions.add(clientIDCondition);
+ conditions.add(aliasCondition);
+
+ Condition condition = new Condition(definitionsService.getConditionType("booleanCondition"));
+ condition.setParameter("operator", "and");
+ condition.setParameter("subConditions", conditions);
+
+ List<ProfileAlias> profileAliases = persistenceService.query(condition, null, ProfileAlias.class);
+
+ if (profileAliases.size() == 1 && persistenceService.removeByQuery(condition, ProfileAlias.class)) {
+ return profileAliases.get(0);
+ }
+
+ return null;
+ }
+
+ @Override
+ public PartialList<ProfileAlias> findProfileAliases(String profileId, int offset, int size, String sortBy) {
+ Condition condition = new Condition(definitionsService.getConditionType("profileAliasesPropertyCondition"));
+ condition.setParameter("propertyName", "profileID.keyword");
+ condition.setParameter("comparisonOperator", "equals");
+ condition.setParameter("propertyValue", profileId);
+
+ return persistenceService.query(condition, sortBy, ProfileAlias.class, offset, size);
+ }
+
private Profile save(Profile profile, boolean forceRefresh) {
if (profile.getItemId() == null) {
return null;