Explorar o código

Use a configurable list of password fields

You can now use the `config.js` to specify a list of password fields,
which will be used to rendered inputs as password inputs. Applicable to
options and endpoints fields.

If an option or endpoint field contains the 'password' keyword, the
fields will be rendered as password by default (no need to add it to the
config list).
Sergiu Miclea %!s(int64=6) %!d(string=hai) anos
pai
achega
7f2767f0dd

+ 4 - 0
config.js

@@ -73,6 +73,10 @@ const conf: Config = {
   // The list of the users to hide in the UI
   hiddenUsers: ['barbican', 'coriolis'],
 
+  // By default, if a field name contains `password` in it (ex.: `user_password`), it will be rendered as a password input
+  // If the field doesn't contain `password` in its name, the following list will be used instead
+  passwordFields: ['private_key_passphrase', 'secret_access_key'],
+
 }
 
 export const config = conf

+ 1 - 2
src/components/organisms/Endpoint/Endpoint.jsx

@@ -29,7 +29,7 @@ import LoadingButton from '../../molecules/LoadingButton'
 import type { Endpoint as EndpointType } from '../../../types/Endpoint'
 import type { Field } from '../../../types/Field'
 import notificationStore from '../../../stores/NotificationStore'
-import endpointStore, { passwordFields } from '../../../stores/EndpointStore'
+import endpointStore from '../../../stores/EndpointStore'
 import providerStore from '../../../stores/ProviderStore'
 import ObjectUtils from '../../../utils/ObjectUtils'
 import Palette from '../../styleUtils/Palette'
