Skip to content
This repository has been archived by the owner on Apr 19, 2023. It is now read-only.

Commit

Permalink
✨ Add support for login links
Browse files Browse the repository at this point in the history
  • Loading branch information
AnandChowdhary committed Aug 4, 2020
1 parent 3923220 commit 47ceb5b
Show file tree
Hide file tree
Showing 5 changed files with 46 additions and 9 deletions.
1 change: 1 addition & 0 deletions src/_staart/interfaces/enum.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ export enum Templates {
UNAPPROVED_LOCATION = "unapproved-location",
CREDITS_NEW_USER = "credits-new-user",
CREDITS_INVITED_BY = "credits-invited-by",
LOGIN_LINK = "login-link",
}

export enum Tokens {
Expand Down
37 changes: 29 additions & 8 deletions src/_staart/rest/auth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,10 +54,10 @@ export const validateRefreshToken = async (token: string, locals: Locals) => {
};

export const invalidateRefreshToken = async (token: string, locals: Locals) => {
const data = await verifyToken<{ id: string }>(token, Tokens.REFRESH);
const data = await verifyToken<{ id: number }>(token, Tokens.REFRESH);
if (!data.id) throw new Error(USER_NOT_FOUND);
await prisma.sessions.deleteMany({
where: { token, userId: parseInt(data.id) },
where: { token, userId: data.id },
});
return;
};
Expand Down Expand Up @@ -85,7 +85,10 @@ export const login = async (
if (hasUserWithUnverifiedEmail) throw new Error("401/unverified-email");
throw new Error(USER_NOT_FOUND);
}
if (!user.password) throw new Error(MISSING_PASSWORD);
if (!user.password) {
await mail({ template: Templates.LOGIN_LINK, data: user, to: email });
return { success: true, message: "login-link-sent" };
}
const isPasswordCorrect = await compare(password, user.password);
if (isPasswordCorrect)
return getLoginResponse(user, EventType.AUTH_LOGIN, "local", locals);
Expand Down Expand Up @@ -210,10 +213,10 @@ export const sendNewPassword = async (userId: number, email: string) => {

export const verifyEmail = async (token: string, locals: Locals) => {
const emailId = (
await verifyToken<{ id: string }>(token, Tokens.EMAIL_VERIFY)
await verifyToken<{ id: number }>(token, Tokens.EMAIL_VERIFY)
).id;
const email = await prisma.emails.findOne({
where: { id: parseInt(emailId) },
where: { id: emailId },
});
if (!email) throw new Error(RESOURCE_NOT_FOUND);
trackEvent(
Expand All @@ -225,21 +228,39 @@ export const verifyEmail = async (token: string, locals: Locals) => {
locals
);
return prisma.emails.update({
where: { id: parseInt(emailId) },
where: { id: emailId },
data: { isVerified: true },
});
};

export const loginLink = async (token: string, locals: Locals) => {
const userId = (await verifyToken<{ id: number }>(token, Tokens.EMAIL_VERIFY))
.id;
const user = await prisma.users.findOne({
where: { id: userId },
});
if (!user) throw new Error(RESOURCE_NOT_FOUND);
trackEvent(
{
userId,
type: EventType.AUTH_LOGIN,
data: { id: userId },
},
locals
);
return postLoginTokens(user, locals);
};

export const updatePassword = async (
token: string,
password: string,
locals: Locals
) => {
const userId = (
await verifyToken<{ id: string }>(token, Tokens.PASSWORD_RESET)
await verifyToken<{ id: number }>(token, Tokens.PASSWORD_RESET)
).id;
await prisma.users.update({
where: { id: parseInt(userId) },
where: { id: userId },
data: { password: await hash(password, 8) },
});
await deleteItemFromCache(`cache_getUserById_${userId}`);
Expand Down
1 change: 0 additions & 1 deletion src/_staart/rest/group.ts
Original file line number Diff line number Diff line change
Expand Up @@ -646,7 +646,6 @@ export const inviteMemberToGroup = async (
const newAccount = await register(
{
name: newMemberName,
prefersEmail: {},
},
locals,
newMemberEmail,
Expand Down
9 changes: 9 additions & 0 deletions src/controllers/auth/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import {
updatePassword,
validateRefreshToken,
verifyEmail,
loginLink,
} from "../../_staart/rest/auth";
import { addInvitationCredits } from "../../_staart/rest/user";
import { twtToId } from "../../_staart/helpers/utils";
Expand Down Expand Up @@ -210,4 +211,12 @@ export class AuthController {
await verifyEmail(token, res.locals);
return respond(RESOURCE_SUCCESS);
}

@Post("login-link")
async postLoginLink(req: Request, res: Response) {
const token = req.body.token || req.params.token;
joiValidate({ token: Joi.string().required() }, { token });
await loginLink(token, res.locals);
return respond(RESOURCE_SUCCESS);
}
}
7 changes: 7 additions & 0 deletions src/templates/login-link.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# Your login link

Dear {{name}},

To log in to your account, click on the following link:

<a style="background: #3f51b5; padding: 1rem 2rem; font-size: 120%; color: #fff; display: inline-block; margin: 2rem auto; border-radius: 0.25rem" href="{{frontendUrl}}/auth/token?subject=login&token={{token}}">Login to your account</a>

0 comments on commit 47ceb5b

Please sign in to comment.