Merge remote-tracking branch 'origin/master' into feat-settings-ui
# Conflicts: # docs/package.json # docs/pnpm-lock.yaml # internal/configuration/validator/identity_providers_test.go # web/package.json # web/pnpm-lock.yamlfeat-otp-verification
commit
7ef1ba23df
|
@ -15,7 +15,7 @@ RUN yarn global add pnpm && \
|
||||||
# =======================================
|
# =======================================
|
||||||
# ===== Build image for the backend =====
|
# ===== Build image for the backend =====
|
||||||
# =======================================
|
# =======================================
|
||||||
FROM golang:1.20.1-alpine AS builder-backend
|
FROM golang:1.20.2-alpine AS builder-backend
|
||||||
|
|
||||||
WORKDIR /go/src/app
|
WORKDIR /go/src/app
|
||||||
|
|
||||||
|
|
|
@ -13,7 +13,7 @@ RUN yarn install --frozen-lockfile && yarn build
|
||||||
# =======================================
|
# =======================================
|
||||||
# ===== Build image for the backend =====
|
# ===== Build image for the backend =====
|
||||||
# =======================================
|
# =======================================
|
||||||
FROM golang:1.20.1-alpine AS builder-backend
|
FROM golang:1.20.2-alpine AS builder-backend
|
||||||
|
|
||||||
WORKDIR /go/src/app
|
WORKDIR /go/src/app
|
||||||
|
|
||||||
|
|
|
@ -34,3 +34,20 @@ abide by:
|
||||||
- The available space is utilized efficiently in order to avoid scrolling where possible.
|
- The available space is utilized efficiently in order to avoid scrolling where possible.
|
||||||
- The user only has to scroll in one direction to view available information. This direction should always be
|
- The user only has to scroll in one direction to view available information. This direction should always be
|
||||||
vertically.
|
vertically.
|
||||||
|
|
||||||
|
Recommendations on resolutions which are common:
|
||||||
|
|
||||||
|
- Desktop/Laptop:
|
||||||
|
1. 1920x1080
|
||||||
|
2. 1366x768
|
||||||
|
3. 2560x1440
|
||||||
|
4. 1280x720
|
||||||
|
- Tablet Devices (With Touch and Landscape):
|
||||||
|
1. 768x1024
|
||||||
|
2. 810x1080
|
||||||
|
3. 800x1280
|
||||||
|
- Mobile Devices (With Touch and Landscape):
|
||||||
|
1. 360x800
|
||||||
|
2. 390x844
|
||||||
|
3. 414x896
|
||||||
|
4. 412x915
|
||||||
|
|
|
@ -3,8 +3,7 @@
|
||||||
"description": "Doks theme",
|
"description": "Doks theme",
|
||||||
"version": "0.5.0",
|
"version": "0.5.0",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=16.18.1",
|
"node": ">=16.18.1"
|
||||||
"pnpm": "7"
|
|
||||||
},
|
},
|
||||||
"browserslist": [
|
"browserslist": [
|
||||||
"defaults"
|
"defaults"
|
||||||
|
@ -39,8 +38,8 @@
|
||||||
"version": "auto-changelog -p && git add CHANGELOG.md"
|
"version": "auto-changelog -p && git add CHANGELOG.md"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/cli": "7.20.7",
|
"@babel/cli": "7.21.0",
|
||||||
"@babel/core": "7.20.12",
|
"@babel/core": "7.21.0",
|
||||||
"@babel/preset-env": "7.20.2",
|
"@babel/preset-env": "7.20.2",
|
||||||
"@fullhuman/postcss-purgecss": "5.0.0",
|
"@fullhuman/postcss-purgecss": "5.0.0",
|
||||||
"@hyas/images": "0.3.2",
|
"@hyas/images": "0.3.2",
|
||||||
|
@ -50,7 +49,7 @@
|
||||||
"bootstrap": "5.2.3",
|
"bootstrap": "5.2.3",
|
||||||
"bootstrap-icons": "1.10.3",
|
"bootstrap-icons": "1.10.3",
|
||||||
"clipboard": "2.0.11",
|
"clipboard": "2.0.11",
|
||||||
"eslint": "8.34.0",
|
"eslint": "8.35.0",
|
||||||
"exec-bin": "1.0.0",
|
"exec-bin": "1.0.0",
|
||||||
"flexsearch": "0.7.31",
|
"flexsearch": "0.7.31",
|
||||||
"highlight.js": "11.7.0",
|
"highlight.js": "11.7.0",
|
||||||
|
@ -65,10 +64,10 @@
|
||||||
"postcss-cli": "10.1.0",
|
"postcss-cli": "10.1.0",
|
||||||
"purgecss-whitelister": "2.4.0",
|
"purgecss-whitelister": "2.4.0",
|
||||||
"shx": "0.3.4",
|
"shx": "0.3.4",
|
||||||
"stylelint": "15.1.0",
|
"stylelint": "14.16.1",
|
||||||
"stylelint-config-standard-scss": "6.1.0"
|
"stylelint-config-standard-scss": "6.1.0"
|
||||||
},
|
},
|
||||||
"otherDependencies": {
|
"otherDependencies": {
|
||||||
"hugo": "0.110.0"
|
"hugo": "0.111.2"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -140,6 +140,20 @@ type PasswordDigest struct {
|
||||||
algorithm.Digest
|
algorithm.Digest
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// IsPlainText returns true if the underlying algorithm.Digest is a *plaintext.Digest.
|
||||||
|
func (d *PasswordDigest) IsPlainText() bool {
|
||||||
|
if d == nil || d.Digest == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
switch d.Digest.(type) {
|
||||||
|
case *plaintext.Digest:
|
||||||
|
return true
|
||||||
|
default:
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// NewX509CertificateChain creates a new *X509CertificateChain from a given string, parsing each PEM block one by one.
|
// NewX509CertificateChain creates a new *X509CertificateChain from a given string, parsing each PEM block one by one.
|
||||||
func NewX509CertificateChain(in string) (chain *X509CertificateChain, err error) {
|
func NewX509CertificateChain(in string) (chain *X509CertificateChain, err error) {
|
||||||
if in == "" {
|
if in == "" {
|
||||||
|
|
|
@ -160,6 +160,7 @@ const (
|
||||||
"an empty id"
|
"an empty id"
|
||||||
|
|
||||||
errFmtOIDCClientInvalidSecret = "identity_providers: oidc: client '%s': option 'secret' is required"
|
errFmtOIDCClientInvalidSecret = "identity_providers: oidc: client '%s': option 'secret' is required"
|
||||||
|
errFmtOIDCClientInvalidSecretPlainText = "identity_providers: oidc: client '%s': option 'secret' is plaintext but it should be a hashed value as plaintext values are deprecated and will be removed when oidc becomes stable"
|
||||||
errFmtOIDCClientPublicInvalidSecret = "identity_providers: oidc: client '%s': option 'secret' is " +
|
errFmtOIDCClientPublicInvalidSecret = "identity_providers: oidc: client '%s': option 'secret' is " +
|
||||||
"required to be empty when option 'public' is true"
|
"required to be empty when option 'public' is true"
|
||||||
errFmtOIDCClientRedirectURICantBeParsed = "identity_providers: oidc: client '%s': option 'redirect_uris' has an " +
|
errFmtOIDCClientRedirectURICantBeParsed = "identity_providers: oidc: client '%s': option 'redirect_uris' has an " +
|
||||||
|
|
|
@ -166,6 +166,8 @@ func validateOIDCClients(config *schema.OpenIDConnectConfiguration, val *schema.
|
||||||
} else {
|
} else {
|
||||||
if client.Secret == nil {
|
if client.Secret == nil {
|
||||||
val.Push(fmt.Errorf(errFmtOIDCClientInvalidSecret, client.ID))
|
val.Push(fmt.Errorf(errFmtOIDCClientInvalidSecret, client.ID))
|
||||||
|
} else if client.Secret.IsPlainText() {
|
||||||
|
val.PushWarning(fmt.Errorf(errFmtOIDCClientInvalidSecretPlainText, client.ID))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -179,8 +179,8 @@ func TestShouldRaiseErrorWhenOIDCServerClientBadValues(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Errors: []string{
|
Errors: []string{
|
||||||
fmt.Sprintf(errFmtOIDCClientInvalidSecret, ""),
|
"identity_providers: oidc: client '': option 'secret' is required",
|
||||||
errFmtOIDCClientsWithEmptyID,
|
"identity_providers: oidc: one or more clients have been configured with an empty id",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -195,7 +195,7 @@ func TestShouldRaiseErrorWhenOIDCServerClientBadValues(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Errors: []string{fmt.Sprintf(errFmtOIDCClientInvalidPolicy, "client-1", "a-policy")},
|
Errors: []string{"identity_providers: oidc: client 'client-1': option 'policy' must be 'one_factor' or 'two_factor' but it is configured as 'a-policy'"},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: "ClientIDDuplicated",
|
Name: "ClientIDDuplicated",
|
||||||
|
@ -427,7 +427,7 @@ func TestShouldRaiseErrorWhenOIDCClientConfiguredWithBadGrantTypes(t *testing.T)
|
||||||
Clients: []schema.OpenIDConnectClientConfiguration{
|
Clients: []schema.OpenIDConnectClientConfiguration{
|
||||||
{
|
{
|
||||||
ID: "good_id",
|
ID: "good_id",
|
||||||
Secret: MustDecodeSecret("$plaintext$good_secret"),
|
Secret: MustDecodeSecret(goodOpenIDConnectClientSecret),
|
||||||
Policy: "two_factor",
|
Policy: "two_factor",
|
||||||
GrantTypes: []string{"bad_grant_type"},
|
GrantTypes: []string{"bad_grant_type"},
|
||||||
RedirectURIs: []string{
|
RedirectURIs: []string{
|
||||||
|
@ -454,7 +454,7 @@ func TestShouldNotErrorOnCertificateValid(t *testing.T) {
|
||||||
Clients: []schema.OpenIDConnectClientConfiguration{
|
Clients: []schema.OpenIDConnectClientConfiguration{
|
||||||
{
|
{
|
||||||
ID: "good_id",
|
ID: "good_id",
|
||||||
Secret: MustDecodeSecret("$plaintext$good_secret"),
|
Secret: MustDecodeSecret(goodOpenIDConnectClientSecret),
|
||||||
Policy: "two_factor",
|
Policy: "two_factor",
|
||||||
RedirectURIs: []string{
|
RedirectURIs: []string{
|
||||||
"https://google.com/callback",
|
"https://google.com/callback",
|
||||||
|
@ -480,7 +480,7 @@ func TestShouldRaiseErrorOnCertificateNotValid(t *testing.T) {
|
||||||
Clients: []schema.OpenIDConnectClientConfiguration{
|
Clients: []schema.OpenIDConnectClientConfiguration{
|
||||||
{
|
{
|
||||||
ID: "good_id",
|
ID: "good_id",
|
||||||
Secret: MustDecodeSecret("$plaintext$good_secret"),
|
Secret: MustDecodeSecret(goodOpenIDConnectClientSecret),
|
||||||
Policy: "two_factor",
|
Policy: "two_factor",
|
||||||
RedirectURIs: []string{
|
RedirectURIs: []string{
|
||||||
"https://google.com/callback",
|
"https://google.com/callback",
|
||||||
|
@ -507,7 +507,7 @@ func TestShouldRaiseErrorOnKeySizeTooSmall(t *testing.T) {
|
||||||
Clients: []schema.OpenIDConnectClientConfiguration{
|
Clients: []schema.OpenIDConnectClientConfiguration{
|
||||||
{
|
{
|
||||||
ID: "good_id",
|
ID: "good_id",
|
||||||
Secret: MustDecodeSecret("$plaintext$good_secret"),
|
Secret: MustDecodeSecret(goodOpenIDConnectClientSecret),
|
||||||
Policy: "two_factor",
|
Policy: "two_factor",
|
||||||
RedirectURIs: []string{
|
RedirectURIs: []string{
|
||||||
"https://google.com/callback",
|
"https://google.com/callback",
|
||||||
|
@ -587,7 +587,7 @@ func TestValidateIdentityProvidersShouldRaiseWarningOnSecurityIssue(t *testing.T
|
||||||
Clients: []schema.OpenIDConnectClientConfiguration{
|
Clients: []schema.OpenIDConnectClientConfiguration{
|
||||||
{
|
{
|
||||||
ID: "good_id",
|
ID: "good_id",
|
||||||
Secret: MustDecodeSecret("$plaintext$good_secret"),
|
Secret: MustDecodeSecret(goodOpenIDConnectClientSecret),
|
||||||
Policy: "two_factor",
|
Policy: "two_factor",
|
||||||
RedirectURIs: []string{
|
RedirectURIs: []string{
|
||||||
"https://google.com/callback",
|
"https://google.com/callback",
|
||||||
|
@ -623,7 +623,7 @@ func TestValidateIdentityProvidersShouldRaiseErrorsOnInvalidClientTypes(t *testi
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
ID: "client-with-bad-redirect-uri",
|
ID: "client-with-bad-redirect-uri",
|
||||||
Secret: MustDecodeSecret("$plaintext$a-secret"),
|
Secret: MustDecodeSecret(goodOpenIDConnectClientSecret),
|
||||||
Public: false,
|
Public: false,
|
||||||
Policy: "two_factor",
|
Policy: "two_factor",
|
||||||
RedirectURIs: []string{
|
RedirectURIs: []string{
|
||||||
|
@ -702,6 +702,33 @@ func TestValidateIdentityProvidersShouldNotRaiseErrorsOnValidClientOptions(t *te
|
||||||
assert.Len(t, validator.Warnings(), 0)
|
assert.Len(t, validator.Warnings(), 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestValidateIdentityProvidersShouldRaiseWarningOnPlainTextClients(t *testing.T) {
|
||||||
|
validator := schema.NewStructValidator()
|
||||||
|
config := &schema.IdentityProvidersConfiguration{
|
||||||
|
OIDC: &schema.OpenIDConnectConfiguration{
|
||||||
|
HMACSecret: "hmac1",
|
||||||
|
IssuerPrivateKey: MustParseRSAPrivateKey(testKey1),
|
||||||
|
Clients: []schema.OpenIDConnectClientConfiguration{
|
||||||
|
{
|
||||||
|
ID: "client-with-invalid-secret_standard",
|
||||||
|
Secret: MustDecodeSecret("$plaintext$a-secret"),
|
||||||
|
Policy: "two_factor",
|
||||||
|
RedirectURIs: []string{
|
||||||
|
"https://localhost",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
ValidateIdentityProviders(config, validator)
|
||||||
|
|
||||||
|
assert.Len(t, validator.Errors(), 0)
|
||||||
|
require.Len(t, validator.Warnings(), 1)
|
||||||
|
|
||||||
|
assert.EqualError(t, validator.Warnings()[0], "identity_providers: oidc: client 'client-with-invalid-secret_standard': option 'secret' is plaintext but it should be a hashed value as plaintext values are deprecated and will be removed when oidc becomes stable")
|
||||||
|
}
|
||||||
|
|
||||||
func TestValidateIdentityProvidersShouldSetDefaultValues(t *testing.T) {
|
func TestValidateIdentityProvidersShouldSetDefaultValues(t *testing.T) {
|
||||||
timeDay := time.Hour * 24
|
timeDay := time.Hour * 24
|
||||||
|
|
||||||
|
@ -713,7 +740,7 @@ func TestValidateIdentityProvidersShouldSetDefaultValues(t *testing.T) {
|
||||||
Clients: []schema.OpenIDConnectClientConfiguration{
|
Clients: []schema.OpenIDConnectClientConfiguration{
|
||||||
{
|
{
|
||||||
ID: "a-client",
|
ID: "a-client",
|
||||||
Secret: MustDecodeSecret("$plaintext$a-client-secret"),
|
Secret: MustDecodeSecret(goodOpenIDConnectClientSecret),
|
||||||
RedirectURIs: []string{
|
RedirectURIs: []string{
|
||||||
"https://google.com",
|
"https://google.com",
|
||||||
},
|
},
|
||||||
|
@ -721,8 +748,8 @@ func TestValidateIdentityProvidersShouldSetDefaultValues(t *testing.T) {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
ID: "b-client",
|
ID: "b-client",
|
||||||
Description: "Normal DisplayName",
|
Description: "Normal Description",
|
||||||
Secret: MustDecodeSecret("$plaintext$b-client-secret"),
|
Secret: MustDecodeSecret(goodOpenIDConnectClientSecret),
|
||||||
Policy: policyOneFactor,
|
Policy: policyOneFactor,
|
||||||
UserinfoSigningAlgorithm: "RS256",
|
UserinfoSigningAlgorithm: "RS256",
|
||||||
RedirectURIs: []string{
|
RedirectURIs: []string{
|
||||||
|
@ -745,7 +772,7 @@ func TestValidateIdentityProvidersShouldSetDefaultValues(t *testing.T) {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
ID: "c-client",
|
ID: "c-client",
|
||||||
Secret: MustDecodeSecret("$plaintext$a-client-secret"),
|
Secret: MustDecodeSecret(goodOpenIDConnectClientSecret),
|
||||||
RedirectURIs: []string{
|
RedirectURIs: []string{
|
||||||
"https://google.com",
|
"https://google.com",
|
||||||
},
|
},
|
||||||
|
@ -753,7 +780,7 @@ func TestValidateIdentityProvidersShouldSetDefaultValues(t *testing.T) {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
ID: "d-client",
|
ID: "d-client",
|
||||||
Secret: MustDecodeSecret("$plaintext$a-client-secret"),
|
Secret: MustDecodeSecret(goodOpenIDConnectClientSecret),
|
||||||
RedirectURIs: []string{
|
RedirectURIs: []string{
|
||||||
"https://google.com",
|
"https://google.com",
|
||||||
},
|
},
|
||||||
|
@ -761,7 +788,7 @@ func TestValidateIdentityProvidersShouldSetDefaultValues(t *testing.T) {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
ID: "e-client",
|
ID: "e-client",
|
||||||
Secret: MustDecodeSecret("$plaintext$a-client-secret"),
|
Secret: MustDecodeSecret(goodOpenIDConnectClientSecret),
|
||||||
RedirectURIs: []string{
|
RedirectURIs: []string{
|
||||||
"https://google.com",
|
"https://google.com",
|
||||||
},
|
},
|
||||||
|
@ -1019,4 +1046,6 @@ AQmB98tdGLggbyXiODV2h+Rd37aFGb0QHzerIIsVNtMwlPCcp733D4kWJqTUYWZ+
|
||||||
KBL3XEahgs6Os5EYZ4aBAkEAjKE+2/nBYUdHVusjMXeNsE5rqwJND5zvYzmToG7+
|
KBL3XEahgs6Os5EYZ4aBAkEAjKE+2/nBYUdHVusjMXeNsE5rqwJND5zvYzmToG7+
|
||||||
xhv4RUAe4dHL4IDQoQRjhr3Nw+JYvtzBx0Iq/178xMnGKg==
|
xhv4RUAe4dHL4IDQoQRjhr3Nw+JYvtzBx0Iq/178xMnGKg==
|
||||||
-----END RSA PRIVATE KEY-----`
|
-----END RSA PRIVATE KEY-----`
|
||||||
|
|
||||||
|
goodOpenIDConnectClientSecret = "$pbkdf2-sha512$310000$c8p78n7pUMln0jzvd4aK4Q$JNRBzwAo0ek5qKn50cFzzvE9RXV88h1wJn5KGiHrD0YKtZaR/nCb2CJPOsKaPK0hjf.9yHxzQGZziziccp6Yng" //nolint:gosec
|
||||||
)
|
)
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
FROM golang:1.20.1-alpine
|
FROM golang:1.20.2-alpine
|
||||||
|
|
||||||
ARG USER_ID
|
ARG USER_ID
|
||||||
ARG GROUP_ID
|
ARG GROUP_ID
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
FROM haproxy:2.7.3-alpine
|
FROM haproxy:2.7.4-alpine
|
||||||
USER root
|
USER root
|
||||||
|
|
||||||
RUN \
|
RUN \
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
This email has been sent to you in order to validate your identity.
|
This email has been sent to you in order to validate your identity. Purpose: {{ .Title }}.
|
||||||
|
|
||||||
If you did not initiate the process your credentials might have been compromised and you should reset your password and contact an administrator.
|
If you did not initiate the process your credentials might have been compromised and you should reset your password and contact an administrator.
|
||||||
|
|
||||||
To setup your 2FA please visit the following URL: {{ .LinkURL }}
|
To confirm your identity please visit the following URL: {{ .LinkURL }}
|
||||||
|
|
||||||
This email was generated by a user with the IP {{ .RemoteIP }}.
|
This email was generated by a user with the IP {{ .RemoteIP }}.
|
||||||
|
|
||||||
|
|
|
@ -30,14 +30,14 @@
|
||||||
"@fortawesome/free-solid-svg-icons": "6.3.0",
|
"@fortawesome/free-solid-svg-icons": "6.3.0",
|
||||||
"@fortawesome/react-fontawesome": "0.2.0",
|
"@fortawesome/react-fontawesome": "0.2.0",
|
||||||
"@mui/icons-material": "5.11.11",
|
"@mui/icons-material": "5.11.11",
|
||||||
"@mui/material": "5.11.11",
|
"@mui/material": "5.11.12",
|
||||||
"@mui/styles": "5.11.11",
|
"@mui/styles": "5.11.12",
|
||||||
"@simplewebauthn/browser": "7.1.0",
|
"@simplewebauthn/browser": "7.1.0",
|
||||||
"@simplewebauthn/typescript-types": "7.0.0",
|
"@simplewebauthn/typescript-types": "7.0.0",
|
||||||
"axios": "1.3.4",
|
"axios": "1.3.4",
|
||||||
"broadcast-channel": "4.20.2",
|
"broadcast-channel": "4.20.2",
|
||||||
"classnames": "2.3.2",
|
"classnames": "2.3.2",
|
||||||
"i18next": "22.4.10",
|
"i18next": "22.4.11",
|
||||||
"i18next-browser-languagedetector": "7.0.1",
|
"i18next-browser-languagedetector": "7.0.1",
|
||||||
"i18next-http-backend": "2.1.1",
|
"i18next-http-backend": "2.1.1",
|
||||||
"qrcode.react": "3.1.0",
|
"qrcode.react": "3.1.0",
|
||||||
|
@ -45,7 +45,7 @@
|
||||||
"react-dom": "18.2.0",
|
"react-dom": "18.2.0",
|
||||||
"react-i18next": "12.2.0",
|
"react-i18next": "12.2.0",
|
||||||
"react-loading": "2.0.3",
|
"react-loading": "2.0.3",
|
||||||
"react-router-dom": "6.8.2",
|
"react-router-dom": "6.9.0",
|
||||||
"react18-input-otp": "1.1.2",
|
"react18-input-otp": "1.1.2",
|
||||||
"zxcvbn": "4.4.2"
|
"zxcvbn": "4.4.2"
|
||||||
},
|
},
|
||||||
|
@ -154,17 +154,17 @@
|
||||||
"@testing-library/jest-dom": "5.16.5",
|
"@testing-library/jest-dom": "5.16.5",
|
||||||
"@testing-library/react": "14.0.0",
|
"@testing-library/react": "14.0.0",
|
||||||
"@types/jest": "29.4.0",
|
"@types/jest": "29.4.0",
|
||||||
"@types/node": "18.14.6",
|
"@types/node": "18.15.0",
|
||||||
"@types/qrcode.react": "1.0.2",
|
"@types/qrcode.react": "1.0.2",
|
||||||
"@types/react": "18.0.28",
|
"@types/react": "18.0.28",
|
||||||
"@types/react-dom": "18.0.11",
|
"@types/react-dom": "18.0.11",
|
||||||
"@types/zxcvbn": "4.4.1",
|
"@types/zxcvbn": "4.4.1",
|
||||||
"@typescript-eslint/eslint-plugin": "5.54.0",
|
"@typescript-eslint/eslint-plugin": "5.54.1",
|
||||||
"@typescript-eslint/parser": "5.54.0",
|
"@typescript-eslint/parser": "5.54.1",
|
||||||
"@vitejs/plugin-react": "3.1.0",
|
"@vitejs/plugin-react": "3.1.0",
|
||||||
"esbuild": "0.17.11",
|
"esbuild": "0.17.11",
|
||||||
"esbuild-jest": "0.5.0",
|
"esbuild-jest": "0.5.0",
|
||||||
"eslint": "8.35.0",
|
"eslint": "8.36.0",
|
||||||
"eslint-config-prettier": "8.7.0",
|
"eslint-config-prettier": "8.7.0",
|
||||||
"eslint-config-react-app": "7.0.1",
|
"eslint-config-react-app": "7.0.1",
|
||||||
"eslint-formatter-rdjson": "1.0.5",
|
"eslint-formatter-rdjson": "1.0.5",
|
||||||
|
@ -175,8 +175,8 @@
|
||||||
"eslint-plugin-react": "7.32.2",
|
"eslint-plugin-react": "7.32.2",
|
||||||
"eslint-plugin-react-hooks": "4.6.0",
|
"eslint-plugin-react-hooks": "4.6.0",
|
||||||
"husky": "8.0.3",
|
"husky": "8.0.3",
|
||||||
"jest": "29.4.3",
|
"jest": "29.5.0",
|
||||||
"jest-environment-jsdom": "29.4.3",
|
"jest-environment-jsdom": "29.5.0",
|
||||||
"jest-transform-stub": "2.0.0",
|
"jest-transform-stub": "2.0.0",
|
||||||
"jest-watch-typeahead": "2.2.2",
|
"jest-watch-typeahead": "2.2.2",
|
||||||
"prettier": "2.8.4",
|
"prettier": "2.8.4",
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue