Skip to content

Commit

Permalink
Merge branch 'main' into develop
Browse files Browse the repository at this point in the history
  • Loading branch information
sherfin94 committed Sep 22, 2022
2 parents 02e4d5f + 4137a25 commit ddf28a1
Show file tree
Hide file tree
Showing 20 changed files with 235 additions and 61 deletions.
2 changes: 1 addition & 1 deletion .version
@@ -1 +1 @@
1.25.3
1.25.6
34 changes: 28 additions & 6 deletions frontend/src/Editor/Components/Calendar.jsx
Expand Up @@ -3,6 +3,7 @@ import { Calendar as ReactCalendar, momentLocalizer } from 'react-big-calendar';
import moment from 'moment';
import 'react-big-calendar/lib/css/react-big-calendar.css';
import { CalendarEventPopover } from './CalendarPopover';
import _ from 'lodash';

const localizer = momentLocalizer(moment);

Expand All @@ -12,7 +13,16 @@ const prepareEvent = (event, dateFormat) => ({
end: moment(event.end, dateFormat).toDate(),
});

const parseDate = (date, dateFormat) => moment(date, dateFormat).toDate();
const parseDate = (date, dateFormat) => {
const parsed = moment(date, dateFormat).toDate();

//handle invalid dates
if (isNaN(parsed.getTime())) {
return null;
}

return parsed;
};

const allowedCalendarViews = ['month', 'week', 'day'];

