Skip to content

Commit

Permalink
merge upstream
Browse files Browse the repository at this point in the history
  • Loading branch information
Hoie Kim committed Oct 1, 2020
2 parents b1a7c1e + 39a2f8e commit bedbc4f
Show file tree
Hide file tree
Showing 19 changed files with 645 additions and 374 deletions.
39 changes: 11 additions & 28 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,27 +1,14 @@
# databases
# Learn Databases

Fork the repository
Go to https://c0d3.com
Create a username and account
A free site to learn and try different databases.

Ssh into c0d3 server
`ssh [c0d3.com username]@c0d.com -p 221`
**Installation**

Clone your fork on the server
`git clone https://github.com/[github username]/databases.git`

To run server
1. install nodemon
2. run npm start:dev

To install nodemon
`npm i -g nodemon`

To start the server
`npm run start:dev`

If you need to make changes to the Database run:
`ALTER_DB=true npm run start:dev`
1. Fork the repository. If you're new to github refer to this [guide](https://github.com/garageScript/curriculum/wiki/Engineering-Workflow).
2. Download the fork into your local machine.
3. Install required node modules with `npm i`.
4. Create new .env file, it should look like env.example but with valid credentials instead of `***`. Ask for passwords and api keys on our [chat](https://chat.c0d3.com/c0d3/channels/).
5. Start server with `npm run start:dev` and register a new user.

### Production Phases

Expand All @@ -34,13 +21,9 @@ Phase 3: API to power user interactions (backend)
Phase 4: UI (aka frontend)
**We are here!**

What needs to worked on
https://github.com/garageScript/databases/issues
* [Issues](https://github.com/garageScript/databases/issues)

Wiki
https://github.com/garageScript/databases/wiki
* [Wiki](https://github.com/garageScript/databases/wiki)

If you have any questions message us on our chat:
https://chat.c0d3.com/c0d3/channels/
* If you have any questions message us on our [chat](https://chat.c0d3.com/c0d3/channels/)

__Sequelize credentials are in the chat for privacy__
6 changes: 3 additions & 3 deletions database/elasticsearch/elastic.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ const sendESRequest = (path, method, body) => {
};

es.createAccount = async (account) => {
if (!account.username || !account.dbPassword || !account.email) {
if (!account.username || !account.dbPassword) {
logger.error("Account data is invalid");
throw new Error("Account data is invalid");
}
Expand Down Expand Up @@ -87,10 +87,10 @@ es.deleteAccount = async (account) => {
if (err || !r1.found || !r2.found) {
logger.error("Deleting Elasticsearch user failed");
throw new Error(
`Failed to delete Elasticsearch account for user: ${account.email}`
`Failed to delete Elasticsearch account for user: ${account.id}`
);
}
logger.info("Successfully deleted Elasticsearch user", account.email);
logger.info("Successfully deleted Elasticsearch user", account.id);
};

es.checkAccount = async (account) => {
Expand Down
7 changes: 4 additions & 3 deletions database/postgres/pg.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,9 @@ pgModule.closePGDB = () => {
return client.end();
};

pgModule.createPgAccount = async (username, password) => {
if (!username || !password) return;
pgModule.createPgAccount = async (user) => {
const { username, dbPassword } = user;
if (!username || !dbPassword) return;
try {
// Could not escape user input by using $1 $2
// https://github.com/brianc/node-postgres/issues/539
Expand All @@ -30,7 +31,7 @@ pgModule.createPgAccount = async (username, password) => {
const sqlQuery2 = escape(
`create user %s with encrypted password %Q`,
username,
password
dbPassword
);

const sqlQuery3 = escape(
Expand Down
12 changes: 6 additions & 6 deletions database/postgres/pg.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,8 @@ describe("Test PG DB", () => {
});
describe("Test createPgAccount", () => {
it("it should execute all queries if required arguments are passed into createPgAccount", async () => {
await createPgAccount("username", "password");
const user = { username: "username", dbPassword: "password" };
await createPgAccount(user);
expect(mockClient.query).toHaveBeenCalledTimes(3);
expect(mockClient.query.mock.calls[0]).toEqual([
`CREATE DATABASE username;`,
Expand All @@ -65,16 +66,15 @@ describe("Test PG DB", () => {
]);
});
it("it should not execute any queries in createPgAccount if required arguments are not passed in", async () => {
await createPgAccount();
const user = {};
await createPgAccount(user);
expect(mockClient.query).toHaveBeenCalledTimes(0);
});
it("it should check if logger.error is called at throw of createPgAccount", async () => {
try {
await mockClient.query.mockReturnValue(Promise.reject());
const resCreatePgAccount = await createPgAccount(
"username",
"password"
);
const user = { username: "username", dbPassword: "password" };
const resCreatePgAccount = await createPgAccount(user);
expect(resCreatePgAccount).rejects.toThrow();
} catch (err) {
expect(logger.error).toHaveBeenCalledTimes(1);
Expand Down
40 changes: 31 additions & 9 deletions env.example
Original file line number Diff line number Diff line change
@@ -1,9 +1,31 @@
HOST=databases.com
PORT=3000
PG_USER=username
PASSWORD=password
DATABASE=database
DIALECT=postgres
ALTER_DB=true
MAILGUN_API_KEY=01234567890123456789
MAILGUN_DOMAIN=databases.com
#api key for mailing service
MAILGUN_API_KEY=***
#mailgun domain
MAILGUN_DOMAIN=code3scape.com
#testing port for jest
TEST_PORT=30300
#sequelize host adress
HOST=104.168.169.204
#sequelize postgres username
PG_USER=***
#sequelize postgres database name
DATABASE=***
#sequelize database password
PASSWORD=***
#sequelize allow to alter database: true/false
ALTER_DB=true
#password for session-express
SECRET=***
#Neo4j graph database url
NEO4J_URL=neo4j://104.168.169.204
#Neo4j username
NEO4J_USER=***
#Neo4j password
NEO4J_PASSWORD=***
#production/development flag, in jest tests this varible is "test" by default
NODE_ENV = development
#local port, default value 3052
PORT = 3052
#hostname adress, default is https://learndatabases.dev,
#if you want to use localhost you need to specify port, for example http://localhost:4000
HOSTNAME = https://learndatabases.dev
8 changes: 0 additions & 8 deletions lib/getEnvVar.js

This file was deleted.

16 changes: 0 additions & 16 deletions lib/getEnvVar.test.js

This file was deleted.

29 changes: 8 additions & 21 deletions lib/users.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ const {
const users = {};

const schema = yup.object().shape({
email: yup.string().required().email(),
email: yup.string().nullable().email(),
});

users.sendPasswordResetEmail = async (userAccount) => {
Expand All @@ -38,35 +38,22 @@ users.sendPasswordResetEmail = async (userAccount) => {
};

users.signUp = async (userInfo) => {
try {
await schema.validate(userInfo);
} catch (err) {
throw new Error(err);
}

const { email } = userInfo;
const { Accounts } = db.getModels();
const userAccount = await Accounts.findOne({
where: {
email: email,
},
});
await schema.validate(userInfo);
const username = uniqueNamesGenerator({
length: 2,
dictionaries: [adjectives, colors, animals],
dictionaries: [adjectives, animals],
separator: "",
});
const dbPassword = genPw();
if (userAccount) {
logger.info("this account already exists", email);
throw new Error("this account already exists");
}
const { Accounts } = db.getModels();
const newAccount = await Accounts.create({
email: email,
email: userInfo.email,
username: username,
dbPassword: dbPassword,
});
await users.sendPasswordResetEmail(newAccount);
if (userInfo.email) {
await users.sendPasswordResetEmail(newAccount);
}
return newAccount;
};

Expand Down
43 changes: 24 additions & 19 deletions lib/users.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -58,42 +58,47 @@ describe("Sign up", () => {
});

it("should throw an error if accounts already exists", () => {
mockFindOne.mockImplementation((query) => {
if (query.where.email) return { email: "[email protected]" };
if (query.where.username) return false;
mockCreateAccount.mockImplementation(() => {
throw new Error("This account already exists");
});
const obj = {
email: "[email protected]",
};
return expect(signUp(obj)).rejects.toThrow("this account already exists");
return expect(signUp(obj)).rejects.toThrow("This account already exists");
});

it("should create a user account", async () => {
const dataValues = await genUserInfoWithPw("abcd1234");
mockFindOne.mockImplementation((query) => {
if (query.where.email) return undefined;
if (query.where.username) return false;
const obj = { email: "[email protected]" };
const dataValues = { ...obj, username: "testuser", dbPassword: "database" };
mockCreateAccount.mockReturnValue({
dataValues: dataValues,
update: () => {},
});
const data = await signUp(obj);
expect(data.dataValues).toEqual(dataValues);
});

it("should create a anonymous user account", async () => {
const obj = {};
const dataValues = { username: "testuser", dbPassword: "database" };
mockCreateAccount.mockReturnValue({
dataValues: dataValues,
update: () => {},
});
const obj = {
email: "[email protected]",
};
const data = await signUp(obj);
expect(data.dataValues).toEqual(dataValues);
expect(email.sendPasswordResetEmail).not.toHaveBeenCalled();
});

it("should send a user set Password email", async () => {
const obj = {
id: 4,
email: "[email protected]",
update: jest.fn(),
};

await sendPasswordResetEmail(obj);
expect(email.sendPasswordResetEmail.mock.calls.length).toEqual(1);
const obj = { email: "[email protected]" };
const dataValues = { ...obj, username: "testuser", dbPassword: "database" };
mockCreateAccount.mockReturnValue({
dataValues: dataValues,
update: () => {},
});
await signUp(obj);
expect(email.sendPasswordResetEmail).toHaveBeenCalled();
});
});

Expand Down
1 change: 1 addition & 0 deletions sequelize/db.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ dbModule.start = async () => {
email: {
type: DataTypes.STRING,
unique: true,
allowNull: true,
},
dbPassword: {
type: DataTypes.STRING,
Expand Down
2 changes: 1 addition & 1 deletion services/__snapshots__/mailer.test.js.snap
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ Object {
<hr>
<div id=\\"content\\">
<p>You have requested a (re)set password token. The button below will redirect you to our website with an autheticated token. Please click the button and set your password.</p>
<a href=\\"https://learndatabases.dev/setPassword/token123\\" target=\\"_blank\\" id=\\"button\\">Set my Password</a>
<a href=\\"https://learndatabases.dev/setPassword/token123\\" target=\\"_blank\\" id=\\"button\\">Set my Password</a>
<p><small><b style=\\"color: red\\">Warning</b>: Anyone with access to this email has access to your account. Don't share this email with other people.</small></p>
</div>
</div>
Expand Down
11 changes: 7 additions & 4 deletions services/mailer.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
const mailgun = require("mailgun-js");
const logger = require("../lib/log")(__filename);
const getEnvVar = require("../lib/getEnvVar");
require("dotenv").config();

const mg = mailgun(getEnvVar("mailgun"));
const mg = mailgun({
apiKey: process.env.MAILGUN_API_KEY,
domain: process.env.MAILGUN_DOMAIN,
});

const mgModule = {};

mgModule.sendPasswordResetEmail = (receiver, token) => {
const link = `https://learndatabases.dev/setPassword/${token}`;
const link = `${process.env.HOSTNAME||"https://learndatabases.dev"}/setPassword/${token}`
const data = {
from: "[email protected]",
to: receiver,
Expand All @@ -19,7 +22,7 @@ mgModule.sendPasswordResetEmail = (receiver, token) => {
<hr>
<div id="content">
<p>You have requested a (re)set password token. The button below will redirect you to our website with an autheticated token. Please click the button and set your password.</p>
<a href="${link}" target="_blank" id="button">Set my Password</a>
<a href="${link}" target="_blank" id="button">Set my Password</a> ${link!=`https://learndatabases.dev/setPassword/${token}`?"<h2>DEVELOPMENT MODE IS ON. This link will redirect you to your development server</h2>" : ""}
<p><small><b style="color: red">Warning</b>: Anyone with access to this email has access to your account. Don't share this email with other people.</small></p>
</div>
</div>
Expand Down
Loading

0 comments on commit bedbc4f

Please sign in to comment.