diff --git a/backend/src/api/auth/authSignUp.ts b/backend/src/api/auth/authSignUp.ts
index 67f261120b..51faac3a3d 100644
--- a/backend/src/api/auth/authSignUp.ts
+++ b/backend/src/api/auth/authSignUp.ts
@@ -1,6 +1,9 @@
import AuthService from '../../services/auth/authService'
export default async (req, res) => {
+ if (!req.body.acceptedTermsAndPrivacy) {
+ return res.status(422).send({ error: 'Please accept terms of service and privacy policy' })
+ }
const payload = await AuthService.signup(
req.body.email,
req.body.password,
@@ -8,8 +11,9 @@ export default async (req, res) => {
req.body.tenantId,
req.body.firstName,
req.body.lastName,
+ req.body.acceptedTermsAndPrivacy,
req,
)
- await req.responseHandler.success(req, res, payload)
+ return req.responseHandler.success(req, res, payload)
}
diff --git a/backend/src/database/migrations/U1689235178__addTermsAndPrivacyColumn.sql b/backend/src/database/migrations/U1689235178__addTermsAndPrivacyColumn.sql
new file mode 100644
index 0000000000..54d92a34c9
--- /dev/null
+++ b/backend/src/database/migrations/U1689235178__addTermsAndPrivacyColumn.sql
@@ -0,0 +1 @@
+ALTER TABLE public."users" DROP COLUMN "acceptedTermsAndPrivacy";
diff --git a/backend/src/database/migrations/V1689235178__addTermsAndPrivacyColumn.sql b/backend/src/database/migrations/V1689235178__addTermsAndPrivacyColumn.sql
new file mode 100644
index 0000000000..fdd4b789c6
--- /dev/null
+++ b/backend/src/database/migrations/V1689235178__addTermsAndPrivacyColumn.sql
@@ -0,0 +1 @@
+ALTER TABLE public."users" ADD COLUMN "acceptedTermsAndPrivacy" BOOLEAN DEFAULT true;
\ No newline at end of file
diff --git a/backend/src/database/models/user.ts b/backend/src/database/models/user.ts
index a64482691b..2deb3ab223 100644
--- a/backend/src/database/models/user.ts
+++ b/backend/src/database/models/user.ts
@@ -95,6 +95,10 @@ export default (sequelize, DataTypes) => {
jwtTokenInvalidBefore: {
type: DataTypes.DATE,
},
+ acceptedTermsAndPrivacy: {
+ type: DataTypes.BOOLEAN,
+ defaultValue: true,
+ },
importHash: {
type: DataTypes.STRING(255),
allowNull: true,
diff --git a/backend/src/database/repositories/userRepository.ts b/backend/src/database/repositories/userRepository.ts
index a121c31024..9453f51b27 100644
--- a/backend/src/database/repositories/userRepository.ts
+++ b/backend/src/database/repositories/userRepository.ts
@@ -104,6 +104,7 @@ export default class UserRepository {
lastName: data.lastName,
fullName: data.fullName,
password: data.password,
+ acceptedTermsAndPrivacy: data.acceptedTermsAndPrivacy,
},
{ transaction },
)
@@ -142,6 +143,7 @@ export default class UserRepository {
firstName: data.firstName || null,
lastName: data.lastName || null,
phoneNumber: data.phoneNumber || null,
+ acceptedTermsAndPrivacy: data.acceptedTermsAndPrivacy || false,
updatedById: currentUser.id,
},
{ transaction },
@@ -662,6 +664,7 @@ export default class UserRepository {
firstName,
lastName,
fullName,
+ acceptedTermsAndPrivacy: false,
}
const transaction = SequelizeRepository.getTransaction(options)
diff --git a/backend/src/services/auth/authService.ts b/backend/src/services/auth/authService.ts
index 20e142ccc0..e72f19acac 100644
--- a/backend/src/services/auth/authService.ts
+++ b/backend/src/services/auth/authService.ts
@@ -28,6 +28,7 @@ class AuthService {
tenantId,
firstName,
lastName,
+ acceptedTermsAndPrivacy,
options: any = {},
) {
const transaction = await SequelizeRepository.createTransaction(options)
@@ -126,6 +127,7 @@ class AuthService {
fullName,
password: hashedPassword,
email,
+ acceptedTermsAndPrivacy,
},
{
...options,
diff --git a/frontend/src/i18n/en.js b/frontend/src/i18n/en.js
index 8786715187..3f16a20b05 100644
--- a/frontend/src/i18n/en.js
+++ b/frontend/src/i18n/en.js
@@ -570,6 +570,7 @@ const en = {
fullName: 'Name',
firstName: 'First name',
lastName: 'Last name',
+ acceptedTermsAndPrivacy: 'Terms and privacy',
status: 'Status',
phoneNumber: 'Phone Number',
role: 'Role',
diff --git a/frontend/src/middleware/auth/auth-guard.js b/frontend/src/middleware/auth/auth-guard.js
index 40182b11d6..0fe7a4fc46 100644
--- a/frontend/src/middleware/auth/auth-guard.js
+++ b/frontend/src/middleware/auth/auth-guard.js
@@ -28,9 +28,11 @@ export default async function ({ to, store, router }) {
}
await store.dispatch('auth/doWaitUntilInit');
+ const currentUser = store.getters['auth/currentUser'];
+
const permissionChecker = new PermissionChecker(
store.getters['auth/currentTenant'],
- store.getters['auth/currentUser'],
+ currentUser,
);
if (!permissionChecker.isAuthenticated) {
@@ -57,6 +59,11 @@ export default async function ({ to, store, router }) {
router.push('/403');
return;
}
+ console.log(currentUser);
+ if (!currentUser.acceptedTermsAndPrivacy) {
+ router.push({ path: '/auth/terms-and-privacy' });
+ return;
+ }
if (
['multi', 'multi-with-subdomain'].includes(
diff --git a/frontend/src/modules/auth/auth-routes.js b/frontend/src/modules/auth/auth-routes.js
index 8429282842..050a7c7778 100644
--- a/frontend/src/modules/auth/auth-routes.js
+++ b/frontend/src/modules/auth/auth-routes.js
@@ -13,6 +13,7 @@ const ProfileFormPage = () => import('@/modules/auth/pages/profile-form-page.vue
const PasswordResetPage = () => import('@/modules/auth/pages/password-reset-page.vue');
const VerifyEmailPage = () => import('@/modules/auth/pages/verify-email-page.vue');
const InvitationPage = () => import('@/modules/auth/pages/invitation-page.vue');
+const TermsAndPrivacyPage = () => import('@/modules/auth/pages/terms-and-privacy.vue');
const EmptyPermissionsPage = () => import('@/modules/auth/pages/empty-permissions-page.vue');
export default [
@@ -69,6 +70,12 @@ export default [
component: InvitationPage,
meta: { title: 'Invitation' },
},
+ {
+ name: 'terms-and-privacy',
+ path: 'terms-and-privacy',
+ component: TermsAndPrivacyPage,
+ meta: { title: 'Terms of service and privacy policy' },
+ },
],
},
{
diff --git a/frontend/src/modules/auth/auth-service.js b/frontend/src/modules/auth/auth-service.js
index df63a5cc90..ad32d53c0a 100644
--- a/frontend/src/modules/auth/auth-service.js
+++ b/frontend/src/modules/auth/auth-service.js
@@ -15,20 +15,10 @@ export class AuthService {
.then((response) => response.data);
}
- static sendPasswordResetEmail(email) {
- return authAxios
- .post('/auth/send-password-reset-email', {
- email,
- tenantId: tenantSubdomain.isSubdomain
- ? AuthCurrentTenant.get()
- : undefined,
- })
- .then((response) => response.data);
- }
-
static registerWithEmailAndPassword(
email,
password,
+ acceptedTermsAndPrivacy,
data = {},
) {
const invitationToken = AuthInvitationToken.get();
@@ -39,6 +29,7 @@ export class AuthService {
password,
invitationToken,
...data,
+ acceptedTermsAndPrivacy,
tenantId: tenantSubdomain.isSubdomain
? AuthCurrentTenant.get()
: undefined,
@@ -50,6 +41,17 @@ export class AuthService {
});
}
+ static sendPasswordResetEmail(email) {
+ return authAxios
+ .post('/auth/send-password-reset-email', {
+ email,
+ tenantId: tenantSubdomain.isSubdomain
+ ? AuthCurrentTenant.get()
+ : undefined,
+ })
+ .then((response) => response.data);
+ }
+
static signinWithEmailAndPassword(email, password) {
const invitationToken = AuthInvitationToken.get();
diff --git a/frontend/src/modules/auth/pages/signup-page.vue b/frontend/src/modules/auth/pages/signup-page.vue
index c02da342ef..eca7056e09 100644
--- a/frontend/src/modules/auth/pages/signup-page.vue
+++ b/frontend/src/modules/auth/pages/signup-page.vue
@@ -174,6 +174,23 @@
+