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

closes #53 - add influxDB #244

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 60 additions & 0 deletions database/influx/influx.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
const Influx = require("influx");
const logger = require("./../../lib/log")(__filename);
require("dotenv").config();

const influxModule = {};
let client;
const HOST = process.env.INF_HOST||"localhost";
const PORT = process.env.INF_PORT||8086;
influxModule.startInflux = () => {
client = new Influx.InfluxDB({
host: HOST,
port: PORT,
});
logger.info("Sucessfully started InfluxDB");
};

influxModule.createAccount = async (account) => {
const { username, dbPassword } = account;
if (!username || !dbPassword) return;
try {
await client.createUser(username, dbPassword);
await client.createDatabase(username);
await client.grantPrivilege(username, "WRITE", username);
logger.info(
`Sucessfully created new user and database with ${username} name`
);
} catch (err) {
logger.error(err);
throw new Error(`failed to create new influx user with ${username} name`);
}
};
influxModule.deleteAccount = async (username) => {
if (!username) return;
try {
await client.dropUser(username);
await client.dropDatabase(username);
logger.info(`Sucessfully deleted account with ${username} name`);
} catch (err) {
logger.error(err);
throw new Error(`failed to delete influx ${username} account`);
}
};
influxModule.checkAccount = async (username) => {
if (!username) return;
try {
const users = await client.getUsers();
const user = users.filter((u) => u === username)[0];
logger.info(
user
? `Found ${user} account with ${username}`
: `No account with ${username} were found`
);
return Boolean(user);
} catch (err) {
logger.error(err);
throw new Error(`failed to check for influx ${username} account`);
}
};

module.exports = influxModule;
107 changes: 107 additions & 0 deletions database/influx/influx.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
jest.mock("../../lib/log");
const logGen = require("../../lib/log");
const logger = { error: jest.fn(), info: jest.fn() };
logGen.mockReturnValue(logger);
jest.mock("dotenv");
require("dotenv").config();
jest.mock("influx");
const { InfluxDB } = require("influx");
const influx = require("influx");
const {
startInflux,
createAccount,
deleteAccount,
checkAccount,
} = require("./influx");
describe("test InfluxDB", () => {
beforeEach(() => {
jest.clearAllMocks();
});
const mockClient = {
InfluxDB: jest.fn(),
createUser: jest.fn(),
createDatabase: jest.fn(),
grantPrivilege: jest.fn(),
dropUser: jest.fn(),
dropDatabase: jest.fn(),
getUsers: jest.fn(),
};
const user = { username: "username", dbPassword: "password" };
InfluxDB.mockImplementation(function () {
return mockClient;
});
it("should start influx client", () => {
startInflux();
expect(influx.InfluxDB).toHaveBeenCalledTimes(1);
});
it("should use global variables", () => {
startInflux();
expect(influx.InfluxDB.mock.calls[0][0].host).toEqual("localhost");
expect(influx.InfluxDB.mock.calls[0][0].port).toEqual(8086);
});
describe("createAccount", () => {
it("should sucessfully create new account", async () => {
await createAccount(user);
expect(mockClient.createUser).toHaveBeenCalledTimes(1);
expect(mockClient.createDatabase).toHaveBeenCalledTimes(1);
expect(mockClient.grantPrivilege).toHaveBeenCalledTimes(1);
});
it("should call logger in case of an error", async () => {
try {
mockClient.createUser.mockReturnValue(Promise.reject());
expect(await createAccount(user)).rejects.toThrow();
} catch (err) {
expect(logger.error).toHaveBeenCalledTimes(1);
}
});
it("should return if no account argument was provided", async () => {
const res = await createAccount({});
expect(res).toEqual(undefined);
});
});
describe("deleteAccount", () => {
it("should sucessfully delete account", async () => {
await deleteAccount(user.username);
expect(mockClient.dropUser).toHaveBeenCalledTimes(1);
expect(mockClient.dropDatabase).toHaveBeenCalledTimes(1);
});
it("should throw error to invalid credentials", async () => {
try {
mockClient.dropUser.mockReturnValue(Promise.reject());
expect(await deleteAccount(user.username)).rejects.toThrow();
} catch (err) {
expect(logger.error).toHaveBeenCalledTimes(1);
}
});
it("should return if no username was provided", async () => {
const res = await deleteAccount("");
expect(res).toEqual(undefined);
});
});
describe("checkAccount", () => {
it("should return true if account exists", async () => {
mockClient.getUsers.mockReturnValue(["name", "username"]);
const res = await checkAccount("username");
expect(mockClient.getUsers).toHaveBeenCalledTimes(1);
expect(res).toEqual(true);
});
it("should return false if account doesnt exitsts", async () => {
mockClient.getUsers.mockReturnValue([]);
const res = await checkAccount(user);
expect(mockClient.getUsers).toHaveBeenCalledTimes(1);
expect(res).toEqual(false);
});
it("should throw an error", async () => {
try {
mockClient.getUsers.mockReturnValue(Promise.reject());
expect(await checkAccount(user)).rejects.toThrow();
} catch (err) {
expect(logger.error).toHaveBeenCalledTimes(1);
}
});
it("should return if no username was provided", async () => {
const res = await checkAccount();
expect(res).toEqual(undefined);
});
});
});
16 changes: 10 additions & 6 deletions env.example
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,20 @@ PASSWORD=***
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
#ArangoDB hostname
ARANGO_URL = http://localhost:8529
#ArangoDB username
ARANGO_USER = root
#ArangoDB password
ARANGO_PW = ***
#InfluxDB hostname
INF_HOST = localhost
#InfluxDB port
INF_PORT = 8086
4 changes: 4 additions & 0 deletions lib/util.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ const db = require("../sequelize/db");
const pg = require("../database/postgres/pg");
const arango = require("../database/arango/arango");
const es = require("../database/elasticsearch/elastic");
const influx = require("../database/influx/influx");
const logger = require("./log")(__filename);

