Skip to content

Commit 8c1dbe1

Browse files
committed
feat: 🚧 authorize app [CS-35317]
1 parent 8e3b86c commit 8c1dbe1

File tree

5 files changed

+210
-1
lines changed

5 files changed

+210
-1
lines changed

lib/app/index.js

Lines changed: 76 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ import error from '../core/contentstackError'
33
import { create, deleteEntity, fetch, fetchAll, update } from '../entity'
44
import { Hosting } from './hosting'
55
import { Installation } from './installation'
6-
import { Request } from './request'
76

87
export function App (http, data) {
98
http.defaults.versioningStrategy = undefined
@@ -252,6 +251,50 @@ export function App (http, data) {
252251
throw error(err)
253252
}
254253
}
254+
/**
255+
* @description The App authorization allow to authorize app for specific scope.
256+
* @returns Promise<Response>
257+
* @param {string} param.responseType Desired grant type
258+
* @param {string} param.clientId Client id of the app
259+
* @param {string} param.redirectUri Redirect URL of the app
260+
* @param {string} param.scope Scopes of the app
261+
* @param {string} param.state Local state provided by the client
262+
*
263+
* @memberof App
264+
* @func authorize
265+
*
266+
* @example
267+
* import * as contentstack from '@contentstack/management'
268+
* const client = contentstack.client({ authtoken: 'TOKEN'})
269+
*
270+
* client.organization('organization_uid').app('app_uid').authorize()
271+
* .then((response) => console.log(response))
272+
*
273+
*/
274+
this.authorize = async ({ responseType, clientId, redirectUri, scope, state }) => {
275+
try {
276+
const headers = {
277+
headers: { ...cloneDeep(this.params) }
278+
}
279+
const content = {
280+
response_type: responseType,
281+
client_id: clientId,
282+
redirect_uri: redirectUri,
283+
scope: scope
284+
}
285+
if (state) {
286+
content.state = state
287+
}
288+
const response = await http.post(`${this.urlPath}/authorize`, content, headers)
289+
if (response.data) {
290+
return response.data
291+
} else {
292+
throw error(response)
293+
}
294+
} catch (err) {
295+
throw error(err)
296+
}
297+
}
255298
} else {
256299
/**
257300
* @description The create manifest call is used for creating a new app/manifest in your Contentstack organization.
@@ -299,6 +342,38 @@ export function App (http, data) {
299342
*
300343
*/
301344
this.findAll = fetchAll(http, AppCollection, this.params)
345+
346+
/**
347+
* @description To get the apps list of authorized apps for the particular organization
348+
* @memberof Organization
349+
* @func authorizedApps
350+
* @param {number} skip - Offset for skipping content in the response.
351+
* @param {number} limit - Limit on api response to provide content in list.
352+
* @example
353+
* import * as contentstack from '@contentstack/management'
354+
* const client = contentstack.client()
355+
*
356+
* client.organization('organization_uid').authorizedApps({ skip: 10 })
357+
* .then((roles) => console.log(roles))
358+
*
359+
*/
360+
this.findAllAuthorized = async (param = {}) => {
361+
const headers = {
362+
headers: { ...cloneDeep(this.params) }
363+
}
364+
365+
headers.params = { ...param }
366+
try {
367+
const response = await http.get(`/authorized-apps`, headers)
368+
if (response.data) {
369+
return response.data
370+
} else {
371+
return error(response)
372+
}
373+
} catch (err) {
374+
return error(err)
375+
}
376+
}
302377
}
303378
}
304379
return this

test/api/app-test.js

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,20 @@ describe('Apps api Test', () => {
3939
.catch(done)
4040
})
4141

42+
it('Fetch all authorized apps test', done => {
43+
client.organization(orgID).app().findAllAuthorized()
44+
.then((apps) => {
45+
for (const index in apps.data) {
46+
const appObject = apps.data[index]
47+
expect(appObject.name).to.not.equal(null)
48+
expect(appObject.uid).to.not.equal(null)
49+
expect(appObject.target_type).to.not.equal(null)
50+
}
51+
done()
52+
})
53+
.catch(done)
54+
})
55+
4256
it('Create app test', done => {
4357
client.organization(orgID).app().create(app)
4458
.then((appResponse) => {

test/typescript/app.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,18 @@ export function fetchApp(organization: Organization) {
5656
done()
5757
}).catch(done)
5858
})
59+
test('Find all Authorized Apps', done => {
60+
organization.app().findAllAuthorized()
61+
.then((apps) => {
62+
for (const index in apps.data) {
63+
const appObject = apps.data[index]
64+
expect(appObject.name).to.not.equal(null)
65+
expect(appObject.uid).to.not.equal(null)
66+
expect(appObject.target_type).to.not.equal(null)
67+
}
68+
done()
69+
}).catch(done)
70+
})
5971
})
6072
}
6173

