You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@skywalking.apache.org by qi...@apache.org on 2023/05/12 11:21:51 UTC

[skywalking-grafana-plugins] branch main updated: feat: add username and password (#8)

This is an automated email from the ASF dual-hosted git repository.

qiuxiafan pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/skywalking-grafana-plugins.git


The following commit(s) were added to refs/heads/main by this push:
     new 71b60de  feat: add username and password (#8)
71b60de is described below

commit 71b60dee410ca37bc6c6a949b08b321d774071b6
Author: Fine0830 <fa...@gmail.com>
AuthorDate: Fri May 12 19:21:45 2023 +0800

    feat: add username and password (#8)
---
 src/components/ConfigEditor.tsx | 101 ++++++++++++++++++++++++----------------
 src/constant.ts                 |   4 ++
 src/datasource.ts               |  18 +++++--
 src/plugin.json                 |   8 +++-
 src/types.ts                    |   4 ++
 5 files changed, 89 insertions(+), 46 deletions(-)

diff --git a/src/components/ConfigEditor.tsx b/src/components/ConfigEditor.tsx
index cecc99d..153d556 100644
--- a/src/components/ConfigEditor.tsx
+++ b/src/components/ConfigEditor.tsx
@@ -15,61 +15,70 @@
  * limitations under the License.
  */
 import React, { ChangeEvent } from 'react';
-import { InlineField, Input, SecretInput } from '@grafana/ui';
+import { InlineField, Input, Select } from '@grafana/ui';
 import { DataSourcePluginOptionsEditorProps } from '@grafana/data';
-import { MyDataSourceOptions, MySecureJsonData } from '../types';
+import { MyDataSourceOptions } from '../types';
+import {AuthenticationType} from "../constant";
 
 interface Props extends DataSourcePluginOptionsEditorProps<MyDataSourceOptions> {}
 
 export function ConfigEditor(props: Props) {
-  const { onOptionsChange, options } = props;
-  const onPathChange = (event: ChangeEvent<HTMLInputElement>) => {
+  const { options } = props;
+
+  const onURLChange = (event: ChangeEvent<HTMLInputElement>) => {
+    const { onOptionsChange, options } = props;
     const jsonData = {
       ...options.jsonData,
-      path: event.target.value,
+      URL: event.target.value,
     };
     onOptionsChange({ ...options, jsonData });
   };
 
-  // Secure field (only sent to the backend)
-  const onAPIKeyChange = (event: ChangeEvent<HTMLInputElement>) => {
-    onOptionsChange({
-      ...options,
-      secureJsonData: {
-        apiKey: event.target.value,
-      },
-    });
+  const onTypeChange = (v: any) => {
+    const { onOptionsChange, options } = props;
+    const jsonData = {
+      ...options.jsonData,
+      type: v.value,
+      username: v.value === AuthenticationType[1].value ? '' : options.jsonData.username,
+      password: v.value === AuthenticationType[1].value ? '' : options.jsonData.password,
+    };
+    onOptionsChange({ ...options, jsonData });
   };
 
-  const onResetAPIKey = () => {
-    onOptionsChange({
+  const onUserChange = (event: ChangeEvent<HTMLInputElement>) => {
+    const { onOptionsChange, options } = props;
+    const basicAuth = btoa(encodeURI(`${event.target.value}:${options.jsonData.password}`));
+    const jsonData = {
+      ...options.jsonData,
+      username: event.target.value,
+      basicAuth,
+    };
+
+    onOptionsChange({ 
       ...options,
-      secureJsonFields: {
-        ...options.secureJsonFields,
-        apiKey: false,
-      },
-      secureJsonData: {
-        ...options.secureJsonData,
-        apiKey: '',
-      },
+      jsonData,
     });
   };
 
-  const onURLChange = (event: ChangeEvent<HTMLInputElement>) => {
+  const onPasswordChange = (event: ChangeEvent<HTMLInputElement>) => {
     const { onOptionsChange, options } = props;
+    const basicAuth = btoa(encodeURI(`${options.jsonData.username}:${event.target.value}`));
     const jsonData = {
       ...options.jsonData,
-      URL: event.target.value,
+      password: event.target.value,
+      basicAuth,
     };
-    onOptionsChange({ ...options, jsonData });
+    onOptionsChange({ 
+      ...options,
+      jsonData,
+    });
   };
 
-  const { jsonData, secureJsonFields } = options;
-  const secureJsonData = (options.secureJsonData || {}) as MySecureJsonData;
+  const { jsonData } = options;
 
   return (
     <div className="gf-form-group">
-      <InlineField label="URL" labelWidth={12}>
+      <InlineField label="URL" labelWidth={18}>
         <Input
           onChange={onURLChange}
           value={jsonData.URL || ''}
@@ -77,24 +86,36 @@ export function ConfigEditor(props: Props) {
           width={40}
         />
       </InlineField>
-      <InlineField label="Path" labelWidth={12}>
+      <InlineField label="Authentication Type" labelWidth={18} >
+        <Select
+          options={AuthenticationType}
+          value={jsonData.type || AuthenticationType[1].value}
+          onChange={onTypeChange}
+          width={40}
+          placeholder="Choose an authentication type"
+          menuPlacement="bottom"
+        />
+      </InlineField>
+      {jsonData.type === AuthenticationType[0].value &&
+      <div>
+        <InlineField label="User Name" labelWidth={18}>
         <Input
-          onChange={onPathChange}
-          value={jsonData.path || ''}
-          placeholder="json field returned to frontend"
+          onChange={onUserChange}
+          value={jsonData.username || ''}
+          placeholder="Please input username"
           width={40}
         />
       </InlineField>
-      <InlineField label="API Key" labelWidth={12}>
-        <SecretInput
-          isConfigured={(secureJsonFields && secureJsonFields.apiKey) as boolean}
-          value={secureJsonData.apiKey || ''}
-          placeholder="secure json field (backend only)"
+      <InlineField label="Password" labelWidth={18}>
+        <Input
+          onChange={onPasswordChange}
+          value={jsonData.password || ''}
+          placeholder="Please input password"
           width={40}
-          onReset={onResetAPIKey}
-          onChange={onAPIKeyChange}
+          type="password"
         />
       </InlineField>
+    </div>}
     </div>
   );
 }
diff --git a/src/constant.ts b/src/constant.ts
index 79f1658..6731f8e 100644
--- a/src/constant.ts
+++ b/src/constant.ts
@@ -66,3 +66,7 @@ export const EdgeMetrics = `{
   "unit": "cpm",
   "type": "CLINET"
 }`
+export const AuthenticationType = [
+  {label: 'BASIC', value: 'BASIC', text: 'BASIC'},
+  {label: 'None', value: 'NONE', text: 'None'},
+]
diff --git a/src/datasource.ts b/src/datasource.ts
index f7835cb..afba49d 100644
--- a/src/datasource.ts
+++ b/src/datasource.ts
@@ -41,14 +41,18 @@ import {
   Node,
   Recordable
 } from './types';
-import { Fragments, RoutePath, TimeType, Calculations } from "./constant";
+import { Fragments, RoutePath, TimeType, Calculations, AuthenticationType } from "./constant";
 
 export class DataSource extends DataSourceApi<MyQuery, MyDataSourceOptions> {
   URL: string;
+  type: string;
+  basicAuth: string
   constructor(instanceSettings: DataSourceInstanceSettings<MyDataSourceOptions>) {
     super(instanceSettings);
     // proxy url
     this.URL = instanceSettings.url || '';
+    this.type = instanceSettings.jsonData.type || '';
+    this.basicAuth = instanceSettings.jsonData.basicAuth || '';
     dayjs.extend(utc)
     dayjs.extend(timezone)
   }
@@ -156,10 +160,14 @@ export class DataSource extends DataSourceApi<MyQuery, MyDataSourceOptions> {
   async doRequest(params?: Recordable) {
     // Do the request on proxy; the server will replace url + routePath with the url
     // defined in plugin.json
-    const result = getBackendSrv().post(`${this.URL}${RoutePath}`, params, { headers: {
-      'Content-Type': 'application/json',
-      'Authorization': 'Basic c2t5d2Fsa2luZzpza3l3YWxraW5n',
-    } });
+    let headers =  {};
+
+    if (this.type === AuthenticationType[0].value) {
+      headers = {
+        'Authorization': `Basic ${this.basicAuth}`, // 'Basic c2t5d2Fsa2luZzpza3l3YWxraW5n'
+      };
+    }
+    const result = getBackendSrv().post(`${this.URL}${RoutePath}`, params, {headers});
 
     return result;
   }
diff --git a/src/plugin.json b/src/plugin.json
index 5f3c761..7e29163 100644
--- a/src/plugin.json
+++ b/src/plugin.json
@@ -26,7 +26,13 @@
   "routes": [
     {
       "path": "graphql",
-      "url": "{{ .JsonData.URL }}"
+      "url": "{{ .JsonData.URL }}",
+      "headers": [
+        {
+          "name": "Content-Type",
+          "content": "application/json"
+        }
+      ]
     }
   ]
 }
diff --git a/src/types.ts b/src/types.ts
index c85b38a..87601e9 100644
--- a/src/types.ts
+++ b/src/types.ts
@@ -33,6 +33,10 @@ export const DEFAULT_QUERY: Partial<MyQuery> = {};
 export interface MyDataSourceOptions extends DataSourceJsonData {
   path?: string;
   URL: string;
+  username: string;
+  password: string;
+  basicAuth: string;
+  type: string;
 }
 
 /**