You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@devlake.apache.org by li...@apache.org on 2023/02/01 14:15:41 UTC
[incubator-devlake] branch main updated: feat(config-ui): support bearer authentication for jira (#4287)
This is an automated email from the ASF dual-hosted git repository.
likyh pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/incubator-devlake.git
The following commit(s) were added to refs/heads/main by this push:
new e5157e854 feat(config-ui): support bearer authentication for jira (#4287)
e5157e854 is described below
commit e5157e854aa5da68680de729ee77cbc33ee8d91e
Author: 青湛 <0x...@gmail.com>
AuthorDate: Wed Feb 1 22:15:36 2023 +0800
feat(config-ui): support bearer authentication for jira (#4287)
---
.../src/pages/connection/form/components/index.ts | 1 +
.../connection/form/components/jira-auth/index.tsx | 115 +++++++++++++++++++++
config-ui/src/pages/connection/form/index.tsx | 32 +++++-
.../src/plugins/register/base/connection-fields.ts | 8 ++
config-ui/src/plugins/register/jira/config.ts | 10 +-
config-ui/src/plugins/types.ts | 5 +-
6 files changed, 158 insertions(+), 13 deletions(-)
diff --git a/config-ui/src/pages/connection/form/components/index.ts b/config-ui/src/pages/connection/form/components/index.ts
index 3fc2e5b52..448d0ba62 100644
--- a/config-ui/src/pages/connection/form/components/index.ts
+++ b/config-ui/src/pages/connection/form/components/index.ts
@@ -19,3 +19,4 @@
export * from './rate-limit';
export * from './github-token';
export * from './gitlab-token';
+export * from './jira-auth';
diff --git a/config-ui/src/pages/connection/form/components/jira-auth/index.tsx b/config-ui/src/pages/connection/form/components/jira-auth/index.tsx
new file mode 100644
index 000000000..638b15324
--- /dev/null
+++ b/config-ui/src/pages/connection/form/components/jira-auth/index.tsx
@@ -0,0 +1,115 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+import React, { useState } from 'react';
+import { FormGroup, RadioGroup, Radio, InputGroup } from '@blueprintjs/core';
+
+type Method = 'BasicAuth' | 'AccessToken';
+
+type Value = {
+ authMethod: string;
+ username?: string;
+ password?: string;
+ token?: string;
+};
+
+interface Props {
+ value: Value;
+ onChange: (value: Value) => void;
+}
+
+export const JIRAAuth = ({ value, onChange }: Props) => {
+ const [method, setMethod] = useState<Method>('BasicAuth');
+
+ const handleChangeMethod = (e: React.FormEvent<HTMLInputElement>) => {
+ const m = (e.target as HTMLInputElement).value as Method;
+
+ setMethod(m);
+ onChange({
+ authMethod: m,
+ username: m === 'BasicAuth' ? value.username : undefined,
+ password: m === 'BasicAuth' ? value.password : undefined,
+ token: m === 'AccessToken' ? value.token : undefined,
+ });
+ };
+
+ const handleChangeUsername = (e: React.ChangeEvent<HTMLInputElement>) => {
+ onChange({
+ authMethod: 'BasicAuth',
+ username: e.target.value,
+ });
+ };
+
+ const handleChangePassword = (e: React.ChangeEvent<HTMLInputElement>) => {
+ onChange({
+ authMethod: 'BasicAuth',
+ password: e.target.value,
+ });
+ };
+
+ const handleChangeToken = (e: React.ChangeEvent<HTMLInputElement>) => {
+ onChange({
+ ...value,
+ token: e.target.value,
+ });
+ };
+
+ return (
+ <div>
+ <FormGroup inline label="Authentication Method" labelInfo="*">
+ <RadioGroup selectedValue={method} onChange={handleChangeMethod}>
+ <Radio value="BasicAuth">Basic Authentication</Radio>
+ <Radio value="AccessToken">Using Personal Access Token</Radio>
+ </RadioGroup>
+ </FormGroup>
+ {method === 'BasicAuth' && (
+ <>
+ <FormGroup inline label="Username/e-mail" labelInfo="*">
+ <InputGroup
+ placeholder="Your Username/e-mail"
+ value={value.username || ''}
+ onChange={handleChangeUsername}
+ />
+ </FormGroup>
+ <FormGroup inline label="Password" labelInfo="*">
+ <InputGroup
+ type="password"
+ placeholder="Your Password"
+ value={value.password || ''}
+ onChange={handleChangePassword}
+ />
+ </FormGroup>
+ </>
+ )}
+ {method === 'AccessToken' && (
+ <FormGroup inline label="Personal Access Token" labelInfo="*">
+ <p>
+ <a
+ href="https://confluence.atlassian.com/enterprise/using-personal-access-tokens-1026032365.html"
+ target="_blank"
+ rel="noreferrer"
+ >
+ Learn about how to create PAT
+ </a>
+ </p>
+ <InputGroup type="password" placeholder="Your PAT" value={value.token || ''} onChange={handleChangeToken} />
+ </FormGroup>
+ )}
+ </div>
+ );
+};
diff --git a/config-ui/src/pages/connection/form/index.tsx b/config-ui/src/pages/connection/form/index.tsx
index a5d0504ae..630c36ce2 100644
--- a/config-ui/src/pages/connection/form/index.tsx
+++ b/config-ui/src/pages/connection/form/index.tsx
@@ -26,7 +26,7 @@ import { PageHeader, Card, PageLoading } from '@/components';
import type { PluginConfigConnectionType } from '@/plugins';
import { PluginConfig } from '@/plugins';
-import { RateLimit, GitHubToken, GitLabToken } from './components';
+import { RateLimit, GitHubToken, GitLabToken, JIRAAuth } from './components';
import { useForm } from './use-form';
import * as S from './styled';
@@ -51,12 +51,23 @@ export const ConnectionFormPage = () => {
}, [initialValues, connection]);
const error = useMemo(
- () => !!(fields.filter((field) => field.required) ?? []).find((field) => !form[field.key]),
+ () =>
+ fields.every((field) => {
+ if (field.required) {
+ return !!form[field.key];
+ }
+
+ if (field.checkError) {
+ return !field.checkError(form);
+ }
+
+ return true;
+ }),
[form, fields],
);
const handleTest = () =>
- onTest(pick(form, ['endpoint', 'token', 'username', 'password', 'app_id', 'secret_key', 'proxy']));
+ onTest(pick(form, ['endpoint', 'token', 'username', 'password', 'app_id', 'secret_key', 'proxy', 'authMethod']));
const handleCancel = () => history.push(`/connections/${plugin}`);
@@ -70,6 +81,21 @@ export const ConnectionFormPage = () => {
placeholder,
tooltip,
}: PluginConfigConnectionType['connection']['fields']['0']) => {
+ if (type === 'jiraAuth') {
+ return (
+ <JIRAAuth
+ key={key}
+ value={{ authMethod: form.authMethod, username: form.username, password: form.password, token: form.token }}
+ onChange={(value) => {
+ setForm({
+ ...form,
+ ...value,
+ });
+ }}
+ />
+ );
+ }
+
return (
<FormGroup
key={key}
diff --git a/config-ui/src/plugins/register/base/connection-fields.ts b/config-ui/src/plugins/register/base/connection-fields.ts
index 56b4701b1..0a6493bdf 100644
--- a/config-ui/src/plugins/register/base/connection-fields.ts
+++ b/config-ui/src/plugins/register/base/connection-fields.ts
@@ -98,3 +98,11 @@ export const ConnectionGitLabToken = () => ({
required: true,
placeholder: 'eg. ff9d1ad0e5c04f1f98fa',
});
+
+export const ConnectionJIRAAuth = () => ({
+ key: 'auth',
+ type: 'jiraAuth' as const,
+ checkError: (form: any) => {
+ return !!(form.username && form.password) || !!form.token;
+ },
+});
diff --git a/config-ui/src/plugins/register/jira/config.ts b/config-ui/src/plugins/register/jira/config.ts
index eb6289cc4..77dcbea3e 100644
--- a/config-ui/src/plugins/register/jira/config.ts
+++ b/config-ui/src/plugins/register/jira/config.ts
@@ -22,10 +22,9 @@ import {
BaseConnectionConfig,
ConnectionName,
ConnectionEndpoint,
- ConnectionUsername,
- ConnectionPassword,
ConnectionProxy,
ConnectionRatelimit,
+ ConnectionJIRAAuth,
} from '../base';
import Icon from './assets/icon.svg';
@@ -48,12 +47,7 @@ export const JIRAConfig: PluginConfigType = {
ConnectionEndpoint({
placeholder: 'eg. https://your-domain.atlassian.net/rest/',
}),
- ConnectionUsername({
- label: 'Username / E-mail',
- }),
- ConnectionPassword({
- tooltip: 'If you are using JIRA Cloud or JIRA Server,\nyour API Token should be used as password.',
- }),
+ ConnectionJIRAAuth(),
ConnectionProxy(),
ConnectionRatelimit(),
],
diff --git a/config-ui/src/plugins/types.ts b/config-ui/src/plugins/types.ts
index 94282845c..f91389553 100644
--- a/config-ui/src/plugins/types.ts
+++ b/config-ui/src/plugins/types.ts
@@ -32,11 +32,12 @@ export type PluginConfigConnectionType = {
initialValues?: Record<string, any>;
fields: Array<{
key: string;
- type: 'text' | 'password' | 'switch' | 'rateLimit' | 'githubToken' | 'gitlabToken';
- label: string;
+ type: 'text' | 'password' | 'switch' | 'rateLimit' | 'githubToken' | 'gitlabToken' | 'jiraAuth';
+ label?: string;
required?: boolean;
placeholder?: string;
tooltip?: string;
+ checkError?: (value: any) => boolean;
}>;
};
entities: string[];