Merge pull request #2255 from automatisch/rename-app-auth-clients

refactor: Rename AppAuthClient model as OAuthClient
This commit is contained in:
Ömer Faruk Aydın
2024-12-20 12:46:37 +01:00
committed by GitHub
87 changed files with 844 additions and 814 deletions

View File

@@ -6,14 +6,14 @@ export default async (request, response) => {
.findOne({ key: request.params.appKey }) .findOne({ key: request.params.appKey })
.throwIfNotFound(); .throwIfNotFound();
const appAuthClient = await appConfig const oauthClient = await appConfig
.$relatedQuery('appAuthClients') .$relatedQuery('oauthClients')
.insert(appAuthClientParams(request)); .insert(oauthClientParams(request));
renderObject(response, appAuthClient, { status: 201 }); renderObject(response, oauthClient, { status: 201 });
}; };
const appAuthClientParams = (request) => { const oauthClientParams = (request) => {
const { active, appKey, name, formattedAuthDefaults } = request.body; const { active, appKey, name, formattedAuthDefaults } = request.body;
return { return {

View File

@@ -5,11 +5,11 @@ import app from '../../../../../app.js';
import createAuthTokenByUserId from '../../../../../helpers/create-auth-token-by-user-id.js'; import createAuthTokenByUserId from '../../../../../helpers/create-auth-token-by-user-id.js';
import { createUser } from '../../../../../../test/factories/user.js'; import { createUser } from '../../../../../../test/factories/user.js';
import { createRole } from '../../../../../../test/factories/role.js'; import { createRole } from '../../../../../../test/factories/role.js';
import createAppAuthClientMock from '../../../../../../test/mocks/rest/api/v1/admin/apps/create-auth-client.js'; import createOAuthClientMock from '../../../../../../test/mocks/rest/api/v1/admin/apps/create-oauth-client.js';
import { createAppConfig } from '../../../../../../test/factories/app-config.js'; import { createAppConfig } from '../../../../../../test/factories/app-config.js';
import * as license from '../../../../../helpers/license.ee.js'; import * as license from '../../../../../helpers/license.ee.js';
describe('POST /api/v1/admin/apps/:appKey/auth-clients', () => { describe('POST /api/v1/admin/apps/:appKey/oauth-clients', () => {
let currentUser, adminRole, token; let currentUser, adminRole, token;
beforeEach(async () => { beforeEach(async () => {
@@ -26,7 +26,7 @@ describe('POST /api/v1/admin/apps/:appKey/auth-clients', () => {
key: 'gitlab', key: 'gitlab',
}); });
const appAuthClient = { const oauthClient = {
active: true, active: true,
appKey: 'gitlab', appKey: 'gitlab',
name: 'First auth client', name: 'First auth client',
@@ -39,17 +39,17 @@ describe('POST /api/v1/admin/apps/:appKey/auth-clients', () => {
}; };
const response = await request(app) const response = await request(app)
.post('/api/v1/admin/apps/gitlab/auth-clients') .post('/api/v1/admin/apps/gitlab/oauth-clients')
.set('Authorization', token) .set('Authorization', token)
.send(appAuthClient) .send(oauthClient)
.expect(201); .expect(201);
const expectedPayload = createAppAuthClientMock(appAuthClient); const expectedPayload = createOAuthClientMock(oauthClient);
expect(response.body).toMatchObject(expectedPayload); expect(response.body).toMatchObject(expectedPayload);
}); });
it('should return not found response for not existing app config', async () => { it('should return not found response for not existing app config', async () => {
const appAuthClient = { const oauthClient = {
active: true, active: true,
appKey: 'gitlab', appKey: 'gitlab',
name: 'First auth client', name: 'First auth client',
@@ -62,9 +62,9 @@ describe('POST /api/v1/admin/apps/:appKey/auth-clients', () => {
}; };
await request(app) await request(app)
.post('/api/v1/admin/apps/gitlab/auth-clients') .post('/api/v1/admin/apps/gitlab/oauth-clients')
.set('Authorization', token) .set('Authorization', token)
.send(appAuthClient) .send(oauthClient)
.expect(404); .expect(404);
}); });
@@ -73,14 +73,14 @@ describe('POST /api/v1/admin/apps/:appKey/auth-clients', () => {
key: 'gitlab', key: 'gitlab',
}); });
const appAuthClient = { const oauthClient = {
appKey: 'gitlab', appKey: 'gitlab',
}; };
const response = await request(app) const response = await request(app)
.post('/api/v1/admin/apps/gitlab/auth-clients') .post('/api/v1/admin/apps/gitlab/oauth-clients')
.set('Authorization', token) .set('Authorization', token)
.send(appAuthClient) .send(oauthClient)
.expect(422); .expect(422);
expect(response.body.meta.type).toStrictEqual('ModelValidation'); expect(response.body.meta.type).toStrictEqual('ModelValidation');

View File

@@ -1,11 +0,0 @@
import { renderObject } from '../../../../../helpers/renderer.js';
import AppAuthClient from '../../../../../models/app-auth-client.js';
export default async (request, response) => {
const appAuthClient = await AppAuthClient.query()
.findById(request.params.appAuthClientId)
.where({ app_key: request.params.appKey })
.throwIfNotFound();
renderObject(response, appAuthClient);
};

View File

@@ -0,0 +1,11 @@
import { renderObject } from '../../../../../helpers/renderer.js';
import OAuthClient from '../../../../../models/oauth-client.js';
export default async (request, response) => {
const oauthClient = await OAuthClient.query()
.findById(request.params.oauthClientId)
.where({ app_key: request.params.appKey })
.throwIfNotFound();
renderObject(response, oauthClient);
};

View File

@@ -5,12 +5,12 @@ import app from '../../../../../app.js';
import createAuthTokenByUserId from '../../../../../helpers/create-auth-token-by-user-id.js'; import createAuthTokenByUserId from '../../../../../helpers/create-auth-token-by-user-id.js';
import { createUser } from '../../../../../../test/factories/user.js'; import { createUser } from '../../../../../../test/factories/user.js';
import { createRole } from '../../../../../../test/factories/role.js'; import { createRole } from '../../../../../../test/factories/role.js';
import getAppAuthClientMock from '../../../../../../test/mocks/rest/api/v1/admin/apps/get-auth-client.js'; import getOAuthClientMock from '../../../../../../test/mocks/rest/api/v1/admin/apps/get-oauth-client.js';
import { createAppAuthClient } from '../../../../../../test/factories/app-auth-client.js'; import { createOAuthClient } from '../../../../../../test/factories/oauth-client.js';
import * as license from '../../../../../helpers/license.ee.js'; import * as license from '../../../../../helpers/license.ee.js';
describe('GET /api/v1/admin/apps/:appKey/auth-clients/:appAuthClientId', () => { describe('GET /api/v1/admin/apps/:appKey/oauth-clients/:oauthClientId', () => {
let currentUser, adminRole, currentAppAuthClient, token; let currentUser, adminRole, currentOAuthClient, token;
beforeEach(async () => { beforeEach(async () => {
vi.spyOn(license, 'hasValidLicense').mockResolvedValue(true); vi.spyOn(license, 'hasValidLicense').mockResolvedValue(true);
@@ -18,29 +18,29 @@ describe('GET /api/v1/admin/apps/:appKey/auth-clients/:appAuthClientId', () => {
adminRole = await createRole({ name: 'Admin' }); adminRole = await createRole({ name: 'Admin' });
currentUser = await createUser({ roleId: adminRole.id }); currentUser = await createUser({ roleId: adminRole.id });
currentAppAuthClient = await createAppAuthClient({ currentOAuthClient = await createOAuthClient({
appKey: 'deepl', appKey: 'deepl',
}); });
token = await createAuthTokenByUserId(currentUser.id); token = await createAuthTokenByUserId(currentUser.id);
}); });
it('should return specified app auth client', async () => { it('should return specified oauth client', async () => {
const response = await request(app) const response = await request(app)
.get(`/api/v1/admin/apps/deepl/auth-clients/${currentAppAuthClient.id}`) .get(`/api/v1/admin/apps/deepl/oauth-clients/${currentOAuthClient.id}`)
.set('Authorization', token) .set('Authorization', token)
.expect(200); .expect(200);
const expectedPayload = getAppAuthClientMock(currentAppAuthClient); const expectedPayload = getOAuthClientMock(currentOAuthClient);
expect(response.body).toStrictEqual(expectedPayload); expect(response.body).toStrictEqual(expectedPayload);
}); });
it('should return not found response for not existing app auth client ID', async () => { it('should return not found response for not existing oauth client ID', async () => {
const notExistingAppAuthClientUUID = Crypto.randomUUID(); const notExistingOAuthClientUUID = Crypto.randomUUID();
await request(app) await request(app)
.get( .get(
`/api/v1/admin/apps/deepl/auth-clients/${notExistingAppAuthClientUUID}` `/api/v1/admin/apps/deepl/oauth-clients/${notExistingOAuthClientUUID}`
) )
.set('Authorization', token) .set('Authorization', token)
.expect(404); .expect(404);
@@ -48,7 +48,7 @@ describe('GET /api/v1/admin/apps/:appKey/auth-clients/:appAuthClientId', () => {
it('should return bad request response for invalid UUID', async () => { it('should return bad request response for invalid UUID', async () => {
await request(app) await request(app)
.get('/api/v1/admin/apps/deepl/auth-clients/invalidAppAuthClientUUID') .get('/api/v1/admin/apps/deepl/oauth-clients/invalidOAuthClientUUID')
.set('Authorization', token) .set('Authorization', token)
.expect(400); .expect(400);
}); });

View File

@@ -1,10 +1,10 @@
import { renderObject } from '../../../../../helpers/renderer.js'; import { renderObject } from '../../../../../helpers/renderer.js';
import AppAuthClient from '../../../../../models/app-auth-client.js'; import OAuthClient from '../../../../../models/oauth-client.js';
export default async (request, response) => { export default async (request, response) => {
const appAuthClients = await AppAuthClient.query() const oauthClients = await OAuthClient.query()
.where({ app_key: request.params.appKey }) .where({ app_key: request.params.appKey })
.orderBy('created_at', 'desc'); .orderBy('created_at', 'desc');
renderObject(response, appAuthClients); renderObject(response, oauthClients);
}; };

View File

@@ -4,11 +4,11 @@ import app from '../../../../../app.js';
import createAuthTokenByUserId from '../../../../../helpers/create-auth-token-by-user-id.js'; import createAuthTokenByUserId from '../../../../../helpers/create-auth-token-by-user-id.js';
import { createUser } from '../../../../../../test/factories/user.js'; import { createUser } from '../../../../../../test/factories/user.js';
import { createRole } from '../../../../../../test/factories/role.js'; import { createRole } from '../../../../../../test/factories/role.js';
import getAuthClientsMock from '../../../../../../test/mocks/rest/api/v1/admin/apps/get-auth-clients.js'; import getAdminOAuthClientsMock from '../../../../../../test/mocks/rest/api/v1/admin/apps/get-oauth-clients.js';
import { createAppAuthClient } from '../../../../../../test/factories/app-auth-client.js'; import { createOAuthClient } from '../../../../../../test/factories/oauth-client.js';
import * as license from '../../../../../helpers/license.ee.js'; import * as license from '../../../../../helpers/license.ee.js';
describe('GET /api/v1/admin/apps/:appKey/auth-clients', () => { describe('GET /api/v1/admin/apps/:appKey/oauth-clients', () => {
let currentUser, adminRole, token; let currentUser, adminRole, token;
beforeEach(async () => { beforeEach(async () => {
@@ -20,23 +20,23 @@ describe('GET /api/v1/admin/apps/:appKey/auth-clients', () => {
token = await createAuthTokenByUserId(currentUser.id); token = await createAuthTokenByUserId(currentUser.id);
}); });
it('should return specified app auth client info', async () => { it('should return specified oauth client info', async () => {
const appAuthClientOne = await createAppAuthClient({ const oauthClientOne = await createOAuthClient({
appKey: 'deepl', appKey: 'deepl',
}); });
const appAuthClientTwo = await createAppAuthClient({ const oauthClientTwo = await createOAuthClient({
appKey: 'deepl', appKey: 'deepl',
}); });
const response = await request(app) const response = await request(app)
.get('/api/v1/admin/apps/deepl/auth-clients') .get('/api/v1/admin/apps/deepl/oauth-clients')
.set('Authorization', token) .set('Authorization', token)
.expect(200); .expect(200);
const expectedPayload = getAuthClientsMock([ const expectedPayload = getAdminOAuthClientsMock([
appAuthClientTwo, oauthClientTwo,
appAuthClientOne, oauthClientOne,
]); ]);
expect(response.body).toStrictEqual(expectedPayload); expect(response.body).toStrictEqual(expectedPayload);

View File

@@ -1,22 +0,0 @@
import { renderObject } from '../../../../../helpers/renderer.js';
import AppAuthClient from '../../../../../models/app-auth-client.js';
export default async (request, response) => {
const appAuthClient = await AppAuthClient.query()
.findById(request.params.appAuthClientId)
.throwIfNotFound();
await appAuthClient.$query().patchAndFetch(appAuthClientParams(request));
renderObject(response, appAuthClient);
};
const appAuthClientParams = (request) => {
const { active, name, formattedAuthDefaults } = request.body;
return {
active,
name,
formattedAuthDefaults,
};
};

View File

@@ -0,0 +1,22 @@
import { renderObject } from '../../../../../helpers/renderer.js';
import OAuthClient from '../../../../../models/oauth-client.js';
export default async (request, response) => {
const oauthClient = await OAuthClient.query()
.findById(request.params.oauthClientId)
.throwIfNotFound();
await oauthClient.$query().patchAndFetch(oauthClientParams(request));
renderObject(response, oauthClient);
};
const oauthClientParams = (request) => {
const { active, name, formattedAuthDefaults } = request.body;
return {
active,
name,
formattedAuthDefaults,
};
};

View File

@@ -6,12 +6,12 @@ import app from '../../../../../app.js';
import createAuthTokenByUserId from '../../../../../helpers/create-auth-token-by-user-id.js'; import createAuthTokenByUserId from '../../../../../helpers/create-auth-token-by-user-id.js';
import { createUser } from '../../../../../../test/factories/user.js'; import { createUser } from '../../../../../../test/factories/user.js';
import { createRole } from '../../../../../../test/factories/role.js'; import { createRole } from '../../../../../../test/factories/role.js';
import updateAppAuthClientMock from '../../../../../../test/mocks/rest/api/v1/admin/apps/update-auth-client.js'; import updateOAuthClientMock from '../../../../../../test/mocks/rest/api/v1/admin/apps/update-oauth-client.js';
import { createAppConfig } from '../../../../../../test/factories/app-config.js'; import { createAppConfig } from '../../../../../../test/factories/app-config.js';
import { createAppAuthClient } from '../../../../../../test/factories/app-auth-client.js'; import { createOAuthClient } from '../../../../../../test/factories/oauth-client.js';
import * as license from '../../../../../helpers/license.ee.js'; import * as license from '../../../../../helpers/license.ee.js';
describe('PATCH /api/v1/admin/apps/:appKey/auth-clients', () => { describe('PATCH /api/v1/admin/apps/:appKey/oauth-clients', () => {
let currentUser, adminRole, token; let currentUser, adminRole, token;
beforeEach(async () => { beforeEach(async () => {
@@ -27,8 +27,8 @@ describe('PATCH /api/v1/admin/apps/:appKey/auth-clients', () => {
}); });
}); });
it('should return updated entity for valid app auth client', async () => { it('should return updated entity for valid oauth client', async () => {
const appAuthClient = { const oauthClient = {
active: true, active: true,
appKey: 'gitlab', appKey: 'gitlab',
formattedAuthDefaults: { formattedAuthDefaults: {
@@ -39,33 +39,33 @@ describe('PATCH /api/v1/admin/apps/:appKey/auth-clients', () => {
}, },
}; };
const existingAppAuthClient = await createAppAuthClient({ const existingOAuthClient = await createOAuthClient({
appKey: 'gitlab', appKey: 'gitlab',
name: 'First auth client', name: 'First auth client',
}); });
const response = await request(app) const response = await request(app)
.patch( .patch(
`/api/v1/admin/apps/gitlab/auth-clients/${existingAppAuthClient.id}` `/api/v1/admin/apps/gitlab/oauth-clients/${existingOAuthClient.id}`
) )
.set('Authorization', token) .set('Authorization', token)
.send(appAuthClient) .send(oauthClient)
.expect(200); .expect(200);
const expectedPayload = updateAppAuthClientMock({ const expectedPayload = updateOAuthClientMock({
...existingAppAuthClient, ...existingOAuthClient,
...appAuthClient, ...oauthClient,
}); });
expect(response.body).toMatchObject(expectedPayload); expect(response.body).toMatchObject(expectedPayload);
}); });
it('should return not found response for not existing app auth client', async () => { it('should return not found response for not existing oauth client', async () => {
const notExistingAppAuthClientId = Crypto.randomUUID(); const notExistingOAuthClientId = Crypto.randomUUID();
await request(app) await request(app)
.patch( .patch(
`/api/v1/admin/apps/gitlab/auth-clients/${notExistingAppAuthClientId}` `/api/v1/admin/apps/gitlab/oauth-clients/${notExistingOAuthClientId}`
) )
.set('Authorization', token) .set('Authorization', token)
.expect(404); .expect(404);
@@ -73,27 +73,27 @@ describe('PATCH /api/v1/admin/apps/:appKey/auth-clients', () => {
it('should return bad request response for invalid UUID', async () => { it('should return bad request response for invalid UUID', async () => {
await request(app) await request(app)
.patch('/api/v1/admin/apps/gitlab/auth-clients/invalidAuthClientUUID') .patch('/api/v1/admin/apps/gitlab/oauth-clients/invalidAuthClientUUID')
.set('Authorization', token) .set('Authorization', token)
.expect(400); .expect(400);
}); });
it('should return HTTP 422 for invalid payload', async () => { it('should return HTTP 422 for invalid payload', async () => {
const appAuthClient = { const oauthClient = {
formattedAuthDefaults: 'invalid input', formattedAuthDefaults: 'invalid input',
}; };
const existingAppAuthClient = await createAppAuthClient({ const existingOAuthClient = await createOAuthClient({
appKey: 'gitlab', appKey: 'gitlab',
name: 'First auth client', name: 'First auth client',
}); });
const response = await request(app) const response = await request(app)
.patch( .patch(
`/api/v1/admin/apps/gitlab/auth-clients/${existingAppAuthClient.id}` `/api/v1/admin/apps/gitlab/oauth-clients/${existingOAuthClient.id}`
) )
.set('Authorization', token) .set('Authorization', token)
.send(appAuthClient) .send(oauthClient)
.expect(422); .expect(422);
expect(response.body.meta.type).toBe('ModelValidation'); expect(response.body.meta.type).toBe('ModelValidation');

View File

@@ -9,18 +9,18 @@ export default async (request, response) => {
.$query() .$query()
.withGraphFetched({ .withGraphFetched({
appConfig: true, appConfig: true,
appAuthClient: true, oauthClient: true,
}); });
renderObject(response, connectionWithAppConfigAndAuthClient, { status: 201 }); renderObject(response, connectionWithAppConfigAndAuthClient, { status: 201 });
}; };
const connectionParams = (request) => { const connectionParams = (request) => {
const { appAuthClientId, formattedData } = request.body; const { oauthClientId, formattedData } = request.body;
return { return {
key: request.params.appKey, key: request.params.appKey,
appAuthClientId, oauthClientId,
formattedData, formattedData,
verified: false, verified: false,
}; };

View File

@@ -3,7 +3,7 @@ import request from 'supertest';
import app from '../../../../app.js'; import app from '../../../../app.js';
import createAuthTokenByUserId from '../../../../helpers/create-auth-token-by-user-id.js'; import createAuthTokenByUserId from '../../../../helpers/create-auth-token-by-user-id.js';
import { createAppConfig } from '../../../../../test/factories/app-config.js'; import { createAppConfig } from '../../../../../test/factories/app-config.js';
import { createAppAuthClient } from '../../../../../test/factories/app-auth-client.js'; import { createOAuthClient } from '../../../../../test/factories/oauth-client.js';
import { createUser } from '../../../../../test/factories/user.js'; import { createUser } from '../../../../../test/factories/user.js';
import { createPermission } from '../../../../../test/factories/permission.js'; import { createPermission } from '../../../../../test/factories/permission.js';
import { createRole } from '../../../../../test/factories/role.js'; import { createRole } from '../../../../../test/factories/role.js';
@@ -267,7 +267,7 @@ describe('POST /api/v1/apps/:appKey/connections', () => {
}); });
describe('with auth client enabled', async () => { describe('with auth client enabled', async () => {
let appAuthClient; let oauthClient;
beforeEach(async () => { beforeEach(async () => {
await createAppConfig({ await createAppConfig({
@@ -276,7 +276,7 @@ describe('POST /api/v1/apps/:appKey/connections', () => {
useOnlyPredefinedAuthClients: false, useOnlyPredefinedAuthClients: false,
}); });
appAuthClient = await createAppAuthClient({ oauthClient = await createOAuthClient({
appKey: 'gitlab', appKey: 'gitlab',
active: true, active: true,
formattedAuthDefaults: { formattedAuthDefaults: {
@@ -290,7 +290,7 @@ describe('POST /api/v1/apps/:appKey/connections', () => {
it('should return created connection', async () => { it('should return created connection', async () => {
const connectionData = { const connectionData = {
appAuthClientId: appAuthClient.id, oauthClientId: oauthClient.id,
}; };
const response = await request(app) const response = await request(app)
@@ -338,7 +338,7 @@ describe('POST /api/v1/apps/:appKey/connections', () => {
}); });
describe('with auth client disabled', async () => { describe('with auth client disabled', async () => {
let appAuthClient; let oauthClient;
beforeEach(async () => { beforeEach(async () => {
await createAppConfig({ await createAppConfig({
@@ -347,7 +347,7 @@ describe('POST /api/v1/apps/:appKey/connections', () => {
useOnlyPredefinedAuthClients: false, useOnlyPredefinedAuthClients: false,
}); });
appAuthClient = await createAppAuthClient({ oauthClient = await createOAuthClient({
appKey: 'gitlab', appKey: 'gitlab',
active: false, active: false,
}); });
@@ -355,7 +355,7 @@ describe('POST /api/v1/apps/:appKey/connections', () => {
it('should return with not authorized response', async () => { it('should return with not authorized response', async () => {
const connectionData = { const connectionData = {
appAuthClientId: appAuthClient.id, oauthClientId: oauthClient.id,
}; };
await request(app) await request(app)

View File

@@ -15,7 +15,7 @@ describe('GET /api/v1/apps/:appKey/actions/:actionKey/substeps', () => {
exampleApp = await App.findOneByKey('github'); exampleApp = await App.findOneByKey('github');
}); });
it('should return the app auth info', async () => { it('should return the action substeps info', async () => {
const actions = await App.findActionsByKey('github'); const actions = await App.findActionsByKey('github');
const exampleAction = actions.find( const exampleAction = actions.find(
(action) => action.key === 'createIssue' (action) => action.key === 'createIssue'

View File

@@ -1,11 +0,0 @@
import { renderObject } from '../../../../helpers/renderer.js';
import AppAuthClient from '../../../../models/app-auth-client.js';
export default async (request, response) => {
const appAuthClient = await AppAuthClient.query()
.findById(request.params.appAuthClientId)
.where({ app_key: request.params.appKey, active: true })
.throwIfNotFound();
renderObject(response, appAuthClient);
};

View File

@@ -4,7 +4,7 @@ import AppConfig from '../../../../models/app-config.js';
export default async (request, response) => { export default async (request, response) => {
const appConfig = await AppConfig.query() const appConfig = await AppConfig.query()
.withGraphFetched({ .withGraphFetched({
appAuthClients: true, oauthClients: true,
}) })
.findOne({ .findOne({
key: request.params.appKey, key: request.params.appKey,

View File

@@ -9,7 +9,7 @@ export default async (request, response) => {
.select('connections.*') .select('connections.*')
.withGraphFetched({ .withGraphFetched({
appConfig: true, appConfig: true,
appAuthClient: true, oauthClient: true,
}) })
.fullOuterJoinRelated('steps') .fullOuterJoinRelated('steps')
.where({ .where({

View File

@@ -0,0 +1,11 @@
import { renderObject } from '../../../../helpers/renderer.js';
import OAuthClient from '../../../../models/oauth-client.js';
export default async (request, response) => {
const oauthClient = await OAuthClient.query()
.findById(request.params.oauthClientId)
.where({ app_key: request.params.appKey, active: true })
.throwIfNotFound();
renderObject(response, oauthClient);
};

View File

@@ -4,46 +4,46 @@ import Crypto from 'crypto';
import app from '../../../../app.js'; import app from '../../../../app.js';
import createAuthTokenByUserId from '../../../../helpers/create-auth-token-by-user-id.js'; import createAuthTokenByUserId from '../../../../helpers/create-auth-token-by-user-id.js';
import { createUser } from '../../../../../test/factories/user.js'; import { createUser } from '../../../../../test/factories/user.js';
import getAppAuthClientMock from '../../../../../test/mocks/rest/api/v1/apps/get-auth-client.js'; import getOAuthClientMock from '../../../../../test/mocks/rest/api/v1/apps/get-oauth-client.js';
import { createAppAuthClient } from '../../../../../test/factories/app-auth-client.js'; import { createOAuthClient } from '../../../../../test/factories/oauth-client.js';
import * as license from '../../../../helpers/license.ee.js'; import * as license from '../../../../helpers/license.ee.js';
describe('GET /api/v1/apps/:appKey/auth-clients/:appAuthClientId', () => { describe('GET /api/v1/apps/:appKey/oauth-clients/:oauthClientId', () => {
let currentUser, currentAppAuthClient, token; let currentUser, currentOAuthClient, token;
beforeEach(async () => { beforeEach(async () => {
vi.spyOn(license, 'hasValidLicense').mockResolvedValue(true); vi.spyOn(license, 'hasValidLicense').mockResolvedValue(true);
currentUser = await createUser(); currentUser = await createUser();
currentAppAuthClient = await createAppAuthClient({ currentOAuthClient = await createOAuthClient({
appKey: 'deepl', appKey: 'deepl',
}); });
token = await createAuthTokenByUserId(currentUser.id); token = await createAuthTokenByUserId(currentUser.id);
}); });
it('should return specified app auth client', async () => { it('should return specified oauth client', async () => {
const response = await request(app) const response = await request(app)
.get(`/api/v1/apps/deepl/auth-clients/${currentAppAuthClient.id}`) .get(`/api/v1/apps/deepl/oauth-clients/${currentOAuthClient.id}`)
.set('Authorization', token) .set('Authorization', token)
.expect(200); .expect(200);
const expectedPayload = getAppAuthClientMock(currentAppAuthClient); const expectedPayload = getOAuthClientMock(currentOAuthClient);
expect(response.body).toStrictEqual(expectedPayload); expect(response.body).toStrictEqual(expectedPayload);
}); });
it('should return not found response for not existing app auth client ID', async () => { it('should return not found response for not existing oauth client ID', async () => {
const notExistingAppAuthClientUUID = Crypto.randomUUID(); const notExistingOAuthClientUUID = Crypto.randomUUID();
await request(app) await request(app)
.get(`/api/v1/apps/deepl/auth-clients/${notExistingAppAuthClientUUID}`) .get(`/api/v1/apps/deepl/oauth-clients/${notExistingOAuthClientUUID}`)
.set('Authorization', token) .set('Authorization', token)
.expect(404); .expect(404);
}); });
it('should return bad request response for invalid UUID', async () => { it('should return bad request response for invalid UUID', async () => {
await request(app) await request(app)
.get('/api/v1/apps/deepl/auth-clients/invalidAppAuthClientUUID') .get('/api/v1/apps/deepl/oauth-clients/invalidOAuthClientUUID')
.set('Authorization', token) .set('Authorization', token)
.expect(400); .expect(400);
}); });

View File

@@ -1,10 +1,10 @@
import { renderObject } from '../../../../helpers/renderer.js'; import { renderObject } from '../../../../helpers/renderer.js';
import AppAuthClient from '../../../../models/app-auth-client.js'; import OAuthClient from '../../../../models/oauth-client.js';
export default async (request, response) => { export default async (request, response) => {
const appAuthClients = await AppAuthClient.query() const oauthClients = await OAuthClient.query()
.where({ app_key: request.params.appKey, active: true }) .where({ app_key: request.params.appKey, active: true })
.orderBy('created_at', 'desc'); .orderBy('created_at', 'desc');
renderObject(response, appAuthClients); renderObject(response, oauthClients);
}; };

View File

@@ -3,11 +3,11 @@ import request from 'supertest';
import app from '../../../../app.js'; import app from '../../../../app.js';
import createAuthTokenByUserId from '../../../../helpers/create-auth-token-by-user-id.js'; import createAuthTokenByUserId from '../../../../helpers/create-auth-token-by-user-id.js';
import { createUser } from '../../../../../test/factories/user.js'; import { createUser } from '../../../../../test/factories/user.js';
import getAuthClientsMock from '../../../../../test/mocks/rest/api/v1/apps/get-auth-clients.js'; import getOAuthClientsMock from '../../../../../test/mocks/rest/api/v1/apps/get-oauth-clients.js';
import { createAppAuthClient } from '../../../../../test/factories/app-auth-client.js'; import { createOAuthClient } from '../../../../../test/factories/oauth-client.js';
import * as license from '../../../../helpers/license.ee.js'; import * as license from '../../../../helpers/license.ee.js';
describe('GET /api/v1/apps/:appKey/auth-clients', () => { describe('GET /api/v1/apps/:appKey/oauth-clients', () => {
let currentUser, token; let currentUser, token;
beforeEach(async () => { beforeEach(async () => {
@@ -18,23 +18,23 @@ describe('GET /api/v1/apps/:appKey/auth-clients', () => {
token = await createAuthTokenByUserId(currentUser.id); token = await createAuthTokenByUserId(currentUser.id);
}); });
it('should return specified app auth client info', async () => { it('should return specified oauth client info', async () => {
const appAuthClientOne = await createAppAuthClient({ const oauthClientOne = await createOAuthClient({
appKey: 'deepl', appKey: 'deepl',
}); });
const appAuthClientTwo = await createAppAuthClient({ const oauthClientTwo = await createOAuthClient({
appKey: 'deepl', appKey: 'deepl',
}); });
const response = await request(app) const response = await request(app)
.get('/api/v1/apps/deepl/auth-clients') .get('/api/v1/apps/deepl/oauth-clients')
.set('Authorization', token) .set('Authorization', token)
.expect(200); .expect(200);
const expectedPayload = getAuthClientsMock([ const expectedPayload = getOAuthClientsMock([
appAuthClientTwo, oauthClientTwo,
appAuthClientOne, oauthClientOne,
]); ]);
expect(response.body).toStrictEqual(expectedPayload); expect(response.body).toStrictEqual(expectedPayload);

View File

@@ -15,7 +15,7 @@ describe('GET /api/v1/apps/:appKey/triggers/:triggerKey/substeps', () => {
exampleApp = await App.findOneByKey('github'); exampleApp = await App.findOneByKey('github');
}); });
it('should return the app auth info', async () => { it('should return the trigger substeps info', async () => {
const triggers = await App.findTriggersByKey('github'); const triggers = await App.findTriggersByKey('github');
const exampleTrigger = triggers.find( const exampleTrigger = triggers.find(
(trigger) => trigger.key === 'newIssues' (trigger) => trigger.key === 'newIssues'

View File

@@ -14,6 +14,6 @@ export default async (request, response) => {
}; };
const connectionParams = (request) => { const connectionParams = (request) => {
const { formattedData, appAuthClientId } = request.body; const { formattedData, oauthClientId } = request.body;
return { formattedData, appAuthClientId }; return { formattedData, oauthClientId };
}; };

View File

@@ -0,0 +1,31 @@
export async function up(knex) {
await knex.schema.renameTable('app_auth_clients', 'oauth_clients');
await knex.schema.raw(
'ALTER INDEX app_auth_clients_pkey RENAME TO oauth_clients_pkey'
);
await knex.schema.raw(
'ALTER INDEX app_auth_clients_name_unique RENAME TO oauth_clients_name_unique'
);
return await knex.schema.alterTable('connections', (table) => {
table.renameColumn('app_auth_client_id', 'oauth_client_id');
});
}
export async function down(knex) {
await knex.schema.renameTable('oauth_clients', 'app_auth_clients');
await knex.schema.raw(
'ALTER INDEX oauth_clients_pkey RENAME TO app_auth_clients_pkey'
);
await knex.schema.raw(
'ALTER INDEX oauth_clients_name_unique RENAME TO app_auth_clients_name_unique'
);
return await knex.schema.alterTable('connections', (table) => {
table.renameColumn('oauth_client_id', 'app_auth_client_id');
});
}

View File

@@ -88,8 +88,8 @@ const sharedAuthenticationStepsWithAuthUrl = [
value: '{key}', value: '{key}',
}, },
{ {
name: 'appAuthClientId', name: 'oauthClientId',
value: '{appAuthClientId}', value: '{oauthClientId}',
}, },
], ],
}, },

View File

@@ -3,10 +3,6 @@
exports[`Connection model > jsonSchema should have correct validations 1`] = ` exports[`Connection model > jsonSchema should have correct validations 1`] = `
{ {
"properties": { "properties": {
"appAuthClientId": {
"format": "uuid",
"type": "string",
},
"createdAt": { "createdAt": {
"type": "string", "type": "string",
}, },
@@ -31,6 +27,10 @@ exports[`Connection model > jsonSchema should have correct validations 1`] = `
"minLength": 1, "minLength": 1,
"type": "string", "type": "string",
}, },
"oauthClientId": {
"format": "uuid",
"type": "string",
},
"updatedAt": { "updatedAt": {
"type": "string", "type": "string",
}, },

View File

@@ -1,6 +1,6 @@
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
exports[`AppAuthClient model > jsonSchema should have correct validations 1`] = ` exports[`OAuthClient model > jsonSchema should have correct validations 1`] = `
{ {
"properties": { "properties": {
"active": { "active": {

View File

@@ -1,202 +0,0 @@
import { describe, it, expect, vi } from 'vitest';
import AES from 'crypto-js/aes.js';
import enc from 'crypto-js/enc-utf8.js';
import AppConfig from './app-config.js';
import AppAuthClient from './app-auth-client.js';
import Base from './base.js';
import appConfig from '../config/app.js';
import { createAppAuthClient } from '../../test/factories/app-auth-client.js';
describe('AppAuthClient model', () => {
it('tableName should return correct name', () => {
expect(AppAuthClient.tableName).toBe('app_auth_clients');
});
it('jsonSchema should have correct validations', () => {
expect(AppAuthClient.jsonSchema).toMatchSnapshot();
});
it('relationMappings should return correct associations', () => {
const relationMappings = AppAuthClient.relationMappings();
const expectedRelations = {
appConfig: {
relation: Base.BelongsToOneRelation,
modelClass: AppConfig,
join: {
from: 'app_auth_clients.app_key',
to: 'app_configs.key',
},
},
};
expect(relationMappings).toStrictEqual(expectedRelations);
});
describe('encryptData', () => {
it('should return undefined if eligibleForEncryption is not true', async () => {
vi.spyOn(
AppAuthClient.prototype,
'eligibleForEncryption'
).mockReturnValue(false);
const appAuthClient = new AppAuthClient();
expect(appAuthClient.encryptData()).toBeUndefined();
});
it('should encrypt formattedAuthDefaults and set it to authDefaults', async () => {
vi.spyOn(
AppAuthClient.prototype,
'eligibleForEncryption'
).mockReturnValue(true);
const formattedAuthDefaults = {
key: 'value',
};
const appAuthClient = new AppAuthClient();
appAuthClient.formattedAuthDefaults = formattedAuthDefaults;
appAuthClient.encryptData();
const expectedDecryptedValue = JSON.parse(
AES.decrypt(
appAuthClient.authDefaults,
appConfig.encryptionKey
).toString(enc)
);
expect(formattedAuthDefaults).toStrictEqual(expectedDecryptedValue);
expect(appAuthClient.authDefaults).not.toStrictEqual(
formattedAuthDefaults
);
});
it('should encrypt formattedAuthDefaults and remove formattedAuthDefaults', async () => {
vi.spyOn(
AppAuthClient.prototype,
'eligibleForEncryption'
).mockReturnValue(true);
const formattedAuthDefaults = {
key: 'value',
};
const appAuthClient = new AppAuthClient();
appAuthClient.formattedAuthDefaults = formattedAuthDefaults;
appAuthClient.encryptData();
expect(appAuthClient.formattedAuthDefaults).not.toBeDefined();
});
});
describe('decryptData', () => {
it('should return undefined if eligibleForDecryption is not true', () => {
vi.spyOn(
AppAuthClient.prototype,
'eligibleForDecryption'
).mockReturnValue(false);
const appAuthClient = new AppAuthClient();
expect(appAuthClient.decryptData()).toBeUndefined();
});
it('should decrypt authDefaults and set it to formattedAuthDefaults', async () => {
vi.spyOn(
AppAuthClient.prototype,
'eligibleForDecryption'
).mockReturnValue(true);
const formattedAuthDefaults = {
key: 'value',
};
const authDefaults = AES.encrypt(
JSON.stringify(formattedAuthDefaults),
appConfig.encryptionKey
).toString();
const appAuthClient = new AppAuthClient();
appAuthClient.authDefaults = authDefaults;
appAuthClient.decryptData();
expect(appAuthClient.formattedAuthDefaults).toStrictEqual(
formattedAuthDefaults
);
expect(appAuthClient.authDefaults).not.toStrictEqual(
formattedAuthDefaults
);
});
});
describe('eligibleForEncryption', () => {
it('should return true when formattedAuthDefaults property exists', async () => {
const appAuthClient = await createAppAuthClient();
expect(appAuthClient.eligibleForEncryption()).toBe(true);
});
it("should return false when formattedAuthDefaults property doesn't exist", async () => {
const appAuthClient = await createAppAuthClient();
delete appAuthClient.formattedAuthDefaults;
expect(appAuthClient.eligibleForEncryption()).toBe(false);
});
});
describe('eligibleForDecryption', () => {
it('should return true when authDefaults property exists', async () => {
const appAuthClient = await createAppAuthClient();
expect(appAuthClient.eligibleForDecryption()).toBe(true);
});
it("should return false when authDefaults property doesn't exist", async () => {
const appAuthClient = await createAppAuthClient();
delete appAuthClient.authDefaults;
expect(appAuthClient.eligibleForDecryption()).toBe(false);
});
});
it('$beforeInsert should call AppAuthClient.encryptData', async () => {
const appAuthClientBeforeInsertSpy = vi.spyOn(
AppAuthClient.prototype,
'encryptData'
);
await createAppAuthClient();
expect(appAuthClientBeforeInsertSpy).toHaveBeenCalledOnce();
});
it('$beforeUpdate should call AppAuthClient.encryptData', async () => {
const appAuthClient = await createAppAuthClient();
const appAuthClientBeforeUpdateSpy = vi.spyOn(
AppAuthClient.prototype,
'encryptData'
);
await appAuthClient.$query().patchAndFetch({ name: 'sample' });
expect(appAuthClientBeforeUpdateSpy).toHaveBeenCalledOnce();
});
it('$afterFind should call AppAuthClient.decryptData', async () => {
const appAuthClient = await createAppAuthClient();
const appAuthClientAfterFindSpy = vi.spyOn(
AppAuthClient.prototype,
'decryptData'
);
await appAuthClient.$query();
expect(appAuthClientAfterFindSpy).toHaveBeenCalledOnce();
});
});

View File

@@ -1,5 +1,5 @@
import App from './app.js'; import App from './app.js';
import AppAuthClient from './app-auth-client.js'; import OAuthClient from './oauth-client.js';
import Base from './base.js'; import Base from './base.js';
class AppConfig extends Base { class AppConfig extends Base {
@@ -24,12 +24,12 @@ class AppConfig extends Base {
}; };
static relationMappings = () => ({ static relationMappings = () => ({
appAuthClients: { oauthClients: {
relation: Base.HasManyRelation, relation: Base.HasManyRelation,
modelClass: AppAuthClient, modelClass: OAuthClient,
join: { join: {
from: 'app_configs.key', from: 'app_configs.key',
to: 'app_auth_clients.app_key', to: 'oauth_clients.app_key',
}, },
}, },
}); });

View File

@@ -3,7 +3,7 @@ import { describe, it, expect } from 'vitest';
import Base from './base.js'; import Base from './base.js';
import AppConfig from './app-config.js'; import AppConfig from './app-config.js';
import App from './app.js'; import App from './app.js';
import AppAuthClient from './app-auth-client.js'; import OAuthClient from './oauth-client.js';
describe('AppConfig model', () => { describe('AppConfig model', () => {
it('tableName should return correct name', () => { it('tableName should return correct name', () => {
@@ -22,12 +22,12 @@ describe('AppConfig model', () => {
const relationMappings = AppConfig.relationMappings(); const relationMappings = AppConfig.relationMappings();
const expectedRelations = { const expectedRelations = {
appAuthClients: { oauthClients: {
relation: Base.HasManyRelation, relation: Base.HasManyRelation,
modelClass: AppAuthClient, modelClass: OAuthClient,
join: { join: {
from: 'app_configs.key', from: 'app_configs.key',
to: 'app_auth_clients.app_key', to: 'oauth_clients.app_key',
}, },
}, },
}; };

View File

@@ -2,7 +2,7 @@ import AES from 'crypto-js/aes.js';
import enc from 'crypto-js/enc-utf8.js'; import enc from 'crypto-js/enc-utf8.js';
import App from './app.js'; import App from './app.js';
import AppConfig from './app-config.js'; import AppConfig from './app-config.js';
import AppAuthClient from './app-auth-client.js'; import OAuthClient from './oauth-client.js';
import Base from './base.js'; import Base from './base.js';
import User from './user.js'; import User from './user.js';
import Step from './step.js'; import Step from './step.js';
@@ -24,7 +24,7 @@ class Connection extends Base {
data: { type: 'string' }, data: { type: 'string' },
formattedData: { type: 'object' }, formattedData: { type: 'object' },
userId: { type: 'string', format: 'uuid' }, userId: { type: 'string', format: 'uuid' },
appAuthClientId: { type: 'string', format: 'uuid' }, oauthClientId: { type: 'string', format: 'uuid' },
verified: { type: 'boolean', default: false }, verified: { type: 'boolean', default: false },
draft: { type: 'boolean' }, draft: { type: 'boolean' },
deletedAt: { type: 'string' }, deletedAt: { type: 'string' },
@@ -69,12 +69,12 @@ class Connection extends Base {
to: 'app_configs.key', to: 'app_configs.key',
}, },
}, },
appAuthClient: { oauthClient: {
relation: Base.BelongsToOneRelation, relation: Base.BelongsToOneRelation,
modelClass: AppAuthClient, modelClass: OAuthClient,
join: { join: {
from: 'connections.app_auth_client_id', from: 'connections.oauth_client_id',
to: 'app_auth_clients.id', to: 'oauth_clients.id',
}, },
}, },
}); });
@@ -136,8 +136,8 @@ class Connection extends Base {
if (!this.formattedData) { if (!this.formattedData) {
const authClient = await appConfig const authClient = await appConfig
.$relatedQuery('appAuthClients') .$relatedQuery('oauthClients')
.findById(this.appAuthClientId) .findById(this.oauthClientId)
.where({ active: true }) .where({ active: true })
.throwIfNotFound(); .throwIfNotFound();
@@ -215,13 +215,13 @@ class Connection extends Base {
return updatedConnection; return updatedConnection;
} }
async updateFormattedData({ formattedData, appAuthClientId }) { async updateFormattedData({ formattedData, oauthClientId }) {
if (appAuthClientId) { if (oauthClientId) {
const appAuthClient = await AppAuthClient.query() const oauthClient = await OAuthClient.query()
.findById(appAuthClientId) .findById(oauthClientId)
.throwIfNotFound(); .throwIfNotFound();
formattedData = appAuthClient.formattedAuthDefaults; formattedData = oauthClient.formattedAuthDefaults;
} }
return await this.$query().patchAndFetch({ return await this.$query().patchAndFetch({

View File

@@ -2,7 +2,7 @@ import { describe, it, expect, vi } from 'vitest';
import AES from 'crypto-js/aes.js'; import AES from 'crypto-js/aes.js';
import enc from 'crypto-js/enc-utf8.js'; import enc from 'crypto-js/enc-utf8.js';
import appConfig from '../config/app.js'; import appConfig from '../config/app.js';
import AppAuthClient from './app-auth-client.js'; import OAuthClient from './oauth-client.js';
import App from './app.js'; import App from './app.js';
import AppConfig from './app-config.js'; import AppConfig from './app-config.js';
import Base from './base.js'; import Base from './base.js';
@@ -12,7 +12,7 @@ import User from './user.js';
import Telemetry from '../helpers/telemetry/index.js'; import Telemetry from '../helpers/telemetry/index.js';
import { createConnection } from '../../test/factories/connection.js'; import { createConnection } from '../../test/factories/connection.js';
import { createAppConfig } from '../../test/factories/app-config.js'; import { createAppConfig } from '../../test/factories/app-config.js';
import { createAppAuthClient } from '../../test/factories/app-auth-client.js'; import { createOAuthClient } from '../../test/factories/oauth-client.js';
describe('Connection model', () => { describe('Connection model', () => {
it('tableName should return correct name', () => { it('tableName should return correct name', () => {
@@ -61,12 +61,12 @@ describe('Connection model', () => {
to: 'app_configs.key', to: 'app_configs.key',
}, },
}, },
appAuthClient: { oauthClient: {
relation: Base.BelongsToOneRelation, relation: Base.BelongsToOneRelation,
modelClass: AppAuthClient, modelClass: OAuthClient,
join: { join: {
from: 'connections.app_auth_client_id', from: 'connections.oauth_client_id',
to: 'app_auth_clients.id', to: 'oauth_clients.id',
}, },
}, },
}; };
@@ -307,13 +307,13 @@ describe('Connection model', () => {
); );
}); });
it('should apply app auth client auth defaults when creating with shared app auth client', async () => { it('should apply oauth client auth defaults when creating with shared oauth client', async () => {
await createAppConfig({ await createAppConfig({
key: 'gitlab', key: 'gitlab',
disabled: false, disabled: false,
}); });
const appAuthClient = await createAppAuthClient({ const oauthClient = await createOAuthClient({
appKey: 'gitlab', appKey: 'gitlab',
active: true, active: true,
formattedAuthDefaults: { formattedAuthDefaults: {
@@ -323,7 +323,7 @@ describe('Connection model', () => {
const connection = await createConnection({ const connection = await createConnection({
key: 'gitlab', key: 'gitlab',
appAuthClientId: appAuthClient.id, oauthClientId: oauthClient.id,
formattedData: null, formattedData: null,
}); });
@@ -559,22 +559,22 @@ describe('Connection model', () => {
}); });
describe('updateFormattedData', () => { describe('updateFormattedData', () => {
it('should extend connection data with app auth client auth defaults', async () => { it('should extend connection data with oauth client auth defaults', async () => {
const appAuthClient = await createAppAuthClient({ const oauthClient = await createOAuthClient({
formattedAuthDefaults: { formattedAuthDefaults: {
clientId: 'sample-id', clientId: 'sample-id',
}, },
}); });
const connection = await createConnection({ const connection = await createConnection({
appAuthClientId: appAuthClient.id, oauthClientId: oauthClient.id,
formattedData: { formattedData: {
token: 'sample-token', token: 'sample-token',
}, },
}); });
const updatedConnection = await connection.updateFormattedData({ const updatedConnection = await connection.updateFormattedData({
appAuthClientId: appAuthClient.id, oauthClientId: oauthClient.id,
}); });
expect(updatedConnection.formattedData).toStrictEqual({ expect(updatedConnection.formattedData).toStrictEqual({

View File

@@ -4,8 +4,8 @@ import appConfig from '../config/app.js';
import Base from './base.js'; import Base from './base.js';
import AppConfig from './app-config.js'; import AppConfig from './app-config.js';
class AppAuthClient extends Base { class OAuthClient extends Base {
static tableName = 'app_auth_clients'; static tableName = 'oauth_clients';
static jsonSchema = { static jsonSchema = {
type: 'object', type: 'object',
@@ -27,7 +27,7 @@ class AppAuthClient extends Base {
relation: Base.BelongsToOneRelation, relation: Base.BelongsToOneRelation,
modelClass: AppConfig, modelClass: AppConfig,
join: { join: {
from: 'app_auth_clients.app_key', from: 'oauth_clients.app_key',
to: 'app_configs.key', to: 'app_configs.key',
}, },
}, },
@@ -87,4 +87,4 @@ class AppAuthClient extends Base {
} }
} }
export default AppAuthClient; export default OAuthClient;

View File

@@ -0,0 +1,192 @@
import { describe, it, expect, vi } from 'vitest';
import AES from 'crypto-js/aes.js';
import enc from 'crypto-js/enc-utf8.js';
import AppConfig from './app-config.js';
import OAuthClient from './oauth-client.js';
import Base from './base.js';
import appConfig from '../config/app.js';
import { createOAuthClient } from '../../test/factories/oauth-client.js';
describe('OAuthClient model', () => {
it('tableName should return correct name', () => {
expect(OAuthClient.tableName).toBe('oauth_clients');
});
it('jsonSchema should have correct validations', () => {
expect(OAuthClient.jsonSchema).toMatchSnapshot();
});
it('relationMappings should return correct associations', () => {
const relationMappings = OAuthClient.relationMappings();
const expectedRelations = {
appConfig: {
relation: Base.BelongsToOneRelation,
modelClass: AppConfig,
join: {
from: 'oauth_clients.app_key',
to: 'app_configs.key',
},
},
};
expect(relationMappings).toStrictEqual(expectedRelations);
});
describe('encryptData', () => {
it('should return undefined if eligibleForEncryption is not true', async () => {
vi.spyOn(OAuthClient.prototype, 'eligibleForEncryption').mockReturnValue(
false
);
const oauthClient = new OAuthClient();
expect(oauthClient.encryptData()).toBeUndefined();
});
it('should encrypt formattedAuthDefaults and set it to authDefaults', async () => {
vi.spyOn(OAuthClient.prototype, 'eligibleForEncryption').mockReturnValue(
true
);
const formattedAuthDefaults = {
key: 'value',
};
const oauthClient = new OAuthClient();
oauthClient.formattedAuthDefaults = formattedAuthDefaults;
oauthClient.encryptData();
const expectedDecryptedValue = JSON.parse(
AES.decrypt(oauthClient.authDefaults, appConfig.encryptionKey).toString(
enc
)
);
expect(formattedAuthDefaults).toStrictEqual(expectedDecryptedValue);
expect(oauthClient.authDefaults).not.toStrictEqual(formattedAuthDefaults);
});
it('should encrypt formattedAuthDefaults and remove formattedAuthDefaults', async () => {
vi.spyOn(OAuthClient.prototype, 'eligibleForEncryption').mockReturnValue(
true
);
const formattedAuthDefaults = {
key: 'value',
};
const oauthClient = new OAuthClient();
oauthClient.formattedAuthDefaults = formattedAuthDefaults;
oauthClient.encryptData();
expect(oauthClient.formattedAuthDefaults).not.toBeDefined();
});
});
describe('decryptData', () => {
it('should return undefined if eligibleForDecryption is not true', () => {
vi.spyOn(OAuthClient.prototype, 'eligibleForDecryption').mockReturnValue(
false
);
const oauthClient = new OAuthClient();
expect(oauthClient.decryptData()).toBeUndefined();
});
it('should decrypt authDefaults and set it to formattedAuthDefaults', async () => {
vi.spyOn(OAuthClient.prototype, 'eligibleForDecryption').mockReturnValue(
true
);
const formattedAuthDefaults = {
key: 'value',
};
const authDefaults = AES.encrypt(
JSON.stringify(formattedAuthDefaults),
appConfig.encryptionKey
).toString();
const oauthClient = new OAuthClient();
oauthClient.authDefaults = authDefaults;
oauthClient.decryptData();
expect(oauthClient.formattedAuthDefaults).toStrictEqual(
formattedAuthDefaults
);
expect(oauthClient.authDefaults).not.toStrictEqual(formattedAuthDefaults);
});
});
describe('eligibleForEncryption', () => {
it('should return true when formattedAuthDefaults property exists', async () => {
const oauthClient = await createOAuthClient();
expect(oauthClient.eligibleForEncryption()).toBe(true);
});
it("should return false when formattedAuthDefaults property doesn't exist", async () => {
const oauthClient = await createOAuthClient();
delete oauthClient.formattedAuthDefaults;
expect(oauthClient.eligibleForEncryption()).toBe(false);
});
});
describe('eligibleForDecryption', () => {
it('should return true when authDefaults property exists', async () => {
const oauthClient = await createOAuthClient();
expect(oauthClient.eligibleForDecryption()).toBe(true);
});
it("should return false when authDefaults property doesn't exist", async () => {
const oauthClient = await createOAuthClient();
delete oauthClient.authDefaults;
expect(oauthClient.eligibleForDecryption()).toBe(false);
});
});
it('$beforeInsert should call OAuthClient.encryptData', async () => {
const oauthClientBeforeInsertSpy = vi.spyOn(
OAuthClient.prototype,
'encryptData'
);
await createOAuthClient();
expect(oauthClientBeforeInsertSpy).toHaveBeenCalledOnce();
});
it('$beforeUpdate should call OAuthClient.encryptData', async () => {
const oauthClient = await createOAuthClient();
const oauthClientBeforeUpdateSpy = vi.spyOn(
OAuthClient.prototype,
'encryptData'
);
await oauthClient.$query().patchAndFetch({ name: 'sample' });
expect(oauthClientBeforeUpdateSpy).toHaveBeenCalledOnce();
});
it('$afterFind should call OAuthClient.decryptData', async () => {
const oauthClient = await createOAuthClient();
const oauthClientAfterFindSpy = vi.spyOn(
OAuthClient.prototype,
'decryptData'
);
await oauthClient.$query();
expect(oauthClientAfterFindSpy).toHaveBeenCalledOnce();
});
});

View File

@@ -4,10 +4,10 @@ import { authorizeAdmin } from '../../../../helpers/authorization.js';
import { checkIsEnterprise } from '../../../../helpers/check-is-enterprise.js'; import { checkIsEnterprise } from '../../../../helpers/check-is-enterprise.js';
import createConfigAction from '../../../../controllers/api/v1/admin/apps/create-config.ee.js'; import createConfigAction from '../../../../controllers/api/v1/admin/apps/create-config.ee.js';
import updateConfigAction from '../../../../controllers/api/v1/admin/apps/update-config.ee.js'; import updateConfigAction from '../../../../controllers/api/v1/admin/apps/update-config.ee.js';
import getAuthClientsAction from '../../../../controllers/api/v1/admin/apps/get-auth-clients.ee.js'; import getOAuthClientsAction from '../../../../controllers/api/v1/admin/apps/get-oauth-clients.ee.js';
import getAuthClientAction from '../../../../controllers/api/v1/admin/apps/get-auth-client.ee.js'; import getOAuthClientAction from '../../../../controllers/api/v1/admin/apps/get-oauth-client.ee.js';
import createAuthClientAction from '../../../../controllers/api/v1/admin/apps/create-auth-client.ee.js'; import createOAuthClientAction from '../../../../controllers/api/v1/admin/apps/create-oauth-client.ee.js';
import updateAuthClientAction from '../../../../controllers/api/v1/admin/apps/update-auth-client.ee.js'; import updateOAuthClientAction from '../../../../controllers/api/v1/admin/apps/update-oauth-client.ee.js';
const router = Router(); const router = Router();
@@ -28,35 +28,35 @@ router.patch(
); );
router.get( router.get(
'/:appKey/auth-clients', '/:appKey/oauth-clients',
authenticateUser, authenticateUser,
authorizeAdmin, authorizeAdmin,
checkIsEnterprise, checkIsEnterprise,
getAuthClientsAction getOAuthClientsAction
); );
router.post( router.post(
'/:appKey/auth-clients', '/:appKey/oauth-clients',
authenticateUser, authenticateUser,
authorizeAdmin, authorizeAdmin,
checkIsEnterprise, checkIsEnterprise,
createAuthClientAction createOAuthClientAction
); );
router.get( router.get(
'/:appKey/auth-clients/:appAuthClientId', '/:appKey/oauth-clients/:oauthClientId',
authenticateUser, authenticateUser,
authorizeAdmin, authorizeAdmin,
checkIsEnterprise, checkIsEnterprise,
getAuthClientAction getOAuthClientAction
); );
router.patch( router.patch(
'/:appKey/auth-clients/:appAuthClientId', '/:appKey/oauth-clients/:oauthClientId',
authenticateUser, authenticateUser,
authorizeAdmin, authorizeAdmin,
checkIsEnterprise, checkIsEnterprise,
updateAuthClientAction updateOAuthClientAction
); );
export default router; export default router;

View File

@@ -7,8 +7,8 @@ import getAppsAction from '../../../controllers/api/v1/apps/get-apps.js';
import getAuthAction from '../../../controllers/api/v1/apps/get-auth.js'; import getAuthAction from '../../../controllers/api/v1/apps/get-auth.js';
import getConnectionsAction from '../../../controllers/api/v1/apps/get-connections.js'; import getConnectionsAction from '../../../controllers/api/v1/apps/get-connections.js';
import getConfigAction from '../../../controllers/api/v1/apps/get-config.ee.js'; import getConfigAction from '../../../controllers/api/v1/apps/get-config.ee.js';
import getAuthClientsAction from '../../../controllers/api/v1/apps/get-auth-clients.ee.js'; import getOAuthClientsAction from '../../../controllers/api/v1/apps/get-oauth-clients.ee.js';
import getAuthClientAction from '../../../controllers/api/v1/apps/get-auth-client.ee.js'; import getOAuthClientAction from '../../../controllers/api/v1/apps/get-oauth-client.ee.js';
import getTriggersAction from '../../../controllers/api/v1/apps/get-triggers.js'; import getTriggersAction from '../../../controllers/api/v1/apps/get-triggers.js';
import getTriggerSubstepsAction from '../../../controllers/api/v1/apps/get-trigger-substeps.js'; import getTriggerSubstepsAction from '../../../controllers/api/v1/apps/get-trigger-substeps.js';
import getActionsAction from '../../../controllers/api/v1/apps/get-actions.js'; import getActionsAction from '../../../controllers/api/v1/apps/get-actions.js';
@@ -44,17 +44,17 @@ router.get(
); );
router.get( router.get(
'/:appKey/auth-clients', '/:appKey/oauth-clients',
authenticateUser, authenticateUser,
checkIsEnterprise, checkIsEnterprise,
getAuthClientsAction getOAuthClientsAction
); );
router.get( router.get(
'/:appKey/auth-clients/:appAuthClientId', '/:appKey/oauth-clients/:oauthClientId',
authenticateUser, authenticateUser,
checkIsEnterprise, checkIsEnterprise,
getAuthClientAction getOAuthClientAction
); );
router.get('/:appKey/triggers', authenticateUser, getTriggersAction); router.get('/:appKey/triggers', authenticateUser, getTriggersAction);

View File

@@ -1,10 +0,0 @@
const appAuthClientSerializer = (appAuthClient) => {
return {
id: appAuthClient.id,
appConfigId: appAuthClient.appConfigId,
name: appAuthClient.name,
active: appAuthClient.active,
};
};
export default appAuthClientSerializer;

View File

@@ -1,24 +0,0 @@
import { describe, it, expect, beforeEach } from 'vitest';
import { createAppAuthClient } from '../../test/factories/app-auth-client';
import appAuthClientSerializer from './app-auth-client';
describe('appAuthClient serializer', () => {
let appAuthClient;
beforeEach(async () => {
appAuthClient = await createAppAuthClient();
});
it('should return app auth client data', async () => {
const expectedPayload = {
id: appAuthClient.id,
appConfigId: appAuthClient.appConfigId,
name: appAuthClient.name,
active: appAuthClient.active,
};
expect(appAuthClientSerializer(appAuthClient)).toStrictEqual(
expectedPayload
);
});
});

View File

@@ -2,7 +2,7 @@ const connectionSerializer = (connection) => {
return { return {
id: connection.id, id: connection.id,
key: connection.key, key: connection.key,
appAuthClientId: connection.appAuthClientId, oauthClientId: connection.oauthClientId,
formattedData: { formattedData: {
screenName: connection.formattedData.screenName, screenName: connection.formattedData.screenName,
}, },

View File

@@ -13,7 +13,7 @@ describe('connectionSerializer', () => {
const expectedPayload = { const expectedPayload = {
id: connection.id, id: connection.id,
key: connection.key, key: connection.key,
appAuthClientId: connection.appAuthClientId, oauthClientId: connection.oauthClientId,
formattedData: { formattedData: {
screenName: connection.formattedData.screenName, screenName: connection.formattedData.screenName,
}, },

View File

@@ -4,7 +4,7 @@ import permissionSerializer from './permission.js';
import adminSamlAuthProviderSerializer from './admin-saml-auth-provider.ee.js'; import adminSamlAuthProviderSerializer from './admin-saml-auth-provider.ee.js';
import samlAuthProviderSerializer from './saml-auth-provider.ee.js'; import samlAuthProviderSerializer from './saml-auth-provider.ee.js';
import samlAuthProviderRoleMappingSerializer from './role-mapping.ee.js'; import samlAuthProviderRoleMappingSerializer from './role-mapping.ee.js';
import appAuthClientSerializer from './app-auth-client.js'; import oauthClientSerializer from './oauth-client.js';
import appConfigSerializer from './app-config.js'; import appConfigSerializer from './app-config.js';
import flowSerializer from './flow.js'; import flowSerializer from './flow.js';
import stepSerializer from './step.js'; import stepSerializer from './step.js';
@@ -28,7 +28,7 @@ const serializers = {
AdminSamlAuthProvider: adminSamlAuthProviderSerializer, AdminSamlAuthProvider: adminSamlAuthProviderSerializer,
SamlAuthProvider: samlAuthProviderSerializer, SamlAuthProvider: samlAuthProviderSerializer,
RoleMapping: samlAuthProviderRoleMappingSerializer, RoleMapping: samlAuthProviderRoleMappingSerializer,
AppAuthClient: appAuthClientSerializer, OAuthClient: oauthClientSerializer,
AppConfig: appConfigSerializer, AppConfig: appConfigSerializer,
Flow: flowSerializer, Flow: flowSerializer,
Step: stepSerializer, Step: stepSerializer,

View File

@@ -0,0 +1,10 @@
const oauthClientSerializer = (oauthClient) => {
return {
id: oauthClient.id,
appConfigId: oauthClient.appConfigId,
name: oauthClient.name,
active: oauthClient.active,
};
};
export default oauthClientSerializer;

View File

@@ -0,0 +1,22 @@
import { describe, it, expect, beforeEach } from 'vitest';
import { createOAuthClient } from '../../test/factories/oauth-client';
import oauthClientSerializer from './oauth-client';
describe('oauthClient serializer', () => {
let oauthClient;
beforeEach(async () => {
oauthClient = await createOAuthClient();
});
it('should return oauth client data', async () => {
const expectedPayload = {
id: oauthClient.id,
appConfigId: oauthClient.appConfigId,
name: oauthClient.name,
active: oauthClient.active,
};
expect(oauthClientSerializer(oauthClient)).toStrictEqual(expectedPayload);
});
});

View File

@@ -1,5 +1,5 @@
import { faker } from '@faker-js/faker'; import { faker } from '@faker-js/faker';
import AppAuthClient from '../../src/models/app-auth-client'; import OAuthClient from '../../src/models/oauth-client';
const formattedAuthDefaults = { const formattedAuthDefaults = {
oAuthRedirectUrl: faker.internet.url(), oAuthRedirectUrl: faker.internet.url(),
@@ -8,14 +8,14 @@ const formattedAuthDefaults = {
clientSecret: faker.string.uuid(), clientSecret: faker.string.uuid(),
}; };
export const createAppAuthClient = async (params = {}) => { export const createOAuthClient = async (params = {}) => {
params.name = params?.name || faker.person.fullName(); params.name = params?.name || faker.person.fullName();
params.appKey = params?.appKey || 'deepl'; params.appKey = params?.appKey || 'deepl';
params.active = params?.active ?? true; params.active = params?.active ?? true;
params.formattedAuthDefaults = params.formattedAuthDefaults =
params?.formattedAuthDefaults || formattedAuthDefaults; params?.formattedAuthDefaults || formattedAuthDefaults;
const appAuthClient = await AppAuthClient.query().insertAndFetch(params); const oauthClient = await OAuthClient.query().insertAndFetch(params);
return appAuthClient; return oauthClient;
}; };

View File

@@ -1,17 +0,0 @@
const createAppAuthClientMock = (appAuthClient) => {
return {
data: {
name: appAuthClient.name,
active: appAuthClient.active,
},
meta: {
count: 1,
currentPage: null,
isArray: false,
totalPages: null,
type: 'AppAuthClient',
},
};
};
export default createAppAuthClientMock;

View File

@@ -0,0 +1,17 @@
const createOAuthClientMock = (oauthClient) => {
return {
data: {
name: oauthClient.name,
active: oauthClient.active,
},
meta: {
count: 1,
currentPage: null,
isArray: false,
totalPages: null,
type: 'OAuthClient',
},
};
};
export default createOAuthClientMock;

View File

@@ -1,18 +0,0 @@
const getAppAuthClientMock = (appAuthClient) => {
return {
data: {
name: appAuthClient.name,
id: appAuthClient.id,
active: appAuthClient.active,
},
meta: {
count: 1,
currentPage: null,
isArray: false,
totalPages: null,
type: 'AppAuthClient',
},
};
};
export default getAppAuthClientMock;

View File

@@ -1,18 +0,0 @@
const getAdminAppAuthClientsMock = (appAuthClients) => {
return {
data: appAuthClients.map((appAuthClient) => ({
name: appAuthClient.name,
id: appAuthClient.id,
active: appAuthClient.active,
})),
meta: {
count: appAuthClients.length,
currentPage: null,
isArray: true,
totalPages: null,
type: 'AppAuthClient',
},
};
};
export default getAdminAppAuthClientsMock;

View File

@@ -0,0 +1,18 @@
const getOAuthClientMock = (oauthClient) => {
return {
data: {
name: oauthClient.name,
id: oauthClient.id,
active: oauthClient.active,
},
meta: {
count: 1,
currentPage: null,
isArray: false,
totalPages: null,
type: 'OAuthClient',
},
};
};
export default getOAuthClientMock;

View File

@@ -0,0 +1,18 @@
const getAdminOAuthClientsMock = (oauthClients) => {
return {
data: oauthClients.map((oauthClient) => ({
name: oauthClient.name,
id: oauthClient.id,
active: oauthClient.active,
})),
meta: {
count: oauthClients.length,
currentPage: null,
isArray: true,
totalPages: null,
type: 'OAuthClient',
},
};
};
export default getAdminOAuthClientsMock;

View File

@@ -1,18 +0,0 @@
const updateAppAuthClientMock = (appAuthClient) => {
return {
data: {
id: appAuthClient.id,
name: appAuthClient.name,
active: appAuthClient.active,
},
meta: {
count: 1,
currentPage: null,
isArray: false,
totalPages: null,
type: 'AppAuthClient',
},
};
};
export default updateAppAuthClientMock;

View File

@@ -0,0 +1,18 @@
const updateOAuthClientMock = (oauthClient) => {
return {
data: {
id: oauthClient.id,
name: oauthClient.name,
active: oauthClient.active,
},
meta: {
count: 1,
currentPage: null,
isArray: false,
totalPages: null,
type: 'OAuthClient',
},
};
};
export default updateOAuthClientMock;

View File

@@ -2,7 +2,7 @@ const createConnection = (connection) => {
const connectionData = { const connectionData = {
id: connection.id, id: connection.id,
key: connection.key, key: connection.key,
appAuthClientId: connection.appAuthClientId, oauthClientId: connection.oauthClientId,
formattedData: connection.formattedData, formattedData: connection.formattedData,
verified: connection.verified || false, verified: connection.verified || false,
createdAt: connection.createdAt.getTime(), createdAt: connection.createdAt.getTime(),

View File

@@ -1,18 +0,0 @@
const getAppAuthClientMock = (appAuthClient) => {
return {
data: {
name: appAuthClient.name,
id: appAuthClient.id,
active: appAuthClient.active,
},
meta: {
count: 1,
currentPage: null,
isArray: false,
totalPages: null,
type: 'AppAuthClient',
},
};
};
export default getAppAuthClientMock;

View File

@@ -1,18 +0,0 @@
const getAppAuthClientsMock = (appAuthClients) => {
return {
data: appAuthClients.map((appAuthClient) => ({
name: appAuthClient.name,
id: appAuthClient.id,
active: appAuthClient.active,
})),
meta: {
count: appAuthClients.length,
currentPage: null,
isArray: true,
totalPages: null,
type: 'AppAuthClient',
},
};
};
export default getAppAuthClientsMock;

View File

@@ -4,7 +4,7 @@ const getConnectionsMock = (connections) => {
id: connection.id, id: connection.id,
key: connection.key, key: connection.key,
verified: connection.verified, verified: connection.verified,
appAuthClientId: connection.appAuthClientId, oauthClientId: connection.oauthClientId,
formattedData: { formattedData: {
screenName: connection.formattedData.screenName, screenName: connection.formattedData.screenName,
}, },

View File

@@ -0,0 +1,18 @@
const getOAuthClientMock = (oauthClient) => {
return {
data: {
name: oauthClient.name,
id: oauthClient.id,
active: oauthClient.active,
},
meta: {
count: 1,
currentPage: null,
isArray: false,
totalPages: null,
type: 'OAuthClient',
},
};
};
export default getOAuthClientMock;

View File

@@ -0,0 +1,18 @@
const getOAuthClientsMock = (oauthClients) => {
return {
data: oauthClients.map((oauthClient) => ({
name: oauthClient.name,
id: oauthClient.id,
active: oauthClient.active,
})),
meta: {
count: oauthClients.length,
currentPage: null,
isArray: true,
totalPages: null,
type: 'OAuthClient',
},
};
};
export default getOAuthClientsMock;

View File

@@ -3,7 +3,7 @@ const resetConnectionMock = (connection) => {
id: connection.id, id: connection.id,
key: connection.key, key: connection.key,
verified: connection.verified, verified: connection.verified,
appAuthClientId: connection.appAuthClientId, oauthClientId: connection.oauthClientId,
formattedData: { formattedData: {
screenName: connection.formattedData.screenName, screenName: connection.formattedData.screenName,
}, },

View File

@@ -3,7 +3,7 @@ const updateConnectionMock = (connection) => {
id: connection.id, id: connection.id,
key: connection.key, key: connection.key,
verified: connection.verified, verified: connection.verified,
appAuthClientId: connection.appAuthClientId, oauthClientId: connection.oauthClientId,
formattedData: { formattedData: {
screenName: connection.formattedData.screenName, screenName: connection.formattedData.screenName,
}, },

View File

@@ -3,7 +3,7 @@ const getConnectionMock = async (connection) => {
id: connection.id, id: connection.id,
key: connection.key, key: connection.key,
verified: connection.verified, verified: connection.verified,
appAuthClientId: connection.appAuthClientId, oauthClientId: connection.oauthClientId,
formattedData: { formattedData: {
screenName: connection.formattedData.screenName, screenName: connection.formattedData.screenName,
}, },

View File

@@ -2,14 +2,14 @@ import { expect } from '@playwright/test';
const { AuthenticatedPage } = require('../authenticated-page'); const { AuthenticatedPage } = require('../authenticated-page');
export class AdminApplicationAuthClientsPage extends AuthenticatedPage { export class AdminApplicationOAuthClientsPage extends AuthenticatedPage {
/** /**
* @param {import('@playwright/test').Page} page * @param {import('@playwright/test').Page} page
*/ */
constructor(page) { constructor(page) {
super(page); super(page);
this.authClientsTab = this.page.getByTestId('auth-clients-tab'); this.authClientsTab = this.page.getByTestId('oauth-clients-tab');
this.saveButton = this.page.getByTestId('submitButton'); this.saveButton = this.page.getByTestId('submitButton');
this.successSnackbar = this.page.getByTestId( this.successSnackbar = this.page.getByTestId(
'snackbar-save-admin-apps-settings-success' 'snackbar-save-admin-apps-settings-success'

View File

@@ -8,7 +8,9 @@ const { AdminEditRolePage } = require('./edit-role-page');
const { AdminApplicationsPage } = require('./applications-page'); const { AdminApplicationsPage } = require('./applications-page');
const { AdminApplicationSettingsPage } = require('./application-settings-page'); const { AdminApplicationSettingsPage } = require('./application-settings-page');
const { AdminApplicationAuthClientsPage } = require('./application-auth-clients-page'); const {
AdminApplicationOAuthClientsPage,
} = require('./application-oauth-clients-page');
export const adminFixtures = { export const adminFixtures = {
adminUsersPage: async ({ page }, use) => { adminUsersPage: async ({ page }, use) => {
@@ -35,8 +37,7 @@ export const adminFixtures = {
adminApplicationSettingsPage: async ({ page }, use) => { adminApplicationSettingsPage: async ({ page }, use) => {
await use(new AdminApplicationSettingsPage(page)); await use(new AdminApplicationSettingsPage(page));
}, },
adminApplicationAuthClientsPage: async ({ page }, use) => { adminApplicationOAuthClientsPage: async ({ page }, use) => {
await use(new AdminApplicationAuthClientsPage(page)); await use(new AdminApplicationOAuthClientsPage(page));
} },
}; };

View File

@@ -4,8 +4,8 @@ const { insertAppConnection } = require('../../helpers/db-helpers');
test.describe('Admin Applications', () => { test.describe('Admin Applications', () => {
test.beforeAll(async () => { test.beforeAll(async () => {
const deleteAppAuthClients = { const deleteOAuthClients = {
text: 'DELETE FROM app_auth_clients WHERE app_key in ($1, $2, $3, $4, $5, $6)', text: 'DELETE FROM oauth_clients WHERE app_key in ($1, $2, $3, $4, $5, $6)',
values: [ values: [
'carbone', 'carbone',
'spotify', 'spotify',
@@ -29,10 +29,8 @@ test.describe('Admin Applications', () => {
}; };
try { try {
const deleteAppAuthClientsResult = await pgPool.query( const deleteOAuthClientsResult = await pgPool.query(deleteOAuthClients);
deleteAppAuthClients expect(deleteOAuthClientsResult.command).toBe('DELETE');
);
expect(deleteAppAuthClientsResult.command).toBe('DELETE');
const deleteAppConfigsResult = await pgPool.query(deleteAppConfigs); const deleteAppConfigsResult = await pgPool.query(deleteAppConfigs);
expect(deleteAppConfigsResult.command).toBe('DELETE'); expect(deleteAppConfigsResult.command).toBe('DELETE');
} catch (err) { } catch (err) {
@@ -73,7 +71,7 @@ test.describe('Admin Applications', () => {
test('should allow only custom connections', async ({ test('should allow only custom connections', async ({
adminApplicationsPage, adminApplicationsPage,
adminApplicationSettingsPage, adminApplicationSettingsPage,
adminApplicationAuthClientsPage, adminApplicationOAuthClientsPage,
flowEditorPage, flowEditorPage,
page, page,
}) => { }) => {
@@ -97,9 +95,9 @@ test.describe('Admin Applications', () => {
adminApplicationSettingsPage.disableConnectionsSwitch adminApplicationSettingsPage.disableConnectionsSwitch
).not.toBeChecked(); ).not.toBeChecked();
await adminApplicationAuthClientsPage.openAuthClientsTab(); await adminApplicationOAuthClientsPage.openAuthClientsTab();
await expect( await expect(
adminApplicationAuthClientsPage.createFirstAuthClientButton adminApplicationOAuthClientsPage.createFirstAuthClientButton
).toHaveCount(1); ).toHaveCount(1);
await page.goto('/'); await page.goto('/');
@@ -119,9 +117,9 @@ test.describe('Admin Applications', () => {
const newConnectionOption = page const newConnectionOption = page
.getByRole('option') .getByRole('option')
.filter({ hasText: 'Add new connection' }); .filter({ hasText: 'Add new connection' });
const newSharedConnectionOption = page const newOAuthConnectionOption = page
.getByRole('option') .getByRole('option')
.filter({ hasText: 'Add new connection with auth client' }); .filter({ hasText: 'Add connection with OAuth client' });
const existingConnection = page const existingConnection = page
.getByRole('option') .getByRole('option')
.filter({ hasText: 'Unnamed' }); .filter({ hasText: 'Unnamed' });
@@ -129,13 +127,13 @@ test.describe('Admin Applications', () => {
await expect(await existingConnection.count()).toBeGreaterThan(0); await expect(await existingConnection.count()).toBeGreaterThan(0);
await expect(newConnectionOption).toBeEnabled(); await expect(newConnectionOption).toBeEnabled();
await expect(newConnectionOption).toHaveCount(1); await expect(newConnectionOption).toHaveCount(1);
await expect(newSharedConnectionOption).toHaveCount(0); await expect(newOAuthConnectionOption).toHaveCount(0);
}); });
test('should allow only predefined connections and existing custom', async ({ test('should allow only predefined connections and existing custom', async ({
adminApplicationsPage, adminApplicationsPage,
adminApplicationSettingsPage, adminApplicationSettingsPage,
adminApplicationAuthClientsPage, adminApplicationOAuthClientsPage,
flowEditorPage, flowEditorPage,
page, page,
}) => { }) => {
@@ -155,8 +153,8 @@ test.describe('Admin Applications', () => {
await adminApplicationSettingsPage.saveSettings(); await adminApplicationSettingsPage.saveSettings();
await adminApplicationSettingsPage.expectSuccessSnackbarToBeVisible(); await adminApplicationSettingsPage.expectSuccessSnackbarToBeVisible();
await adminApplicationAuthClientsPage.openAuthClientsTab(); await adminApplicationOAuthClientsPage.openAuthClientsTab();
await adminApplicationAuthClientsPage.openFirstAuthClientCreateForm(); await adminApplicationOAuthClientsPage.openFirstAuthClientCreateForm();
const authClientForm = page.getByTestId('auth-client-form'); const authClientForm = page.getByTestId('auth-client-form');
await authClientForm.locator(page.getByTestId('switch')).check(); await authClientForm.locator(page.getByTestId('switch')).check();
await authClientForm await authClientForm
@@ -168,8 +166,8 @@ test.describe('Admin Applications', () => {
await authClientForm await authClientForm
.locator(page.locator('[name="clientSecret"]')) .locator(page.locator('[name="clientSecret"]'))
.fill('spotifyClientSecret'); .fill('spotifyClientSecret');
await adminApplicationAuthClientsPage.submitAuthClientForm(); await adminApplicationOAuthClientsPage.submitAuthClientForm();
await adminApplicationAuthClientsPage.authClientShouldBeVisible( await adminApplicationOAuthClientsPage.authClientShouldBeVisible(
'spotifyAuthClient' 'spotifyAuthClient'
); );
@@ -189,23 +187,23 @@ test.describe('Admin Applications', () => {
const newConnectionOption = page const newConnectionOption = page
.getByRole('option') .getByRole('option')
.filter({ hasText: 'Add new connection' }); .filter({ hasText: 'Add new connection' });
const newSharedConnectionOption = page const newOAuthConnectionOption = page
.getByRole('option') .getByRole('option')
.filter({ hasText: 'Add connection with auth client' }); .filter({ hasText: 'Add connection with OAuth client' });
const existingConnection = page const existingConnection = page
.getByRole('option') .getByRole('option')
.filter({ hasText: 'Unnamed' }); .filter({ hasText: 'Unnamed' });
await expect(await existingConnection.count()).toBeGreaterThan(0); await expect(await existingConnection.count()).toBeGreaterThan(0);
await expect(newConnectionOption).toHaveCount(0); await expect(newConnectionOption).toHaveCount(0);
await expect(newSharedConnectionOption).toBeEnabled(); await expect(newOAuthConnectionOption).toBeEnabled();
await expect(newSharedConnectionOption).toHaveCount(1); await expect(newOAuthConnectionOption).toHaveCount(1);
}); });
test('should allow all connections', async ({ test('should allow all connections', async ({
adminApplicationsPage, adminApplicationsPage,
adminApplicationSettingsPage, adminApplicationSettingsPage,
adminApplicationAuthClientsPage, adminApplicationOAuthClientsPage,
flowEditorPage, flowEditorPage,
page, page,
}) => { }) => {
@@ -221,8 +219,8 @@ test.describe('Admin Applications', () => {
adminApplicationSettingsPage.disableConnectionsSwitch adminApplicationSettingsPage.disableConnectionsSwitch
).not.toBeChecked(); ).not.toBeChecked();
await adminApplicationAuthClientsPage.openAuthClientsTab(); await adminApplicationOAuthClientsPage.openAuthClientsTab();
await adminApplicationAuthClientsPage.openFirstAuthClientCreateForm(); await adminApplicationOAuthClientsPage.openFirstAuthClientCreateForm();
const authClientForm = page.getByTestId('auth-client-form'); const authClientForm = page.getByTestId('auth-client-form');
await authClientForm.locator(page.getByTestId('switch')).check(); await authClientForm.locator(page.getByTestId('switch')).check();
await authClientForm await authClientForm
@@ -234,8 +232,8 @@ test.describe('Admin Applications', () => {
await authClientForm await authClientForm
.locator(page.locator('[name="clientSecret"]')) .locator(page.locator('[name="clientSecret"]'))
.fill('redditClientSecret'); .fill('redditClientSecret');
await adminApplicationAuthClientsPage.submitAuthClientForm(); await adminApplicationOAuthClientsPage.submitAuthClientForm();
await adminApplicationAuthClientsPage.authClientShouldBeVisible( await adminApplicationOAuthClientsPage.authClientShouldBeVisible(
'redditAuthClient' 'redditAuthClient'
); );
@@ -255,23 +253,23 @@ test.describe('Admin Applications', () => {
const newConnectionOption = page const newConnectionOption = page
.getByRole('option') .getByRole('option')
.filter({ hasText: 'Add new connection' }); .filter({ hasText: 'Add new connection' });
const newSharedConnectionOption = page const newOAuthConnectionOption = page
.getByRole('option') .getByRole('option')
.filter({ hasText: 'Add connection with auth client' }); .filter({ hasText: 'Add connection with OAuth client' });
const existingConnection = page const existingConnection = page
.getByRole('option') .getByRole('option')
.filter({ hasText: 'Unnamed' }); .filter({ hasText: 'Unnamed' });
await expect(await existingConnection.count()).toBeGreaterThan(0); await expect(await existingConnection.count()).toBeGreaterThan(0);
await expect(newConnectionOption).toHaveCount(1); await expect(newConnectionOption).toHaveCount(1);
await expect(newSharedConnectionOption).toBeEnabled(); await expect(newOAuthConnectionOption).toBeEnabled();
await expect(newSharedConnectionOption).toHaveCount(1); await expect(newOAuthConnectionOption).toHaveCount(1);
}); });
test('should not allow new connections but existing custom', async ({ test('should not allow new connections but existing custom', async ({
adminApplicationsPage, adminApplicationsPage,
adminApplicationSettingsPage, adminApplicationSettingsPage,
adminApplicationAuthClientsPage, adminApplicationOAuthClientsPage,
flowEditorPage, flowEditorPage,
page, page,
}) => { }) => {
@@ -284,8 +282,8 @@ test.describe('Admin Applications', () => {
await adminApplicationSettingsPage.saveSettings(); await adminApplicationSettingsPage.saveSettings();
await adminApplicationSettingsPage.expectSuccessSnackbarToBeVisible(); await adminApplicationSettingsPage.expectSuccessSnackbarToBeVisible();
await adminApplicationAuthClientsPage.openAuthClientsTab(); await adminApplicationOAuthClientsPage.openAuthClientsTab();
await adminApplicationAuthClientsPage.openFirstAuthClientCreateForm(); await adminApplicationOAuthClientsPage.openFirstAuthClientCreateForm();
const authClientForm = page.getByTestId('auth-client-form'); const authClientForm = page.getByTestId('auth-client-form');
await authClientForm.locator(page.getByTestId('switch')).check(); await authClientForm.locator(page.getByTestId('switch')).check();
@@ -298,8 +296,8 @@ test.describe('Admin Applications', () => {
await authClientForm await authClientForm
.locator(page.locator('[name="clientSecret"]')) .locator(page.locator('[name="clientSecret"]'))
.fill('clickupClientSecret'); .fill('clickupClientSecret');
await adminApplicationAuthClientsPage.submitAuthClientForm(); await adminApplicationOAuthClientsPage.submitAuthClientForm();
await adminApplicationAuthClientsPage.authClientShouldBeVisible( await adminApplicationOAuthClientsPage.authClientShouldBeVisible(
'clickupAuthClient' 'clickupAuthClient'
); );
@@ -319,22 +317,22 @@ test.describe('Admin Applications', () => {
const newConnectionOption = page const newConnectionOption = page
.getByRole('option') .getByRole('option')
.filter({ hasText: 'Add new connection' }); .filter({ hasText: 'Add new connection' });
const newSharedConnectionOption = page const newOAuthConnectionOption = page
.getByRole('option') .getByRole('option')
.filter({ hasText: 'Add connection with auth client' }); .filter({ hasText: 'Add connection with OAuth client' });
const existingConnection = page const existingConnection = page
.getByRole('option') .getByRole('option')
.filter({ hasText: 'Unnamed' }); .filter({ hasText: 'Unnamed' });
await expect(await existingConnection.count()).toBeGreaterThan(0); await expect(await existingConnection.count()).toBeGreaterThan(0);
await expect(newConnectionOption).toHaveCount(0); await expect(newConnectionOption).toHaveCount(0);
await expect(newSharedConnectionOption).toHaveCount(0); await expect(newOAuthConnectionOption).toHaveCount(0);
}); });
test('should not allow new connections but existing custom even if predefined auth clients are enabled', async ({ test('should not allow new connections but existing custom even if predefined OAuth clients are enabled', async ({
adminApplicationsPage, adminApplicationsPage,
adminApplicationSettingsPage, adminApplicationSettingsPage,
adminApplicationAuthClientsPage, adminApplicationOAuthClientsPage,
flowEditorPage, flowEditorPage,
page, page,
}) => { }) => {
@@ -350,8 +348,8 @@ test.describe('Admin Applications', () => {
await adminApplicationSettingsPage.saveSettings(); await adminApplicationSettingsPage.saveSettings();
await adminApplicationSettingsPage.expectSuccessSnackbarToBeVisible(); await adminApplicationSettingsPage.expectSuccessSnackbarToBeVisible();
await adminApplicationAuthClientsPage.openAuthClientsTab(); await adminApplicationOAuthClientsPage.openAuthClientsTab();
await adminApplicationAuthClientsPage.openFirstAuthClientCreateForm(); await adminApplicationOAuthClientsPage.openFirstAuthClientCreateForm();
const authClientForm = page.getByTestId('auth-client-form'); const authClientForm = page.getByTestId('auth-client-form');
await authClientForm.locator(page.getByTestId('switch')).check(); await authClientForm.locator(page.getByTestId('switch')).check();
@@ -364,8 +362,8 @@ test.describe('Admin Applications', () => {
await authClientForm await authClientForm
.locator(page.locator('[name="clientSecret"]')) .locator(page.locator('[name="clientSecret"]'))
.fill('mailchimpClientSecret'); .fill('mailchimpClientSecret');
await adminApplicationAuthClientsPage.submitAuthClientForm(); await adminApplicationOAuthClientsPage.submitAuthClientForm();
await adminApplicationAuthClientsPage.authClientShouldBeVisible( await adminApplicationOAuthClientsPage.authClientShouldBeVisible(
'mailchimpAuthClient' 'mailchimpAuthClient'
); );
@@ -389,9 +387,9 @@ test.describe('Admin Applications', () => {
const newConnectionOption = page const newConnectionOption = page
.getByRole('option') .getByRole('option')
.filter({ hasText: 'Add new connection' }); .filter({ hasText: 'Add new connection' });
const newSharedConnectionOption = page const newOAuthConnectionOption = page
.getByRole('option') .getByRole('option')
.filter({ hasText: 'Add new shared connection' }); .filter({ hasText: 'Add connection with OAuth client' });
const noConnectionsOption = page const noConnectionsOption = page
.locator('.MuiAutocomplete-noOptions') .locator('.MuiAutocomplete-noOptions')
.filter({ hasText: 'No options' }); .filter({ hasText: 'No options' });
@@ -399,6 +397,6 @@ test.describe('Admin Applications', () => {
await expect(await existingConnection.count()).toBeGreaterThan(0); await expect(await existingConnection.count()).toBeGreaterThan(0);
await expect(noConnectionsOption).toHaveCount(0); await expect(noConnectionsOption).toHaveCount(0);
await expect(newConnectionOption).toHaveCount(0); await expect(newConnectionOption).toHaveCount(0);
await expect(newSharedConnectionOption).toHaveCount(0); await expect(newOAuthConnectionOption).toHaveCount(0);
}); });
}); });

View File

@@ -55,7 +55,7 @@ test.describe('Apps page', () => {
test('goes to app page to create a connection', async ({ test('goes to app page to create a connection', async ({
applicationsPage, applicationsPage,
}) => { }) => {
// loading app, app config, app auth clients take time // loading app, app config, app oauth clients take time
test.setTimeout(60000); test.setTimeout(60000);
await applicationsPage.page.getByTestId('app-list-item').first().click(); await applicationsPage.page.getByTestId('app-list-item').first().click();

View File

@@ -9,7 +9,7 @@ import * as React from 'react';
import { useNavigate, useSearchParams } from 'react-router-dom'; import { useNavigate, useSearchParams } from 'react-router-dom';
import { AppPropType } from 'propTypes/propTypes'; import { AppPropType } from 'propTypes/propTypes';
import AppAuthClientsDialog from 'components/AppAuthClientsDialog/index.ee'; import AppOAuthClientsDialog from 'components/OAuthClientsDialog/index.ee';
import InputCreator from 'components/InputCreator'; import InputCreator from 'components/InputCreator';
import * as URLS from 'config/urls'; import * as URLS from 'config/urls';
import useAuthenticateApp from 'hooks/useAuthenticateApp.ee'; import useAuthenticateApp from 'hooks/useAuthenticateApp.ee';
@@ -31,12 +31,12 @@ function AddAppConnection(props) {
const [inProgress, setInProgress] = React.useState(false); const [inProgress, setInProgress] = React.useState(false);
const hasConnection = Boolean(connectionId); const hasConnection = Boolean(connectionId);
const useShared = searchParams.get('shared') === 'true'; const useShared = searchParams.get('shared') === 'true';
const appAuthClientId = searchParams.get('appAuthClientId') || undefined; const oauthClientId = searchParams.get('oauthClientId') || undefined;
const { authenticate } = useAuthenticateApp({ const { authenticate } = useAuthenticateApp({
appKey: key, appKey: key,
connectionId, connectionId,
appAuthClientId, oauthClientId,
useShared: !!appAuthClientId, useShared: !!oauthClientId,
}); });
const queryClient = useQueryClient(); const queryClient = useQueryClient();
@@ -52,8 +52,8 @@ function AddAppConnection(props) {
}, []); }, []);
React.useEffect( React.useEffect(
function initiateSharedAuthenticationForGivenAuthClient() { function initiateSharedAuthenticationForGivenOAuthClient() {
if (!appAuthClientId) return; if (!oauthClientId) return;
if (!authenticate) return; if (!authenticate) return;
@@ -64,13 +64,13 @@ function AddAppConnection(props) {
asyncAuthenticate(); asyncAuthenticate();
}, },
[appAuthClientId, authenticate, key, navigate], [oauthClientId, authenticate, key, navigate],
); );
const handleClientClick = (appAuthClientId) => const handleClientClick = (oauthClientId) =>
navigate(URLS.APP_ADD_CONNECTION_WITH_AUTH_CLIENT_ID(key, appAuthClientId)); navigate(URLS.APP_ADD_CONNECTION_WITH_OAUTH_CLIENT_ID(key, oauthClientId));
const handleAuthClientsDialogClose = () => const handleOAuthClientsDialogClose = () =>
navigate(URLS.APP_CONNECTIONS(key)); navigate(URLS.APP_CONNECTIONS(key));
const submitHandler = React.useCallback( const submitHandler = React.useCallback(
@@ -104,14 +104,14 @@ function AddAppConnection(props) {
if (useShared) if (useShared)
return ( return (
<AppAuthClientsDialog <AppOAuthClientsDialog
appKey={key} appKey={key}
onClose={handleAuthClientsDialogClose} onClose={handleOAuthClientsDialogClose}
onClientClick={handleClientClick} onClientClick={handleClientClick}
/> />
); );
if (appAuthClientId) return <React.Fragment />; if (oauthClientId) return <React.Fragment />;
return ( return (
<Dialog <Dialog

View File

@@ -5,11 +5,11 @@ import { AppPropType } from 'propTypes/propTypes';
import useAdminCreateAppConfig from 'hooks/useAdminCreateAppConfig'; import useAdminCreateAppConfig from 'hooks/useAdminCreateAppConfig';
import useAppConfig from 'hooks/useAppConfig.ee'; import useAppConfig from 'hooks/useAppConfig.ee';
import useFormatMessage from 'hooks/useFormatMessage'; import useFormatMessage from 'hooks/useFormatMessage';
import useAdminCreateAppAuthClient from 'hooks/useAdminCreateAppAuthClient.ee'; import useAdminCreateOAuthClient from 'hooks/useAdminCreateOAuthClient.ee';
import AdminApplicationAuthClientDialog from 'components/AdminApplicationAuthClientDialog'; import AdminApplicationOAuthClientDialog from 'components/AdminApplicationOAuthClientDialog';
import useAppAuth from 'hooks/useAppAuth'; import useAppAuth from 'hooks/useAppAuth';
function AdminApplicationCreateAuthClient(props) { function AdminApplicationCreateOAuthClient(props) {
const { appKey, onClose } = props; const { appKey, onClose } = props;
const { data: auth } = useAppAuth(appKey); const { data: auth } = useAppAuth(appKey);
const formatMessage = useFormatMessage(); const formatMessage = useFormatMessage();
@@ -24,10 +24,10 @@ function AdminApplicationCreateAuthClient(props) {
} = useAdminCreateAppConfig(props.appKey); } = useAdminCreateAppConfig(props.appKey);
const { const {
mutateAsync: createAppAuthClient, mutateAsync: createOAuthClient,
isPending: isCreateAppAuthClientPending, isPending: isCreateOAuthClientPending,
error: createAppAuthClientError, error: createOAuthClientError,
} = useAdminCreateAppAuthClient(appKey); } = useAdminCreateOAuthClient(appKey);
const submitHandler = async (values) => { const submitHandler = async (values) => {
let appConfigKey = appConfig?.data?.key; let appConfigKey = appConfig?.data?.key;
@@ -43,7 +43,7 @@ function AdminApplicationCreateAuthClient(props) {
const { name, active, ...formattedAuthDefaults } = values; const { name, active, ...formattedAuthDefaults } = values;
await createAppAuthClient({ await createOAuthClient({
appKey, appKey,
name, name,
active, active,
@@ -81,23 +81,23 @@ function AdminApplicationCreateAuthClient(props) {
); );
return ( return (
<AdminApplicationAuthClientDialog <AdminApplicationOAuthClientDialog
onClose={onClose} onClose={onClose}
error={createAppConfigError || createAppAuthClientError} error={createAppConfigError || createOAuthClientError}
title={formatMessage('createAuthClient.title')} title={formatMessage('createOAuthClient.title')}
loading={isAppConfigLoading} loading={isAppConfigLoading}
submitHandler={submitHandler} submitHandler={submitHandler}
authFields={auth?.data?.fields} authFields={auth?.data?.fields}
submitting={isCreateAppConfigPending || isCreateAppAuthClientPending} submitting={isCreateAppConfigPending || isCreateOAuthClientPending}
defaultValues={defaultValues} defaultValues={defaultValues}
/> />
); );
} }
AdminApplicationCreateAuthClient.propTypes = { AdminApplicationCreateOAuthClient.propTypes = {
appKey: PropTypes.string.isRequired, appKey: PropTypes.string.isRequired,
application: AppPropType.isRequired, application: AppPropType.isRequired,
onClose: PropTypes.func.isRequired, onClose: PropTypes.func.isRequired,
}; };
export default AdminApplicationCreateAuthClient; export default AdminApplicationCreateOAuthClient;

View File

@@ -15,7 +15,7 @@ import Switch from 'components/Switch';
import TextField from 'components/TextField'; import TextField from 'components/TextField';
import { Form } from './style'; import { Form } from './style';
function AdminApplicationAuthClientDialog(props) { function AdminApplicationOAuthClientDialog(props) {
const { const {
error, error,
onClose, onClose,
@@ -52,12 +52,12 @@ function AdminApplicationAuthClientDialog(props) {
<> <>
<Switch <Switch
name="active" name="active"
label={formatMessage('authClient.inputActive')} label={formatMessage('oauthClient.inputActive')}
/> />
<TextField <TextField
required={true} required={true}
name="name" name="name"
label={formatMessage('authClient.inputName')} label={formatMessage('oauthClient.inputName')}
fullWidth fullWidth
/> />
{authFields?.map((field) => ( {authFields?.map((field) => (
@@ -72,7 +72,7 @@ function AdminApplicationAuthClientDialog(props) {
loading={submitting} loading={submitting}
disabled={disabled || !isDirty} disabled={disabled || !isDirty}
> >
{formatMessage('authClient.buttonSubmit')} {formatMessage('oauthClient.buttonSubmit')}
</LoadingButton> </LoadingButton>
</> </>
)} )}
@@ -84,7 +84,7 @@ function AdminApplicationAuthClientDialog(props) {
); );
} }
AdminApplicationAuthClientDialog.propTypes = { AdminApplicationOAuthClientDialog.propTypes = {
error: PropTypes.shape({ error: PropTypes.shape({
message: PropTypes.string, message: PropTypes.string,
}), }),
@@ -98,4 +98,4 @@ AdminApplicationAuthClientDialog.propTypes = {
disabled: PropTypes.bool, disabled: PropTypes.bool,
}; };
export default AdminApplicationAuthClientDialog; export default AdminApplicationOAuthClientDialog;

View File

@@ -8,29 +8,30 @@ import CardContent from '@mui/material/CardContent';
import Typography from '@mui/material/Typography'; import Typography from '@mui/material/Typography';
import Chip from '@mui/material/Chip'; import Chip from '@mui/material/Chip';
import Button from '@mui/material/Button'; import Button from '@mui/material/Button';
import NoResultFound from 'components/NoResultFound';
import * as URLS from 'config/urls'; import * as URLS from 'config/urls';
import useFormatMessage from 'hooks/useFormatMessage'; import useFormatMessage from 'hooks/useFormatMessage';
import useAdminAppAuthClients from 'hooks/useAdminAppAuthClients'; import useAdminOAuthClients from 'hooks/useAdminOAuthClients';
import NoResultFound from 'components/NoResultFound';
function AdminApplicationAuthClients(props) { function AdminApplicationOAuthClients(props) {
const { appKey } = props; const { appKey } = props;
const formatMessage = useFormatMessage(); const formatMessage = useFormatMessage();
const { data: appAuthClients, isLoading } = useAdminAppAuthClients(appKey); const { data: appOAuthClients, isLoading } = useAdminOAuthClients(appKey);
if (isLoading) if (isLoading)
return <CircularProgress sx={{ display: 'block', margin: '20px auto' }} />; return <CircularProgress sx={{ display: 'block', margin: '20px auto' }} />;
if (!appAuthClients?.data.length) { if (!appOAuthClients?.data.length) {
return ( return (
<NoResultFound <NoResultFound
to={URLS.ADMIN_APP_AUTH_CLIENTS_CREATE(appKey)} to={URLS.ADMIN_APP_AUTH_CLIENTS_CREATE(appKey)}
text={formatMessage('adminAppsAuthClients.noAuthClients')} text={formatMessage('adminAppsOAuthClients.noOauthClients')}
/> />
); );
} }
const sortedAuthClients = appAuthClients.data.slice().sort((a, b) => { const sortedOAuthClients = appOAuthClients.data.slice().sort((a, b) => {
if (a.id < b.id) { if (a.id < b.id) {
return -1; return -1;
} }
@@ -42,7 +43,7 @@ function AdminApplicationAuthClients(props) {
return ( return (
<div> <div>
{sortedAuthClients.map((client) => ( {sortedOAuthClients.map((client) => (
<Card sx={{ mb: 1 }} key={client.id} data-test="auth-client"> <Card sx={{ mb: 1 }} key={client.id} data-test="auth-client">
<CardActionArea <CardActionArea
component={Link} component={Link}
@@ -59,8 +60,8 @@ function AdminApplicationAuthClients(props) {
variant={client?.active ? 'filled' : 'outlined'} variant={client?.active ? 'filled' : 'outlined'}
label={formatMessage( label={formatMessage(
client?.active client?.active
? 'adminAppsAuthClients.statusActive' ? 'adminAppsOAuthClients.statusActive'
: 'adminAppsAuthClients.statusInactive', : 'adminAppsOAuthClients.statusInactive',
)} )}
/> />
</Stack> </Stack>
@@ -70,8 +71,13 @@ function AdminApplicationAuthClients(props) {
))} ))}
<Stack justifyContent="flex-end" direction="row"> <Stack justifyContent="flex-end" direction="row">
<Link to={URLS.ADMIN_APP_AUTH_CLIENTS_CREATE(appKey)}> <Link to={URLS.ADMIN_APP_AUTH_CLIENTS_CREATE(appKey)}>
<Button variant="contained" sx={{ mt: 2 }} component="div" data-test="create-auth-client-button"> <Button
{formatMessage('createAuthClient.button')} variant="contained"
sx={{ mt: 2 }}
component="div"
data-test="create-auth-client-button"
>
{formatMessage('createOAuthClient.button')}
</Button> </Button>
</Link> </Link>
</Stack> </Stack>
@@ -79,8 +85,8 @@ function AdminApplicationAuthClients(props) {
); );
} }
AdminApplicationAuthClients.propTypes = { AdminApplicationOAuthClients.propTypes = {
appKey: PropTypes.string.isRequired, appKey: PropTypes.string.isRequired,
}; };
export default AdminApplicationAuthClients; export default AdminApplicationOAuthClients;

View File

@@ -4,26 +4,26 @@ import { useParams } from 'react-router-dom';
import { AppPropType } from 'propTypes/propTypes'; import { AppPropType } from 'propTypes/propTypes';
import useFormatMessage from 'hooks/useFormatMessage'; import useFormatMessage from 'hooks/useFormatMessage';
import AdminApplicationAuthClientDialog from 'components/AdminApplicationAuthClientDialog'; import AdminApplicationOAuthClientDialog from 'components/AdminApplicationOAuthClientDialog';
import useAdminAppAuthClient from 'hooks/useAdminAppAuthClient.ee'; import useAdminOAuthClient from 'hooks/useAdminOAuthClient.ee';
import useAdminUpdateAppAuthClient from 'hooks/useAdminUpdateAppAuthClient.ee'; import useAdminUpdateOAuthClient from 'hooks/useAdminUpdateOAuthClient.ee';
import useAppAuth from 'hooks/useAppAuth'; import useAppAuth from 'hooks/useAppAuth';
function AdminApplicationUpdateAuthClient(props) { function AdminApplicationUpdateOAuthClient(props) {
const { application, onClose } = props; const { application, onClose } = props;
const formatMessage = useFormatMessage(); const formatMessage = useFormatMessage();
const { clientId } = useParams(); const { clientId } = useParams();
const { data: adminAppAuthClient, isLoading: isAdminAuthClientLoading } = const { data: adminOAuthClient, isLoading: isAdminOAuthClientLoading } =
useAdminAppAuthClient(application.key, clientId); useAdminOAuthClient(application.key, clientId);
const { data: auth } = useAppAuth(application.key); const { data: auth } = useAppAuth(application.key);
const { const {
mutateAsync: updateAppAuthClient, mutateAsync: updateOAuthClient,
isPending: isUpdateAppAuthClientPending, isPending: isUpdateOAuthClientPending,
error: updateAppAuthClientError, error: updateOAuthClientError,
} = useAdminUpdateAppAuthClient(application.key, clientId); } = useAdminUpdateOAuthClient(application.key, clientId);
const authFields = auth?.data?.fields?.map((field) => ({ const authFields = auth?.data?.fields?.map((field) => ({
...field, ...field,
@@ -31,13 +31,13 @@ function AdminApplicationUpdateAuthClient(props) {
})); }));
const submitHandler = async (values) => { const submitHandler = async (values) => {
if (!adminAppAuthClient) { if (!adminOAuthClient) {
return; return;
} }
const { name, active, ...formattedAuthDefaults } = values; const { name, active, ...formattedAuthDefaults } = values;
await updateAppAuthClient({ await updateOAuthClient({
name, name,
active, active,
formattedAuthDefaults, formattedAuthDefaults,
@@ -64,31 +64,31 @@ function AdminApplicationUpdateAuthClient(props) {
const defaultValues = useMemo( const defaultValues = useMemo(
() => ({ () => ({
name: adminAppAuthClient?.data?.name || '', name: adminOAuthClient?.data?.name || '',
active: adminAppAuthClient?.data?.active || false, active: adminOAuthClient?.data?.active || false,
...getAuthFieldsDefaultValues(), ...getAuthFieldsDefaultValues(),
}), }),
[adminAppAuthClient, getAuthFieldsDefaultValues], [adminOAuthClient, getAuthFieldsDefaultValues],
); );
return ( return (
<AdminApplicationAuthClientDialog <AdminApplicationOAuthClientDialog
onClose={onClose} onClose={onClose}
error={updateAppAuthClientError} error={updateOAuthClientError}
title={formatMessage('updateAuthClient.title')} title={formatMessage('updateOAuthClient.title')}
loading={isAdminAuthClientLoading} loading={isAdminOAuthClientLoading}
submitHandler={submitHandler} submitHandler={submitHandler}
authFields={authFields} authFields={authFields}
submitting={isUpdateAppAuthClientPending} submitting={isUpdateOAuthClientPending}
defaultValues={defaultValues} defaultValues={defaultValues}
disabled={!adminAppAuthClient} disabled={!adminOAuthClient}
/> />
); );
} }
AdminApplicationUpdateAuthClient.propTypes = { AdminApplicationUpdateOAuthClient.propTypes = {
application: AppPropType.isRequired, application: AppPropType.isRequired,
onClose: PropTypes.func.isRequired, onClose: PropTypes.func.isRequired,
}; };
export default AdminApplicationUpdateAuthClient; export default AdminApplicationUpdateOAuthClient;

View File

@@ -70,7 +70,7 @@ function ContextMenu(props) {
to={URLS.APP_RECONNECT_CONNECTION( to={URLS.APP_RECONNECT_CONNECTION(
appKey, appKey,
connection.id, connection.id,
connection.appAuthClientId, connection.oauthClientId,
)} )}
onClick={createActionHandler({ type: 'reconnect' })} onClick={createActionHandler({ type: 'reconnect' })}
> >

View File

@@ -7,7 +7,7 @@ import TextField from '@mui/material/TextField';
import * as React from 'react'; import * as React from 'react';
import AddAppConnection from 'components/AddAppConnection'; import AddAppConnection from 'components/AddAppConnection';
import AppAuthClientsDialog from 'components/AppAuthClientsDialog/index.ee'; import AppOAuthClientsDialog from 'components/OAuthClientsDialog/index.ee';
import FlowSubstepTitle from 'components/FlowSubstepTitle'; import FlowSubstepTitle from 'components/FlowSubstepTitle';
import useAppConfig from 'hooks/useAppConfig.ee'; import useAppConfig from 'hooks/useAppConfig.ee';
import { EditorContext } from 'contexts/Editor'; import { EditorContext } from 'contexts/Editor';
@@ -22,7 +22,7 @@ import useStepConnection from 'hooks/useStepConnection';
import { useQueryClient } from '@tanstack/react-query'; import { useQueryClient } from '@tanstack/react-query';
import useAppConnections from 'hooks/useAppConnections'; import useAppConnections from 'hooks/useAppConnections';
import useTestConnection from 'hooks/useTestConnection'; import useTestConnection from 'hooks/useTestConnection';
import useAppAuthClients from 'hooks/useAppAuthClients'; import useOAuthClients from 'hooks/useOAuthClients';
const ADD_CONNECTION_VALUE = 'ADD_CONNECTION'; const ADD_CONNECTION_VALUE = 'ADD_CONNECTION';
const ADD_SHARED_CONNECTION_VALUE = 'ADD_SHARED_CONNECTION'; const ADD_SHARED_CONNECTION_VALUE = 'ADD_SHARED_CONNECTION';
@@ -54,7 +54,7 @@ function ChooseConnectionSubstep(props) {
const [showAddSharedConnectionDialog, setShowAddSharedConnectionDialog] = const [showAddSharedConnectionDialog, setShowAddSharedConnectionDialog] =
React.useState(false); React.useState(false);
const queryClient = useQueryClient(); const queryClient = useQueryClient();
const { data: appAuthClients } = useAppAuthClients(application.key); const { data: appOAuthClients } = useOAuthClients(application.key);
const { authenticate } = useAuthenticateApp({ const { authenticate } = useAuthenticateApp({
appKey: application.key, appKey: application.key,
@@ -100,9 +100,9 @@ function ChooseConnectionSubstep(props) {
value: ADD_CONNECTION_VALUE, value: ADD_CONNECTION_VALUE,
}; };
const addConnectionWithAuthClient = { const addConnectionWithOAuthClient = {
label: formatMessage( label: formatMessage(
'chooseConnectionSubstep.addConnectionWithAuthClient', 'chooseConnectionSubstep.addConnectionWithOAuthClient',
), ),
value: ADD_SHARED_CONNECTION_VALUE, value: ADD_SHARED_CONNECTION_VALUE,
}; };
@@ -115,33 +115,33 @@ function ChooseConnectionSubstep(props) {
// app is disabled. // app is disabled.
if (appConfig.data.disabled) return options; if (appConfig.data.disabled) return options;
// means only auth clients are allowed for connection creation and there is app auth client // means only OAuth clients are allowed for connection creation and there is OAuth client
if ( if (
appConfig.data.useOnlyPredefinedAuthClients === true && appConfig.data.useOnlyPredefinedAuthClients === true &&
appAuthClients.data.length > 0 appOAuthClients.data.length > 0
) { ) {
return options.concat([addConnectionWithAuthClient]); return options.concat([addConnectionWithOAuthClient]);
} }
// means there is no app auth client. so we don't show the `addConnectionWithAuthClient` // means there is no OAuth client. so we don't show the `addConnectionWithOAuthClient`
if ( if (
appConfig.data.useOnlyPredefinedAuthClients === true && appConfig.data.useOnlyPredefinedAuthClients === true &&
appAuthClients.data.length === 0 appOAuthClients.data.length === 0
) { ) {
return options; return options;
} }
if (appAuthClients.data.length === 0) { if (appOAuthClients.data.length === 0) {
return options.concat([addCustomConnection]); return options.concat([addCustomConnection]);
} }
return options.concat([addCustomConnection, addConnectionWithAuthClient]); return options.concat([addCustomConnection, addConnectionWithOAuthClient]);
}, [data, formatMessage, appConfig, appAuthClients]); }, [data, formatMessage, appConfig, appOAuthClients]);
const handleClientClick = async (appAuthClientId) => { const handleClientClick = async (oauthClientId) => {
try { try {
const response = await authenticate?.({ const response = await authenticate?.({
appAuthClientId, oauthClientId,
}); });
const connectionId = response?.createConnection.id; const connectionId = response?.createConnection.id;
@@ -292,7 +292,7 @@ function ChooseConnectionSubstep(props) {
)} )}
{application && showAddSharedConnectionDialog && ( {application && showAddSharedConnectionDialog && (
<AppAuthClientsDialog <AppOAuthClientsDialog
appKey={application.key} appKey={application.key}
onClose={() => setShowAddSharedConnectionDialog(false)} onClose={() => setShowAddSharedConnectionDialog(false)}
onClientClick={handleClientClick} onClientClick={handleClientClick}

View File

@@ -6,26 +6,26 @@ import ListItem from '@mui/material/ListItem';
import ListItemButton from '@mui/material/ListItemButton'; import ListItemButton from '@mui/material/ListItemButton';
import ListItemText from '@mui/material/ListItemText'; import ListItemText from '@mui/material/ListItemText';
import * as React from 'react'; import * as React from 'react';
import useAppAuthClients from 'hooks/useAppAuthClients'; import useOAuthClients from 'hooks/useOAuthClients';
import useFormatMessage from 'hooks/useFormatMessage'; import useFormatMessage from 'hooks/useFormatMessage';
function AppAuthClientsDialog(props) { function AppOAuthClientsDialog(props) {
const { appKey, onClientClick, onClose } = props; const { appKey, onClientClick, onClose } = props;
const { data: appAuthClients } = useAppAuthClients(appKey); const { data: appOAuthClients } = useOAuthClients(appKey);
const formatMessage = useFormatMessage(); const formatMessage = useFormatMessage();
if (!appAuthClients?.data.length) return <React.Fragment />; if (!appOAuthClients?.data.length) return <React.Fragment />;
return ( return (
<Dialog onClose={onClose} open={true}> <Dialog onClose={onClose} open={true}>
<DialogTitle>{formatMessage('appAuthClientsDialog.title')}</DialogTitle> <DialogTitle>{formatMessage('appOAuthClientsDialog.title')}</DialogTitle>
<List sx={{ pt: 0 }}> <List sx={{ pt: 0 }}>
{appAuthClients.data.map((appAuthClient) => ( {appOAuthClients.data.map((oauthClient) => (
<ListItem disableGutters key={appAuthClient.id}> <ListItem disableGutters key={oauthClient.id}>
<ListItemButton onClick={() => onClientClick(appAuthClient.id)}> <ListItemButton onClick={() => onClientClick(oauthClient.id)}>
<ListItemText primary={appAuthClient.name} /> <ListItemText primary={oauthClient.name} />
</ListItemButton> </ListItemButton>
</ListItem> </ListItem>
))} ))}
@@ -34,10 +34,10 @@ function AppAuthClientsDialog(props) {
); );
} }
AppAuthClientsDialog.propTypes = { AppOAuthClientsDialog.propTypes = {
appKey: PropTypes.string.isRequired, appKey: PropTypes.string.isRequired,
onClientClick: PropTypes.func.isRequired, onClientClick: PropTypes.func.isRequired,
onClose: PropTypes.func.isRequired, onClose: PropTypes.func.isRequired,
}; };
export default AppAuthClientsDialog; export default AppOAuthClientsDialog;

View File

@@ -17,19 +17,19 @@ export const APP_CONNECTIONS = (appKey) => `/app/${appKey}/connections`;
export const APP_CONNECTIONS_PATTERN = '/app/:appKey/connections'; export const APP_CONNECTIONS_PATTERN = '/app/:appKey/connections';
export const APP_ADD_CONNECTION = (appKey, shared = false) => export const APP_ADD_CONNECTION = (appKey, shared = false) =>
`/app/${appKey}/connections/add?shared=${shared}`; `/app/${appKey}/connections/add?shared=${shared}`;
export const APP_ADD_CONNECTION_WITH_AUTH_CLIENT_ID = ( export const APP_ADD_CONNECTION_WITH_OAUTH_CLIENT_ID = (
appKey, appKey,
appAuthClientId, oauthClientId,
) => `/app/${appKey}/connections/add?appAuthClientId=${appAuthClientId}`; ) => `/app/${appKey}/connections/add?oauthClientId=${oauthClientId}`;
export const APP_ADD_CONNECTION_PATTERN = '/app/:appKey/connections/add'; export const APP_ADD_CONNECTION_PATTERN = '/app/:appKey/connections/add';
export const APP_RECONNECT_CONNECTION = ( export const APP_RECONNECT_CONNECTION = (
appKey, appKey,
connectionId, connectionId,
appAuthClientId, oauthClientId,
) => { ) => {
const path = `/app/${appKey}/connections/${connectionId}/reconnect`; const path = `/app/${appKey}/connections/${connectionId}/reconnect`;
if (appAuthClientId) { if (oauthClientId) {
return `${path}?appAuthClientId=${appAuthClientId}`; return `${path}?oauthClientId=${oauthClientId}`;
} }
return path; return path;
}; };
@@ -71,18 +71,18 @@ export const ADMIN_APPS = `${ADMIN_SETTINGS}/apps`;
export const ADMIN_APP = (appKey) => `${ADMIN_SETTINGS}/apps/${appKey}`; export const ADMIN_APP = (appKey) => `${ADMIN_SETTINGS}/apps/${appKey}`;
export const ADMIN_APP_PATTERN = `${ADMIN_SETTINGS}/apps/:appKey`; export const ADMIN_APP_PATTERN = `${ADMIN_SETTINGS}/apps/:appKey`;
export const ADMIN_APP_SETTINGS_PATTERN = `${ADMIN_SETTINGS}/apps/:appKey/settings`; export const ADMIN_APP_SETTINGS_PATTERN = `${ADMIN_SETTINGS}/apps/:appKey/settings`;
export const ADMIN_APP_AUTH_CLIENTS_PATTERN = `${ADMIN_SETTINGS}/apps/:appKey/auth-clients`; export const ADMIN_APP_AUTH_CLIENTS_PATTERN = `${ADMIN_SETTINGS}/apps/:appKey/oauth-clients`;
export const ADMIN_APP_CONNECTIONS_PATTERN = `${ADMIN_SETTINGS}/apps/:appKey/connections`; export const ADMIN_APP_CONNECTIONS_PATTERN = `${ADMIN_SETTINGS}/apps/:appKey/connections`;
export const ADMIN_APP_CONNECTIONS = (appKey) => export const ADMIN_APP_CONNECTIONS = (appKey) =>
`${ADMIN_SETTINGS}/apps/${appKey}/connections`; `${ADMIN_SETTINGS}/apps/${appKey}/connections`;
export const ADMIN_APP_SETTINGS = (appKey) => export const ADMIN_APP_SETTINGS = (appKey) =>
`${ADMIN_SETTINGS}/apps/${appKey}/settings`; `${ADMIN_SETTINGS}/apps/${appKey}/settings`;
export const ADMIN_APP_AUTH_CLIENTS = (appKey) => export const ADMIN_APP_AUTH_CLIENTS = (appKey) =>
`${ADMIN_SETTINGS}/apps/${appKey}/auth-clients`; `${ADMIN_SETTINGS}/apps/${appKey}/oauth-clients`;
export const ADMIN_APP_AUTH_CLIENT = (appKey, id) => export const ADMIN_APP_AUTH_CLIENT = (appKey, id) =>
`${ADMIN_SETTINGS}/apps/${appKey}/auth-clients/${id}`; `${ADMIN_SETTINGS}/apps/${appKey}/oauth-clients/${id}`;
export const ADMIN_APP_AUTH_CLIENTS_CREATE = (appKey) => export const ADMIN_APP_AUTH_CLIENTS_CREATE = (appKey) =>
`${ADMIN_SETTINGS}/apps/${appKey}/auth-clients/create`; `${ADMIN_SETTINGS}/apps/${appKey}/oauth-clients/create`;
export const DASHBOARD = FLOWS; export const DASHBOARD = FLOWS;
// External links and paths // External links and paths

View File

@@ -1,19 +0,0 @@
import { useQuery } from '@tanstack/react-query';
import api from 'helpers/api';
export default function useAdminAppAuthClient(appKey, id) {
const query = useQuery({
queryKey: ['admin', 'apps', appKey, 'authClients', id],
queryFn: async ({ signal }) => {
const { data } = await api.get(`/v1/admin/apps/${appKey}/auth-clients/${id}`, {
signal,
});
return data;
},
enabled: !!appKey && !!id,
});
return query;
}

View File

@@ -1,20 +1,23 @@
import { useMutation, useQueryClient } from '@tanstack/react-query'; import { useMutation, useQueryClient } from '@tanstack/react-query';
import api from 'helpers/api'; import api from 'helpers/api';
export default function useAdminCreateAppAuthClient(appKey) { export default function useAdminCreateOAuthClient(appKey) {
const queryClient = useQueryClient(); const queryClient = useQueryClient();
const query = useMutation({ const query = useMutation({
mutationFn: async (payload) => { mutationFn: async (payload) => {
const { data } = await api.post(`/v1/admin/apps/${appKey}/auth-clients`, payload); const { data } = await api.post(
`/v1/admin/apps/${appKey}/oauth-clients`,
payload,
);
return data; return data;
}, },
onSuccess: () => { onSuccess: () => {
queryClient.invalidateQueries({ queryClient.invalidateQueries({
queryKey: ['admin', 'apps', appKey, 'authClients'], queryKey: ['admin', 'apps', appKey, 'oauthClients'],
}); });
} },
}); });
return query; return query;

View File

@@ -0,0 +1,22 @@
import { useQuery } from '@tanstack/react-query';
import api from 'helpers/api';
export default function useAdminOAuthClient(appKey, id) {
const query = useQuery({
queryKey: ['admin', 'apps', appKey, 'oauthClients', id],
queryFn: async ({ signal }) => {
const { data } = await api.get(
`/v1/admin/apps/${appKey}/oauth-clients/${id}`,
{
signal,
},
);
return data;
},
enabled: !!appKey && !!id,
});
return query;
}

View File

@@ -1,11 +1,11 @@
import { useQuery } from '@tanstack/react-query'; import { useQuery } from '@tanstack/react-query';
import api from 'helpers/api'; import api from 'helpers/api';
export default function useAdminAppAuthClients(appKey) { export default function useAdminOAuthClients(appKey) {
const query = useQuery({ const query = useQuery({
queryKey: ['admin', 'apps', appKey, 'authClients'], queryKey: ['admin', 'apps', appKey, 'oauthClients'],
queryFn: async ({ signal }) => { queryFn: async ({ signal }) => {
const { data } = await api.get(`/v1/admin/apps/${appKey}/auth-clients`, { const { data } = await api.get(`/v1/admin/apps/${appKey}/oauth-clients`, {
signal, signal,
}); });
return data; return data;

View File

@@ -1,13 +1,13 @@
import { useMutation, useQueryClient } from '@tanstack/react-query'; import { useMutation, useQueryClient } from '@tanstack/react-query';
import api from 'helpers/api'; import api from 'helpers/api';
export default function useAdminUpdateAppAuthClient(appKey, id) { export default function useAdminUpdateOAuthClient(appKey, id) {
const queryClient = useQueryClient(); const queryClient = useQueryClient();
const query = useMutation({ const mutation = useMutation({
mutationFn: async (payload) => { mutationFn: async (payload) => {
const { data } = await api.patch( const { data } = await api.patch(
`/v1/admin/apps/${appKey}/auth-clients/${id}`, `/v1/admin/apps/${appKey}/oauth-clients/${id}`,
payload, payload,
); );
@@ -15,14 +15,14 @@ export default function useAdminUpdateAppAuthClient(appKey, id) {
}, },
onSuccess: () => { onSuccess: () => {
queryClient.invalidateQueries({ queryClient.invalidateQueries({
queryKey: ['admin', 'apps', appKey, 'authClients', id], queryKey: ['admin', 'apps', appKey, 'oauthClients', id],
}); });
queryClient.invalidateQueries({ queryClient.invalidateQueries({
queryKey: ['admin', 'apps', appKey, 'authClients'], queryKey: ['admin', 'apps', appKey, 'oauthClients'],
}); });
}, },
}); });
return query; return mutation;
} }

View File

@@ -31,7 +31,7 @@ function getSteps(auth, hasConnection, useShared) {
} }
export default function useAuthenticateApp(payload) { export default function useAuthenticateApp(payload) {
const { appKey, appAuthClientId, connectionId, useShared = false } = payload; const { appKey, oauthClientId, connectionId, useShared = false } = payload;
const { data: auth } = useAppAuth(appKey); const { data: auth } = useAppAuth(appKey);
const queryClient = useQueryClient(); const queryClient = useQueryClient();
const { mutateAsync: createConnection } = useCreateConnection(appKey); const { mutateAsync: createConnection } = useCreateConnection(appKey);
@@ -55,7 +55,7 @@ export default function useAuthenticateApp(payload) {
const response = { const response = {
key: appKey, key: appKey,
appAuthClientId: appAuthClientId || payload.appAuthClientId, oauthClientId: oauthClientId || payload.oauthClientId,
connectionId, connectionId,
fields, fields,
}; };
@@ -133,7 +133,7 @@ export default function useAuthenticateApp(payload) {
}, [ }, [
steps, steps,
appKey, appKey,
appAuthClientId, oauthClientId,
connectionId, connectionId,
queryClient, queryClient,
createConnection, createConnection,
@@ -147,7 +147,7 @@ export default function useAuthenticateApp(payload) {
[ [
steps, steps,
appKey, appKey,
appAuthClientId, oauthClientId,
connectionId, connectionId,
queryClient, queryClient,
createConnection, createConnection,
@@ -156,7 +156,7 @@ export default function useAuthenticateApp(payload) {
resetConnection, resetConnection,
verifyConnection, verifyConnection,
], ],
'steps, appKey, appAuthClientId, connectionId, queryClient, createConnection, createConnectionAuthUrl, updateConnection, resetConnection, verifyConnection', 'steps, appKey, oauthClientId, connectionId, queryClient, createConnection, createConnectionAuthUrl, updateConnection, resetConnection, verifyConnection',
'', '',
'useAuthenticate', 'useAuthenticate',
); );

View File

@@ -4,9 +4,9 @@ import api from 'helpers/api';
export default function useCreateConnection(appKey) { export default function useCreateConnection(appKey) {
const mutation = useMutation({ const mutation = useMutation({
mutationFn: async ({ appAuthClientId, formattedData }) => { mutationFn: async ({ oauthClientId, formattedData }) => {
const { data } = await api.post(`/v1/apps/${appKey}/connections`, { const { data } = await api.post(`/v1/apps/${appKey}/connections`, {
appAuthClientId, oauthClientId,
formattedData, formattedData,
}); });

View File

@@ -1,11 +1,11 @@
import { useQuery } from '@tanstack/react-query'; import { useQuery } from '@tanstack/react-query';
import api from 'helpers/api'; import api from 'helpers/api';
export default function useAppAuthClients(appKey) { export default function useOAuthClients(appKey) {
const query = useQuery({ const query = useQuery({
queryKey: ['apps', appKey, 'auth-clients'], queryKey: ['apps', appKey, 'oauth-clients'],
queryFn: async ({ signal }) => { queryFn: async ({ signal }) => {
const { data } = await api.get(`/v1/apps/${appKey}/auth-clients`, { const { data } = await api.get(`/v1/apps/${appKey}/oauth-clients`, {
signal, signal,
}); });
return data; return data;

View File

@@ -4,10 +4,10 @@ import api from 'helpers/api';
export default function useUpdateConnection() { export default function useUpdateConnection() {
const query = useMutation({ const query = useMutation({
mutationFn: async ({ connectionId, formattedData, appAuthClientId }) => { mutationFn: async ({ connectionId, formattedData, oauthClientId }) => {
const { data } = await api.patch(`/v1/connections/${connectionId}`, { const { data } = await api.patch(`/v1/connections/${connectionId}`, {
formattedData, formattedData,
appAuthClientId, oauthClientId,
}); });
return data; return data;

View File

@@ -22,7 +22,7 @@
"app.connectionCount": "{count} connections", "app.connectionCount": "{count} connections",
"app.flowCount": "{count} flows", "app.flowCount": "{count} flows",
"app.addConnection": "Add connection", "app.addConnection": "Add connection",
"app.addConnectionWithAuthClient": "Add connection with auth client", "app.addConnectionWithOAuthClient": "Add connection with OAuth client",
"app.reconnectConnection": "Reconnect connection", "app.reconnectConnection": "Reconnect connection",
"app.createFlow": "Create flow", "app.createFlow": "Create flow",
"app.settings": "Settings", "app.settings": "Settings",
@@ -74,7 +74,7 @@
"filterConditions.orContinueIf": "OR continue if…", "filterConditions.orContinueIf": "OR continue if…",
"chooseConnectionSubstep.continue": "Continue", "chooseConnectionSubstep.continue": "Continue",
"chooseConnectionSubstep.addNewConnection": "Add new connection", "chooseConnectionSubstep.addNewConnection": "Add new connection",
"chooseConnectionSubstep.addConnectionWithAuthClient": "Add connection with auth client", "chooseConnectionSubstep.addConnectionWithOAuthClient": "Add connection with OAuth client",
"chooseConnectionSubstep.chooseConnection": "Choose connection", "chooseConnectionSubstep.chooseConnection": "Choose connection",
"flow.createdAt": "created {datetime}", "flow.createdAt": "created {datetime}",
"flow.updatedAt": "updated {datetime}", "flow.updatedAt": "updated {datetime}",
@@ -258,7 +258,7 @@
"permissionSettings.cancel": "Cancel", "permissionSettings.cancel": "Cancel",
"permissionSettings.apply": "Apply", "permissionSettings.apply": "Apply",
"permissionSettings.title": "Conditions", "permissionSettings.title": "Conditions",
"appAuthClientsDialog.title": "Choose your authentication client", "appOAuthClientsDialog.title": "Choose your authentication client",
"userInterfacePage.title": "User Interface", "userInterfacePage.title": "User Interface",
"userInterfacePage.successfullyUpdated": "User interface has been updated.", "userInterfacePage.successfullyUpdated": "User interface has been updated.",
"userInterfacePage.titleFieldLabel": "Title", "userInterfacePage.titleFieldLabel": "Title",
@@ -290,22 +290,22 @@
"roleMappingsForm.successfullySaved": "Role mappings have been saved.", "roleMappingsForm.successfullySaved": "Role mappings have been saved.",
"adminApps.title": "Apps", "adminApps.title": "Apps",
"adminApps.connections": "Connections", "adminApps.connections": "Connections",
"adminApps.authClients": "Auth clients", "adminApps.oauthClients": "OAuth clients",
"adminApps.settings": "Settings", "adminApps.settings": "Settings",
"adminAppsSettings.useOnlyPredefinedAuthClients": "Use only predefined auth clients", "adminAppsSettings.useOnlyPredefinedAuthClients": "Use only predefined OAuth clients",
"adminAppsSettings.shared": "Shared", "adminAppsSettings.shared": "Shared",
"adminAppsSettings.disabled": "Disabled", "adminAppsSettings.disabled": "Disabled",
"adminAppsSettings.save": "Save", "adminAppsSettings.save": "Save",
"adminAppsSettings.successfullySaved": "Settings have been saved.", "adminAppsSettings.successfullySaved": "Settings have been saved.",
"adminAppsAuthClients.noAuthClients": "You don't have any auth clients yet.", "adminAppsOAuthClients.noOauthClients": "You don't have any OAuth clients yet.",
"adminAppsAuthClients.statusActive": "Active", "adminAppsOAuthClients.statusActive": "Active",
"adminAppsAuthClients.statusInactive": "Inactive", "adminAppsOAuthClients.statusInactive": "Inactive",
"createAuthClient.button": "Create auth client", "createOAuthClient.button": "Create OAuth client",
"createAuthClient.title": "Create auth client", "createOAuthClient.title": "Create OAuth client",
"authClient.buttonSubmit": "Submit", "oauthClient.buttonSubmit": "Submit",
"authClient.inputName": "Name", "oauthClient.inputName": "Name",
"authClient.inputActive": "Active", "oauthClient.inputActive": "Active",
"updateAuthClient.title": "Update auth client", "updateOAuthClient.title": "Update OAuth client",
"notFoundPage.title": "We can't seem to find a page you're looking for.", "notFoundPage.title": "We can't seem to find a page you're looking for.",
"notFoundPage.button": "Back to home page" "notFoundPage.button": "Back to home page"
} }

View File

@@ -21,9 +21,9 @@ import AppIcon from 'components/AppIcon';
import Container from 'components/Container'; import Container from 'components/Container';
import PageTitle from 'components/PageTitle'; import PageTitle from 'components/PageTitle';
import AdminApplicationSettings from 'components/AdminApplicationSettings'; import AdminApplicationSettings from 'components/AdminApplicationSettings';
import AdminApplicationAuthClients from 'components/AdminApplicationAuthClients'; import AdminApplicationOAuthClients from 'components/AdminApplicationOAuthClients';
import AdminApplicationCreateAuthClient from 'components/AdminApplicationCreateAuthClient'; import AdminApplicationCreateOAuthClient from 'components/AdminApplicationCreateOAuthClient';
import AdminApplicationUpdateAuthClient from 'components/AdminApplicationUpdateAuthClient'; import AdminApplicationUpdateOAuthClient from 'components/AdminApplicationUpdateOAuthClient';
import useApp from 'hooks/useApp'; import useApp from 'hooks/useApp';
export default function AdminApplication() { export default function AdminApplication() {
@@ -39,7 +39,7 @@ export default function AdminApplication() {
path: URLS.ADMIN_APP_SETTINGS_PATTERN, path: URLS.ADMIN_APP_SETTINGS_PATTERN,
end: false, end: false,
}); });
const authClientsPathMatch = useMatch({ const oauthClientsPathMatch = useMatch({
path: URLS.ADMIN_APP_AUTH_CLIENTS_PATTERN, path: URLS.ADMIN_APP_AUTH_CLIENTS_PATTERN,
end: false, end: false,
}); });
@@ -49,7 +49,7 @@ export default function AdminApplication() {
const app = data?.data || {}; const app = data?.data || {};
const goToAuthClientsPage = () => navigate('auth-clients'); const goToAuthClientsPage = () => navigate('oauth-clients');
if (loading) return null; if (loading) return null;
@@ -77,7 +77,7 @@ export default function AdminApplication() {
value={ value={
settingsPathMatch?.pattern?.path || settingsPathMatch?.pattern?.path ||
connectionsPathMatch?.pattern?.path || connectionsPathMatch?.pattern?.path ||
authClientsPathMatch?.pattern?.path oauthClientsPathMatch?.pattern?.path
} }
> >
<Tab <Tab
@@ -87,8 +87,8 @@ export default function AdminApplication() {
component={Link} component={Link}
/> />
<Tab <Tab
data-test="auth-clients-tab" data-test="oauth-clients-tab"
label={formatMessage('adminApps.authClients')} label={formatMessage('adminApps.oauthClients')}
to={URLS.ADMIN_APP_AUTH_CLIENTS(appKey)} to={URLS.ADMIN_APP_AUTH_CLIENTS(appKey)}
value={URLS.ADMIN_APP_AUTH_CLIENTS_PATTERN} value={URLS.ADMIN_APP_AUTH_CLIENTS_PATTERN}
component={Link} component={Link}
@@ -102,8 +102,8 @@ export default function AdminApplication() {
element={<AdminApplicationSettings appKey={appKey} />} element={<AdminApplicationSettings appKey={appKey} />}
/> />
<Route <Route
path={`/auth-clients/*`} path={`/oauth-clients/*`}
element={<AdminApplicationAuthClients appKey={appKey} />} element={<AdminApplicationOAuthClients appKey={appKey} />}
/> />
<Route <Route
path="/" path="/"
@@ -118,9 +118,9 @@ export default function AdminApplication() {
</Container> </Container>
<Routes> <Routes>
<Route <Route
path="/auth-clients/create" path="/oauth-clients/create"
element={ element={
<AdminApplicationCreateAuthClient <AdminApplicationCreateOAuthClient
application={app} application={app}
onClose={goToAuthClientsPage} onClose={goToAuthClientsPage}
appKey={appKey} appKey={appKey}
@@ -128,9 +128,9 @@ export default function AdminApplication() {
} }
/> />
<Route <Route
path="/auth-clients/:clientId" path="/oauth-clients/:clientId"
element={ element={
<AdminApplicationUpdateAuthClient <AdminApplicationUpdateOAuthClient
application={app} application={app}
onClose={goToAuthClientsPage} onClose={goToAuthClientsPage}
/> />

View File

@@ -30,7 +30,7 @@ import AppIcon from 'components/AppIcon';
import Container from 'components/Container'; import Container from 'components/Container';
import PageTitle from 'components/PageTitle'; import PageTitle from 'components/PageTitle';
import useApp from 'hooks/useApp'; import useApp from 'hooks/useApp';
import useAppAuthClients from 'hooks/useAppAuthClients'; import useOAuthClients from 'hooks/useOAuthClients';
import Can from 'components/Can'; import Can from 'components/Can';
import { AppPropType } from 'propTypes/propTypes'; import { AppPropType } from 'propTypes/propTypes';
@@ -63,7 +63,7 @@ export default function Application() {
const flowsPathMatch = useMatch({ path: URLS.APP_FLOWS_PATTERN, end: false }); const flowsPathMatch = useMatch({ path: URLS.APP_FLOWS_PATTERN, end: false });
const { appKey } = useParams(); const { appKey } = useParams();
const navigate = useNavigate(); const navigate = useNavigate();
const { data: appAuthClients } = useAppAuthClients(appKey); const { data: appOAuthClients } = useOAuthClients(appKey);
const { data, loading } = useApp(appKey); const { data, loading } = useApp(appKey);
const app = data?.data || {}; const app = data?.data || {};
@@ -86,14 +86,14 @@ export default function Application() {
appConfig?.data?.disabled === true, appConfig?.data?.disabled === true,
}; };
const addConnectionWithAuthClient = { const addConnectionWithOAuthClient = {
label: formatMessage('app.addConnectionWithAuthClient'), label: formatMessage('app.addConnectionWithOAuthClient'),
key: 'addConnectionWithAuthClient', key: 'addConnectionWithOAuthClient',
'data-test': 'add-connection-with-auth-client-button', 'data-test': 'add-connection-with-auth-client-button',
to: URLS.APP_ADD_CONNECTION(appKey, true), to: URLS.APP_ADD_CONNECTION(appKey, true),
disabled: disabled:
!currentUserAbility.can('create', 'Connection') || !currentUserAbility.can('create', 'Connection') ||
appAuthClients?.data?.length === 0 || appOAuthClients?.data?.length === 0 ||
appConfig?.data?.disabled === true, appConfig?.data?.disabled === true,
}; };
@@ -102,18 +102,18 @@ export default function Application() {
return [addCustomConnection]; return [addCustomConnection];
} }
// means only auth clients are allowed for connection creation // means only OAuth clients are allowed for connection creation
if (appConfig?.data?.useOnlyPredefinedAuthClients === true) { if (appConfig?.data?.useOnlyPredefinedAuthClients === true) {
return [addConnectionWithAuthClient]; return [addConnectionWithOAuthClient];
} }
// means there is no app auth client. so we don't show the `addConnectionWithAuthClient` // means there is no OAuth client. so we don't show the `addConnectionWithOAuthClient`
if (appAuthClients?.data?.length === 0) { if (appOAuthClients?.data?.length === 0) {
return [addCustomConnection]; return [addCustomConnection];
} }
return [addCustomConnection, addConnectionWithAuthClient]; return [addCustomConnection, addConnectionWithOAuthClient];
}, [appKey, appConfig, appAuthClients, currentUserAbility, formatMessage]); }, [appKey, appConfig, appOAuthClients, currentUserAbility, formatMessage]);
if (loading) return null; if (loading) return null;

View File

@@ -211,7 +211,7 @@ export const ConnectionPropType = PropTypes.shape({
flowCount: PropTypes.number, flowCount: PropTypes.number,
appData: AppPropType, appData: AppPropType,
createdAt: PropTypes.number, createdAt: PropTypes.number,
appAuthClientId: PropTypes.string, oauthClientId: PropTypes.string,
}); });
AppPropType.connection = PropTypes.arrayOf(ConnectionPropType); AppPropType.connection = PropTypes.arrayOf(ConnectionPropType);
@@ -463,7 +463,7 @@ export const AppConfigPropType = PropTypes.shape({
disabled: PropTypes.bool, disabled: PropTypes.bool,
}); });
export const AppAuthClientPropType = PropTypes.shape({ export const OAuthClientPropType = PropTypes.shape({
id: PropTypes.string, id: PropTypes.string,
name: PropTypes.string, name: PropTypes.string,
appConfigKey: PropTypes.string, appConfigKey: PropTypes.string,