Expand All @@ -39,6 +49,7 @@ export const Calendar = function ({
const startTime = properties.startTime ? parseDate(properties.startTime, properties.dateFormat) : todayStartTime;
const endTime = properties.endTime ? parseDate(properties.endTime, properties.dateFormat) : todayEndTime;

const [currentDate, setCurrentDate] = useState(defaultDate);
const [eventPopoverOptions, setEventPopoverOptions] = useState({ show: false });

const eventPropGetter = (event) => {
Expand Down Expand Up @@ -82,9 +93,15 @@ export const Calendar = function ({
: allowedCalendarViews[0];

useEffect(() => {
setExposedVariable('currentView', defaultView);
//check if the default date is a valid date

if (defaultDate !== null && !_.isEqual(exposedVariables.currentDate, properties.defaultDate)) {
setExposedVariable('currentDate', moment(defaultDate).format(properties.dateFormat));
setCurrentDate(defaultDate);
}

// eslint-disable-next-line react-hooks/exhaustive-deps
}, [defaultView]);
}, [JSON.stringify(moment(defaultDate).format('DD-MM-YYYY'))]);

const components = {
timeGutterHeader: () => <div style={{ height: '100%', display: 'flex', alignItems: 'flex-end' }}>All day</div>,
Expand All @@ -93,7 +110,10 @@ export const Calendar = function ({
},
};

if (exposedVariables.currentDate === undefined) setExposedVariable('currentDate', properties.defaultDate);
//! hack
if (exposedVariables.currentDate === undefined) {
setExposedVariable('currentDate', moment(defaultDate).format(properties.dateFormat));
}

return (
<div id={id} style={{ display: styles.visibility ? 'block' : 'none' }}>
Expand All @@ -105,7 +125,7 @@ export const Calendar = function ({
${exposedVariables.currentView === 'week' ? 'resources-week-cls' : ''}
${properties.displayViewSwitcher ? '' : 'hide-view-switcher'}`}
localizer={localizer}
defaultDate={defaultDate}
date={currentDate}
events={events}
startAccessor="start"
endAccessor="end"
Expand Down Expand Up @@ -136,7 +156,9 @@ export const Calendar = function ({
});
}}
onNavigate={(date) => {
setExposedVariable('currentDate', moment(date).format(properties.dateFormat));
const formattedDate = moment(date).format(properties.dateFormat);
setExposedVariable('currentDate', formattedDate);
setCurrentDate(date);
fireEvent('onCalendarNavigate');
}}
selectable={true}
Expand Down
2 changes: 0 additions & 2 deletions frontend/src/SignupPage/SignupPage.jsx
Expand Up @@ -15,8 +15,6 @@ class SignupPageComponent extends React.Component {
isLoading: false,
};

console.log('window.public_config?.SSO_DISABLE_SIGNUPS--- ', window.public_config?.SSO_DISABLE_SIGNUPS != true);

this.ssoConfigs = {
enableSignUp:
window.public_config?.DISABLE_MULTI_WORKSPACE !== 'true' &&
Expand Down
1 change: 1 addition & 0 deletions frontend/src/_components/DynamicForm.jsx
Expand Up @@ -132,6 +132,7 @@ const DynamicForm = ({
auth_key: options.auth_key?.value,
custom_auth_params: options.custom_auth_params?.value,
custom_query_params: options.custom_query_params?.value,
multiple_auth_enabled: options.multiple_auth_enabled?.value,
optionchanged,
};
case 'react-component-google-sheets':
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/_helpers/appUtils.js
Expand Up @@ -667,7 +667,7 @@ export function runQuery(_ref, queryId, queryName, confirmed = undefined, mode =
.then((data) => {
if (data.status === 'needs_oauth') {
const url = data.data.auth_url; // Backend generates and return sthe auth url
fetchOAuthToken(url, dataQuery.data_source_id);
fetchOAuthToken(url, dataQuery['data_source_id'] || dataQuery['dataSourceId']);
}

if (data.status === 'failed') {
Expand Down
10 changes: 10 additions & 0 deletions frontend/src/_ui/OAuth/Authentication.jsx
Expand Up @@ -20,6 +20,7 @@ const Authentication = ({
bearer_token,
password,
auth_url,
multiple_auth_enabled,
optionchanged,
}) => {
if (auth_type === 'oauth2') {
Expand Down Expand Up @@ -153,6 +154,15 @@ const Authentication = ({
width={'100%'}
useMenuPortal={false}
/>
<label className="form-check form-switch my-4 ">
<input
className="form-check-input"
type="checkbox"
checked={multiple_auth_enabled}
onChange={() => optionchanged('multiple_auth_enabled', !multiple_auth_enabled)}
/>
<span className="form-check-label">Authentication Required for All Users</span>
</label>
</div>
)}
</div>
Expand Down
2 changes: 2 additions & 0 deletions frontend/src/_ui/OAuth/index.js
Expand Up @@ -19,6 +19,7 @@ const OAuth = ({
auth_url,
header_prefix,
add_token_to,
multiple_auth_enabled,
optionchanged,
}) => {
return (
Expand Down Expand Up @@ -48,6 +49,7 @@ const OAuth = ({
client_id={client_id}
client_secret={client_secret}
client_auth={client_auth}
multiple_auth_enabled={multiple_auth_enabled}
scopes={scopes}
username={username}
password={password}
Expand Down
4 changes: 4 additions & 0 deletions plugins/packages/common/lib/app.type.ts
@@ -0,0 +1,4 @@
export type App = {
id: string;
isPublic: boolean;
};
7 changes: 6 additions & 1 deletion plugins/packages/common/lib/index.ts
@@ -1,17 +1,22 @@
import { QueryError, OAuthUnauthorizedClientError } from './query.error';
import { QueryResult } from './query_result.type';
import { User } from './user.type';
import { App } from './app.type';
import { QueryService } from './query_service.interface';
import { cacheConnection, getCachedConnection, parseJson, cleanSensitiveData } from './utils.helper';
import { cacheConnection, getCachedConnection, parseJson, cleanSensitiveData, getCurrentToken } from './utils.helper';
import { ConnectionTestResult } from './connection_test_result.type';

export {
QueryError,
OAuthUnauthorizedClientError,
QueryResult,
QueryService,
User,
App,
cacheConnection,
getCachedConnection,
parseJson,
ConnectionTestResult,
cleanSensitiveData,
getCurrentToken,
};
6 changes: 4 additions & 2 deletions plugins/packages/common/lib/query_service.interface.ts
@@ -1,12 +1,14 @@
import { App } from './app.type';
import { ConnectionTestResult } from './connection_test_result.type';
import { QueryResult } from './query_result.type';

import { User } from './user.type';
export interface QueryService {
run(
sourceOptions: object,
queryOptions: object,
dataSourceId?: string,
dataSourceUpdatedAt?: string
dataSourceUpdatedAt?: string,
context?: { user?: User; app?: App }
): Promise<QueryResult>;
getConnection?(queryOptions: object, options: any, checkCache: boolean, dataSourceId: string): Promise<object>;
testConnection?(sourceOptions: object): Promise<ConnectionTestResult>;
Expand Down
3 changes: 3 additions & 0 deletions plugins/packages/common/lib/user.type.ts
@@ -0,0 +1,3 @@
export type User = {
id: string;
};
13 changes: 13 additions & 0 deletions plugins/packages/common/lib/utils.helper.ts
Expand Up @@ -51,3 +51,16 @@ function clearData(data, keys) {
}
}
}

export const getCurrentToken = (isMultiAuthEnabled: boolean, tokenData: any, userId: string, isAppPublic: boolean) => {
if (isMultiAuthEnabled) {
if (!tokenData || !Array.isArray(tokenData)) return null;
return !isAppPublic
? tokenData.find((token: any) => token.user_id === userId)
: userId
? tokenData.find((token: any) => token.user_id === userId)
: tokenData[0];
} else {
return tokenData;
}
};
36 changes: 30 additions & 6 deletions plugins/packages/restapi/lib/index.ts
@@ -1,7 +1,15 @@
const urrl = require('url');
import { readFileSync } from 'fs';
import * as tls from 'tls';
import { QueryError, QueryResult, QueryService, cleanSensitiveData } from '@tooljet-plugins/common';
import {
QueryError,
QueryResult,
QueryService,
cleanSensitiveData,
User,
App,
getCurrentToken,
} from '@tooljet-plugins/common';
const JSON5 = require('json5');
import got, { Headers, HTTPError, OptionsOfTextResponseBody } from 'got';

Expand Down Expand Up @@ -85,7 +93,13 @@ export default class RestapiQueryService implements QueryService {
return true;
}

async run(sourceOptions: any, queryOptions: any, dataSourceId: string): Promise<RestAPIResult> {
async run(
sourceOptions: any,
queryOptions: any,
dataSourceId: string,
dataSourceUpdatedAt: string,
context?: { user?: User; app?: App }
): Promise<RestAPIResult> {
/* REST API queries can be adhoc or associated with a REST API datasource */
const hasDataSource = dataSourceId !== undefined;
const authType = sourceOptions['auth_type'];
Expand All @@ -94,12 +108,20 @@ export default class RestapiQueryService implements QueryService {
const headers = this.headers(sourceOptions, queryOptions, hasDataSource);
const customQueryParams = sanitizeCustomParams(sourceOptions['custom_query_params']);
const isUrlEncoded = this.checkIfContentTypeIsURLenc(queryOptions['headers']);
const isMultiAuthEnabled = sourceOptions['multiple_auth_enabled'];

/* Chceck if OAuth tokens exists for the source if query requires OAuth */
if (requiresOauth) {
const tokenData = sourceOptions['tokenData'];
const isAppPublic = context?.app.isPublic;
const userData = context?.user;
const currentToken = getCurrentToken(isMultiAuthEnabled, tokenData, userData?.id, isAppPublic);

if (!tokenData) {
if (!currentToken && !userData?.id && isAppPublic) {
throw new QueryError('Missing access token', {}, {});
}

if (!currentToken) {
const tooljetHost = process.env.TOOLJET_HOST;
const authUrl = new URL(
`${sourceOptions['auth_url']}?response_type=code&client_id=${sourceOptions['client_id']}&redirect_uri=${tooljetHost}/oauth2/authorize&scope=${sourceOptions['scopes']}`
Expand All @@ -111,7 +133,7 @@ export default class RestapiQueryService implements QueryService {
data: { auth_url: authUrl },
};
} else {
const accessToken = tokenData['access_token'];
const accessToken = currentToken['access_token'];
if (sourceOptions['add_token_to'] === 'header') {
const headerPrefix = sourceOptions['header_prefix'];
headers['Authorization'] = `${headerPrefix}${accessToken}`;
Expand Down Expand Up @@ -214,8 +236,10 @@ export default class RestapiQueryService implements QueryService {
return contentType === 'application/x-www-form-urlencoded';
}

async refreshToken(sourceOptions, error) {
const refreshToken = sourceOptions['tokenData']['refresh_token'];
async refreshToken(sourceOptions: any, error: any, userId: string, isAppPublic: boolean) {
const isMultiAuthEnabled = sourceOptions['multiple_auth_enabled'];
const currentToken = getCurrentToken(isMultiAuthEnabled, sourceOptions['tokenData'], userId, isAppPublic);
const refreshToken = currentToken['refresh_token'];
if (!refreshToken) {
throw new QueryError('Refresh token not found', error.response, {});
}
Expand Down
37 changes: 9 additions & 28 deletions plugins/packages/restapi/lib/manifest.json
Expand Up @@ -35,7 +35,7 @@
"password": {
"encrypted": true
},
"bearer_token":{
"bearer_token": {
"encrypted": true
},
"scopes": {
Expand Down Expand Up @@ -105,36 +105,19 @@
"value": "header"
},
"headers": {
"value": [
[
"",
""
]
]
"value": [["", ""]]
},
"custom_query_params": {
"value": [
[
"",
""
]
]
"value": [["", ""]]
},
"custom_auth_params": {
"value": [
[
"",
""
]
]
"value": [["", ""]]
},
"access_token_custom_headers": {
"value": [
[
"",
""
]
]
"value": [["", ""]]
},
"multiple_auth_enabled": {
"value": false
}
},
"properties": {
Expand All @@ -157,7 +140,5 @@
"description": "key-value pair headers for rest api"
}
},
"required": [
"url"
]
"required": ["url"]
}
23 changes: 22 additions & 1 deletion plugins/packages/stripe/lib/index.ts
Expand Up @@ -35,10 +35,11 @@ export default class StripeQueryService implements QueryService {
searchParams: queryParams,
});
} else {
const resolvedBodyParams = this.resolveBodyparams(bodyParams);
response = await got(url, {
method: operation,
headers: this.authHeader(apiKey),
form: bodyParams,
form: resolvedBodyParams,
searchParams: queryParams,
});
}
Expand All @@ -53,4 +54,24 @@ export default class StripeQueryService implements QueryService {
data: result,
};
}

private resolveBodyparams(bodyParams: object): object {
if (typeof bodyParams === 'string') {
return bodyParams;
}

const expectedResult = {};

for (const key of Object.keys(bodyParams)) {
if (typeof bodyParams[key] === 'object') {
for (const subKey of Object.keys(bodyParams[key])) {
expectedResult[`${key}[${subKey}]`] = bodyParams[key][subKey];
}
} else {
expectedResult[key] = bodyParams[key];
}
}

return expectedResult;
}
}
2 changes: 1 addition & 1 deletion server/.version
@@ -1 +1 @@
1.25.3
1.25.6

0 comments on commit ddf28a1

Please sign in to comment.