Skip to content

Commit 603298c

Browse files
Merge pull request #75 from SachiniSiriwardene/login
Add role validation checks and portal settings pages
2 parents dcbd249 + a93b3a5 commit 603298c

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

46 files changed

+1892
-182
lines changed

.github/workflows/build-and-release.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ jobs:
6262
mkdir -p ./temp-dir/developer-portal
6363
6464
# Copy the additional files and folders into developer-portal
65-
cp -r bin artifacts InstallationGuide.md QuickStart.md README.md config.json ./temp-dir/developer-portal/
65+
cp -r bin/startup.sh bin/startup.bat artifacts InstallationGuide.md QuickStart.md README.md config.json ./temp-dir/developer-portal/
6666
6767
# Move the current dist file into developer-portal
6868
mv "$file" ./temp-dir/developer-portal/

artifacts/script.sql

+10
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,15 @@ CREATE TABLE "DP_ORGANIZATION" (
1515
"BUSINESS_OWNER" VARCHAR(256) NOT NULL,
1616
"BUSINESS_OWNER_CONTACT" VARCHAR(256) NOT NULL,
1717
"BUSINESS_OWNER_EMAIL" VARCHAR(256) NOT NULL,
18+
"DEV_PORTAL_URL_IDENTIFIER" VARCHAR(255),
19+
"ROLE_CLAIM_NAME" VARCHAR(255) NOT NULL,
20+
"GROUPS_CLAIM_NAME" VARCHAR(255) NOT NULL,
21+
"ORGANIZATION_CLAIM_NAME" VARCHAR(255) NOT NULL,
22+
"ORGANIZATION_IDENTIFIER" VARCHAR(255) NOT NULL,
23+
"ADMIN_ROLE" VARCHAR(255) NOT NULL,
24+
"SUBSCRIBER_ROLE" VARCHAR(255) NOT NULL,
25+
"GROUP_CLAIM_NAME" VARCHAR(255) NOT NULL,
26+
"SUPER_ADMIN_ROLE" VARCHAR(255) NOT NULL
1827
UNIQUE ("ORG_NAME"),
1928
PRIMARY KEY("ORG_ID")
2029
);
@@ -66,6 +75,7 @@ CREATE TABLE "DP_API_METADATA" (
6675
"PRODUCTION_URL" VARCHAR(256),
6776
"SANDBOX_URL" VARCHAR(256),
6877
"METADATA_SEARCH" JSON,
78+
"PROVIDER" VARCHAR(256)
6979
PRIMARY KEY ("API_ID"),
7080
FOREIGN KEY ("ORG_ID") REFERENCES "DP_ORGANIZATION"("ORG_ID") ON DELETE CASCADE
7181
);

config.json

+42-5
Original file line numberDiff line numberDiff line change
@@ -3,19 +3,56 @@
33
"pathToContent": "../src/",
44
"mode": "production",
55
"controlPlane" : {
6-
"url": "https://localhost:9443/api/am/devportal/v3",
7-
"accessToken" :"Bearer <control-plane-access-token>",
8-
"disableCertValidation": false,
6+
"url": "https://127.0.0.1:9443/api/am/devportal/v3",
7+
"disableCertValidation": true,
98
"pathToCertificate": "../api-developer-portal/conf/security/client-truststore.pem"
109
},
1110
"db": {
1211
"username": "postgres",
1312
"password": "postgres",
14-
"database": "devportal",
13+
"database": "DEVPORTAL_NEWSCHEMA",
1514
"host": "localhost",
1615
"dialect": "postgres"
1716
},
1817
"providerURL": {
1918
"AWS": "https://aws.amazon.com"
20-
}
19+
},
20+
"identityProvider" : {
21+
"name": "IS",
22+
"issuer": "https://127.0.0.1:9443/oauth2/token",
23+
"authorizationURL": "https://localhost:9443/oauth2/authorize",
24+
"tokenURL": "https://127.0.0.1:9443/oauth2/token",
25+
"userInfoURL": "https://localhost:9443/oauth2/userinfo",
26+
"clientId": "meVRlVAkUoVufXXjN3aUk72PVF8a",
27+
"callbackURL": "http://localhost:3000/ACME/callback",
28+
"scope": "openid email profile apim:subscribe role",
29+
"signUpURL": "",
30+
"logoutURL": "https://localhost:9443/oidc/logout",
31+
"logoutRedirectURI": "http://localhost:3000/ACME"
32+
},
33+
"roleClaim": "roles",
34+
"orgIDClaim": "organizationID",
35+
"groupsClaim": "groups",
36+
"adminRole": "admin",
37+
"subscriberRole": "Interna/subscriber",
38+
"superAdminRole": "superAdmin",
39+
"authenticatedPages": [
40+
"/*/configure",
41+
"/portal",
42+
"/*/applications",
43+
"/*/applications/*",
44+
"/*/api/*",
45+
"/*/myAPIs",
46+
"/*/myAPIs/*"
47+
48+
],
49+
"authorizedPages": [
50+
"/*/applications",
51+
"/*/applications/*",
52+
"/*/configure",
53+
"/portal",
54+
"/*/api/*",
55+
"/*/myAPIs",
56+
"/*/myAPIs/*"
57+
]
2158
}

