Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove accounts #165

Merged
merged 11 commits into from
Dec 5, 2021
16 changes: 16 additions & 0 deletions back-end/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ mongoose
// importing user context
const UserModel = require("./model/user");
const isDuplicateAccount = require("./functions/isDuplicateAccount");
const removeAccount = require("./functions/removeAccount");

// Initialize the Plaid client
const configuration = new Configuration({
Expand Down Expand Up @@ -475,5 +476,20 @@ app.post("/api/contactInfo", async (req, resp) => {
}
});

app.post("/api/delete_account", async (req, res) => {
try {
const bankName = req.body.account_name;
const id = req.body._id;
const accessTokensArr = await getAccessTokens(id); // get all tokens
removeAccount(bankName, accessTokensArr, id);
return res.status(200).json({ removed: bankName, successful: true });
} catch (error) {
console.log(error);
return res.status(400).json({
err: error,
});
}
});

// export the express app we created to make it available to other modules
module.exports = { app, prettyPrintResponse, formatError };
64 changes: 64 additions & 0 deletions back-end/functions/removeAccount.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
require("dotenv").config({ silent: true });
const { Configuration, PlaidApi, PlaidEnvironments } = require("plaid");
const UserModel = require("../model/user");

// Initialize the Plaid client
const PLAID_CLIENT_ID = process.env.PLAID_CLIENT_ID;
const PLAID_SECRET = process.env.PLAID_SECRET;
const PLAID_ENV = process.env.PLAID_ENV || "sandbox";

const configuration = new Configuration({
basePath: PlaidEnvironments[PLAID_ENV],
baseOptions: {
headers: {
"PLAID-CLIENT-ID": PLAID_CLIENT_ID,
"PLAID-SECRET": PLAID_SECRET,
"Plaid-Version": "2020-09-14",
},
},
});

const plaidClient = new PlaidApi(configuration);

/**
* Removes the access token of the account specified from the DB
* @param {*} curAccountName
* @param {*} accessTokensArr
* @param {*} userId
* @returns true if account was removed, false otherwise
*/
const removeAccount = async (curAccountName, accessTokensArr, userId) => {
azc242 marked this conversation as resolved.
Show resolved Hide resolved
try {
for (const token of accessTokensArr) {
const tempAccount = await plaidClient.accountsGet({
access_token: token.access_token,
});
// prevent null errors if tempAccount.data.accounts is null or anything is null
const accountArr = tempAccount?.data?.accounts ? tempAccount?.data?.accounts : [];
// check each bank's accounts to see if account to be removed exists
for (const accountObj of accountArr) {
if (accountObj.name === curAccountName) {
UserModel.updateOne(
{ _id: userId },
{ $pull: { access_token: token } },
function (err) {
if (err) {
console.log(err);
} else {
console.log("Successfully removed access token from db.");
}
}
);
return true; // stop iterating, account already removed
}
}
}
// if we get here, then we did not remove anything
return false;
} catch (error) {
console.log(error);
return false;
}
};

module.exports = removeAccount;
13 changes: 13 additions & 0 deletions back-end/test/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ Object.assign(global, require(path.join(__dirname, "../app.js")));

const sinon = require("sinon");
const isDuplicateAccount = require("../functions/isDuplicateAccount");
const removeAccount = require("../functions/removeAccount");
sinon.stub(console, "log"); // comment this out if you want debugging statements!

transactionsTest = [
Expand Down Expand Up @@ -601,4 +602,16 @@ describe("testing constructing functions", () => {
);
});
});
describe("testing removeAccount function with bad access token", () => {
it("reads function response and returns false", () => {
expect(
removeAccount("fakeAccountName", ["foo", "bar"], "fakeUserId") === false
);
});
});
describe("testing removeAccount function with no access tokens", () => {
it("reads function response and returns false", () => {
expect(removeAccount("fakeAccountName", [], "fakeUserId") === false);
});
});
});
37 changes: 34 additions & 3 deletions front-end/src/components/AccountDetail/AccountDetail.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import React from "react";
import Button from "@mui/material/Button";
import "../css/AccountDetail.css";
import axios from "axios";

/**
* This component renders the body for the details page of 1 bank account.
* Clicking on the "Save Details" button at the end will bring the user pack to the
Expand All @@ -9,12 +11,18 @@ import "../css/AccountDetail.css";
* @returns Details page for 1 bank account
*/
function AccountDetail(props) {
console.log(props.bankDetails);
console.log(props.bankDetails);
return (
<div>
<h1>{props.bankDetails.name}</h1>
<h5>Available Balance: {props.bankDetails.balances.available} {props.bankDetails.balances.currency}</h5>
<h5>Current Balance: {props.bankDetails.balances.current} {props.bankDetails.balances.currency}</h5>
<h5>
Available Balance: {props.bankDetails.balances.available}{" "}
{props.bankDetails.balances.currency}
</h5>
<h5>
Current Balance: {props.bankDetails.balances.current}{" "}
{props.bankDetails.balances.currency}
</h5>
<Button
onClick={() => {
props.showAccountDetail(false);
Expand All @@ -25,6 +33,29 @@ function AccountDetail(props) {
>
Back
</Button>
<div>
<Button
onClick={() => {
axios
.post("/api/delete_account", {
account_name: props.bankDetails.name,
_id: JSON.parse(sessionStorage.getItem("user"))._id,
})
.then((resp) => {
console.log(resp.data);
alert("Account successfully removed.");
window.location.reload();
// props.showAccountDetail(false);
// props.setBankDetailHeader("");
});
}}
variant="contained"
id="save-details-btn"
color="secondary"
>
Delete Account
</Button>
</div>
</div>
);
}
Expand Down
3 changes: 3 additions & 0 deletions front-end/src/components/Accounts/AccountsPage.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ const PlaidLink = (props) => {
.then((resp) => {
console.log(resp.data);
localStorage.setItem("access_token_object", JSON.stringify(resp.data));
setTimeout(function () {
window.location.reload();
}, 3000);
});
};

Expand Down