Skip to content

Commit 37accec

Browse files
authored
Merge pull request #1035 from fdrab/secrets
Change to secret inputs in response to #6338 in st2
2 parents be6b339 + 845c4b2 commit 37accec

File tree

9 files changed

+98
-51
lines changed

9 files changed

+98
-51
lines changed

CHANGELOG.rst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,11 @@ in development
66

77
Changed
88
~~~~~~~
9+
* Changed how secrets are handled in the UI from type=password
10+
to using CSS webkit-text-security.
11+
12+
Contributed by @fdrab
13+
914
* Updated various dependencies (security). #1009, #1020
1015

1116
Contributed by @enykeev

modules/st2-auto-form/auto-form.component.js

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@ import IntegerField from './fields/integer';
2323
import BooleanField from './fields/boolean';
2424
import StringField from './fields/string';
2525
import ObjectField from './fields/object';
26-
import PasswordField from './fields/password';
2726
import EnumField from './fields/enum';
2827

2928
import './style.css';
@@ -57,10 +56,6 @@ export default class AutoForm extends React.Component {
5756
case 'boolean':
5857
return BooleanField;
5958
case 'string':
60-
if (field.secret) {
61-
return PasswordField;
62-
}
63-
6459
return StringField;
6560
case 'object':
6661
return ObjectField;

modules/st2-auto-form/fields/base.js

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ export class BaseTextField extends React.Component {
4545
spec: PropTypes.object,
4646
value: PropTypes.any,
4747
disabled: PropTypes.bool,
48+
visible: PropTypes.bool,
4849
onChange: PropTypes.func,
4950
'data-test': PropTypes.string,
5051
}
@@ -54,6 +55,7 @@ export class BaseTextField extends React.Component {
5455

5556
this.state = {
5657
value: this.toStateValue(this.props.value),
58+
visible: false,
5759
};
5860
}
5961

@@ -105,6 +107,10 @@ export class BaseTextField extends React.Component {
105107
}
106108
}
107109

110+
visibilityToggle() {
111+
this.setState({visible: !this.state.visible})
112+
}
113+
108114
emitChange() {
109115
return this.props.onChange(this.fromStateValue(this.state.value));
110116
}
@@ -113,18 +119,22 @@ export class BaseTextField extends React.Component {
113119
const { icon } = this.constructor;
114120
const { invalid } = this.state;
115121
const { spec={} } = this.props;
116-
const wrapperProps = Object.assign({}, this.props);
122+
const wrapperProps = Object.assign({}, this.props, {
123+
visibilityToggle: () => this.visibilityToggle(),
124+
visible: this.state.visible,
125+
});
117126

118127
if (invalid) {
119128
wrapperProps.invalid = invalid;
120129
}
121130

122131
const inputProps = {
123-
className: 'st2-auto-form__field',
124-
type: spec.secret ? 'password' : 'text',
132+
className: spec.secret && !this.state.visible ? 'st2-auto-form__field--secret' : 'st2-auto-form__field',
133+
type: 'text',
125134
placeholder:this.toStateValue(spec.default),
126135
disabled: this.props.disabled,
127136
value: this.state.value,
137+
spellCheck: spec.secret && !this.state.visible ? false : true,
128138
onChange: (e) => this.handleChange(e, e.target.value),
129139
'data-test': this.props['data-test'],
130140
};
@@ -135,7 +145,7 @@ export class BaseTextField extends React.Component {
135145

136146
return (
137147
<TextFieldWrapper icon={icon} {...wrapperProps}>
138-
<input {...inputProps} />
148+
<input {...inputProps} />
139149
</TextFieldWrapper>
140150
);
141151
}
@@ -145,19 +155,23 @@ export class BaseTextareaField extends BaseTextField {
145155
render() {
146156
const { icon } = this.constructor;
147157
const { invalid } = this.state;
148-
const { spec={} } = this.props;
158+
const { spec = {} } = this.props;
149159

150-
const wrapperProps = Object.assign({}, this.props);
160+
const wrapperProps = Object.assign({}, this.props, {
161+
visibilityToggle: () => this.visibilityToggle(),
162+
visible: this.state.visible,
163+
});
151164

152165
if (invalid) {
153166
wrapperProps.invalid = invalid;
154167
}
155168

156169
const inputProps = {
157-
className: 'st2-auto-form__field',
170+
className: spec.secret && !this.state.visible ? 'st2-auto-form__field--secret' : 'st2-auto-form__field',
158171
placeholder: this.toStateValue(spec.default),
159172
disabled: this.props.disabled,
160173
value: this.state.value,
174+
spellCheck: spec.secret && !this.state.visible ? false : true,
161175
onChange: (e) => this.handleChange(e, e.target.value),
162176
minRows: 1,
163177
maxRows: 10,
@@ -170,7 +184,7 @@ export class BaseTextareaField extends BaseTextField {
170184

171185
return (
172186
<TextFieldWrapper icon={icon} {...wrapperProps}>
173-
<Textarea {...inputProps} />
187+
<Textarea {...inputProps} />
174188
</TextFieldWrapper>
175189
);
176190
}

modules/st2-auto-form/fields/index.js

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@ import EnumField from './enum';
1919
import IntegerField from './integer';
2020
import NumberField from './number';
2121
import ObjectField from './object';
22-
import PasswordField from './password';
2322
import StringField from './string';
2423
import SelectField from './select';
2524
import ColorStringField from './color-string';
@@ -31,7 +30,6 @@ export {
3130
IntegerField,
3231
NumberField,
3332
ObjectField,
34-
PasswordField,
3533
StringField,
3634
SelectField,
3735
ColorStringField,

modules/st2-auto-form/fields/integer.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,6 @@ export default class IntegerField extends BaseTextField {
7272
}
7373
}
7474

75-
return v && !validator.isInt(v) && `'${v}' is not an integer`;
75+
return v && !validator.isInt(v) && `'${spec.secret ? "*".repeat(v.length) : v}' is not an integer`;
7676
}
7777
}

modules/st2-auto-form/fields/number.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ export default class NumberField extends BaseTextField {
4848
if (invalid !== void 0) {
4949
return invalid;
5050
}
51-
52-
return v && !validator.isFloat(v) && `'${v}' is not a number`;
51+
52+
return v && !validator.isFloat(v) && `'${spec.secret ? "*".repeat(v.length) : v}' is not a number`;
5353
}
5454
}

modules/st2-auto-form/fields/password.js

Lines changed: 0 additions & 27 deletions
This file was deleted.

modules/st2-auto-form/style.css

Lines changed: 41 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,11 @@
1717
margin-bottom: 12px;
1818
}
1919

