diff --git a/app/api/src/controllers/auth.controller.ts b/app/api/src/controllers/auth.controller.ts index 14d0e83d8..9d8225827 100644 --- a/app/api/src/controllers/auth.controller.ts +++ b/app/api/src/controllers/auth.controller.ts @@ -87,12 +87,18 @@ export const signup = catchAsync(async (req, res): Promise => { // delete the invited account await userService.deleteUserById(foundInvitedUser.user_id); + + // verify the user email + await userService.updateUserById(foundExistingUser.user_id, { + email_verified: true, + }); } else { // make the user as non-invited and login user = await userService.updateUserById(userId, { user_name: foundInvitedUser.user_name || 'anonymous', is_invited: false, wallet_address: hashedWalletAddress, + email_verified: true, }); } diff --git a/app/api/src/controllers/creation.controller.ts b/app/api/src/controllers/creation.controller.ts index a9f0b2d8d..35586808f 100644 --- a/app/api/src/controllers/creation.controller.ts +++ b/app/api/src/controllers/creation.controller.ts @@ -9,12 +9,14 @@ import * as litigationService from '../services/litigation.service'; import { getMaterialById, updateMaterialById } from '../services/material.service'; import { createRecognition } from '../services/recognition.service'; import { getTagById } from '../services/tag.service'; -import { IUserDoc } from '../services/user.service'; +import { getUserByCriteria, IUserDoc } from '../services/user.service'; import ApiError from '../utils/ApiError'; import catchAsync from '../utils/catchAsync'; +import { sendMail } from '../utils/email'; import { generateProofOfCreation } from '../utils/generateProofOfCreation'; import { getSupportedFileTypeFromLink } from '../utils/getSupportedFileTypeFromLink'; import { pinJSON, unpinData } from '../utils/ipfs'; +import { encode } from '../utils/jwt'; export const queryCreations = catchAsync(async (req, res): Promise => { // when req user is requesting their own creations (search_fields has author_id, and query matches auth user id) @@ -103,8 +105,24 @@ export const createCreation = catchAsync(async (req, res): Promise => { // get all materials // eslint-disable-next-line @typescript-eslint/return-await const materials = await Promise.all(req.body.materials.map(async (id: string) => await getMaterialById(id))); + await Promise.all( materials.map(async (m: any) => { + const foundAuthor = await getUserByCriteria('user_id', m.author_id, true); + + // send invitation emails to new authors + if (foundAuthor && foundAuthor.is_invited && foundAuthor.email_address) { + await sendMail({ + to: foundAuthor?.email_address as string, + subject: `Invitation to recognize authorship of "${m.material_title}"`, + message: `You were recognized as author of "${m.material_title}" by ${ + (req.user as IUserDoc)?.user_name + }. Please signup on ${config.web_client_base_url}/signup?token=${encode( + foundAuthor.user_id + )} to be recognized as the author.`, + }).catch(() => null); + } + // send recognition const recognition = await createRecognition({ recognition_for: m.author_id, @@ -205,6 +223,21 @@ export const updateCreationById = catchAsync(async (req, res): Promise => await Promise.all( materials.map(async (m: any) => { + const foundAuthor = await getUserByCriteria('user_id', m.author_id, true); + + // send invitation emails to new authors + if (foundAuthor && foundAuthor.is_invited && foundAuthor.email_address) { + await sendMail({ + to: foundAuthor?.email_address as string, + subject: `Invitation to recognize authorship of "${m.material_title}"`, + message: `You were recognized as author of "${m.material_title}" by ${ + (req.user as IUserDoc)?.user_name + }. Please signup on ${config.web_client_base_url}/signup?token=${encode( + foundAuthor.user_id + )} to be recognized as the author.`, + }).catch(() => null); + } + // send recognition const recognition = await createRecognition({ recognition_for: m.author_id, diff --git a/app/api/src/controllers/litigation.controller.ts b/app/api/src/controllers/litigation.controller.ts index a0999a5b9..857b0d2f5 100644 --- a/app/api/src/controllers/litigation.controller.ts +++ b/app/api/src/controllers/litigation.controller.ts @@ -53,7 +53,7 @@ export const createLitigation = catchAsync(async (req, res): Promise } // check if material can be claimed - if (material && !material?.is_claimable) { + if ((material && !material?.is_claimable) || isCAWPassed || (creation.is_draft && material)) { throw new ApiError(httpStatus.NOT_FOUND, 'material is not claimable'); } diff --git a/app/api/src/controllers/material.controller.ts b/app/api/src/controllers/material.controller.ts index a3c42f65f..1a2336ed8 100644 --- a/app/api/src/controllers/material.controller.ts +++ b/app/api/src/controllers/material.controller.ts @@ -1,11 +1,8 @@ -import config from '../config/config'; import * as materialService from '../services/material.service'; import { getRecognitionById } from '../services/recognition.service'; import { getUserByCriteria, IUserDoc } from '../services/user.service'; import catchAsync from '../utils/catchAsync'; -import { sendMail } from '../utils/email'; import { getSupportedFileTypeFromLink } from '../utils/getSupportedFileTypeFromLink'; -import { encode } from '../utils/jwt'; export const queryMaterials = catchAsync(async (req, res): Promise => { const creation = await materialService.queryMaterials(req.query as any); @@ -21,10 +18,9 @@ export const getMaterialById = catchAsync(async (req, res): Promise => { export const createMaterial = catchAsync(async (req, res): Promise => { // check if reference docs exist - let foundUser = null; if (req.body.recognition_id) await getRecognitionById(req.body.recognition_id as string); // verify recognition, will throw an error if recognition not found if (req.body.author_id && req.body.author_id !== (req.user as IUserDoc).user_id) { - foundUser = await getUserByCriteria('user_id', req.body.author_id as string, true); // verify author id (if present), will throw an error if not found + await getUserByCriteria('user_id', req.body.author_id as string, true); // verify author id (if present), will throw an error if not found } // get the material type from link @@ -37,19 +33,6 @@ export const createMaterial = catchAsync(async (req, res): Promise => { author_id: req.body.author_id || (req.user as IUserDoc).user_id, }); - // send email to the invited user if found - if (foundUser && foundUser.is_invited && foundUser.email_address) { - await sendMail({ - to: foundUser.email_address as string, - subject: `Invitation to recognize authorship of "${newMaterial.material_title}"`, - message: `You were recognized as author of "${newMaterial.material_title}" by ${ - (req.user as IUserDoc)?.user_name - }. Please signup on ${config.web_client_base_url}/signup?token=${encode( - foundUser.user_id - )} to be recognized as the author.`, - }).catch(() => null); - } - res.send(newMaterial); }); diff --git a/app/web-frontend/src/pages/Signup/index.jsx b/app/web-frontend/src/pages/Signup/index.jsx index 0f2cf4e6e..d23ec18f4 100644 --- a/app/web-frontend/src/pages/Signup/index.jsx +++ b/app/web-frontend/src/pages/Signup/index.jsx @@ -1,24 +1,46 @@ import LoginForm from 'components/LoginForm'; +import useAppKeys from 'hooks/useAppKeys'; +import { useEffect } from 'react'; import { useNavigate } from 'react-router-dom'; +import authUser from 'utils/helpers/authUser'; + +const handleLogout = () => { + authUser.removeJWTToken(); + authUser.removeUser(); +}; + +let isAppUpdated = false; function Signup() { const navigate = useNavigate(); + const { updateAppKey } = useAppKeys(); // get token from url const parameters = new URLSearchParams(window.location.search); const token = parameters.get('token'); + const handleLogin = () => { + navigate('/wallet'); + updateAppKey(); + }; + + useEffect(() => { + handleLogout(); + if (!isAppUpdated) { updateAppKey(); isAppUpdated = true; } + }, []); + return ( -

Signup with your cardano wallet. @@ -28,7 +50,7 @@ function Signup() { wallet address and you select the same wallet address for signup here we will merge your invited account into your existing account.

- navigate('/wallet')} /> +

); }