package-lock.json

+13
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

+4-5
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
"express": "^4.21.0",
3434
"express-handlebars": "^7.1.3",
3535
"express-session": "^1.18.0",
36+
"express-validator": "^7.2.0",
3637
"fs-extra": "^11.2.0",
3738
"graphiql": "^3.7.1",
3839
"graphql": "^16.9.0",
@@ -69,15 +70,13 @@
6970
],
7071
"assets": [
7172
"src/pages/**/*",
72-
"src/styles/**/*"
73+
"src/styles/**/*",
74+
"node_modules/axios/**/*"
7375
],
7476
"targets": [
7577
"node18-macos-x64",
7678
"node18-linux-x64",
77-
"node18-win-x64",
78-
"node18-macos-x86",
79-
"node18-linux-x86",
80-
"node18-win-x86"
79+
"node18-win-x64"
8180
],
8281
"outputPath": "dist"
8382
},

src/app.js

+2
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ const config = require(process.cwd() + '/config.json');
3333
const Handlebars = require('handlebars');
3434
const constants = require("./utils/constants");
3535
const designRoute = require('./routes/designModeRoute');
36+
const settingsRoute = require('./routes/configureRoute');
3637

3738
const app = express();
3839
const secret = crypto.randomBytes(64).toString('hex');
@@ -93,6 +94,7 @@ if (config.mode === constants.DEV_MODE) {
9394
app.use(constants.ROUTE.DEFAULT, applicationContent);
9495
app.use(constants.ROUTE.DEFAULT, orgContent);
9596
app.use(constants.ROUTE.DEFAULT, myAPIs);
97+
app.use(constants.ROUTE.DEFAULT, settingsRoute);
9698
app.use(constants.ROUTE.DEFAULT, customContent);
9799
}
98100

src/controllers/apiContentController.js

