Skip to content

Commit 6ae836e

Browse files
gaspergromJoan Reyero
andauthored
Fix signin regex validation (#1850)
Co-authored-by: Joan Reyero <joan@crowd.dev>
1 parent 326093a commit 6ae836e

17 files changed

Lines changed: 117 additions & 11 deletions

File tree

backend/src/api/tenant/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ export default (app) => {
1515
app.get(`/tenant`, safeWrap(require('./tenantList').default))
1616
app.get(`/tenant/url`, safeWrap(require('./tenantFind').default))
1717
app.get(`/tenant/:id`, safeWrap(require('./tenantFind').default))
18+
app.get(`/tenant/:id/name`, safeWrap(require('./tenantFindName').default))
1819
app.get(`/tenant/:tenantId/membersToMerge`, safeWrap(require('./tenantMembersToMerge').default))
1920
app.get(
2021
`/tenant/:tenantId/organizationsToMerge`,

backend/src/api/tenant/tenantFind.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
11
import identifyTenant from '../../segment/identifyTenant'
22
import TenantService from '../../services/tenantService'
33
import Error404 from '../../errors/Error404'
4+
import PermissionChecker from '../../services/user/permissionChecker'
5+
import Permissions from '../../security/permissions'
46

57
export default async (req, res) => {
8+
req.currentTenant = { id: req.params.id }
9+
new PermissionChecker(req).validateHas(Permissions.values.memberRead)
610
let payload
7-
811
if (req.params.id) {
912
payload = await new TenantService(req).findById(req.params.id)
1013
} else {
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import identifyTenant from '../../segment/identifyTenant'
2+
import TenantService from '../../services/tenantService'
3+
import Error404 from '../../errors/Error404'
4+
5+
export default async (req, res) => {
6+
// This endpoint is unauthenticated on purpose, but public reprots.
7+
const payload = await new TenantService(req).findById(req.params.id)
8+
9+
if (payload) {
10+
if (req.currentUser) {
11+
identifyTenant({ ...req, currentTenant: payload })
12+
}
13+
14+
const payloadOut = {
15+
name: payload.name,
16+
id: payload.id,
17+
}
18+
19+
await req.responseHandler.success(req, res, payloadOut)
20+
} else {
21+
throw new Error404()
22+
}
23+
}

backend/src/database/repositories/userRepository.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -547,12 +547,22 @@ export default class UserRepository {
547547
status: 'active',
548548
},
549549
})
550+
550551
record = {
551552
...record,
552553
...record.json,
553554
}
554555
delete record.json
555556

557+
// Remove sensitive fields
558+
delete record.password
559+
delete record.emailVerificationToken
560+
delete record.emailVerificationTokenExpiresAt
561+
delete record.providerId
562+
delete record.passwordResetToken
563+
delete record.passwordResetTokenExpiresAt
564+
delete record.jwtTokenInvalidBefore
565+
556566
if (!record) {
557567
throw new Error404()
558568
}

backend/src/i18n/en.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,8 @@ const en = {
4545
invalidToken: 'Invalid or expired password reset link',
4646
error: `Invalid email`,
4747
},
48+
passwordInvalid:
49+
'Passwords must have at least one letter, one number, one symbol, and be at least 8 characters long.',
4850
emailAddressVerificationEmail: {
4951
invalidToken: 'Invalid or expired email verification link.',
5052
error: `Email not recognized.`,

backend/src/security/permissions.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ class Permissions {
9999
},
100100
userRead: {
101101
id: 'userRead',
102-
allowedRoles: [roles.admin, roles.readonly],
102+
allowedRoles: [roles.admin],
103103
allowedPlans: [
104104
plans.essential,
105105
plans.growth,
@@ -110,7 +110,7 @@ class Permissions {
110110
},
111111
userAutocomplete: {
112112
id: 'userAutocomplete',
113-
allowedRoles: [roles.admin, roles.readonly],
113+
allowedRoles: [roles.admin],
114114
allowedPlans: [
115115
plans.essential,
116116
plans.growth,

backend/src/services/auth/authService.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,12 @@ class AuthService {
3838

3939
const existingUser = await UserRepository.findByEmail(email, options)
4040

41+
const passwordRegex = /^(?=.*[A-Za-z])(?=.*\d)(?=.*[@$!%*#?&])[A-Za-z\d@$!%*#?&]{8,}$/
42+
43+
if (!passwordRegex.test(password)) {
44+
throw new Error400(options.language, 'auth.passwordInvalid')
45+
}
46+
4147
// Generates a hashed password to hide the original one.
4248
const hashedPassword = await bcrypt.hash(password, BCRYPT_SALT_ROUNDS)
4349

frontend/src/i18n/en.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -813,7 +813,7 @@ const en = {
813813
/* eslint-disable */
814814
validation: {
815815
mixed: {
816-
default: 'path} is invalid',
816+
default: '{path} is invalid',
817817
required: 'This field is required',
818818
oneOf:
819819
'{path} must be one of the following values: ${values}',

frontend/src/modules/auth/pages/signin-page.vue

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,11 @@
7272
class="h-4 flex items-center ri-error-warning-line text-base text-red-500"
7373
/>
7474
<span
75+
v-if="error === 'Password is invalid'"
76+
class="pl-1 text-2xs text-red-500 leading-4.5"
77+
>Passwords must have at least one letter, one number, one symbol, and be at least 8 characters long.</span>
78+
<span
79+
v-else
7580
class="pl-1 text-2xs text-red-500 leading-4.5"
7681
>{{ error }}</span>
7782
</div>
@@ -166,7 +171,7 @@ export default {
166171
return {
167172
rules: {
168173
email: fields.email.forFormRules(),
169-
password: fields.password.forFormRules(),
174+
password: fields.passwordSignin.forFormRules(),
170175
rememberMe: fields.rememberMe.forFormRules(),
171176
},
172177
model: {

frontend/src/modules/auth/pages/signup-page.vue

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,11 @@
129129
class="h-4 flex items-center ri-error-warning-line text-base text-red-500"
130130
/>
131131
<span
132+
v-if="error === 'Password is invalid'"
133+
class="pl-1 text-2xs text-red-500 leading-4.5"
134+
>Passwords must have at least one letter, one number, one symbol, and be at least 8 characters long.</span>
135+
<span
136+
v-else
132137
class="pl-1 text-2xs text-red-500 leading-4.5"
133138
>{{ error }}</span>
134139
</div>

0 commit comments

Comments
 (0)