-
Notifications
You must be signed in to change notification settings - Fork 190
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
5 changed files
with
510 additions
and
450 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,200 @@ | ||
import Session from "../session"; | ||
import logger from "../utils/logger"; | ||
import fail from "../utils/fail"; | ||
import { | ||
queryP as pgQueryP, | ||
queryP_readOnly as pgQueryP_readOnly, | ||
} from "../db/pg-query"; | ||
import { generateHashedPassword } from "../auth/password"; | ||
import Config from "../config"; | ||
import cookies from "../utils/cookies"; | ||
import User from "../user"; | ||
import emailSenders from "../email/senders"; | ||
|
||
const sendTextEmail = emailSenders.sendTextEmail; | ||
|
||
const getUidForPwResetToken = Session.getUidForPwResetToken; | ||
const clearPwResetToken = Session.clearPwResetToken; | ||
const getServerNameWithProtocol = Config.getServerNameWithProtocol; | ||
const setupPwReset = Session.setupPwReset; | ||
const polisFromAddress = Config.polisFromAddress; | ||
const getUserInfoForUid = User.getUserInfoForUid; | ||
|
||
function sendPasswordResetEmail( | ||
uid?: any, | ||
pwresettoken?: any, | ||
serverName?: any, | ||
callback?: { (err: any): void; (arg0?: string): void } | ||
) { | ||
getUserInfoForUid( | ||
uid, | ||
// Argument of type '(err: any, userInfo: { hname: any; email: any; }) => void' is not assignable to parameter of type '(arg0: null, arg1?: undefined) => void'. | ||
// Types of parameters 'userInfo' and 'arg1' are incompatible. | ||
// Type 'undefined' is not assignable to type '{ hname: any; email: any; }'.ts(2345) | ||
// @ts-ignore | ||
function (err: any, userInfo: { hname: any; email: any }) { | ||
if (err) { | ||
return callback?.(err); | ||
} | ||
if (!userInfo) { | ||
return callback?.("missing user info"); | ||
} | ||
let body = `Hi ${userInfo.hname}, | ||
We have just received a password reset request for ${userInfo.email} | ||
To reset your password, visit this page: | ||
${serverName}/pwreset/${pwresettoken} | ||
"Thank you for using Polis`; | ||
|
||
sendTextEmail( | ||
polisFromAddress, | ||
userInfo.email, | ||
"Polis Password Reset", | ||
body | ||
) | ||
.then(function () { | ||
callback?.(); | ||
}) | ||
.catch(function (err: any) { | ||
logger.error("polis_err_failed_to_email_password_reset_code", err); | ||
callback?.(err); | ||
}); | ||
} | ||
); | ||
} | ||
|
||
function getUidByEmail(email: string) { | ||
email = email.toLowerCase(); | ||
return pgQueryP_readOnly( | ||
"SELECT uid FROM users where LOWER(email) = ($1);", | ||
[email] | ||
// Argument of type '(rows: string | any[]) => any' is not assignable to parameter of type '(value: unknown) => any'. | ||
// Types of parameters 'rows' and 'value' are incompatible. | ||
// Type 'unknown' is not assignable to type 'string | any[]'. | ||
// Type 'unknown' is not assignable to type 'any[]'.ts(2345) | ||
// @ts-ignore | ||
).then(function (rows: string | any[]) { | ||
if (!rows || !rows.length) { | ||
throw new Error("polis_err_no_user_matching_email"); | ||
} | ||
return rows[0].uid; | ||
}); | ||
} | ||
|
||
function handle_POST_auth_password( | ||
req: { p: { pwresettoken: any; newPassword: any } }, | ||
res: { | ||
status: ( | ||
arg0: number | ||
) => { | ||
(): any; | ||
new (): any; | ||
json: { (arg0: string): void; new (): any }; | ||
}; | ||
} | ||
) { | ||
let pwresettoken = req.p.pwresettoken; | ||
let newPassword = req.p.newPassword; | ||
|
||
getUidForPwResetToken( | ||
pwresettoken, | ||
// Argument of type '(err: any, userParams: { uid?: any; }) => void' is not assignable to parameter of type '(arg0: number | null, arg1?: { uid: any; } | undefined) => void'. | ||
// Types of parameters 'userParams' and 'arg1' are incompatible. | ||
// Type '{ uid: any; } | undefined' is not assignable to type '{ uid?: any; }'. | ||
// Type 'undefined' is not assignable to type '{ uid?: any; }'.ts(2345) | ||
// @ts-ignore | ||
function (err: any, userParams: { uid?: any }) { | ||
if (err) { | ||
fail( | ||
res, | ||
500, | ||
"Password Reset failed. Couldn't find matching pwresettoken.", | ||
err | ||
); | ||
return; | ||
} | ||
let uid = Number(userParams.uid); | ||
generateHashedPassword( | ||
newPassword, | ||
function (err: any, hashedPassword: any) { | ||
return pgQueryP( | ||
"insert into jianiuevyew (uid, pwhash) values " + | ||
"($1, $2) on conflict (uid) " + | ||
"do update set pwhash = excluded.pwhash;", | ||
[uid, hashedPassword] | ||
).then( | ||
(rows: any) => { | ||
res.status(200).json("Password reset successful."); | ||
clearPwResetToken(pwresettoken, function (err: any) { | ||
if (err) { | ||
logger.error("polis_err_auth_pwresettoken_clear_fail", err); | ||
} | ||
}); | ||
}, | ||
(err: any) => { | ||
fail(res, 500, "Couldn't reset password.", err); | ||
} | ||
); | ||
} | ||
); | ||
} | ||
); | ||
} | ||
|
||
function handle_POST_auth_pwresettoken( | ||
req: { p: { email: any } }, | ||
res: { | ||
status: ( | ||
arg0: number | ||
) => { | ||
(): any; | ||
new (): any; | ||
json: { (arg0: string): void; new (): any }; | ||
}; | ||
} | ||
) { | ||
let email = req.p.email; | ||
|
||
let server = getServerNameWithProtocol(req); | ||
|
||
// let's clear the cookies here, in case something is borked. | ||
cookies.clearCookies(req, res); | ||
|
||
function finish() { | ||
res.status(200).json("Password reset email sent, please check your email."); | ||
} | ||
|
||
getUidByEmail(email).then( | ||
function (uid?: any) { | ||
setupPwReset(uid, function (err: any, pwresettoken: any) { | ||
sendPasswordResetEmail(uid, pwresettoken, server, function (err: any) { | ||
if (err) { | ||
fail(res, 500, "Error: Couldn't send password reset email.", err); | ||
return; | ||
} | ||
finish(); | ||
}); | ||
}); | ||
}, | ||
function () { | ||
sendPasswordResetEmailFailure(email, server); | ||
finish(); | ||
} | ||
); | ||
} | ||
|
||
function sendPasswordResetEmailFailure(email: any, server: any) { | ||
let body = `We were unable to find a pol.is account registered with the email address: ${email} | ||
You may have used another email address to create your account. | ||
If you need to create a new account, you can do that here ${server}/home | ||
Feel free to reply to this email if you need help.`; | ||
|
||
return sendTextEmail(polisFromAddress, email, "Password Reset Failed", body); | ||
} | ||
|
||
export { handle_POST_auth_password, handle_POST_auth_pwresettoken }; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,144 @@ | ||
import _ from "underscore"; | ||
import { | ||
query as pgQuery, | ||
query_readOnly as pgQuery_readOnly, | ||
queryP_readOnly as pgQueryP_readOnly, | ||
} from "../db/pg-query"; | ||
import { isDuplicateKey } from "../utils/common"; | ||
import logger from "../utils/logger"; | ||
import Conversation from "../conversation"; | ||
import SQL from "../db/sql"; | ||
|
||
const isXidWhitelisted = Conversation.isXidWhitelisted; | ||
const sql_votes_latest_unique = SQL.sql_votes_latest_unique; | ||
|
||
function doVotesPost( | ||
uid?: any, | ||
pid?: any, | ||
conv?: { zid: any }, | ||
tid?: any, | ||
voteType?: any, | ||
weight?: number, | ||
high_priority?: boolean | ||
) { | ||
let zid = conv?.zid; | ||
weight = weight || 0; | ||
let weight_x_32767 = Math.trunc(weight * 32767); // weight is stored as a SMALLINT, so convert from a [-1,1] float to [-32767,32767] int | ||
return new Promise(function ( | ||
resolve: (arg0: { conv: any; vote: any }) => void, | ||
reject: (arg0: string) => void | ||
) { | ||
let query = | ||
"INSERT INTO votes (pid, zid, tid, vote, weight_x_32767, high_priority, created) VALUES ($1, $2, $3, $4, $5, $6, default) RETURNING *;"; | ||
let params = [pid, zid, tid, voteType, weight_x_32767, high_priority]; | ||
pgQuery(query, params, function (err: any, result: { rows: any[] }) { | ||
if (err) { | ||
if (isDuplicateKey(err)) { | ||
reject("polis_err_vote_duplicate"); | ||
} else { | ||
logger.error("polis_err_vote_other", err); | ||
reject("polis_err_vote_other"); | ||
} | ||
return; | ||
} | ||
|
||
const vote = result.rows[0]; | ||
|
||
resolve({ | ||
conv: conv, | ||
vote: vote, | ||
}); | ||
}); | ||
}); | ||
} | ||
|
||
function votesPost( | ||
uid?: any, | ||
pid?: any, | ||
zid?: any, | ||
tid?: any, | ||
xid?: any, | ||
voteType?: any, | ||
weight?: number, | ||
high_priority?: boolean | ||
) { | ||
return ( | ||
pgQueryP_readOnly("select * from conversations where zid = ($1);", [zid]) | ||
// Argument of type '(rows: string | any[]) => any' is not assignable to parameter of type '(value: unknown) => any'. | ||
// Types of parameters 'rows' and 'value' are incompatible. | ||
// Type 'unknown' is not assignable to type 'string | any[]'. | ||
// Type 'unknown' is not assignable to type 'any[]'.ts(2345) | ||
// @ts-ignore | ||
.then(function (rows: string | any[]) { | ||
if (!rows || !rows.length) { | ||
throw "polis_err_unknown_conversation"; | ||
} | ||
const conv = rows[0]; | ||
if (!conv.is_active) { | ||
throw "polis_err_conversation_is_closed"; | ||
} | ||
if (conv.use_xid_whitelist) { | ||
return isXidWhitelisted(conv.owner, xid).then( | ||
(is_whitelisted: boolean) => { | ||
if (is_whitelisted) { | ||
return conv; | ||
} else { | ||
throw "polis_err_xid_not_whitelisted"; | ||
} | ||
} | ||
); | ||
} | ||
return conv; | ||
}) | ||
.then(function (conv: any) { | ||
return doVotesPost( | ||
uid, | ||
pid, | ||
conv, | ||
tid, | ||
voteType, | ||
weight, | ||
high_priority | ||
); | ||
}) | ||
); | ||
} | ||
|
||
function getVotesForSingleParticipant(p: { pid: any }) { | ||
if (_.isUndefined(p.pid)) { | ||
return Promise.resolve([]); | ||
} | ||
return votesGet(p); | ||
} | ||
|
||
function votesGet(p: { zid?: any; pid?: any; tid?: any }) { | ||
// 'new' expression, whose target lacks a construct signature, implicitly has an 'any' type.ts(7009) | ||
// @ts-ignore | ||
return new MPromise( | ||
"votesGet", | ||
function (resolve: (arg0: any) => void, reject: (arg0: any) => void) { | ||
let q = sql_votes_latest_unique | ||
.select(sql_votes_latest_unique.star()) | ||
.where(sql_votes_latest_unique.zid.equals(p.zid)); | ||
|
||
if (!_.isUndefined(p.pid)) { | ||
q = q.where(sql_votes_latest_unique.pid.equals(p.pid)); | ||
} | ||
if (!_.isUndefined(p.tid)) { | ||
q = q.where(sql_votes_latest_unique.tid.equals(p.tid)); | ||
} | ||
pgQuery_readOnly( | ||
q.toString(), | ||
function (err: any, results: { rows: any }) { | ||
if (err) { | ||
reject(err); | ||
} else { | ||
resolve(results.rows); | ||
} | ||
} | ||
); | ||
} | ||
); | ||
} | ||
|
||
export { votesGet, getVotesForSingleParticipant, votesPost, doVotesPost }; |
Oops, something went wrong.