diff --git a/src/apps/protocols.clj b/src/apps/protocols.clj index 2f038770..7aab6a0f 100644 --- a/src/apps/protocols.clj +++ b/src/apps/protocols.clj @@ -11,6 +11,8 @@ (listAppsInCategory [_ system-id category-id params]) (listAppsUnderHierarchy [_ root-iri attr params]) (adminListAppsUnderHierarchy [_ ontology-version root-iri attr params]) + (listAppsInCommunity [_ community-id params]) + (adminListAppsInCommunity [_ community-id params]) (searchApps [_ search-term params]) (adminSearchApps [_ search-term params]) (canEditApps [_]) diff --git a/src/apps/routes.clj b/src/apps/routes.clj index e42c63fa..bb1e235a 100644 --- a/src/apps/routes.clj +++ b/src/apps/routes.clj @@ -42,6 +42,7 @@ :tags [{:name "service-info", :description "Service Status Information"} {:name "callbacks", :description "General callback endpoints"} {:name "app-categories", :description "App Category endpoints."} + {:name "app-communities", :description "App Community endpoints."} {:name "app-hierarchies", :description "App Hierarchy endpoints."} {:name "app-element-types", :description "App Element endpoints."} {:name "apps", :description "App endpoints."} @@ -62,6 +63,7 @@ {:name "admin-apps", :description "Admin App endpoints."} {:name "admin-app-metadata", :description "Admin App Metadata endpoints."} {:name "admin-categories", :description "Admin App Category endpoints."} + {:name "admin-communities", :description "Admin App Community endpoints."} {:name "admin-ontologies", :description "Admin App Ontology endpoints."} {:name "admin-container-images", :description "Admin Tool Docker Images endpoints."} {:name "admin-data-containers", :description "Admin Docker Data Container endpoints."} @@ -93,6 +95,9 @@ (context "/apps/categories" [] :tags ["app-categories"] app-category-routes/app-categories) + (context "/apps/communities" [] + :tags ["app-communities"] + app-category-routes/app-communities) (context "/apps/hierarchies" [] :tags ["app-hierarchies"] app-category-routes/app-hierarchies) @@ -150,6 +155,9 @@ (context "/admin/apps/categories" [] :tags ["admin-categories"] admin-routes/admin-categories) + (context "/admin/apps/communities" [] + :tags ["admin-communities"] + admin-routes/admin-communities) (context "/admin/apps/:app-id/metadata" [] :tags ["admin-app-metadata"] metadata-routes/admin-app-metadata) diff --git a/src/apps/routes/admin.clj b/src/apps/routes/admin.clj index 13f1dbbf..5451664a 100644 --- a/src/apps/routes/admin.clj +++ b/src/apps/routes/admin.clj @@ -253,6 +253,19 @@ on the fields included in the request." (ok (apps/admin-update-category current-user system-id (assoc body :id category-id)))))) +(defroutes admin-communities + + (GET "/:community-id/apps" [] + :path-params [community-id :- AppCommunityGroupNameParam] + :query [params AdminAppListingPagingParams] + :return AdminAppListing + :summary "List Apps in a Community" + :description (str "Lists all of the apps under an App Community that are visible to an admin." + (get-endpoint-delegate-block + "metadata" + "POST /avus/filter-targets")) + (ok (coerce! AdminAppListing (apps/admin-list-apps-in-community current-user community-id params))))) + (defroutes admin-ontologies (GET "/" [] diff --git a/src/apps/routes/apps/categories.clj b/src/apps/routes/apps/categories.clj index 12885d1b..782de1aa 100644 --- a/src/apps/routes/apps/categories.clj +++ b/src/apps/routes/apps/categories.clj @@ -91,3 +91,18 @@ (ok (coerce! AppListing (listings/get-unclassified-app-listing current-user root-iri attr params)))) (undocumented (route/not-found (service/unrecognized-path-response)))) + +(defroutes app-communities + + (GET "/:community-id/apps" [] + :path-params [community-id :- AppCommunityGroupNameParam] + :query [params AppListingPagingParams] + :return AppListing + :summary "List Apps in a Community" + :description (str "Lists all of the apps under an App Community that are visible to the user." + (get-endpoint-delegate-block + "metadata" + "POST /avus/filter-targets")) + (ok (coerce! AppListing (apps/list-apps-in-community current-user community-id params)))) + + (undocumented (route/not-found (service/unrecognized-path-response)))) diff --git a/src/apps/routes/schemas/app/category.clj b/src/apps/routes/schemas/app/category.clj index 2ec26caa..b35d91a5 100644 --- a/src/apps/routes/schemas/app/category.clj +++ b/src/apps/routes/schemas/app/category.clj @@ -14,6 +14,7 @@ (:import [java.util Date UUID])) (def AppCategoryNameParam (describe String "The App Category's name")) +(def AppCommunityGroupNameParam (describe String "The full group name of the App Community")) (defschema CategoryListingParams (merge SecuredQueryParamsEmailRequired @@ -29,6 +30,11 @@ (optional-key :name) (describe [String] "Category names to search for."))) +(defschema AdminAppListingPagingParams + (assoc AppListingPagingParams + SortFieldOptionalKey + (describe (apply enum AdminAppListingValidSortFields) SortFieldDocs))) + (defschema AppCategoryId {:system_id SystemId diff --git a/src/apps/service/apps.clj b/src/apps/service/apps.clj index 038d7c3e..d9f01b60 100644 --- a/src/apps/service/apps.clj +++ b/src/apps/service/apps.clj @@ -91,6 +91,14 @@ [user ontology-version root-iri attr params] (.adminListAppsUnderHierarchy (get-apps-client user) ontology-version root-iri attr params)) +(defn list-apps-in-community + [user community-id params] + (.listAppsInCommunity (get-apps-client user) community-id params)) + +(defn admin-list-apps-in-community + [user community-id params] + (.adminListAppsInCommunity (get-apps-client user) community-id params)) + (defn search-apps [user {:keys [search] :as params}] (.searchApps (get-apps-client user) search params)) diff --git a/src/apps/service/apps/agave.clj b/src/apps/service/apps/agave.clj index ca5bd6c7..f804fccf 100644 --- a/src/apps/service/apps/agave.clj +++ b/src/apps/service/apps/agave.clj @@ -94,6 +94,19 @@ (listings/list-apps-with-ontology agave root-iri params true) (.emptyAppListing agave)))) + ;; Since Agave doesn't list apps under ontology hierarchies, we'll use the ontology listing with communities for now. + (listAppsInCommunity [self community-id params] + (when (user-has-access-token?) + (if (apps-util/app-type-qualifies? self params) + (listings/list-apps-with-ontology agave community-id params false) + (.emptyAppListing agave)))) + + (adminListAppsInCommunity [self community-id params] + (when (user-has-access-token?) + (if (apps-util/app-type-qualifies? self params) + (listings/list-apps-with-ontology agave community-id params true) + (.emptyAppListing agave)))) + (searchApps [self search-term params] (when (user-has-access-token?) (if (apps-util/app-type-qualifies? self params) diff --git a/src/apps/service/apps/combined.clj b/src/apps/service/apps/combined.clj index 4ae7400a..dbf16e3c 100644 --- a/src/apps/service/apps/combined.clj +++ b/src/apps/service/apps/combined.clj @@ -51,6 +51,18 @@ (remove nil?) (util/combine-app-listings params)))) + (listAppsInCommunity [_ community-id params] + (let [unpaged-params (dissoc params :limit :offset)] + (->> (map #(.listAppsInCommunity % community-id unpaged-params) clients) + (remove nil?) + (util/combine-app-listings params)))) + + (adminListAppsInCommunity [_ community-id params] + (let [unpaged-params (dissoc params :limit :offset)] + (->> (map #(.adminListAppsInCommunity % community-id unpaged-params) clients) + (remove nil?) + (util/combine-app-listings params)))) + (searchApps [_ search-term params] (->> (map #(.searchApps % search-term (select-keys params [:search :app-type])) clients) (remove nil?) diff --git a/src/apps/service/apps/de.clj b/src/apps/service/apps/de.clj index 5bcf93ce..32549db9 100644 --- a/src/apps/service/apps/de.clj +++ b/src/apps/service/apps/de.clj @@ -58,6 +58,12 @@ (adminListAppsUnderHierarchy [_ ontology-version root-iri attr params] (listings/list-apps-under-hierarchy user ontology-version root-iri attr params true)) + (listAppsInCommunity [_ community-id params] + (listings/list-apps-in-community user community-id params false)) + + (adminListAppsInCommunity [_ community-id params] + (listings/list-apps-in-community user community-id params true)) + (searchApps [_ _ params] (listings/list-apps user params false)) diff --git a/src/apps/service/apps/de/listings.clj b/src/apps/service/apps/de/listings.clj index b36badb0..3e48f03f 100644 --- a/src/apps/service/apps/de/listings.clj +++ b/src/apps/service/apps/de/listings.clj @@ -315,6 +315,13 @@ :value (workspace-metadata-beta-value)}] (set (metadata-client/filter-by-avus username app-ids [beta-avu])))) +(defn- filter-app-ids-by-community + "Filters the given list of app-ids into a set containing the ids of apps tagged with the given community-id" + [username community-id app-ids] + (let [community-avu {:attr (workspace-metadata-communities-attr) + :value community-id}] + (set (metadata-client/filter-by-avus username app-ids [community-avu])))) + (defn- app-listing-by-id [{:keys [username shortUsername]} params perms app-ids admin?] (let [workspace (get-optional-workspace username) @@ -365,6 +372,11 @@ (let [metadata-filter (partial metadata-client/filter-unclassified username ontology-version root-iri attr)] (apps-listing-with-metadata-filter user params metadata-filter admin?)))) +(defn list-apps-in-community + [{:keys [username] :as user} community-id params admin?] + (let [metadata-filter (partial filter-app-ids-by-community username community-id)] + (apps-listing-with-metadata-filter user params metadata-filter admin?))) + (defn- list-apps-in-virtual-group "Formats a listing for a virtual group." [{:keys [shortUsername] :as user} workspace group-id perms {:keys [public-app-ids] :as params}] diff --git a/src/apps/util/config.clj b/src/apps/util/config.clj index f511bb30..29c3d3b3 100644 --- a/src/apps/util/config.clj +++ b/src/apps/util/config.clj @@ -158,6 +158,11 @@ [props config-valid configs] "apps.workspace.metadata.category.attrs" ["rdf:type", "http://edamontology.org/has_topic"]) +(cc/defprop-optstr workspace-metadata-communities-attr + "The attr of an App Community tag AVU." + [props config-valid configs] + "apps.workspace.metadata.communities.attr" "cyverse-community") + (cc/defprop-str uid-domain "The domain name to append to the user identifier to get the fully qualified user identifier."