aboutsummaryrefslogtreecommitdiffstats
path: root/routes
diff options
context:
space:
mode:
authorAdam Soltys <[email protected]>2020-07-29 16:40:30 -0700
committerAdam Soltys <[email protected]>2020-07-29 16:40:30 -0700
commit99d71f034cfb7c1675263539fa6aecb17429d134 (patch)
tree6d29806937436fde454f357a8dd5f7a30fa6b8bd /routes
parentffee4c7051982f3677d6717d24e7b357a89802eb (diff)
downloadcoinos-server-99d71f034cfb7c1675263539fa6aecb17429d134.tar.gz
coinos-server-99d71f034cfb7c1675263539fa6aecb17429d134.zip
redeem codes
Diffstat (limited to 'routes')
-rw-r--r--routes/payments.js34
-rw-r--r--routes/send.js165
-rw-r--r--routes/swaps.js43
-rw-r--r--routes/users.js654
4 files changed, 512 insertions, 384 deletions
diff --git a/routes/payments.js b/routes/payments.js
index 20a56baf..0a1ff27e 100644
--- a/routes/payments.js
+++ b/routes/payments.js
@@ -5,7 +5,7 @@ const { join } = require("path");
const fs = require("fs");
const read = require("../lib/read");
-(async () => {
+(ah(async () => {
seen = [];
addresses = {};
issuances = {};
@@ -121,7 +121,7 @@ const read = require("../lib/read");
app.get(
"/payments",
auth,
- ah(async (req, res, next) => {
+ ah(async (req, res) => {
let payments = await req.user.getPayments({
where: {
account_id: req.user.account_id,
@@ -136,4 +136,32 @@ const read = require("../lib/read");
res.send(payments);
})
);
-})();
+
+ app.get(
+ "/payment/:redeemcode",
+ ah(async (req, res) => {
+ try {
+ const { redeemcode } = req.params;
+ l.info("getting payment", redeemcode);
+ let payment = await db.Payment.findOne({
+ where: {
+ redeemcode,
+ },
+ include: {
+ model: db.Account,
+ as: "account",
+ },
+ });
+
+ l.info("oyyy");
+ if (!payment) fail("invalid code");
+
+ l.info("got payment", payment);
+
+ res.send(payment);
+ } catch(e) {
+ res.status(500).send(e.message);
+ }
+ })
+ );
+}))();
diff --git a/routes/send.js b/routes/send.js
index 00943d29..8ffff4dd 100644
--- a/routes/send.js
+++ b/routes/send.js
@@ -1,4 +1,5 @@
const axios = require("axios");
+const uuidv4 = require("uuid/v4");
module.exports = ah(async (req, res, next) => {
let { amount, asset, memo, username } = req.body;
@@ -9,14 +10,14 @@ module.exports = ah(async (req, res, next) => {
return res.status(500).send("Amount must be greater than zero");
try {
- await db.transaction(async transaction => {
+ await db.transaction(async (transaction) => {
let account = await db.Account.findOne({
where: {
user_id: user.id,
- asset
+ asset,
},
lock: transaction.LOCK.UPDATE,
- transaction
+ transaction,
});
if (account.balance < amount) {
@@ -28,20 +29,24 @@ module.exports = ah(async (req, res, next) => {
account.balance -= amount;
await account.save({ transaction });
- let payment = await db.Payment.create(
- {
- amount: -amount,
- account_id: account.id,
- memo,
- user_id: user.id,
- rate: app.get("rates")[user.currency],
- currency: user.currency,
- confirmed: true,
- hash: "Internal Transfer",
- network: "COINOS"
- },
- { transaction }
- );
+ const params = {
+ amount: -amount,
+ account_id: account.id,
+ memo,
+ user_id: user.id,
+ rate: app.get("rates")[user.currency],
+ currency: user.currency,
+ confirmed: true,
+ hash: "Internal Transfer",
+ network: "COINOS",
+ };
+
+ if (!username) {
+ l.info("creating redeemable payment");
+ params.redeemcode = uuidv4();
+ }
+
+ let payment = await db.Payment.create(params, { transaction });
payment = payment.get({ plain: true });
payment.account = account.get({ plain: true });
@@ -53,80 +58,82 @@ module.exports = ah(async (req, res, next) => {
emit(user.username, "user", user);
res.send(payment);
- user = await db.User.findOne({
- where: { username }
- });
+ if (username) {
+ user = await db.User.findOne({
+ where: { username },
+ });
- let params = {
- user_id: user.id,
- asset
- };
+ let params = {
+ user_id: user.id,
+ asset,
+ };
- account = await db.Account.findOne({
- where: params,
- lock: transaction.LOCK.UPDATE,
- transaction
- });
+ account = await db.Account.findOne({
+ where: params,
+ lock: transaction.LOCK.UPDATE,
+ transaction,
+ });
- if (account) {
- account.balance += amount;
- await account.save({ transaction });
- } else {
- let name = asset.substr(0, 6);
- let domain;
- let ticker = asset.substr(0, 3).toUpperCase();
- let precision = 8;
+ if (account) {
+ account.balance += amount;
+ await account.save({ transaction });
+ } else {
+ let name = asset.substr(0, 6);
+ let domain;
+ let ticker = asset.substr(0, 3).toUpperCase();
+ let precision = 8;
- const assets = (await axios.get("https://assets.blockstream.info/"))
- .data;
+ const assets = (await axios.get("https://assets.blockstream.info/"))
+ .data;
- if (assets[asset]) {
- ({ domain, ticker, precision, name } = assets[asset]);
- } else {
- const existing = await db.Account.findOne({
- where: {
- asset
- },
- order: [["id", "ASC"]],
- limit: 1
- });
+ if (assets[asset]) {
+ ({ domain, ticker, precision, name } = assets[asset]);
+ } else {
+ const existing = await db.Account.findOne({
+ where: {
+ asset,
+ },
+ order: [["id", "ASC"]],
+ limit: 1,
+ });
- l.info("existing", existing);
+ l.info("existing", existing);
- if (existing) {
- ({ domain, ticker, precision, name } = existing);
+ if (existing) {
+ ({ domain, ticker, precision, name } = existing);
+ }
}
- }
- params = { ...params, ...{ domain, ticker, precision, name } };
- params.balance = amount;
- params.pending = 0;
- account = await db.Account.create(params, { transaction });
- }
+ params = { ...params, ...{ domain, ticker, precision, name } };
+ params.balance = amount;
+ params.pending = 0;
+ account = await db.Account.create(params, { transaction });
+ }
- payment = await db.Payment.create(
- {
- amount,
- account_id: account.id,
- user_id: user.id,
- rate: app.get("rates")[user.currency],
- currency: user.currency,
- confirmed: true,
- hash: "Internal Transfer",
- memo,
- network: "COINOS",
- received: true
- },
- { transaction }
- );
+ payment = await db.Payment.create(
+ {
+ amount,
+ account_id: account.id,
+ user_id: user.id,
+ rate: app.get("rates")[user.currency],
+ currency: user.currency,
+ confirmed: true,
+ hash: "Internal Transfer",
+ memo,
+ network: "COINOS",
+ received: true,
+ },
+ { transaction }
+ );
- payment = payment.get({ plain: true });
- payment.account = account.get({ plain: true });
- emit(user.username, "account", account);
- emit(user.username, "payment", payment);
+ payment = payment.get({ plain: true });
+ payment.account = account.get({ plain: true });
+ emit(user.username, "account", account);
+ emit(user.username, "payment", payment);
- l.info("received internal", user.username, amount);
- notify(user, `Received ${amount} SAT`);
+ l.info("received internal", user.username, amount);
+ notify(user, `Received ${amount} SAT`);
+ }
});
} catch (e) {
l.error(
diff --git a/routes/swaps.js b/routes/swaps.js
index 0d88f3bf..203b6602 100644
--- a/routes/swaps.js
+++ b/routes/swaps.js
@@ -4,6 +4,7 @@ const level = require("level");
const fs = require("fs");
const { spawn } = require("child_process");
const leveldb = level("leveldb");
+const getAccount = require("../lib/account");
const assets = {
b2e15d0d7a0c94e4e2ce0fe6e8691b9e451377f6e46e8045a86f7c4b5d4f0f23: "bitcoin",
@@ -538,45 +539,3 @@ app.post("/publish", auth, ah(async (req, res) => {
}
}));
-const getAccount = async (asset, user) => {
- const account = await db.Account.findOne({
- where: {
- user_id: user.id,
- asset,
- },
- });
-
- if (account) return account;
-
- let params = {
- user_id: user.id,
- asset,
- };
- let name = asset.substr(0, 6);
- let domain = '';
- let ticker = asset.substr(0, 3).toUpperCase();
- let precision = 8;
-
- const assets = (await axios.get("https://assets.blockstream.info/")).data;
-
- if (assets[asset]) {
- ({ domain, ticker, precision, name } = assets[asset]);
- } else {
- const existing = await db.Account.findOne({
- where: {
- asset,
- },
- order: [["id", "ASC"]],
- limit: 1,
- });
-
- if (existing) {
- ({ domain, ticker, precision, name } = existing);
- }
- }
-
- params = { ...params, ...{ domain, ticker, precision, name } };
- params.balance = 0;
- params.pending = 0;
- return db.Account.create(params);
-};
diff --git a/routes/users.js b/routes/users.js
index eaf10d72..81ecf817 100644
--- a/routes/users.js
+++ b/routes/users.js
@@ -4,11 +4,12 @@ const jwt = require("jsonwebtoken");
const authenticator = require("otplib").authenticator;
const textToImage = require("text-to-image");
const randomWord = require("random-words");
+const getAccount = require("../lib/account");
const pick = (O, ...K) => K.reduce((o, k) => ((o[k] = O[k]), o), {});
require("../lib/whitelist");
-const twofa = (req, res, next) => {
+const twofa = ah((req, res, next) => {
let {
user,
body: { token },
@@ -20,321 +21,454 @@ const twofa = (req, res, next) => {
) {
return res.status(401).send("2fa required");
} else next();
-};
-
-app.get("/users/:username", async (req, res) => {
- const { username } = req.params;
- const user = await db.User.findOne({
- attributes: ["username"],
- where: { username },
- });
- if (user) res.send(user);
- else res.status(500).send("User not found");
});
-app.get("/challenge", async (req, res) => {
- const ip = req.headers["x-forwarded-for"] || req.connection.remoteAddress;
- challenge[ip] = randomWord();
- l.info("setting up challenge", ip, challenge[ip]);
- const data = await textToImage.generate(challenge[ip]);
- res.send(data);
-});
+app.get(
+ "/users/:username",
+ ah(async (req, res) => {
+ const { username } = req.params;
+ const user = await db.User.findOne({
+ attributes: ["username"],
+ where: { username },
+ });
+ if (user) res.send(user);
+ else res.status(500).send("User not found");
+ })
+);
-app.post("/register", async (req, res) => {
- try {
+app.get(
+ "/challenge",
+ ah(async (req, res) => {
const ip = req.headers["x-forwarded-for"] || req.connection.remoteAddress;
- const user = await register(req.body.user, ip, true);
- res.send(pick(user, ...whitelist));
- } catch (e) {
- res.status(500).send(e.message);
- }
-});
+ challenge[ip] = randomWord();
+ l.info("setting up challenge", ip, challenge[ip]);
+ const data = await textToImage.generate(challenge[ip]);
+ res.send(data);
+ })
+);
-app.post("/disable2fa", auth, twofa, async (req, res) => {
- let { user } = req;
- user.twofa = false;
- await user.save();
- emit(user.username, "user", user);
- emit(user.username, "otpsecret", user.otpsecret);
- l.info("disabled 2fa", user.username);
- res.end();
-});
+app.post(
+ "/register",
+ ah(async (req, res) => {
+ try {
+ const ip = req.headers["x-forwarded-for"] || req.connection.remoteAddress;
+ const user = await register(req.body.user, ip, true);
+ res.send(pick(user, ...whitelist));
+ } catch (e) {
+ res.status(500).send(e.message);
+ }
+ })
+);
-app.get("/otpsecret", auth, twofa, async (req, res) => {
- let { user } = req;
- emit(user.username, "otpsecret", user.otpsecret);
- res.end();
-});
+app.post(
+ "/disable2fa",
+ auth,
+ twofa,
+ ah(async (req, res) => {
+ let { user } = req;
+ user.twofa = false;
+ await user.save();
+ emit(user.username, "user", user);
+ emit(user.username, "otpsecret", user.otpsecret);
+ l.info("disabled 2fa", user.username);
+ res.end();
+ })
+);
+
+app.get(
+ "/otpsecret",
+ auth,
+ twofa,
+ ah(async (req, res) => {
+ let { user } = req;
+ emit(user.username, "otpsecret", user.otpsecret);
+ res.end();
+ })
+);
-app.post("/2fa", auth, async (req, res) => {
- let { user } = req;
- try {
- const isValid = authenticator.check(req.body.token, req.user.otpsecret);
- if (isValid) {
- user.twofa = true;
- user.save();
- emit(user.username, "user", req.user);
- } else {
- return res.status(500).send("Invalid token");
+app.post(
+ "/2fa",
+ auth,
+ ah(async (req, res) => {
+ let { user } = req;
+ try {
+ const isValid = authenticator.check(req.body.token, req.user.otpsecret);
+ if (isValid) {
+ user.twofa = true;
+ user.save();
+ emit(user.username, "user", req.user);
+ } else {
+ return res.status(500).send("Invalid token");
+ }
+ } catch (e) {
+ l.error("error setting up 2fa", e);
}
- } catch (e) {
- l.error("error setting up 2fa", e);
- }
- l.info("enabled 2fa", user.username);
- res.end();
-});
+ l.info("enabled 2fa", user.username);
+ res.end();
+ })
+);
-app.post("/user", auth, async (req, res) => {
- try {
- let { user } = req;
- let {
- username,
- fiat,
- unit,
- currency,
- currencies,
- twofa,
- pin,
- password,
- passconfirm,
- tokens,
- seed,
- } = req.body;
+app.post(
+ "/user",
+ auth,
+ ah(async (req, res) => {
+ try {
+ let { user } = req;
+ let {
+ username,
+ fiat,
+ unit,
+ currency,
+ currencies,
+ twofa,
+ pin,
+ password,
+ passconfirm,
+ tokens,
+ seed,
+ } = req.body;
- let exists = await db.User.findOne({
- where: { username },
- });
+ let exists = await db.User.findOne({
+ where: { username },
+ });
- let token;
- if (user.username !== username && exists) {
- return res.status(500).send("Username taken");
- } else {
- sockets[username] = sockets[user.username];
- user.username = username;
+ let token;
+ if (user.username !== username && exists) {
+ return res.status(500).send("Username taken");
+ } else {
+ sockets[username] = sockets[user.username];
+ user.username = username;
- if (user.address) addresses[user.address] = username;
+ if (user.address) addresses[user.address] = username;
- if (user.liquid) addresses[user.liquid] = user.username;
+ if (user.liquid) addresses[user.liquid] = user.username;
- token = jwt.sign({ username }, config.jwt);
- res.cookie("token", token, {
- expires: new Date(Date.now() + 432000000),
- });
- }
+ token = jwt.sign({ username }, config.jwt);
+ res.cookie("token", token, {
+ expires: new Date(Date.now() + 432000000),
+ });
+ }
+
+ if (unit) user.unit = unit;
+ user.currency = currency;
+ user.currencies = currencies;
- if (unit) user.unit = unit;
- user.currency = currency;
- user.currencies = currencies;
+ user.tokens = tokens;
+ user.twofa = twofa;
+ user.pin = pin;
+ user.seed = seed;
+ user.fiat = fiat;
- user.tokens = tokens;
- user.twofa = twofa;
- user.pin = pin;
- user.seed = seed;
- user.fiat = fiat;
+ if (password && password === passconfirm) {
+ user.password = await bcrypt.hash(password, 1);
+ }
- if (password && password === passconfirm) {
- user.password = await bcrypt.hash(password, 1);
+ await user.save();
+ emit(user.username, "user", user);
+ res.send({ user, token });
+ } catch (e) {
+ l.error("error updating user", e.message);
}
+ })
+);
- await user.save();
- emit(user.username, "user", user);
- res.send({ user, token });
- } catch (e) {
- l.error("error updating user", e.message);
- }
-});
+app.post(
+ "/keys",
+ auth,
+ ah(async (req, res) => {
+ const { key: hex } = req.body;
+ const key = await db.Key.create({
+ user_id: req.user.id,
+ hex,
+ });
+ emit(req.user.username, "key", key);
+ })
+);
-app.post("/keys", auth, async (req, res) => {
- const { key: hex } = req.body;
- const key = await db.Key.create({
- user_id: req.user.id,
- hex,
- });
- emit(req.user.username, "key", key);
-});
+app.post(
+ "/keys/delete",
+ auth,
+ ah(async (req, res) => {
+ const { hex } = req.body;
+ (
+ await db.Key.findOne({
+ where: {
+ user_id: req.user.id,
+ hex,
+ },
+ })
+ ).destroy();
+ })
+);
-app.post("/keys/delete", auth, async (req, res) => {
- const { hex } = req.body;
- (
- await db.Key.findOne({
- where: {
- user_id: req.user.id,
- hex,
- },
- })
- ).destroy();
-});
+app.post(
+ "/login",
+ ah(async (req, res) => {
+ const { params, sig, key } = req.body;
-app.post("/login", async (req, res) => {
- const { params, sig, key } = req.body;
+ if (sig) {
+ const { callback } = params;
- if (sig) {
- const { callback } = params;
+ try {
+ const url = `${callback}&sig=${sig}&key=${key}`;
+ const response = await axios.get(url);
+ res.send(response.data);
+ } catch (e) {
+ l.error("problem calling lnurl login", e.message);
+ res.status(500).send(e.message);
+ }
- try {
- const url = `${callback}&sig=${sig}&key=${key}`;
- const response = await axios.get(url);
- res.send(response.data);
- } catch (e) {
- l.error("problem calling lnurl login", e.message);
- res.status(500).send(e.message);
+ return;
}
- return;
- }
+ let twofa = req.body.token;
+ l.info(
+ "login attempt",
+ req.body.username,
+ req.headers["x-forwarded-for"] || req.connection.remoteAddress
+ );
+
+ try {
+ let user = await getUser(req.body.username);
- let twofa = req.body.token;
- l.info(
- "login attempt",
- req.body.username,
- req.headers["x-forwarded-for"] || req.connection.remoteAddress
- );
+ if (
+ !user ||
+ (user.password &&
+ !(await bcrypt.compare(req.body.password, user.password)))
+ ) {
+ l.warn(
+ "invalid username or password attempt",
+ req.body.username,
+ req.body.password
+ );
+ return res.status(401).end();
+ }
- try {
- let user = await getUser(req.body.username);
+ if (
+ user.twofa &&
+ (typeof twofa === "undefined" ||
+ !authenticator.check(twofa, user.otpsecret))
+ ) {
+ return res.status(401).send("2fa required");
+ }
- if (
- !user ||
- (user.password &&
- !(await bcrypt.compare(req.body.password, user.password)))
- ) {
- l.warn(
- "invalid username or password attempt",
- req.body.username,
- req.body.password
- );
- return res.status(401).end();
+ let payload = { username: user.username };
+ let token = jwt.sign(payload, config.jwt);
+ res.cookie("token", token, { expires: new Date(Date.now() + 432000000) });
+ user.keys = await user.getKeys();
+ user = pick(user, ...whitelist);
+ res.send({ user, token });
+ } catch (e) {
+ l.error("login error", e.message);
+ res.status(401).end();
}
+ })
+);
- if (
- user.twofa &&
- (typeof twofa === "undefined" ||
- !authenticator.check(twofa, user.otpsecret))
- ) {
- return res.status(401).send("2fa required");
+app.post(
+ "/logout",
+ auth,
+ ah(async (req, res) => {
+ let { subscription } = req.body;
+ const { username } = req.user;
+ l.info("logging out", username);
+ if (!subscription) return res.end();
+ let i = req.user.subscriptions.findIndex(
+ (s) => JSON.stringify(s) === subscription
+ );
+ if (i > -1) {
+ req.user.subscriptions.splice(i, 1);
}
+ await req.user.save();
+ Object.keys(logins).map(
+ (k) => logins[k]["username"] === username && delete logins[k]
+ );
- let payload = { username: user.username };
- let token = jwt.sign(payload, config.jwt);
- res.cookie("token", token, { expires: new Date(Date.now() + 432000000) });
- user.keys = await user.getKeys();
- user = pick(user, ...whitelist);
- res.send({ user, token });
- } catch (e) {
- l.error("login error", e.message);
- res.status(401).end();
- }
-});
+ res.end();
+ })
+);
-app.post("/logout", auth, async (req, res) => {
- let { subscription } = req.body;
- const { username } = req.user;
- l.info("logging out", username);
- if (!subscription) return res.end();
- let i = req.user.subscriptions.findIndex(
- (s) => JSON.stringify(s) === subscription
- );
- if (i > -1) {
- req.user.subscriptions.splice(i, 1);
- }
- await req.user.save();
- Object.keys(logins).map(
- (k) => logins[k]["username"] === username && delete logins[k]
- );
+app.post(
+ "/address",
+ auth,
+ ah(async (req, res) => {
+ if (!config.bitcoin) return res.status(500).send("Bitcoin not configured");
- res.end();
-});
+ let { user } = req;
+ delete addresses[user.address];
-app.post("/address", auth, async (req, res) => {
- if (!config.bitcoin) return res.status(500).send("Bitcoin not configured");
+ if (config.bitcoin.walletpass)
+ await bc.walletPassphrase(config.bitcoin.walletpass, 300);
- let { user } = req;
- delete addresses[user.address];
+ user.address = await bc.getNewAddress("", req.body.type || "bech32");
+ await user.save();
+ addresses[user.address] = user.username;
+ emit(user.username, "user", user);
+ res.send(user.address);
+ })
+);
- if (config.bitcoin.walletpass)
- await bc.walletPassphrase(config.bitcoin.walletpass, 300);
+app.post(
+ "/account",
+ auth,
+ ah(async (req, res) => {
+ let { user } = req;
+ let { asset, domain, precision, name, ticker, user_id } = req.body;
- user.address = await bc.getNewAddress("", req.body.type || "bech32");
- await user.save();
- addresses[user.address] = user.username;
- emit(user.username, "user", user);
- res.send(user.address);
-});
+ try {
+ const account = await db.Account.findOne({
+ where: { user_id, asset },
+ });
-app.post("/account", auth, async (req, res) => {
- let { user } = req;
- let { asset, domain, precision, name, ticker, user_id } = req.body;
+ account.domain = domain;
+ account.name = name;
+ account.ticker = ticker;
+ account.precision = precision;
- try {
- const account = await db.Account.findOne({
- where: { user_id, asset },
- });
+ await account.save();
- account.domain = domain;
- account.name = name;
- account.ticker = ticker;
- account.precision = precision;
+ emit(user.username, "account", account);
+ res.end();
+ } catch (e) {
+ l.error(e.message);
+ return res.status(500).send("There was a problem updating the account");
+ }
+ })
+);
- await account.save();
+app.post(
+ "/shiftAccount",
+ auth,
+ ah(async (req, res) => {
+ let { user } = req;
+ let { asset } = req.body;
- emit(user.username, "account", account);
- res.end();
- } catch (e) {
- l.error(e.message);
- return res.status(500).send("There was a problem updating the account");
- }
+ try {
+ const account = await db.Account.findOne({
+ where: { user_id: user.id, asset },
+ });
+
+ user.account_id = account.id;
+ await user.save();
+ let payments = await user.getPayments({
+ where: {
+ account_id: user.account_id,
+ },
+ order: [["id", "DESC"]],
+ limit: 12,
+ include: {
+ model: db.Account,
+ as: "account",
+ },
+ });
+ user.payments = payments;
+ user.account = account;
+
+ emit(user.username, "user", user);
+ res.end();
+ } catch (e) {
+ l.error(e.message);
+ return res.status(500).send("There was a problem switching accounts");
+ }
+ })
+);
+
+app.get("/vapidPublicKey", function (req, res) {
+ res.send(config.vapid.publicKey);
});
-app.post("/shiftAccount", auth, async (req, res) => {
- let { user } = req;
- let { asset } = req.body;
+app.post(
+ "/subscribe",
+ auth,
+ ah(async function (req, res) {
+ let { subscriptions } = req.user;
+ let { subscription } = req.body;
+ if (!subscriptions) subscriptions = [];
+ if (
+ !subscriptions.find(
+ (s) => JSON.stringify(s) === JSON.stringify(subscription)
+ )
+ )
+ subscriptions.push(subscription);
+ req.user.subscriptions = subscriptions;
+ l.info("subscribing", req.user.username);
+ await req.user.save();
+ res.sendStatus(201);
+ })
+);
- try {
- const account = await db.Account.findOne({
- where: { user_id: user.id, asset },
- });
+app.post(
+ "/redeem",
+ optionalAuth,
+ ah(async function (req, res) {
+ const { redeemcode } = req.body;
+ if (!redeemcode) fail("no code provided");
- user.account_id = account.id;
- await user.save();
- let payments = await user.getPayments({
+ let { user } = req;
+
+ const source = await db.Payment.findOne({
where: {
- account_id: user.account_id,
+ redeemcode: req.body.redeemcode,
},
- order: [["id", "DESC"]],
- limit: 12,
include: {
model: db.Account,
as: "account",
},
});
- user.payments = payments;
- user.account = account;
- emit(user.username, "user", user);
- res.end();
- } catch (e) {
- l.error(e.message);
- return res.status(500).send("There was a problem switching accounts");
- }
-});
+ l.info("redeeming", redeemcode);
-app.get("/vapidPublicKey", function (req, res) {
- res.send(config.vapid.publicKey);
-});
+ if (!source) fail("Invalid code");
+ if (source.redeemed) fail("Voucher has already been redeemed");
-app.post("/subscribe", auth, async function (req, res) {
- let { subscriptions } = req.user;
- let { subscription } = req.body;
- if (!subscriptions) subscriptions = [];
- if (
- !subscriptions.find(
- (s) => JSON.stringify(s) === JSON.stringify(subscription)
- )
- )
- subscriptions.push(subscription);
- req.user.subscriptions = subscriptions;
- l.info("subscribing", req.user.username);
- await req.user.save();
- res.sendStatus(201);
-});
+ if (!user) {
+ const ip = req.headers["x-forwarded-for"] || req.connection.remoteAddress;
+ user = await register({
+ username: redeemcode.substr(0, 8),
+ password: '',
+ } , ip, false);
+
+ let payload = { username: user.username };
+ let token = jwt.sign(payload, config.jwt);
+ res.cookie("token", token, { expires: new Date(Date.now() + 432000000) });
+ return res.send({ user });
+ }
+
+ let account = await getAccount(source.account.asset, user);
+
+ await db.transaction(async (transaction) => {
+ let { hash, memo, confirmed, fee, network } = source;
+
+ source.redeemed = true;
+ await source.save();
+
+ let payment = await db.Payment.create(
+ {
+ amount: -source.amount,
+ account_id: account.id,
+ user_id: user.id,
+ hash: "Redeemed Voucher " + redeemcode,
+ memo,
+ rate: app.get("rates")[user.currency],
+ currency: user.currency,
+ confirmed,
+ network,
+ received: true,
+ fee,
+ },
+ { transaction }
+ );
+
+ account.balance -= source.amount;
+ await account.save();
+
+ payment = payment.get({ plain: true });
+ payment.account = account.get({ plain: true });
+ emit(user.username, "payment", payment);
+ emit(user.username, "account", account);
+
+ res.send({ payment });
+ });
+ })
+);