@@ -387,7 +387,6 @@ class Endpoint extends React.Component<Props, State> {
           validating: this.state.validating,
           disabled: this.state.validating,
           cancelButtonText: this.props.cancelButtonText,
-          passwordFields,
           getFieldValue: field => this.getFieldValue(field),
           highlightRequired: () => this.highlightRequired(),
           handleFieldChange: (field, value) => {

+ 2 - 2
src/components/organisms/EndpointDetailsContent/EndpointDetailsContent.jsx

@@ -32,6 +32,7 @@ import StyleProps from '../../styleUtils/StyleProps'
 import Palette from '../../styleUtils/Palette'
 import DateUtils from '../../../utils/DateUtils'
 import LabelDictionary from '../../../utils/LabelDictionary'
+import configLoader from '../../../utils/Config'
 
 const Wrapper = styled.div`
   ${StyleProps.exactWidth(StyleProps.contentWidth)}
@@ -83,7 +84,6 @@ type Props = {
   usage: { migrations: MainItem[], replicas: MainItem[] },
   onDeleteClick: () => void,
   onValidateClick: () => void,
-  passwordFields?: string[],
 }
 @observer
 class EndpointDetailsContent extends React.Component<Props> {
@@ -133,7 +133,7 @@ class EndpointDetailsContent extends React.Component<Props> {
 
       let valueClass = null
 
-      if (this.props.passwordFields && this.props.passwordFields.find(fn => fn === key)) {
+      if (configLoader.config.passwordFields.find(fn => fn === key) || key.indexOf('password') > -1) {
         valueClass = <PasswordValue value={value} data-test-id="edContent-connPassword" />
       } else {
         valueClass = this.renderValue(value, `connValue-${key}`)

+ 4 - 4
src/components/organisms/WizardOptions/WizardOptions.jsx

@@ -19,6 +19,7 @@ import styled from 'styled-components'
 import { observer } from 'mobx-react'
 import autobind from 'autobind-decorator'
 
+import configLoader from '../../../utils/Config'
 import StyleProps from '../../styleUtils/StyleProps'
 import ToggleButtonBar from '../../atoms/ToggleButtonBar'
 import FieldInput from '../../molecules/FieldInput'
@@ -160,9 +161,8 @@ class WizardOptions extends React.Component<Props> {
     return fieldsSchema
   }
 
-  isPassword(field: Field): boolean {
-    return field.type === 'string' && (!field.enum || field.enum.length === 0) &&
-      field.name.indexOf('password') > -1
+  isPassword(fieldName: string): boolean {
+    return fieldName.indexOf('password') > -1 || Boolean(configLoader.config.passwordFields.find(f => f === fieldName))
   }
 
   @autobind
@@ -190,7 +190,7 @@ class WizardOptions extends React.Component<Props> {
         key={field.name}
         name={field.name}
         type={field.type}
-        password={this.isPassword(field)}
+        password={this.isPassword(field.name)}
         enum={field.enum}
         addNullValue
         required={field.required}

+ 1 - 2
src/components/pages/EndpointDetailsPage/EndpointDetailsPage.jsx

@@ -28,7 +28,7 @@ import EndpointValidation from '../../organisms/EndpointValidation'
 import Endpoint from '../../organisms/Endpoint'
 import EndpointDuplicateOptions from '../../organisms/EndpointDuplicateOptions'
 
-import endpointStore, { passwordFields } from '../../../stores/EndpointStore'
+import endpointStore from '../../../stores/EndpointStore'
 import migrationStore from '../../../stores/MigrationStore'
 import replicaStore from '../../../stores/ReplicaStore'
 import userStore from '../../../stores/UserStore'
@@ -245,7 +245,6 @@ class EndpointDetailsPage extends React.Component<Props, State> {
           />}
           contentComponent={<EndpointDetailsContent
             item={endpoint}
-            passwordFields={passwordFields}
             usage={this.state.endpointUsage}
             loading={endpointStore.connectionInfoLoading || endpointStore.loading}
             connectionInfo={endpointStore.connectionInfo}

+ 4 - 1
src/plugins/endpoint/azure/ContentPlugin.jsx

@@ -21,6 +21,7 @@ import TextArea from '../../../components/atoms/TextArea'
 import ToggleButtonBar from '../../../components/atoms/ToggleButtonBar'
 import type { Field } from '../../../types/Field'
 
+import configLoader from '../../../utils/Config'
 import Palette from '../../../components/styleUtils/Palette'
 import StyleProps from '../../../components/styleUtils/StyleProps'
 import KeyboardManager from '../../../utils/KeyboardManager'
@@ -207,13 +208,15 @@ class ContentPlugin extends React.Component<Props, State> {
   }
 
   renderField(field: Field, customProps?: { value: any, onChange: (value: any) => void }) {
+    let isPassword = Boolean(configLoader.config.passwordFields.find(fn => field.name === fn))
+      || field.name.indexOf('password') > -1
     return (
       <FieldStyled
         {...field}
         width={StyleProps.inputSizes.large.width}
         disabled={this.props.disabled}
         key={field.name}
-        password={field.name === 'password'}
+        password={isPassword}
         highlight={this.props.invalidFields.findIndex(fn => fn === field.name) > -1}
         value={this.props.getFieldValue(field)}
         onChange={value => { this.handleFieldChange(field, value) }}

+ 4 - 2
src/plugins/endpoint/default/ContentPlugin.jsx

@@ -17,6 +17,8 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 import * as React from 'react'
 import styled from 'styled-components'
 
+import configLoader from '../../../utils/Config'
+
 import FieldInput from '../../../components/molecules/FieldInput'
 import type { Field } from '../../../types/Field'
 
@@ -55,7 +57,6 @@ type Props = {
   cancelButtonText: string,
   validating: boolean,
   onRef: (contentPlugin: any) => void,
-  passwordFields?: string[],
 }
 class ContentPlugin extends React.Component<Props> {
   componentDidMount() {
@@ -83,7 +84,8 @@ class ContentPlugin extends React.Component<Props> {
     let lastField
     let i = 0
     this.props.connectionInfoSchema.forEach((field, schemaIndex) => {
-      let isPassword = this.props.passwordFields && this.props.passwordFields.find(fn => fn === field.name)
+      let isPassword = Boolean(configLoader.config.passwordFields.find(fn => field.name === fn))
+        || field.name.indexOf('password') > -1
       const currentField = (
         <FieldStyled
           {...field}

+ 3 - 2
src/plugins/endpoint/openstack/ContentPlugin.jsx

@@ -166,14 +166,15 @@ class ContentPlugin extends React.Component<Props, State> {
         || (this.useCurrentUser && field.name !== 'name' && field.name !== 'description' && field.name !== 'openstack_use_current_user')
       let required = this.isFieldRequired(field)
         || (this.getApiVersion() > 2 ? field.name === 'user_domain' || field.name === 'project_domain' : false)
-
+      let isPassword = Boolean(configLoader.config.passwordFields.find(fn => field.name === fn))
+        || field.name.indexOf('password') > -1
       const currentField = (
         <FieldStyled
           {...field}
           required={required}
+          password={isPassword}
           width={StyleProps.inputSizes.large.width}
           disabled={disabled}
-          password={field.name === 'password'}
           highlight={this.props.invalidFields.findIndex(fn => fn === field.name) > -1}
           value={this.getFieldValue(field)}
           onChange={value => { this.props.handleFieldChange(field, value) }}

+ 0 - 2
src/stores/EndpointStore.js

@@ -18,8 +18,6 @@ import type { Endpoint, Validation, StorageBackend, Storage } from '../types/End
 import notificationStore from './NotificationStore'
 import EndpointSource from '../sources/EndpointSource'
 
-export const passwordFields = ['password', 'private_key_passphrase', 'secret_access_key']
-
 const updateEndpoint = (endpoint, endpoints) => endpoints.map(e => {
   if (e.id === endpoint.id) {
     return { ...endpoint }

+ 1 - 0
src/types/Config.js

@@ -14,4 +14,5 @@ export type Config = {
   extraOptionsApiCalls: Array<{ name: string, types: Type[], requiredFields: string[] }>,
   providerSortPriority: { [providerName: string]: number },
   hiddenUsers: string[],
+  passwordFields: string[],
 }