+8-7
Original file line numberDiff line numberDiff line change
@@ -51,11 +51,7 @@ const loadAPIs = async (req, res) => {
5151
html = await renderTemplateFromAPI(templateContent, orgID, orgName, "pages/apis");
5252
} catch (error) {
5353
console.error(`Error while loading organization content ,${error}`);
54-
console.log("Rendering default api listing page from file");
55-
const templateContent = {
56-
baseUrl: constants.BASE_URL + config.port
57-
}
58-
html = renderTemplate(filePrefix + 'pages/apis/page.hbs', filePrefix + 'layout/main.hbs', templateContent, false);
54+
return res.redirect('/configure');
5955
}
6056
}
6157
res.send(html);
@@ -137,7 +133,7 @@ const loadAPIContent = async (req, res) => {
137133

138134
const loadSubscriptionPlan = async (req, res, policyId) => {
139135
try {
140-
return await util.invokeApiRequest('GET', `${config.controlPlane.url}/throttling-policies/subscription/${policyId}`);
136+
return await util.invokeApiRequest(req, 'GET', `${config.controlPlane.url}/throttling-policies/subscription/${policyId}`);
141137
} catch (error) {
142138
console.error("Error occurred while loading subscription plans", error);
143139
util.handleError(res, error);
@@ -166,7 +162,12 @@ const loadTryOutPage = async (req, res) => {
166162
const orgID = await adminDao.getOrgId(orgName);
167163
const apiID = await apiDao.getAPIId(apiName);
168164
const metaData = await loadAPIMetaData(req, orgID, apiID);
169-
let apiDefinition = await apiDao.getAPIFile(constants.FILE_NAME.API_DEFINITION_FILE_NAME, orgID, apiID);
165+
let apiDefinition;
166+
if (metaData.apiType === "GraphQL") {
167+
apiDefinition = await apiDao.getAPIFile(constants.FILE_NAME.API_DEFINITION_GRAPHQL, orgID, apiID);
168+
} else {
169+
apiDefinition = await apiDao.getAPIFile(constants.FILE_NAME.API_DEFINITION_FILE_NAME, orgID, apiID);
170+
}
170171
apiDefinition = apiDefinition.API_FILE.toString(constants.CHARSET_UTF8);
171172
const templateContent = {
172173
apiMetadata: metaData,

src/controllers/applicationsContentController.js

+40-22
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,21 @@
1+
/*
2+
* Copyright (c) 2024, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
3+
*
4+
* WSO2 Inc. licenses this file to you under the Apache License,
5+
* Version 2.0 (the "License"); you may not use this file except
6+
* in compliance with the License.
7+
* You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing,
12+
* software distributed under the License is distributed on an
13+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
* KIND, either express or implied. See the License for the
15+
* specific language governing permissions and limitations
16+
* under the License.
17+
*/
18+
/* eslint-disable no-undef */
119
const { renderTemplate, renderGivenTemplate, loadLayoutFromAPI, invokeApiRequest } = require('../utils/util');
220
const config = require(process.cwd() + '/config');
321
const constants = require('../utils/constants');
@@ -33,7 +51,7 @@ const loadApplications = async (req, res) => {
3351
else {
3452
const orgName = req.params.orgName;
3553
const orgID = await orgIDValue(orgName);
36-
metaData = await getAPIMApplications();
54+
metaData = await getAPIMApplications(req);
3755
templateContent = {
3856
applicationsMetadata: metaData,
3957
baseUrl: '/' + orgName
@@ -51,8 +69,8 @@ async function getMockApplications() {
5169
return mockApplicationsMetaData.list;
5270
}
5371

54-
async function getAPIMApplications() {
55-
const responseData = await invokeApiRequest('GET', controlPlaneUrl + '/applications', null, null);
72+
async function getAPIMApplications(req) {
73+
const responseData = await invokeApiRequest(req, 'GET', controlPlaneUrl + '/applications', null, null);
5674
return responseData.list;
5775
}
5876

@@ -71,7 +89,7 @@ const loadThrottlingPolicies = async (req, res) => {
7189
else {
7290
const orgName = req.params.orgName;
7391
const orgID = await orgIDValue(orgName);
74-
metaData = await getAPIMThrottlingPolicies();
92+
metaData = await getAPIMThrottlingPolicies(req);
7593
templateContent = {
7694
throttlingPoliciesMetadata: metaData,
7795
baseUrl: '/' + orgName
@@ -90,8 +108,8 @@ async function getMockThrottlingPolicies() {
90108
return mockThrottlingPoliciesMetaData.list;
91109
}
92110

93-
async function getAPIMThrottlingPolicies() {
94-
const responseData = await invokeApiRequest('GET', controlPlaneUrl + '/throttling-policies/application', null, null);
111+
async function getAPIMThrottlingPolicies(req) {
112+
const responseData = await invokeApiRequest(req, 'GET', controlPlaneUrl + '/throttling-policies/application', null, null);
95113
return responseData.list;
96114
}
97115

@@ -113,9 +131,9 @@ const loadApplication = async (req, res) => {
113131
} else {
114132
const orgName = req.params.orgName;
115133
const orgID = await orgIDValue(orgName);
116-
metaData = await getAPIMApplication(applicationId);
117-
const allApis = await getAllAPIs();
118-
const subApis = await getSubscribedApis(applicationId);
134+
metaData = await getAPIMApplication(req, applicationId);
135+
const allApis = await getAllAPIs(req);
136+
const subApis = await getSubscribedApis(req, applicationId);
119137
const subApiMap = new Map();
120138
subApis.list.forEach(subApi => subApiMap.set(subApi.apiId, { policy: subApi.throttlingPolicy, id: subApi.subscriptionId }));
121139
const apiList = [];
@@ -142,7 +160,7 @@ const loadApplication = async (req, res) => {
142160

143161
});
144162

145-
kMmetaData = await getAPIMKeyManagers();
163+
kMmetaData = await getAPIMKeyManagers(req);
146164
templateContent = {
147165
applicationMetadata: metaData,
148166
keyManagersMetadata: kMmetaData,
@@ -162,28 +180,28 @@ const loadApplication = async (req, res) => {
162180
}
163181

164182

165-
async function getAllAPIs() {
183+
async function getAllAPIs(req) {
166184
try {
167-
return await util.invokeApiRequest('GET', `${controlPlaneUrl}/apis`);
185+
return await util.invokeApiRequest(req, 'GET', `${controlPlaneUrl}/apis`);
168186
} catch (error) {
169187
console.error("Error occurred while loading APIs", error);
170188
throw error;
171189
}
172190
}
173191

174-
const getSubscribedApis = async (appId) => {
192+
const getSubscribedApis = async (req, appId) => {
175193
try {
176-
return await util.invokeApiRequest('GET', `${controlPlaneUrl}/subscriptions?applicationId=${appId}`);
194+
return await util.invokeApiRequest(req, 'GET', `${controlPlaneUrl}/subscriptions?applicationId=${appId}`);
177195
} catch (error) {
178196
console.error("Error occurred while loading subscriptions", error);
179197
throw error;
180198
}
181199
}
182200

183201
const loadApplicationForEdit = async (req, res) => {
184-
const orgName = req.params.orgName;
202+
185203
const applicationId = req.params.applicationid;
186-
let html, templateContent, metaData;
204+
let html, templateContent, metaData, throttlingMetaData;
187205
if (config.mode === constants.DEV_MODE) {
188206
metaData = await getMockApplication();
189207
throttlingMetaData = await getMockThrottlingPolicies();
@@ -196,8 +214,8 @@ const loadApplicationForEdit = async (req, res) => {
196214
} else {
197215
const orgName = req.params.orgName;
198216
const orgID = await orgIDValue(orgName);
199-
metaData = await getAPIMApplication(applicationId);
200-
throttlingMetaData = await getAPIMThrottlingPolicies();
217+
metaData = await getAPIMApplication(req, applicationId);
218+
throttlingMetaData = await getAPIMThrottlingPolicies(req);
201219
templateContent = {
202220
applicationMetadata: metaData,
203221
throttlingPoliciesMetadata: throttlingMetaData,
@@ -223,13 +241,13 @@ async function getMockKeyManagers() {
223241
return mockKeyManagersMetaData.list;
224242
}
225243

226-
async function getAPIMApplication(applicationId) {
227-
const responseData = await invokeApiRequest('GET', controlPlaneUrl + '/applications/' + applicationId, null, null);
244+
async function getAPIMApplication(req, applicationId) {
245+
const responseData = await invokeApiRequest(req, 'GET', controlPlaneUrl + '/applications/' + applicationId, null, null);
228246
return responseData;
229247
}
230248

231-
async function getAPIMKeyManagers() {
232-
const responseData = await invokeApiRequest('GET', controlPlaneUrl + '/key-managers', null, null);
249+
async function getAPIMKeyManagers(req) {
250+
const responseData = await invokeApiRequest(req, 'GET', controlPlaneUrl + '/key-managers', null, null);
233251
return responseData.list;
234252
}
235253

0 commit comments

Comments
 (0)