This commit is contained in:
Mohamed Karray
2018-12-06 17:38:03 +01:00
7 changed files with 61 additions and 31 deletions

View File

@@ -11,7 +11,7 @@ type State = {
passwordConfirmationFailed: boolean
};
type Props = {
passwordChanged: string => void,
passwordChanged: (string, boolean) => void,
passwordValidator?: string => boolean,
// Context props
t: string => string
@@ -98,14 +98,12 @@ class PasswordConfirmation extends React.Component<Props, State> {
);
};
isValid = () => {
return this.state.passwordValid && !this.state.passwordConfirmationFailed
};
propagateChange = () => {
if (
this.state.password &&
this.state.passwordValid &&
!this.state.passwordConfirmationFailed
) {
this.props.passwordChanged(this.state.password);
}
this.props.passwordChanged(this.state.password, this.isValid());
};
}

View File

@@ -21,7 +21,8 @@ type State = {
password: string,
loading: boolean,
error?: Error,
passwordChanged: boolean
passwordChanged: boolean,
passwordValid: boolean
};
class ChangeUserPassword extends React.Component<Props, State> {
@@ -35,7 +36,8 @@ class ChangeUserPassword extends React.Component<Props, State> {
passwordConfirmationError: false,
validatePasswordError: false,
validatePassword: "",
passwordChanged: false
passwordChanged: false,
passwordValid: false
};
}
@@ -83,6 +85,10 @@ class ChangeUserPassword extends React.Component<Props, State> {
}
};
isValid = () => {
return this.state.oldPassword && this.state.passwordValid;
};
render() {
const { t } = this.props;
const { loading, passwordChanged, error } = this.state;
@@ -118,7 +124,7 @@ class ChangeUserPassword extends React.Component<Props, State> {
key={this.state.passwordChanged ? "changed" : "unchanged"}
/>
<SubmitButton
disabled={!this.state.password}
disabled={!this.isValid()}
loading={loading}
label={t("password.submit")}
/>
@@ -126,8 +132,8 @@ class ChangeUserPassword extends React.Component<Props, State> {
);
}
passwordChanged = (password: string) => {
this.setState({ ...this.state, password });
passwordChanged = (password: string, passwordValid: boolean) => {
this.setState({ ...this.state, password, passwordValid: (!!password && passwordValid) });
};
onClose = () => {

View File

@@ -19,7 +19,8 @@ type State = {
password: string,
loading: boolean,
error?: Error,
passwordChanged: boolean
passwordChanged: boolean,
passwordValid: boolean
};
class SetUserPassword extends React.Component<Props, State> {
@@ -32,7 +33,8 @@ class SetUserPassword extends React.Component<Props, State> {
passwordConfirmationError: false,
validatePasswordError: false,
validatePassword: "",
passwordChanged: false
passwordChanged: false,
passwordValid: false
};
}
@@ -104,7 +106,7 @@ class SetUserPassword extends React.Component<Props, State> {
key={this.state.passwordChanged ? "changed" : "unchanged"}
/>
<SubmitButton
disabled={!this.state.password}
disabled={!this.state.passwordValid}
loading={loading}
label={t("user-form.submit")}
/>
@@ -112,8 +114,8 @@ class SetUserPassword extends React.Component<Props, State> {
);
}
passwordChanged = (password: string) => {
this.setState({ ...this.state, password });
passwordChanged = (password: string, passwordValid: boolean) => {
this.setState({ ...this.state, password, passwordValid: (!!password && passwordValid) });
};
onClose = () => {

View File

@@ -22,7 +22,8 @@ type State = {
user: User,
mailValidationError: boolean,
nameValidationError: boolean,
displayNameValidationError: boolean
displayNameValidationError: boolean,
passwordValid: boolean
};
class UserForm extends React.Component<Props, State> {
@@ -41,7 +42,8 @@ class UserForm extends React.Component<Props, State> {
},
mailValidationError: false,
displayNameValidationError: false,
nameValidationError: false
nameValidationError: false,
passwordValid: false
};
}
@@ -61,7 +63,6 @@ class UserForm extends React.Component<Props, State> {
isValid = () => {
const user = this.state.user;
const passwordValid = this.props.user ? !this.isFalsy(user.password) : true;
return !(
this.state.nameValidationError ||
this.state.mailValidationError ||
@@ -69,7 +70,7 @@ class UserForm extends React.Component<Props, State> {
this.isFalsy(user.name) ||
this.isFalsy(user.displayName) ||
this.isFalsy(user.mail) ||
passwordValid
!this.state.passwordValid
);
};
@@ -166,9 +167,10 @@ class UserForm extends React.Component<Props, State> {
});
};
handlePasswordChange = (password: string) => {
handlePasswordChange = (password: string, passwordValid: boolean) => {
this.setState({
user: { ...this.state.user, password }
user: { ...this.state.user, password },
passwordValid: !this.isFalsy(password) && passwordValid
});
};

View File

@@ -51,6 +51,7 @@ import static com.google.common.base.Preconditions.*;
//~--- JDK imports ------------------------------------------------------------
import java.security.SecureRandom;
import java.util.Random;
import javax.inject.Inject;
import javax.inject.Singleton;
@@ -88,12 +89,17 @@ public class SecureKeyResolver extends SigningKeyResolverAdapter
*/
@Inject
@SuppressWarnings("unchecked")
public SecureKeyResolver(ConfigurationEntryStoreFactory storeFactory)
public SecureKeyResolver(ConfigurationEntryStoreFactory storeFactory) {
this(storeFactory, new SecureRandom());
}
SecureKeyResolver(ConfigurationEntryStoreFactory storeFactory, Random random)
{
store = storeFactory
.withType(SecureKey.class)
.withName(STORE_NAME)
.build();
this.random = random;
}
//~--- methods --------------------------------------------------------------
@@ -112,7 +118,9 @@ public class SecureKeyResolver extends SigningKeyResolverAdapter
SecureKey key = store.get(subject);
checkState(key != null, "could not resolve key for subject %s", subject);
if (key == null) {
return getSecureKey(subject).getBytes();
}
return key.getBytes();
}
@@ -161,7 +169,7 @@ public class SecureKeyResolver extends SigningKeyResolverAdapter
//~--- fields ---------------------------------------------------------------
/** secure randon */
private final SecureRandom random = new SecureRandom();
private final Random random;
/** configuration entry store */
private final ConfigurationEntryStore<SecureKey> store;

View File

@@ -1,5 +1,6 @@
package sonia.scm.web.security;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationToken;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -64,7 +65,13 @@ public class TokenRefreshFilter extends HttpFilter {
}
private void examineToken(HttpServletRequest request, HttpServletResponse response, BearerToken token) {
AccessToken accessToken = resolver.resolve(token);
AccessToken accessToken;
try {
accessToken = resolver.resolve(token);
} catch (AuthenticationException e) {
LOG.trace("could not resolve token", e);
return;
}
if (accessToken instanceof JwtAccessToken) {
refresher.refresh((JwtAccessToken) accessToken)
.ifPresent(jwtAccessToken -> refreshToken(request, response, jwtAccessToken));

View File

@@ -44,12 +44,16 @@ import org.mockito.junit.MockitoJUnitRunner;
import sonia.scm.store.ConfigurationEntryStore;
import sonia.scm.store.ConfigurationEntryStoreFactory;
import java.util.Random;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.in;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertSame;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.argThat;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
@@ -99,10 +103,11 @@ public class SecureKeyResolverTest
* Method description
*
*/
@Test(expected = IllegalStateException.class)
@Test
public void testResolveSigningKeyBytesWithoutKey()
{
resolver.resolveSigningKeyBytes(null, Jwts.claims().setSubject("test"));
byte[] bytes = resolver.resolveSigningKeyBytes(null, Jwts.claims().setSubject("test"));
assertThat(bytes[0]).isEqualTo((byte) 42);
}
/**
@@ -132,7 +137,9 @@ public class SecureKeyResolverTest
assertThat(storeParameters.getType()).isEqualTo(SecureKey.class);
return true;
}))).thenReturn(store);
resolver = new SecureKeyResolver(factory);
Random random = mock(Random.class);
doAnswer(invocation -> ((byte[]) invocation.getArguments()[0])[0] = 42).when(random).nextBytes(any());
resolver = new SecureKeyResolver(factory, random);
}
//~--- fields ---------------------------------------------------------------