diff --git a/catalogue/client/grid/grid.less b/catalogue/client/grid/grid.less
index 74603a2ec0..729b67f4b0 100644
--- a/catalogue/client/grid/grid.less
+++ b/catalogue/client/grid/grid.less
@@ -67,6 +67,7 @@
.api-card-created {
color: #777;
font-size: 0.85em;
+ margin-right: 5em;
}
.api-card-info {
@@ -80,6 +81,8 @@
}
.api-card-stats {
- margin-bottom: 0;
+ position: absolute;
+ bottom: 2em;
+ width: 100%;
margin-left: 0.5em;
}
diff --git a/catalogue/client/table/table.html b/catalogue/client/table/table.html
index bf14559ce0..21d25360e8 100644
--- a/catalogue/client/table/table.html
+++ b/catalogue/client/table/table.html
@@ -17,15 +17,20 @@
{{ api.name }}
-
- {{_ "catalogueTable_addedBy" }}
- {{ api.getApiManagersByName }}
-
-
-
- {{_ "catalogueTable_added" }}
- {{ api.relativeCreatedAt }}
-
+ {{# unless api.isPublic }}
+ private
+ {{/ unless }}
+
+
+ {{_ "catalogueTable_addedBy" }}
+ {{ api.getApiManagersByName }}
+
+
+
+ {{_ "catalogueTable_added" }}
+ {{ api.relativeCreatedAt }}
+
+
{{> apiBackendRating api }}
diff --git a/catalogue/client/table/table.less b/catalogue/client/table/table.less
index 4e7f5e056f..f1572386d6 100644
--- a/catalogue/client/table/table.less
+++ b/catalogue/client/table/table.less
@@ -14,5 +14,9 @@
}
.api-catalogue-table-title {
margin-top: 0;
+ display: inline;
+ }
+ .label-align {
+ vertical-align: text-top;
}
}
diff --git a/catalogue/server/publications.js b/catalogue/server/publications.js
index 36a25db073..33d63b1ef2 100644
--- a/catalogue/server/publications.js
+++ b/catalogue/server/publications.js
@@ -1,3 +1,6 @@
+import { Meteor } from 'meteor/meteor';
+import { Roles } from 'meteor/alanning:roles';
+
// Collection imports
import { Apis } from '/apis/collection';
import { ApiBackendRatings } from '/ratings/collection';
@@ -11,16 +14,24 @@ Meteor.publish('catalogue', function ({ filterBy, sortBy, sortDirection }) {
// Get user ID
const userId = this.userId;
+ const userIsAdmin = Roles.userIsInRole(userId, ['admin']);
+
if (userId) {
- // If user logged in
- // Select public and managed APIs
- selector = {
- $or:
- [
- { isPublic: true },
- { managerIds: userId },
- ],
- };
+ if (userIsAdmin) {
+ // Select all APIs
+ selector = {};
+ } else {
+ // If user logged in
+ // Select public, managed APIs & APIs user is authorized to see
+ selector = {
+ $or:
+ [
+ { isPublic: true },
+ { managerIds: userId },
+ { authorizedUserIds: userId },
+ ],
+ };
+ }
}
// Set up query options with empty sort settings
@@ -34,29 +45,42 @@ Meteor.publish('catalogue', function ({ filterBy, sortBy, sortDirection }) {
// Get user bookmarks
const userBookmarks = ApiBookmarks.findOne({ userId });
- // Get bookmarked API IDs
+ // Check userBookmarks exist
if (userBookmarks) {
+ // Get bookmarkedApiIds
const bookmarkedApiIds = userBookmarks.apiIds;
-
- // Set up query object to contain bookmarked API IDs which are public
- selector = {
- $or: [
- {
- $and:
- [// User has bookmarked and API is public
+ // Check if userIsAdmin
+ if (userIsAdmin) {
+ // Show bookmarked APIs (regardless of visibility status)
+ selector = { _id: { $in: bookmarkedApiIds } };
+ } else {
+ // Set up query object to contain bookmarked API IDs which are public
+ selector = {
+ $or: [
+ {
+ $and:
+ [// User has bookmarked and API is public
+ { _id: { $in: bookmarkedApiIds } },
+ { isPublic: true },
+ ],
+ },
+ {
+ $and:
+ [// User has bookmarked and is manager (regardless of public status)
{ _id: { $in: bookmarkedApiIds } },
- { isPublic: true },
- ],
- },
- {
- $and:
- [// User has bookmarked and is manager (regardless of public status)
- { _id: { $in: bookmarkedApiIds } },
- { managerIds: userId },
- ],
- },
- ],
- };
+ { managerIds: userId },
+ ],
+ },
+ {
+ $and:
+ [// User has bookmarked and has view rights to API
+ { _id: { $in: bookmarkedApiIds } },
+ { authorizedUserIds: userId },
+ ],
+ },
+ ],
+ };
+ }
} else {
// If user has no bookmarks, don't return any results
return [];
@@ -79,12 +103,12 @@ Meteor.publish('catalogue', function ({ filterBy, sortBy, sortDirection }) {
return Apis.find(selector, queryOptions);
});
-Meteor.publish('catalogueRatings', function () {
+Meteor.publish('catalogueRatings', () => {
// Find all API Backends
return ApiBackendRatings.find();
});
-Meteor.publish('catalogueBookmarks', function () {
+Meteor.publish('catalogueBookmarks', () => {
// Find all API Backends
return ApiBookmarks.find();
});
diff --git a/core/client/error_templates/forbidden.html b/core/client/error_templates/forbidden.html
new file mode 100644
index 0000000000..1d225e1fd0
--- /dev/null
+++ b/core/client/error_templates/forbidden.html
@@ -0,0 +1,16 @@
+
+
+
+
+ {{_ "forbidden_Title" }}
+
+
+
+
+
+ {{_ "forbidden_Message" }}
+
+
+
+
+
diff --git a/core/client/not_authorized/not_authorized.html b/core/client/error_templates/not_authorized.html
similarity index 100%
rename from core/client/not_authorized/not_authorized.html
rename to core/client/error_templates/not_authorized.html
diff --git a/core/client/not_authorized/not_found.html b/core/client/error_templates/not_found.html
similarity index 100%
rename from core/client/not_authorized/not_found.html
rename to core/client/error_templates/not_found.html
diff --git a/core/client/form_hints/form_hints.js b/core/client/form_hints/form_hints.js
index 3bfc5b558a..e0b63e2411 100644
--- a/core/client/form_hints/form_hints.js
+++ b/core/client/form_hints/form_hints.js
@@ -1,3 +1,7 @@
+import { TAPi18n } from 'meteor/tap:i18n';
+import { InlineHelp } from 'meteor/pahans:inline-help';
+
+
// Initialize help texts
const formHints = {
documentation_link: {
@@ -29,7 +33,7 @@ const formHints = {
options: {
placement: 'left',
},
- }
+ },
};
InlineHelp.initHelp(formHints);
diff --git a/core/client/lib/router.js b/core/client/lib/router.js
index 817bd5bb48..dbafdc7fda 100755
--- a/core/client/lib/router.js
+++ b/core/client/lib/router.js
@@ -45,4 +45,9 @@ Router.map(function() {
layoutTemplate: "masterLayout",
render: "notAuthorized"
});
+ this.route("forbidden", {
+ path: "/forbidden",
+ layoutTemplate: "masterLayout",
+ render: "forbidden"
+ });
});
diff --git a/core/lib/i18n/en.i18n.json b/core/lib/i18n/en.i18n.json
index 446cf36822..2430c2d017 100644
--- a/core/lib/i18n/en.i18n.json
+++ b/core/lib/i18n/en.i18n.json
@@ -115,6 +115,7 @@
"apiSettings_visibilityPanel_title": "Visibility",
"apiSettings_visibility_heading": "Change API visibility",
"apiSettings_visibility_text": "Make this API private or public",
+ "apiSettings_visibility_authorizedUsers": "Give single users permissions to view API even when API is globally marked Private.",
"api_backend_rating_anonymous": "Please log in to vote.",
"apinf_usernotloggedin_error": "Could not find logged in user.",
"apiMonitoring_panelTitle_Monitoring": "API Monitoring",
@@ -230,6 +231,8 @@
"flagApiModal_titleText": "Flag API Backend",
"flagApiSchema_DefunctText": "Defunct",
"flagApiSchema_inappropriateText": "Inappropriate",
+ "forbidden_Title": "403 Forbidden",
+ "forbidden_Message": "You don't have permissions to view this page.",
"homeBody_contactUs_heading": "Contact Us",
"homeBody_contactUs_text": "Contact us to ask anything.",
"homeBody_feature_section_heading1": "Are you an API user?",
diff --git a/proxy_backends/collection/server/publications.js b/proxy_backends/collection/server/publications.js
index 4877dc0bec..f9b40fd65d 100644
--- a/proxy_backends/collection/server/publications.js
+++ b/proxy_backends/collection/server/publications.js
@@ -10,27 +10,13 @@ import { ProxyBackends } from '/proxy_backends/collection';
import _ from 'lodash';
Meteor.publish('apiProxySettings', function (apiId) {
- // TODO: determine how to use 'api.userCanEdit()' helper
- // which uses 'Meteor.userId()' instead of 'this.userId'
-
// Get current userId
const userId = this.userId;
// Check that user is logged in
if (userId) {
- // Get API document
- const api = Apis.findOne(apiId);
-
- // Check if user is API manager
- const userIsManager = _.includes(api.managerIds, userId);
-
- // Check if user is administrator
- const userIsAdmin = Roles.userIsInRole(userId, ['admin']);
-
- // Check if user is authorized to access API proxy settings
- if (userIsManager || userIsAdmin) {
- return ProxyBackends.find({ apiId });
- }
+ // Return APIs proxy settings
+ return ProxyBackends.find({ apiId });
}
// Complete publication execution
@@ -38,7 +24,6 @@ Meteor.publish('apiProxySettings', function (apiId) {
});
Meteor.publish('proxyApis', function () {
-
// TODO: pass proxy Id to this publication ?
// Placeholder for proxy backends
|