20+
&__wrapper-block {
21+
display: flex;
22+
align-items: center;
23+
}
24+
2025
&__title {
2126
font-size: 15px;
2227
line-height: 18px;
@@ -70,6 +75,21 @@
7075
&:hover {
7176
color: var(--aqua-base);
7277
}
78+
79+
&:before {
80+
font-family: "brocadeicons";
81+
font-size: 18px;
82+
font-weight: normal;
83+
font-style: normal;
84+
line-height: 36px;
85+
86+
display: flex;
87+
88+
vertical-align: middle;
89+
pointer-events: none;
90+
91+
color: var(--grey-base);
92+
}
7393
}
7494

7595
&__field {
@@ -88,6 +108,21 @@
88108
background-color: white;
89109
box-shadow: 0 1px 0 var(--grey-lighten-2);
90110

111+
&--secret {
112+
font-weight: normal;
113+
font-family: Roboto, sans-serif;
114+
-webkit-box-sizing: border-box;
115+
-moz-box-sizing: border-box;
116+
box-sizing: border-box;
117+
width: 100%;
118+
119+
color: black;
120+
border: none;
121+
outline: 0;
122+
box-shadow: 0 1px 0 var(--grey-lighten-2);
123+
-webkit-text-security: disc;
124+
}
125+
91126
&&[disabled] {
92127
cursor: default;
93128

@@ -144,24 +179,25 @@
144179
color: black;
145180
}
146181

147-
&__text-field &__field {
182+
&__text-field &__field,
183+
&__text-field &__field--secret {
148184
font-size: 13px;
149185
line-height: 18px;
150186

151187
display: block;
152188
overflow-x: hidden;
153189
overflow-y: scroll;
154190

155-
padding: 9px 12px;
191+
padding: 9px 40px 9px 9px;
156192

157193
resize: none;
158194
cursor: text;
159195
word-wrap: break-word;
160-
max-height:50px;
196+
max-height:100px;
161197
&::-webkit-scrollbar {
162198
width: 13px;
163199
height: 13px;
164-
200+
165201
background-color: transparent;
166202
}
167203

@@ -171,6 +207,7 @@
171207
background-color: rgba(117, 117, 117, .3);
172208
background-clip: padding-box;
173209

210+
174211
&:hover {
175212
background-color: rgba(117, 117, 117, .7);
176213
}
@@ -249,7 +286,6 @@
249286
padding: 0 10px 0 0;
250287

251288
content: "\e91c";
252-
vertical-align: middle;
253289
pointer-events: none;
254290

255291
color: black;

modules/st2-auto-form/wrappers.js

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -171,15 +171,41 @@ export class TextFieldWrapper extends React.Component {
171171
children: PropTypes.element.isRequired,
172172
icon: PropTypes.string,
173173
labelClass: PropTypes.string,
174+
visible: PropTypes.bool,
175+
visibilityToggle: PropTypes.func,
174176
}
175177

178+
handleVisibilityToggle() {
179+
this.props.visibilityToggle && this.props.visibilityToggle()
180+
}
181+
182+
176183
render() {
184+
const buttonProps = {
185+
icon: this.props.visible ? 'view2' : 'view',
186+
title: this.props.visible ? 'hide value' : 'see value',
187+
onClick: () => this.handleVisibilityToggle(),
188+
};
189+
190+
const blockProps = {
191+
className: 'st2-auto-form__wrapper-block',
192+
};
193+
177194
const line = (
178195
<div className='st2-auto-form__line'>
179196
<Label className={this.props.labelClass || 'st2-auto-form__text-field'}>
180197
<Icon name={this.props.icon} />
181198
<Title {...this.props} />
182-
{ this.props.children }
199+
{
200+
this.props.spec && this.props.spec.secret
201+
?
202+
<div {...blockProps}>
203+
<Button {...buttonProps} />
204+
{ this.props.children }
205+
</div>
206+
:
207+
this.props.children
208+
}
183209
<ErrorMessage>{ this.props.invalid }</ErrorMessage>
184210
</Label>
185211
<Description {...this.props} />

0 commit comments

Comments
 (0)