Skip to content

Commit b5e9a05

Browse files
Merge remote-tracking branch 'origin/main' into feat/rbac-refactor
2 parents 1115a4b + 3c8f76d commit b5e9a05

85 files changed

Lines changed: 3274 additions & 2766 deletions

File tree

Some content is hidden

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

THIRD_PARTY_LICENSES.txt

Lines changed: 283 additions & 165 deletions
Large diffs are not rendered by default.

package-lock.json

Lines changed: 1734 additions & 2155 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/blocks/aws-athena/src/lib/actions/query-athena-action.ts

Lines changed: 11 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import {
33
amazonAuth,
44
dryRunCheckBox,
55
getAwsAccountsSingleSelectDropdown,
6-
getCredentialsListFromAuth,
6+
getCredentialsForAccount,
77
getRegionsDropdownState,
88
listAthenaDatabases,
99
runAndWaitForQueryResult,
@@ -33,10 +33,9 @@ export const runAthenaQueryAction = createAction({
3333
database: Property.Dropdown<string>({
3434
displayName: 'Database',
3535
description: 'Database that contains the table to query on',
36-
37-
refreshers: ['auth', 'accounts', 'region'],
36+
refreshers: ['auth', 'accounts', 'accounts.accounts', 'region'],
3837
required: true,
39-
options: async ({ auth, accounts, region }) => {
38+
options: async ({ auth, accounts, region }: any) => {
4039
if (!auth) {
4140
return {
4241
disabled: true,
@@ -46,24 +45,14 @@ export const runAthenaQueryAction = createAction({
4645
}
4746

4847
try {
49-
const authProp = auth as {
50-
accessKeyId: string;
51-
secretAccessKey: string;
52-
defaultRegion: string;
53-
};
54-
const selectedAccounts = (
55-
accounts as unknown as {
56-
accounts?: string[];
57-
}
58-
)?.accounts;
59-
const credentialsList = await getCredentialsListFromAuth(
60-
authProp,
61-
selectedAccounts,
48+
const credentials = await getCredentialsForAccount(
49+
auth,
50+
accounts?.['accounts'],
6251
);
6352

6453
const databases = await listAthenaDatabases(
65-
credentialsList[0],
66-
(region as string | undefined) ?? authProp.defaultRegion,
54+
credentials,
55+
(region as string | undefined) ?? auth.defaultRegion,
6756
);
6857

6958
return {
@@ -119,14 +108,13 @@ export const runAthenaQueryAction = createAction({
119108
}
120109

121110
try {
122-
const selectedAccounts = context.propsValue.accounts?.['accounts'];
123-
const credentialsList = await getCredentialsListFromAuth(
111+
const credentials = await getCredentialsForAccount(
124112
context.auth,
125-
selectedAccounts,
113+
context.propsValue.accounts?.['accounts'],
126114
);
127115

128116
return await runAndWaitForQueryResult(
129-
credentialsList[0],
117+
credentials,
130118
context.propsValue.region ?? context.auth.defaultRegion,
131119
query,
132120
database,

packages/blocks/aws-athena/test/athena-query-action.test.ts

Lines changed: 11 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
const openopsCommonMock = {
22
...jest.requireActual('@openops/common'),
3-
getCredentialsListFromAuth: jest.fn(),
3+
getCredentialsForAccount: jest.fn(),
44
runAndWaitForQueryResult: jest.fn(),
55
};
66

@@ -12,9 +12,9 @@ describe('runAthenaQueryAction tests', () => {
1212
beforeEach(() => {
1313
jest.clearAllMocks();
1414

15-
openopsCommonMock.getCredentialsListFromAuth.mockResolvedValue([
16-
{ someCreds: 'some creds' },
17-
]);
15+
openopsCommonMock.getCredentialsForAccount.mockResolvedValue({
16+
someCreds: 'some creds',
17+
});
1818
});
1919

2020
const auth = {
@@ -76,7 +76,7 @@ describe('runAthenaQueryAction tests', () => {
7676
...jest.requireActual('@openops/blocks-framework'),
7777
auth: auth,
7878
propsValue: {
79-
accounts: { accounts: ['some-account-id'] },
79+
accounts: { accounts: 'some-account-id' },
8080
query: 'some query',
8181
database: 'some database',
8282
outputBucket: 'some outputBucket',
@@ -87,12 +87,10 @@ describe('runAthenaQueryAction tests', () => {
8787
const result = (await runAthenaQueryAction.run(context)) as any;
8888

8989
expect(result).toEqual('mockResult');
90-
expect(openopsCommonMock.getCredentialsListFromAuth).toHaveBeenCalledTimes(
91-
1,
92-
);
93-
expect(openopsCommonMock.getCredentialsListFromAuth).toHaveBeenCalledWith(
90+
expect(openopsCommonMock.getCredentialsForAccount).toHaveBeenCalledTimes(1);
91+
expect(openopsCommonMock.getCredentialsForAccount).toHaveBeenCalledWith(
9492
auth,
95-
['some-account-id'],
93+
'some-account-id',
9694
);
9795
});
9896

@@ -138,7 +136,6 @@ describe('runAthenaQueryAction tests', () => {
138136
...jest.requireActual('@openops/blocks-framework'),
139137
auth: auth,
140138
propsValue: {
141-
accounts: { accounts: ['some-account-id'] },
142139
region: 'some region',
143140
query: 'some query',
144141
database: 'some database',
@@ -158,12 +155,10 @@ describe('runAthenaQueryAction tests', () => {
158155
'some database',
159156
'some outputBucket',
160157
);
161-
expect(openopsCommonMock.getCredentialsListFromAuth).toHaveBeenCalledTimes(
162-
1,
163-
);
164-
expect(openopsCommonMock.getCredentialsListFromAuth).toHaveBeenCalledWith(
158+
expect(openopsCommonMock.getCredentialsForAccount).toHaveBeenCalledTimes(1);
159+
expect(openopsCommonMock.getCredentialsForAccount).toHaveBeenCalledWith(
165160
auth,
166-
['some-account-id'],
161+
undefined,
167162
);
168163
});
169164

packages/blocks/aws/src/lib/actions/get-price-action.ts

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ import { Property, createAction } from '@openops/blocks-framework';
33
import {
44
amazonAuth,
55
getAttributeValues,
6+
getAwsAccountsSingleSelectDropdown,
7+
getCredentialsForAccount,
68
getCredentialsFromAuth,
79
getPriceListWithCache,
810
getServices,
@@ -17,12 +19,13 @@ export const getPriceAction = createAction({
1719
displayName: 'Get Price from Price Catalog',
1820
isWriteAction: false,
1921
props: {
22+
account: getAwsAccountsSingleSelectDropdown().accounts,
2023
service: Property.Dropdown({
2124
displayName: 'Service Code',
2225
description: 'Service code for which to fetch the price',
23-
refreshers: ['auth'],
26+
refreshers: ['auth', 'account', 'account.accounts'],
2427
required: true,
25-
options: async ({ auth }: any) => {
28+
options: async ({ auth, account }: any) => {
2629
if (!auth) {
2730
return {
2831
disabled: true,
@@ -31,8 +34,11 @@ export const getPriceAction = createAction({
3134
};
3235
}
3336

34-
const credentials = await getCredentialsFromAuth(auth);
3537
try {
38+
const credentials = await getCredentialsForAccount(
39+
auth,
40+
account?.['accounts'],
41+
);
3642
const services = await getServices(credentials, PRICING_REGION);
3743

3844
if (!services.length) {
@@ -66,8 +72,8 @@ export const getPriceAction = createAction({
6672
displayName: '',
6773
description: '',
6874
required: true,
69-
refreshers: ['auth', 'service'],
70-
props: async ({ auth, service }, { input }) => {
75+
refreshers: ['auth', 'account', 'account.accounts', 'service'],
76+
props: async ({ auth, account, service }, { input }) => {
7177
if (!auth || !service) {
7278
return {};
7379
}
@@ -101,7 +107,10 @@ export const getPriceAction = createAction({
101107
};
102108
}
103109

104-
const credentials = await getCredentialsFromAuth(auth);
110+
const credentials = await getCredentialsForAccount(
111+
auth,
112+
account?.['accounts'],
113+
);
105114
try {
106115
const attributeValues: AttributeValue[] =
107116
await getAttributeValues(
@@ -139,17 +148,20 @@ export const getPriceAction = createAction({
139148
},
140149
async run(context) {
141150
try {
142-
const { service, queryFilters } = context.propsValue;
151+
const { account, service, queryFilters } = context.propsValue;
143152
const filters = queryFilters['queryFilters'].map((filter: any) => {
144153
return {
145154
Field: filter.attributeName,
146155
Type: FilterType.TERM_MATCH,
147156
Value: filter.attributeValue,
148157
};
149158
});
159+
const credentials = account?.['accounts']
160+
? await getCredentialsForAccount(context.auth, account['accounts'])
161+
: await getCredentialsFromAuth(context.auth);
150162

151163
const priceList = getPriceListWithCache(
152-
context.auth,
164+
credentials,
153165
service.ServiceCode!,
154166
filters,
155167
PRICING_REGION,

packages/blocks/aws/test/get-price-action.test.ts

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
const openopsCommonMock = {
22
...jest.requireActual('@openops/common'),
33
getCredentialsFromAuth: jest.fn(),
4+
getCredentialsForAccount: jest.fn(),
45
getAttributeValues: jest.fn(),
56
getServices: jest.fn(),
67
getPriceListWithCache: jest.fn(),
@@ -18,6 +19,9 @@ describe('getPriceAction', () => {
1819
openopsCommonMock.getCredentialsFromAuth.mockResolvedValue({
1920
someCreds: 'some value',
2021
});
22+
openopsCommonMock.getCredentialsForAccount.mockResolvedValue({
23+
someCreds: 'some value',
24+
});
2125
});
2226

2327
const auth = {
@@ -34,12 +38,16 @@ describe('getPriceAction', () => {
3438
},
3539
auth: auth,
3640
propsValue: {
37-
accountId: 'some account id',
41+
account: { accounts: 'some account id' },
3842
},
3943
};
4044

4145
test('should create action with correct properties', () => {
4246
expect(getPriceAction.props).toMatchObject({
47+
account: {
48+
type: 'DYNAMIC',
49+
required: true,
50+
},
4351
service: {
4452
type: 'DROPDOWN',
4553
required: true,
@@ -80,22 +88,40 @@ describe('getPriceAction', () => {
8088

8189
expect(openopsCommonMock.getPriceListWithCache).toHaveBeenCalledTimes(1);
8290
expect(openopsCommonMock.getPriceListWithCache).toHaveBeenCalledWith(
83-
auth,
91+
{ someCreds: 'some value' },
8492
'some service',
8593
expectedFilters,
8694
'us-east-1',
8795
);
96+
expect(openopsCommonMock.getCredentialsForAccount).toHaveBeenCalledWith(
97+
auth,
98+
'some account id',
99+
);
88100
},
89101
);
90102

103+
test('should fallback to getCredentialsFromAuth when account is missing in run', async () => {
104+
openopsCommonMock.getPriceListWithCache.mockResolvedValue('mockResult');
105+
context.propsValue = {
106+
service: { ServiceCode: 'some service' },
107+
queryFilters: { queryFilters: [] },
108+
};
109+
110+
const result = (await getPriceAction.run(context)) as any;
111+
112+
expect(result).toEqual('mockResult');
113+
expect(openopsCommonMock.getCredentialsFromAuth).toHaveBeenCalledWith(auth);
114+
expect(openopsCommonMock.getCredentialsForAccount).not.toHaveBeenCalled();
115+
});
116+
91117
test('should return the list of services in property service', async () => {
92118
openopsCommonMock.getServices.mockResolvedValue([
93119
{ ServiceCode: 'service1' },
94120
{ ServiceCode: 'service2' },
95121
]);
96122

97123
const result = await getPriceAction.props['service'].options(
98-
{ auth },
124+
{ auth, account: { accounts: 'some account id' } },
99125
context,
100126
);
101127

@@ -118,6 +144,7 @@ describe('getPriceAction', () => {
118144
ServiceCode: 'some service',
119145
AttributeNames: ['some attibute'],
120146
};
147+
context.propsValue.account = { accounts: 'some account id' };
121148
context.propsValue.auth = auth;
122149
context.input = { attributeName: 'some attibute' };
123150

packages/blocks/jira-cloud/src/auth.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ You can generate your API token from:
4444
} catch (e) {
4545
return {
4646
valid: false,
47-
error: ((e as HttpError).response.body as any).message,
47+
error: (e as HttpError)?.message ?? 'Invalid credentials',
4848
};
4949
}
5050
},

packages/blocks/slack/src/lib/common/utils.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -269,7 +269,8 @@ export function dynamicBlockKitProperties(): any {
269269
const result: any = {
270270
blocks: Property.Json({
271271
displayName: 'Block Kit blocks',
272-
description: 'See https://api.slack.com/block-kit for specs',
272+
description:
273+
'See https://api.slack.com/block-kit for specs. Visual preview available at https://app.slack.com/block-kit-builder',
273274
required: true,
274275
defaultValue: [
275276
{

packages/react-ui/src/app/features/builder/run-details/flow-step-details-card-item.tsx

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import {
66
CollapsibleContent,
77
CollapsibleTrigger,
88
} from '@openops/components/ui';
9-
import { ChevronRight } from 'lucide-react';
9+
import { ChevronRight, SquareX } from 'lucide-react';
1010
import React, { useCallback, useMemo } from 'react';
1111

1212
import { blocksHooks } from '@/app/features/blocks/lib/blocks-hook';
@@ -18,6 +18,7 @@ import { ActionType, FlagId, flowHelper } from '@openops/shared';
1818
import { flagsHooks } from '@/app/common/hooks/flags-hooks';
1919
import { useCenterWorkflowViewOntoStep } from '@/app/features/builder/hooks/center-workflow-view-onto-step';
2020
import { StepStatusIcon } from '@/app/features/flow-runs/components/step-status-icon';
21+
import { t } from 'i18next';
2122
import { RUN_DETAILS_STEP_CARD_ID_PREFIX } from './constants';
2223
import { LoopIterationInput } from './loop-iteration-input';
2324

@@ -145,10 +146,24 @@ const FlowStepDetailsCardItem = ({
145146
/>
146147
</Button>
147148
)}
148-
<img className="w-6 h-6" alt={'logo'} src={stepMetadata?.logoUrl} />
149-
<div className="break-all truncate">{`${stepIndex + 1}. ${
150-
step?.displayName
151-
}`}</div>
149+
{stepMetadata?.logoUrl ? (
150+
<img
151+
className="w-6 h-6"
152+
alt={'logo'}
153+
src={stepMetadata?.logoUrl}
154+
/>
155+
) : (
156+
<SquareX className="w-6 h-6 text-muted-foreground" />
157+
)}
158+
159+
<div
160+
className={cn('break-all truncate', {
161+
'text-muted-foreground italic': !step?.displayName,
162+
})}
163+
>
164+
{(stepIndex !== -1 ? `${stepIndex + 1}. ` : '') +
165+
(step?.displayName ?? t('Deleted Step'))}
166+
</div>
152167
<div className="w-2"></div>
153168
<div className="flex gap-1 justify-end items-center flex-grow">
154169
{isLoopStep && (

0 commit comments

Comments
 (0)