const util = {};
Expand Down Expand Up @@ -37,6 +38,9 @@ util.cleanAnonymous = async () => {
const arangoDbExists = await arango.checkIfDatabaseExists(username);
if (arangoDbExists) await arango.deleteAccount(username);

const influxDbExists = await influx.checkAccount(username);
if (influxDbExists) await influx.deleteAccount(username);

return await user.destroy();
})
).then(() => {
Expand Down
7 changes: 7 additions & 0 deletions lib/util.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,15 @@ jest.mock("../sequelize/db");
jest.mock("../database/postgres/pg");
jest.mock("../database/arango/arango");
jest.mock("../database/elasticsearch/elastic");
jest.mock("../database/influx/influx");
jest.mock("./log");

const sequelize = require("sequelize");
const db = require("../sequelize/db");
const pg = require("../database/postgres/pg");
const es = require("../database/elasticsearch/elastic");
const arango = require("../database/arango/arango");
const influx = require("../database/influx/influx");

sequelize.Op = { and: "and", lt: "lt" };
const Accounts = {
Expand All @@ -21,6 +23,7 @@ db.getModels = () => {
pg.deletePgAccount = jest.fn();
es.deleteAccount = jest.fn();
arango.deleteAccount = jest.fn();
influx.deleteAccount = jest.fn();
const logGen = require("./log");
const logger = {
info: jest.fn(),
Expand Down Expand Up @@ -54,20 +57,24 @@ describe("Testing cleanAnonymous function", () => {
pg.userHasPgAccount = () => false;
es.checkAccount = () => false;
arango.checkIfDatabaseExists = () => false;
influx.checkAccount = () => false;
await util.cleanAnonymous();
expect(pg.deletePgAccount).not.toHaveBeenCalled();
expect(es.deleteAccount).not.toHaveBeenCalled();
expect(arango.deleteAccount).not.toHaveBeenCalled();
expect(influx.deleteAccount).not.toHaveBeenCalled();
});
it("should call database functions if expired accounts are found", async () => {
Accounts.findAll.mockReturnValue([{ destroy: () => {} }]);
pg.userHasPgAccount = () => true;
es.checkAccount = () => true;
arango.checkIfDatabaseExists = () => true;
influx.checkAccount = () => true;
await util.cleanAnonymous();
expect(pg.deletePgAccount).toHaveBeenCalled();
expect(es.deleteAccount).toHaveBeenCalled();
expect(arango.deleteAccount).toHaveBeenCalled();
expect(influx.deleteAccount).toHaveBeenCalled();
});
it("should call logger.error if cleaning fails", async () => {
Accounts.findAll.mockImplementation(() => {
Expand Down
5 changes: 5 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
"ejs": "^3.1.3",
"express": "^4.17.1",
"express-session": "^1.17.1",
"influx": "^5.6.3",
"mailgun-js": "^0.22.0",
"mongodb": "^3.6.1",
"neo4j-driver": "^4.1.1",
Expand Down
Binary file added public/TICK.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading