diff --git a/app-center-services/pom.xml b/app-center-services/pom.xml index abaee5d36..71c1f9426 100644 --- a/app-center-services/pom.xml +++ b/app-center-services/pom.xml @@ -1,19 +1,23 @@ App-center Rest Api 1.0 - App-center addon rest endpoints + App-center addon Rest endpoints - 0.72 + 0.71 - - org.exoplatform.core - exo.core.component.organization.api - - - org.exoplatform.gatein.portal - exo.portal.component.common - - - org.exoplatform.commons - commons-api - - - org.exoplatform.gatein.portal - exo.portal.component.file-storage - org.exoplatform.social - social-component-service - - - org.exoplatform.gatein.portal - exo.portal.component.identity - test - test-jar - - - org.exoplatform.gatein.portal - exo.portal.component.common - test - test-jar - - - junit - junit - test - - - org.mockito - mockito-core - test + social-component-core + - org.hsqldb - hsqldb + org.springframework.boot + spring-boot-starter-test test + + + com.vaadin.external.google + android-json + + - - - io.openapitools.swagger - swagger-maven-plugin - - true - - org.exoplatform.appcenter.rest - - - - ${rest.api.doc.title} - ${rest.api.doc.version} - ${rest.api.doc.description} - - https://www.gnu.org/licenses/lgpl-3.0.en.html - LGPL - - - - - - - org.apache.maven.plugins - maven-surefire-plugin - - - - exo.files.storage.dir - target/exo-files - - - - - + ${project.artifactId} diff --git a/app-center-services/src/main/java/io/meeds/appcenter/dao/ApplicationDAO.java b/app-center-services/src/main/java/io/meeds/appcenter/dao/ApplicationDAO.java new file mode 100644 index 000000000..00232e901 --- /dev/null +++ b/app-center-services/src/main/java/io/meeds/appcenter/dao/ApplicationDAO.java @@ -0,0 +1,66 @@ +/** + * This file is part of the Meeds project (https://meeds.io/). + * + * Copyright (C) 2020 - 2024 Meeds Association contact@meeds.io + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package io.meeds.appcenter.dao; + +import java.util.List; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.stereotype.Component; + +import io.meeds.appcenter.entity.ApplicationEntity; + +@Component +public interface ApplicationDAO extends JpaRepository { + + @Query(""" + SELECT app FROM ApplicationEntity app + WHERE app.active = TRUE + AND app.isMandatory = TRUE + """) + List getMandatoryActiveApps(); + + @Query(""" + SELECT app FROM ApplicationEntity app + ORDER BY LOWER(app.title) + """) + List getApplications(); + + @Query(""" + SELECT app FROM ApplicationEntity app + WHERE LOWER(app.title) LIKE ?1 + OR LOWER(app.description) like ?1 + OR LOWER(app.url) LIKE ?1 + ORDER BY LOWER(app.title) + """) + List getApplications(String keyword); + + @Query(""" + SELECT app FROM ApplicationEntity app + WHERE app.system = TRUE + """) + List getSystemApplications(); + + @Query(""" + SELECT app FROM ApplicationEntity app + WHERE app.title = ?1 + """) + ApplicationEntity getApplicationByTitle(String title); + +} diff --git a/app-center-services/src/main/java/io/meeds/appcenter/dao/FavoriteApplicationDAO.java b/app-center-services/src/main/java/io/meeds/appcenter/dao/FavoriteApplicationDAO.java new file mode 100644 index 000000000..d535bb550 --- /dev/null +++ b/app-center-services/src/main/java/io/meeds/appcenter/dao/FavoriteApplicationDAO.java @@ -0,0 +1,59 @@ +/** + * This file is part of the Meeds project (https://meeds.io/). + * + * Copyright (C) 2020 - 2024 Meeds Association contact@meeds.io + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package io.meeds.appcenter.dao; + +import java.util.List; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Modifying; +import org.springframework.data.jpa.repository.Query; +import org.springframework.transaction.annotation.Transactional; + +import io.meeds.appcenter.entity.FavoriteApplicationEntity; + +public interface FavoriteApplicationDAO extends JpaRepository { + + @Query(""" + SELECT favoriteApp FROM FavoriteApplicationEntity favoriteApp + WHERE favoriteApp.userName = ?1 + ORDER BY favoriteApp.order NULLS LAST + """) + List getFavoriteAppsByUser(String userName); + + @Query(""" + SELECT distinct(favoriteApp) FROM FavoriteApplicationEntity favoriteApp + WHERE favoriteApp.application.id = ?1 + AND favoriteApp.userName = ?2 + """) + FavoriteApplicationEntity getFavoriteAppByUserNameAndAppId(Long applicationId, String userName); + + @Query(""" + SELECT count(*) FROM FavoriteApplicationEntity favoriteApp + WHERE favoriteApp.userName = ?1 + """) + long countFavoritesForUser(String username); + + @Transactional + @Modifying(clearAutomatically = true, flushAutomatically = true) + @Query(""" + DELETE FROM FavoriteApplicationEntity favoriteApp + WHERE favoriteApp.application.id = ?1 + """) + void removeAllFavoritesOfApplication(Long applicationId); +} diff --git a/app-center-services/src/main/java/io/meeds/appcenter/entity/ApplicationEntity.java b/app-center-services/src/main/java/io/meeds/appcenter/entity/ApplicationEntity.java new file mode 100644 index 000000000..b1afb9f27 --- /dev/null +++ b/app-center-services/src/main/java/io/meeds/appcenter/entity/ApplicationEntity.java @@ -0,0 +1,97 @@ +/** + * This file is part of the Meeds project (https://meeds.io/). + * + * Copyright (C) 2020 - 2024 Meeds Association contact@meeds.io + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package io.meeds.appcenter.entity; + +import java.util.Collection; + +import jakarta.persistence.*; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@NoArgsConstructor +@AllArgsConstructor +@Entity(name = "ApplicationEntity") +@Table(name = "AC_APPLICATION") +public class ApplicationEntity { + + @Id + @SequenceGenerator(name = "SEQ_APPLICATION_ID", sequenceName = "SEQ_APPLICATION_ID", allocationSize = 1) + @GeneratedValue(strategy = GenerationType.AUTO, generator = "SEQ_APPLICATION_ID") + @Column(name = "ID") + private Long id; + + @Column(name = "TITLE") + private String title; + + @Column(name = "URL") + private String url; + + @Column(name = "HELP_PAGE_URL") + private String helpPageUrl; + + @Column(name = "IMAGE_FILE_ID") + private Long imageFileId; + + @Column(name = "DESCRIPTION") + private String description; + + @Column(name = "ACTIVE") + private boolean active; + + @Column(name = "BY_DEFAULT") + private boolean isMandatory; + + @Column(name = "IS_MOBILE") + private boolean isMobile; + + @Column(name = "IS_SYSTEM") + private boolean system; + + @Column(name = "PERMISSIONS") + private String permissions; + + @Column(name = "IS_CHANGED_MANUALLY") + private boolean isChangedManually; + + @OneToMany(fetch = FetchType.LAZY, mappedBy = "application", cascade = CascadeType.REMOVE) + private Collection favorites; + + public ApplicationEntity(Long id, // NOSONAR + String title, + String url, + Long imageFileId, + String description, + boolean active, + boolean isMandatory, + String permissions, + boolean isChangedManually) { + this.id = id; + this.title = title; + this.url = url; + this.imageFileId = imageFileId; + this.description = description; + this.active = active; + this.isMandatory = isMandatory; + this.permissions = permissions; + this.isChangedManually = isChangedManually; + } + +} diff --git a/app-center-services/src/main/java/io/meeds/appcenter/entity/FavoriteApplicationEntity.java b/app-center-services/src/main/java/io/meeds/appcenter/entity/FavoriteApplicationEntity.java new file mode 100644 index 000000000..f6dd141f8 --- /dev/null +++ b/app-center-services/src/main/java/io/meeds/appcenter/entity/FavoriteApplicationEntity.java @@ -0,0 +1,54 @@ +/** + * This file is part of the Meeds project (https://meeds.io/). + * + * Copyright (C) 2020 - 2024 Meeds Association contact@meeds.io + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package io.meeds.appcenter.entity; + +import jakarta.persistence.*; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Entity(name = "FavoriteApplicationEntity") +@Table(name = "AC_FAVORITE_APPLICATION") +@Data +@NoArgsConstructor +@AllArgsConstructor +public class FavoriteApplicationEntity { + + @Id + @SequenceGenerator(name = "SEQ_FAVORITE_APPLICATION_ID", sequenceName = "SEQFAVORITE_APPLICATION_ID", allocationSize = 1) + @GeneratedValue(strategy = GenerationType.AUTO, generator = "SEQ_FAVORITE_APPLICATION_ID") + @Column(name = "ID") + private Long id; + + @ManyToOne(fetch = FetchType.EAGER) + @JoinColumn(name = "APPLICATION_ID") + private ApplicationEntity application; + + @Column(name = "USER_NAME") + private String userName; + + @Column(name = "APPLICATION_ORDER") + private Long order; + + public FavoriteApplicationEntity(ApplicationEntity application, String userName) { + this.application = application; + this.userName = userName; + } + +} diff --git a/app-center-services/src/main/java/io/meeds/appcenter/model/Application.java b/app-center-services/src/main/java/io/meeds/appcenter/model/Application.java new file mode 100644 index 000000000..73f9c8bf8 --- /dev/null +++ b/app-center-services/src/main/java/io/meeds/appcenter/model/Application.java @@ -0,0 +1,128 @@ +/** + * This file is part of the Meeds project (https://meeds.io/). + * + * Copyright (C) 2020 - 2024 Meeds Association contact@meeds.io + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package io.meeds.appcenter.model; + +import java.util.Arrays; +import java.util.List; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@NoArgsConstructor +@AllArgsConstructor +public class Application { + + private Long id; + + private String title; + + private String url; + + private String helpPageURL; + + private String description; + + private boolean active; + + private boolean isMandatory; + + private boolean isMobile; + + private boolean system; + + private List permissions; + + private String imageFileBody; + + private String imageFileName; + + private Long imageFileId; + + private Long imageLastModified; + + private Long order; + + private boolean isChangedManually; + + public Application(Long id, // NOSONAR + String title, + String url, + String helpPageURL, + Long imageFileId, + Long imageLastModified, + String imageFileBody, + String imageFileName, + String description, + boolean isSystem, + boolean active, + boolean isMandatory, + boolean isMobile, + boolean isChangedManually, + String... permissions) { + this(id, + title, + url, + helpPageURL, + imageFileId, + imageLastModified, + imageFileBody, + imageFileName, + description, + isSystem, + active, + isMandatory, + isMobile, + isChangedManually, + permissions == null ? null : Arrays.asList(permissions)); + } + + public Application(Long id, // NOSONAR + String title, + String url, + String helpPageURL, + Long imageFileId, + Long imageLastModified, + String imageFileBody, + String imageFileName, + String description, + boolean isSystem, + boolean active, + boolean isMandatory, + boolean isMobile, + boolean isChangedManually, + List permissions) { + this.id = id; + this.title = title; + this.url = url; + this.helpPageURL = helpPageURL; + this.description = description; + this.active = active; + this.isMandatory = isMandatory; + this.isMobile = isMobile; + this.system = isSystem; + this.permissions = permissions; + this.imageFileId = imageFileId; + this.imageLastModified = imageLastModified; + this.imageFileBody = imageFileBody; + this.imageFileName = imageFileName; + this.isChangedManually = isChangedManually; + } +} diff --git a/app-center-services/src/main/java/io/meeds/appcenter/model/ApplicationDescriptor.java b/app-center-services/src/main/java/io/meeds/appcenter/model/ApplicationDescriptor.java new file mode 100644 index 000000000..2f3d36cea --- /dev/null +++ b/app-center-services/src/main/java/io/meeds/appcenter/model/ApplicationDescriptor.java @@ -0,0 +1,47 @@ +/** + * This file is part of the Meeds project (https://meeds.io/). + * + * Copyright (C) 2020 - 2024 Meeds Association contact@meeds.io + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package io.meeds.appcenter.model; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@NoArgsConstructor +@AllArgsConstructor +public class ApplicationDescriptor { + + private String name; + + private Application application; + + private String imagePath; + + private String overrideMode; + + private boolean override; + + private boolean enabled; + + public ApplicationDescriptor(String name, Application application) { + this.name = name; + this.application = application; + } + +} diff --git a/app-center-services/src/main/java/io/meeds/appcenter/model/ApplicationDescriptorList.java b/app-center-services/src/main/java/io/meeds/appcenter/model/ApplicationDescriptorList.java new file mode 100644 index 000000000..095ddb7b0 --- /dev/null +++ b/app-center-services/src/main/java/io/meeds/appcenter/model/ApplicationDescriptorList.java @@ -0,0 +1,34 @@ +/** + * This file is part of the Meeds project (https://meeds.io/). + * + * Copyright (C) 2020 - 2024 Meeds Association contact@meeds.io + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package io.meeds.appcenter.model; + +import java.util.List; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@NoArgsConstructor +@AllArgsConstructor +public class ApplicationDescriptorList { + + private List descriptors; + +} diff --git a/app-center-services/src/main/java/org/exoplatform/appcenter/dto/ApplicationImage.java b/app-center-services/src/main/java/io/meeds/appcenter/model/ApplicationImage.java similarity index 88% rename from app-center-services/src/main/java/org/exoplatform/appcenter/dto/ApplicationImage.java rename to app-center-services/src/main/java/io/meeds/appcenter/model/ApplicationImage.java index ddb8177f3..63a9e9341 100644 --- a/app-center-services/src/main/java/org/exoplatform/appcenter/dto/ApplicationImage.java +++ b/app-center-services/src/main/java/io/meeds/appcenter/model/ApplicationImage.java @@ -1,26 +1,25 @@ -/* +/** * This file is part of the Meeds project (https://meeds.io/). - * Copyright (C) 2020 Meeds Association - * contact@meeds.io + * + * Copyright (C) 2020 - 2024 Meeds Association contact@meeds.io * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 3 of the License, or (at your option) any later version. + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. + * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -package org.exoplatform.appcenter.dto; +package io.meeds.appcenter.model; import java.io.Serializable; -/** - * @author Ayoub Zayati - */ public class ApplicationImage implements Serializable { private static final long serialVersionUID = -2001197615359890089L; diff --git a/app-center-services/src/main/java/org/exoplatform/appcenter/dto/ApplicationList.java b/app-center-services/src/main/java/io/meeds/appcenter/model/ApplicationList.java similarity index 80% rename from app-center-services/src/main/java/org/exoplatform/appcenter/dto/ApplicationList.java rename to app-center-services/src/main/java/io/meeds/appcenter/model/ApplicationList.java index e2daac7ef..e5439ebbc 100644 --- a/app-center-services/src/main/java/org/exoplatform/appcenter/dto/ApplicationList.java +++ b/app-center-services/src/main/java/io/meeds/appcenter/model/ApplicationList.java @@ -1,27 +1,26 @@ -/* +/** * This file is part of the Meeds project (https://meeds.io/). - * Copyright (C) 2020 Meeds Association - * contact@meeds.io + * + * Copyright (C) 2020 - 2024 Meeds Association contact@meeds.io * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 3 of the License, or (at your option) any later version. + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. + * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -package org.exoplatform.appcenter.dto; +package io.meeds.appcenter.model; -import java.io.Serializable; import java.util.List; -public class ApplicationList implements Serializable { - - private static final long serialVersionUID = 8955981782215121831L; +public class ApplicationList { private List applications; diff --git a/app-center-services/src/main/java/io/meeds/appcenter/model/ApplicationOrder.java b/app-center-services/src/main/java/io/meeds/appcenter/model/ApplicationOrder.java new file mode 100644 index 000000000..0a13420a4 --- /dev/null +++ b/app-center-services/src/main/java/io/meeds/appcenter/model/ApplicationOrder.java @@ -0,0 +1,34 @@ +/** + * This file is part of the Meeds project (https://meeds.io/). + * + * Copyright (C) 2020 - 2024 Meeds Association contact@meeds.io + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package io.meeds.appcenter.model; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@NoArgsConstructor +@AllArgsConstructor +public class ApplicationOrder { + + private Long id; + + private Long order; + +} diff --git a/app-center-services/src/main/java/io/meeds/appcenter/model/GeneralSettings.java b/app-center-services/src/main/java/io/meeds/appcenter/model/GeneralSettings.java new file mode 100644 index 000000000..1d7afc88c --- /dev/null +++ b/app-center-services/src/main/java/io/meeds/appcenter/model/GeneralSettings.java @@ -0,0 +1,34 @@ +/** + * This file is part of the Meeds project (https://meeds.io/). + * + * Copyright (C) 2020 - 2024 Meeds Association contact@meeds.io + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package io.meeds.appcenter.model; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@NoArgsConstructor +@AllArgsConstructor +public class GeneralSettings { + + private long maxFavoriteApps; + + private ApplicationImage defaultApplicationImage; + +} diff --git a/app-center-services/src/main/java/org/exoplatform/appcenter/dto/UserApplication.java b/app-center-services/src/main/java/io/meeds/appcenter/model/UserApplication.java similarity index 81% rename from app-center-services/src/main/java/org/exoplatform/appcenter/dto/UserApplication.java rename to app-center-services/src/main/java/io/meeds/appcenter/model/UserApplication.java index ca9cb6f52..a29b0c0f2 100644 --- a/app-center-services/src/main/java/org/exoplatform/appcenter/dto/UserApplication.java +++ b/app-center-services/src/main/java/io/meeds/appcenter/model/UserApplication.java @@ -1,26 +1,35 @@ -/* +/** * This file is part of the Meeds project (https://meeds.io/). - * Copyright (C) 2020 Meeds Association - * contact@meeds.io + * + * Copyright (C) 2020 - 2024 Meeds Association contact@meeds.io * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 3 of the License, or (at your option) any later version. + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. + * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -package org.exoplatform.appcenter.dto; +package io.meeds.appcenter.model; -public class UserApplication extends Application { +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; - private static final long serialVersionUID = -2451635329141517005L; +@Data +@EqualsAndHashCode(callSuper = true) +@NoArgsConstructor +@AllArgsConstructor +public class UserApplication extends Application { - private boolean favorite; + private boolean favorite; public UserApplication(Application app) { super(app.getId(), @@ -40,7 +49,7 @@ public UserApplication(Application app) { app.getPermissions()); } - public UserApplication(Long id, + public UserApplication(Long id, // NOSONAR String title, String url, String helpPageURL, @@ -74,11 +83,4 @@ public UserApplication(Long id, this.favorite = favorite; } - public boolean isFavorite() { - return favorite; - } - - public void setFavorite(boolean favorite) { - this.favorite = favorite; - } } diff --git a/app-center-services/src/main/java/org/exoplatform/appcenter/service/ApplicationAlreadyExistsException.java b/app-center-services/src/main/java/io/meeds/appcenter/model/exception/ApplicationAlreadyExistsException.java similarity index 79% rename from app-center-services/src/main/java/org/exoplatform/appcenter/service/ApplicationAlreadyExistsException.java rename to app-center-services/src/main/java/io/meeds/appcenter/model/exception/ApplicationAlreadyExistsException.java index 8ad044102..c35fb73d1 100644 --- a/app-center-services/src/main/java/org/exoplatform/appcenter/service/ApplicationAlreadyExistsException.java +++ b/app-center-services/src/main/java/io/meeds/appcenter/model/exception/ApplicationAlreadyExistsException.java @@ -1,20 +1,22 @@ -/* +/** * This file is part of the Meeds project (https://meeds.io/). - * Copyright (C) 2020 Meeds Association - * contact@meeds.io + * + * Copyright (C) 2020 - 2024 Meeds Association contact@meeds.io * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 3 of the License, or (at your option) any later version. + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. + * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -package org.exoplatform.appcenter.service; +package io.meeds.appcenter.model.exception; public class ApplicationAlreadyExistsException extends Exception { diff --git a/app-center-services/src/main/java/org/exoplatform/appcenter/service/ApplicationNotFoundException.java b/app-center-services/src/main/java/io/meeds/appcenter/model/exception/ApplicationNotFoundException.java similarity index 79% rename from app-center-services/src/main/java/org/exoplatform/appcenter/service/ApplicationNotFoundException.java rename to app-center-services/src/main/java/io/meeds/appcenter/model/exception/ApplicationNotFoundException.java index bdfa3caf2..422c2b282 100644 --- a/app-center-services/src/main/java/org/exoplatform/appcenter/service/ApplicationNotFoundException.java +++ b/app-center-services/src/main/java/io/meeds/appcenter/model/exception/ApplicationNotFoundException.java @@ -1,20 +1,22 @@ -/* +/** * This file is part of the Meeds project (https://meeds.io/). - * Copyright (C) 2020 Meeds Association - * contact@meeds.io + * + * Copyright (C) 2020 - 2024 Meeds Association contact@meeds.io * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 3 of the License, or (at your option) any later version. + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. + * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -package org.exoplatform.appcenter.service; +package io.meeds.appcenter.model.exception; public class ApplicationNotFoundException extends Exception { diff --git a/app-center-services/src/main/java/io/meeds/appcenter/rest/ApplicationFavoriteRest.java b/app-center-services/src/main/java/io/meeds/appcenter/rest/ApplicationFavoriteRest.java new file mode 100644 index 000000000..41e375ad0 --- /dev/null +++ b/app-center-services/src/main/java/io/meeds/appcenter/rest/ApplicationFavoriteRest.java @@ -0,0 +1,130 @@ +/** + * This file is part of the Meeds project (https://meeds.io/). + * + * Copyright (C) 2020 - 2024 Meeds Association contact@meeds.io + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package io.meeds.appcenter.rest; + +import java.util.List; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.security.access.annotation.Secured; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.server.ResponseStatusException; + +import io.meeds.appcenter.model.ApplicationList; +import io.meeds.appcenter.model.ApplicationOrder; +import io.meeds.appcenter.model.exception.ApplicationNotFoundException; +import io.meeds.appcenter.service.ApplicationCenterService; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.responses.ApiResponses; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.servlet.http.HttpServletRequest; + +@RestController +@RequestMapping("favorites") +@Tag(name = "/app-center/rest/favorites", description = "Manage and access application center applications") // NOSONAR +public class ApplicationFavoriteRest { + + @Autowired + private ApplicationCenterService appCenterService; + + @GetMapping + @Secured("users") + @Operation( + summary = "Retrieves favorite applications for currently authenticated user", + method = "GET", + description = "Return list of applications in json format") + @ApiResponses(value = { @ApiResponse(responseCode = "200", description = "Request fulfilled"), + @ApiResponse(responseCode = "500", description = "Internal server error") }) + public ApplicationList getFavoriteApplicationsList(HttpServletRequest request) { + return appCenterService.getMandatoryAndFavoriteApplicationsList(request.getRemoteUser()); + } + + @PostMapping(path = "{applicationId}") + @Secured("users") + @Operation( + summary = "Adds an existing application identified by its id as favorite for current authenticated user", + method = "POST", + description = "Adds an existing application identified by its id as favorite for current authenticated user") + @ApiResponses(value = { @ApiResponse(responseCode = "204", description = "Request fulfilled"), + @ApiResponse(responseCode = "500", description = "Internal server error") }) + public void addFavoriteApplication( + HttpServletRequest request, + @Parameter(description = "Application technical id to add as favorite", required = true) + @PathVariable("applicationId") + Long applicationId) { + try { + appCenterService.addFavoriteApplication(applicationId, request.getRemoteUser()); + } catch (ApplicationNotFoundException e) { + throw new ResponseStatusException(HttpStatus.NOT_FOUND, e.getMessage()); + } catch (IllegalAccessException e) { + throw new ResponseStatusException(HttpStatus.FORBIDDEN, e.getMessage()); + } + } + + @PutMapping(consumes = MediaType.APPLICATION_JSON_VALUE) + @Secured("users") + @Operation( + summary = "Updates an existing application's order identified by its id", + method = "PUT", + description = "Updates an existing application's order identified by its id and returns an empty response") + @ApiResponses(value = { @ApiResponse(responseCode = "204", description = "Request fulfilled"), + @ApiResponse(responseCode = "401", description = "Unauthorized operation"), + @ApiResponse(responseCode = "500", description = "Internal server error") }) + public void updateApplicationsOrder( + HttpServletRequest request, + @RequestBody(required = true) + List applicationOrders) { + try { + for (ApplicationOrder applicationOrder : applicationOrders) { + appCenterService.updateFavoriteApplicationOrder(applicationOrder, request.getRemoteUser()); + } + } catch (ApplicationNotFoundException e) { + throw new ResponseStatusException(HttpStatus.NOT_FOUND, e.getMessage()); + } + } + + @DeleteMapping(path = "{applicationId}") + @Secured("users") + @Operation( + summary = "Deletes an existing application identified by its id from current authenticated user favorites", + method = "GET", + description = "Deletes an existing application identified by its id from current authenticated user favorites and returns an empty response") + @ApiResponses(value = { @ApiResponse(responseCode = "204", description = "Request fulfilled"), + @ApiResponse(responseCode = "500", description = "Internal server error") }) + public void deleteFavoriteApplication( + HttpServletRequest request, + @Parameter(description = "Application technical id to delete from favorite", + required = true) + @PathVariable("applicationId") + Long applicationId) { + appCenterService.deleteFavoriteApplication(applicationId, request.getRemoteUser()); + } + +} diff --git a/app-center-services/src/main/java/io/meeds/appcenter/rest/ApplicationRest.java b/app-center-services/src/main/java/io/meeds/appcenter/rest/ApplicationRest.java new file mode 100644 index 000000000..43a1063e0 --- /dev/null +++ b/app-center-services/src/main/java/io/meeds/appcenter/rest/ApplicationRest.java @@ -0,0 +1,234 @@ +/** + * This file is part of the Meeds project (https://meeds.io/). + * + * Copyright (C) 2020 - 2024 Meeds Association contact@meeds.io + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package io.meeds.appcenter.rest; + +import java.io.InputStream; +import java.time.Duration; +import java.util.Objects; +import java.util.Optional; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.core.io.InputStreamResource; +import org.springframework.http.CacheControl; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.http.ResponseEntity.BodyBuilder; +import org.springframework.security.access.annotation.Secured; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.server.ResponseStatusException; + +import io.meeds.appcenter.model.Application; +import io.meeds.appcenter.model.ApplicationList; +import io.meeds.appcenter.model.exception.ApplicationAlreadyExistsException; +import io.meeds.appcenter.model.exception.ApplicationNotFoundException; +import io.meeds.appcenter.service.ApplicationCenterService; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.responses.ApiResponses; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.servlet.http.HttpServletRequest; + +@RestController +@RequestMapping("applications") +@Tag(name = "/app-center/rest/applications", description = "Manage and access application center applications") // NOSONAR +public class ApplicationRest { + + @Autowired + private ApplicationCenterService appCenterService; + + @GetMapping + @Secured("users") + @Operation( + summary = "Retrieves all authorized applications for currently authenticated user", + method = "GET", + description = "Return list of applications in json format") + @ApiResponses(value = { @ApiResponse(responseCode = "200", description = "Request fulfilled"), + @ApiResponse(responseCode = "500", description = "Internal server error") }) + public ApplicationList getActiveApplications( + HttpServletRequest request, + @Parameter(description = "Query Offset", required = true) + @RequestParam("offset") + Optional offset, + @Parameter(description = "Query results limit", required = true) + @RequestParam("limit") + Optional limit, + @Parameter(description = "Keyword to search in applications title and url", + required = false) + @RequestParam("keyword") + Optional keyword) { + return appCenterService.getActiveApplications(offset.orElse(0), + limit.orElse(0), + keyword.orElse(null), + request.getRemoteUser()); + } + + @GetMapping(path = "all") + @Secured("administrators") + @Operation( + summary = "Retrieves all available applications", + method = "GET", + description = "Return list of applications in json format") + @ApiResponses(value = { @ApiResponse(responseCode = "200", description = "Request fulfilled"), + @ApiResponse(responseCode = "500", description = "Internal server error") }) + public ApplicationList getApplications( + @Parameter(description = "Query Offset", required = true) + @RequestParam("offset") + Optional offset, + @Parameter(description = "Query results limit", required = true) + @RequestParam("limit") + Optional limit, + @Parameter(description = "Keyword to search in applications title and url", + required = true) + @RequestParam("keyword") + Optional keyword) { + return appCenterService.getApplications(offset.orElse(0), limit.orElse(0), keyword.orElse(null)); + } + + @PostMapping + @Secured("administrators") + @Operation( + summary = "Creates a new application in application center", + method = "GET", + description = "Creates a new application in application center and returns an empty response") + @ApiResponses(value = { @ApiResponse(responseCode = "200", description = "Request fulfilled"), + @ApiResponse(responseCode = "400", description = "Bad Request"), + @ApiResponse(responseCode = "401", description = "Unauthorized operation"), + @ApiResponse(responseCode = "409", description = "Conflict") }) + public Application createApplication( + HttpServletRequest request, + @RequestBody + Application application) { + try { + return appCenterService.createApplication(application, request.getRemoteUser()); + } catch (IllegalAccessException e) { + throw new ResponseStatusException(HttpStatus.UNAUTHORIZED); + } catch (IllegalArgumentException e) { + throw new ResponseStatusException(HttpStatus.BAD_REQUEST, e.getMessage()); + } catch (ApplicationAlreadyExistsException e) { + throw new ResponseStatusException(HttpStatus.CONFLICT, e.getMessage()); + } + } + + @PutMapping + @Secured("administrators") + @Operation( + summary = "Updates an existing application identified by its id or title or url", + method = "GET", + description = "Updates an existing application identified by its id or title or url") + @ApiResponses(value = { @ApiResponse(responseCode = "204", description = "Request fulfilled"), + @ApiResponse(responseCode = "401", description = "Unauthorized operation"), + @ApiResponse(responseCode = "500", description = "Internal server error") }) + public void updateApplication( + HttpServletRequest request, + @RequestBody + Application application) { + try { + application.setChangedManually(true); + appCenterService.updateApplication(application, request.getRemoteUser()); + } catch (IllegalAccessException e) { + throw new ResponseStatusException(HttpStatus.UNAUTHORIZED); + } catch (ApplicationNotFoundException e) { + throw new ResponseStatusException(HttpStatus.NOT_FOUND); + } catch (IllegalArgumentException e) { + throw new ResponseStatusException(HttpStatus.BAD_REQUEST, e.getMessage()); + } + } + + @DeleteMapping(path = "{applicationId}") + @Secured("administrators") + @Operation( + summary = "Deletes an existing application identified by its id", + method = "GET", + description = "Deletes an existing application identified by its id") + @ApiResponses(value = { @ApiResponse(responseCode = "204", description = "Request fulfilled"), + @ApiResponse(responseCode = "401", description = "Unauthorized operation"), + @ApiResponse(responseCode = "500", description = "Internal server error") }) + public void deleteApplication( + HttpServletRequest request, + @Parameter(description = "Application technical id to delete", required = true) + @PathVariable("applicationId") + Long applicationId) { + try { + appCenterService.deleteApplication(applicationId, request.getRemoteUser()); + } catch (IllegalAccessException e) { + throw new ResponseStatusException(HttpStatus.UNAUTHORIZED); + } catch (ApplicationNotFoundException e) { + throw new ResponseStatusException(HttpStatus.NOT_FOUND); + } catch (IllegalArgumentException e) { + throw new ResponseStatusException(HttpStatus.BAD_REQUEST, e.getMessage()); + } + } + + @GetMapping(path = "/illustration/{applicationId}") + @Secured("users") + @Operation( + summary = "Gets an application illustration by application id", + method = "GET", + description = "This can only be done by the logged in user.") + @ApiResponses(value = { @ApiResponse(responseCode = "200", description = "Request fulfilled"), + @ApiResponse(responseCode = "500", description = "Internal server error"), + @ApiResponse(responseCode = "400", description = "Invalid query input"), + @ApiResponse(responseCode = "404", description = "Resource not found") }) + public ResponseEntity getApplicationIllustration( + HttpServletRequest request, + @Parameter(description = "Application id", + required = true) + @PathVariable("applicationId") + long applicationId, + @Parameter(description = "Last modified parameter", + required = false) + @RequestParam(name = "v", required = false) + Optional lastModified) { + try { + InputStream stream = appCenterService.getApplicationImageInputStream(applicationId, request.getRemoteUser()); + if (stream == null) { + throw new ResponseStatusException(HttpStatus.NOT_FOUND); + } + Long lastUpdated = appCenterService.getApplicationImageLastUpdated(applicationId, request.getRemoteUser()); + BodyBuilder builder = ResponseEntity.ok(); + if (lastModified.isPresent()) { + builder.lastModified(lastUpdated) + .eTag(String.valueOf(Objects.hash(lastUpdated))) + .cacheControl(CacheControl.maxAge(Duration.ofDays(365)).cachePublic()); + } else { + builder.cacheControl(CacheControl.noStore()); + } + return builder.contentType(MediaType.IMAGE_PNG) + .body(new InputStreamResource(stream)); + } catch (IllegalAccessException e) { + throw new ResponseStatusException(HttpStatus.UNAUTHORIZED); + } catch (ApplicationNotFoundException e) { + throw new ResponseStatusException(HttpStatus.NOT_FOUND); + } catch (IllegalArgumentException e) { + throw new ResponseStatusException(HttpStatus.BAD_REQUEST, e.getMessage()); + } + } + +} diff --git a/app-center-services/src/main/java/io/meeds/appcenter/rest/ApplicationSettingsRest.java b/app-center-services/src/main/java/io/meeds/appcenter/rest/ApplicationSettingsRest.java new file mode 100644 index 000000000..59a89e9dc --- /dev/null +++ b/app-center-services/src/main/java/io/meeds/appcenter/rest/ApplicationSettingsRest.java @@ -0,0 +1,90 @@ +/** + * This file is part of the Meeds project (https://meeds.io/). + * + * Copyright (C) 2020 - 2024 Meeds Association contact@meeds.io + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package io.meeds.appcenter.rest; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.access.annotation.Secured; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PatchMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +import io.meeds.appcenter.model.ApplicationImage; +import io.meeds.appcenter.model.GeneralSettings; +import io.meeds.appcenter.service.ApplicationCenterService; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.responses.ApiResponses; +import io.swagger.v3.oas.annotations.tags.Tag; + +@RestController +@RequestMapping("settings") +@Tag(name = "/app-center/rest/settings", description = "Manage and access application center applications") // NOSONAR +public class ApplicationSettingsRest { + + @Autowired + private ApplicationCenterService appCenterService; + + @GetMapping + @Secured("users") + @Operation( + summary = "Modifies default application image setting", + method = "GET", + description = "Modifies default application image setting and returns an empty response") + @ApiResponses(value = { @ApiResponse(responseCode = "204", description = "Request fulfilled"), + @ApiResponse(responseCode = "500", description = "Internal server error") }) + public GeneralSettings getSettings() { + return appCenterService.getSettings(); + } + + @PatchMapping(path = "maxFavorites") + @Secured("administrators") + @Operation( + summary = "Modifies maximum application count to add as favorites for all users", + method = "PATCH", + description = "Modifies maximum application count to add as favorites for all users") + @ApiResponses(value = { @ApiResponse(responseCode = "204", description = "Request fulfilled"), + @ApiResponse(responseCode = "500", description = "Internal server error") }) + public void setMaxFavoriteApps( + @Parameter(description = "Max favorites number", required = true) + @RequestParam("number") + long number) { + appCenterService.setMaxFavoriteApps(number); + } + + @PatchMapping(path = "image") + @Secured("administrators") + @Operation( + summary = "Modifies default application image setting", + method = "PATCH", + description = "Modifies default application image setting") + @ApiResponses(value = { @ApiResponse(responseCode = "204", description = "Request fulfilled"), + @ApiResponse(responseCode = "500", description = "Internal server error") }) + public void setDefaultAppImage( + @Parameter(description = "Application image id, body and name", required = true) + @RequestBody + ApplicationImage defaultAppImage) { + appCenterService.setDefaultAppImage(defaultAppImage); + } + +} diff --git a/app-center-services/src/main/java/io/meeds/appcenter/service/ApplicationCenterInjectService.java b/app-center-services/src/main/java/io/meeds/appcenter/service/ApplicationCenterInjectService.java new file mode 100644 index 000000000..94f9b68ed --- /dev/null +++ b/app-center-services/src/main/java/io/meeds/appcenter/service/ApplicationCenterInjectService.java @@ -0,0 +1,286 @@ +/** + * This file is part of the Meeds project (https://meeds.io/). + * + * Copyright (C) 2020 - 2024 Meeds Association contact@meeds.io + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package io.meeds.appcenter.service; + +import java.io.IOException; +import java.io.InputStream; +import java.net.URL; +import java.nio.charset.StandardCharsets; +import java.util.Base64; +import java.util.Collections; +import java.util.Enumeration; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.TimeZone; +import java.util.concurrent.CompletableFuture; + +import org.apache.commons.io.IOUtils; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import com.fasterxml.jackson.annotation.JsonAutoDetect; +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.SerializationFeature; +import com.fasterxml.jackson.databind.introspect.VisibilityChecker; +import com.fasterxml.jackson.databind.util.StdDateFormat; +import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; + +import org.exoplatform.container.configuration.ConfigurationManager; +import org.exoplatform.container.xml.ComponentPlugin; +import org.exoplatform.services.log.ExoLogger; +import org.exoplatform.services.log.Log; + +import io.meeds.appcenter.model.Application; +import io.meeds.appcenter.model.ApplicationDescriptor; +import io.meeds.appcenter.model.ApplicationDescriptorList; +import io.meeds.common.ContainerTransactional; + +import jakarta.annotation.PostConstruct; +import lombok.Getter; +import lombok.SneakyThrows; + +/** + * A Service to access and store applications + */ +@Component +public class ApplicationCenterInjectService { + + private static final Log LOG = + ExoLogger.getLogger(ApplicationCenterInjectService.class); + + public static final ObjectMapper OBJECT_MAPPER = new ObjectMapper(); + + static { + // Workaround when Jackson is defined in shared library with different + // version and without artifact jackson-datatype-jsr310 + OBJECT_MAPPER.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); + OBJECT_MAPPER.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES); + OBJECT_MAPPER.setVisibility(VisibilityChecker.Std.defaultInstance().withFieldVisibility(JsonAutoDetect.Visibility.ANY)); + OBJECT_MAPPER.registerModule(new JavaTimeModule()); + OBJECT_MAPPER.setDateFormat(new StdDateFormat().withTimeZone(TimeZone.getTimeZone("UTC"))); + } + + private static final String DEFAULT_USERS_GROUP = "/platform/users"; + + private static final String DEFAULT_USERS_PERMISSION = "*:" + DEFAULT_USERS_GROUP; + + private static final String MERGE_MODE = "merge"; + + @Autowired + private ConfigurationManager configurationManager; + + @Autowired + private ApplicationCenterService applicationCenterService; + + @Getter + private Map defaultApplications = new LinkedHashMap<>(); + + @PostConstruct + public void init() { + CompletableFuture.runAsync(this::initTransactional); + } + + @ContainerTransactional + public void initTransactional() { + injectDefaultApplications(); + } + + /** + * Inject a default application using IOC {@link ComponentPlugin} using + * configuration + * + * @param applicationPlugin plugin containing application to inject + */ + public void addApplicationPlugin(ApplicationDescriptor applicationPlugin) { + if (applicationPlugin == null) { + throw new IllegalArgumentException("'applicationPlugin' is mandatory"); + } + if (StringUtils.isBlank(applicationPlugin.getName())) { + throw new IllegalStateException("'applicationPlugin' name is mandatory"); + } + this.defaultApplications.put(applicationPlugin.getName(), applicationPlugin); + } + + /** + * Delete an injected plugin identified by its name + * + * @param pluginName plugin name to delete + */ + public void removeApplicationPlugin(String pluginName) { + if (StringUtils.isBlank(pluginName)) { + throw new IllegalArgumentException("'pluginName' is mandatory"); + } + this.defaultApplications.remove(pluginName); + } + + /** + * Checks whether the application is a system application injected by + * configuration or not + * + * @param application application to check its state + * @return true if the configuration of the application exists with same title + * and URL, else false. + */ + public boolean isDefaultSystemApplication(Application application) { + if (application == null) { + throw new IllegalArgumentException("'application' is mandatory"); + } + return this.defaultApplications.values() + .stream() + .filter(ApplicationDescriptor::isEnabled) + .anyMatch(app -> StringUtils.equals(app.getApplication().getTitle(), application.getTitle()) + && StringUtils.equals(app.getApplication().getUrl(), application.getUrl())); + } + + protected void injectDefaultApplications() { + try { + readDescriptorsFromFiles(); + deleteRemovedSystemApplications(); + defaultApplications.values() + .stream() + .filter(ApplicationDescriptor::isEnabled) + .forEach(this::injectDefaultApplication); + } catch (Exception e) { + LOG.warn("An unknown error occurs while retrieving system applications images", e); + } + } + + private void readDescriptorsFromFiles() throws IOException { + Enumeration descriptorFiles = getClass().getClassLoader() + .getResources("applications.json"); + Collections.list(descriptorFiles) + .stream() + .map(this::parseDescriptors) + .flatMap(List::stream) + .forEach(d -> defaultApplications.put(d.getName(), d)); + } + + private List parseDescriptors(URL url) { + try (InputStream inputStream = url.openStream()) { + String content = IOUtils.toString(inputStream, StandardCharsets.UTF_8); + ApplicationDescriptorList list = fromJsonString(content, ApplicationDescriptorList.class); + return list.getDescriptors(); + } catch (IOException e) { + LOG.warn("An unkown error happened while parsing application descriptors from url {}", url, e); + return Collections.emptyList(); + } + } + + private void deleteRemovedSystemApplications() { + List systemApplications = applicationCenterService.getSystemApplications(); + systemApplications.forEach(application -> { + if (!isDefaultSystemApplication(application)) { + try { + LOG.info("Delete application '{}' that was previously injected as system application and that doesn't exist in configuration anymore", + application.getTitle()); + applicationCenterService.deleteApplication(application.getId()); + } catch (Exception e) { + LOG.warn("An unknown error occurs while deleting not found system application '{}' in store", + application.getTitle(), + e); + } + } + }); + } + + private void injectDefaultApplication(ApplicationDescriptor applicationPlugin) { // NOSONAR + Application application = applicationPlugin.getApplication(); + String pluginName = applicationPlugin.getName(); + if (application == null) { + LOG.warn("An application plugin '{}' holds an empty application", pluginName); + return; + } + + String title = application.getTitle(); + if (StringUtils.isBlank(title)) { + LOG.warn("Plugin '{}' has an application with empty title, it will not be injected", pluginName); + return; + } + + String url = application.getUrl(); + if (StringUtils.isBlank(url)) { + LOG.warn("Plugin '{}' has an application with empty url, it will not be injected", pluginName); + return; + } + + Application storedApplication = applicationCenterService.getApplicationByTitle(title); + if (storedApplication != null && !applicationPlugin.isOverride() + && storedApplication.isChangedManually() + && (MERGE_MODE.equals(applicationPlugin.getOverrideMode()) || applicationPlugin.getOverrideMode() == null)) { + LOG.info("Ignore updating system application '{}', override flag is turned off", application.getTitle()); + return; + } + + List permissions = application.getPermissions(); + if (permissions == null || permissions.isEmpty()) { + // Set default permission if empty + application.setPermissions(Collections.singletonList(DEFAULT_USERS_PERMISSION)); + } + + String imagePath = applicationPlugin.getImagePath(); + if (StringUtils.isNotBlank(imagePath)) { + try { + InputStream inputStream = configurationManager.getInputStream(imagePath); + String fileBody = new String(Base64.getEncoder().encode(IOUtils.toByteArray(inputStream))); + application.setImageFileBody(fileBody); + } catch (Exception e) { + LOG.warn("Error reading image from file {}. Application will be injected without image", imagePath, e); + } + } + + if (StringUtils.isBlank(application.getImageFileName())) { + application.setImageFileName(application.getTitle() + ".png"); + } + + if (storedApplication == null) { + try { + LOG.info("Create system application '{}'", application.getTitle()); + application.setSystem(true); + application.setChangedManually(false); + application.setImageFileId(null); + applicationCenterService.createApplication(application); + } catch (Exception e) { + LOG.error("Error creating application {}", application, e); + } + } else { + try { + LOG.info("Update system application '{}'", application.getTitle()); + application.setSystem(true); + application.setChangedManually(false); + application.setId(storedApplication.getId()); + application.setImageFileId(storedApplication.getImageFileId()); + applicationCenterService.updateApplication(application); + } catch (Exception e) { + LOG.error("Error updating application {}", application, e); + } + } + } + + @SneakyThrows + public T fromJsonString(String value, Class resultClass) { + if (StringUtils.isBlank(value)) { + return null; + } + return OBJECT_MAPPER.readValue(value, resultClass); + } + +} diff --git a/app-center-services/src/main/java/io/meeds/appcenter/service/ApplicationCenterService.java b/app-center-services/src/main/java/io/meeds/appcenter/service/ApplicationCenterService.java new file mode 100644 index 000000000..979067ba5 --- /dev/null +++ b/app-center-services/src/main/java/io/meeds/appcenter/service/ApplicationCenterService.java @@ -0,0 +1,668 @@ +/** + * This file is part of the Meeds project (https://meeds.io/). + * + * Copyright (C) 2020 - 2024 Meeds Association contact@meeds.io + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package io.meeds.appcenter.service; + +import java.io.InputStream; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.regex.Pattern; +import java.util.stream.Collectors; + +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Service; + +import org.exoplatform.commons.api.settings.SettingService; +import org.exoplatform.commons.api.settings.SettingValue; +import org.exoplatform.commons.api.settings.data.Context; +import org.exoplatform.commons.api.settings.data.Scope; +import org.exoplatform.container.ExoContainerContext; +import org.exoplatform.services.security.Authenticator; +import org.exoplatform.services.security.Identity; +import org.exoplatform.services.security.IdentityRegistry; +import org.exoplatform.services.security.MembershipEntry; + +import io.meeds.appcenter.model.Application; +import io.meeds.appcenter.model.ApplicationImage; +import io.meeds.appcenter.model.ApplicationList; +import io.meeds.appcenter.model.ApplicationOrder; +import io.meeds.appcenter.model.GeneralSettings; +import io.meeds.appcenter.model.UserApplication; +import io.meeds.appcenter.model.exception.ApplicationAlreadyExistsException; +import io.meeds.appcenter.model.exception.ApplicationNotFoundException; +import io.meeds.appcenter.storage.ApplicationCenterStorage; + +import lombok.SneakyThrows; + +/** + * A Service to access and store applications + */ +@Service +public class ApplicationCenterService { + + private static final String APPLICATION_IS_MANDATORY_MESSAGE = "application is mandatory"; + + public static final String DEFAULT_ADMINISTRATORS_GROUP = "/platform/administrators"; + + public static final String DEFAULT_ADMINISTRATORS_PERMISSION = "*:" + DEFAULT_ADMINISTRATORS_GROUP; + + public static final String ANY_PERMISSION = "any"; + + public static final String DEFAULT_USERS_GROUP = "/platform/users"; + + public static final String DEFAULT_USERS_PERMISSION = "*:" + DEFAULT_USERS_GROUP; + + public static final String MAX_FAVORITE_APPS = "maxFavoriteApps"; + + public static final String DEFAULT_APP_IMAGE_ID = "defaultAppImageId"; + + public static final String DEFAULT_APP_IMAGE_NAME = "defaultAppImageName"; + + public static final String DEFAULT_APP_IMAGE_BODY = "defaultAppImageBody"; + + public static final int DEFAULT_LIMIT = 10; + + public static final Context APP_CENTER_CONTEXT = Context.GLOBAL.id("APP_CENTER"); + + public static final Scope APP_CENTER_SCOPE = Scope.APPLICATION.id("APP_CENTER"); + + private static final String USERNAME_IS_MANDATORY_MESSAGE = "username is mandatory"; + + private static final String APPLICATION_ID_IS_MANDATORY_MESSAGE = "applicationId is mandatory"; + + private static final String USER_NOT_ALLOWED_MESSAGE = "User %s is not allowed to save application : %s"; + + private static final String APPLICATION_NOT_FOUND_MESSAGE = "Application with id %s doesn't exist"; + + @Autowired + private SettingService settingService; + + @Autowired + private Authenticator authenticator; + + @Autowired(required = false) + private IdentityRegistry identityRegistry; + + @Autowired + private ApplicationCenterStorage appCenterStorage; + + @Value("${appcenter.administrators.expression:*:/platform/administrators}") // NOSONAR + private String defaultAdministratorPermission = null; + + @Value("${appcenter.favorites.count:12}") // NOSONAR + private long defaultMaxFavoriteApps; + + @Value("${appcenter.favorites.max:-1}") // NOSONAR + private long maxFavoriteApps; + + /** + * Create new Application that will be available for all users. If the + * application already exits an {@link ApplicationAlreadyExistsException} will + * be thrown. + * + * @param application application to create + * @param username user making the operation + * @return stored {@link Application} in datasource + * @throws ApplicationAlreadyExistsException when application already exists + * @throws IllegalAccessException if user is not allowed to create an + * application + */ + public Application createApplication(Application application, String username) throws ApplicationAlreadyExistsException, + IllegalAccessException { + if (StringUtils.isBlank(username) || !isAdministrator(username)) { + throw new IllegalAccessException(String.format(USER_NOT_ALLOWED_MESSAGE, + username, + application.getTitle())); + } + return createApplication(application); + } + + /** + * Create new Application that will be available for all users. If the + * application already exits an {@link ApplicationAlreadyExistsException} will + * be thrown. + * + * @param application application to create + * @return stored {@link Application} in datasource + * @throws ApplicationAlreadyExistsException when application already exists + */ + public Application createApplication(Application application) throws ApplicationAlreadyExistsException { + if (application == null) { + throw new IllegalArgumentException(APPLICATION_IS_MANDATORY_MESSAGE); + } + Application existingApplication = appCenterStorage.getApplicationByTitle(application.getTitle()); + if (existingApplication != null) { + throw new ApplicationAlreadyExistsException("appcenter.sameTitleAlreadyExists"); + } + if (!isUrlValid(application.getUrl())) { + throw new IllegalArgumentException("appcenter.malformedUrl"); + } + if (StringUtils.isNotBlank(application.getHelpPageURL()) && !isUrlValid(application.getHelpPageURL())) { + throw new IllegalArgumentException("appcenter.malformedHelpUrl"); + } + if (application.getPermissions() == null || application.getPermissions().isEmpty()) { + application.setPermissions(Collections.singletonList(DEFAULT_USERS_PERMISSION)); + } + return appCenterStorage.createApplication(application); + } + + /** + * Get an application by id + * + * @param applicationId application to find + * @return stored {@link Application} in datasource + * @throws ApplicationNotFoundException when application doesn't exists + */ + public Application findApplication(long applicationId) throws ApplicationNotFoundException { + Application application = appCenterStorage.getApplicationById(applicationId); + if (application == null) { + throw new ApplicationNotFoundException(String.format(APPLICATION_NOT_FOUND_MESSAGE, applicationId)); + } + return application; + } + + /** + * Update an existing application on datasource. If the application doesn't + * exit an {@link ApplicationNotFoundException} will be thrown. + * + * @param application dto to update on store + * @param username username storing application + * @return stored {@link Application} in datasource + * @throws IllegalAccessException if user is not allowed to update application + * @throws ApplicationNotFoundException if application wasn't found + */ + public Application updateApplication(Application application, String username) throws IllegalAccessException, + ApplicationNotFoundException { + if (application == null) { + throw new IllegalArgumentException(APPLICATION_IS_MANDATORY_MESSAGE); + } + Long applicationId = application.getId(); + if (applicationId == null) { + throw new IllegalArgumentException(APPLICATION_ID_IS_MANDATORY_MESSAGE); + } + Application storedApplication = appCenterStorage.getApplicationById(applicationId); + if (storedApplication == null) { + throw new ApplicationNotFoundException(String.format(APPLICATION_NOT_FOUND_MESSAGE, applicationId)); + } + if (StringUtils.isBlank(username) || !isAdministrator(username)) { + throw new IllegalAccessException(String.format(USER_NOT_ALLOWED_MESSAGE, + username, + application.getTitle())); + } + if (application.getPermissions() == null || application.getPermissions().isEmpty()) { + application.setPermissions(Collections.singletonList(DEFAULT_USERS_PERMISSION)); + } + + return updateApplication(application); + } + + public Application updateApplication(Application application) throws ApplicationNotFoundException { + return appCenterStorage.updateApplication(application); + } + + /** + * Delete application identified by its id and check if username has + * permission to delete it. + * + * @param applicationId technical identifier of application + * @param username user currently deleting application + * @throws IllegalAccessException if user is not allowed to delete application + * @throws ApplicationNotFoundException if application wasn't found + */ + public void deleteApplication(Long applicationId, String username) throws ApplicationNotFoundException, + IllegalAccessException { + if (applicationId == null || applicationId <= 0) { + throw new IllegalArgumentException(APPLICATION_ID_IS_MANDATORY_MESSAGE); + } + if (StringUtils.isBlank(username)) { + throw new IllegalArgumentException(USERNAME_IS_MANDATORY_MESSAGE); + } + + Application storedApplication = appCenterStorage.getApplicationById(applicationId); + if (storedApplication == null) { + throw new ApplicationNotFoundException(String.format(APPLICATION_NOT_FOUND_MESSAGE, applicationId)); + } else if (!isAdministrator(username)) { + throw new IllegalAccessException(String.format(USER_NOT_ALLOWED_MESSAGE, + username, + storedApplication.getTitle())); + } else if (storedApplication.isSystem()) { + throw new IllegalAccessException(String.format("Application with id %s is a system application, thus it can't be deleted", + applicationId)); + } + deleteApplication(applicationId); + } + + public void deleteApplication(Long applicationId) throws ApplicationNotFoundException { + appCenterStorage.deleteApplication(applicationId); + } + + /** + * Add an application, identified by its technical id, as favorite of a user + * + * @param applicationId technical application id + * @param username user login + * @throws ApplicationNotFoundException when application is not found + * @throws IllegalAccessException if user hasn't access permission to the + * application + */ + public void addFavoriteApplication(long applicationId, String username) throws ApplicationNotFoundException, + IllegalAccessException { + if (StringUtils.isBlank(username)) { + throw new IllegalArgumentException(USERNAME_IS_MANDATORY_MESSAGE); + } + if (applicationId <= 0) { + throw new IllegalArgumentException(APPLICATION_ID_IS_MANDATORY_MESSAGE); + } + Application application = appCenterStorage.getApplicationById(applicationId); + if (application == null) { + throw new ApplicationNotFoundException(String.format(APPLICATION_NOT_FOUND_MESSAGE, applicationId)); + } + if (!hasPermission(username, application)) { + throw new IllegalAccessException(String.format("User %s doesn't have enough permissions to delete application '%s'", + username, + application.getTitle())); + } + appCenterStorage.addApplicationToUserFavorite(applicationId, username); + } + + /** + * Deletes an application identified by its id from favorite applications of + * user + * + * @param applicationId application technical identifier + * @param username login of user currently deleting application + */ + public void deleteFavoriteApplication(Long applicationId, String username) { + if (applicationId == null || applicationId <= 0) { + throw new IllegalArgumentException(APPLICATION_ID_IS_MANDATORY_MESSAGE); + } + if (StringUtils.isBlank(username)) { + throw new IllegalArgumentException(USERNAME_IS_MANDATORY_MESSAGE); + } + appCenterStorage.deleteApplicationFavorite(applicationId, username); + } + + /** + * Change general setting for maximum allowed favorites that a user can have + * + * @param maxFavoriteApplications max favorite applications count + */ + public void setMaxFavoriteApps(long maxFavoriteApplications) { + if (maxFavoriteApplications >= 0) { + settingService.set(APP_CENTER_CONTEXT, APP_CENTER_SCOPE, MAX_FAVORITE_APPS, SettingValue.create(maxFavoriteApplications)); + this.maxFavoriteApps = maxFavoriteApplications; + } else { + settingService.remove(APP_CENTER_CONTEXT, APP_CENTER_SCOPE, MAX_FAVORITE_APPS); + this.maxFavoriteApps = -1; + } + } + + /** + * @return the maximum favorite applications that a user can have as favorite + */ + public long getMaxFavoriteApps() { + if (this.maxFavoriteApps < 0) { + SettingValue maxFavoriteAppsValue = settingService.get(APP_CENTER_CONTEXT, APP_CENTER_SCOPE, MAX_FAVORITE_APPS); + if (maxFavoriteAppsValue != null && maxFavoriteAppsValue.getValue() != null) { + this.maxFavoriteApps = Long.parseLong(maxFavoriteAppsValue.getValue().toString()); + } else { + this.maxFavoriteApps = this.defaultMaxFavoriteApps; + } + } + return this.maxFavoriteApps; + } + + /** + * Stores default image for applications not having an attached illustration + * + * @param defaultAppImage image content and name + * @return stored image + */ + public ApplicationImage setDefaultAppImage(ApplicationImage defaultAppImage) { + if (defaultAppImage == null + || (StringUtils.isBlank(defaultAppImage.getFileName()) && StringUtils.isBlank(defaultAppImage.getFileBody()))) { + settingService.remove(APP_CENTER_CONTEXT, APP_CENTER_SCOPE, DEFAULT_APP_IMAGE_ID); + } else { + ApplicationImage applicationImage = appCenterStorage.saveAppImageFileItem(defaultAppImage); + if (applicationImage != null && applicationImage.getId() != null && applicationImage.getId() > 0) { + settingService.set(APP_CENTER_CONTEXT, + APP_CENTER_SCOPE, + DEFAULT_APP_IMAGE_ID, + SettingValue.create(String.valueOf(applicationImage.getId()))); + return applicationImage; + } + } + return null; + } + + /** + * @return {@link GeneralSettings} of application including default image and + * maximum favorite applications count + */ + public GeneralSettings getSettings() { // NOSONAR + GeneralSettings generalsettings = new GeneralSettings(); + generalsettings.setMaxFavoriteApps(getMaxFavoriteApps()); + + Long defaultAppImageId = getDefaultImageId(); + if (defaultAppImageId != null) { + ApplicationImage defaultImage = appCenterStorage.getAppImageFile(defaultAppImageId); + generalsettings.setDefaultApplicationImage(defaultImage); + } + return generalsettings; + } + + /** + * Retrieves the list of applications with offset, limit and a keyword that + * can be empty + * + * @param offset offset of the query + * @param limit limit of the query that can be less or equal to 0, which mean, + * getting all available applications + * @param keyword used to search in title and url + * @return {@link ApplicationList} that contains the list of applications + */ + public ApplicationList getApplications(int offset, int limit, String keyword) { + ApplicationList applicationList = new ApplicationList(); + List applications = appCenterStorage.getApplications(keyword); + if (limit <= 0) { + limit = applications.size(); + } + applications = applications.stream().skip(offset).limit(limit).toList(); + applicationList.setApplications(applications); + applicationList.setSize(applications.size()); + applicationList.setOffset(offset); + applicationList.setLimit(limit); + return applicationList; + } + + public Application getApplicationByTitle(String title) { + return appCenterStorage.getApplicationByTitle(title); + } + + /** + * Retrieves the list of applications switch offset and limit of the query, a + * keyword to filter on title and url of {@link Application} and the username + * to filter on authorized applications + * + * @param offset offset of the query + * @param limit limit of the query that can be less or equal to 0, which mean, + * getting all available applications + * @param keyword used to search in title and url + * @param username login of user to use to filter on authorized applications + * @return {@link ApplicationList} that contains the {@link List} of + * authorized {@link UserApplication} + */ + public ApplicationList getActiveApplications(int offset, + int limit, + String keyword, + String username) { + if (StringUtils.isBlank(username)) { + throw new IllegalArgumentException(USERNAME_IS_MANDATORY_MESSAGE); + } + ApplicationList resultApplicationsList = new ApplicationList(); + List applications = getActiveApplications(keyword, username).stream().toList(); + if (limit > 0) { + if (offset < 0) { + offset = 0; + } + applications = applications.stream() + .skip(offset) + .limit(limit) + .toList(); + } + applications = applications.stream() + .map(app -> { + UserApplication applicationFavorite = new UserApplication(app); + applicationFavorite.setFavorite(appCenterStorage.isFavoriteApplication(applicationFavorite.getId(), + username)); + return (Application) applicationFavorite; + }) + .toList(); + resultApplicationsList.setApplications(applications); + long countFavorites = appCenterStorage.countFavorites(username); + resultApplicationsList.setCanAddFavorite(countFavorites < getMaxFavoriteApps()); + resultApplicationsList.setOffset(offset); + resultApplicationsList.setLimit(limit); + resultApplicationsList.setSize(applications.size()); + return resultApplicationsList; + } + + /** + * Retrieves all the list of applications for a user + * + * @param username login of user + * @return {@link ApplicationList} that contains {@link List} of + * {@link UserApplication} + */ + public ApplicationList getMandatoryAndFavoriteApplicationsList(String username) { + List mandatoryAndFavoriteApplications = + new ArrayList<>(appCenterStorage.getFavoriteApplicationsByUser(username)); + List mandatoryAndFavoriteApplicationsId = mandatoryAndFavoriteApplications.stream() + .map(UserApplication::getId) + .toList(); + appCenterStorage.getMandatoryApplications().forEach(userApplication -> { + if (!mandatoryAndFavoriteApplicationsId.contains(userApplication.getId())) { + mandatoryAndFavoriteApplications.add(userApplication); + } + }); + + List applications = mandatoryAndFavoriteApplications.stream() + .filter(app -> hasPermission(username, app)) + .collect(Collectors.toList()); + ApplicationList applicationList = new ApplicationList(); + applicationList.setApplications(applications); + long countFavorites = appCenterStorage.countFavorites(username); + applicationList.setCanAddFavorite(countFavorites < getMaxFavoriteApps()); + applicationList.setLimit(applications.size()); + applicationList.setSize(applications.size()); + applicationList.setOffset(0); + return applicationList; + } + + /** + * Update favorite applications order for a user + * + * @param applicationOrder + * @param userName + */ + public void updateFavoriteApplicationOrder(ApplicationOrder applicationOrder, + String userName) throws ApplicationNotFoundException { + if (StringUtils.isBlank(userName)) { + throw new IllegalArgumentException(USERNAME_IS_MANDATORY_MESSAGE); + } + if (applicationOrder.getId() <= 0) { + throw new IllegalArgumentException(APPLICATION_ID_IS_MANDATORY_MESSAGE); + } + Application application = appCenterStorage.getApplicationById(applicationOrder.getId()); + if (application == null) { + throw new ApplicationNotFoundException(String.format(APPLICATION_NOT_FOUND_MESSAGE, applicationOrder.getId())); + } + appCenterStorage.updateFavoriteApplicationOrder(applicationOrder.getId(), userName, applicationOrder.getOrder()); + } + + /** + * Return the {@link Application} illustration last modifed timestamp (in ms), + * if not found, the default image last modifed timestamp will be retrieved + * + * @param applicationId technical id of application + * @param username login of user accessing application + * @return timestamp in milliseconds of last modified date of illustration + * @throws ApplicationNotFoundException if application wasn't found + * @throws IllegalAccessException if user doesn't have access permission to + * application + */ + public Long getApplicationImageLastUpdated(long applicationId, String username) throws ApplicationNotFoundException, + IllegalAccessException { + if (StringUtils.isBlank(username)) { + throw new IllegalArgumentException(USERNAME_IS_MANDATORY_MESSAGE); + } + Application application = appCenterStorage.getApplicationById(applicationId); + if (application == null) { + throw new ApplicationNotFoundException(String.format(APPLICATION_NOT_FOUND_MESSAGE, applicationId)); + } + // if user is admin then no need to check for permissions + if (!isAdministrator(username) && !hasPermission(username, application)) { + throw new IllegalAccessException(String.format(USER_NOT_ALLOWED_MESSAGE, username, application.getTitle())); + } + if (application.getImageFileId() != null && application.getImageFileId() > 0) { + return appCenterStorage.getApplicationImageLastUpdated(application.getImageFileId()); + } else { + Long defaultImageId = getDefaultImageId(); + if (defaultImageId != null && defaultImageId > 0) { + return appCenterStorage.getApplicationImageLastUpdated(defaultImageId); + } + } + return null; + } + + /** + * Return the {@link Application} illustration {@link InputStream}, if not + * found, the default image {@link InputStream} will be retrieved + * + * @param applicationId technical id of application + * @param username login of user accessing application + * @return {@link InputStream} of application illustration + * @throws ApplicationNotFoundException if application wasn't found + * @throws IllegalAccessException if user doesn't have access permission to + * application + */ + public InputStream getApplicationImageInputStream(long applicationId, String username) throws ApplicationNotFoundException, + IllegalAccessException { + if (StringUtils.isBlank(username)) { + throw new IllegalArgumentException(USERNAME_IS_MANDATORY_MESSAGE); + } + Application application = appCenterStorage.getApplicationById(applicationId); + if (application == null) { + throw new ApplicationNotFoundException(String.format(APPLICATION_NOT_FOUND_MESSAGE, applicationId)); + } + // if user is admin then no need to check for permissions + if (!isAdministrator(username) && !hasPermission(username, application)) { + throw new IllegalAccessException(String.format(USER_NOT_ALLOWED_MESSAGE, username, application.getTitle())); + } + InputStream applicationImageInputStream = null; + if (application.getImageFileId() != null && application.getImageFileId() > 0) { + applicationImageInputStream = appCenterStorage.getApplicationImageInputStream(application.getImageFileId()); + } + if (applicationImageInputStream == null) { + // result is null if there is no image associated to the application + // or if the image is not readable (data corruption, or quarantined by an + // antivirus) + Long defaultImageId = getDefaultImageId(); + if (defaultImageId != null && defaultImageId > 0) { + applicationImageInputStream = appCenterStorage.getApplicationImageInputStream(defaultImageId); + } + } + return applicationImageInputStream; + } + + public List getSystemApplications() { + return appCenterStorage.getSystemApplications(); + } + + private boolean isAdministrator(String username) { + return hasPermission(username, DEFAULT_ADMINISTRATORS_GROUP); + } + + private boolean hasPermission(String username, Application application) { + return hasPermission(username, application.getPermissions()); + } + + private boolean hasPermission(String username, List storedPermissions) { + if (storedPermissions == null) { + return true; + } + for (String storedPermission : storedPermissions) { + if (hasPermission(username, storedPermission)) { + return true; + } + } + return false; + } + + private boolean hasPermission(String username, String permissionExpression) { + if (StringUtils.isBlank(permissionExpression)) { + return true; + } else if (StringUtils.isBlank(username)) { + return false; + } + + // In general case, the user is already loggedin, thus we will get the + // Identity from registry without having to compute it again from + // OrganisationService, thus the condition (identity == null) will be false + // most of the time for better performances + MembershipEntry membership = null; + if (permissionExpression.contains(":")) { + String[] permissionExpressionParts = permissionExpression.split(":"); + membership = new MembershipEntry(permissionExpressionParts[1], permissionExpressionParts[0]); + } else if (permissionExpression.contains("/")) { + membership = new MembershipEntry(permissionExpression, MembershipEntry.ANY_TYPE); + } else { + return StringUtils.equals(username, permissionExpression); + } + return getUserIdentity(username).isMemberOf(membership); + } + + @SneakyThrows + private Identity getUserIdentity(String username) { + Identity identity = getIdentityRegistry().getIdentity(username); + if (identity == null) { + return authenticator.createIdentity(username); + } else { + return identity; + } + } + + private Long getDefaultImageId() { + SettingValue defaultAppImageIdSetting = settingService.get(APP_CENTER_CONTEXT, APP_CENTER_SCOPE, DEFAULT_APP_IMAGE_ID); + Long defaultAppImageId = null; + if (defaultAppImageIdSetting != null && defaultAppImageIdSetting.getValue() != null) { + defaultAppImageId = Long.parseLong(defaultAppImageIdSetting.getValue().toString()); + } + return defaultAppImageId; + } + + private List getActiveApplications(String keyword, String username) { + return appCenterStorage.getApplications(keyword) + .stream() + .filter(app -> hasPermission(username, app)) + .filter(Application::isActive) + .toList(); + + } + + private boolean isUrlValid(String url) { + // [-a-zA-Z0-9@:%._\\\\/+~#=] allowed characters + String regex = "(http(s)?:\\/\\/.)[-a-zA-Z0-9@:%._\\\\/+~#=]{2,256}"; + Pattern pattern = Pattern.compile(regex); + return url != null && !url.isBlank() + && (url.startsWith("/portal/") || url.startsWith("./") || pattern.matcher(url).matches()); + } + + public IdentityRegistry getIdentityRegistry() { + if (identityRegistry == null) { + // Kernel Container Service not recognized, thus retrieve it + // differently when not possible through @Autowired + identityRegistry = ExoContainerContext.getService(IdentityRegistry.class); + } + return identityRegistry; + } + +} diff --git a/app-center-services/src/main/java/org/exoplatform/appcenter/storage/ApplicationCenterStorage.java b/app-center-services/src/main/java/io/meeds/appcenter/storage/ApplicationCenterStorage.java similarity index 79% rename from app-center-services/src/main/java/org/exoplatform/appcenter/storage/ApplicationCenterStorage.java rename to app-center-services/src/main/java/io/meeds/appcenter/storage/ApplicationCenterStorage.java index d170ba28c..f1fdaa4cf 100644 --- a/app-center-services/src/main/java/org/exoplatform/appcenter/storage/ApplicationCenterStorage.java +++ b/app-center-services/src/main/java/io/meeds/appcenter/storage/ApplicationCenterStorage.java @@ -1,70 +1,76 @@ -/* +/** * This file is part of the Meeds project (https://meeds.io/). - * Copyright (C) 2020 Meeds Association - * contact@meeds.io + * + * Copyright (C) 2020 - 2024 Meeds Association contact@meeds.io * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 3 of the License, or (at your option) any later version. + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. + * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -package org.exoplatform.appcenter.storage; +package io.meeds.appcenter.storage; import java.io.ByteArrayInputStream; -import java.io.IOException; import java.io.InputStream; import java.nio.charset.Charset; import java.util.ArrayList; +import java.util.Base64; import java.util.Date; import java.util.List; -import java.util.stream.Collectors; import org.apache.commons.lang3.StringUtils; -import java.util.Base64; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; -import org.exoplatform.appcenter.dao.ApplicationDAO; -import org.exoplatform.appcenter.dao.FavoriteApplicationDAO; -import org.exoplatform.appcenter.dto.Application; -import org.exoplatform.appcenter.dto.ApplicationImage; -import org.exoplatform.appcenter.dto.UserApplication; -import org.exoplatform.appcenter.entity.ApplicationEntity; -import org.exoplatform.appcenter.entity.FavoriteApplicationEntity; -import org.exoplatform.appcenter.service.ApplicationNotFoundException; import org.exoplatform.commons.file.model.FileInfo; import org.exoplatform.commons.file.model.FileItem; import org.exoplatform.commons.file.services.FileService; -import org.exoplatform.commons.file.services.FileStorageException; + +import io.meeds.appcenter.dao.ApplicationDAO; +import io.meeds.appcenter.dao.FavoriteApplicationDAO; +import io.meeds.appcenter.entity.ApplicationEntity; +import io.meeds.appcenter.entity.FavoriteApplicationEntity; +import io.meeds.appcenter.model.Application; +import io.meeds.appcenter.model.ApplicationImage; +import io.meeds.appcenter.model.UserApplication; +import io.meeds.appcenter.model.exception.ApplicationNotFoundException; + +import lombok.SneakyThrows; /** * Storage service to access / load and save applications. This service will be * used , as well, to convert from JPA entity to DTO. */ +@Component public class ApplicationCenterStorage { - public static final String NAME_SPACE = "appCenter"; + private static final String APPLICATION_NOT_FOUND_MESSAGE = "Application with id %s doesn't exist"; + + private static final String APPLICATION_ID_IS_MANDATORY_MESSAGE = "applicationId is mandatory"; - public static final Long DEFAULT_LAST_MODIFIED = System.currentTimeMillis(); + private static final String USERNAME_IS_MANDATORY_MESSAGE = "username is mandatory"; + public static final String NAME_SPACE = "appCenter"; + + public static final Long DEFAULT_LAST_MODIFIED = System.currentTimeMillis(); + + @Autowired private FileService fileService; + @Autowired private ApplicationDAO applicationDAO; + @Autowired private FavoriteApplicationDAO favoriteApplicationDAO; - public ApplicationCenterStorage(ApplicationDAO applicationDAO, - FavoriteApplicationDAO favoriteApplicationDAO, - FileService fileService) { - this.applicationDAO = applicationDAO; - this.favoriteApplicationDAO = favoriteApplicationDAO; - this.fileService = fileService; - } - public Application getApplicationByTitle(String title) { if (StringUtils.isBlank(title)) { throw new IllegalArgumentException("title is mandatory"); @@ -73,29 +79,29 @@ public Application getApplicationByTitle(String title) { return toDTO(applicationentity); } - public Application createApplication(Application applicationForm) throws Exception { - if (applicationForm == null) { + public Application createApplication(Application application) { + if (application == null) { throw new IllegalArgumentException("application is mandatory"); } - ApplicationEntity applicationEntity = toEntity(applicationForm); + ApplicationEntity applicationEntity = toEntity(application); applicationEntity.setId(null); - ApplicationImage applicationImage = createAppImageFileItem(applicationForm.getImageFileName(), - applicationForm.getImageFileBody()); + ApplicationImage applicationImage = createAppImageFileItem(application.getImageFileName(), + application.getImageFileBody()); if (applicationImage != null) { applicationEntity.setImageFileId(applicationImage.getId()); } - applicationEntity = applicationDAO.create(applicationEntity); + applicationEntity = applicationDAO.save(applicationEntity); return toDTO(applicationEntity); } - public Application updateApplication(Application application) throws Exception { + public Application updateApplication(Application application) throws ApplicationNotFoundException { if (application == null) { throw new IllegalArgumentException("application is mandatory"); } Long applicationId = application.getId(); - ApplicationEntity storedApplicationEntity = applicationDAO.find(applicationId); + ApplicationEntity storedApplicationEntity = applicationDAO.findById(applicationId).orElse(null); if (storedApplicationEntity == null) { - throw new ApplicationNotFoundException("Application with id " + applicationId + " wasn't found"); + throw new ApplicationNotFoundException(String.format(APPLICATION_NOT_FOUND_MESSAGE, applicationId)); } // Avoid changing this flag by UI @@ -104,10 +110,12 @@ public Application updateApplication(Application application) throws Exception { Long oldImageFileId = storedApplicationEntity.getImageFileId(); boolean imageRemoved = StringUtils.isBlank(application.getImageFileBody()) - && StringUtils.isBlank(application.getImageFileName()) && oldImageFileId != null && oldImageFileId > 0; + && StringUtils.isBlank(application.getImageFileName()) + && oldImageFileId != null + && oldImageFileId > 0; boolean newImageAttached = StringUtils.isNotBlank(application.getImageFileBody()) - && StringUtils.isNotBlank(application.getImageFileName()); + && StringUtils.isNotBlank(application.getImageFileName()); // if new image make sure to update it if (newImageAttached) { ApplicationImage applicationImage = createAppImageFileItem(application.getImageFileName(), application.getImageFileBody()); @@ -135,39 +143,39 @@ public Application updateApplication(Application application) throws Exception { } ApplicationEntity applicationEntity = toEntity(application); - applicationEntity = applicationDAO.update(applicationEntity); + applicationEntity = applicationDAO.save(applicationEntity); return toDTO(applicationEntity); } public void deleteApplication(long applicationId) throws ApplicationNotFoundException { if (applicationId <= 0) { - throw new IllegalArgumentException("applicationId must be a positive integer"); + throw new IllegalArgumentException(APPLICATION_ID_IS_MANDATORY_MESSAGE); } - ApplicationEntity applicationEntity = applicationDAO.find(applicationId); + ApplicationEntity applicationEntity = applicationDAO.findById(applicationId).orElse(null); if (applicationEntity == null) { - throw new ApplicationNotFoundException("Application with id " + applicationId + " not found"); + throw new ApplicationNotFoundException(String.format(APPLICATION_NOT_FOUND_MESSAGE, applicationId)); } applicationDAO.delete(applicationEntity); } public Application getApplicationById(long applicationId) { if (applicationId <= 0) { - throw new IllegalArgumentException("applicationId must be a positive integer"); + throw new IllegalArgumentException(APPLICATION_ID_IS_MANDATORY_MESSAGE); } - ApplicationEntity applicationEntity = applicationDAO.find(applicationId); + ApplicationEntity applicationEntity = applicationDAO.findById(applicationId).orElse(null); return toDTO(applicationEntity); } public void addApplicationToUserFavorite(long applicationId, String username) throws ApplicationNotFoundException { if (applicationId <= 0) { - throw new IllegalArgumentException("applicationId must be a positive integer"); + throw new IllegalArgumentException(APPLICATION_ID_IS_MANDATORY_MESSAGE); } - ApplicationEntity application = applicationDAO.find(applicationId); + ApplicationEntity application = applicationDAO.findById(applicationId).orElse(null); if (application == null) { - throw new ApplicationNotFoundException("Application with id " + applicationId + " wasn't found in store"); + throw new ApplicationNotFoundException(String.format(APPLICATION_NOT_FOUND_MESSAGE, applicationId)); } - favoriteApplicationDAO.create(new FavoriteApplicationEntity(application, username)); + favoriteApplicationDAO.save(new FavoriteApplicationEntity(application, username)); } public void updateFavoriteApplicationOrder(long applicationId, String username, Long order) throws ApplicationNotFoundException { @@ -177,12 +185,12 @@ public void updateFavoriteApplicationOrder(long applicationId, String username, entity = favoriteApplicationDAO.getFavoriteAppByUserNameAndAppId(applicationId, username); } entity.setOrder(order); - favoriteApplicationDAO.update(entity); + favoriteApplicationDAO.save(entity); } public void deleteApplicationFavorite(Long applicationId, String username) { if (applicationId <= 0) { - throw new IllegalArgumentException("applicationId must be a positive integer"); + throw new IllegalArgumentException(APPLICATION_ID_IS_MANDATORY_MESSAGE); } FavoriteApplicationEntity applicationFavorite = favoriteApplicationDAO.getFavoriteAppByUserNameAndAppId(applicationId, username); @@ -195,18 +203,18 @@ public List getMandatoryApplications() { List applications = applicationDAO.getMandatoryActiveApps(); return applications.stream() .map(this::toUserApplicationDTO) - .collect(Collectors.toList()); + .toList(); } public List getFavoriteApplicationsByUser(String username) { if (StringUtils.isBlank(username)) { - throw new IllegalArgumentException("username is mandatory"); + throw new IllegalArgumentException(USERNAME_IS_MANDATORY_MESSAGE); } List applications = favoriteApplicationDAO.getFavoriteAppsByUser(username); return applications.stream() .map(this::toUserApplicationDTO) - .filter(userApplication -> userApplication.isActive()) - .collect(Collectors.toList()); + .filter(UserApplication::isActive) + .toList(); } public List getSystemApplications() { @@ -222,22 +230,22 @@ public List getSystemApplications() { public boolean isFavoriteApplication(Long applicationId, String username) { if (applicationId == null || applicationId <= 0) { - throw new IllegalArgumentException("applicationId must be a positive integer"); + throw new IllegalArgumentException(APPLICATION_ID_IS_MANDATORY_MESSAGE); } if (StringUtils.isBlank(username)) { - throw new IllegalArgumentException("username is mandatory"); + throw new IllegalArgumentException(USERNAME_IS_MANDATORY_MESSAGE); } return favoriteApplicationDAO.getFavoriteAppByUserNameAndAppId(applicationId, username) != null; } public long countFavorites(String username) { if (StringUtils.isBlank(username)) { - throw new IllegalArgumentException("username is mandatory"); + throw new IllegalArgumentException(USERNAME_IS_MANDATORY_MESSAGE); } return favoriteApplicationDAO.countFavoritesForUser(username); } - public ApplicationImage saveAppImageFileItem(ApplicationImage defaultAppImage) throws Exception { + public ApplicationImage saveAppImageFileItem(ApplicationImage defaultAppImage) { if (defaultAppImage == null) { throw new IllegalArgumentException("Application image is mandatory"); } @@ -248,11 +256,12 @@ public ApplicationImage saveAppImageFileItem(ApplicationImage defaultAppImage) t } } - public ApplicationImage createAppImageFileItem(String fileName, String fileBody) throws Exception { + public ApplicationImage createAppImageFileItem(String fileName, String fileBody) { return updateAppImageFileItem(null, fileName, fileBody); } - public Long getApplicationImageLastUpdated(long fileId) throws FileStorageException { + @SneakyThrows + public Long getApplicationImageLastUpdated(long fileId) { FileItem fileItem = fileService.getFile(fileId); if (fileItem != null && fileItem.getFileInfo().getUpdatedDate() != null) { return fileItem.getFileInfo().getUpdatedDate().getTime(); @@ -260,7 +269,8 @@ public Long getApplicationImageLastUpdated(long fileId) throws FileStorageExcept return null; } - public InputStream getApplicationImageInputStream(long fileId) throws FileStorageException, IOException { // NOSONAR + @SneakyThrows + public InputStream getApplicationImageInputStream(long fileId) { FileItem fileItem = fileService.getFile(fileId); if (fileItem != null && fileItem.getAsByte() != null) { return new ByteArrayInputStream(fileItem.getAsByte()); @@ -268,7 +278,8 @@ public InputStream getApplicationImageInputStream(long fileId) throws FileStorag return null; } - public ApplicationImage getAppImageFile(Long fileId) throws FileStorageException { + @SneakyThrows + public ApplicationImage getAppImageFile(Long fileId) { FileItem fileItem = fileService.getFile(fileId); if (fileItem != null) { byte[] bytes = fileItem.getAsByte(); @@ -280,13 +291,9 @@ public ApplicationImage getAppImageFile(Long fileId) throws FileStorageException } public List getApplications(String keyword) { - List applications = applicationDAO.getApplications(keyword); - List list = new ArrayList<>(); - for (ApplicationEntity entity : applications) { - Application application = toDTO(entity); - list.add(application); - } - return list; + List applications = StringUtils.isBlank(keyword) ? applicationDAO.findAll() : + applicationDAO.getApplications(keyword); + return applications.stream().map(this::toDTO).toList(); } public long countApplications() { @@ -299,9 +306,9 @@ private Application toDTO(ApplicationEntity applicationEntity) { } String imageFileName = null; long imageLastModified = DEFAULT_LAST_MODIFIED; - if(applicationEntity.getImageFileId() != null && applicationEntity.getImageFileId()>0){ + if (applicationEntity.getImageFileId() != null && applicationEntity.getImageFileId() > 0) { FileInfo fileInfo = fileService.getFileInfo(applicationEntity.getImageFileId()); - if(fileInfo != null){ + if (fileInfo != null) { imageFileName = fileInfo.getName(); if (fileInfo.getUpdatedDate() != null) { imageLastModified = fileInfo.getUpdatedDate().getTime(); @@ -326,7 +333,7 @@ private Application toDTO(ApplicationEntity applicationEntity) { permissions); application.setSystem(applicationEntity.isSystem()); application.setHelpPageURL(applicationEntity.getHelpPageUrl()); - application.setIsMobile(applicationEntity.isMobile()); + application.setMobile(applicationEntity.isMobile()); return application; } @@ -336,9 +343,9 @@ private UserApplication toUserApplicationDTO(ApplicationEntity applicationEntity } String imageFileName = null; long imageLastModified = DEFAULT_LAST_MODIFIED; - if(applicationEntity.getImageFileId() != null && applicationEntity.getImageFileId()>0){ + if (applicationEntity.getImageFileId() != null && applicationEntity.getImageFileId() > 0) { FileInfo fileInfo = fileService.getFileInfo(applicationEntity.getImageFileId()); - if(fileInfo != null){ + if (fileInfo != null) { imageFileName = fileInfo.getName(); if (fileInfo.getUpdatedDate() != null) { imageLastModified = fileInfo.getUpdatedDate().getTime(); @@ -364,7 +371,7 @@ private UserApplication toUserApplicationDTO(ApplicationEntity applicationEntity permissions); userApplication.setSystem(applicationEntity.isSystem()); userApplication.setHelpPageURL(applicationEntity.getHelpPageUrl()); - userApplication.setIsMobile(applicationEntity.isMobile()); + userApplication.setMobile(applicationEntity.isMobile()); return userApplication; } @@ -405,7 +412,7 @@ private UserApplication toUserApplicationDTO(FavoriteApplicationEntity favoriteA userApplication.setOrder(favoriteApplicationEntity.getOrder()); userApplication.setSystem(applicationEntity.isSystem()); userApplication.setHelpPageURL(applicationEntity.getHelpPageUrl()); - userApplication.setIsMobile(applicationEntity.isMobile()); + userApplication.setMobile(applicationEntity.isMobile()); return userApplication; } @@ -424,11 +431,12 @@ private ApplicationEntity toEntity(Application application) { application.isChangedManually()); applicationEntity.setSystem(application.isSystem()); applicationEntity.setHelpPageUrl(application.getHelpPageURL()); - applicationEntity.setIsMobile(application.isMobile()); + applicationEntity.setMobile(application.isMobile()); return applicationEntity; } - private ApplicationImage updateAppImageFileItem(Long fileId, String fileName, String fileBody) throws Exception { // NOSONAR + @SneakyThrows + private ApplicationImage updateAppImageFileItem(Long fileId, String fileName, String fileBody) { // NOSONAR if (StringUtils.isBlank(fileName) || StringUtils.isBlank(fileBody)) { return null; } diff --git a/app-center-services/src/main/java/org/exoplatform/appcenter/dao/ApplicationDAO.java b/app-center-services/src/main/java/org/exoplatform/appcenter/dao/ApplicationDAO.java deleted file mode 100644 index 7299f9fe8..000000000 --- a/app-center-services/src/main/java/org/exoplatform/appcenter/dao/ApplicationDAO.java +++ /dev/null @@ -1,78 +0,0 @@ -/* - * This file is part of the Meeds project (https://meeds.io/). - * Copyright (C) 2020 Meeds Association - * contact@meeds.io - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.exoplatform.appcenter.dao; - -import java.util.List; - -import jakarta.persistence.TypedQuery; - -import org.apache.commons.lang3.StringUtils; - -import org.exoplatform.appcenter.entity.ApplicationEntity; -import org.exoplatform.commons.persistence.impl.GenericDAOJPAImpl; -import org.exoplatform.services.log.ExoLogger; -import org.exoplatform.services.log.Log; - -/** - * @author Ayoub Zayati - */ -public class ApplicationDAO extends GenericDAOJPAImpl { - private static final Log LOG = ExoLogger.getLogger(ApplicationDAO.class); - - public List getMandatoryActiveApps() { - return getEntityManager().createNamedQuery("ApplicationEntity.getMandatoryActiveApps", ApplicationEntity.class) - .getResultList(); - } - - public List getApplications(String keyword) { - TypedQuery query = null; - if (StringUtils.isBlank(keyword)) { - query = getEntityManager().createNamedQuery("ApplicationEntity.getApplications", ApplicationEntity.class); - } else { - query = getEntityManager().createNamedQuery("ApplicationEntity.getApplicationsByKeyword", ApplicationEntity.class); - keyword = keyword.toLowerCase(); - keyword = "%" + keyword.replaceAll("%", "").replaceAll("\\*", "%") + "%"; - query.setParameter("title", keyword); - query.setParameter("description", keyword); - query.setParameter("url", keyword); - } - return query.getResultList(); - } - - public List getSystemApplications() { - TypedQuery query = getEntityManager().createNamedQuery("ApplicationEntity.getSystemApplications", - ApplicationEntity.class); - return query.getResultList(); - } - - public ApplicationEntity getApplicationByTitle(String title) { - TypedQuery query = getEntityManager() - .createNamedQuery("ApplicationEntity.getAppByTitle", - ApplicationEntity.class) - .setParameter("title", title); - List result = query.getResultList(); - if (result == null || result.isEmpty()) { - return null; - } else if (result.size() > 1) { - LOG.warn("More than one application was found with Title '{}'", title); - return result.get(0); - } else { - return result.get(0); - } - } - -} diff --git a/app-center-services/src/main/java/org/exoplatform/appcenter/dao/FavoriteApplicationDAO.java b/app-center-services/src/main/java/org/exoplatform/appcenter/dao/FavoriteApplicationDAO.java deleted file mode 100644 index e87b65569..000000000 --- a/app-center-services/src/main/java/org/exoplatform/appcenter/dao/FavoriteApplicationDAO.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * This file is part of the Meeds project (https://meeds.io/). - * Copyright (C) 2020 Meeds Association - * contact@meeds.io - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.exoplatform.appcenter.dao; - -import java.util.List; - -import jakarta.persistence.TypedQuery; - -import org.exoplatform.appcenter.entity.FavoriteApplicationEntity; -import org.exoplatform.commons.persistence.impl.GenericDAOJPAImpl; -import org.exoplatform.services.log.ExoLogger; -import org.exoplatform.services.log.Log; - -/** - * @author Ayoub Zayati - */ -public class FavoriteApplicationDAO extends GenericDAOJPAImpl { - private static final Log LOG = ExoLogger.getLogger(FavoriteApplicationDAO.class); - - public List getFavoriteAppsByUser(String userName) { - return getEntityManager().createNamedQuery("FavoriteApplicationEntity.getFavoriteAppsByUser", FavoriteApplicationEntity.class) - .setParameter("userName", userName) - .getResultList(); - } - - public FavoriteApplicationEntity getFavoriteAppByUserNameAndAppId(Long applicationId, String userName) { - TypedQuery query = - getEntityManager().createNamedQuery("FavoriteApplicationEntity.getFavoriteAppByUserNameAndAppId", - FavoriteApplicationEntity.class) - .setParameter("applicationId", applicationId) - .setParameter("userName", userName); - List result = query.getResultList(); - if (result == null || result.isEmpty()) { - return null; - } else if (result.size() > 1) { - LOG.warn("More than one application was found with applicationId '{}' and userName '{}'", applicationId, userName); - return result.get(0); - } else { - return result.get(0); - } - } - - public long countFavoritesForUser(String username) { - TypedQuery query = getEntityManager().createNamedQuery("FavoriteApplicationEntity.countFavoritesByUser", Long.class); - query.setParameter("userName", username); - return query.getSingleResult(); - } - - public void removeAllFavoritesOfApplication(Long applicationId) { - getEntityManager().getTransaction().begin(); - getEntityManager().createQuery("DELETE FROM FavoriteApplicationEntity favoriteApp WHERE favoriteApp.application.id = :applicationId ") - .setParameter("applicationId", applicationId) - .executeUpdate(); - getEntityManager().getTransaction().commit(); - } -} diff --git a/app-center-services/src/main/java/org/exoplatform/appcenter/dto/Application.java b/app-center-services/src/main/java/org/exoplatform/appcenter/dto/Application.java deleted file mode 100644 index 6d90229cc..000000000 --- a/app-center-services/src/main/java/org/exoplatform/appcenter/dto/Application.java +++ /dev/null @@ -1,261 +0,0 @@ -/* - * This file is part of the Meeds project (https://meeds.io/). - * Copyright (C) 2020 Meeds Association - * contact@meeds.io - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.exoplatform.appcenter.dto; - -import java.io.Serializable; -import java.util.Arrays; -import java.util.List; - -/** - * @author Ayoub Zayati - */ -public class Application implements Serializable { - - private static final long serialVersionUID = -3486306198744219949L; - - private Long id; - - private String title; - - private String url; - - private String helpPageURL; - - private String description; - - private boolean active; - - private boolean isMandatory; - - private boolean isMobile; - - private boolean system; - - private List permissions; - - private String imageFileBody; - - private String imageFileName; - - private Long imageFileId; - - private Long imageLastModified; - - private Long order; - - private boolean isChangedManually; - - public Application() { - } - - public Application(Long id, - String title, - String url, - String helpPageURL, - Long imageFileId, - Long imageLastModified, - String imageFileBody, - String imageFileName, - String description, - boolean isSystem, - boolean active, - boolean isMandatory, - boolean isMobile, - boolean isChangedManually, - String... permissions) { - this(id, - title, - url, - helpPageURL, - imageFileId, - imageLastModified, - imageFileBody, - imageFileName, - description, - isSystem, - active, - isMandatory, - isMobile, - isChangedManually, - permissions == null ? null : Arrays.asList(permissions)); - } - - public Application(Long id, - String title, - String url, - String helpPageURL, - Long imageFileId, - Long imageLastModified, - String imageFileBody, - String imageFileName, - String description, - boolean isSystem, - boolean active, - boolean isMandatory, - boolean isMobile, - boolean isChangedManually, - List permissions) { - this.id = id; - this.title = title; - this.url = url; - this.helpPageURL = helpPageURL; - this.description = description; - this.active = active; - this.isMandatory = isMandatory; - this.isMobile = isMobile; - this.system = isSystem; - this.permissions = permissions; - this.imageFileId = imageFileId; - this.imageLastModified = imageLastModified; - this.imageFileBody = imageFileBody; - this.imageFileName = imageFileName; - this.isChangedManually = isChangedManually; - } - - public Long getId() { - return id; - } - - public void setId(Long id) { - this.id = id; - } - - public String getTitle() { - return title; - } - - public void setTitle(String title) { - this.title = title; - } - - public String getUrl() { - return url; - } - - public void setUrl(String url) { - this.url = url; - } - - public String getHelpPageURL() { - return helpPageURL; - } - - public void setHelpPageURL(String helpPageURL) { - this.helpPageURL = helpPageURL; - } - - public String getDescription() { - return description; - } - - public void setDescription(String description) { - this.description = description; - } - - public boolean isActive() { - return active; - } - - public void setActive(boolean active) { - this.active = active; - } - - public boolean isMandatory() { - return isMandatory; - } - - public void setMandatory(boolean mandatory) { - this.isMandatory = mandatory; - } - - public boolean isMobile() { - return isMobile; - } - - public void setIsMobile(boolean mobile) { - isMobile = mobile; - } - - public List getPermissions() { - return permissions; - } - - public void setPermissions(String... permissions) { - this.permissions = Arrays.asList(permissions); - } - - public String getImageFileBody() { - return imageFileBody; - } - - public void setImageFileBody(String imageFileBody) { - this.imageFileBody = imageFileBody; - } - - public String getImageFileName() { - return imageFileName; - } - - public void setImageFileName(String imageFileName) { - this.imageFileName = imageFileName; - } - - public Long getImageFileId() { - return imageFileId; - } - - public void setImageFileId(Long imageFileId) { - this.imageFileId = imageFileId; - } - - public Long getImageLastModified() { - return imageLastModified; - } - - public void setImageLastModified(Long imageLastModified) { - this.imageLastModified = imageLastModified; - } - - public boolean isSystem() { - return system; - } - - public void setSystem(boolean system) { - this.system = system; - } - - public Long getOrder() { - return order; - } - - public void setOrder(Long order) { - this.order = order; - } - - public boolean isChangedManually() { - return isChangedManually; - } - - public void setChangedManually(boolean changedManually) { - this.isChangedManually = changedManually; - } - - @Override - public String toString() { - return "[Application: title = '" + title + "', url = '" + url + "']"; - } -} diff --git a/app-center-services/src/main/java/org/exoplatform/appcenter/dto/ApplicationOrder.java b/app-center-services/src/main/java/org/exoplatform/appcenter/dto/ApplicationOrder.java deleted file mode 100644 index 641d7261a..000000000 --- a/app-center-services/src/main/java/org/exoplatform/appcenter/dto/ApplicationOrder.java +++ /dev/null @@ -1,35 +0,0 @@ -package org.exoplatform.appcenter.dto; - -import java.io.Serializable; - -public class ApplicationOrder implements Serializable { - /** Application id */ - private Long id; - - /** Application order */ - private Long order; - - public ApplicationOrder() { - } - - public ApplicationOrder(Long id, Long order) { - this.id = id; - this.order = order; - } - - public Long getId() { - return id; - } - - public void setId(Long id) { - this.id = id; - } - - public Long getOrder() { - return order; - } - - public void setOrder(Long order) { - this.order = order; - } -} diff --git a/app-center-services/src/main/java/org/exoplatform/appcenter/dto/GeneralSettings.java b/app-center-services/src/main/java/org/exoplatform/appcenter/dto/GeneralSettings.java deleted file mode 100644 index fb20decc8..000000000 --- a/app-center-services/src/main/java/org/exoplatform/appcenter/dto/GeneralSettings.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * This file is part of the Meeds project (https://meeds.io/). - * Copyright (C) 2020 Meeds Association - * contact@meeds.io - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.exoplatform.appcenter.dto; - -import java.io.Serializable; - -public class GeneralSettings implements Serializable { - - private static final long serialVersionUID = -7944257841117045698L; - - private long maxFavoriteApps; - - private ApplicationImage defaultApplicationImage; - - public long getMaxFavoriteApps() { - return maxFavoriteApps; - } - - public void setMaxFavoriteApps(long maxFavoriteApps) { - this.maxFavoriteApps = maxFavoriteApps; - } - - public ApplicationImage getDefaultApplicationImage() { - return defaultApplicationImage; - } - - public void setDefaultApplicationImage(ApplicationImage defaultApplicationImage) { - this.defaultApplicationImage = defaultApplicationImage; - } - -} diff --git a/app-center-services/src/main/java/org/exoplatform/appcenter/entity/ApplicationEntity.java b/app-center-services/src/main/java/org/exoplatform/appcenter/entity/ApplicationEntity.java deleted file mode 100644 index 9857fd488..000000000 --- a/app-center-services/src/main/java/org/exoplatform/appcenter/entity/ApplicationEntity.java +++ /dev/null @@ -1,268 +0,0 @@ -/* - * This file is part of the Meeds project (https://meeds.io/). - * Copyright (C) 2020 Meeds Association - * contact@meeds.io - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.exoplatform.appcenter.entity; - -import java.util.Collection; - -import jakarta.persistence.*; - -import org.exoplatform.commons.api.persistence.ExoEntity; - -/** - * @author Ayoub Zayati - */ -@ExoEntity -@Entity(name = "ApplicationEntity") -@Table(name = "AC_APPLICATION") -@NamedQueries({ - @NamedQuery(name = "ApplicationEntity.getAppByTitle", query = "SELECT app FROM ApplicationEntity app " - + "WHERE app.title = :title"), - @NamedQuery(name = "ApplicationEntity.getApplicationsByKeyword", query = "SELECT app FROM ApplicationEntity app " - + "WHERE LOWER(app.title) like :title OR LOWER(app.description) like :description OR LOWER(app.url) like :url ORDER BY LOWER(app.title)"), - @NamedQuery(name = "ApplicationEntity.getApplications", query = "SELECT app FROM ApplicationEntity app ORDER BY LOWER(app.title)"), - @NamedQuery(name = "ApplicationEntity.getSystemApplications", query = "SELECT app FROM ApplicationEntity app WHERE app.system = TRUE"), - @NamedQuery(name = "ApplicationEntity.getMandatoryActiveApps", query = "SELECT app FROM ApplicationEntity app " - + " WHERE app.active = TRUE AND app.isMandatory = TRUE"), }) -public class ApplicationEntity { - - @Id - @SequenceGenerator(name = "SEQ_APPLICATION_ID", sequenceName = "SEQ_APPLICATION_ID", allocationSize = 1) - @GeneratedValue(strategy = GenerationType.AUTO, generator = "SEQ_APPLICATION_ID") - @Column(name = "ID") - private Long id; - - @Column(name = "TITLE") - private String title; - - @Column(name = "URL") - private String url; - - @Column(name = "HELP_PAGE_URL") - private String helpPageUrl; - - @Column(name = "IMAGE_FILE_ID") - private Long imageFileId; - - @Column(name = "DESCRIPTION") - private String description; - - @Column(name = "ACTIVE") - private boolean active; - - @Column(name = "BY_DEFAULT") - private boolean isMandatory; - - @Column(name = "IS_MOBILE") - private boolean isMobile; - - @Column(name = "IS_SYSTEM") - private Boolean system; - - @Column(name = "PERMISSIONS") - private String permissions; - - @Column(name = "IS_CHANGED_MANUALLY") - private Boolean isChangedManually; - - @OneToMany(fetch = FetchType.LAZY, mappedBy = "application", cascade = CascadeType.REMOVE) - private Collection favorites; - - public ApplicationEntity() { - } - - public ApplicationEntity(Long id, - String title, - String url, - Long imageFileId, - String description, - boolean active, - boolean isMandatory, - String permissions, - boolean isChangedManually) { - this.id = id; - this.title = title; - this.url = url; - this.imageFileId = imageFileId; - this.description = description; - this.active = active; - this.isMandatory = isMandatory; - this.permissions = permissions; - this.isChangedManually = isChangedManually; - } - - /** - * @return the id - */ - public Long getId() { - return id; - } - - /** - * @param id the id to set - */ - public void setId(Long id) { - this.id = id; - } - - /** - * @return the title - */ - public String getTitle() { - return title; - } - - /** - * @param title the title to set - */ - public void setTitle(String title) { - this.title = title; - } - - /** - * @return the url - */ - public String getUrl() { - return url; - } - - /** - * @param url the url to set - */ - public void setUrl(String url) { - this.url = url; - } - - /** - * @return the help page url - */ - public String getHelpPageUrl() { - return helpPageUrl; - } - - /** - * @param helpPageUrl the help page url to set - */ - public void setHelpPageUrl(String helpPageUrl) { - this.helpPageUrl = helpPageUrl; - } - - /** - * @return the imageFileId - */ - public Long getImageFileId() { - return imageFileId; - } - - /** - * @param imageFileId the imageFileId to set - */ - public void setImageFileId(Long imageFileId) { - this.imageFileId = imageFileId; - } - - /** - * @return the description - */ - public String getDescription() { - return description; - } - - /** - * @param description the description to set - */ - public void setDescription(String description) { - this.description = description; - } - - /** - * @return the active - */ - public boolean isActive() { - return active; - } - - /** - * @param active the active to set - */ - public void setActive(boolean active) { - this.active = active; - } - - /** - * @return the isMandatory - */ - public boolean isMandatory() { - return isMandatory; - } - - /** - * @param mandatory the isMandatory to set - */ - public void setMandatory(boolean mandatory) { - this.isMandatory = mandatory; - } - - /** - * @return the isMobile - */ - public boolean isMobile() { - return isMobile; - } - - /** - * @param isMobile the isMobile to set - */ - public void setIsMobile(boolean isMobile) { - this.isMobile = isMobile; - } - - /** - * @return the permissions - */ - public String getPermissions() { - return permissions; - } - - /** - * @param permissions the permissions to set - */ - public void setPermissions(String permissions) { - this.permissions = permissions; - } - - public boolean isSystem() { - return system != null && system; - } - - public void setSystem(boolean system) { - this.system = system; - } - - /** - * @return the isChangedManually - */ - public boolean isChangedManually() { - return isChangedManually; - } - - /** - * @param isChangedManually the isChangedManually to set - */ - public void setChangedManually(boolean isChangedManually) { - isChangedManually = isChangedManually; - } -} diff --git a/app-center-services/src/main/java/org/exoplatform/appcenter/entity/FavoriteApplicationEntity.java b/app-center-services/src/main/java/org/exoplatform/appcenter/entity/FavoriteApplicationEntity.java deleted file mode 100644 index 657402874..000000000 --- a/app-center-services/src/main/java/org/exoplatform/appcenter/entity/FavoriteApplicationEntity.java +++ /dev/null @@ -1,127 +0,0 @@ -/* - * This file is part of the Meeds project (https://meeds.io/). - * Copyright (C) 2020 Meeds Association - * contact@meeds.io - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.exoplatform.appcenter.entity; - -import jakarta.persistence.*; - -import org.exoplatform.commons.api.persistence.ExoEntity; - -/** - * @author Ayoub Zayati - */ -@Entity(name = "FavoriteApplicationEntity") -@ExoEntity -@Table(name = "AC_FAVORITE_APPLICATION") -@NamedQueries({ - @NamedQuery(name = "FavoriteApplicationEntity.getFavoriteAppByUserNameAndAppId", query = "SELECT distinct(favoriteApp) FROM FavoriteApplicationEntity favoriteApp " - + " WHERE favoriteApp.application.id = :applicationId AND favoriteApp.userName = :userName"), - @NamedQuery(name = "FavoriteApplicationEntity.getFavoriteAppsByAppId", query = "SELECT distinct(favoriteApp) FROM FavoriteApplicationEntity favoriteApp " - + " WHERE favoriteApp.application.id = :applicationId"), - @NamedQuery(name = "FavoriteApplicationEntity.countFavoritesByUser", query = "SELECT count(*) FROM FavoriteApplicationEntity favoriteApp " - + " WHERE favoriteApp.userName = :userName"), - @NamedQuery(name = "FavoriteApplicationEntity.getFavoriteAppsByUser", query = "SELECT favoriteApp FROM FavoriteApplicationEntity favoriteApp" - + " WHERE favoriteApp.userName = :userName ORDER BY favoriteApp.order NULLS LAST"), - -}) -public class FavoriteApplicationEntity { - - @Id - @SequenceGenerator(name = "SEQ_FAVORITE_APPLICATION_ID", sequenceName = "SEQFAVORITE_APPLICATION_ID", allocationSize = 1) - @GeneratedValue(strategy = GenerationType.AUTO, generator = "SEQ_FAVORITE_APPLICATION_ID") - @Column(name = "ID") - private Long id; - - @ManyToOne(fetch = FetchType.LAZY) - @JoinColumn(name = "APPLICATION_ID") - private ApplicationEntity application; - - @Column(name = "USER_NAME") - private String userName; - - @Column(name = "APPLICATION_ORDER") - private Long order; - - public FavoriteApplicationEntity() { - } - - public FavoriteApplicationEntity(ApplicationEntity application, String userName) { - this.application = application; - this.userName = userName; - } - - public FavoriteApplicationEntity(ApplicationEntity application, String userName, Long order) { - this.application = application; - this.userName = userName; - this.order = order; - } - - /** - * @return the id - */ - public Long getId() { - return id; - } - - /** - * @param id the id to set - */ - public void setId(Long id) { - this.id = id; - } - - /** - * @return the application - */ - public ApplicationEntity getApplication() { - return application; - } - - /** - * @param application the application to set - */ - public void setApplication(ApplicationEntity application) { - this.application = application; - } - - /** - * @return the userName - */ - public String getUserName() { - return userName; - } - - /** - * @param userName the userName to set - */ - public void setUserName(String userName) { - this.userName = userName; - } - - /** - * @return the application's order - */ - public Long getOrder() { - return order; - } - - /** - * @param order the application's order - */ - public void setOrder(Long order) { - this.order = order; - } -} diff --git a/app-center-services/src/main/java/org/exoplatform/appcenter/plugin/ApplicationPlugin.java b/app-center-services/src/main/java/org/exoplatform/appcenter/plugin/ApplicationPlugin.java deleted file mode 100644 index 29a9920b1..000000000 --- a/app-center-services/src/main/java/org/exoplatform/appcenter/plugin/ApplicationPlugin.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - * This file is part of the Meeds project (https://meeds.io/). - * Copyright (C) 2020 Meeds Association - * contact@meeds.io - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.exoplatform.appcenter.plugin; - -import org.exoplatform.appcenter.dto.Application; -import org.exoplatform.container.component.BaseComponentPlugin; -import org.exoplatform.container.xml.InitParams; - -public class ApplicationPlugin extends BaseComponentPlugin { - - private Application application; - - private boolean enabled; - - private String imagePath; - - private boolean override; - - private String overrideMode; - - public ApplicationPlugin(InitParams params) { - if (params == null || !params.containsKey("application")) { - throw new IllegalArgumentException("params containing 'application' parameter of plugin is mandatory"); - } - - application = (Application) params.getObjectParam("application").getObject(); - if (application == null) { - throw new IllegalStateException("'application' init parameter is null"); - } - - if(params.containsKey("enabled")) { - this.enabled = Boolean.parseBoolean(params.getValueParam("enabled").getValue()); - } else { - this.enabled = true; - } - - if (params.containsKey("imagePath")) { - this.imagePath = params.getValueParam("imagePath").getValue(); - } - - if (params.containsKey("override")) { - this.override = Boolean.parseBoolean(params.getValueParam("override").getValue()); - } - if (params.containsKey("override-mode")) { - this.overrideMode = params.getValueParam("override-mode").getValue(); - } - } - - public Application getApplication() { - return application; - } - - public String getImagePath() { - return imagePath; - } - - public boolean isEnabled() { - return enabled; - } - - public boolean isOverride() { - return override; - } - public String getOverrideMode(){ - return overrideMode; - } -} diff --git a/app-center-services/src/main/java/org/exoplatform/appcenter/rest/ApplicationCenterREST.java b/app-center-services/src/main/java/org/exoplatform/appcenter/rest/ApplicationCenterREST.java deleted file mode 100644 index 1014c5d76..000000000 --- a/app-center-services/src/main/java/org/exoplatform/appcenter/rest/ApplicationCenterREST.java +++ /dev/null @@ -1,561 +0,0 @@ -/* - * This file is part of the Meeds project (https://meeds.io/). - * Copyright (C) 2020 Meeds Association - * contact@meeds.io - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.exoplatform.appcenter.rest; - -import java.io.InputStream; -import java.net.MalformedURLException; -import java.util.*; - -import javax.annotation.security.RolesAllowed; -import javax.ws.rs.*; -import javax.ws.rs.core.*; -import javax.ws.rs.core.Response.Status; - -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.Parameter; -import io.swagger.v3.oas.annotations.parameters.RequestBody; -import io.swagger.v3.oas.annotations.responses.ApiResponse; -import io.swagger.v3.oas.annotations.responses.ApiResponses; -import io.swagger.v3.oas.annotations.tags.Tag; -import org.exoplatform.appcenter.dto.*; -import org.exoplatform.appcenter.dto.Application; -import org.exoplatform.appcenter.service.*; -import org.exoplatform.common.http.HTTPStatus; -import org.exoplatform.container.PortalContainer; -import org.exoplatform.services.log.ExoLogger; -import org.exoplatform.services.log.Log; -import org.exoplatform.services.rest.resource.ResourceContainer; -import org.exoplatform.services.security.ConversationState; -import org.exoplatform.services.security.MembershipEntry; - -import org.exoplatform.services.rest.http.PATCH; - -@Path("app-center") -@RolesAllowed("users") -@Tag(name = "/app-center", description = "Manage and access application center applications") // NOSONAR -public class ApplicationCenterREST implements ResourceContainer { - - private static final String APPLICATIONS_ENDPOINT = "applications"; - - private static final String SETTINGS_ENDPOINT = "settings"; - - private static final String FAVORITES_APPLICATIONS_ENDPOINT = "applications/favorites"; - - private static final String AUTHORIZED_APPLICATIONS_ENDPOINT = "applications/authorized"; - - private static final String LOG_OPEN_DRAWER_ENDPOINT = "applications/logOpenDrawer"; - - private static final String LOG_CLICK_ALL_APPLICATIONS_ENDPOINT = "applications/logClickAllApplications"; - - private static final String LOG_CLICK_ONE_APPLICATION_ENDPOINT = "applications/logClickApplication"; - - private static final String ADMINISTRATORS_GROUP = "/platform/administrators"; - - private static final int CACHE_DURATION_SECONDS = 31536000; - - private static final long CACHE_DURATION_MILLISECONDS = CACHE_DURATION_SECONDS * 1000l; - - private static final CacheControl ILLUSTRATION_CACHE_CONTROL = new CacheControl(); - - static { - ILLUSTRATION_CACHE_CONTROL.setMaxAge(CACHE_DURATION_SECONDS); - } - - private static final Log LOG = ExoLogger.getLogger(ApplicationCenterREST.class); - - private ApplicationCenterService appCenterService; - - private final String baseURI; - - public ApplicationCenterREST(ApplicationCenterService appCenterService, PortalContainer container) { - this.appCenterService = appCenterService; - this.baseURI = "/" + container.getName() + "/" + container.getRestContextName() + "/"; - } - - @GET - @Produces(MediaType.APPLICATION_JSON) - @RolesAllowed("users") - @Operation( - summary = "Retrieves all available sub resources of current endpoint", - method = "GET", - description = "Retrieves all available sub resources of current endpoint") - @ApiResponses(value = { @ApiResponse(responseCode = "200", description = "Request fulfilled"), - @ApiResponse(responseCode = "500", description = "Internal server error") }) - public Response getAvailableSubResources() { - try { - Map> availableEnpoints = new HashMap<>(); - ConversationState current = ConversationState.getCurrent(); - if (current.getIdentity().isMemberOf(new MembershipEntry(ADMINISTRATORS_GROUP, "*"))) { - availableEnpoints.put("subResourcesHref", - Arrays.asList(this.baseURI + FAVORITES_APPLICATIONS_ENDPOINT, - this.baseURI + AUTHORIZED_APPLICATIONS_ENDPOINT, - this.baseURI + SETTINGS_ENDPOINT, - this.baseURI + APPLICATIONS_ENDPOINT)); - } else { - availableEnpoints.put("subResourcesHref", - Arrays.asList(this.baseURI + FAVORITES_APPLICATIONS_ENDPOINT, - this.baseURI + AUTHORIZED_APPLICATIONS_ENDPOINT, - this.baseURI + SETTINGS_ENDPOINT)); - } - return Response.ok(availableEnpoints).build(); - } catch (Exception e) { - LOG.error("Unknown error occurred while updating application", e); - return Response.serverError().build(); - } - } - - @GET - @Path(APPLICATIONS_ENDPOINT) - @Produces(MediaType.APPLICATION_JSON) - @RolesAllowed("administrators") - @Operation( - summary = "Retrieves all available applications", - method = "GET", - description = "Return list of applications in json format") - @ApiResponses(value = { @ApiResponse(responseCode = "200", description = "Request fulfilled"), - @ApiResponse(responseCode = "500", description = "Internal server error") }) - public Response getApplicationsList(@Parameter(description = "Query Offset", required = true) @QueryParam("offset") int offset, - @Parameter(description = "Query results limit", required = true) @QueryParam("limit") int limit, - @Parameter(description = "Keyword to search in applications title and url", required = true) @QueryParam("keyword") String keyword) { - try { - ApplicationList applicationList = appCenterService.getApplicationsList(offset, limit, keyword); - return Response.ok(applicationList).build(); - } catch (Exception e) { - LOG.error("Unknown error occurred while updating application", e); - return Response.serverError().build(); - } - } - - @GET - @Path(AUTHORIZED_APPLICATIONS_ENDPOINT) - @Produces(MediaType.APPLICATION_JSON) - @RolesAllowed("users") - @Operation( - summary = "Retrieves all authorized applications for currently authenticated user", - method = "GET", - description = "Return list of applications in json format") - @ApiResponses(value = { @ApiResponse(responseCode = "200", description = "Request fulfilled"), - @ApiResponse(responseCode = "500", description = "Internal server error") }) - public Response getAuthorizedApplicationsList(@Parameter(description = "Query Offset", required = true) @QueryParam("offset") int offset, - @Parameter(description = "Query results limit", required = true) @QueryParam("limit") int limit, - @Parameter(description = "Keyword to search in applications title and url", required = true) @QueryParam("keyword") String keyword) { - - try { - ApplicationList applicationList = appCenterService.getAuthorizedApplicationsList(offset, - limit, - keyword, - getCurrentUserName()); - return Response.ok(applicationList).build(); - } catch (Exception e) { - LOG.error("Unknown error occurred while updating application", e); - return Response.serverError().build(); - } - } - - @GET - @Path(FAVORITES_APPLICATIONS_ENDPOINT) - @Produces(MediaType.APPLICATION_JSON) - @RolesAllowed("users") - @Operation( - summary = "Retrieves favorite applications for currently authenticated user", - method = "GET", - description = "Return list of applications in json format") - @ApiResponses(value = { @ApiResponse(responseCode = "200", description = "Request fulfilled"), - @ApiResponse(responseCode = "500", description = "Internal server error") }) - public Response getFavoriteApplicationsList() { - try { - ApplicationList applicationList = appCenterService.getMandatoryAndFavoriteApplicationsList(getCurrentUserName()); - return Response.ok(applicationList).build(); - } catch (Exception e) { - LOG.error("Unknown error occurred while updating application", e); - return Response.serverError().build(); - } - } - - @GET - @Path(LOG_CLICK_ALL_APPLICATIONS_ENDPOINT) - @RolesAllowed("users") - @Operation( - summary = "Log that the currently authenticated user clicked on View All Applications button", - method = "GET", - description = "Log that the currently authenticated user clicked on View All Applications button and returns an empty response") - @ApiResponses(value = { @ApiResponse(responseCode = "200", description = "Request fulfilled"), - @ApiResponse(responseCode = "500", description = "Internal server error") }) - public Response logClickAllApplications() { - try { - LOG.info("service={} operation={} parameters=\"user:{}\" status=ok " + "duration_ms={}", - ApplicationCenterService.LOG_SERVICE_NAME, - ApplicationCenterService.LOG_CLICK_ALL_APPLICATIONS, - getCurrentUserName(), - "0"); - return Response.ok().build(); - } catch (Exception e) { - LOG.error("Unknown error occurred while updating application", e); - return Response.serverError().build(); - } - } - - - @GET - @Path(LOG_CLICK_ONE_APPLICATION_ENDPOINT+ "/{applicationId}") - @RolesAllowed("users") - @Operation( - summary = "Log that the currently authenticated user clicked on one Application", - method = "GET", - description = "Log that the currently authenticated user clicked on one Application and returns an empty response") - @ApiResponses(value = { @ApiResponse(responseCode = "200", description = "Request fulfilled"), - @ApiResponse(responseCode = "500", description = "Internal server error") }) - public Response logClickOneApplications(@Parameter(description = "Application technical id to log", required = true) @PathParam("applicationId") Long applicationId) { - try { - Application application = appCenterService.findApplication(applicationId); - - LOG.info("service={} operation={} parameters=\"user:{},applicationId={},applicationName={}\" status=ok " + "duration_ms={}", - ApplicationCenterService.LOG_SERVICE_NAME, - ApplicationCenterService.LOG_OPEN_APPLICATION, - getCurrentUserName(), - applicationId, - application.getTitle(), - "0"); - return Response.ok().build(); - } catch (Exception e) { - LOG.error("Unknown error occurred while updating application", e); - return Response.serverError().build(); - } - } - - @GET - @Path(LOG_OPEN_DRAWER_ENDPOINT) - @RolesAllowed("users") - @Operation( - summary = "Log that the currently authenticated user has opened the favorites drawer", - method = "GET", - description = "Log that the currently authenticated user has opened the favorites drawer and returns an empty response") - @ApiResponses(value = { @ApiResponse(responseCode = "200", description = "Request fulfilled"), - @ApiResponse(responseCode = "500", description = "Internal server error") }) - public Response logOpenDrawer() { - try { - LOG.info("service={} operation={} parameters=\"user:{}\" status=ok " + "duration_ms={}", - ApplicationCenterService.LOG_SERVICE_NAME, - ApplicationCenterService.LOG_OPEN_FAVORITE_DRAWER, - getCurrentUserName(), - "0"); - return Response.ok().build(); - } catch (Exception e) { - LOG.error("Unknown error occurred while updating application", e); - return Response.serverError().build(); - } - } - - @GET - @Path(SETTINGS_ENDPOINT) - @Produces(MediaType.APPLICATION_JSON) - @RolesAllowed("users") - @Operation( - summary = "Modifies default application image setting", - method = "GET", - description = "Modifies default application image setting and returns an empty response") - @ApiResponses(value = { @ApiResponse(responseCode = "204", description = "Request fulfilled"), - @ApiResponse(responseCode = "500", description = "Internal server error") }) - public Response getAppGeneralSettings() { - try { - GeneralSettings generalSettings = appCenterService.getAppGeneralSettings(); - return Response.ok(generalSettings).build(); - } catch (ApplicationNotFoundException e) { - LOG.warn(e); - return Response.serverError().build(); - } catch (Exception e) { - LOG.error("Unknown error occurred while updating application", e); - return Response.serverError().build(); - } - } - - @POST - @Path(APPLICATIONS_ENDPOINT) - @Consumes(MediaType.APPLICATION_JSON) - @RolesAllowed("administrators") - @Operation( - summary = "Creates a new application in application center", - method = "GET", - description = "Creates a new application in application center and returns an empty response") - @ApiResponses(value = { @ApiResponse(responseCode = "204", description = "Request fulfilled"), - @ApiResponse(responseCode = "401", description = "Unauthorized operation"), - @ApiResponse(responseCode = "500", description = "Internal server error") }) - public Response createApplication(@RequestBody(description = "Application to save", required = true) Application application) { - try { - appCenterService.createApplication(application); - } catch (MalformedURLException malformedURLException) { - LOG.error("The application URL or the application help page URL is malformed: {}", malformedURLException.getMessage()); - return Response.serverError().build(); - } catch (ApplicationAlreadyExistsException e) { - LOG.warn(e); - return Response.serverError().build(); - } catch (Exception e) { - LOG.error("Unknown error occurred while creating application", e); - return Response.serverError().build(); - } - return Response.noContent().build(); - } - - @PUT - @Path(APPLICATIONS_ENDPOINT) - @RolesAllowed("administrators") - @Operation( - summary = "Updates an existing application identified by its id or title or url", - method = "GET", - description = "Updates an existing application identified by its id or title or url") - @ApiResponses(value = { @ApiResponse(responseCode = "204", description = "Request fulfilled"), - @ApiResponse(responseCode = "401", description = "Unauthorized operation"), - @ApiResponse(responseCode = "500", description = "Internal server error") }) - public Response updateApplication(@RequestBody(description = "Application to update", required = true) Application application) { - try { - application.setChangedManually(true); - appCenterService.updateApplication(application, getCurrentUserName()); - } catch (IllegalAccessException e) { - LOG.warn(e); - return Response.status(HTTPStatus.UNAUTHORIZED).build(); - } catch (ApplicationAlreadyExistsException e) { - LOG.warn(e); - return Response.serverError().build(); - } catch (Exception e) { - LOG.error("Unknown error occurred while updating application", e); - return Response.serverError().build(); - } - return Response.noContent().build(); - } - - @DELETE - @Path(APPLICATIONS_ENDPOINT + "/{applicationId}") - @RolesAllowed("administrators") - @Operation( - summary = "Deletes an existing application identified by its id", - method = "GET", - description = "Deletes an existing application identified by its id") - @ApiResponses(value = { @ApiResponse(responseCode = "204", description = "Request fulfilled"), - @ApiResponse(responseCode = "401", description = "Unauthorized operation"), - @ApiResponse(responseCode = "500", description = "Internal server error") }) - public Response deleteApplication(@Parameter(description = "Application technical id to delete", required = true) @PathParam("applicationId") Long applicationId) { - try { - appCenterService.deleteApplication(applicationId, getCurrentUserName()); - } catch (IllegalAccessException e) { - LOG.warn(e); - return Response.status(HTTPStatus.UNAUTHORIZED).build(); - } catch (ApplicationNotFoundException e) { - LOG.warn(e); - return Response.serverError().build(); - } catch (Exception e) { - LOG.error("Unknown error occurred while deleting application", e); - return Response.serverError().build(); - } - return Response.noContent().build(); - } - - @POST - @Path(FAVORITES_APPLICATIONS_ENDPOINT + "/{applicationId}") - @RolesAllowed("users") - @Operation( - summary = "Adds an existing application identified by its id as favorite for current authenticated user", - method = "GET", - description = "Adds an existing application identified by its id as favorite for current authenticated user") - @ApiResponses(value = { @ApiResponse(responseCode = "204", description = "Request fulfilled"), - @ApiResponse(responseCode = "500", description = "Internal server error") }) - public Response addFavoriteApplication(@Parameter(description = "Application technical id to add as favorite", required = true) @PathParam("applicationId") Long applicationId) { - try { - long startTime = System.currentTimeMillis(); - Application application = appCenterService.findApplication(applicationId); - appCenterService.addFavoriteApplication(applicationId, getCurrentUserName()); - long endTime = System.currentTimeMillis(); - long totalTime = endTime - startTime; - LOG.info("service={} operation={} parameters=\"user:{},applicationId={},applicationName={}\" status=ok " + "duration_ms={}", - ApplicationCenterService.LOG_SERVICE_NAME, - ApplicationCenterService.LOG_ADD_FAVORITE, - getCurrentUserName(), - applicationId, - application.getTitle(), - totalTime); - return Response.noContent().build(); - } catch (IllegalAccessException e) { - LOG.warn(e); - return Response.status(HTTPStatus.UNAUTHORIZED).build(); - } catch (ApplicationNotFoundException e) { - LOG.warn(e); - return Response.serverError().build(); - } catch (Exception e) { - LOG.error("Unknown error occurred while adding application as favorite", e); - return Response.serverError().build(); - } - } - - @PUT - @Path(FAVORITES_APPLICATIONS_ENDPOINT) - @RolesAllowed("users") - @Operation( - summary = "Updates an existing application's order identified by its id", - method = "GET", - description = "Updates an existing application's order identified by its id and returns an empty response") - @ApiResponses(value = { @ApiResponse(responseCode = "204", description = "Request fulfilled"), - @ApiResponse(responseCode = "401", description = "Unauthorized operation"), - @ApiResponse(responseCode = "500", description = "Internal server error") }) - public Response updateApplicationsOrder(@RequestBody(description = "Application to update", required = true) List applicationOrders) { - try { - long startTime = System.currentTimeMillis(); - for (ApplicationOrder applicationOrder : applicationOrders) { - appCenterService.updateFavoriteApplicationOrder(applicationOrder, getCurrentUserName()); - } - long endTime = System.currentTimeMillis(); - long totalTime = endTime - startTime; - LOG.info("service={} operation={} parameters=\"user:{}\" status=ok " + "duration_ms={}", - ApplicationCenterService.LOG_SERVICE_NAME, - ApplicationCenterService.LOG_REORGANIZE_FAVORITES, - getCurrentUserName(), - totalTime); - } catch (ApplicationNotFoundException e) { - LOG.warn(e); - return Response.serverError().build(); - } catch (Exception e) { - LOG.error("Unknown error occurred while adding application as favorite", e); - return Response.serverError().build(); - } - return Response.noContent().build(); - } - - @DELETE - @Path(FAVORITES_APPLICATIONS_ENDPOINT + "/{applicationId}") - @RolesAllowed("users") - @Operation( - summary = "Deletes an existing application identified by its id from current authenticated user favorites", - method = "GET", - description = "Deletes an existing application identified by its id from current authenticated user favorites and returns an empty response") - @ApiResponses(value = { @ApiResponse(responseCode = "204", description = "Request fulfilled"), - @ApiResponse(responseCode = "500", description = "Internal server error") }) - public Response deleteFavoriteApplication(@Parameter(description = "Application technical id to delete from favorite", required = true) @PathParam("applicationId") Long applicationId) { - try { - long startTime = System.currentTimeMillis(); - Application application = appCenterService.findApplication(applicationId); - appCenterService.deleteFavoriteApplication(applicationId, getCurrentUserName()); - long endTime = System.currentTimeMillis(); - long totalTime = endTime - startTime; - LOG.info("service={} operation={} parameters=\"user:{},applicationId={},applicationName={}\" status=ok " + "duration_ms={}", - ApplicationCenterService.LOG_SERVICE_NAME, - ApplicationCenterService.LOG_REMOVE_FAVORITE, - getCurrentUserName(), - applicationId, - application.getTitle(), - totalTime); - return Response.noContent().build(); - } catch (Exception e) { - LOG.error("Unknown error occurred while deleting application from favorites", e); - return Response.serverError().build(); - } - } - - @PATCH - @Path(SETTINGS_ENDPOINT + "/maxFavorites") - @RolesAllowed("administrators") - @Operation( - summary = "Modifies maximum application count to add as favorites for all users", - method = "GET", - description = "Modifies maximum application count to add as favorites for all users") - @ApiResponses(value = { @ApiResponse(responseCode = "204", description = "Request fulfilled"), - @ApiResponse(responseCode = "500", description = "Internal server error") }) - public Response setMaxFavoriteApps(@Parameter(description = "Max favorites number", required = true) @QueryParam("number") long number) { - try { - appCenterService.setMaxFavoriteApps(number); - } catch (Exception e) { - LOG.error("Unknown error occurred while updating application", e); - return Response.serverError().build(); - } - return Response.noContent().build(); - } - - @PATCH - @Path(SETTINGS_ENDPOINT + "/image") - @Consumes(MediaType.APPLICATION_JSON) - @RolesAllowed("administrators") - @Operation( - summary = "Modifies default application image setting", - method = "GET", - description = "Modifies default application image setting") - @ApiResponses(value = { @ApiResponse(responseCode = "204", description = "Request fulfilled"), - @ApiResponse(responseCode = "500", description = "Internal server error") }) - public Response setDefaultAppImage(@Parameter(description = "Application image id, body and name", required = true) ApplicationImage defaultAppImage) { - try { - appCenterService.setDefaultAppImage(defaultAppImage); - return Response.noContent().build(); - } catch (Exception e) { - LOG.error("Unknown error occurred while updating application", e); - return Response.serverError().build(); - } - } - - @GET - @Path(APPLICATIONS_ENDPOINT + "/illustration/{applicationId}") - @RolesAllowed("users") - @Operation( - summary = "Gets an application illustration by application id", - method = "GET", - description = "This can only be done by the logged in user.") - @ApiResponses(value = { @ApiResponse(responseCode = "200", description = "Request fulfilled"), - @ApiResponse(responseCode = "500", description = "Internal server error"), - @ApiResponse(responseCode = "400", description = "Invalid query input"), - @ApiResponse(responseCode = "404", description = "Resource not found") }) - public Response getApplicationIllustration(@Context Request request, - @Parameter(description = "Application id", required = true) @PathParam("applicationId") long applicationId, - @Parameter(description = "Optional last modified parameter") @QueryParam("v") long lastModified) { - try { - Long lastUpdated = appCenterService.getApplicationImageLastUpdated(applicationId, getCurrentUserName()); - if (lastUpdated == null) { - return Response.status(404).build(); - } - EntityTag eTag = new EntityTag(String.valueOf(lastUpdated), true); - Response.ResponseBuilder builder = request.evaluatePreconditions(eTag); - if (builder == null) { - InputStream stream = appCenterService.getApplicationImageInputStream(applicationId, getCurrentUserName()); - if (stream == null) { - return Response.status(404).build(); - } - /* - * As recommended in the the RFC1341 - * (https://www.w3.org/Protocols/rfc1341/4_Content-Type.html), we set the avatar - * content-type to "image/png". So, its data would be recognized as "image" by - * the user-agent. - */ - builder = Response.ok(stream, "image/png"); - builder.tag(eTag); - if (lastModified > 0) { - builder.lastModified(new Date(lastUpdated)); - builder.expires(new Date(System.currentTimeMillis() + CACHE_DURATION_MILLISECONDS)); - builder.cacheControl(ILLUSTRATION_CACHE_CONTROL); - } - } - return builder.build(); - } catch (IllegalAccessException e) { - LOG.warn("Unauthorised access to application {} illustration", applicationId, e); - return Response.status(Status.NOT_FOUND).build(); - } catch (ApplicationNotFoundException e) { - return Response.status(Status.NOT_FOUND).build(); - } catch (Exception e) { - LOG.error("An error occurred while getting application illustration", e); - return Response.serverError().build(); - } - } - - private String getCurrentUserName() { - ConversationState state = ConversationState.getCurrent(); - return state == null || state.getIdentity() == null ? null : state.getIdentity().getUserId(); - } - -} diff --git a/app-center-services/src/main/java/org/exoplatform/appcenter/service/ApplicationCenterService.java b/app-center-services/src/main/java/org/exoplatform/appcenter/service/ApplicationCenterService.java deleted file mode 100644 index df0fd3b75..000000000 --- a/app-center-services/src/main/java/org/exoplatform/appcenter/service/ApplicationCenterService.java +++ /dev/null @@ -1,832 +0,0 @@ -/* - * This file is part of the Meeds project (https://meeds.io/). - * Copyright (C) 2020 Meeds Association - * contact@meeds.io - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.exoplatform.appcenter.service; - -import java.io.IOException; -import java.io.InputStream; -import java.net.MalformedURLException; -import java.util.ArrayList; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; -import java.util.regex.Pattern; -import java.util.stream.Collectors; - -import org.apache.commons.io.IOUtils; -import org.apache.commons.lang3.StringUtils; -import java.util.Base64; -import org.picocontainer.Startable; - -import org.exoplatform.appcenter.dto.*; -import org.exoplatform.appcenter.plugin.ApplicationPlugin; -import org.exoplatform.appcenter.storage.ApplicationCenterStorage; -import org.exoplatform.commons.api.settings.SettingService; -import org.exoplatform.commons.api.settings.SettingValue; -import org.exoplatform.commons.api.settings.data.Context; -import org.exoplatform.commons.api.settings.data.Scope; -import org.exoplatform.commons.file.services.FileStorageException; -import org.exoplatform.commons.utils.CommonsUtils; -import org.exoplatform.container.ExoContainerContext; -import org.exoplatform.container.PortalContainer; -import org.exoplatform.container.component.RequestLifeCycle; -import org.exoplatform.container.configuration.ConfigurationManager; -import org.exoplatform.container.xml.ComponentPlugin; -import org.exoplatform.container.xml.InitParams; -import org.exoplatform.portal.config.UserACL; -import org.exoplatform.services.log.ExoLogger; -import org.exoplatform.services.log.Log; -import org.exoplatform.services.security.Authenticator; -import org.exoplatform.services.security.Identity; -import org.exoplatform.services.security.IdentityRegistry; -import org.exoplatform.services.security.MembershipEntry; - -/** - * A Service to access and store applications - */ -public class ApplicationCenterService implements Startable { - - private static final Log LOG = ExoLogger.getLogger(ApplicationCenterService.class); - - public static final String DEFAULT_ADMINISTRATORS_GROUP = "/platform/administrators"; - - public static final String DEFAULT_ADMINISTRATORS_PERMISSION = "*:" + DEFAULT_ADMINISTRATORS_GROUP; - - public static final String ANY_PERMISSION = "any"; - - public static final String DEFAULT_USERS_GROUP = "/platform/users"; - - public static final String DEFAULT_USERS_PERMISSION = "*:" + DEFAULT_USERS_GROUP; - - public static final String MAX_FAVORITE_APPS = "maxFavoriteApps"; - - public static final String DEFAULT_APP_IMAGE_ID = "defaultAppImageId"; - - public static final String DEFAULT_APP_IMAGE_NAME = "defaultAppImageName"; - - public static final String DEFAULT_APP_IMAGE_BODY = "defaultAppImageBody"; - - public static final int DEFAULT_LIMIT = 10; - - private static final Context APP_CENTER_CONTEXT = Context.GLOBAL.id("APP_CENTER"); - - private static final Scope APP_CENTER_SCOPE = Scope.APPLICATION.id("APP_CENTER"); - - private PortalContainer container; - - private ConfigurationManager configurationManager; - - private SettingService settingService; - - private Authenticator authenticator; - - private IdentityRegistry identityRegistry; - - private ApplicationCenterStorage appCenterStorage; - - private String defaultAdministratorPermission = null; - - private long maxFavoriteApps = -1; - - private long defaultMaxFavoriteApps = 0; - - private Map defaultApplications = new LinkedHashMap<>(); - - public static String LOG_SERVICE_NAME = "application-center"; - - public static String LOG_OPEN_FAVORITE_DRAWER = "open-favorite-drawer"; - - public static String LOG_CLICK_ALL_APPLICATIONS = "click-all-applications"; - - public static final String LOG_OPEN_APPLICATION = "open-application"; - - public static final String LOG_REORGANIZE_FAVORITES = "reorganize-favorites"; - - public static final String LOG_ADD_FAVORITE = "add-favorite"; - public static final String LOG_REMOVE_FAVORITE = "remove-favorite"; - public static final String MERGE_MODE = "merge"; - - public ApplicationCenterService(ConfigurationManager configurationManager, - ApplicationCenterStorage appCenterStorage, - SettingService settingService, - IdentityRegistry identityRegistry, - Authenticator authenticator, - PortalContainer container, - InitParams params) { - this.container = container; - this.configurationManager = configurationManager; - this.settingService = settingService; - this.authenticator = authenticator; - this.identityRegistry = identityRegistry; - this.appCenterStorage = appCenterStorage; - - if (params != null && params.containsKey("default.administrators.expression")) { - this.defaultAdministratorPermission = params.getValueParam("default.administrators.expression").getValue(); - } - if (params != null && params.containsKey("default.favorites")) { - this.defaultMaxFavoriteApps = Long.parseLong(params.getValueParam("default.favorites").getValue()); - } - if (StringUtils.isBlank(this.defaultAdministratorPermission)) { - this.defaultAdministratorPermission = DEFAULT_ADMINISTRATORS_PERMISSION; - } - } - - /** - * A method that will be invoked when the server starts ( - * {@link PortalContainer} starts ) to inject default application and to delete - * injected default applications - */ - @Override - public void start() { - ExoContainerContext.setCurrentContainer(container); - RequestLifeCycle.begin(this.container); - try { - List systemApplications = appCenterStorage.getSystemApplications(); - systemApplications.forEach(application -> { - if (!isDefaultSystemApplication(application)) { - try { - LOG.info("Delete application '{}' that was previously injected as system application and that doesn't exist in configuration anymore", - application.getTitle()); - appCenterStorage.deleteApplication(application.getId()); - } catch (Exception e) { - LOG.warn("An unknown error occurs while deleting not found system application '{}' in store", - application.getTitle(), - e); - } - } - }); - - this.defaultApplications.values().forEach(applicationPlugin -> { - Application application = applicationPlugin.getApplication(); - String pluginName = applicationPlugin.getName(); - if (application == null) { - LOG.warn("An application plugin '{}' holds an empty application", pluginName); - return; - } - - String title = application.getTitle(); - if (StringUtils.isBlank(title)) { - LOG.warn("Plugin '{}' has an application with empty title, it will not be injected", pluginName); - return; - } - - String url = application.getUrl(); - if (StringUtils.isBlank(url)) { - LOG.warn("Plugin '{}' has an application with empty url, it will not be injected", pluginName); - return; - } - - Application storedApplication = appCenterStorage.getApplicationByTitle(title); - if (storedApplication != null && !applicationPlugin.isOverride() && storedApplication.isChangedManually() && ( MERGE_MODE.equals(applicationPlugin.getOverrideMode()) || applicationPlugin.getOverrideMode() == null) ) { - LOG.info("Ignore updating system application '{}', override flag is turned off", application.getTitle()); - return; - } - - List permissions = application.getPermissions(); - if (permissions == null || permissions.isEmpty()) { - // Set default permission if empty - application.setPermissions(DEFAULT_USERS_PERMISSION); - } - - String imagePath = applicationPlugin.getImagePath(); - if (StringUtils.isNotBlank(imagePath)) { - try { - InputStream inputStream = configurationManager.getInputStream(imagePath); - String fileBody = new String(Base64.getEncoder().encode(IOUtils.toByteArray(inputStream))); - application.setImageFileBody(fileBody); - } catch (Exception e) { - LOG.warn("Error reading image from file {}. Application will be injected without image", imagePath, e); - } - } - - if (StringUtils.isBlank(application.getImageFileName())) { - application.setImageFileName(application.getTitle() + ".png"); - } - - if (storedApplication == null) { - try { - LOG.info("Create system application '{}'", application.getTitle()); - application.setSystem(true); - application.setChangedManually(false); - application.setImageFileId(null); - this.createApplication(application); - } catch (Exception e) { - LOG.error("Error creating application {}", application, e); - } - } else { - try { - LOG.info("Update system application '{}'", application.getTitle()); - application.setSystem(true); - application.setChangedManually(false); - application.setId(storedApplication.getId()); - application.setImageFileId(storedApplication.getImageFileId()); - appCenterStorage.updateApplication(application); - } catch (Exception e) { - LOG.error("Error updating application {}", application, e); - } - } - }); - } catch (Exception e) { - LOG.warn("An unknown error occurs while retrieving system applications images", e); - } finally { - RequestLifeCycle.end(); - } - } - - @Override - public void stop() { - // Nothing to do - } - - /** - * Create new Application that will be available for all users. If the - * application already exits an {@link ApplicationAlreadyExistsException} will - * be thrown. - * - * @param application application to create - * @return stored {@link Application} in datasource - * @throws Exception when application already exists or an error occurs while - * creating application or its attached image - */ - public Application createApplication(Application application) throws Exception { - if (application == null) { - throw new IllegalArgumentException("application is mandatory"); - } - Application existingApplication = appCenterStorage.getApplicationByTitle(application.getTitle()); - if (existingApplication != null) { - throw new ApplicationAlreadyExistsException("An application with same title already exists"); - } - - if (!isUrlValid(application.getUrl()) || (application.getHelpPageURL() != null && !application.getHelpPageURL().isBlank() && !isUrlValid(application.getHelpPageURL()))) { - throw new MalformedURLException(); - } - - if (application.getPermissions() == null || application.getPermissions().isEmpty()) { - application.setPermissions(DEFAULT_USERS_PERMISSION); - } - - return appCenterStorage.createApplication(application); - } - - /** - * Get an application by id - * - * @param applicationId application to find - * @return stored {@link Application} in datasource - * @throws Exception when {@link ApplicationNotFoundException} is thrown or an - * error occurs while saving application - */ - public Application findApplication(long applicationId) throws Exception { - Application application = appCenterStorage.getApplicationById(applicationId); - if (application == null) { - throw new ApplicationNotFoundException("Application with id " + applicationId + " wasn't found"); - } - return application; - } - - /** - * Update an existing application on datasource. If the application doesn't exit - * an {@link ApplicationNotFoundException} will be thrown. - * - * @param application dto to update on store - * @param username username storing application - * @return stored {@link Application} in datasource - * @throws Exception when {@link ApplicationNotFoundException} is thrown or an - * error occurs while saving application - */ - public Application updateApplication(Application application, String username) throws Exception { - if (application == null) { - throw new IllegalArgumentException("application is mandatory"); - } - if (StringUtils.isBlank(username)) { - throw new IllegalArgumentException("username is mandatory"); - } - Long applicationId = application.getId(); - if (applicationId == null) { - throw new ApplicationNotFoundException("Application with null id wasn't found"); - } - Application storedApplication = appCenterStorage.getApplicationById(applicationId); - if (storedApplication == null) { - throw new ApplicationNotFoundException("Application with id " + applicationId + " wasn't found"); - } - if (!isAdmin()) { - throw new IllegalAccessException("User " + username + " is not allowed to modify application : " - + storedApplication.getTitle()); - } - - if (application.getPermissions() == null || application.getPermissions().isEmpty()) { - application.setPermissions(DEFAULT_USERS_PERMISSION); - } - - return appCenterStorage.updateApplication(application); - } - - private boolean isAdmin() { - UserACL userACL = CommonsUtils.getService(UserACL.class); - return userACL.isSuperUser() || userACL.isUserInGroup(userACL.getAdminGroups()); - } - - /** - * Delete application identified by its id and check if username has permission - * to delete it. - * - * @param applicationId technical identifier of application - * @param username user currently deleting application - * @throws ApplicationNotFoundException if application wasn't found - * @throws IllegalAccessException if user is not allowed to delete application - */ - public void deleteApplication(Long applicationId, String username) throws ApplicationNotFoundException, - IllegalAccessException, - FileStorageException { - if (applicationId == null || applicationId <= 0) { - throw new IllegalArgumentException("applicationId must be a positive integer"); - } - if (StringUtils.isBlank(username)) { - throw new IllegalArgumentException("username is mandatory"); - } - - Application storedApplication = appCenterStorage.getApplicationById(applicationId); - if (storedApplication == null) { - throw new ApplicationNotFoundException("Application with id " + applicationId + " not found"); - } - if (storedApplication.isSystem()) { - throw new IllegalAccessException("Application with id " + applicationId - + " is a system application, thus it can't be deleted"); - } - - if (!isAdmin()) { - throw new IllegalAccessException("User " + username + " is not allowed to modify application : " - + storedApplication.getTitle()); - } - - appCenterStorage.deleteApplication(applicationId); - } - - /** - * Add an application, identified by its technical id, as favorite of a user - * - * @param applicationId technical application id - * @param username user login - * @throws ApplicationNotFoundException when application is not found - * @throws IllegalAccessException if user hasn't access permission to the - * application - */ - public void addFavoriteApplication(long applicationId, String username) throws ApplicationNotFoundException, - IllegalAccessException, - FileStorageException { - if (StringUtils.isBlank(username)) { - throw new IllegalArgumentException("username is mandatory"); - } - if (applicationId <= 0) { - throw new IllegalArgumentException("applicationId must be a positive integer"); - } - Application application = appCenterStorage.getApplicationById(applicationId); - if (application == null) { - throw new ApplicationNotFoundException("Application with id " + applicationId + " wasn't found in store"); - } - if (!hasPermission(username, application)) { - throw new IllegalAccessException("User " + username + " doesn't have enough permissions to delete application " - + application.getTitle()); - } - appCenterStorage.addApplicationToUserFavorite(applicationId, username); - } - - /** - * Deletes an application identified by its id from favorite applications of - * user - * - * @param applicationId application technical identifier - * @param username login of user currently deleting application - */ - public void deleteFavoriteApplication(Long applicationId, String username) { - if (applicationId == null || applicationId <= 0) { - throw new IllegalArgumentException("applicationId must be a positive integer"); - } - if (StringUtils.isBlank(username)) { - throw new IllegalArgumentException("username is mandatory"); - } - appCenterStorage.deleteApplicationFavorite(applicationId, username); - } - - /** - * Change general setting for maximum allowed favorites that a user can have - * - * @param maxFavoriteApplications max favorite applications count - */ - public void setMaxFavoriteApps(long maxFavoriteApplications) { - if (maxFavoriteApplications >= 0) { - settingService.set(APP_CENTER_CONTEXT, APP_CENTER_SCOPE, MAX_FAVORITE_APPS, SettingValue.create(maxFavoriteApplications)); - this.maxFavoriteApps = maxFavoriteApplications; - } else { - settingService.remove(APP_CENTER_CONTEXT, APP_CENTER_SCOPE, MAX_FAVORITE_APPS); - this.maxFavoriteApps = -1; - } - } - - /** - * @return the maximum favorite applications that a user can have as favorite - */ - public long getMaxFavoriteApps() { - if (this.maxFavoriteApps < 0) { - SettingValue maxFavoriteAppsValue = settingService.get(APP_CENTER_CONTEXT, APP_CENTER_SCOPE, MAX_FAVORITE_APPS); - if (maxFavoriteAppsValue != null && maxFavoriteAppsValue.getValue() != null) { - this.maxFavoriteApps = Long.parseLong(maxFavoriteAppsValue.getValue().toString()); - } else { - this.maxFavoriteApps = this.defaultMaxFavoriteApps; - } - } - return this.maxFavoriteApps; - } - - /** - * Stores default image for applications not having an attached illustration - * - * @param defaultAppImage image content and name - * @return stored image - * @throws Exception if an exception occurs while storing image into database - */ - public ApplicationImage setDefaultAppImage(ApplicationImage defaultAppImage) throws Exception { - if (defaultAppImage == null - || (StringUtils.isBlank(defaultAppImage.getFileName()) && StringUtils.isBlank(defaultAppImage.getFileBody()))) { - settingService.remove(APP_CENTER_CONTEXT, APP_CENTER_SCOPE, DEFAULT_APP_IMAGE_ID); - } else { - ApplicationImage applicationImage = appCenterStorage.saveAppImageFileItem(defaultAppImage); - if (applicationImage != null && applicationImage.getId() != null && applicationImage.getId() > 0) { - settingService.set(APP_CENTER_CONTEXT, - APP_CENTER_SCOPE, - DEFAULT_APP_IMAGE_ID, - SettingValue.create(String.valueOf(applicationImage.getId()))); - return applicationImage; - } - } - return null; - } - - /** - * @return {@link GeneralSettings} of application including default image and - * maximum favorite applications count - * @throws Exception if an exception occurs while retrieving image data from - * store - */ - public GeneralSettings getAppGeneralSettings() throws Exception { // NOSONAR - GeneralSettings generalsettings = new GeneralSettings(); - generalsettings.setMaxFavoriteApps(getMaxFavoriteApps()); - - Long defaultAppImageId = getDefaultImageId(); - if (defaultAppImageId != null) { - ApplicationImage defaultImage = appCenterStorage.getAppImageFile(defaultAppImageId); - generalsettings.setDefaultApplicationImage(defaultImage); - } - return generalsettings; - } - - /** - * Retrieves the list of applications with offset, limit and a keyword that can - * be empty - * - * @param offset offset of the query - * @param limit limit of the query that can be less or equal to 0, which mean, - * getting all available applications - * @param keyword used to search in title and url - * @return {@link ApplicationList} that contains the list of applications - */ - public ApplicationList getApplicationsList(int offset, int limit, String keyword) throws FileStorageException { - ApplicationList applicationList = new ApplicationList(); - List applications = appCenterStorage.getApplications(keyword); - if (limit <= 0) { - limit = applications.size(); - } - applications = applications.stream().skip(offset).limit(limit).collect(Collectors.toList()); - applicationList.setApplications(applications); - applicationList.setSize(applications.size()); - applicationList.setOffset(offset); - applicationList.setLimit(limit); - return applicationList; - } - - /** - * Retrieves the list of applications switch offset and limit of the query, a - * keyword to filter on title and url of {@link Application} and the username to - * filter on authorized applications - * - * @param offset offset of the query - * @param limit limit of the query that can be less or equal to 0, which mean, - * getting all available applications - * @param keyword used to search in title and url - * @param username login of user to use to filter on authorized applications - * @return {@link ApplicationList} that contains the {@link List} of authorized - * {@link UserApplication} - */ - public ApplicationList getAuthorizedApplicationsList(int offset, - int limit, - String keyword, - String username) throws FileStorageException { - if (StringUtils.isBlank(username)) { - throw new IllegalArgumentException("username is mandatory"); - } - if (offset < 0) { - offset = 0; - } - ApplicationList resultApplicationsList = new ApplicationList(); - List userApplicationsList = new ArrayList<>(); - List applications = getApplications(keyword, username).stream().collect(Collectors.toList()); - if (limit <= 0) { - limit = applications.size(); - } - userApplicationsList = applications.stream().skip(offset).limit(limit).collect(Collectors.toList()); - userApplicationsList = userApplicationsList.stream().map(app -> { - UserApplication applicationFavorite = new UserApplication(app); - applicationFavorite.setFavorite(appCenterStorage.isFavoriteApplication(applicationFavorite.getId(), username)); - return applicationFavorite; - }).collect(Collectors.toList()); - resultApplicationsList.setApplications(userApplicationsList); - long countFavorites = appCenterStorage.countFavorites(username); - resultApplicationsList.setCanAddFavorite(countFavorites < getMaxFavoriteApps()); - resultApplicationsList.setOffset(offset); - resultApplicationsList.setLimit(limit); - resultApplicationsList.setSize(applications.size()); - return resultApplicationsList; - } - - /** - * Retrieves all the list of applications for a user - * - * @param username login of user - * @return {@link ApplicationList} that contains {@link List} of - * {@link UserApplication} - */ - public ApplicationList getMandatoryAndFavoriteApplicationsList(String username) { - List mandatoryAndFavoriteApplications = appCenterStorage.getFavoriteApplicationsByUser(username); - List mandatoryAndFavoriteApplicationsId = mandatoryAndFavoriteApplications.stream().map(userApplication -> userApplication.getId()).collect(Collectors.toList()); - appCenterStorage.getMandatoryApplications().forEach(userApplication -> { - if (!mandatoryAndFavoriteApplicationsId.contains(userApplication.getId())) { - mandatoryAndFavoriteApplications.add(userApplication); - } - }); - List applications = mandatoryAndFavoriteApplications.stream() - .filter(app -> hasPermission(username, app)) - .collect(Collectors.toList()); - - ApplicationList applicationList = new ApplicationList(); - applicationList.setApplications(applications); - long countFavorites = appCenterStorage.countFavorites(username); - applicationList.setCanAddFavorite(countFavorites < getMaxFavoriteApps()); - applicationList.setLimit(mandatoryAndFavoriteApplications.size()); - applicationList.setSize(mandatoryAndFavoriteApplications.size()); - applicationList.setOffset(0); - return applicationList; - } - - /** - * Update favorite applications order for a user - * - * @param applicationOrder - * @param userName - */ - public void updateFavoriteApplicationOrder(ApplicationOrder applicationOrder, - String userName) throws ApplicationNotFoundException, FileStorageException { - if (StringUtils.isBlank(userName)) { - throw new IllegalArgumentException("userName is mandatory"); - } - if (applicationOrder.getId() <= 0) { - throw new IllegalArgumentException("applicationId must be a positive integer"); - } - Application application = appCenterStorage.getApplicationById(applicationOrder.getId()); - if (application == null) { - throw new ApplicationNotFoundException("Application with id " + applicationOrder.getId().toString() - + " wasn't found in store"); - } - appCenterStorage.updateFavoriteApplicationOrder(applicationOrder.getId(), userName, applicationOrder.getOrder()); - } - - /** - * Return the {@link Application} illustration last modifed timestamp (in ms), - * if not found, the default image last modifed timestamp will be retrieved - * - * @param applicationId technical id of application - * @param username login of user accessing application - * @return timestamp in milliseconds of last modified date of illustration - * @throws ApplicationNotFoundException if application wasn't found - * @throws IllegalAccessException if user doesn't have access permission to - * application - * @throws FileStorageException if an error occurs while accessing file from - * store - */ - public Long getApplicationImageLastUpdated(long applicationId, String username) throws ApplicationNotFoundException, - IllegalAccessException, - FileStorageException { - if (StringUtils.isBlank(username)) { - throw new IllegalArgumentException("username is mandatory"); - } - Application application = appCenterStorage.getApplicationById(applicationId); - if (application == null) { - throw new ApplicationNotFoundException("Application with id " + applicationId + " wasn't found"); - } - // if user is admin then no need to check for permissions - if (!isAdmin()) { - if (!hasPermission(username, application)) { - throw new IllegalAccessException("User " + username + " isn't allowed to access application with id " + applicationId); - } - } - if (application.getImageFileId() != null && application.getImageFileId() > 0) { - return appCenterStorage.getApplicationImageLastUpdated(application.getImageFileId()); - } else { - Long defaultImageId = getDefaultImageId(); - if (defaultImageId != null && defaultImageId > 0) { - return appCenterStorage.getApplicationImageLastUpdated(defaultImageId); - } - } - return null; - } - - /** - * Return the {@link Application} illustration {@link InputStream}, if not - * found, the default image {@link InputStream} will be retrieved - * - * @param applicationId technical id of application - * @param username login of user accessing application - * @return {@link InputStream} of application illustration - * @throws ApplicationNotFoundException if application wasn't found - * @throws IllegalAccessException if user doesn't have access permission to - * application - * @throws FileStorageException if an error occurs while accessing file from - * store - * @throws IOException if an error occurs while building {@link InputStream} - */ - public InputStream getApplicationImageInputStream(long applicationId, String username) throws ApplicationNotFoundException, - IllegalAccessException, - FileStorageException, - IOException { - if (StringUtils.isBlank(username)) { - throw new IllegalArgumentException("username is mandatory"); - } - Application application = appCenterStorage.getApplicationById(applicationId); - if (application == null) { - throw new ApplicationNotFoundException("Application with id " + applicationId + " wasn't found"); - } - // if user is admin then no need to check for permissions - if (!isAdmin()) { - if (!hasPermission(username, application)) { - throw new IllegalAccessException("User " + username + " isn't allowed to access application with id " + applicationId); - } - } - InputStream applicationImageInputStream=null; - if (application.getImageFileId() != null && application.getImageFileId() > 0) { - applicationImageInputStream = appCenterStorage.getApplicationImageInputStream(application.getImageFileId()); - } - if (applicationImageInputStream==null) { - //result is null if there is no image associated to the application - //or if the image is not readable (data corruption, or quarantined by an antivirus) - Long defaultImageId = getDefaultImageId(); - if (defaultImageId != null && defaultImageId > 0) { - applicationImageInputStream=appCenterStorage.getApplicationImageInputStream(defaultImageId); - } - } - return applicationImageInputStream; - } - - /** - * Inject a default application using IOC {@link ComponentPlugin} using - * configuration - * - * @param applicationPlugin plugin containing application to inject - */ - public void addApplicationPlugin(ApplicationPlugin applicationPlugin) { - if (applicationPlugin == null) { - throw new IllegalArgumentException("'applicationPlugin' is mandatory"); - } - if (StringUtils.isBlank(applicationPlugin.getName())) { - throw new IllegalStateException("'applicationPlugin' name is mandatory"); - } - if(applicationPlugin.isEnabled()) { - this.defaultApplications.put(applicationPlugin.getName(), applicationPlugin); - } - } - - /** - * Delete an injected plugin identified by its name - * - * @param pluginName plugin name to delete - */ - public void removeApplicationPlugin(String pluginName) { - if (StringUtils.isBlank(pluginName)) { - throw new IllegalArgumentException("'pluginName' is mandatory"); - } - this.defaultApplications.remove(pluginName); - } - - /** - * Checks whether the application is a system application injected by - * configuration or not - * - * @param application application to check its state - * @return true if the configuration of the application exists with same title - * and URL, else false. - */ - public boolean isDefaultSystemApplication(Application application) { - if (application == null) { - throw new IllegalArgumentException("'application' is mandatory"); - } - return this.defaultApplications.values() - .stream() - .anyMatch(app -> StringUtils.equals(app.getApplication().getTitle(), application.getTitle()) - && StringUtils.equals(app.getApplication().getUrl(), application.getUrl())); - } - - private boolean hasPermission(String username, Application application) { - return hasPermission(username, application.getPermissions()); - } - - private boolean hasPermission(String username, List storedPermissions) { - if (storedPermissions == null) { - return true; - } - for (String storedPermission : storedPermissions) { - if (hasPermission(username, storedPermission)) { - return true; - } - } - return false; - } - - private boolean hasPermission(String username, String permissionExpression) { - if (StringUtils.isBlank(permissionExpression)) { - return true; - } - - if (StringUtils.isBlank(username)) { - return false; - } - - // Ingeneral case, the user is already loggedin, thus we will get the - // Identity from registry without having to compute it again from - // OrganisationService, thus the condition (identity == null) will be false - // most of the time for better performances - Identity identity = identityRegistry.getIdentity(username); - if (identity == null) { - try { - identity = authenticator.createIdentity(username); - } catch (Exception e) { - LOG.warn("Error getting memberships of user {}", username, e); - return false; - } - - // Check null again after building identity - if (identity == null) { - return false; - } - } - - MembershipEntry membership = null; - if (permissionExpression.contains(":")) { - String[] permissionExpressionParts = permissionExpression.split(":"); - membership = new MembershipEntry(permissionExpressionParts[1], permissionExpressionParts[0]); - } else if (permissionExpression.contains("/")) { - membership = new MembershipEntry(permissionExpression, MembershipEntry.ANY_TYPE); - } else { - return StringUtils.equals(username, permissionExpression); - } - return identity.isMemberOf(membership); - } - - private Long getDefaultImageId() { - SettingValue defaultAppImageIdSetting = settingService.get(APP_CENTER_CONTEXT, APP_CENTER_SCOPE, DEFAULT_APP_IMAGE_ID); - Long defaultAppImageId = null; - if (defaultAppImageIdSetting != null && defaultAppImageIdSetting.getValue() != null) { - defaultAppImageId = Long.parseLong(defaultAppImageIdSetting.getValue().toString()); - } - return defaultAppImageId; - } - - private List getApplications(String keyword, String username) throws FileStorageException { - - List applications = appCenterStorage.getApplications(keyword); - applications = applications.stream() - .filter(app -> hasPermission(username, app)) - .filter(Application::isActive) - .collect(Collectors.toList()); - - return applications; - } - - private boolean isUrlValid(String url) { - //[-a-zA-Z0-9@:%._\\\\/+~#=] allowed characters - String regex = "(http(s)?:\\/\\/.)[-a-zA-Z0-9@:%._\\\\/+~#=]{2,256}"; - Pattern pattern = Pattern.compile(regex); - return url != null && !url.isBlank() && (url.startsWith("/portal/") || url.startsWith("./") || pattern.matcher(url).matches()); - } - -} diff --git a/app-center-services/src/main/resources/conf/configuration.xml b/app-center-services/src/main/resources/conf/configuration.xml deleted file mode 100644 index e973c32f2..000000000 --- a/app-center-services/src/main/resources/conf/configuration.xml +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - org.exoplatform.commons.api.persistence.DataInitializer - - AppCenterChangeLogsPlugin - addChangeLogsPlugin - org.exoplatform.commons.persistence.impl.ChangeLogsPlugin - - - changelogs - Change logs of appCenter - db.changelogs/app-center-changelog-1.0.0.xml - - - - - - \ No newline at end of file diff --git a/app-center-services/src/main/resources/conf/portal/configuration.xml b/app-center-services/src/main/resources/conf/portal/configuration.xml deleted file mode 100644 index 46e373ee0..000000000 --- a/app-center-services/src/main/resources/conf/portal/configuration.xml +++ /dev/null @@ -1,69 +0,0 @@ - - - - - - org.exoplatform.appcenter.dao.ApplicationDAO - - - - org.exoplatform.appcenter.dao.FavoriteApplicationDAO - - - - org.exoplatform.appcenter.storage.ApplicationCenterStorage - - - - org.exoplatform.appcenter.service.ApplicationCenterService - - - default.administrators.expression - Default administrators of application center - ${exo.appcenter.administrators.expression:*:/platform/administrators} - - - default.favorites - Default allowed favorites - ${exo.appcenter.favorites.count:12} - - - - - - org.exoplatform.appcenter.rest.ApplicationCenterREST - - - - org.exoplatform.commons.file.services.NameSpaceService - - AppCenterNameSpacePlugin - addNameSpacePlugin - org.exoplatform.commons.file.services.NameSpacePlugin - - - fileNameSpace.params - - - - - - - - \ No newline at end of file diff --git a/app-center-services/src/main/resources/db.changelogs/app-center-changelog-1.0.0.xml b/app-center-services/src/main/resources/db.changelogs/app-center-changelog-1.0.0.xml index d6986a5de..86b68699b 100644 --- a/app-center-services/src/main/resources/db.changelogs/app-center-changelog-1.0.0.xml +++ b/app-center-services/src/main/resources/db.changelogs/app-center-changelog-1.0.0.xml @@ -1,19 +1,23 @@ applicationOrders() { + return Arrays.asList(new ApplicationOrder(1l, 2l), new ApplicationOrder(2l, 3l)); + } + + @SneakyThrows + public static String asJsonString(final Object obj) { + return OBJECT_MAPPER.writeValueAsString(obj); + } + +} diff --git a/app-center-services/src/test/java/io/meeds/appcenter/rest/ApplicationRestTest.java b/app-center-services/src/test/java/io/meeds/appcenter/rest/ApplicationRestTest.java new file mode 100644 index 000000000..d6ff3a7fa --- /dev/null +++ b/app-center-services/src/test/java/io/meeds/appcenter/rest/ApplicationRestTest.java @@ -0,0 +1,200 @@ +/** + * This file is part of the Meeds project (https://meeds.io/). + * + * Copyright (C) 2020 - 2024 Meeds Association contact@meeds.io + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package io.meeds.appcenter.rest; + +import static org.mockito.Mockito.when; +import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.user; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.put; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +import java.util.Collections; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.junit.jupiter.MockitoExtension; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureWebMvc; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.http.MediaType; +import org.springframework.security.core.authority.SimpleGrantedAuthority; +import org.springframework.security.web.SecurityFilterChain; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.ResultActions; +import org.springframework.test.web.servlet.request.RequestPostProcessor; +import org.springframework.test.web.servlet.setup.MockMvcBuilders; +import org.springframework.web.context.WebApplicationContext; + +import com.fasterxml.jackson.core.json.JsonReadFeature; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.SerializationFeature; +import com.fasterxml.jackson.databind.json.JsonMapper; +import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; + +import io.meeds.appcenter.model.Application; +import io.meeds.appcenter.model.ApplicationList; +import io.meeds.appcenter.service.ApplicationCenterService; +import io.meeds.spring.web.security.PortalAuthenticationManager; +import io.meeds.spring.web.security.WebSecurityConfiguration; + +import jakarta.servlet.Filter; +import lombok.SneakyThrows; + +@SpringBootTest(classes = { ApplicationRest.class, PortalAuthenticationManager.class }) +@ContextConfiguration(classes = { WebSecurityConfiguration.class }) +@AutoConfigureWebMvc +@AutoConfigureMockMvc(addFilters = false) +@ExtendWith(MockitoExtension.class) +public class ApplicationRestTest { + + private static final String APPLICATIONS_PATH = "/applications"; // NOSONAR + + private static final String ALL_APPLICATIONS_PATH = "/applications/all";// NOSONAR + + private static final String SIMPLE_USER = "simple"; + + private static final String ADMIN_USER = "admin"; + + private static final String TEST_PASSWORD = "testPassword"; + + static final ObjectMapper OBJECT_MAPPER; + + static { + // Workaround when Jackson is defined in shared library with different + // version and without artifact jackson-datatype-jsr310 + OBJECT_MAPPER = JsonMapper.builder() + .configure(JsonReadFeature.ALLOW_MISSING_VALUES, true) + .configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false) + .build(); + OBJECT_MAPPER.registerModule(new JavaTimeModule()); + } + + @MockBean + private ApplicationCenterService applicationCenterService; + + @Autowired + private SecurityFilterChain filterChain; + + @Autowired + private WebApplicationContext context; + + private MockMvc mockMvc; + + @BeforeEach + void setup() { + mockMvc = MockMvcBuilders.webAppContextSetup(context) + .addFilters(filterChain.getFilters().toArray(new Filter[0])) + .build(); + } + + @Test + void getAllApplicationsAnonymously() throws Exception { + ResultActions response = mockMvc.perform(get(ALL_APPLICATIONS_PATH)); + response.andExpect(status().isForbidden()); + } + + @Test + void getAllApplications() throws Exception { + when(applicationCenterService.getApplications(0, 10, "")).thenReturn(applicationList()); + ResultActions response = mockMvc.perform(get(ALL_APPLICATIONS_PATH).with(testAdminUser())); + response.andExpect(status().isOk()); + } + + @Test + void getApplicationsAnonymously() throws Exception { + ResultActions response = mockMvc.perform(get(APPLICATIONS_PATH)); + response.andExpect(status().isForbidden()); + } + + @Test + void getApplications() throws Exception { + ResultActions response = mockMvc.perform(get(APPLICATIONS_PATH).with(testSimpleUser())); + response.andExpect(status().isOk()); + } + + @Test + void createApplication() throws Exception { + ResultActions response = mockMvc.perform(post(APPLICATIONS_PATH).with(testAdminUser()) + .content(asJsonString(application())) + .contentType(MediaType.APPLICATION_JSON) + .accept(MediaType.APPLICATION_JSON)); + response.andExpect(status().isOk()); + } + + @Test + void updateApplication() throws Exception { + ResultActions response = mockMvc.perform(put(APPLICATIONS_PATH).with(testAdminUser()) + .content(asJsonString(application())) + .contentType(MediaType.APPLICATION_JSON) + .accept(MediaType.APPLICATION_JSON)); + response.andExpect(status().isOk()); + } + + @Test + void deleteApplication() throws Exception { + ResultActions response = mockMvc.perform(delete(APPLICATIONS_PATH + "/1").with(testAdminUser())); + response.andExpect(status().isOk()); + } + + private RequestPostProcessor testAdminUser() { + return user(ADMIN_USER).password(TEST_PASSWORD) + .authorities(new SimpleGrantedAuthority("administrators")); + } + + private RequestPostProcessor testSimpleUser() { + return user(SIMPLE_USER).password(TEST_PASSWORD) + .authorities(new SimpleGrantedAuthority("users")); + } + + private ApplicationList applicationList() { + ApplicationList result = new ApplicationList(); + result.setApplications(Collections.singletonList(application())); + return result; + } + + private Application application() { + return new Application(1L, + "titre", + "url", + "", + 0L, + 0L, + "", + "", + "description", + false, + true, + false, + true, + false, + ""); + } + + @SneakyThrows + public static String asJsonString(final Object obj) { + return OBJECT_MAPPER.writeValueAsString(obj); + } + +} diff --git a/app-center-services/src/test/java/io/meeds/appcenter/rest/ApplicationSettingsRestTest.java b/app-center-services/src/test/java/io/meeds/appcenter/rest/ApplicationSettingsRestTest.java new file mode 100644 index 000000000..629308d67 --- /dev/null +++ b/app-center-services/src/test/java/io/meeds/appcenter/rest/ApplicationSettingsRestTest.java @@ -0,0 +1,158 @@ +/** + * This file is part of the Meeds project (https://meeds.io/). + * + * Copyright (C) 2020 - 2024 Meeds Association contact@meeds.io + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package io.meeds.appcenter.rest; + +import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.user; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.patch; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.junit.jupiter.MockitoExtension; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureWebMvc; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.http.MediaType; +import org.springframework.security.core.authority.SimpleGrantedAuthority; +import org.springframework.security.web.SecurityFilterChain; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.ResultActions; +import org.springframework.test.web.servlet.request.RequestPostProcessor; +import org.springframework.test.web.servlet.setup.MockMvcBuilders; +import org.springframework.web.context.WebApplicationContext; + +import com.fasterxml.jackson.core.json.JsonReadFeature; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.SerializationFeature; +import com.fasterxml.jackson.databind.json.JsonMapper; +import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; + +import io.meeds.appcenter.model.ApplicationImage; +import io.meeds.appcenter.service.ApplicationCenterService; +import io.meeds.spring.web.security.PortalAuthenticationManager; +import io.meeds.spring.web.security.WebSecurityConfiguration; + +import jakarta.servlet.Filter; +import lombok.SneakyThrows; + +@SpringBootTest(classes = { ApplicationSettingsRest.class, PortalAuthenticationManager.class }) +@ContextConfiguration(classes = { WebSecurityConfiguration.class }) +@AutoConfigureWebMvc +@AutoConfigureMockMvc(addFilters = false) +@ExtendWith(MockitoExtension.class) +public class ApplicationSettingsRestTest { + + private static final String SETTINGS_PATH = "/settings"; // NOSONAR + + private static final String SIMPLE_USER = "simple"; + + private static final String ADMIN_USER = "admin"; + + private static final String TEST_PASSWORD = "testPassword"; + + static final ObjectMapper OBJECT_MAPPER; + + static { + // Workaround when Jackson is defined in shared library with different + // version and without artifact jackson-datatype-jsr310 + OBJECT_MAPPER = JsonMapper.builder() + .configure(JsonReadFeature.ALLOW_MISSING_VALUES, true) + .configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false) + .build(); + OBJECT_MAPPER.registerModule(new JavaTimeModule()); + } + + @MockBean + private ApplicationCenterService applicationCenterService; + + @Autowired + private SecurityFilterChain filterChain; + + @Autowired + private WebApplicationContext context; + + private MockMvc mockMvc; + + @BeforeEach + void setup() { + mockMvc = MockMvcBuilders.webAppContextSetup(context) + .addFilters(filterChain.getFilters().toArray(new Filter[0])) + .build(); + } + + @Test + void getSettingsAnonymously() throws Exception { + ResultActions response = mockMvc.perform(get(SETTINGS_PATH)); + response.andExpect(status().isForbidden()); + } + + @Test + void getSettings() throws Exception { + ResultActions response = mockMvc.perform(get(SETTINGS_PATH).with(testSimpleUser())); + response.andExpect(status().isOk()); + } + + @Test + void setMaxFavoriteAppsAnonymously() throws Exception { + ResultActions response = mockMvc.perform(patch(SETTINGS_PATH + "/maxFavorites?number=3")); + response.andExpect(status().isForbidden()); + } + + @Test + void setMaxFavoriteApps() throws Exception { + ResultActions response = mockMvc.perform(patch(SETTINGS_PATH + "/maxFavorites?number=3").with(testAdminUser())); + response.andExpect(status().isOk()); + } + + @Test + void setDefaultAppImageAnonymously() throws Exception { + ResultActions response = mockMvc.perform(patch(SETTINGS_PATH + "/image").content(asJsonString(new ApplicationImage())) + .contentType(MediaType.APPLICATION_JSON)); + response.andExpect(status().isForbidden()); + } + + @Test + void setDefaultAppImage() throws Exception { + ResultActions response = mockMvc.perform(patch(SETTINGS_PATH + "/image").with(testAdminUser()) + .content(asJsonString(new ApplicationImage())) + .contentType(MediaType.APPLICATION_JSON)); + response.andExpect(status().isOk()); + } + + private RequestPostProcessor testAdminUser() { + return user(ADMIN_USER).password(TEST_PASSWORD) + .authorities(new SimpleGrantedAuthority("administrators")); + } + + private RequestPostProcessor testSimpleUser() { + return user(SIMPLE_USER).password(TEST_PASSWORD) + .authorities(new SimpleGrantedAuthority("users")); + } + + @SneakyThrows + public static String asJsonString(final Object obj) { + return OBJECT_MAPPER.writeValueAsString(obj); + } + +} diff --git a/app-center-services/src/test/java/io/meeds/appcenter/service/ApplicationCenterInjectServiceTest.java b/app-center-services/src/test/java/io/meeds/appcenter/service/ApplicationCenterInjectServiceTest.java new file mode 100644 index 000000000..9bbed957f --- /dev/null +++ b/app-center-services/src/test/java/io/meeds/appcenter/service/ApplicationCenterInjectServiceTest.java @@ -0,0 +1,154 @@ +/** + * This file is part of the Meeds project (https://meeds.io/). + * + * Copyright (C) 2020 - 2024 Meeds Association contact@meeds.io + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package io.meeds.appcenter.service; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.atLeast; +import static org.mockito.Mockito.*; +import static org.mockito.Mockito.when; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.junit.jupiter.MockitoExtension; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.mock.mockito.MockBean; + +import org.exoplatform.commons.api.settings.SettingService; +import org.exoplatform.container.configuration.ConfigurationManager; + +import io.meeds.appcenter.model.Application; +import io.meeds.appcenter.model.ApplicationDescriptor; + +import lombok.SneakyThrows; + +@SpringBootTest(classes = { ApplicationCenterInjectService.class }) +@ExtendWith(MockitoExtension.class) +public class ApplicationCenterInjectServiceTest { + + private static final long IMAGE_FILE_ID = 5l; + + private static final long IMAGE_LAST_MODIFIED = 588l; + + private static final String HELP_PAGE_URL = "./helpPageUrl"; + + private static final String URL = "./url"; + + private static final String PERMISSIONS_1 = "/permissions1"; + + private static final String DESCRIPTION = "description"; + + private static final String TITLE = "title"; + + private static final Long ID = 2l; + + @MockBean + private ConfigurationManager configurationManager; + + @MockBean + private SettingService settingService; + + @MockBean + private ApplicationCenterService applicationCenterService; + + @Autowired + private ApplicationCenterInjectService applicationCenterInjectService; + + @Test + @SneakyThrows + void injectDefaultApplications() { + assertThrows(IllegalArgumentException.class, () -> applicationCenterInjectService.addApplicationPlugin(null)); + + applicationCenterInjectService.injectDefaultApplications(); + assertEquals(1, + applicationCenterInjectService.getDefaultApplications().size(), + "Should have injected data from 'applications.json' file"); + + String pluginName = "testapp"; + + Application application = application(); + ApplicationDescriptor applicationPlugin1 = new ApplicationDescriptor(null, application); + assertThrows(IllegalStateException.class, () -> applicationCenterInjectService.addApplicationPlugin(applicationPlugin1)); + applicationPlugin1.setName(pluginName); + applicationCenterInjectService.addApplicationPlugin(applicationPlugin1); + applicationCenterInjectService.injectDefaultApplications(); + verify(applicationCenterService, never()).createApplication(any()); + + applicationPlugin1.setEnabled(true); + try { + applicationCenterInjectService.addApplicationPlugin(applicationPlugin1); + applicationCenterInjectService.injectDefaultApplications(); + verify(applicationCenterService).createApplication(applicationPlugin1.getApplication()); + } finally { + applicationCenterInjectService.removeApplicationPlugin(pluginName); + } + + ApplicationDescriptor applicationPlugin2 = new ApplicationDescriptor(pluginName, + application, + "jar:/test.png", + "write", + true, + true); + try { + applicationCenterInjectService.addApplicationPlugin(applicationPlugin2); + when(applicationCenterService.getApplicationByTitle(application.getTitle())).thenReturn(application); + application.setChangedManually(true); + applicationCenterInjectService.injectDefaultApplications(); + verify(applicationCenterService).updateApplication(application); + } finally { + applicationCenterInjectService.removeApplicationPlugin(pluginName); + } + + // Third start with file attached and override-mode is merge + applicationPlugin2 = new ApplicationDescriptor(pluginName, application, "jar:/test.png", "merge", false, true); + applicationPlugin2.setName(pluginName); + try { + applicationCenterInjectService.addApplicationPlugin(applicationPlugin2); + applicationCenterInjectService.injectDefaultApplications(); + verify(configurationManager, atLeast(1)).getInputStream(applicationPlugin2.getImagePath()); + } finally { + applicationCenterInjectService.removeApplicationPlugin(pluginName); + } + } + + private Application application() { + return application(ID); + } + + private Application application(Long id) { + return new Application(id, + TITLE, + URL, + HELP_PAGE_URL, + IMAGE_FILE_ID, + IMAGE_LAST_MODIFIED, + "", + "", + DESCRIPTION, + false, + true, + false, + true, + false, + PERMISSIONS_1); + } + +} diff --git a/app-center-services/src/test/java/io/meeds/appcenter/service/ApplicationCenterServiceTest.java b/app-center-services/src/test/java/io/meeds/appcenter/service/ApplicationCenterServiceTest.java new file mode 100644 index 000000000..8e1c6d189 --- /dev/null +++ b/app-center-services/src/test/java/io/meeds/appcenter/service/ApplicationCenterServiceTest.java @@ -0,0 +1,451 @@ +/** + * This file is part of the Meeds project (https://meeds.io/). + * + * Copyright (C) 2020 - 2024 Meeds Association contact@meeds.io + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package io.meeds.appcenter.service; + +import static io.meeds.appcenter.service.ApplicationCenterService.APP_CENTER_CONTEXT; +import static io.meeds.appcenter.service.ApplicationCenterService.APP_CENTER_SCOPE; +import static io.meeds.appcenter.service.ApplicationCenterService.DEFAULT_APP_IMAGE_ID; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.argThat; +import static org.mockito.Mockito.lenient; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import java.io.InputStream; +import java.util.Arrays; +import java.util.Collections; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.ArgumentMatcher; +import org.mockito.junit.jupiter.MockitoExtension; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.mock.mockito.MockBean; + +import org.exoplatform.commons.api.settings.SettingService; +import org.exoplatform.commons.api.settings.SettingValue; +import org.exoplatform.container.configuration.ConfigurationManager; +import org.exoplatform.services.security.Authenticator; +import org.exoplatform.services.security.Identity; +import org.exoplatform.services.security.IdentityRegistry; +import org.exoplatform.services.security.MembershipEntry; + +import io.meeds.appcenter.model.Application; +import io.meeds.appcenter.model.ApplicationImage; +import io.meeds.appcenter.model.ApplicationList; +import io.meeds.appcenter.model.ApplicationOrder; +import io.meeds.appcenter.model.GeneralSettings; +import io.meeds.appcenter.model.UserApplication; +import io.meeds.appcenter.model.exception.ApplicationAlreadyExistsException; +import io.meeds.appcenter.model.exception.ApplicationNotFoundException; +import io.meeds.appcenter.storage.ApplicationCenterStorage; + +import lombok.SneakyThrows; + +@SpringBootTest(classes = { ApplicationCenterService.class }) +@ExtendWith(MockitoExtension.class) +public class ApplicationCenterServiceTest { + + private static final String KEYWORD = "keyword"; + + private static final String ADMIN_USERNAME = "admin"; + + private static final long IMAGE_FILE_ID = 5l; + + private static final long IMAGE_LAST_MODIFIED = 588l; + + private static final String IMAGE_FILE_CONTENT = "content"; + + private static final String HELP_PAGE_URL = "./helpPageUrl"; + + private static final String URL = "./url"; + + private static final String PERMISSIONS_2 = "/permissions2"; + + private static final String PERMISSIONS_1 = "/permissions1"; + + private static final String DESCRIPTION = "description"; + + private static final String TITLE = "title"; + + private static final String TEST_USER = "testuser"; + + private static final Long ID = 2l; + + @MockBean + private ConfigurationManager configurationManager; + + @MockBean + private SettingService settingService; + + @MockBean + private Authenticator authenticator; + + @MockBean + private IdentityRegistry identityRegistry; + + @MockBean + private ApplicationCenterStorage appCenterStorage; + + @Autowired + private ApplicationCenterService applicationCenterService; + + @BeforeEach + @SneakyThrows + void setup() { + Identity userIdentity = mock(Identity.class); + Identity adminIdentity = mock(Identity.class); + lenient().when(adminIdentity.isMemberOf(argThat((ArgumentMatcher) m -> m.getGroup() + .equals("/platform/administrators") + || m.getGroup() + .equals(PERMISSIONS_1)))) + .thenReturn(true); + lenient().when(userIdentity.isMemberOf(argThat((ArgumentMatcher) m -> m.getGroup() + .equals(PERMISSIONS_2)))) + .thenReturn(true); + lenient().when(identityRegistry.getIdentity(ADMIN_USERNAME)).thenReturn(adminIdentity); + lenient().when(identityRegistry.getIdentity(TEST_USER)).thenReturn(userIdentity); + } + + @Test + @SneakyThrows + void createApplication() { + assertThrows(IllegalArgumentException.class, () -> applicationCenterService.createApplication(null)); + Application existingApplication = application(); + existingApplication.setTitle("title2"); + when(appCenterStorage.getApplicationByTitle(existingApplication.getTitle())).thenReturn(existingApplication); + assertThrows(ApplicationAlreadyExistsException.class, () -> applicationCenterService.createApplication(existingApplication)); + existingApplication.setTitle("titleTest"); + existingApplication.setUrl("test"); + assertThrows(IllegalArgumentException.class, () -> applicationCenterService.createApplication(existingApplication)); + existingApplication.setUrl("./test/"); + existingApplication.setHelpPageURL("test"); + assertThrows(IllegalArgumentException.class, () -> applicationCenterService.createApplication(existingApplication)); + + Application application = application(); + applicationCenterService.createApplication(application); + verify(appCenterStorage).createApplication(application); + } + + @Test + @SneakyThrows + void updateApplication() { + assertThrows(IllegalArgumentException.class, () -> applicationCenterService.updateApplication(null, ADMIN_USERNAME)); + assertThrows(IllegalArgumentException.class, () -> applicationCenterService.updateApplication(application(null), null)); + assertThrows(ApplicationNotFoundException.class, + () -> applicationCenterService.updateApplication(application(), ADMIN_USERNAME)); + + when(appCenterStorage.getApplicationById(ID)).thenReturn(application()); + assertThrows(IllegalAccessException.class, () -> applicationCenterService.updateApplication(application(), null)); + assertThrows(IllegalAccessException.class, () -> applicationCenterService.updateApplication(application(), TEST_USER)); + verify(appCenterStorage, never()).updateApplication(any()); + applicationCenterService.updateApplication(application(), ADMIN_USERNAME); + verify(appCenterStorage).updateApplication(any()); + } + + @Test + @SneakyThrows + void deleteApplication() { + assertThrows(IllegalArgumentException.class, () -> applicationCenterService.deleteApplication(null, null)); + assertThrows(IllegalArgumentException.class, () -> applicationCenterService.deleteApplication(null, ADMIN_USERNAME)); + assertThrows(IllegalArgumentException.class, () -> applicationCenterService.deleteApplication(ID, null)); + assertThrows(ApplicationNotFoundException.class, () -> applicationCenterService.deleteApplication(ID, ADMIN_USERNAME)); + when(appCenterStorage.getApplicationById(ID)).thenReturn(application()); + assertThrows(IllegalAccessException.class, () -> applicationCenterService.deleteApplication(ID, TEST_USER)); + + applicationCenterService.deleteApplication(ID, ADMIN_USERNAME); + verify(appCenterStorage).deleteApplication(ID); + } + + @Test + void getMaxFavoriteApps() { + long originalMaxFavoriteApps = applicationCenterService.getMaxFavoriteApps(); + + applicationCenterService.setMaxFavoriteApps(originalMaxFavoriteApps + 1); + assertEquals(originalMaxFavoriteApps + 1, applicationCenterService.getMaxFavoriteApps()); + + applicationCenterService.setMaxFavoriteApps(0); + assertEquals(0, applicationCenterService.getMaxFavoriteApps()); + } + + @Test + void setDefaultAppImage() { + ApplicationImage applicationImage = applicationCenterService.setDefaultAppImage(null); + assertNull(applicationImage); + + applicationImage = new ApplicationImage(null, null, null); + applicationImage = applicationCenterService.setDefaultAppImage(applicationImage); + assertNull(applicationImage); + + applicationImage = new ApplicationImage(null, "name", IMAGE_FILE_CONTENT); + when(appCenterStorage.saveAppImageFileItem(applicationImage)).thenAnswer(invocation -> { + ApplicationImage img = invocation.getArgument(0); + img.setId(IMAGE_FILE_ID); + return img; + }); + applicationImage = applicationCenterService.setDefaultAppImage(applicationImage); + assertNotNull(applicationImage); + assertEquals(IMAGE_FILE_ID, applicationImage.getId()); + } + + @SuppressWarnings({ "unchecked", "rawtypes" }) + @Test + void getAppGeneralSettings() { + applicationCenterService.setDefaultAppImage(null); + applicationCenterService.setMaxFavoriteApps(0); + + GeneralSettings generalSettings = applicationCenterService.getSettings(); + assertNotNull(generalSettings); + assertEquals(0, generalSettings.getMaxFavoriteApps()); + assertNull(generalSettings.getDefaultApplicationImage()); + + applicationCenterService.setDefaultAppImage(new ApplicationImage(null, null, null)); + generalSettings = applicationCenterService.getSettings(); + + assertEquals(0, generalSettings.getMaxFavoriteApps()); + assertNull(generalSettings.getDefaultApplicationImage()); + + when(appCenterStorage.getAppImageFile(IMAGE_FILE_ID)).thenReturn(new ApplicationImage(IMAGE_FILE_ID, + "name", + IMAGE_FILE_CONTENT)); + when(settingService.get(APP_CENTER_CONTEXT, + APP_CENTER_SCOPE, + DEFAULT_APP_IMAGE_ID)).thenReturn(new SettingValue(String.valueOf(IMAGE_FILE_ID))); + + generalSettings = applicationCenterService.getSettings(); + assertEquals(0, generalSettings.getMaxFavoriteApps()); + assertNotNull(generalSettings.getDefaultApplicationImage()); + assertEquals("name", generalSettings.getDefaultApplicationImage().getFileName()); + assertFalse(generalSettings.getDefaultApplicationImage().getFileBody().isEmpty()); + assertNotNull(generalSettings.getDefaultApplicationImage().getId()); + } + + @Test + @SneakyThrows + void addFavoriteApplication() { + assertThrows(IllegalArgumentException.class, () -> applicationCenterService.addFavoriteApplication(0, null)); + assertThrows(IllegalArgumentException.class, () -> applicationCenterService.addFavoriteApplication(0, TEST_USER)); + assertThrows(ApplicationNotFoundException.class, + () -> applicationCenterService.addFavoriteApplication(ID, TEST_USER)); + + Application application = application(); + when(appCenterStorage.getApplicationById(ID)).thenReturn(application); + assertThrows(IllegalAccessException.class, + () -> applicationCenterService.addFavoriteApplication(ID, TEST_USER)); + applicationCenterService.addFavoriteApplication(ID, ADMIN_USERNAME); + verify(appCenterStorage).addApplicationToUserFavorite(ID, ADMIN_USERNAME); + + application.setPermissions(Collections.singletonList(TEST_USER)); + applicationCenterService.addFavoriteApplication(ID, TEST_USER); + verify(appCenterStorage).addApplicationToUserFavorite(ID, TEST_USER); + } + + @Test + @SneakyThrows + void deleteFavoriteApplication() { + assertThrows(IllegalArgumentException.class, () -> applicationCenterService.deleteFavoriteApplication(null, null)); + assertThrows(IllegalArgumentException.class, () -> applicationCenterService.deleteFavoriteApplication(0L, TEST_USER)); + applicationCenterService.deleteFavoriteApplication(ID, TEST_USER); + verify(appCenterStorage).deleteApplicationFavorite(ID, TEST_USER); + } + + @Test + @SneakyThrows + void getApplicationsList() { + ApplicationList applicationsList = applicationCenterService.getApplications(0, 0, KEYWORD); + assertNotNull(applicationsList); + assertNotNull(applicationsList.getApplications()); + assertEquals(0, applicationsList.getApplications().size()); + assertEquals(0, applicationsList.getSize()); + assertEquals(0, applicationsList.getOffset()); + assertEquals(0, applicationsList.getLimit()); + + Application application = application(); + when(appCenterStorage.getApplications(KEYWORD)).thenReturn(Collections.singletonList(application)); + applicationsList = applicationCenterService.getApplications(1, 2, KEYWORD); + assertNotNull(applicationsList); + assertNotNull(applicationsList.getApplications()); + assertEquals(0, applicationsList.getApplications().size()); + assertEquals(0, applicationsList.getSize()); + assertEquals(1, applicationsList.getOffset()); + assertEquals(2, applicationsList.getLimit()); + + applicationsList = applicationCenterService.getApplications(0, 2, KEYWORD); + assertNotNull(applicationsList); + assertNotNull(applicationsList.getApplications()); + assertEquals(1, applicationsList.getApplications().size()); + assertEquals(1, applicationsList.getSize()); + assertEquals(0, applicationsList.getOffset()); + assertEquals(2, applicationsList.getLimit()); + } + + @Test + @SneakyThrows + void getMandatoryAndFavoriteApplicationsList() { + UserApplication application1 = new UserApplication(application(6l)); + UserApplication application2 = new UserApplication(application(7l)); + UserApplication application3 = new UserApplication(application(8l)); + UserApplication application4 = new UserApplication(application(9l)); + UserApplication application5 = new UserApplication(application(10l)); + + when(appCenterStorage.getMandatoryApplications()).thenReturn(Arrays.asList(application1, application2, application3)); + when(appCenterStorage.countFavorites(ADMIN_USERNAME)).thenReturn(1l); + when(appCenterStorage.getFavoriteApplicationsByUser(ADMIN_USERNAME)).thenReturn(Arrays.asList(application4, application5)); + applicationCenterService.setMaxFavoriteApps(1); + + ApplicationList applicationList = applicationCenterService.getMandatoryAndFavoriteApplicationsList(ADMIN_USERNAME); + assertFalse(applicationList.isCanAddFavorite()); + assertEquals(5, applicationList.getApplications().size()); + assertEquals(5, applicationList.getSize()); + + applicationList = applicationCenterService.getMandatoryAndFavoriteApplicationsList(TEST_USER); + assertTrue(applicationList.isCanAddFavorite()); + assertEquals(0, applicationList.getApplications().size()); + assertEquals(0, applicationList.getSize()); + + application1.setPermissions(Collections.singletonList(PERMISSIONS_2)); + application2.setPermissions(Collections.singletonList(PERMISSIONS_2)); + applicationList = applicationCenterService.getMandatoryAndFavoriteApplicationsList(TEST_USER); + assertTrue(applicationList.isCanAddFavorite()); + assertEquals(2, applicationList.getApplications().size()); + assertEquals(2, applicationList.getSize()); + } + + @Test + @SneakyThrows + void updateFavoriteApplicationOrder() { + assertThrows(IllegalArgumentException.class, + () -> applicationCenterService.updateFavoriteApplicationOrder(new ApplicationOrder(ID, 1L), "")); + assertThrows(IllegalArgumentException.class, + () -> applicationCenterService.updateFavoriteApplicationOrder(new ApplicationOrder(0L, 1L), ADMIN_USERNAME)); + assertThrows(ApplicationNotFoundException.class, + () -> applicationCenterService.updateFavoriteApplicationOrder(new ApplicationOrder(ID, 1L), ADMIN_USERNAME)); + + when(appCenterStorage.getApplicationById(ID)).thenReturn(application()); + applicationCenterService.updateFavoriteApplicationOrder(new ApplicationOrder(ID, 1L), ADMIN_USERNAME); + verify(appCenterStorage).updateFavoriteApplicationOrder(ID, ADMIN_USERNAME, 1L); + } + + @Test + @SneakyThrows + void getActiveApplications() { + assertThrows(IllegalArgumentException.class, () -> applicationCenterService.getActiveApplications(0, 0, null, null)); + ApplicationList applicationsList = applicationCenterService.getActiveApplications(0, 0, null, TEST_USER); + assertNotNull(applicationsList); + assertNotNull(applicationsList.getApplications()); + assertEquals(0, applicationsList.getApplications().size()); + assertEquals(0, applicationsList.getSize()); + assertEquals(0, applicationsList.getOffset()); + assertEquals(0, applicationsList.getLimit()); + + applicationsList = applicationCenterService.getActiveApplications(2, 3, null, ADMIN_USERNAME); + assertNotNull(applicationsList); + assertNotNull(applicationsList.getApplications()); + assertEquals(0, applicationsList.getApplications().size()); + assertEquals(0, applicationsList.getSize()); + assertEquals(2, applicationsList.getOffset()); + assertEquals(3, applicationsList.getLimit()); + + String keyword1 = "keyword1"; + Application application = application(); + when(appCenterStorage.getApplications(keyword1)).thenReturn(Collections.singletonList(application)); + + application.setActive(false); + applicationsList = applicationCenterService.getActiveApplications(0, 0, keyword1, ADMIN_USERNAME); + assertNotNull(applicationsList); + assertNotNull(applicationsList.getApplications()); + assertEquals(0, applicationsList.getApplications().size()); + assertEquals(0, applicationsList.getSize()); + + application.setActive(true); + applicationsList = applicationCenterService.getActiveApplications(0, 0, keyword1, ADMIN_USERNAME); + assertNotNull(applicationsList); + assertNotNull(applicationsList.getApplications()); + assertEquals(1, applicationsList.getApplications().size()); + assertEquals(1, applicationsList.getSize()); + } + + @Test + @SneakyThrows + void getLastUpdated() { + assertThrows(IllegalArgumentException.class, () -> applicationCenterService.getApplicationImageLastUpdated(50000L, null)); + assertThrows(ApplicationNotFoundException.class, + () -> applicationCenterService.getApplicationImageLastUpdated(50000L, TEST_USER)); + + Application application = application(); + application.setImageFileName("name"); + application.setImageFileBody(IMAGE_FILE_CONTENT); + when(appCenterStorage.getApplicationById(ID)).thenReturn(application()); + assertThrows(IllegalAccessException.class, + () -> applicationCenterService.getApplicationImageLastUpdated(application.getId(), TEST_USER)); + Long lastUpdated = applicationCenterService.getApplicationImageLastUpdated(application.getId(), ADMIN_USERNAME); + assertNotNull(lastUpdated); + } + + @Test + @SneakyThrows + void getImageStream() { + assertThrows(IllegalArgumentException.class, () -> applicationCenterService.getApplicationImageLastUpdated(50000L, null)); + assertThrows(ApplicationNotFoundException.class, + () -> applicationCenterService.getApplicationImageInputStream(50000L, TEST_USER)); + + Application application = application(); + application.setImageFileName("name"); + application.setImageFileBody(IMAGE_FILE_CONTENT); + when(appCenterStorage.getApplicationById(ID)).thenReturn(application()); + when(appCenterStorage.getApplicationImageInputStream(IMAGE_FILE_ID)).thenReturn(mock(InputStream.class)); + assertThrows(IllegalAccessException.class, + () -> applicationCenterService.getApplicationImageInputStream(application.getId(), TEST_USER)); + InputStream stream = applicationCenterService.getApplicationImageInputStream(application.getId(), ADMIN_USERNAME); + assertNotNull(stream); + } + + private Application application() { + return application(ID); + } + + private Application application(Long id) { + return new Application(id, + TITLE, + URL, + HELP_PAGE_URL, + IMAGE_FILE_ID, + IMAGE_LAST_MODIFIED, + "", + "", + DESCRIPTION, + false, + true, + false, + true, + false, + PERMISSIONS_1); + } + +} diff --git a/app-center-services/src/test/java/io/meeds/appcenter/storage/ApplicationCenterStorageTest.java b/app-center-services/src/test/java/io/meeds/appcenter/storage/ApplicationCenterStorageTest.java new file mode 100644 index 000000000..bd437dcb3 --- /dev/null +++ b/app-center-services/src/test/java/io/meeds/appcenter/storage/ApplicationCenterStorageTest.java @@ -0,0 +1,484 @@ +/** + * This file is part of the Meeds project (https://meeds.io/). + * + * Copyright (C) 2020 - 2024 Meeds Association contact@meeds.io + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package io.meeds.appcenter.storage; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.mockito.ArgumentMatchers.*; +import static org.mockito.Mockito.*; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.Optional; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.junit.jupiter.MockitoExtension; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.mock.mockito.MockBean; + +import org.exoplatform.commons.file.model.FileInfo; +import org.exoplatform.commons.file.model.FileItem; +import org.exoplatform.commons.file.services.FileService; + +import io.meeds.appcenter.dao.ApplicationDAO; +import io.meeds.appcenter.dao.FavoriteApplicationDAO; +import io.meeds.appcenter.entity.ApplicationEntity; +import io.meeds.appcenter.entity.FavoriteApplicationEntity; +import io.meeds.appcenter.model.Application; +import io.meeds.appcenter.model.ApplicationImage; +import io.meeds.appcenter.model.UserApplication; +import io.meeds.appcenter.model.exception.ApplicationNotFoundException; + +import lombok.SneakyThrows; + +@SpringBootTest(classes = { ApplicationCenterStorage.class }) +@ExtendWith(MockitoExtension.class) +public class ApplicationCenterStorageTest { + + private static final long IMAGE_FILE_ID = 5l; + + private static final long IMAGE_LAST_MODIFIED = 588l; + + private static final String HELP_PAGE_URL = "helpPageUrl"; + + private static final String URL = "url"; + + private static final String PERMISSIONS_2 = "permissions2"; + + private static final String PERMISSIONS_1 = "permissions1"; + + private static final String DESCRIPTION = "description"; + + private static final String TITLE = "title"; + + private static final String TEST_USER = "testuser"; + + private static final String FILE_CONTENT = "fileContent"; + + private static final Long ID = 2l; + + @MockBean + private FileService fileService; + + @MockBean + private ApplicationDAO applicationDAO; + + @MockBean + private FavoriteApplicationDAO favoriteApplicationDAO; + + @Autowired + private ApplicationCenterStorage applicationCenterStorage; + + @BeforeEach + void setup() { + when(applicationDAO.save(any())).thenAnswer(invocation -> { + ApplicationEntity entity = invocation.getArgument(0); + if (entity.getId() == null) { + entity.setId(ID); + } + when(applicationDAO.findById(ID)).thenReturn(Optional.of(entity)); + return entity; + }); + doAnswer(invocation -> { + ApplicationEntity entity = invocation.getArgument(0); + when(applicationDAO.findById(entity.getId())).thenReturn(Optional.empty()); + return null; + }).when(applicationDAO).delete(any()); + } + + @Test + void testCreateApplication() { + assertThrows(IllegalArgumentException.class, () -> applicationCenterStorage.createApplication(null)); + Application application = new Application(null, + TITLE, + URL, + "", + 0L, + 0L, + null, + null, + DESCRIPTION, + false, + true, + false, + false, + false, + PERMISSIONS_1, + PERMISSIONS_2); + + Application storedApplication = applicationCenterStorage.createApplication(application); + assertNotNull(storedApplication); + assertNotNull(storedApplication.getId()); + assertEquals(application.getTitle(), storedApplication.getTitle()); + assertEquals(application.getUrl(), storedApplication.getUrl()); + assertEquals(application.getImageFileId(), storedApplication.getImageFileId()); + assertEquals(application.getDescription(), storedApplication.getDescription()); + assertEquals(application.isActive(), storedApplication.isActive()); + assertEquals(application.isMandatory(), storedApplication.isMandatory()); + assertEquals(application.getPermissions(), storedApplication.getPermissions()); + } + + @Test + @SneakyThrows + void testUpdateApplication() { + ApplicationEntity existingApplication = new ApplicationEntity(ID, + TITLE + "1", + URL + "1", + HELP_PAGE_URL + "1", + 6l, + DESCRIPTION + "1", + true, + false, + false, + false, + PERMISSIONS_2, + false, + null); + when(applicationDAO.findById(ID)).thenReturn(Optional.of(existingApplication)); + + Application application = application(ID); + Application storedApplication = applicationCenterStorage.updateApplication(application); + + assertNotNull(storedApplication); + assertNotNull(storedApplication.getId()); + assertEquals(application.getTitle(), storedApplication.getTitle()); + assertEquals(application.getUrl(), storedApplication.getUrl()); + assertEquals(application.getImageFileId(), storedApplication.getImageFileId()); + assertEquals(application.getDescription(), storedApplication.getDescription()); + assertEquals(application.isActive(), storedApplication.isActive()); + assertEquals(application.isMandatory(), storedApplication.isMandatory()); + assertEquals(application.getPermissions(), storedApplication.getPermissions()); + } + + @Test + @SneakyThrows + void testDeleteApplication() { + assertThrows(IllegalArgumentException.class, () -> applicationCenterStorage.deleteApplication(0)); + assertThrows(ApplicationNotFoundException.class, () -> applicationCenterStorage.deleteApplication(5000L)); + + Application application = new Application(null, + TITLE, + URL, + "", + 0L, + 0L, + null, + null, + DESCRIPTION, + false, + true, + false, + false, + false, + PERMISSIONS_1, + PERMISSIONS_2); + + Application storedApplication = applicationCenterStorage.createApplication(application); + applicationCenterStorage.deleteApplication(storedApplication.getId()); + assertNull(applicationCenterStorage.getApplicationById(storedApplication.getId())); + } + + @Test + @SneakyThrows + void testGetApplication() { + assertThrows(IllegalArgumentException.class, () -> applicationCenterStorage.getApplicationById(0)); + assertNull(applicationCenterStorage.getApplicationById(50000)); + + Application application = new Application(null, + TITLE, + URL, + "", + 0L, + 0L, + null, + null, + DESCRIPTION, + false, + true, + false, + false, + false, + PERMISSIONS_1, + PERMISSIONS_2); + + Application storedApplication = applicationCenterStorage.createApplication(application); + storedApplication = applicationCenterStorage.getApplicationById(storedApplication.getId()); + assertNotNull(storedApplication); + assertNotNull(storedApplication.getId()); + assertEquals(application.getTitle(), storedApplication.getTitle()); + assertEquals(application.getUrl(), storedApplication.getUrl()); + assertEquals(application.getImageFileId(), storedApplication.getImageFileId()); + assertEquals(application.getDescription(), storedApplication.getDescription()); + assertEquals(application.isActive(), storedApplication.isActive()); + assertEquals(application.isMandatory(), storedApplication.isMandatory()); + assertEquals(application.getPermissions(), storedApplication.getPermissions()); + } + + @Test + void testGetApplicationByTitleOrURL() { + assertThrows(IllegalArgumentException.class, () -> applicationCenterStorage.getApplicationByTitle(null)); + assertNull(applicationCenterStorage.getApplicationByTitle(TITLE)); + + when(applicationDAO.getApplicationByTitle(TITLE)).thenReturn(applicationEntity(ID)); + Application storedApplication = applicationCenterStorage.getApplicationByTitle(TITLE); + assertNotNull(storedApplication); + } + + @Test + @SneakyThrows + void testAddApplicationToUserFavorite() { + assertThrows(IllegalArgumentException.class, () -> applicationCenterStorage.addApplicationToUserFavorite(0, TEST_USER)); + assertThrows(ApplicationNotFoundException.class, + () -> applicationCenterStorage.addApplicationToUserFavorite(50000, TEST_USER)); + + Application application = new Application(null, + TITLE, + URL, + "", + 0L, + 0L, + null, + null, + DESCRIPTION, + false, + true, + false, + false, + false, + PERMISSIONS_1, + PERMISSIONS_2); + + Application storedApplication = applicationCenterStorage.createApplication(application); + applicationCenterStorage.addApplicationToUserFavorite(storedApplication.getId(), TEST_USER); + } + + @Test + @SneakyThrows + void testUpdateApplicationFavoriteOrder() { + FavoriteApplicationEntity favoriteApplicationEntity = mock(FavoriteApplicationEntity.class); + when(favoriteApplicationDAO.getFavoriteAppByUserNameAndAppId(ID, TEST_USER)).thenReturn(favoriteApplicationEntity); + applicationCenterStorage.updateFavoriteApplicationOrder(ID, TEST_USER, 1l); + + verify(favoriteApplicationDAO).save(favoriteApplicationEntity); + + applicationCenterStorage.updateFavoriteApplicationOrder(ID, TEST_USER, 1l); + verify(favoriteApplicationDAO, times(2)).save(favoriteApplicationEntity); + } + + @Test + @SneakyThrows + void testDeleteApplicationFavorite() { + assertThrows(IllegalArgumentException.class, () -> applicationCenterStorage.deleteApplicationFavorite(0L, TEST_USER)); + applicationCenterStorage.deleteApplicationFavorite(50000L, TEST_USER); + Application application = new Application(null, + TITLE, + URL, + "", + 0L, + 0L, + null, + null, + DESCRIPTION, + false, + true, + false, + false, + false, + PERMISSIONS_1, + PERMISSIONS_2); + Application storedApplication = applicationCenterStorage.createApplication(application); + applicationCenterStorage.addApplicationToUserFavorite(storedApplication.getId(), TEST_USER); + applicationCenterStorage.deleteApplicationFavorite(storedApplication.getId(), TEST_USER); + } + + @Test + @SneakyThrows + void testGetFavoriteApplicationsByUser() { + assertThrows(IllegalArgumentException.class, () -> applicationCenterStorage.getFavoriteApplicationsByUser(null)); + List favoriteApplications = applicationCenterStorage.getFavoriteApplicationsByUser(TEST_USER); + assertNotNull(favoriteApplications); + assertEquals(0, favoriteApplications.size()); + + FavoriteApplicationEntity favoriteApplicationEntity = mock(FavoriteApplicationEntity.class); + ApplicationEntity applicationEntity = mock(ApplicationEntity.class); + when(favoriteApplicationDAO.getFavoriteAppsByUser(TEST_USER)).thenReturn(Collections.singletonList(favoriteApplicationEntity)); + when(favoriteApplicationEntity.getApplication()).thenReturn(applicationEntity); + when(applicationEntity.isActive()).thenReturn(true); + assertEquals(1, applicationCenterStorage.getFavoriteApplicationsByUser(TEST_USER).size()); + + when(applicationEntity.isMandatory()).thenReturn(true); + assertEquals(1, applicationCenterStorage.getFavoriteApplicationsByUser(TEST_USER).size()); + + when(applicationEntity.isActive()).thenReturn(false); + assertEquals(0, applicationCenterStorage.getFavoriteApplicationsByUser(TEST_USER).size()); + } + + @Test + void testGetMandatoryApplicationsByUser() { + assertThrows(IllegalArgumentException.class, () -> applicationCenterStorage.getFavoriteApplicationsByUser(null)); + + List mandatoryApplications = applicationCenterStorage.getMandatoryApplications(); + assertNotNull(mandatoryApplications); + assertEquals(0, mandatoryApplications.size()); + when(applicationDAO.getMandatoryActiveApps()).thenReturn(Collections.singletonList(applicationEntity())); + assertEquals(1, applicationCenterStorage.getMandatoryApplications().size()); + } + + @Test + void testGetApplications() { + + List applications = applicationCenterStorage.getApplications(null); + assertNotNull(applications); + assertEquals(0, applications.size()); + + applications = applicationCenterStorage.getApplications(TITLE); + assertNotNull(applications); + assertEquals(0, applications.size()); + + when(applicationDAO.findAll()).thenReturn(Arrays.asList(applicationEntity(3l), + applicationEntity(2l), + applicationEntity(5l))); + when(applicationDAO.getApplications(TITLE)).thenReturn(Arrays.asList(applicationEntity(3l), + applicationEntity(5l))); + when(applicationDAO.getApplications(URL)).thenReturn(Arrays.asList(applicationEntity(3l))); + + applications = applicationCenterStorage.getApplications(null); + assertNotNull(applications); + assertEquals(3, applications.size()); + + applications = applicationCenterStorage.getApplications(TITLE); + assertNotNull(applications); + assertEquals(2, applications.size()); + + applications = applicationCenterStorage.getApplications(URL); + assertNotNull(applications); + assertEquals(1, applications.size()); + } + + @Test + void testCountApplications() { + assertEquals(0l, applicationCenterStorage.countApplications()); + when(applicationDAO.count()).thenReturn(1l); + assertEquals(1l, applicationCenterStorage.countApplications()); + } + + @Test + @SneakyThrows + void testIsFavoriteApplication() { + assertThrows(IllegalArgumentException.class, () -> applicationCenterStorage.isFavoriteApplication(null, null)); + assertThrows(IllegalArgumentException.class, () -> applicationCenterStorage.isFavoriteApplication(null, TEST_USER)); + assertThrows(IllegalArgumentException.class, () -> applicationCenterStorage.isFavoriteApplication(0L, TEST_USER)); + assertThrows(IllegalArgumentException.class, () -> applicationCenterStorage.isFavoriteApplication(1L, null)); + when(favoriteApplicationDAO.getFavoriteAppByUserNameAndAppId(ID, + TEST_USER)).thenReturn(mock(FavoriteApplicationEntity.class)); + assertFalse(applicationCenterStorage.isFavoriteApplication(1L, TEST_USER)); + assertTrue(applicationCenterStorage.isFavoriteApplication(ID, TEST_USER)); + } + + @Test + @SneakyThrows + void testCountFavorites() { + assertThrows(IllegalArgumentException.class, () -> applicationCenterStorage.countFavorites(null)); + assertEquals(0, applicationCenterStorage.countFavorites(TEST_USER)); + when(favoriteApplicationDAO.countFavoritesForUser(TEST_USER)).thenReturn(1l); + assertEquals(1, applicationCenterStorage.countFavorites(TEST_USER)); + } + + @Test + void testCreateAppImageFileItem() { + assertNull(applicationCenterStorage.createAppImageFileItem(null, null)); + assertNull(applicationCenterStorage.createAppImageFileItem("name", null)); + assertNull(applicationCenterStorage.createAppImageFileItem(null, FILE_CONTENT)); + ApplicationImage applicationImage = applicationCenterStorage.createAppImageFileItem("name", FILE_CONTENT); + assertNotNull(applicationImage); + assertNotNull(applicationImage.getFileName()); + assertNotNull(applicationImage.getFileBody()); + } + + @Test + @SneakyThrows + void testGetAppImageFile() { + ApplicationImage applicationImage = applicationCenterStorage.createAppImageFileItem("name", FILE_CONTENT); + assertNotNull(applicationImage); + + applicationImage = applicationCenterStorage.getAppImageFile(ID); + assertNull(applicationImage); + + FileItem fileItem = mock(FileItem.class); + FileInfo fileInfo = mock(FileInfo.class); + when(fileItem.getAsByte()).thenReturn(FILE_CONTENT.getBytes()); + when(fileItem.getFileInfo()).thenReturn(fileInfo); + when(fileInfo.getName()).thenReturn("filename"); + when(fileService.getFile(IMAGE_FILE_ID)).thenReturn(fileItem); + + applicationImage = applicationCenterStorage.getAppImageFile(IMAGE_FILE_ID); + assertNotNull(applicationImage); + assertNotNull(applicationImage.getFileName()); + assertNotNull(applicationImage.getFileBody()); + } + + private ApplicationEntity applicationEntity() { + return applicationEntity(null); + } + + private ApplicationEntity applicationEntity(Long id) { + return new ApplicationEntity(id, + TITLE + "1", + URL + "1", + HELP_PAGE_URL + "1", + 6l, + DESCRIPTION + "1", + true, + false, + false, + false, + PERMISSIONS_2, + false, + null); + } + + private Application application(Long id) { + return new Application(id, + "titre", + URL, + HELP_PAGE_URL, + IMAGE_FILE_ID, + IMAGE_LAST_MODIFIED, + "", + "", + DESCRIPTION, + false, + true, + false, + true, + false, + PERMISSIONS_1); + } + +} diff --git a/app-center-services/src/test/java/org/exoplatform/appcenter/dao/ApplicationDAOTest.java b/app-center-services/src/test/java/org/exoplatform/appcenter/dao/ApplicationDAOTest.java deleted file mode 100644 index 69513bf76..000000000 --- a/app-center-services/src/test/java/org/exoplatform/appcenter/dao/ApplicationDAOTest.java +++ /dev/null @@ -1,296 +0,0 @@ -/* - * This file is part of the Meeds project (https://meeds.io/). - * Copyright (C) 2020 Meeds Association - * contact@meeds.io - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.exoplatform.appcenter.dao; - -import static org.junit.Assert.*; - -import java.util.List; - -import org.junit.After; -import org.junit.Before; -import org.junit.BeforeClass; -import org.junit.Test; - -import org.exoplatform.appcenter.entity.ApplicationEntity; -import org.exoplatform.appcenter.entity.FavoriteApplicationEntity; -import org.exoplatform.container.ExoContainerContext; -import org.exoplatform.container.PortalContainer; -import org.exoplatform.container.RootContainer; -import org.exoplatform.container.component.RequestLifeCycle; -import org.exoplatform.services.naming.InitialContextInitializer; - -public class ApplicationDAOTest { - - private PortalContainer container; - - @BeforeClass - @SuppressWarnings("deprecation") - public static void startDB() { - RootContainer rootContainer = RootContainer.getInstance(); - InitialContextInitializer initializer = rootContainer.getComponentInstanceOfType(InitialContextInitializer.class); - initializer.recall(); // NOSONAR - } - - @Before - public void setup() { - container = PortalContainer.getInstance(); - assertNotNull(container); - ExoContainerContext.setCurrentContainer(container); - RequestLifeCycle.begin(container); - } - - @After - public void teardown() { - ApplicationDAO service = ExoContainerContext.getService(ApplicationDAO.class); - service.deleteAll(); - - RequestLifeCycle.end(); - container.stop(); - container = null; - ExoContainerContext.setCurrentContainer(null); - } - - @Test - public void testServiceInitialized() { - ApplicationDAO service = ExoContainerContext.getService(ApplicationDAO.class); - assertNotNull(service); - - ApplicationEntity applicationEntity = new ApplicationEntity(null, - "title", - "url", - 5L, - "description", - true, - false, - "permissions", - false); - ApplicationEntity storedEntity = service.create(applicationEntity); - assertNotNull(storedEntity); - assertNotNull(storedEntity.getId()); - assertEquals(applicationEntity.getTitle(), storedEntity.getTitle()); - assertEquals(applicationEntity.getUrl(), storedEntity.getUrl()); - assertEquals(applicationEntity.getImageFileId(), storedEntity.getImageFileId()); - assertEquals(applicationEntity.getDescription(), storedEntity.getDescription()); - assertEquals(applicationEntity.isActive(), storedEntity.isActive()); - assertEquals(applicationEntity.isMandatory(), storedEntity.isMandatory()); - assertEquals(applicationEntity.getPermissions(), storedEntity.getPermissions()); - - // Test setters - applicationEntity = new ApplicationEntity(); - applicationEntity.setId(null); - applicationEntity.setTitle("title"); - applicationEntity.setUrl("url"); - applicationEntity.setImageFileId(5L); - applicationEntity.setDescription("description"); - applicationEntity.setActive(false); - applicationEntity.setMandatory(true); - applicationEntity.setPermissions("permissions"); - - storedEntity = service.create(applicationEntity); - assertNotNull(storedEntity); - assertNotNull(storedEntity.getId()); - assertEquals(applicationEntity.getTitle(), storedEntity.getTitle()); - assertEquals(applicationEntity.getUrl(), storedEntity.getUrl()); - assertEquals(applicationEntity.getImageFileId(), storedEntity.getImageFileId()); - assertEquals(applicationEntity.getDescription(), storedEntity.getDescription()); - assertEquals(applicationEntity.isActive(), storedEntity.isActive()); - assertEquals(applicationEntity.isMandatory(), storedEntity.isMandatory()); - assertEquals(applicationEntity.getPermissions(), storedEntity.getPermissions()); - } - - @Test - public void testFindApplications() { - ApplicationDAO service = ExoContainerContext.getService(ApplicationDAO.class); - assertNotNull(service); - - ApplicationEntity applicationEntity = new ApplicationEntity(null, - "title", - "url", - 5L, - "description", - true, - false, - "permissions",false); - applicationEntity = service.create(applicationEntity); - ApplicationEntity applicationEntity2 = new ApplicationEntity(null, - "title2", - "url2", - 5L, - "description2", - true, - false, - "permissions",false); - applicationEntity2 = service.create(applicationEntity2); - - List applications = service.getApplications("title"); - assertNotNull(applications); - assertEquals(2, applications.size()); - assertEquals(applicationEntity.getId(), applications.get(0).getId()); - - applications = service.getApplications("title*"); - assertNotNull(applications); - assertEquals(2, applications.size()); - assertEquals(applicationEntity.getId(), applications.get(0).getId()); - assertEquals(applicationEntity2.getId(), applications.get(1).getId()); - - applications = service.getApplications("title*"); - assertNotNull(applications); - assertEquals(2, applications.size()); - - applications = service.getApplications("title2"); - assertNotNull(applications); - assertEquals(1, applications.size()); - assertEquals(applicationEntity2.getId(), applications.get(0).getId()); - } - - @Test - public void testGetApplicationByTitle() { - ApplicationDAO applicationDAO = ExoContainerContext.getService(ApplicationDAO.class); - assertNotNull(applicationDAO); - FavoriteApplicationDAO favoriteApplicationDAO = ExoContainerContext.getService(FavoriteApplicationDAO.class); - assertNotNull(favoriteApplicationDAO); - - ApplicationEntity applicationEntity = new ApplicationEntity(null, - "title", - "url", - 5L, - "description", - true, - false, - "permissions",false); - applicationDAO.create(applicationEntity); - ApplicationEntity applicationEntity2 = new ApplicationEntity(null, - "title2", - "url2", - 5L, - "description2", - true, - false, - "permissions",false); - applicationDAO.create(applicationEntity2); - - ApplicationEntity foundEntity = applicationDAO.getApplicationByTitle("title"); - assertNotNull(foundEntity); - assertEquals(applicationEntity.getId(), foundEntity.getId()); - - foundEntity = applicationDAO.getApplicationByTitle("title2"); - assertNotNull(foundEntity); - assertEquals(applicationEntity2.getId(), foundEntity.getId()); - - foundEntity = applicationDAO.getApplicationByTitle("title3"); - assertNull(foundEntity); - } - - @Test - public void testGetFavoriteApps() { - ApplicationDAO applicationDAO = ExoContainerContext.getService(ApplicationDAO.class); - assertNotNull(applicationDAO); - FavoriteApplicationDAO favoriteApplicationDAO = ExoContainerContext.getService(FavoriteApplicationDAO.class); - assertNotNull(favoriteApplicationDAO); - - ApplicationEntity applicationEntity = new ApplicationEntity(null, - "title", - "url", - 5L, - "description", - true, - false, - "permissions",false); - applicationEntity = applicationDAO.create(applicationEntity); - - ApplicationEntity applicationEntity2 = new ApplicationEntity(null, - "title2", - "url2", - 5L, - "description2", - true, - false, - "permissions",false); - applicationEntity2 = applicationDAO.create(applicationEntity2); - - ApplicationEntity applicationEntity3 = new ApplicationEntity(null, - "title2", - "url2", - 5L, - "description2", - true, - true, - "permissions",false); - applicationEntity3 = applicationDAO.create(applicationEntity3); - - favoriteApplicationDAO.create(new FavoriteApplicationEntity(applicationEntity, "testuser")); - favoriteApplicationDAO.create(new FavoriteApplicationEntity(applicationEntity, "testuser2")); - favoriteApplicationDAO.create(new FavoriteApplicationEntity(applicationEntity, "testuser3")); - favoriteApplicationDAO.create(new FavoriteApplicationEntity(applicationEntity, "testuser4")); - - favoriteApplicationDAO.create(new FavoriteApplicationEntity(applicationEntity2, "testuser")); - favoriteApplicationDAO.create(new FavoriteApplicationEntity(applicationEntity2, "testuser3")); - - List favorites = favoriteApplicationDAO.getFavoriteAppsByUser("testuser"); - assertNotNull(favorites); - assertEquals(2, favorites.size()); - - favorites = favoriteApplicationDAO.getFavoriteAppsByUser("testuser2"); - assertNotNull(favorites); - assertEquals(1, favorites.size()); - - favorites = favoriteApplicationDAO.getFavoriteAppsByUser("fake"); - assertNotNull(favorites); - assertEquals(0, favorites.size()); - } - - @Test - public void testGetMandatoryApps() { - ApplicationDAO applicationDAO = ExoContainerContext.getService(ApplicationDAO.class); - assertNotNull(applicationDAO); - - ApplicationEntity applicationEntity1 = new ApplicationEntity(null, - "title1", - "url1", - 5L, - "description1", - true, - true, - "permissions",false); - applicationDAO.create(applicationEntity1); - - ApplicationEntity applicationEntity2 = new ApplicationEntity(null, - "title2", - "url2", - 5L, - "description2", - true, - true, - "permissions",false); - applicationDAO.create(applicationEntity2); - - ApplicationEntity applicationEntity3 = new ApplicationEntity(null, - "title3", - "url3", - 5L, - "description3", - false, - true, - "permissions",false); - applicationDAO.create(applicationEntity3); - - List mandatoryApps = applicationDAO.getMandatoryActiveApps(); - assertNotNull(mandatoryApps); - assertEquals(2, mandatoryApps.size()); - } - -} diff --git a/app-center-services/src/test/java/org/exoplatform/appcenter/dao/FavoriteApplicationDAOTest.java b/app-center-services/src/test/java/org/exoplatform/appcenter/dao/FavoriteApplicationDAOTest.java deleted file mode 100644 index 0ce2ab81d..000000000 --- a/app-center-services/src/test/java/org/exoplatform/appcenter/dao/FavoriteApplicationDAOTest.java +++ /dev/null @@ -1,186 +0,0 @@ -/* - * This file is part of the Meeds project (https://meeds.io/). - * Copyright (C) 2020 Meeds Association - * contact@meeds.io - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.exoplatform.appcenter.dao; - -import static org.junit.Assert.*; - -import org.junit.*; - -import org.exoplatform.appcenter.entity.ApplicationEntity; -import org.exoplatform.appcenter.entity.FavoriteApplicationEntity; -import org.exoplatform.container.*; -import org.exoplatform.container.component.RequestLifeCycle; -import org.exoplatform.services.naming.InitialContextInitializer; - -public class FavoriteApplicationDAOTest { - - private PortalContainer container; - - @BeforeClass - @SuppressWarnings("deprecation") - public static void startDB() { - RootContainer rootContainer = RootContainer.getInstance(); - InitialContextInitializer initializer = rootContainer.getComponentInstanceOfType(InitialContextInitializer.class); - initializer.recall(); // NOSONAR - } - - @Before - public void setup() { - container = PortalContainer.getInstance(); - assertNotNull(container); - ExoContainerContext.setCurrentContainer(container); - RequestLifeCycle.begin(container); - } - - @After - public void teardown() { - FavoriteApplicationDAO favoriteApplicationDAO = ExoContainerContext.getService(FavoriteApplicationDAO.class); - favoriteApplicationDAO.deleteAll(); - - ApplicationDAO applicationDAO = ExoContainerContext.getService(ApplicationDAO.class); - applicationDAO.deleteAll(); - - RequestLifeCycle.end(); - container.stop(); - container = null; - ExoContainerContext.setCurrentContainer(null); - } - - @Test - public void testServiceInitialized() { - ApplicationDAO applicationDAO = ExoContainerContext.getService(ApplicationDAO.class); - assertNotNull(applicationDAO); - FavoriteApplicationDAO favoriteApplicationDAO = ExoContainerContext.getService(FavoriteApplicationDAO.class); - assertNotNull(favoriteApplicationDAO); - - ApplicationEntity applicationEntity = new ApplicationEntity(null, - "title", - "url", - 5L, - "description", - true, - false, - "permissions",false); - applicationEntity = applicationDAO.create(applicationEntity); - FavoriteApplicationEntity favoriteApp = new FavoriteApplicationEntity(); - favoriteApp.setId(null); - favoriteApp.setApplication(applicationEntity); - favoriteApp.setUserName("testuser"); - favoriteApp = favoriteApplicationDAO.create(favoriteApp); - assertNotNull(favoriteApp); - assertNotNull(favoriteApp.getId()); - assertNotNull(favoriteApp.getApplication()); - assertEquals(applicationEntity.getId(), favoriteApp.getApplication().getId()); - assertEquals("testuser", favoriteApp.getUserName()); - } - - @Test - public void testGetFavoriteAppByUserNameAndAppId() { - ApplicationDAO applicationDAO = ExoContainerContext.getService(ApplicationDAO.class); - assertNotNull(applicationDAO); - FavoriteApplicationDAO favoriteApplicationDAO = ExoContainerContext.getService(FavoriteApplicationDAO.class); - assertNotNull(favoriteApplicationDAO); - - ApplicationEntity applicationEntity = new ApplicationEntity(null, - "title", - "url", - 5L, - "description", - true, - false, - "permissions",false); - applicationEntity = applicationDAO.create(applicationEntity); - - ApplicationEntity applicationEntity2 = new ApplicationEntity(null, - "title2", - "url2", - 5L, - "description2", - true, - false, - "permissions",false); - applicationEntity2 = applicationDAO.create(applicationEntity2); - - favoriteApplicationDAO.create(new FavoriteApplicationEntity(applicationEntity, "testuser")); - favoriteApplicationDAO.create(new FavoriteApplicationEntity(applicationEntity, "testuser2")); - favoriteApplicationDAO.create(new FavoriteApplicationEntity(applicationEntity, "testuser3")); - favoriteApplicationDAO.create(new FavoriteApplicationEntity(applicationEntity, "testuser4")); - - favoriteApplicationDAO.create(new FavoriteApplicationEntity(applicationEntity2, "testuser")); - favoriteApplicationDAO.create(new FavoriteApplicationEntity(applicationEntity2, "testuser3")); - - FavoriteApplicationEntity favoriteApp = favoriteApplicationDAO.getFavoriteAppByUserNameAndAppId(applicationEntity.getId(), - "testuser4"); - assertNotNull(favoriteApp); - assertNotNull(favoriteApp.getId()); - assertNotNull(favoriteApp.getApplication()); - assertEquals(applicationEntity.getId(), favoriteApp.getApplication().getId()); - assertEquals("testuser4", favoriteApp.getUserName()); - - favoriteApp = favoriteApplicationDAO.getFavoriteAppByUserNameAndAppId(applicationEntity2.getId(), "testuser3"); - assertNotNull(favoriteApp); - assertNotNull(favoriteApp.getId()); - assertNotNull(favoriteApp.getApplication()); - assertEquals(applicationEntity2.getId(), favoriteApp.getApplication().getId()); - assertEquals("testuser3", favoriteApp.getUserName()); - - favoriteApp = favoriteApplicationDAO.getFavoriteAppByUserNameAndAppId(applicationEntity.getId(), "fake"); - assertNull(favoriteApp); - } - - @Test - public void testCountFavoritesForUser() { - ApplicationDAO applicationDAO = ExoContainerContext.getService(ApplicationDAO.class); - assertNotNull(applicationDAO); - FavoriteApplicationDAO favoriteApplicationDAO = ExoContainerContext.getService(FavoriteApplicationDAO.class); - assertNotNull(favoriteApplicationDAO); - - ApplicationEntity applicationEntity = new ApplicationEntity(null, - "title", - "url", - 5L, - "description", - true, - false, - "permissions",false); - applicationEntity = applicationDAO.create(applicationEntity); - - ApplicationEntity applicationEntity2 = new ApplicationEntity(null, - "title2", - "url2", - 5L, - "description2", - true, - false, - "permissions",false); - applicationEntity2 = applicationDAO.create(applicationEntity2); - - favoriteApplicationDAO.create(new FavoriteApplicationEntity(applicationEntity, "testuser")); - favoriteApplicationDAO.create(new FavoriteApplicationEntity(applicationEntity, "testuser2")); - favoriteApplicationDAO.create(new FavoriteApplicationEntity(applicationEntity, "testuser3")); - favoriteApplicationDAO.create(new FavoriteApplicationEntity(applicationEntity, "testuser4")); - - favoriteApplicationDAO.create(new FavoriteApplicationEntity(applicationEntity2, "testuser")); - favoriteApplicationDAO.create(new FavoriteApplicationEntity(applicationEntity2, "testuser3")); - - assertEquals(2, favoriteApplicationDAO.countFavoritesForUser("testuser")); - assertEquals(1, favoriteApplicationDAO.countFavoritesForUser("testuser2")); - assertEquals(2, favoriteApplicationDAO.countFavoritesForUser("testuser3")); - assertEquals(1, favoriteApplicationDAO.countFavoritesForUser("testuser4")); - } - -} diff --git a/app-center-services/src/test/java/org/exoplatform/appcenter/rest/ApplicationCenterRestServiceTest.java b/app-center-services/src/test/java/org/exoplatform/appcenter/rest/ApplicationCenterRestServiceTest.java deleted file mode 100644 index b731eda1a..000000000 --- a/app-center-services/src/test/java/org/exoplatform/appcenter/rest/ApplicationCenterRestServiceTest.java +++ /dev/null @@ -1,140 +0,0 @@ -package org.exoplatform.appcenter.rest; - -import static org.junit.Assert.assertEquals; - -import java.util.ArrayList; -import java.util.List; - -import javax.ws.rs.core.Response; - -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.Mock; -import org.mockito.Mockito; -import org.mockito.runners.MockitoJUnitRunner; - -import org.exoplatform.appcenter.dto.*; -import org.exoplatform.appcenter.service.ApplicationCenterService; -import org.exoplatform.container.PortalContainer; - -@RunWith(MockitoJUnitRunner.class) -public class ApplicationCenterRestServiceTest { - - @Mock - private ApplicationCenterService applicationCenterService; - - @Mock - private PortalContainer portalContainer; - - @Before - public void setup() throws Exception { - Mockito.when(portalContainer.getName()).thenReturn("portal"); - Mockito.when(portalContainer.getRestContextName()).thenReturn("rest"); - } - - @Test - public void testGetApplicationsList() throws Exception { - - ApplicationList result = new ApplicationList(); - List resultList = new ArrayList(); - resultList.add(new Application(1L, "titre1", "url1", "", 0L, 0L, "", "", - "description1", false, true, false, true, false,"")); - resultList.add(new Application(2L, "titre2", "url2", "", 0L, 0L, "", "", - "description2", false, true, false, true, false,"")); - resultList.add(new Application(3L, "titre3", "url3", "", 0L, 0L, "", "", - "description3", false, true, false, true, false,"")); - resultList.add(new Application(4L, "titre4", "url4", "", 0L, 0L, "", "", - "description4", false, true, false, true, false,"")); - resultList.add(new Application(5L, "titre5", "url5", "", 0L, 0L, "", "", - "description5", false, true, false, true, false,"")); - result.setApplications(resultList); - Mockito.when(applicationCenterService.getApplicationsList(0,10,"")).thenReturn(result); - - ApplicationCenterREST applicationCenterREST= new ApplicationCenterREST(applicationCenterService,portalContainer); - Response response = applicationCenterREST.getApplicationsList(0, 10, ""); - assertEquals(200,response.getStatus()); - assertEquals(resultList.size(),((ApplicationList)response.getEntity()).getApplications().size()); - - } - - @Test - public void testGetAuthorizedApplicationsList() throws Exception { - - ApplicationList result = new ApplicationList(); - List resultList = new ArrayList(); - resultList.add(new Application(1L, "titre1", "url1", "", 0L, 0L, "", "", - "description1", false, true, false, true, false,"")); - resultList.add(new Application(2L, "titre2", "url2", "", 0L, 0L, "", "", - "description2", false, true, false, true, false,"")); - resultList.add(new Application(3L, "titre3", "url3", "", 0L, 0L, "", "", - "description3", false, true, false, true, false,"")); - resultList.add(new Application(4L, "titre4", "url4", "", 0L, 0L, "", "", - "description4", false, true, false, true, false,"")); - resultList.add(new Application(5L, "titre5", "url5", "", 0L, 0L, "", "", - "description5", false, true, false, true, false,"")); - result.setApplications(resultList); - Mockito.when(applicationCenterService.getAuthorizedApplicationsList(0,10,"",null)).thenReturn(result); - - ApplicationCenterREST applicationCenterREST= new ApplicationCenterREST(applicationCenterService,portalContainer); - Response response = applicationCenterREST.getAuthorizedApplicationsList(0, 10, ""); - assertEquals(200,response.getStatus()); - assertEquals(resultList.size(),((ApplicationList)response.getEntity()).getApplications().size()); - - } - - @Test - public void testGetFavoriteApplicationsList() throws Exception { - - ApplicationList result = new ApplicationList(); - List resultList = new ArrayList(); - resultList.add(new Application(1L, "titre1", "url1", "", 0L, 0L, "", "", - "description1", false, true, false, true, false,"")); - resultList.add(new Application(2L, "titre2", "url2", "", 0L, 0L, "", "", - "description2", false, true, false, true, false,"")); - resultList.add(new Application(3L, "titre3", "url3", "", 0L, 0L, "", "", - "description3", false, true, false, true, false,"")); - resultList.add(new Application(4L, "titre4", "url4", "", 0L, 0L, "", "", - "description4", false, true, false, true, false,"")); - resultList.add(new Application(5L, "titre5", "url5", "", 0L, 0L, "", "", - "description5", false, true, false, true, false,"")); - result.setApplications(resultList); - Mockito.when(applicationCenterService.getMandatoryAndFavoriteApplicationsList(null)).thenReturn(result); - - ApplicationCenterREST applicationCenterREST= new ApplicationCenterREST(applicationCenterService,portalContainer); - Response response = applicationCenterREST.getFavoriteApplicationsList(); - assertEquals(200,response.getStatus()); - assertEquals(resultList.size(),((ApplicationList)response.getEntity()).getApplications().size()); - - } - - @Test - public void testLogFunctions() throws Exception { - ApplicationCenterREST applicationCenterREST= new ApplicationCenterREST(applicationCenterService,portalContainer); - Response response =applicationCenterREST.logClickAllApplications(); - assertEquals(200,response.getStatus()); - - Application application = new Application(1L, "titre1", "url1", "", 0L, 0L, "", "", - "description1", false, true, false, true, false,""); - Mockito.when(applicationCenterService.findApplication(1L)).thenReturn(application); - response =applicationCenterREST.logClickOneApplications(1L); - assertEquals(200,response.getStatus()); - - response =applicationCenterREST.logOpenDrawer(); - assertEquals(200,response.getStatus()); - } - - @Test - public void testGeneralSettings() throws Exception { - - GeneralSettings generalSettings = new GeneralSettings(); - generalSettings.setMaxFavoriteApps(12L); - ApplicationCenterREST applicationCenterREST= new ApplicationCenterREST(applicationCenterService,portalContainer); - Mockito.when(applicationCenterService.getAppGeneralSettings()).thenReturn(generalSettings); - - Response response = applicationCenterREST.getAppGeneralSettings(); - assertEquals(200,response.getStatus()); - assertEquals(generalSettings.getMaxFavoriteApps(),((GeneralSettings)response.getEntity()).getMaxFavoriteApps()); - - } -} diff --git a/app-center-services/src/test/java/org/exoplatform/appcenter/service/ApplicationCenterServiceTest.java b/app-center-services/src/test/java/org/exoplatform/appcenter/service/ApplicationCenterServiceTest.java deleted file mode 100644 index 673e2ef38..000000000 --- a/app-center-services/src/test/java/org/exoplatform/appcenter/service/ApplicationCenterServiceTest.java +++ /dev/null @@ -1,1381 +0,0 @@ -/* - * This file is part of the Meeds project (https://meeds.io/). - * Copyright (C) 2020 Meeds Association - * contact@meeds.io - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.exoplatform.appcenter.service; - -import static org.junit.Assert.*; - -import java.io.FileNotFoundException; -import java.io.InputStream; -import java.net.MalformedURLException; -import java.util.ArrayList; -import java.util.Collection; - -import org.exoplatform.appcenter.storage.ApplicationCenterStorage; -import org.exoplatform.services.organization.*; -import org.exoplatform.services.organization.idm.MembershipImpl; -import org.junit.After; -import org.junit.Before; -import org.junit.BeforeClass; -import org.junit.Test; -import org.picocontainer.Startable; - -import org.exoplatform.appcenter.dao.ApplicationDAO; -import org.exoplatform.appcenter.dao.FavoriteApplicationDAO; -import org.exoplatform.appcenter.dto.*; -import org.exoplatform.appcenter.plugin.ApplicationPlugin; -import org.exoplatform.commons.file.services.FileStorageException; -import org.exoplatform.commons.file.services.NameSpaceService; -import org.exoplatform.container.ExoContainerContext; -import org.exoplatform.container.PortalContainer; -import org.exoplatform.container.RootContainer; -import org.exoplatform.container.component.RequestLifeCycle; -import org.exoplatform.container.xml.InitParams; -import org.exoplatform.container.xml.ObjectParameter; -import org.exoplatform.container.xml.ValueParam; -import org.exoplatform.services.naming.InitialContextInitializer; -import org.exoplatform.services.security.ConversationState; -import org.exoplatform.services.security.Identity; -import org.exoplatform.services.security.MembershipEntry; - -public class ApplicationCenterServiceTest { - - private static final String ADMIN_USERNAME = "admin"; - - private static final String SIMPLE_USERNAME = "simple"; - - private ConversationState adminState; - - private ConversationState simpleState; - - private ApplicationCenterService applicationCenterService; - - private ApplicationCenterStorage appCenterStorage; - - @BeforeClass - @SuppressWarnings("deprecation") - public static void startDB() { - RootContainer rootContainer = RootContainer.getInstance(); - InitialContextInitializer initializer = rootContainer.getComponentInstanceOfType(InitialContextInitializer.class); - initializer.recall(); // NOSONAR - } - - @Before - @SuppressWarnings("deprecation") - public void setup() throws Exception { - PortalContainer container = PortalContainer.getInstance(); - assertNotNull(container); - - ExoContainerContext.setCurrentContainer(container); - RequestLifeCycle.begin(container); - applicationCenterService = ExoContainerContext.getService(ApplicationCenterService.class); - appCenterStorage = ExoContainerContext.getService(ApplicationCenterStorage.class); - - OrganizationService organizationService = ExoContainerContext.getService(OrganizationService.class); - UserHandler userHandler = organizationService.getUserHandler(); - MembershipHandler membershipHandler = organizationService.getMembershipHandler(); - - User adminUser = userHandler.findUserByName(ADMIN_USERNAME); - if (adminUser == null) { - adminUser = userHandler.createUserInstance(ADMIN_USERNAME); - userHandler.createUser(adminUser, true); - - Membership membership = new MembershipImpl("member:" + ADMIN_USERNAME + ":" - + ApplicationCenterService.DEFAULT_ADMINISTRATORS_GROUP); - membershipHandler.createMembership(membership, true); // NOSONAR - } - User simpleUser = userHandler.findUserByName(SIMPLE_USERNAME); - if (simpleUser == null) { - simpleUser = userHandler.createUserInstance(SIMPLE_USERNAME); - userHandler.createUser(simpleUser, true); - } - - // Workaround, the service wasn't started - Startable fileNameSpaceService = (Startable) ExoContainerContext.getService(NameSpaceService.class); - assertNotNull(fileNameSpaceService); - fileNameSpaceService.start(); - - Collection adminMemberships = new ArrayList(); - adminMemberships.add(new MembershipEntry(ApplicationCenterService.DEFAULT_ADMINISTRATORS_GROUP, "*")); - adminMemberships.add(new MembershipEntry(ApplicationCenterService.DEFAULT_USERS_GROUP, "*")); - Collection simpleMemberships = new ArrayList(); - simpleMemberships.add(new MembershipEntry(ApplicationCenterService.DEFAULT_USERS_GROUP, "*")); - - Identity adminIdentity = new Identity(ADMIN_USERNAME, adminMemberships); - Identity simpleIdentity = new Identity(SIMPLE_USERNAME, simpleMemberships); - - adminState = new ConversationState(adminIdentity); - simpleState = new ConversationState(simpleIdentity); - } - - @After - public void teardown() { - FavoriteApplicationDAO favoriteApplicationDAO = ExoContainerContext.getService(FavoriteApplicationDAO.class); - favoriteApplicationDAO.deleteAll(); - - ApplicationDAO applicationDAO = ExoContainerContext.getService(ApplicationDAO.class); - applicationDAO.deleteAll(); - - ConversationState.setCurrent(null); - - RequestLifeCycle.end(); - ExoContainerContext.setCurrentContainer(null); - } - - @Test - public void testCreateApplication() throws Exception { - try { - applicationCenterService.createApplication(null); - fail("Shouldn't allow to add null application"); - } catch (IllegalArgumentException e) { - // Expected - } - - Application application = new Application(null, - "title", - "./url", - "", - 0L, - 0L, - null, - null, - "description", - false, - true, - false, - false, - false, - "permissions1", - "permissions2"); - - Application storedApplication = applicationCenterService.createApplication(application); - assertNotNull(storedApplication); - assertNotNull(storedApplication.getId()); - assertEquals(application.getTitle(), storedApplication.getTitle()); - assertEquals(application.getUrl(), storedApplication.getUrl()); - assertEquals(application.getImageFileId(), storedApplication.getImageFileId()); - assertEquals(application.getDescription(), storedApplication.getDescription()); - assertEquals(application.isActive(), storedApplication.isActive()); - assertEquals(application.isMandatory(), storedApplication.isMandatory()); - assertEquals(application.getPermissions(), storedApplication.getPermissions()); - - try { - applicationCenterService.createApplication(storedApplication); - fail("Shouldn't allow to create the application again"); - } catch (ApplicationAlreadyExistsException e) { - // Expected - } - // - application.setUrl(""); - application.setTitle("applicationWithEmptyUrl"); - assertThrows(MalformedURLException.class, () -> applicationCenterService.createApplication(application)); - // - application.setUrl("./url"); - application.setHelpPageURL("javascript:alert('XSS')"); - application.setTitle("applicationWithMalFormedHelpPageUrl"); - assertThrows(MalformedURLException.class, () -> applicationCenterService.createApplication(application)); - // - application.setUrl("/portal/url"); - application.setHelpPageURL(""); - application.setTitle("applicationWithValidUrlAndEmptyHelpPageUrl"); - storedApplication = applicationCenterService.createApplication(application); - assertNotNull(storedApplication); - // - application.setUrl("https://applictaion/url"); - application.setHelpPageURL("https://help/page/url"); - application.setTitle("applicationWithValidUrlAndHelpPageUrl"); - storedApplication = applicationCenterService.createApplication(application); - assertNotNull(storedApplication); - } - - @Test - public void testUpdateApplication() throws Exception { - try { - applicationCenterService.updateApplication(null, null); - fail("Shouldn't allow to add null arguments"); - } catch (IllegalArgumentException e) { - // Expected - } - - try { - applicationCenterService.updateApplication(null, "testuser"); - fail("Shouldn't allow to add null application"); - } catch (IllegalArgumentException e) { - // Expected - } - - Application application = new Application(null, - "title", - "./url", - "", - 0L, - 0L, - null, - null, - "description", - false, - true, - false, - false, - false, - ApplicationCenterService.DEFAULT_ADMINISTRATORS_GROUP); - - try { - applicationCenterService.updateApplication(application, null); - fail("Shouldn't allow to add null user"); - } catch (IllegalArgumentException e) { - // Expected - } - - ConversationState.setCurrent(adminState); - try { - applicationCenterService.updateApplication(application, ADMIN_USERNAME); - fail("Shouldn't allow to update non existing application"); - } catch (ApplicationNotFoundException e) { - // Expected - } - - try { - application.setId(50000L); - applicationCenterService.updateApplication(application, ADMIN_USERNAME); - fail("Shouldn't allow to update non existing application"); - } catch (ApplicationNotFoundException e) { - // Expected - } finally { - application.setId(null); - } - - Application storedApplication = applicationCenterService.createApplication(application); - - application.setId(storedApplication.getId()); - application.setTitle("title2"); - storedApplication = applicationCenterService.updateApplication(application, ADMIN_USERNAME); - - assertNotNull(storedApplication); - assertNotNull(storedApplication.getId()); - assertEquals(application.getTitle(), storedApplication.getTitle()); - assertEquals(application.getUrl(), storedApplication.getUrl()); - assertEquals(application.getImageFileId(), storedApplication.getImageFileId()); - assertEquals(application.getDescription(), storedApplication.getDescription()); - assertEquals(application.isActive(), storedApplication.isActive()); - assertEquals(application.isMandatory(), storedApplication.isMandatory()); - assertEquals(application.getPermissions(), storedApplication.getPermissions()); - - ConversationState.setCurrent(simpleState); - try { - storedApplication = applicationCenterService.updateApplication(application, SIMPLE_USERNAME); - fail("Simple user shouldn't be able to update non authorized application"); - } catch (IllegalAccessException e) { - // Expected - } - - ConversationState.setCurrent(adminState); - application.setPermissions(ApplicationCenterService.DEFAULT_USERS_PERMISSION); - storedApplication = applicationCenterService.updateApplication(application, ADMIN_USERNAME); - assertEquals(ApplicationCenterService.DEFAULT_USERS_PERMISSION, storedApplication.getPermissions().get(0)); - - application.setUrl("./url2"); - storedApplication = applicationCenterService.updateApplication(application, ADMIN_USERNAME); - assertEquals("./url2", storedApplication.getUrl()); - } - - @Test - public void testDeleteApplication() throws Exception { - try { - applicationCenterService.deleteApplication(null, null); - fail("Shouldn't allow to add null arguments"); - } catch (IllegalArgumentException e) { - // Expected - } - - try { - applicationCenterService.deleteApplication(null, "testuser"); - fail("Shouldn't allow to add null application"); - } catch (IllegalArgumentException e) { - // Expected - } - - try { - applicationCenterService.deleteApplication(50000L, null); - fail("Shouldn't allow to add null user"); - } catch (IllegalArgumentException e) { - // Expected - } - - ConversationState.setCurrent(adminState); - try { - applicationCenterService.deleteApplication(50000L, ADMIN_USERNAME); - fail("Shouldn't allow to update non existing application"); - } catch (ApplicationNotFoundException e) { - // Expected - } - - Application application = new Application(null, - "title", - "./url", - "", - 0L, - 0L, - null, - null, - "description", - false, - true, - false, - false, - false, - ApplicationCenterService.DEFAULT_ADMINISTRATORS_GROUP); - Application storedApplication = applicationCenterService.createApplication(application); - applicationCenterService.deleteApplication(storedApplication.getId(), ADMIN_USERNAME); - - application = new Application(null, - "title", - "./url", - "", - 0L, - 0L, - null, - null, - "description", - false, - true, - false, - false, - false, - ApplicationCenterService.DEFAULT_ADMINISTRATORS_GROUP); - storedApplication = applicationCenterService.createApplication(application); - ConversationState.setCurrent(simpleState); - try { - applicationCenterService.deleteApplication(storedApplication.getId(), SIMPLE_USERNAME); - fail("Simple user shouldn't be able to delete non authorized application"); - } catch (IllegalAccessException e1) { - // Expected - } - - ConversationState.setCurrent(adminState); - application.setId(storedApplication.getId()); - application.setPermissions(ApplicationCenterService.DEFAULT_USERS_PERMISSION); - storedApplication = applicationCenterService.updateApplication(application, ADMIN_USERNAME); - - applicationCenterService.deleteApplication(storedApplication.getId(), ADMIN_USERNAME); - } - - @Test - public void testMaxFavoriteApps() { - long originalMaxFavoriteApps = applicationCenterService.getMaxFavoriteApps(); - - applicationCenterService.setMaxFavoriteApps(originalMaxFavoriteApps + 1); - assertEquals(originalMaxFavoriteApps + 1, applicationCenterService.getMaxFavoriteApps()); - - applicationCenterService.setMaxFavoriteApps(0); - assertEquals(0, applicationCenterService.getMaxFavoriteApps()); - } - - @Test - public void testSetDefaultAppImage() throws Exception { - ApplicationImage applicationImage = applicationCenterService.setDefaultAppImage(null); - assertNull(applicationImage); - - applicationImage = new ApplicationImage(null, null, null); - applicationImage = applicationCenterService.setDefaultAppImage(applicationImage); - assertNull(applicationImage); - - applicationImage = new ApplicationImage(null, "name", "content"); - applicationImage = applicationCenterService.setDefaultAppImage(applicationImage); - assertNotNull(applicationImage); - assertNotNull(applicationImage.getId()); - - ApplicationImage storedApplicationImage = applicationCenterService.setDefaultAppImage(applicationImage); - assertNotNull(storedApplicationImage); - assertEquals(applicationImage.getId(), storedApplicationImage.getId()); - } - - @Test - public void testGetAppGeneralSettings() throws Exception { - applicationCenterService.setDefaultAppImage(null); - applicationCenterService.setMaxFavoriteApps(0); - - GeneralSettings generalSettings = applicationCenterService.getAppGeneralSettings(); - assertNotNull(generalSettings); - assertEquals(0, generalSettings.getMaxFavoriteApps()); - assertNull(generalSettings.getDefaultApplicationImage()); - - applicationCenterService.setDefaultAppImage(new ApplicationImage(null, null, null)); - generalSettings = applicationCenterService.getAppGeneralSettings(); - - assertEquals(0, generalSettings.getMaxFavoriteApps()); - assertNull(generalSettings.getDefaultApplicationImage()); - - applicationCenterService.setDefaultAppImage(new ApplicationImage(null, "name", "content")); - - generalSettings = applicationCenterService.getAppGeneralSettings(); - assertEquals(0, generalSettings.getMaxFavoriteApps()); - assertNotNull(generalSettings.getDefaultApplicationImage()); - assertEquals("name", generalSettings.getDefaultApplicationImage().getFileName()); - assertFalse(generalSettings.getDefaultApplicationImage().getFileBody().isEmpty()); - assertNotNull(generalSettings.getDefaultApplicationImage().getId()); - } - - @Test - public void testAddFavoriteApplication() throws Exception { - ConversationState.setCurrent(adminState); - try { - applicationCenterService.addFavoriteApplication(0, null); - fail("Shouldn't allow to add null arguments"); - } catch (IllegalArgumentException e) { - // Expected - } - - ConversationState.setCurrent(simpleState); - try { - applicationCenterService.addFavoriteApplication(0, SIMPLE_USERNAME); - fail("Shouldn't allow to add zero as applicationId"); - } catch (IllegalArgumentException e) { - // Expected - } - - try { - applicationCenterService.addFavoriteApplication(5000L, SIMPLE_USERNAME); - fail("Shouldn't allow to add an application as favorite while it doesn't exist"); - } catch (ApplicationNotFoundException e) { - // Expected - } - - Application application = new Application(null, - "title", - "./url", - "", - 0L, - 0L, - null, - null, - "description", - false, - true, - false, - false, - false, - ApplicationCenterService.DEFAULT_ADMINISTRATORS_GROUP); - Application storedApplication = applicationCenterService.createApplication(application); - ConversationState.setCurrent(simpleState); - try { - applicationCenterService.addFavoriteApplication(storedApplication.getId(), SIMPLE_USERNAME); - fail("Shouldn't allow to add an application as favorite while user doesn't have access to it"); - } catch (IllegalAccessException e) { - // Expected - } - - ConversationState.setCurrent(adminState); - applicationCenterService.addFavoriteApplication(storedApplication.getId(), ADMIN_USERNAME); - storedApplication.setPermissions(ApplicationCenterService.DEFAULT_USERS_PERMISSION); - storedApplication = applicationCenterService.updateApplication(storedApplication, ADMIN_USERNAME); - ConversationState.setCurrent(simpleState); - applicationCenterService.addFavoriteApplication(storedApplication.getId(), SIMPLE_USERNAME); - } - - @Test - public void testDeleteFavoriteApplication() throws Exception { - try { - applicationCenterService.deleteFavoriteApplication(null, null); - fail("Shouldn't allow to add null arguments"); - } catch (IllegalArgumentException e) { - // Expected - } - - ConversationState.setCurrent(simpleState); - try { - applicationCenterService.deleteFavoriteApplication(0L, SIMPLE_USERNAME); - fail("Shouldn't allow to add zero as applicationId"); - } catch (IllegalArgumentException e) { - // Expected - } - - applicationCenterService.deleteFavoriteApplication(5000L, SIMPLE_USERNAME); - - Application application = new Application(null, - "title", - "./url", - "", - 0L, - 0L, - null, - null, - "description", - false, - true, - false, - false, - false, - ApplicationCenterService.DEFAULT_ADMINISTRATORS_GROUP); - Application storedApplication = applicationCenterService.createApplication(application); - applicationCenterService.deleteFavoriteApplication(storedApplication.getId(), SIMPLE_USERNAME); - ConversationState.setCurrent(adminState); - applicationCenterService.deleteFavoriteApplication(storedApplication.getId(), ADMIN_USERNAME); - - applicationCenterService.addFavoriteApplication(storedApplication.getId(), ADMIN_USERNAME); - applicationCenterService.deleteFavoriteApplication(storedApplication.getId(), ADMIN_USERNAME); - - storedApplication.setPermissions(ApplicationCenterService.DEFAULT_USERS_PERMISSION); - storedApplication = applicationCenterService.updateApplication(storedApplication, ADMIN_USERNAME); - - ConversationState.setCurrent(simpleState); - applicationCenterService.addFavoriteApplication(storedApplication.getId(), SIMPLE_USERNAME); - applicationCenterService.deleteFavoriteApplication(storedApplication.getId(), SIMPLE_USERNAME); - } - - @Test - public void testGetApplicationsList() throws Exception { - ApplicationList applicationsList = applicationCenterService.getApplicationsList(0, 0, null); - assertNotNull(applicationsList); - assertNotNull(applicationsList.getApplications()); - assertEquals(0, applicationsList.getApplications().size()); - assertEquals(0, applicationsList.getSize()); - assertEquals(0, applicationsList.getOffset()); - assertEquals(0, applicationsList.getLimit()); - - Application application = new Application(null, - "title", - "./url", - "", - 0L, - 0L, - null, - null, - "description", - false, - true, - false, - false, - false, - ApplicationCenterService.DEFAULT_ADMINISTRATORS_GROUP); - applicationCenterService.createApplication(application); - - Application application2 = new Application(null, - "title2", - "./url2", - "", - 0L, - 0L, - null, - null, - "description", - false, - true, - false, - false, - false, - ApplicationCenterService.DEFAULT_ADMINISTRATORS_GROUP); - applicationCenterService.createApplication(application2); - - applicationsList = applicationCenterService.getApplicationsList(0, 0, null); - assertNotNull(applicationsList); - assertNotNull(applicationsList.getApplications()); - assertEquals(2, applicationsList.getApplications().size()); - assertEquals(2, applicationsList.getSize()); - - applicationsList = applicationCenterService.getApplicationsList(1, 0, null); - assertNotNull(applicationsList); - assertNotNull(applicationsList.getApplications()); - assertEquals(1, applicationsList.getApplications().size()); - assertEquals(1, applicationsList.getSize()); - - applicationsList = applicationCenterService.getApplicationsList(2, 0, null); - assertNotNull(applicationsList); - assertNotNull(applicationsList.getApplications()); - assertEquals(0, applicationsList.getApplications().size()); - assertEquals(0, applicationsList.getSize()); - - applicationsList = applicationCenterService.getApplicationsList(3, 0, null); - assertNotNull(applicationsList); - assertNotNull(applicationsList.getApplications()); - assertEquals(0, applicationsList.getApplications().size()); - assertEquals(0, applicationsList.getSize()); - - applicationsList = applicationCenterService.getApplicationsList(0, 10, null); - assertNotNull(applicationsList); - assertNotNull(applicationsList.getApplications()); - assertEquals(2, applicationsList.getApplications().size()); - assertEquals(2, applicationsList.getSize()); - } - - @Test - public void testGetMandatoryAndFavoriteApplicationsList() throws Exception { - Application application1 = new Application(null, - "title1", - "./url1", - "", - 0L, - 0L, - null, - null, - "description1", - false, - true, - true, - true, - false, - ApplicationCenterService.DEFAULT_ADMINISTRATORS_GROUP); - - Application application2 = new Application(null, - "title2", - "./url2", - "", - 0L, - 0L, - null, - null, - "description", - false, - false, - true, - true, - false, - ApplicationCenterService.DEFAULT_ADMINISTRATORS_GROUP); - - Application application3 = new Application(null, - "title3", - "./url3", - "", - 0L, - 0L, - null, - null, - "description3", - false, - true, - false, - false, - false, - ApplicationCenterService.DEFAULT_ADMINISTRATORS_GROUP); - - Application application4 = new Application(null, - "title4", - "./url4", - "", - 0L, - 0L, - null, - null, - "description4", - false, - true, - false, - false, - false, - ApplicationCenterService.DEFAULT_ADMINISTRATORS_GROUP); - - Application application5 = new Application(null, - "title5", - "./url5", - "", - 0L, - 0L, - null, - null, - "description5", - false, - true, - false, - false, - false, - ApplicationCenterService.DEFAULT_USERS_PERMISSION); - - applicationCenterService.createApplication(application1); - applicationCenterService.createApplication(application2); - Application storedApp3 = applicationCenterService.createApplication(application3); - Application storedApp4 = applicationCenterService.createApplication(application4); - Application storedApp5 = applicationCenterService.createApplication(application5); - - applicationCenterService.addFavoriteApplication(storedApp3.getId(), "admin"); - applicationCenterService.addFavoriteApplication(storedApp4.getId(), "admin"); - applicationCenterService.addFavoriteApplication(storedApp5.getId(), "simple"); - - ApplicationList MandatoryAndFavoriteApplications = applicationCenterService.getMandatoryAndFavoriteApplicationsList("admin"); - assertEquals(3, MandatoryAndFavoriteApplications.getApplications().size()); - assertEquals(3, MandatoryAndFavoriteApplications.getSize()); - } - - @Test - public void testUpdateFavoriteApplicationOrder() throws Exception { - Application application1 = new Application(null, - "title3", - "./url3", - "", - 0L, - 0L, - null, - null, - "description3", - false, - true, - false, - false, - false, - ApplicationCenterService.DEFAULT_ADMINISTRATORS_GROUP); - - Application application2 = new Application(null, - "title5", - "./url5", - "", - 0L, - 0L, - null, - null, - "description5", - false, - true, - false, - false, - false, - ApplicationCenterService.DEFAULT_USERS_PERMISSION); - - try { - applicationCenterService.getMandatoryAndFavoriteApplicationsList(""); - fail("Shouldn't retrieve applications with null username"); - } catch (IllegalArgumentException e) { - // Expected - } - - Application storedApp1 = applicationCenterService.createApplication(application1); - Application storedApp2 = applicationCenterService.createApplication(application2); - - applicationCenterService.addFavoriteApplication(storedApp1.getId(), "admin"); - applicationCenterService.addFavoriteApplication(storedApp2.getId(), "simple"); - - applicationCenterService.updateFavoriteApplicationOrder(new ApplicationOrder(storedApp1.getId(), new Long(1)), "admin"); - applicationCenterService.updateFavoriteApplicationOrder(new ApplicationOrder(storedApp2.getId(), new Long(2)), "simple"); - - try { - applicationCenterService.updateFavoriteApplicationOrder(new ApplicationOrder(storedApp1.getId(), new Long(1)), ""); - fail("Shouldn't retrieve applications with null username"); - } catch (IllegalArgumentException e) { - // Expected - } - - try { - applicationCenterService.updateFavoriteApplicationOrder(new ApplicationOrder(0L, new Long(1)), ""); - fail("Application id can not be negative or equal to zero."); - } catch (IllegalArgumentException e) { - // Expected - } - - assertEquals(new Long(1), - applicationCenterService.getMandatoryAndFavoriteApplicationsList("admin").getApplications().get(0).getOrder()); - assertEquals(new Long(1), - applicationCenterService.getMandatoryAndFavoriteApplicationsList("admin").getApplications().get(0).getOrder()); - - } - - @Test - public void testGetAuthorizedApplicationsList() throws Exception { - try { - applicationCenterService.getAuthorizedApplicationsList(0, 0, null, null); - fail("Shouldn't retrieve applications with null username"); - } catch (IllegalArgumentException e) { - // Expected - } - - ConversationState.setCurrent(simpleState); - ApplicationList applicationsList = applicationCenterService.getAuthorizedApplicationsList(0, 0, null, SIMPLE_USERNAME); - assertNotNull(applicationsList); - assertNotNull(applicationsList.getApplications()); - assertEquals(0, applicationsList.getApplications().size()); - assertEquals(0, applicationsList.getSize()); - - Application application = new Application(null, - "title", - "./url", - "", - 0L, - 0L, - null, - null, - "description", - false, - true, - false, - false, - false, - ApplicationCenterService.DEFAULT_ADMINISTRATORS_GROUP); - ConversationState.setCurrent(adminState); - applicationCenterService.createApplication(application); - - Application application2 = new Application(null, - "title2", - "./url2", - "", - 0L, - 0L, - null, - null, - "description", - false, - true, - false, - false, - false, - ApplicationCenterService.DEFAULT_USERS_PERMISSION); - applicationCenterService.createApplication(application2); - - applicationsList = applicationCenterService.getAuthorizedApplicationsList(0, 0, null, ADMIN_USERNAME); - assertNotNull(applicationsList); - assertNotNull(applicationsList.getApplications()); - assertEquals(2, applicationsList.getApplications().size()); - assertEquals(2, applicationsList.getSize()); - - ConversationState.setCurrent(simpleState); - applicationsList = applicationCenterService.getAuthorizedApplicationsList(0, 0, null, SIMPLE_USERNAME); - assertNotNull(applicationsList); - assertNotNull(applicationsList.getApplications()); - assertEquals(1, applicationsList.getApplications().size()); - assertEquals(1, applicationsList.getSize()); - - ConversationState.setCurrent(adminState); - applicationsList = applicationCenterService.getAuthorizedApplicationsList(1, 0, null, ADMIN_USERNAME); - assertNotNull(applicationsList); - assertNotNull(applicationsList.getApplications()); - assertEquals(1, applicationsList.getApplications().size()); - assertEquals(2, applicationsList.getSize()); - - ConversationState.setCurrent(simpleState); - applicationsList = applicationCenterService.getAuthorizedApplicationsList(1, 0, null, SIMPLE_USERNAME); - assertNotNull(applicationsList); - assertNotNull(applicationsList.getApplications()); - assertEquals(0, applicationsList.getApplications().size()); - assertEquals(1, applicationsList.getSize()); - - ConversationState.setCurrent(adminState); - applicationsList = applicationCenterService.getAuthorizedApplicationsList(2, 0, null, ADMIN_USERNAME); - assertNotNull(applicationsList); - assertNotNull(applicationsList.getApplications()); - assertEquals(0, applicationsList.getApplications().size()); - assertEquals(2, applicationsList.getSize()); - - ConversationState.setCurrent(simpleState); - applicationsList = applicationCenterService.getAuthorizedApplicationsList(2, 0, null, SIMPLE_USERNAME); - assertNotNull(applicationsList); - assertNotNull(applicationsList.getApplications()); - assertEquals(0, applicationsList.getApplications().size()); - assertEquals(1, applicationsList.getSize()); - - ConversationState.setCurrent(adminState); - applicationsList = applicationCenterService.getAuthorizedApplicationsList(3, 0, null, ADMIN_USERNAME); - assertNotNull(applicationsList); - assertNotNull(applicationsList.getApplications()); - assertEquals(0, applicationsList.getApplications().size()); - assertEquals(2, applicationsList.getSize()); - - ConversationState.setCurrent(simpleState); - applicationsList = applicationCenterService.getAuthorizedApplicationsList(3, 0, null, SIMPLE_USERNAME); - assertNotNull(applicationsList); - assertNotNull(applicationsList.getApplications()); - assertEquals(0, applicationsList.getApplications().size()); - assertEquals(1, applicationsList.getSize()); - - ConversationState.setCurrent(adminState); - applicationsList = applicationCenterService.getAuthorizedApplicationsList(0, 10, null, ADMIN_USERNAME); - assertNotNull(applicationsList); - assertNotNull(applicationsList.getApplications()); - assertEquals(2, applicationsList.getApplications().size()); - assertEquals(2, applicationsList.getSize()); - - ConversationState.setCurrent(simpleState); - applicationsList = applicationCenterService.getAuthorizedApplicationsList(0, 10, null, SIMPLE_USERNAME); - assertNotNull(applicationsList); - assertNotNull(applicationsList.getApplications()); - assertEquals(1, applicationsList.getApplications().size()); - assertEquals(1, applicationsList.getSize()); - } - - @Test - public void testGetLastUpdated() throws Exception { - long currentTimeMillis = System.currentTimeMillis(); - try { - applicationCenterService.getApplicationImageLastUpdated(50000L, null); - fail("Shouldn't allow to use null user"); - } catch (IllegalArgumentException e) { - // Expected - } - - ConversationState.setCurrent(simpleState); - try { - applicationCenterService.getApplicationImageLastUpdated(50000L, SIMPLE_USERNAME); - fail("Shouldn't allow to get not found application"); - } catch (ApplicationNotFoundException e) { - // Expected - } - - Application application = new Application(null, - "title", - "./url", - "", - 5L, - 0L, - null, - null, - "description", - false, - true, - false, - false, - false, - ApplicationCenterService.DEFAULT_ADMINISTRATORS_GROUP); - application.setImageFileName("name"); - application.setImageFileBody("content"); - Application storedApplication = applicationCenterService.createApplication(application); - - ConversationState.setCurrent(simpleState); - try { - applicationCenterService.getApplicationImageLastUpdated(storedApplication.getId(), SIMPLE_USERNAME); - fail("Shouldn't allow to get illustration of non authorized application"); - } catch (IllegalAccessException e) { - // Expected - } - - ConversationState.setCurrent(adminState); - Long lastUpdated = applicationCenterService.getApplicationImageLastUpdated(storedApplication.getId(), ADMIN_USERNAME); - assertNotNull(lastUpdated); - assertTrue(lastUpdated >= currentTimeMillis); - } - - @Test - public void testGetImageStream() throws Exception { - try { - applicationCenterService.getApplicationImageInputStream(50000L, null); - fail("Shouldn't allow to use null user"); - } catch (IllegalArgumentException e) { - // Expected - } - - ConversationState.setCurrent(simpleState); - try { - applicationCenterService.getApplicationImageInputStream(50000L, SIMPLE_USERNAME); - fail("Shouldn't allow to get not found application"); - } catch (ApplicationNotFoundException e) { - // Expected - } - - Application application = new Application(null, - "title", - "./url", - "", - 5L, - 0L, - null, - null, - "description", - false, - true, - false, - false, - false, - ApplicationCenterService.DEFAULT_ADMINISTRATORS_GROUP); - application.setImageFileName("name"); - application.setImageFileBody("content"); - Application storedApplication = applicationCenterService.createApplication(application); - - ConversationState.setCurrent(simpleState); - try { - applicationCenterService.getApplicationImageInputStream(storedApplication.getId(), SIMPLE_USERNAME); - fail("Shouldn't allow to get illustration of non authorized application"); - } catch (IllegalAccessException e) { - // Expected - } - - ConversationState.setCurrent(adminState); - InputStream inputStream = applicationCenterService.getApplicationImageInputStream(storedApplication.getId(), ADMIN_USERNAME); - assertNotNull(inputStream); - assertTrue(inputStream.available() > 0); - } - - @Test - public void testAddApplicationPlugin() throws FileStorageException { - try { - applicationCenterService.addApplicationPlugin(null); - fail("Shouldn't be able to add null plugin"); - } catch (IllegalArgumentException e) { - // Expected - } - - try { - new ApplicationPlugin(null); - fail("Shouldn't be able to add null params in plugin"); - } catch (IllegalArgumentException e) { - // Expected - } - - InitParams params = new InitParams(); - try { - new ApplicationPlugin(params); - fail("Shouldn't be able to add null application in parameter of plugin"); - } catch (IllegalArgumentException e) { - // Expected - } - - Application application = new Application(null, - "title", - "./url", - "", - 5L, - 0L, - null, - null, - "description", - false, - true, - false, - false, - true, - ApplicationCenterService.DEFAULT_ADMINISTRATORS_GROUP); - - ObjectParameter applicationParam = new ObjectParameter(); - applicationParam.setName("application"); - applicationParam.setObject(application); - params.addParameter(applicationParam); - - ApplicationPlugin applicationPlugin = new ApplicationPlugin(params); - assertNotNull(applicationPlugin.getApplication()); - assertNull(applicationPlugin.getImagePath()); - - try { - applicationCenterService.addApplicationPlugin(applicationPlugin); - fail("Shouldn't be able to add plugin with null name"); - } catch (IllegalStateException e) { - // Expected - } - - String pluginName = "testapp"; - applicationPlugin.setName(pluginName); - try { - applicationCenterService.addApplicationPlugin(applicationPlugin); - applicationCenterService.start(); - - ApplicationList applicationsList = applicationCenterService.getApplicationsList(0, 0, null); - assertNotNull(applicationsList); - assertNotNull(applicationsList.getApplications()); - assertEquals(1, applicationsList.getApplications().size()); - - Application storedApplication = applicationsList.getApplications().get(0); - - assertNotNull(storedApplication); - assertNotNull(storedApplication.getId()); - assertEquals(application.getTitle(), storedApplication.getTitle()); - assertEquals(application.getUrl(), storedApplication.getUrl()); - assertEquals(application.getDescription(), storedApplication.getDescription()); - assertEquals(application.isActive(), storedApplication.isActive()); - assertEquals(application.isMandatory(), storedApplication.isMandatory()); - assertTrue(storedApplication.isSystem()); - assertEquals(application.getPermissions(), storedApplication.getPermissions()); - assertNull(application.getImageFileId()); - } catch (FileStorageException e) { - fail("Should not throw exception for a missing file"); - } finally { - applicationCenterService.removeApplicationPlugin(pluginName); - } - - // Second start with file attached - ValueParam imagePathValueParam = new ValueParam(); - imagePathValueParam.setName("imagePath"); - imagePathValueParam.setValue("jar:/test.png"); - params.addParameter(imagePathValueParam); - - applicationPlugin = new ApplicationPlugin(params); - applicationPlugin.setName(pluginName); - assertNotNull(applicationPlugin.getApplication()); - assertNotNull(applicationPlugin.getImagePath()); - try { - applicationCenterService.addApplicationPlugin(applicationPlugin); - try { - Application newApplication =appCenterStorage.getApplicationByTitle("title"); - newApplication.setChangedManually(true); - appCenterStorage.updateApplication(newApplication); - } catch (Exception e){ - // Expected - } - applicationCenterService.start(); - - ApplicationList applicationsList = applicationCenterService.getApplicationsList(0, 0, null); - assertNotNull(applicationsList); - assertNotNull(applicationsList.getApplications()); - assertEquals(1, applicationsList.getApplications().size()); - - Application storedApplication = applicationsList.getApplications().get(0); - - assertNotNull(storedApplication); - assertNotNull(storedApplication.getId()); - assertEquals(application.getTitle(), storedApplication.getTitle()); - assertEquals(application.getUrl(), storedApplication.getUrl()); - assertEquals(application.getDescription(), storedApplication.getDescription()); - assertEquals(application.isActive(), storedApplication.isActive()); - assertEquals(application.isMandatory(), storedApplication.isMandatory()); - assertTrue(storedApplication.isSystem()); - assertEquals(application.getPermissions(), storedApplication.getPermissions()); - assertNull(application.getImageFileId()); - } catch (FileStorageException e) { - e.printStackTrace(); - } finally { - applicationCenterService.removeApplicationPlugin(pluginName); - } - - // Third start with override turned on - ValueParam overrideValueParam = new ValueParam(); - overrideValueParam.setName("override"); - overrideValueParam.setValue("true"); - params.addParameter(overrideValueParam); - - applicationPlugin = new ApplicationPlugin(params); - applicationPlugin.setName(pluginName); - assertNotNull(applicationPlugin.getApplication()); - assertNotNull(applicationPlugin.getImagePath()); - try { - applicationCenterService.addApplicationPlugin(applicationPlugin); - applicationCenterService.start(); - - ApplicationList applicationsList = applicationCenterService.getApplicationsList(0, 0, null); - assertNotNull(applicationsList); - assertNotNull(applicationsList.getApplications()); - assertEquals(1, applicationsList.getApplications().size()); - - Application storedApplication = applicationsList.getApplications().get(0); - - assertNotNull(storedApplication); - assertNotNull(storedApplication.getId()); - assertEquals(application.getTitle(), storedApplication.getTitle()); - assertEquals(application.getUrl(), storedApplication.getUrl()); - assertEquals(application.getDescription(), storedApplication.getDescription()); - assertEquals(application.isActive(), storedApplication.isActive()); - assertEquals(application.isMandatory(), storedApplication.isMandatory()); - assertTrue(storedApplication.isSystem()); - assertEquals(application.getPermissions(), storedApplication.getPermissions()); - assertNotNull(application.getImageFileId()); - } finally { - applicationCenterService.removeApplicationPlugin(pluginName); - } - - // Test after deleting plugin from list, if the application was removed - applicationCenterService.start(); - - ApplicationList applicationsList = applicationCenterService.getApplicationsList(0, 0, null); - assertNotNull(applicationsList); - assertNotNull(applicationsList.getApplications()); - assertEquals(0, applicationsList.getApplications().size()); - } - - @Test - public void testEnableDisableApplication() { - InitParams applicationConf = new InitParams(); - ObjectParameter applicationParam = new ObjectParameter(); - applicationParam.setName("application"); - applicationParam.setObject(new Application(null, - "title", - "./url", - "", - 5L, - 0L, - null, - null, - "description", - false, - true, - false, - false, - true, - ApplicationCenterService.DEFAULT_ADMINISTRATORS_GROUP)); - applicationConf.addParameter(applicationParam); - ValueParam valueParam = new ValueParam(); - valueParam.setName("override"); - valueParam.setValue("false"); - applicationConf.addParameter(valueParam); - valueParam.setName("enabled"); - valueParam.setValue("false"); - applicationConf.addParameter(valueParam); - valueParam.setName("imagePath"); - valueParam.setValue("/path/to/image.png"); - applicationConf.addParameter(valueParam); - valueParam.setName("override-mode"); - valueParam.setValue("merge"); - applicationConf.addParameter(valueParam); - ApplicationPlugin applicationPlugin = new ApplicationPlugin(applicationConf); - applicationPlugin.setName("disabledApplication"); - applicationCenterService.addApplicationPlugin(applicationPlugin); - applicationCenterService.start(); - ApplicationList applicationList = new ApplicationList(); - try { - applicationList = applicationCenterService.getApplicationsList(0, 10, null); - } catch (FileStorageException fileNotFoundException) { - // Do nothing - } - assertEquals(0, applicationList.getSize()); - applicationCenterService.stop(); - - // Enable the application - valueParam = applicationConf.getValueParam("enabled"); - valueParam.setValue("true"); - applicationConf.addParameter(valueParam); - applicationPlugin = new ApplicationPlugin(applicationConf); - applicationPlugin.setName("enabledApplication"); - applicationCenterService.addApplicationPlugin(applicationPlugin); - applicationCenterService.start(); - try { - applicationList = applicationCenterService.getApplicationsList(0, 10, null); - } catch (FileStorageException fileNotFoundException) { - // Do nothing - } - assertEquals(1, applicationList.getSize()); - applicationCenterService.stop(); - } - - @Test - public void testUpdateApplicationBySystem() { - try { - applicationCenterService.addApplicationPlugin(null); - fail("Shouldn't be able to add null plugin"); - } catch (IllegalArgumentException e) { - // Expected - } - - try { - new ApplicationPlugin(null); - fail("Shouldn't be able to add null params in plugin"); - } catch (IllegalArgumentException e) { - // Expected - } - - InitParams params = new InitParams(); - try { - new ApplicationPlugin(params); - fail("Shouldn't be able to add null application in parameter of plugin"); - } catch (IllegalArgumentException e) { - // Expected - } - Application application = new Application(null, - "title", - "./url", - "", - 5L, - 0L, - null, - null, - "description", - false, - true, - false, - false, - true, - ApplicationCenterService.DEFAULT_ADMINISTRATORS_GROUP); - - ObjectParameter applicationParam = new ObjectParameter(); - applicationParam.setName("application"); - applicationParam.setObject(application); - params.addParameter(applicationParam); - - ApplicationPlugin applicationPlugin = new ApplicationPlugin(params); - - try { - applicationCenterService.addApplicationPlugin(applicationPlugin); - fail("Shouldn't be able to add plugin with null name"); - } catch (IllegalStateException e) { - // Expected - } - - String pluginName = "testapp"; - applicationPlugin.setName(pluginName); - try { - applicationCenterService.addApplicationPlugin(applicationPlugin); - applicationCenterService.start(); - - ApplicationList applicationsList = applicationCenterService.getApplicationsList(0, 0, null); - assertNotNull(applicationsList); - assertNotNull(applicationsList.getApplications()); - assertEquals(1, applicationsList.getApplications().size()); - } catch (FileStorageException e) { - e.printStackTrace(); - } finally { - applicationCenterService.removeApplicationPlugin(pluginName); - } - // Second start with file attached and override-mode is write - ValueParam imagePathValueParam = new ValueParam(); - imagePathValueParam.setName("imagePath"); - imagePathValueParam.setValue("jar:/test.png"); - params.addParameter(imagePathValueParam); - ValueParam overrideValueParam = new ValueParam(); - overrideValueParam.setName("override"); - overrideValueParam.setValue("false"); - params.addParameter(overrideValueParam); - ValueParam overrideModeValueParam = new ValueParam(); - overrideModeValueParam.setName("override-mode"); - overrideModeValueParam.setValue("write"); - params.addParameter(overrideModeValueParam); - - applicationPlugin = new ApplicationPlugin(params); - applicationPlugin.setName(pluginName); - try { - applicationCenterService.addApplicationPlugin(applicationPlugin); - try { - Application newApplication =appCenterStorage.getApplicationByTitle("title"); - newApplication.setChangedManually(true); - appCenterStorage.updateApplication(newApplication); - } catch (Exception e){ - // Expected - } - - applicationCenterService.start(); - - ApplicationList applicationsList = applicationCenterService.getApplicationsList(0, 0, null); - //this updated done by system because override-mode is write and isChangedManually true - assertEquals(false,applicationsList.getApplications().get(0).isChangedManually()); - } catch (FileStorageException e) { - e.printStackTrace(); - } finally { - applicationCenterService.removeApplicationPlugin(pluginName); - } - // Third start with file attached and override-mode is merge - ValueParam imagePathValueParam1 = new ValueParam(); - imagePathValueParam1.setName("imagePath"); - imagePathValueParam1.setValue("jar:/test.png"); - params.addParameter(imagePathValueParam1); - ValueParam overrideValueParam1 = new ValueParam(); - overrideValueParam1.setName("override"); - overrideValueParam1.setValue("false"); - params.addParameter(overrideValueParam1); - ValueParam overrideModeValueParam1 = new ValueParam(); - overrideModeValueParam1.setName("override-mode"); - overrideModeValueParam1.setValue("merge"); - params.addParameter(overrideModeValueParam1); - - applicationPlugin = new ApplicationPlugin(params); - applicationPlugin.setName(pluginName); - try { - applicationCenterService.addApplicationPlugin(applicationPlugin); - try { - Application newApplication =appCenterStorage.getApplicationByTitle("title"); - newApplication.setChangedManually(true); - appCenterStorage.updateApplication(newApplication); - } catch (Exception e){ - // Expected - } - applicationCenterService.start(); - - ApplicationList applicationsList = applicationCenterService.getApplicationsList(0, 0, null); - //Ignore updating application, override mode is merge and isChangedManually is true - assertEquals(true,applicationsList.getApplications().get(0).isChangedManually()); - } catch (FileStorageException e) { - fail("Avatar file not found for the application"); - } finally { - applicationCenterService.removeApplicationPlugin(pluginName); - } - } -} diff --git a/app-center-services/src/test/java/org/exoplatform/appcenter/storage/ApplicationCenterStorageTest.java b/app-center-services/src/test/java/org/exoplatform/appcenter/storage/ApplicationCenterStorageTest.java deleted file mode 100644 index 5bca7694a..000000000 --- a/app-center-services/src/test/java/org/exoplatform/appcenter/storage/ApplicationCenterStorageTest.java +++ /dev/null @@ -1,692 +0,0 @@ -/* - * This file is part of the Meeds project (https://meeds.io/). - * Copyright (C) 2020 Meeds Association - * contact@meeds.io - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.exoplatform.appcenter.storage; - -import static org.junit.Assert.*; - -import java.util.List; - -import org.junit.After; -import org.junit.Before; -import org.junit.BeforeClass; -import org.junit.Test; - -import org.exoplatform.appcenter.dao.ApplicationDAO; -import org.exoplatform.appcenter.dao.FavoriteApplicationDAO; -import org.exoplatform.appcenter.dto.Application; -import org.exoplatform.appcenter.dto.ApplicationImage; -import org.exoplatform.appcenter.dto.UserApplication; -import org.exoplatform.appcenter.service.ApplicationNotFoundException; -import org.exoplatform.commons.file.services.NameSpaceService; -import org.exoplatform.commons.file.services.impl.NameSpaceServiceImpl; -import org.exoplatform.container.ExoContainerContext; -import org.exoplatform.container.PortalContainer; -import org.exoplatform.container.RootContainer; -import org.exoplatform.container.component.RequestLifeCycle; -import org.exoplatform.services.naming.InitialContextInitializer; - -public class ApplicationCenterStorageTest { - - private PortalContainer container; - - @BeforeClass - @SuppressWarnings("deprecation") - public static void startDB() { - RootContainer rootContainer = RootContainer.getInstance(); - InitialContextInitializer initializer = rootContainer.getComponentInstanceOfType(InitialContextInitializer.class); - initializer.recall(); // NOSONAR - } - - @Before - public void setup() { - container = PortalContainer.getInstance(); - assertNotNull(container); - ExoContainerContext.setCurrentContainer(container); - RequestLifeCycle.begin(container); - - // Workaround, the service wasn't started - NameSpaceService fileNameSpaceService = ExoContainerContext.getService(NameSpaceService.class); - assertNotNull(fileNameSpaceService); - ((NameSpaceServiceImpl) fileNameSpaceService).start(); - } - - @After - public void teardown() { - FavoriteApplicationDAO favoriteApplicationDAO = ExoContainerContext.getService(FavoriteApplicationDAO.class); - favoriteApplicationDAO.deleteAll(); - - ApplicationDAO applicationDAO = ExoContainerContext.getService(ApplicationDAO.class); - applicationDAO.deleteAll(); - - RequestLifeCycle.end(); - container.stop(); - container = null; - ExoContainerContext.setCurrentContainer(null); - } - - @Test - public void testCreateApplication() throws Exception { - ApplicationCenterStorage applicationCenterStorage = ExoContainerContext.getService(ApplicationCenterStorage.class); - assertNotNull(applicationCenterStorage); - - try { - applicationCenterStorage.createApplication(null); - fail("Shouldn't allow to add null application"); - } catch (IllegalArgumentException e) { - // Expected - } - - Application application = new Application(null, - "title", - "url", - "", - 0L, - 0L, - null, - null, - "description", - false, - true, - false, - false, - false, - "permissions1", - "permissions2"); - - Application storedApplication = applicationCenterStorage.createApplication(application); - assertNotNull(storedApplication); - assertNotNull(storedApplication.getId()); - assertEquals(application.getTitle(), storedApplication.getTitle()); - assertEquals(application.getUrl(), storedApplication.getUrl()); - assertEquals(application.getImageFileId(), storedApplication.getImageFileId()); - assertEquals(application.getDescription(), storedApplication.getDescription()); - assertEquals(application.isActive(), storedApplication.isActive()); - assertEquals(application.isMandatory(), storedApplication.isMandatory()); - assertEquals(application.getPermissions(), storedApplication.getPermissions()); - } - - @Test - public void testUpdateApplication() throws Exception { - ApplicationCenterStorage applicationCenterStorage = ExoContainerContext.getService(ApplicationCenterStorage.class); - assertNotNull(applicationCenterStorage); - - Application application = new Application(null, - "title", - "url", - "url", - 0L, - 0L, - null, - null, - "description", - false, - true, - false, - false, - false, - "permissions1", - "permissions2"); - - Application storedApplication = applicationCenterStorage.createApplication(application); - application.setId(storedApplication.getId()); - application.setActive(!storedApplication.isActive()); - application.setMandatory(!storedApplication.isMandatory()); - application.setDescription("description2"); - application.setUrl("url2"); - application.setUrl("title2"); - application.setImageFileId(6L); - application.setPermissions("permissions3", "permissions4"); - - storedApplication = applicationCenterStorage.updateApplication(application); - - assertNotNull(storedApplication); - assertNotNull(storedApplication.getId()); - assertEquals(application.getTitle(), storedApplication.getTitle()); - assertEquals(application.getUrl(), storedApplication.getUrl()); - assertEquals(application.getImageFileId(), storedApplication.getImageFileId()); - assertEquals(application.getDescription(), storedApplication.getDescription()); - assertEquals(application.isActive(), storedApplication.isActive()); - assertEquals(application.isMandatory(), storedApplication.isMandatory()); - assertEquals(application.getPermissions(), storedApplication.getPermissions()); - } - - @Test - public void testDeleteApplication() throws Exception { - ApplicationCenterStorage applicationCenterStorage = ExoContainerContext.getService(ApplicationCenterStorage.class); - assertNotNull(applicationCenterStorage); - - try { - applicationCenterStorage.deleteApplication(0); - fail("Shouldn't allow to delete not existing application"); - } catch (IllegalArgumentException e) { - // Expected - } - - try { - applicationCenterStorage.deleteApplication(5000L); - fail("Shouldn't allow to delete application with not positive id"); - } catch (ApplicationNotFoundException e) { - // Expected - } - - Application application = new Application(null, - "title", - "url", - "", - 0L, - 0L, - null, - null, - "description", - false, - true, - false, - false, - false, - "permissions1", - "permissions2"); - - Application storedApplication = applicationCenterStorage.createApplication(application); - applicationCenterStorage.deleteApplication(storedApplication.getId()); - - assertNull(applicationCenterStorage.getApplicationById(storedApplication.getId())); - } - - @Test - public void testGetApplication() throws Exception { - ApplicationCenterStorage applicationCenterStorage = ExoContainerContext.getService(ApplicationCenterStorage.class); - assertNotNull(applicationCenterStorage); - - try { - applicationCenterStorage.getApplicationById(0); - fail("Shouldn't allow to get application with not positive id"); - } catch (IllegalArgumentException e) { - // Expected - } - - assertNull(applicationCenterStorage.getApplicationById(50000)); - - Application application = new Application(null, - "title", - "url", - "", - 0L, - 0L, - null, - null, - "description", - false, - true, - false, - false, - false, - "permissions1", - "permissions2"); - - Application storedApplication = applicationCenterStorage.createApplication(application); - storedApplication = applicationCenterStorage.getApplicationById(storedApplication.getId()); - assertNotNull(storedApplication); - assertNotNull(storedApplication.getId()); - assertEquals(application.getTitle(), storedApplication.getTitle()); - assertEquals(application.getUrl(), storedApplication.getUrl()); - assertEquals(application.getImageFileId(), storedApplication.getImageFileId()); - assertEquals(application.getDescription(), storedApplication.getDescription()); - assertEquals(application.isActive(), storedApplication.isActive()); - assertEquals(application.isMandatory(), storedApplication.isMandatory()); - assertEquals(application.getPermissions(), storedApplication.getPermissions()); - } - - @Test - public void testGetApplicationByTitleOrURL() throws Exception { - ApplicationCenterStorage applicationCenterStorage = ExoContainerContext.getService(ApplicationCenterStorage.class); - assertNotNull(applicationCenterStorage); - - try { - applicationCenterStorage.getApplicationByTitle(null); - fail("Shouldn't allow to get application by null values"); - } catch (IllegalArgumentException e) { - // Expected - } - - assertNull(applicationCenterStorage.getApplicationByTitle("title")); - - Application application = new Application(null, - "title", - "url", - "", - 0L, - 0L, - null, - null, - "description", - false, - true, - false, - false, - false, - "permissions1", - "permissions2"); - - applicationCenterStorage.createApplication(application); - Application storedApplication = applicationCenterStorage.getApplicationByTitle(application.getTitle()); - assertNotNull(storedApplication); - assertNotNull(storedApplication.getId()); - assertEquals(application.getTitle(), storedApplication.getTitle()); - assertEquals(application.getUrl(), storedApplication.getUrl()); - assertEquals(application.getImageFileId(), storedApplication.getImageFileId()); - assertEquals(application.getDescription(), storedApplication.getDescription()); - assertEquals(application.isActive(), storedApplication.isActive()); - assertEquals(application.isMandatory(), storedApplication.isMandatory()); - assertEquals(application.getPermissions(), storedApplication.getPermissions()); - } - - @Test - public void testAddApplicationToUserFavorite() throws Exception { - ApplicationCenterStorage applicationCenterStorage = ExoContainerContext.getService(ApplicationCenterStorage.class); - assertNotNull(applicationCenterStorage); - - try { - applicationCenterStorage.addApplicationToUserFavorite(0, "testuser"); - fail("Shouldn't allow to add application as favorite with not positive id"); - } catch (IllegalArgumentException e) { - // Expected - } - - try { - applicationCenterStorage.addApplicationToUserFavorite(50000, "testuser"); - fail("Shouldn't allow to add not existing application as favorite"); - } catch (ApplicationNotFoundException e) { - // Expected - } - - Application application = new Application(null, - "title", - "url", - "", - 0L, - 0L, - null, - null, - "description", - false, - true, - false, - false, - false, - "permissions1", - "permissions2"); - - Application storedApplication = applicationCenterStorage.createApplication(application); - applicationCenterStorage.addApplicationToUserFavorite(storedApplication.getId(), "testuser"); - } - - @Test - public void testUpdateApplicationFavoriteOrder() throws Exception { - ApplicationCenterStorage applicationCenterStorage = ExoContainerContext.getService(ApplicationCenterStorage.class); - assertNotNull(applicationCenterStorage); - - Application application = new Application(null, - "title", - "url", - "", - 0L, - 0L, - null, - null, - "description", - false, - true, - false, - false, - false, - "permissions1", - "permissions2"); - - Application storedApplication = applicationCenterStorage.createApplication(application); - applicationCenterStorage.addApplicationToUserFavorite(storedApplication.getId(), "testuser"); - Long appID = applicationCenterStorage.getFavoriteApplicationsByUser("testuser").get(0).getId(); - applicationCenterStorage.updateFavoriteApplicationOrder(appID, "testuser", new Long(1)); - - assertEquals(new Long(1), applicationCenterStorage.getFavoriteApplicationsByUser("testuser").get(0).getOrder()); - } - - @Test - public void testDeleteApplicationFavorite() throws Exception { - ApplicationCenterStorage applicationCenterStorage = ExoContainerContext.getService(ApplicationCenterStorage.class); - assertNotNull(applicationCenterStorage); - - try { - applicationCenterStorage.deleteApplicationFavorite(0L, "testuser"); - fail("Shouldn't allow to delete application as favorite with not positive id"); - } catch (IllegalArgumentException e) { - // Expected - } - - applicationCenterStorage.deleteApplicationFavorite(50000L, "testuser"); - - Application application = new Application(null, - "title", - "url", - "", - 0L, - 0L, - null, - null, - "description", - false, - true, - false, - false, - false, - "permissions1", - "permissions2"); - - Application storedApplication = applicationCenterStorage.createApplication(application); - applicationCenterStorage.addApplicationToUserFavorite(storedApplication.getId(), "testuser"); - applicationCenterStorage.deleteApplicationFavorite(storedApplication.getId(), "testuser"); - } - - @Test - public void testGetFavoriteApplicationsByUser() throws Exception { - ApplicationCenterStorage applicationCenterStorage = ExoContainerContext.getService(ApplicationCenterStorage.class); - assertNotNull(applicationCenterStorage); - - try { - applicationCenterStorage.getFavoriteApplicationsByUser(null); - fail("Shouldn't allow to get favorite of null user"); - } catch (IllegalArgumentException e) { - // Expected - } - - List favoriteApplications = applicationCenterStorage.getFavoriteApplicationsByUser("testuser"); - assertNotNull(favoriteApplications); - assertEquals(0, favoriteApplications.size()); - - Application application = new Application(null, - "title", - "url", - "", - 0L, - 0L, - null, - null, - "description", - false, - true, - false, - false, - false, - "permissions1", - "permissions2"); - - Application storedApplication = applicationCenterStorage.createApplication(application); - applicationCenterStorage.addApplicationToUserFavorite(storedApplication.getId(), "testuser"); - assertEquals(1, applicationCenterStorage.getFavoriteApplicationsByUser("testuser").size()); - } - - @Test - public void testGetMandatoryApplicationsByUser() throws Exception { - ApplicationCenterStorage applicationCenterStorage = ExoContainerContext.getService(ApplicationCenterStorage.class); - assertNotNull(applicationCenterStorage); - - try { - applicationCenterStorage.getFavoriteApplicationsByUser(null); - fail("Shouldn't allow to get favorite of null user"); - } catch (IllegalArgumentException e) { - // Expected - } - - List mandatoryApplications = applicationCenterStorage.getMandatoryApplications(); - assertNotNull(mandatoryApplications); - assertEquals(0, mandatoryApplications.size()); - - Application application1 = new Application(null, - "title", - "url", - "", - 0L, - 0L, - null, - null, - "description", - false, - true, - true, - true, - false, - "permissions1", - "permissions2"); - - Application application2 = new Application(null, - "title", - "url", - "", - 0L, - 0L, - null, - null, - "description", - false, - false, - true, - true, - false, - "permissions1", - "permissions2"); - - applicationCenterStorage.createApplication(application1); - applicationCenterStorage.createApplication(application2); - - assertEquals(1, applicationCenterStorage.getMandatoryApplications().size()); - } - - @Test - public void testGetApplications() throws Exception { - ApplicationCenterStorage applicationCenterStorage = ExoContainerContext.getService(ApplicationCenterStorage.class); - assertNotNull(applicationCenterStorage); - - List applications = applicationCenterStorage.getApplications(null); - assertNotNull(applications); - assertEquals(0, applications.size()); - - applications = applicationCenterStorage.getApplications("title"); - assertNotNull(applications); - assertEquals(0, applications.size()); - - Application application = new Application(null, - "title", - "url", - "", - 0L, - 0L, - null, - null, - "description", - false, - true, - false, - false, - false, - "permissions1", - "permissions2"); - - applicationCenterStorage.createApplication(application); - applications = applicationCenterStorage.getApplications(null); - assertNotNull(applications); - assertEquals(1, applications.size()); - - applications = applicationCenterStorage.getApplications("title"); - assertNotNull(applications); - assertEquals(1, applications.size()); - - applications = applicationCenterStorage.getApplications("url"); - assertNotNull(applications); - assertEquals(1, applications.size()); - } - - @Test - public void testCountApplications() throws Exception { - ApplicationCenterStorage applicationCenterStorage = ExoContainerContext.getService(ApplicationCenterStorage.class); - assertNotNull(applicationCenterStorage); - - assertEquals(0, applicationCenterStorage.countApplications()); - - Application application = new Application(null, - "title", - "url", - "", - 0L, - 0L, - null, - null, - "description", - false, - true, - false, - false, - false, - "permissions1", - "permissions2"); - - applicationCenterStorage.createApplication(application); - assertEquals(1, applicationCenterStorage.countApplications()); - } - - @Test - public void testIsFavoriteApplication() throws Exception { - ApplicationCenterStorage applicationCenterStorage = ExoContainerContext.getService(ApplicationCenterStorage.class); - assertNotNull(applicationCenterStorage); - - try { - applicationCenterStorage.isFavoriteApplication(null, null); - fail("Shouldn't allow to get favorite of null user or applicationId"); - } catch (IllegalArgumentException e) { - // Expected - } - - try { - applicationCenterStorage.isFavoriteApplication(null, "testuser"); - fail("Shouldn't allow to get favorite of null applicationId"); - } catch (IllegalArgumentException e) { - // Expected - } - - try { - applicationCenterStorage.isFavoriteApplication(0L, "testuser"); - fail("Shouldn't allow to get favorite of non positive applicationId"); - } catch (IllegalArgumentException e) { - // Expected - } - - try { - applicationCenterStorage.isFavoriteApplication(1L, null); - fail("Shouldn't allow to get favorite of null user"); - } catch (IllegalArgumentException e) { - // Expected - } - - assertFalse(applicationCenterStorage.isFavoriteApplication(1L, "testuser")); - - Application application = new Application(null, - "title", - "url", - "", - 0L, - 0L, - null, - null, - "description", - false, - true, - false, - false, - false, - "permissions1", - "permissions2"); - - Application storedApplication = applicationCenterStorage.createApplication(application); - applicationCenterStorage.addApplicationToUserFavorite(storedApplication.getId(), "testuser"); - - assertTrue(applicationCenterStorage.isFavoriteApplication(storedApplication.getId(), "testuser")); - } - - @Test - public void testCountFavorites() throws Exception { - ApplicationCenterStorage applicationCenterStorage = ExoContainerContext.getService(ApplicationCenterStorage.class); - assertNotNull(applicationCenterStorage); - - try { - applicationCenterStorage.countFavorites(null); - fail("Shouldn't allow to get favorite of null user"); - } catch (IllegalArgumentException e) { - // Expected - } - - assertEquals(0, applicationCenterStorage.countFavorites("testuser")); - - Application application = new Application(null, - "title", - "url", - "", - 0L, - 0L, - null, - null, - "description", - false, - true, - false, - false, - false, - "permissions1", - "permissions2"); - - Application storedApplication = applicationCenterStorage.createApplication(application); - applicationCenterStorage.addApplicationToUserFavorite(storedApplication.getId(), "testuser"); - - assertEquals(1, applicationCenterStorage.countFavorites("testuser")); - } - - @Test - public void testCreateAppImageFileItem() throws Exception { - ApplicationCenterStorage applicationCenterStorage = ExoContainerContext.getService(ApplicationCenterStorage.class); - assertNotNull(applicationCenterStorage); - - assertNull(applicationCenterStorage.createAppImageFileItem(null, null)); - assertNull(applicationCenterStorage.createAppImageFileItem("name", null)); - assertNull(applicationCenterStorage.createAppImageFileItem(null, "fileContent")); - ApplicationImage applicationImage = applicationCenterStorage.createAppImageFileItem("name", "fileContent"); - assertNotNull(applicationImage); - assertNotNull(applicationImage.getFileName()); - assertNotNull(applicationImage.getFileBody()); - } - - @Test - public void testGetAppImageFile() throws Exception { - ApplicationCenterStorage applicationCenterStorage = ExoContainerContext.getService(ApplicationCenterStorage.class); - assertNotNull(applicationCenterStorage); - - ApplicationImage applicationImage = applicationCenterStorage.createAppImageFileItem("name", "fileContent"); - assertNotNull(applicationImage); - - applicationImage = applicationCenterStorage.getAppImageFile(applicationImage.getId()); - assertNotNull(applicationImage); - assertNotNull(applicationImage.getFileName()); - assertNotNull(applicationImage.getFileBody()); - } - -} diff --git a/app-center-services/src/test/resources/META-INF/services/javax.ws.rs.ext.RuntimeDelegate b/app-center-services/src/test/resources/META-INF/services/javax.ws.rs.ext.RuntimeDelegate deleted file mode 100644 index ac4212764..000000000 --- a/app-center-services/src/test/resources/META-INF/services/javax.ws.rs.ext.RuntimeDelegate +++ /dev/null @@ -1 +0,0 @@ -org.exoplatform.services.rest.impl.RuntimeDelegateImpl \ No newline at end of file diff --git a/app-center-services/src/test/resources/applications.json b/app-center-services/src/test/resources/applications.json new file mode 100644 index 000000000..a5ba8cdf1 --- /dev/null +++ b/app-center-services/src/test/resources/applications.json @@ -0,0 +1,23 @@ +{ + "descriptors": [ + { + "name": "test-application-injection", + "imagePath": "jar:/test.png", + "overrideMode": "merge", + "override": true, + "enabled": false, + "application": { + "title": "test-application-injection", + "description": "test application injection from JSON", + "url": "./test", + "system": true, + "active": true, + "isMobile": true, + "permissions": [ + "*:/platform/analytics", + "*:/platform/administrators" + ] + } + } + ] +} diff --git a/app-center-services/src/test/resources/conf/configuration.properties b/app-center-services/src/test/resources/conf/configuration.properties deleted file mode 100644 index 0d4b5e3de..000000000 --- a/app-center-services/src/test/resources/conf/configuration.properties +++ /dev/null @@ -1,16 +0,0 @@ -# -# This file is part of the Meeds project (https://meeds.io/). -# Copyright (C) 2020 Meeds Association -# contact@meeds.io -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 3 of the License, or (at your option) any later version. -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# You should have received a copy of the GNU Lesser General Public License -# along with this program; if not, write to the Free Software Foundation, -# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -# diff --git a/app-center-services/src/test/resources/conf/configuration.xml b/app-center-services/src/test/resources/conf/configuration.xml deleted file mode 100644 index 54527b182..000000000 --- a/app-center-services/src/test/resources/conf/configuration.xml +++ /dev/null @@ -1,36 +0,0 @@ - - - - - - org.exoplatform.services.naming.InitialContextInitializer - org.exoplatform.commons.InitialContextInitializer2 - true - - - default-properties - Default initial context properties - - - - - - - org.exoplatform.commons.api.persistence.DataInitializer - diff --git a/app-center-services/src/test/resources/conf/portal/configuration.xml b/app-center-services/src/test/resources/conf/portal/configuration.xml deleted file mode 100644 index 012379d63..000000000 --- a/app-center-services/src/test/resources/conf/portal/configuration.xml +++ /dev/null @@ -1,128 +0,0 @@ - - - - - - org.exoplatform.portal.config.UserACL - org.exoplatform.portal.config.UserACL - - - super.user - administrator - root - - - - portal.administrator.groups - administrator - /platform/administrators - - - - portal.administrator.mstype - administrator - manager - - - - portal.creator.groups - groups with membership type have permission to manage portal - *:/platform/administrators,*:/organization/management/executive-board - - - - navigation.creator.membership.type - specific membership type have full permission with group navigation - manager - - - - guests.group - guests group - /platform/guests - - - - mandatory.groups - Groups that can not be deleted. - /platform/administrators - /platform/users - /platform/guests - /spaces - - - - mandatory.mstypes - Membership type that can not be deleted. - member - manager - * - - - - - - org.exoplatform.commons.api.persistence.DataInitializer - org.exoplatform.commons.persistence.impl.LiquibaseDataInitializer - - - liquibase.datasource - java:/comp/env/exo-jpa_portal - - - liquibase.contexts - ${exo.liquibase.contexts} - - - - - - org.exoplatform.ws.frameworks.cometd.ContinuationService - - - org.exoplatform.ws.frameworks.cometd.transport.ContinuationServiceDelegate - org.exoplatform.ws.frameworks.cometd.transport.ContinuationServiceLocalDelegate - - - - - org.exoplatform.commons.api.persistence.DataInitializer - - CommonsChangeLogsPlugin - addChangeLogsPlugin - org.exoplatform.commons.persistence.impl.ChangeLogsPlugin - - - changelogs - Change logs of settings - db/changelog/quartz.db.changelog-1.0.0.xml - db/changelog/settings.db.changelog-1.0.0.xml - db.changelogs/app-center-changelog-1.0.0.xml - - - - - - jar:/conf/exo.portal.component.identity-configuration.xml - jar:/org/exoplatform/services/organization/TestOrganization-configuration.xml - jar:/org/exoplatform/jpa/configuration.xml - - org.exoplatform.commons.search.index.IndexingOperationProcessor - org.exoplatform.commons.search.rest.IndexingManagementRestServiceV1 - diff --git a/app-center-webapps/package-lock.json b/app-center-webapps/package-lock.json index 898bc8cf7..67e566e4e 100644 --- a/app-center-webapps/package-lock.json +++ b/app-center-webapps/package-lock.json @@ -11,8 +11,9 @@ "devDependencies": { "babel-loader": "^8.3.0", "eslint": "^8.12.0", - "eslint-config-meedsio": "^1.0.4", + "eslint-config-meedsio": "^1.0.5", "eslint-plugin-vue": "^8.6.0", + "eslint-plugin-vuejs-accessibility": "^2.1.0", "eslint-webpack-plugin": "^3.1.1", "vue": "^2.6.14", "vue-loader": "^15.10.1", @@ -914,6 +915,15 @@ "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", "dev": true }, + "node_modules/aria-query": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.0.tgz", + "integrity": "sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==", + "dev": true, + "dependencies": { + "dequal": "^2.0.3" + } + }, "node_modules/babel-loader": { "version": "8.3.0", "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-8.3.0.tgz", @@ -1263,6 +1273,15 @@ "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", "dev": true }, + "node_modules/dequal": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", + "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, "node_modules/doctrine": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", @@ -1281,6 +1300,12 @@ "integrity": "sha512-M8WEXFuKXMYMVr45fo8mq0wUrrJHheiKZf6BArTKk9ZBYCKJEOU5H8cdWgDT+qCVZf7Na4lVUaZsA+h6uA9+PA==", "dev": true }, + "node_modules/emoji-regex": { + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.3.0.tgz", + "integrity": "sha512-QpLs9D9v9kArv4lfDEgg1X/gN5XLnf/A6l9cs8SPZLRZR3ZkY9+kwIQTxm+fsSej5UMYGE8fdoaZVIBlqG0XTw==", + "dev": true + }, "node_modules/emojis-list": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz", @@ -1397,9 +1422,9 @@ } }, "node_modules/eslint-config-meedsio": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/eslint-config-meedsio/-/eslint-config-meedsio-1.0.4.tgz", - "integrity": "sha512-hGHNO0ss7jqPgPMQUe+q8UmA4lrIUnaqeusGeiCPYq1z9APGWNrZEIqpY8NGi2at6vcQJ0yXl559RRUeuP3GUg==", + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/eslint-config-meedsio/-/eslint-config-meedsio-1.0.5.tgz", + "integrity": "sha512-eSae9Ald7T7g4gIdomPGJ7/H+aVd9L+wLvDUICvc8vKfLeKoJSdOH1uoJ1beUytObQbzbJJJC+cHvf+8BxYDdg==", "dev": true }, "node_modules/eslint-plugin-vue": { @@ -1455,6 +1480,59 @@ "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", "dev": true }, + "node_modules/eslint-plugin-vuejs-accessibility": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-vuejs-accessibility/-/eslint-plugin-vuejs-accessibility-2.3.0.tgz", + "integrity": "sha512-zQ6IzK+3obZzPsjeVUeL3xAUlMHXZgRZ8vgXvQAmoZVbsp1xZe6UwXIKUFIim5h3tq/7bOLgei09GoBjJQs+Cw==", + "dev": true, + "dependencies": { + "aria-query": "^5.3.0", + "emoji-regex": "^10.0.0", + "vue-eslint-parser": "^9.0.1" + }, + "engines": { + "node": ">=16.0.0" + }, + "peerDependencies": { + "eslint": "^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0 || ^9.0.0" + } + }, + "node_modules/eslint-plugin-vuejs-accessibility/node_modules/semver": { + "version": "7.6.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz", + "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/eslint-plugin-vuejs-accessibility/node_modules/vue-eslint-parser": { + "version": "9.4.2", + "resolved": "https://registry.npmjs.org/vue-eslint-parser/-/vue-eslint-parser-9.4.2.tgz", + "integrity": "sha512-Ry9oiGmCAK91HrKMtCrKFWmSFWvYkpGglCeFAIqDdr9zdXmMMpJOmUJS7WWsW7fX81h6mwHmUZCQQ1E0PkSwYQ==", + "dev": true, + "dependencies": { + "debug": "^4.3.4", + "eslint-scope": "^7.1.1", + "eslint-visitor-keys": "^3.3.0", + "espree": "^9.3.1", + "esquery": "^1.4.0", + "lodash": "^4.17.21", + "semver": "^7.3.6" + }, + "engines": { + "node": "^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/mysticatea" + }, + "peerDependencies": { + "eslint": ">=6.0.0" + } + }, "node_modules/eslint-scope": { "version": "7.1.1", "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.1.1.tgz", @@ -4516,6 +4594,15 @@ "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", "dev": true }, + "aria-query": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.0.tgz", + "integrity": "sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==", + "dev": true, + "requires": { + "dequal": "^2.0.3" + } + }, "babel-loader": { "version": "8.3.0", "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-8.3.0.tgz", @@ -4777,6 +4864,12 @@ "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", "dev": true }, + "dequal": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", + "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", + "dev": true + }, "doctrine": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", @@ -4792,6 +4885,12 @@ "integrity": "sha512-M8WEXFuKXMYMVr45fo8mq0wUrrJHheiKZf6BArTKk9ZBYCKJEOU5H8cdWgDT+qCVZf7Na4lVUaZsA+h6uA9+PA==", "dev": true }, + "emoji-regex": { + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.3.0.tgz", + "integrity": "sha512-QpLs9D9v9kArv4lfDEgg1X/gN5XLnf/A6l9cs8SPZLRZR3ZkY9+kwIQTxm+fsSej5UMYGE8fdoaZVIBlqG0XTw==", + "dev": true + }, "emojis-list": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz", @@ -4947,9 +5046,9 @@ } }, "eslint-config-meedsio": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/eslint-config-meedsio/-/eslint-config-meedsio-1.0.4.tgz", - "integrity": "sha512-hGHNO0ss7jqPgPMQUe+q8UmA4lrIUnaqeusGeiCPYq1z9APGWNrZEIqpY8NGi2at6vcQJ0yXl559RRUeuP3GUg==", + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/eslint-config-meedsio/-/eslint-config-meedsio-1.0.5.tgz", + "integrity": "sha512-eSae9Ald7T7g4gIdomPGJ7/H+aVd9L+wLvDUICvc8vKfLeKoJSdOH1uoJ1beUytObQbzbJJJC+cHvf+8BxYDdg==", "dev": true }, "eslint-plugin-vue": { @@ -4992,6 +5091,40 @@ } } }, + "eslint-plugin-vuejs-accessibility": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-vuejs-accessibility/-/eslint-plugin-vuejs-accessibility-2.3.0.tgz", + "integrity": "sha512-zQ6IzK+3obZzPsjeVUeL3xAUlMHXZgRZ8vgXvQAmoZVbsp1xZe6UwXIKUFIim5h3tq/7bOLgei09GoBjJQs+Cw==", + "dev": true, + "requires": { + "aria-query": "^5.3.0", + "emoji-regex": "^10.0.0", + "vue-eslint-parser": "^9.0.1" + }, + "dependencies": { + "semver": { + "version": "7.6.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz", + "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==", + "dev": true + }, + "vue-eslint-parser": { + "version": "9.4.2", + "resolved": "https://registry.npmjs.org/vue-eslint-parser/-/vue-eslint-parser-9.4.2.tgz", + "integrity": "sha512-Ry9oiGmCAK91HrKMtCrKFWmSFWvYkpGglCeFAIqDdr9zdXmMMpJOmUJS7WWsW7fX81h6mwHmUZCQQ1E0PkSwYQ==", + "dev": true, + "requires": { + "debug": "^4.3.4", + "eslint-scope": "^7.1.1", + "eslint-visitor-keys": "^3.3.0", + "espree": "^9.3.1", + "esquery": "^1.4.0", + "lodash": "^4.17.21", + "semver": "^7.3.6" + } + } + } + }, "eslint-scope": { "version": "7.1.1", "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.1.1.tgz", diff --git a/app-center-webapps/pom.xml b/app-center-webapps/pom.xml index df812ae4a..f5b15994d 100644 --- a/app-center-webapps/pom.xml +++ b/app-center-webapps/pom.xml @@ -1,19 +1,23 @@ Add-on:: Application Center - Webapp - org.exoplatform.gatein.portal - exo.portal.component.api + ${project.groupId} + app-center-services provided diff --git a/app-center-webapps/src/main/java/io/meeds/appcenter/AppCenterApplication.java b/app-center-webapps/src/main/java/io/meeds/appcenter/AppCenterApplication.java new file mode 100644 index 000000000..83b835c95 --- /dev/null +++ b/app-center-webapps/src/main/java/io/meeds/appcenter/AppCenterApplication.java @@ -0,0 +1,43 @@ +/** + * This file is part of the Meeds project (https://meeds.io/). + * + * Copyright (C) 2020 - 2024 Meeds Association contact@meeds.io + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package io.meeds.appcenter; + +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.annotation.PropertySource; +import org.springframework.data.jpa.repository.config.EnableJpaRepositories; + +import io.meeds.spring.AvailableIntegration; +import io.meeds.spring.kernel.PortalApplicationContextInitializer; + +@SpringBootApplication(scanBasePackages = { + AppCenterApplication.MODULE_NAME, + AvailableIntegration.KERNEL_MODULE, + AvailableIntegration.JPA_MODULE, + AvailableIntegration.LIQUIBASE_MODULE, + AvailableIntegration.WEB_MODULE, +}) +@EnableJpaRepositories(basePackages = AppCenterApplication.MODULE_NAME) +@PropertySource("classpath:application.properties") +@PropertySource("classpath:application-common.properties") +@PropertySource("classpath:appcenter.properties") +public class AppCenterApplication extends PortalApplicationContextInitializer { + + public static final String MODULE_NAME = "io.meeds.appcenter"; + +} diff --git a/app-center-webapps/src/main/java/org/exoplatform/portlets/appCenter/AdminSetupPortlet.java b/app-center-webapps/src/main/java/io/meeds/appcenter/portlet/AdminSetupPortlet.java similarity index 84% rename from app-center-webapps/src/main/java/org/exoplatform/portlets/appCenter/AdminSetupPortlet.java rename to app-center-webapps/src/main/java/io/meeds/appcenter/portlet/AdminSetupPortlet.java index d47241d29..7fa4448dc 100644 --- a/app-center-webapps/src/main/java/org/exoplatform/portlets/appCenter/AdminSetupPortlet.java +++ b/app-center-webapps/src/main/java/io/meeds/appcenter/portlet/AdminSetupPortlet.java @@ -1,23 +1,23 @@ /* * This file is part of the Meeds project (https://meeds.io/). - * Copyright (C) 2020 Meeds Association - * contact@meeds.io + * + * Copyright (C) 2020 - 2024 Meeds Association contact@meeds.io + * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 3 of the License, or (at your option) any later version. + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. + * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -/** - * - */ -package org.exoplatform.portlets.appCenter; +package io.meeds.appcenter.portlet; import java.io.IOException; @@ -30,11 +30,13 @@ import javax.portlet.RenderResponse; import javax.portlet.PortletPreferences; - /** * @author Ayoub Zayati */ public class AdminSetupPortlet extends GenericPortlet { + + private static final String PAGE_SIZE_PREFERENCE_NAME = "pageSize"; + @Override protected void doView(RenderRequest request, RenderResponse response) throws IOException, PortletException { PortletRequestDispatcher dispatcher = getPortletContext().getRequestDispatcher("/WEB-INF/jsp/appCenter/adminSetup/view.jsp"); @@ -50,9 +52,10 @@ protected void doEdit(RenderRequest request, RenderResponse response) throws IOE @Override public void processAction(ActionRequest request, ActionResponse response) throws IOException, PortletException { PortletPreferences preferences = request.getPreferences(); - String pageSize = request.getParameter("pageSize"); - preferences.setValue("pageSize", pageSize); - response.setRenderParameter("pageSize", pageSize); + String pageSize = request.getParameter(PAGE_SIZE_PREFERENCE_NAME); + preferences.setValue(PAGE_SIZE_PREFERENCE_NAME, pageSize); + response.setRenderParameter(PAGE_SIZE_PREFERENCE_NAME, pageSize); preferences.store(); } + } diff --git a/app-center-webapps/src/main/java/org/exoplatform/portlets/appCenter/MyApplicationsPortlet.java b/app-center-webapps/src/main/java/io/meeds/appcenter/portlet/MyApplicationsPortlet.java similarity index 83% rename from app-center-webapps/src/main/java/org/exoplatform/portlets/appCenter/MyApplicationsPortlet.java rename to app-center-webapps/src/main/java/io/meeds/appcenter/portlet/MyApplicationsPortlet.java index b31b30d93..5f3db70cd 100644 --- a/app-center-webapps/src/main/java/org/exoplatform/portlets/appCenter/MyApplicationsPortlet.java +++ b/app-center-webapps/src/main/java/io/meeds/appcenter/portlet/MyApplicationsPortlet.java @@ -1,23 +1,22 @@ -/* +/** * This file is part of the Meeds project (https://meeds.io/). - * Copyright (C) 2020 Meeds Association - * contact@meeds.io + * + * Copyright (C) 2020 - 2024 Meeds Association contact@meeds.io * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 3 of the License, or (at your option) any later version. + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. + * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -/** - * + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -package org.exoplatform.portlets.appCenter; +package io.meeds.appcenter.portlet; import java.io.IOException; diff --git a/app-center-webapps/src/main/java/org/exoplatform/portlets/appCenter/UserSetupPortlet.java b/app-center-webapps/src/main/java/io/meeds/appcenter/portlet/UserSetupPortlet.java similarity index 89% rename from app-center-webapps/src/main/java/org/exoplatform/portlets/appCenter/UserSetupPortlet.java rename to app-center-webapps/src/main/java/io/meeds/appcenter/portlet/UserSetupPortlet.java index 20facece7..b6e7ab0be 100644 --- a/app-center-webapps/src/main/java/org/exoplatform/portlets/appCenter/UserSetupPortlet.java +++ b/app-center-webapps/src/main/java/io/meeds/appcenter/portlet/UserSetupPortlet.java @@ -1,23 +1,22 @@ -/* +/** * This file is part of the Meeds project (https://meeds.io/). - * Copyright (C) 2020 Meeds Association - * contact@meeds.io + * + * Copyright (C) 2020 - 2024 Meeds Association contact@meeds.io * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 3 of the License, or (at your option) any later version. + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. + * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -/** - * + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -package org.exoplatform.portlets.appCenter; +package io.meeds.appcenter.portlet; import java.io.IOException; diff --git a/app-center-webapps/src/main/resources/appcenter.properties b/app-center-webapps/src/main/resources/appcenter.properties new file mode 100644 index 000000000..8529e2394 --- /dev/null +++ b/app-center-webapps/src/main/resources/appcenter.properties @@ -0,0 +1,20 @@ +# +# This file is part of the Meeds project (https://meeds.io/). +# +# Copyright (C) 2024 Meeds Association contact@meeds.io +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 3 of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with this program; if not, write to the Free Software Foundation, +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +spring.liquibase.change-log=classpath:db.changelogs/app-center-changelog-1.0.0.xml \ No newline at end of file diff --git a/app-center-webapps/src/main/resources/conf/portal/configuration.xml b/app-center-webapps/src/main/resources/conf/portal/configuration.xml new file mode 100644 index 000000000..7bcdeec31 --- /dev/null +++ b/app-center-webapps/src/main/resources/conf/portal/configuration.xml @@ -0,0 +1,44 @@ + + + + + + org.exoplatform.commons.file.services.NameSpaceService + + AppCenterNameSpacePlugin + addNameSpacePlugin + org.exoplatform.commons.file.services.NameSpacePlugin + + + fileNameSpace.params + + + + + + + + \ No newline at end of file diff --git a/app-center-webapps/src/main/webapp/WEB-INF/conf/app-center/analytics-configuration.xml b/app-center-webapps/src/main/webapp/WEB-INF/conf/app-center/analytics-configuration.xml index d675ec38c..42567c39b 100644 --- a/app-center-webapps/src/main/webapp/WEB-INF/conf/app-center/analytics-configuration.xml +++ b/app-center-webapps/src/main/webapp/WEB-INF/conf/app-center/analytics-configuration.xml @@ -1,19 +1,23 @@ diff --git a/app-center-webapps/src/main/webapp/WEB-INF/conf/app-center/bundle-configuration.xml b/app-center-webapps/src/main/webapp/WEB-INF/conf/app-center/bundle-configuration.xml index 19caf6f79..3c2c1fedb 100644 --- a/app-center-webapps/src/main/webapp/WEB-INF/conf/app-center/bundle-configuration.xml +++ b/app-center-webapps/src/main/webapp/WEB-INF/conf/app-center/bundle-configuration.xml @@ -1,4 +1,25 @@ + diff --git a/app-center-webapps/src/main/webapp/WEB-INF/conf/app-center/portal-configuration.xml b/app-center-webapps/src/main/webapp/WEB-INF/conf/app-center/portal-configuration.xml index a40f3e2db..919ec8154 100644 --- a/app-center-webapps/src/main/webapp/WEB-INF/conf/app-center/portal-configuration.xml +++ b/app-center-webapps/src/main/webapp/WEB-INF/conf/app-center/portal-configuration.xml @@ -1,19 +1,23 @@ applications - + ${exo.search.application.enabled:true} diff --git a/app-center-webapps/src/main/webapp/WEB-INF/conf/configuration.xml b/app-center-webapps/src/main/webapp/WEB-INF/conf/configuration.xml index 90557916d..9983c588f 100644 --- a/app-center-webapps/src/main/webapp/WEB-INF/conf/configuration.xml +++ b/app-center-webapps/src/main/webapp/WEB-INF/conf/configuration.xml @@ -1,19 +1,23 @@ <% - ResourceBundle resource = portletConfig.getResourceBundle(renderRequest.getLocale()); - - + ResourceBundle resource = portletConfig.getResourceBundle(renderRequest.getLocale()); PortletURL actionURL = renderResponse.createActionURL(); PortletPreferences preferences = renderRequest.getPreferences(); String pageSize = renderRequest.getParameter("pageSize"); @@ -19,7 +17,6 @@ } } %> -
diff --git a/app-center-webapps/src/main/webapp/WEB-INF/jsp/appCenter/adminSetup/view.jsp b/app-center-webapps/src/main/webapp/WEB-INF/jsp/appCenter/adminSetup/view.jsp index cd309aefd..2037e9e37 100644 --- a/app-center-webapps/src/main/webapp/WEB-INF/jsp/appCenter/adminSetup/view.jsp +++ b/app-center-webapps/src/main/webapp/WEB-INF/jsp/appCenter/adminSetup/view.jsp @@ -2,12 +2,11 @@ <%@ taglib uri="http://java.sun.com/portlet_2_0" prefix="portlet"%> <% - PortletPreferences preferences = renderRequest.getPreferences(); - String pageSize = preferences.getValue("pageSize", ""); - if (pageSize == null) { - pageSize = ""; - } - + PortletPreferences preferences = renderRequest.getPreferences(); + String pageSize = preferences.getValue("pageSize", ""); + if (pageSize == null) { + pageSize = ""; + } %>
AppCenterAdminSetupPortlet App center admin setup portlet - org.exoplatform.portlets.appCenter.AdminSetupPortlet + io.meeds.appcenter.portlet.AdminSetupPortlet preload.resource.bundles locale.addon.appcenter preload.resource.rest - /portal/rest/app-center/settings + /app-center/rest/settings text/html @@ -56,7 +61,7 @@ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. AppCenterUserSetupPortlet App center user setup portlet - org.exoplatform.portlets.appCenter.UserSetupPortlet + io.meeds.appcenter.portlet.UserSetupPortlet prefetch.resources true @@ -67,7 +72,7 @@ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. prefetch.resource.rest - + text/html @@ -102,7 +107,7 @@ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. preload.resource.rest - /portal/rest/app-center/settings,/portal/rest/app-center/applications/favorites + /app-center/rest/settings,/app-center/rest/favorites -1 PUBLIC diff --git a/app-center-webapps/src/main/webapp/WEB-INF/web.xml b/app-center-webapps/src/main/webapp/WEB-INF/web.xml index fa22b4089..dfd034b70 100644 --- a/app-center-webapps/src/main/webapp/WEB-INF/web.xml +++ b/app-center-webapps/src/main/webapp/WEB-INF/web.xml @@ -1,19 +1,23 @@ - + ResourceRequestFilter - /* + *.css + *.js + *.html + /images/* + + GateInServlet + org.gatein.wci.api.GateInServlet + 0 + + + + GateInServlet + /gateinservlet + + \ No newline at end of file diff --git a/app-center-webapps/src/main/webapp/vue-apps/adminSetup/components/AdminSetupGeneralParams.vue b/app-center-webapps/src/main/webapp/vue-apps/adminSetup/components/AdminSetupGeneralParams.vue index 8bfde2d86..8220ea329 100644 --- a/app-center-webapps/src/main/webapp/vue-apps/adminSetup/components/AdminSetupGeneralParams.vue +++ b/app-center-webapps/src/main/webapp/vue-apps/adminSetup/components/AdminSetupGeneralParams.vue @@ -52,7 +52,7 @@ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
{ @@ -268,7 +256,7 @@ export default { }, setDefaultAppImage() { - const setDefaultAppImageUrl = '/portal/rest/app-center/settings/image'; + const setDefaultAppImageUrl = '/app-center/rest/settings/image'; return fetch(setDefaultAppImageUrl, { method: 'PATCH', credentials: 'include', diff --git a/app-center-webapps/src/main/webapp/vue-apps/adminSetup/components/AdminSetupList.vue b/app-center-webapps/src/main/webapp/vue-apps/adminSetup/components/AdminSetupList.vue index 4db0524a8..fd9b2768d 100644 --- a/app-center-webapps/src/main/webapp/vue-apps/adminSetup/components/AdminSetupList.vue +++ b/app-center-webapps/src/main/webapp/vue-apps/adminSetup/components/AdminSetupList.vue @@ -58,8 +58,8 @@ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - + :src="`/app-center/rest/applications/illustration/${props.item.id}?v=${props.item.imageLastModified}`"> + `*:${group}`), imageFileBody: this.formArray.imageFileBody, diff --git a/app-center-webapps/src/main/webapp/vue-apps/appLauncher/components/AppLauncherDrawer.vue b/app-center-webapps/src/main/webapp/vue-apps/appLauncher/components/AppLauncherDrawer.vue index 8f2105f96..86c2ba567 100644 --- a/app-center-webapps/src/main/webapp/vue-apps/appLauncher/components/AppLauncherDrawer.vue +++ b/app-center-webapps/src/main/webapp/vue-apps/appLauncher/components/AppLauncherDrawer.vue @@ -59,18 +59,17 @@ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + :href="application.computedUrl"> + :src="`/app-center/rest/applications/illustration/${application.id}?v=${application.imageLastModified}`"> + :src="`/app-center/rest/applications/illustration/${application.id}?v=${application.imageLastModified}`"> + :href="appCenterLink"> {{ $t("appCenter.appLauncher.drawer.viewAll") }} @@ -219,7 +215,7 @@ export default { this.$refs.appLauncherDrawer.open(); }, getMandatoryAndFavoriteApplications() { - return fetch('/portal/rest/app-center/applications/favorites', { + return fetch('/app-center/rest/favorites', { method: 'GET', credentials: 'include', }) @@ -295,7 +291,7 @@ export default { }).finally(() => this.loading = false); }, updateApplicationsOrder(applicationsOrder) { - return fetch('/portal/rest/app-center/applications/favorites', { + return fetch('/app-center/rest/favorites', { headers: { 'Content-Type': 'application/json' }, @@ -304,22 +300,8 @@ export default { body: JSON.stringify(applicationsOrder) }); }, - logOpenApplication(id) { - fetch(`/portal/rest/app-center/applications/logClickApplication/${id}`, { - method: 'GET', - credentials: 'include', - }); - }, - navigateTo(link) { - if (link==='appCenterUserSetup/') { - fetch('/portal/rest/app-center/applications/logClickAllApplications', { - method: 'GET', - credentials: 'include', - }); - } - }, getAppGeneralSettings() { - return fetch('/portal/rest/app-center/settings', { + return fetch('/app-center/rest/settings', { method: 'GET', credentials: 'include', }) diff --git a/app-center-webapps/src/main/webapp/vue-apps/application-search/components/ApplicationSearchCard.vue b/app-center-webapps/src/main/webapp/vue-apps/application-search/components/ApplicationSearchCard.vue index 2d87e3b5d..9130f5c67 100644 --- a/app-center-webapps/src/main/webapp/vue-apps/application-search/components/ApplicationSearchCard.vue +++ b/app-center-webapps/src/main/webapp/vue-apps/application-search/components/ApplicationSearchCard.vue @@ -19,8 +19,7 @@ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. @@ -71,13 +69,5 @@ export default { return this.applicationUrl.indexOf('/') === 0 ? '_self' : '_blank'; }, }, - methods: { - logOpenApplication() { - fetch(`/portal/rest/app-center/applications/logClickApplication/${this.result.id}`, { - method: 'GET', - credentials: 'include', - }); - }, - } }; diff --git a/app-center-webapps/src/main/webapp/vue-apps/myApplications/components/MyApplications.vue b/app-center-webapps/src/main/webapp/vue-apps/myApplications/components/MyApplications.vue index 4146c7c52..29e62a44a 100644 --- a/app-center-webapps/src/main/webapp/vue-apps/myApplications/components/MyApplications.vue +++ b/app-center-webapps/src/main/webapp/vue-apps/myApplications/components/MyApplications.vue @@ -26,12 +26,11 @@ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  • + :target="favoriteApp.target"> + :src="`/app-center/rest/applications/illustration/${favoriteApp.id}?v=${favoriteApp.imageLastModified}`">
    {{ favoriteApp.title }}
    {{ favoriteApp.description }} @@ -72,7 +71,7 @@ export default { methods: { getFavoriteApplicationsList() { - return fetch('/portal/rest/app-center/applications/favorites', { + return fetch('/app-center/rest/favorites', { credentials: 'include', method: 'GET' }) @@ -95,14 +94,8 @@ export default { return this.favoriteApplicationsList; }); }, - logOpenApplication(id) { - fetch(`/portal/rest/app-center/applications/logClickApplication/${id}`, { - method: 'GET', - credentials: 'include', - }); - }, getMaxFavoriteApps() { - return fetch('/portal/rest/app-center/settings', { + return fetch('/app-center/rest/settings', { method: 'GET', credentials: 'include', }) diff --git a/app-center-webapps/src/main/webapp/vue-apps/userSetup/components/UserAuthorizedApplications.vue b/app-center-webapps/src/main/webapp/vue-apps/userSetup/components/UserAuthorizedApplications.vue index 485a1faaa..a7b3800ac 100644 --- a/app-center-webapps/src/main/webapp/vue-apps/userSetup/components/UserAuthorizedApplications.vue +++ b/app-center-webapps/src/main/webapp/vue-apps/userSetup/components/UserAuthorizedApplications.vue @@ -76,18 +76,17 @@ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
    + :href="authorizedApp.computedUrl"> + :src="`/app-center/rest/applications/illustration/${authorizedApp.id}?v=${authorizedApp.imageLastModified}`"> + :src="`/app-center/rest/applications/illustration/${authorizedApp.id}?v=${authorizedApp.imageLastModified}`"> + :href="authorizedApp.computedUrl">
    {{ $t("appCenter.userSetup.authorized.open") }} + :href="authorizedApp.computedUrl">{{ $t("appCenter.userSetup.authorized.open") }}
    { @@ -345,7 +342,7 @@ export default { this.getAuthorizedApplicationsList(); }, getMaxFavoriteApps() { - return fetch('/portal/rest/app-center/settings', { + return fetch('/app-center/rest/settings', { method: 'GET', credentials: 'include', }) @@ -364,12 +361,6 @@ export default { this.authorizedApplicationsList = []; this.getAuthorizedApplicationsList(true); }, - logOpenApplication(id) { - fetch(`/portal/rest/app-center/applications/logClickApplication/${id}`, { - method: 'GET', - credentials: 'include', - }); - }, navigateTo(link) { window.open(link); }, diff --git a/app-center-webapps/src/main/webapp/vue-apps/userSetup/components/UserFavoriteApplications.vue b/app-center-webapps/src/main/webapp/vue-apps/userSetup/components/UserFavoriteApplications.vue index c9c118ba6..7ba6b7fe7 100644 --- a/app-center-webapps/src/main/webapp/vue-apps/userSetup/components/UserFavoriteApplications.vue +++ b/app-center-webapps/src/main/webapp/vue-apps/userSetup/components/UserFavoriteApplications.vue @@ -46,18 +46,17 @@ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
    + :href="favoriteApp.computedUrl"> + :src="`/app-center/rest/applications/illustration/${favoriteApp.id}?v=${favoriteApp.imageLastModified}`"> + :src="`/app-center/rest/applications/illustration/${favoriteApp.id}?v=${favoriteApp.imageLastModified}`"> + :href="favoriteApp.computedUrl">
    @@ -147,7 +145,7 @@ export default { }); }, getFavoriteApplicationsList() { - return fetch('/portal/rest/app-center/applications/favorites', { + return fetch('/app-center/rest/favorites', { method: 'GET', credentials: 'include', }) @@ -217,14 +215,8 @@ export default { return this.favoriteApplicationsList; }).finally(() => this.loading = false); }, - logOpenApplication(id) { - fetch(`/portal/rest/app-center/applications/logClickApplication/${id}`, { - method: 'GET', - credentials: 'include', - }); - }, deleteFavoriteApplication(appId) { - return fetch(`/portal/rest/app-center/applications/favorites/${appId}`, { + return fetch(`/app-center/rest/favorites/${appId}`, { method: 'DELETE', credentials: 'include', }) diff --git a/app-center-webapps/src/main/webapp/vue-apps/userSetup/components/UserSetup.vue b/app-center-webapps/src/main/webapp/vue-apps/userSetup/components/UserSetup.vue index 9883d473f..69af23264 100644 --- a/app-center-webapps/src/main/webapp/vue-apps/userSetup/components/UserSetup.vue +++ b/app-center-webapps/src/main/webapp/vue-apps/userSetup/components/UserSetup.vue @@ -55,7 +55,7 @@ export default { this.canAddFavorite = canAddFavorite; }, getAppGeneralSettings() { - return fetch('/portal/rest/app-center/settings', { + return fetch('/app-center/rest/settings', { method: 'GET', credentials: 'include', })