Merge pull request #1802 from automatisch/AUT-688

refactor: rewrite get connected apps with RQ
This commit is contained in:
Ömer Faruk Aydın
2024-04-15 11:43:35 +02:00
committed by GitHub
9 changed files with 48 additions and 115 deletions

View File

@@ -1,67 +0,0 @@
import App from '../../models/app.js';
import Flow from '../../models/flow.js';
import Connection from '../../models/connection.js';
const getConnectedApps = async (_parent, params, context) => {
const conditions = context.currentUser.can('read', 'Connection');
const userConnections = context.currentUser.$relatedQuery('connections');
const allConnections = Connection.query();
const connectionBaseQuery = conditions.isCreator
? userConnections
: allConnections;
const userFlows = context.currentUser.$relatedQuery('flows');
const allFlows = Flow.query();
const flowBaseQuery = conditions.isCreator ? userFlows : allFlows;
let apps = await App.findAll(params.name);
const connections = await connectionBaseQuery
.clone()
.select('connections.key')
.where({ draft: false })
.count('connections.id as count')
.groupBy('connections.key');
const flows = await flowBaseQuery
.clone()
.withGraphJoined('steps')
.orderBy('created_at', 'desc');
const duplicatedUsedApps = flows
.map((flow) => flow.steps.map((step) => step.appKey))
.flat()
.filter(Boolean);
const connectionKeys = connections.map((connection) => connection.key);
const usedApps = [...new Set([...duplicatedUsedApps, ...connectionKeys])];
apps = apps
.filter((app) => {
return usedApps.includes(app.key);
})
.map((app) => {
const connection = connections.find(
(connection) => connection.key === app.key
);
app.connectionCount = connection?.count || 0;
app.flowCount = 0;
flows.forEach((flow) => {
const usedFlow = flow.steps.find((step) => step.appKey === app.key);
if (usedFlow) {
app.flowCount += 1;
}
});
return app;
})
.sort((appA, appB) => appA.name.localeCompare(appB.name));
return apps;
};
export default getConnectedApps;

View File

@@ -1,7 +0,0 @@
import getConnectedApps from './queries/get-connected-apps.js';
const queryResolvers = {
getConnectedApps,
};
export default queryResolvers;

View File

@@ -1,8 +1,6 @@
import mutationResolvers from './mutation-resolvers.js';
import queryResolvers from './query-resolvers.js';
const resolvers = {
Query: queryResolvers,
Mutation: mutationResolvers,
};

View File

@@ -1,7 +1,6 @@
type Query {
getConnectedApps(name: String): [App]
placeholderQuery(name: String): Boolean
}
type Mutation {
createAppConfig(input: CreateAppConfigInput): AppConfig
createAppAuthClient(input: CreateAppAuthClientInput): AppAuthClient

View File

@@ -40,9 +40,6 @@ export const authenticateUser = async (request, response, next) => {
const isAuthenticatedRule = rule()(isAuthenticated);
export const authenticationRules = {
Query: {
'*': isAuthenticatedRule,
},
Mutation: {
'*': isAuthenticatedRule,
forgotPassword: allow,

View File

@@ -42,19 +42,21 @@ describe('authentication rules', () => {
const { queries, mutations } = getQueryAndMutationNames(authenticationRules);
describe('for queries', () => {
queries.forEach((query) => {
it(`should apply correct rule for query: ${query}`, () => {
const ruleApplied = authenticationRules.Query[query];
if (queries.length) {
describe('for queries', () => {
queries.forEach((query) => {
it(`should apply correct rule for query: ${query}`, () => {
const ruleApplied = authenticationRules.Query[query];
if (query === '*') {
expect(ruleApplied.func).toBe(isAuthenticated);
} else {
expect(ruleApplied).toEqual(allow);
}
if (query === '*') {
expect(ruleApplied.func).toBe(isAuthenticated);
} else {
expect(ruleApplied).toEqual(allow);
}
});
});
});
});
}
describe('for mutations', () => {
mutations.forEach((mutation) => {

View File

@@ -1,15 +0,0 @@
import { gql } from '@apollo/client';
export const GET_CONNECTED_APPS = gql`
query GetConnectedApps($name: String) {
getConnectedApps(name: $name) {
key
name
iconUrl
docUrl
primaryColor
connectionCount
flowCount
supportsConnections
}
}
`;

View File

@@ -0,0 +1,25 @@
import { useQuery } from '@tanstack/react-query';
import useCurrentUser from 'hooks/useCurrentUser';
import api from 'helpers/api';
export default function useUserApps(appName) {
const { data } = useCurrentUser();
const userId = data?.data.id;
const query = useQuery({
queryKey: ['users', userId, 'apps', appName],
queryFn: async ({ signal }) => {
const { data } = await api.get(`/v1/users/${userId}/apps`, {
signal,
params: {
...(appName && { name: appName }),
},
});
return data;
},
enabled: !!userId,
});
return query;
}

View File

@@ -1,6 +1,5 @@
import * as React from 'react';
import { Link, Routes, Route, useNavigate } from 'react-router-dom';
import { useQuery } from '@apollo/client';
import Box from '@mui/material/Box';
import Grid from '@mui/material/Grid';
import Divider from '@mui/material/Divider';
@@ -15,23 +14,25 @@ import PageTitle from 'components/PageTitle';
import AppRow from 'components/AppRow';
import SearchInput from 'components/SearchInput';
import useFormatMessage from 'hooks/useFormatMessage';
import { GET_CONNECTED_APPS } from 'graphql/queries/get-connected-apps';
import * as URLS from 'config/urls';
import useUserApps from 'hooks/useUserApps';
export default function Applications() {
const navigate = useNavigate();
const formatMessage = useFormatMessage();
const [appName, setAppName] = React.useState(null);
const { data, loading } = useQuery(GET_CONNECTED_APPS, {
variables: { name: appName },
});
const apps = data?.getConnectedApps;
const { data, isLoading } = useUserApps(appName);
const apps = data?.data;
const hasApps = apps?.length;
const onSearchChange = React.useCallback((event) => {
setAppName(event.target.value);
}, []);
const goToApps = React.useCallback(() => {
navigate(URLS.APPS);
}, [navigate]);
return (
<Box sx={{ py: 3 }}>
<Container>
@@ -75,21 +76,21 @@ export default function Applications() {
<Divider sx={{ mt: [2, 0], mb: 2 }} />
{loading && (
{isLoading && (
<CircularProgress
data-test="apps-loader"
sx={{ display: 'block', margin: '20px auto' }}
/>
)}
{!loading && !hasApps && (
{!isLoading && !hasApps && (
<NoResultFound
text={formatMessage('apps.noConnections')}
to={URLS.NEW_APP_CONNECTION}
/>
)}
{!loading &&
{!isLoading &&
apps?.map((app) => (
<AppRow key={app.name} application={app} url={URLS.APP(app.key)} />
))}