test/unit/apps-test.js

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ describe('Contentstack apps test', () => {
1212
expect(app.urlPath).to.be.equal('/manifests')
1313
expect(app.create).to.not.equal(undefined)
1414
expect(app.findAll).to.not.equal(undefined)
15+
expect(app.findAllAuthorized).to.not.equal(undefined)
1516
expect(app.fetch).to.be.equal(undefined)
1617
expect(app.update).to.be.equal(undefined)
1718
expect(app.delete).to.be.equal(undefined)
@@ -20,6 +21,8 @@ describe('Contentstack apps test', () => {
2021
expect(app.hosting).to.be.equal(undefined)
2122
expect(app.install).to.be.equal(undefined)
2223
expect(app.installation).to.be.equal(undefined)
24+
expect(app.getRequests).to.be.equal(undefined)
25+
expect(app.authorize).to.be.equal(undefined)
2326
done()
2427
})
2528

@@ -29,6 +32,7 @@ describe('Contentstack apps test', () => {
2932
expect(app.urlPath).to.be.equal(`/manifests/${uid}`)
3033
expect(app.create).to.be.equal(undefined)
3134
expect(app.findAll).to.be.equal(undefined)
35+
expect(app.findAllAuthorized).to.be.equal(undefined)
3236
expect(app.fetch).to.not.equal(undefined)
3337
expect(app.update).to.not.equal(undefined)
3438
expect(app.delete).to.not.equal(undefined)
@@ -37,6 +41,8 @@ describe('Contentstack apps test', () => {
3741
expect(app.hosting).to.not.equal(undefined)
3842
expect(app.install).to.not.equal(undefined)
3943
expect(app.installation).to.not.equal(undefined)
44+
expect(app.getRequests).to.not.equal(undefined)
45+
expect(app.authorize).to.not.equal(undefined)
4046
expect(app.hosting()).to.not.equal(undefined)
4147
expect(app.installation()).to.not.equal(undefined)
4248
expect(app.installation(uid)).to.not.equal(undefined)
@@ -50,6 +56,7 @@ describe('Contentstack apps test', () => {
5056
expect(app.urlPath).to.be.equal(`/manifests/${uid}`)
5157
expect(app.create).to.be.equal(undefined)
5258
expect(app.findAll).to.be.equal(undefined)
59+
expect(app.findAllAuthorized).to.be.equal(undefined)
5360
expect(app.fetch).to.not.equal(undefined)
5461
expect(app.update).to.not.equal(undefined)
5562
expect(app.delete).to.not.equal(undefined)
@@ -58,6 +65,8 @@ describe('Contentstack apps test', () => {
5865
expect(app.hosting).to.not.equal(undefined)
5966
expect(app.install).to.not.equal(undefined)
6067
expect(app.installation).to.not.equal(undefined)
68+
expect(app.getRequests).to.not.equal(undefined)
69+
expect(app.authorize).to.not.equal(undefined)
6170
done()
6271
})
6372

@@ -146,6 +155,38 @@ describe('Contentstack apps test', () => {
146155
.catch(done)
147156
})
148157

158+
it('Get all authorized apps in organization test', done => {
159+
const content = {
160+
visibility: 'private',
161+
description: 'This is a test App.',
162+
name: 'New App',
163+
org_id: 'org_uid',
164+
created_at: '2021-07-20T13:34:54.791Z',
165+
updated_at: '2021-07-27T14:05:19.452Z',
166+
id: 'id'
167+
}
168+
const mock = new MockAdapter(Axios)
169+
mock.onGet(`/authorized-apps`).reply(200, {
170+
data: [
171+
content
172+
]
173+
})
174+
175+
makeApp({})
176+
.findAllAuthorized()
177+
.then((response) => {
178+
expect(response.data[0].visibility).to.be.equal(content.visibility)
179+
expect(response.data[0].description).to.be.equal(content.description)
180+
expect(response.data[0].name).to.be.equal(content.name)
181+
expect(response.data[0].org_id).to.be.equal(content.org_id)
182+
expect(response.data[0].created_at).to.be.equal(content.created_at)
183+
expect(response.data[0].updated_at).to.be.equal(content.updated_at)
184+
expect(response.data[0].id).to.be.equal(content.id)
185+
done()
186+
})
187+
.catch(done)
188+
})
189+
149190
it('Get oAuth configuration test', done => {
150191
const mock = new MockAdapter(Axios)
151192
const uid = appMock.uid
@@ -231,6 +272,36 @@ describe('Contentstack apps test', () => {
231272
})
232273
.catch(done)
233274
})
275+
it('test authorize app', (done) => {
276+
const uid = appMock.uid
277+
const mock = new MockAdapter(Axios)
278+
mock.onPost(`/manifests/${appMock.uid}/authorize`).reply(200, {
279+
data: { redirect_uri: 'uri' }
280+
})
281+
282+
makeApp({ data: { uid } })
283+
.authorize({ responseType: 'type', clientId: 'id', redirectUri: 'uri', scope: 'scope' })
284+
.then((response) => {
285+
expect(response.data.redirect_uri).to.be.equal('uri')
286+
done()
287+
})
288+
.catch(done)
289+
})
290+
it('test authorize app fail request', (done) => {
291+
const uid = appMock.uid
292+
const mock = new MockAdapter(Axios)
293+
mock.onPost(`/manifests/${appMock.uid}/authorize`).reply(400, {
294+
295+
})
296+
297+
makeApp({ data: { uid } })
298+
.authorize({ state: 'state', responseType: 'type', clientId: 'id', redirectUri: 'uri', scope: 'scope' })
299+
.then(done)
300+
.catch((error) => {
301+
expect(error).to.not.equal(undefined)
302+
done()
303+
})
304+
})
234305
it('test fetch request for app uid fail request', (done) => {
235306
const uid = appMock.uid
236307
const mock = new MockAdapter(Axios)
@@ -246,6 +317,35 @@ describe('Contentstack apps test', () => {
246317
done()
247318
})
248319
})
320+
it('test authorize app fail request', (done) => {
321+
const uid = appMock.uid
322+
const mock = new MockAdapter(Axios)
323+
mock.onPost(`/manifests/${appMock.uid}/requests`).reply(400, {
324+
325+
})
326+
327+
makeApp({ data: { uid } })
328+
.getRequests()
329+
.then(done)
330+
.catch((error) => {
331+
expect(error).to.not.equal(undefined)
332+
done()
333+
})
334+
})
335+
it('Get all authorized apps in organization fail request', done => {
336+
const mock = new MockAdapter(Axios)
337+
mock.onGet(`/authorized-apps`).reply(400, {
338+
339+
})
340+
341+
makeApp({})
342+
.findAllAuthorized()
343+
.then(done)
344+
.catch((error) => {
345+
expect(error).to.not.equal(undefined)
346+
done()
347+
})
348+
})
249349
})
250350

251351
function checkApp (app) {

types/app/index.d.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { ContentstackCollection } from "../contentstackCollection";
22
import { AnyProperty, SystemFields } from "../utility/fields";
33
import { Creatable, SystemFunction } from "../utility/operations";
4+
import { Pagination } from '../utility/pagination';
45
import { Hosting } from './hosting';
56
import { Installation, Installations } from "./installation";
67

@@ -11,10 +12,17 @@ export interface App extends SystemFields, SystemFunction<App> {
1112
installation(): Installations
1213
installation(uid: string): Installation
1314
hosting(): Hosting
15+
authorize(param: {
16+
responseType: string,
17+
clientId: string,
18+
redirectUri: string,
19+
scope: string,
20+
state: string }): Promise<AnyProperty>
1421
}
1522

1623
export interface Apps extends Creatable<App, AppData> {
1724
findAll(param?: AnyProperty): Promise<ContentstackCollection<App>>
25+
findAllAuthorized(param?: Pagination & AnyProperty): Promise<AnyProperty>
1826
}
1927

2028
export interface AppData extends AnyProperty {

0 commit comments

Comments
 (0)