Skip to content
New issue

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

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

Already on GitHub? # to your account

merge Backend #153

Merged
merged 79 commits into from
Oct 30, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
79 commits
Select commit Hold shift + click to select a range
f8c035c
docs(contributing): move readme directions to own file (#61)
alodahl Aug 23, 2020
7d1819f
docs: Resolve a typo with commands (#87)
jossperdomo Sep 15, 2020
0899a1f
docs: test commit
sraddhanjali Sep 24, 2020
4efcea9
Resolves #65 - Finish ORM Setup (#91)
vegetabill Oct 1, 2020
d1c7d7c
Fix port used in README and remove steps related to when the files we…
vegetabill Sep 13, 2020
f7435d3
orm.js updated with model for UserAnswers
ambikasadhu1101 Oct 1, 2020
8cd5498
updates to UserAnswers model
ambikasadhu1101 Oct 1, 2020
d026158
Merge pull request #97 from ambikasadhu1101/codespace-1
vegetabill Oct 1, 2020
1a642f3
34 caps lock toggle (#98)
ashley-g Oct 1, 2020
12b8ae0
docs: add step for PR description
alodahl Oct 1, 2020
ebcc4fd
Replace repetitive if blocks with lookup
nadyafebi Oct 1, 2020
27c54db
Merge pull request #108 from nadyafebi/replace-repetitive-if-blocks
vegetabill Oct 1, 2020
e326086
Remove unneeded files (#107)
mobasergio Oct 1, 2020
ae2c2ab
Added post endpoint to save an user answer
jossperdomo Oct 1, 2020
9c9d786
refactor: Remove jQuery when possible (#109)
dapper-gh Oct 1, 2020
f42f2a4
Replaced jQuery DOM Selectors with in-built one
i-aryan Oct 1, 2020
c60d9b3
return res object in handlers
jossperdomo Oct 1, 2020
6cd49ef
added backend call when the answer is correct
jossperdomo Oct 1, 2020
4da30f6
Merge branch 'backend' of https://github.com/Techtonica/keyboard-shor…
jossperdomo Oct 1, 2020
48b040a
solved merge conflict
jossperdomo Oct 1, 2020
b9407ab
Merge branch 'backend' into backend
i-aryan Oct 1, 2020
832a836
fix: Add defer to script elements for better loading experience (#113)
racheltl Oct 1, 2020
d26f2ff
fixed mistake with site url
jossperdomo Oct 1, 2020
001c5b2
added find by user_id validation
jossperdomo Oct 1, 2020
48ebbc5
deleted autoincrement config on UserAnswers model
jossperdomo Oct 1, 2020
bd631e2
installing express-openid-connecyt
isabellberzsenyi Oct 1, 2020
33a1a0e
updating the README with instructions for Auth0
isabellberzsenyi Oct 1, 2020
79a8cea
integrating Auth0 middleware into server
isabellberzsenyi Oct 1, 2020
39ccc61
Revert "refactor: Remove jQuery when possible (#109)"
alodahl Oct 1, 2020
76649c5
Merge pull request #116 from josselineperdomo/67__add-post-request
vegetabill Oct 1, 2020
fd97006
Add cross-env package for processing env variables in any platform (#…
paulrrdiaz Oct 1, 2020
a691eaf
Merge branch 'backend' into revert-109-backend
vegetabill Oct 1, 2020
590ce1f
Merge pull request #120 from Techtonica/revert-109-backend
vegetabill Oct 1, 2020
21c1043
Replacing Jquery with Fetch in main.js(#114)
aucodes Oct 1, 2020
2e06d3a
feat: add shortcut type tag to JSON object and main screen (#103)
bellbytes Oct 2, 2020
6b93706
Addressing code review comments
isabellberzsenyi Oct 2, 2020
5daad7e
Replace jQuery.text function
linhhvo Oct 2, 2020
9ecb64b
fixed issues with in-built DOM selector
i-aryan Oct 2, 2020
992a023
Merge branch 'backend' of https://github.com/i-aryan/keyboard-shortcu…
i-aryan Oct 2, 2020
28dc194
Merge branch 'backend' into backend
i-aryan Oct 2, 2020
423355d
remove window height listener in favour of css container height value
FrankyFrankFrank Oct 2, 2020
2474e1f
Merge pull request #115 from i-aryan/backend
vegetabill Oct 2, 2020
64ea88b
Merge pull request #119 from isabellberzsenyi/integrate-auth0-73
vegetabill Oct 2, 2020
f6a0a69
Merge pull request #124 from FrankyFrankFrank/ui/121-replace-window-r…
vegetabill Oct 2, 2020
f30d446
Merge pull request #125 from linhhvo/jquery-text
vegetabill Oct 2, 2020
2be3bae
feat: add toggle to show/hide button hint (#127)
masbagal Oct 3, 2020
46c4e4d
Updated ecstatic to v 4.1.4 (#126)
anuragsati Oct 3, 2020
c031664
get last 3 timing given the user and question id endpoint
jossperdomo Oct 6, 2020
2a37b91
- integrated history endpoint
jossperdomo Oct 7, 2020
3a651b1
refactored history.js
jossperdomo Oct 7, 2020
4db476b
fix: split list keyboard per row (#134)
luciagirasoles Oct 7, 2020
d2d3855
fix: Command hotkeys escaped instead of executed #45 (#118)
KatShambaugh Oct 7, 2020
1bd95a0
Refactor the jquery functions in main.js
y-martinez Oct 7, 2020
3bbd70b
Resolving problems
y-martinez Oct 8, 2020
0ea84ed
Add highlight for Fn key in case F1-F12 is pressed. Fixes #29
Karska-dev Oct 8, 2020
af19151
Merge branch 'backend' of https://github.com/Techtonica/keyboard-shor…
jossperdomo Oct 8, 2020
caf0c67
fixed all the comments made in review stage
jossperdomo Oct 8, 2020
7878e21
Fixes #29. Add Fn un-highlight on release F1-12
Karska-dev Oct 8, 2020
0b014b3
Fixes #29. Change jQuery to native DOM functions. Move macVSCode shor…
Karska-dev Oct 8, 2020
256de3f
added mock userId on the server
jossperdomo Oct 9, 2020
2307a73
Merge pull request #137 from Karska-dev/support-fn-key
vegetabill Oct 9, 2020
a395c60
Added favicon
nidhishs Oct 10, 2020
e16ca53
Refactor the release and handle functions in main
y-martinez Oct 11, 2020
1b78bae
Fixes #138. Add clear prompt for all hint keys (#139)
Karska-dev Oct 13, 2020
ed483bc
Merge branch 'backend' of https://github.com/Techtonica/keyboard-shor…
y-martinez Oct 14, 2020
11d0c5b
Resolve problem with keys that are not used, remove a comment
y-martinez Oct 14, 2020
0d29991
Merge pull request #132 from josselineperdomo/96__retrieve-timing-que…
vegetabill Oct 21, 2020
7f1f42e
Merge pull request #135 from y-martinez/99__replace_toggle_class
vegetabill Oct 21, 2020
94634ad
Merge pull request #140 from nidhishs/backend
vegetabill Oct 21, 2020
fbf911e
App can use Auth0 or local dev auth (#133)
vegetabill Oct 25, 2020
5994699
Add Auth0 callback instructions (#141)
vegetabill Oct 25, 2020
fd688c1
Add indexes: user_answers_created_at_user_id_question_number, user_an…
Nov 6, 2020
a6c4bf3
Merge branch 'backend' into add-indexes-needed-by-common-queries
Hausekey Nov 11, 2020
c3e7ffd
Merge pull request #143 from Hausekey/add-indexes-needed-by-common-qu…
vegetabill Dec 6, 2020
35e2260
Integrate all auth-dependent API stories into working app version (#142)
vegetabill Dec 7, 2020
baeab7f
Bump ini from 1.3.5 to 1.3.8 (#145)
dependabot[bot] Dec 13, 2020
8bc6603
Login button shows correct status centered (#146)
Hausekey Oct 30, 2021
b5c1c2d
Bump jose from 2.0.2 to 2.0.5 (#148)
dependabot[bot] Oct 30, 2021
89303ac
Merge branch 'main' into backend
alodahl Oct 30, 2021
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
4 changes: 4 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
#DB_URL=dev mode defaults to sqlite (so this is not needed)
AUTH0_CLIENT_ID=YOUR_CLIENT_ID
AUTH0_SECRET=YOUR_CLIENT_SECRET
AUTH0_ISSUER_BASE_URL=https://<YOUR-TENANT-NAME>.auth0.com
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
.DS_Store
.env
.env.local
node_modules/
package-lock.json
dev-db.sqlite
7 changes: 4 additions & 3 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,11 @@ Prepare for contributing by following these beginner-friendly steps.
1. Leave a comment that you would like to pick up the issue.
1. Read the description, and make sure to ask questions about anything that is unclear.
1. Start on your forked repo's `backend` branch with `git checkout backend`.
1. Make sure you have the latest version of the project with `git pull upstream/backend`.
1. Create a new branch with `git checkout -b <new-branch-name>`. The name should include the issue number and the topic you're working in. For example, if its about issue #67: adding a GET request, your command could be `git checkout -b 67__add-get-request`.
1. Make sure you have the latest version of the project with `git pull upstream backend` or `git merge upstream/backend`.
1. Create a new branch with `git checkout -b <new-branch-name>`. The name should be short and describe the topic you're working in. For example, if its about adding a GET request for unser data, your command could be `git checkout -b add-user-get-request`.
1. Make and commit your changes on this new branch, and make a PR when you're ready. [Here are some directions on the process](http://www.dasblinkenlichten.com/how-to-create-a-github-pull-request-pr/).
1. When creating your PR, be sure to make your pull request to the `backend` feature branch:

<img src="/images/make-pr-to-backend.png" alt="making a pull request to the backend branch" title="make a pr to backend" width="350" height="200" />
1. See your pull requests here: https://github.com/Techtonica/keyboard-shortcuts-practice/pulls
1. In your new PR's description, add `Fixes #<issue number>`, for example `fixes #1`. This will automatically close the issue once your PR is merged, and it will link the issue with your PR. Also add a description of what the PR is, and how reviewers can validate it.

46 changes: 46 additions & 0 deletions JS/auth-dev.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/**
* Simple cookie session auth for local development when not testing with Auth0.
* Uses Sequelize to store the sessions using an adapter.
*
* - `/#` will automatically sign you in as a current $USER
* (this user will be created if it does not exist)
* - `/logout` will sign you out
*/

const { User, sequelize } = require("./orm");
const session = require("express-session");
const SequelizeStore = require("connect-session-sequelize")(session.Store);

const userIdLoader = (req) => req.session.userId;

const setup = (app) => {
app.use(
session({
secret: "techtonica",
store: new SequelizeStore({
db: sequelize,
tableName: "sessions",
expiration: 1000 * 60 * 30, //30min
}),
unset: "destroy",
resave: false,
saveUninitialized: true,
})
);

app.get("/#", async (req, res) => {
const userId = process.env.USER || "local";
await User.findOrCreate({
where: { id: userId },
});
req.session.userId = userId;
res.redirect("/");
});

app.get("/logout", (req, res) => {
req.session = null;
res.redirect("/");
});
};

module.exports = { setup, userIdLoader };
61 changes: 61 additions & 0 deletions JS/auth-setup.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
const { auth } = require("express-openid-connect");
const Auth0 = require("./auth0");
const { User } = require("./orm");
/**
* Retrieves the currently signed-in user id, if signed-in,
* from the Express Response object.
*
* This mechanism is independent if the app is using Auth0 or not.
*
* @param {*} response Express Response object
*/
const getCurrentUserId = (response) => response.locals.currentUserId;

const findCurrentUserFrom = (loadUserIdFunc) => {
return (req, res, next) => {
const userId = loadUserIdFunc(req);
res.locals.currentUserId = userId;
next();
};
};

/**
* Ensures user record exists for a signed-in user.
* Needed for incoming Auth0 users.
*/
const autoCreateSignedInUser = async (_, res, next) => {
const userId = getCurrentUserId(res);
if (userId) {
const [user, created] = await User.findOrCreate({
where: { id: userId },
});
if (created) {
console.debug(`auto-created newly signed-in user: ${user.id}`);
}
}
next();
};

const routeRequiresSignedIn = (_, res, next) => {
if (!getCurrentUserId(res)) {
return res.sendStatus(401);
}
next();
};

const setupAuth = (app) => {
if (Auth0.authConfig) {
console.debug("Using Auth0 auth");
// auth router attaches /#, /logout, and /callback routes to the baseURL
app.use(auth(Auth0.authConfig));
app.use(findCurrentUserFrom(Auth0.userIdLoader));
app.use("/", autoCreateSignedInUser);
} else {
console.debug("Using dev auth");
const AuthDev = require("./auth-dev");
AuthDev.setup(app);
app.use(findCurrentUserFrom(AuthDev.userIdLoader));
}
};

module.exports = { setupAuth, routeRequiresSignedIn, getCurrentUserId };
22 changes: 22 additions & 0 deletions JS/auth0.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
const { AUTH0_SECRET, AUTH0_CLIENT_ID, AUTH0_ISSUER_BASE_URL } = process.env;
const { port } = require("./config");

let authConfig = false;

if (AUTH0_SECRET && AUTH0_CLIENT_ID) {
authConfig = {
authRequired: false,
auth0Logout: true,
issuerBaseURL: AUTH0_ISSUER_BASE_URL,
baseURL: "http://localhost:".concat(port),
clientID: AUTH0_CLIENT_ID,
secret: AUTH0_SECRET,
};
}

const userIdLoader = (req) => req.oidc.user && req.oidc.user.sub;

module.exports = {
authConfig,
userIdLoader,
};
20 changes: 19 additions & 1 deletion JS/config.js
Original file line number Diff line number Diff line change
@@ -1 +1,19 @@
exports.URL = process.env.URL;
const { DB_URL, NODE_ENV } = process.env;

const port = process.env.port || 3000;

const isProduction = () => NODE_ENV === "production";
const isDevelopment = () => NODE_ENV === "development";

const getDefaultDbUrl = () => {
if (!isProduction()) {
return "sqlite:dev-db.sqlite";
}
};

module.exports = {
isProduction,
isDevelopment,
port,
DB_URL: DB_URL || getDefaultDbUrl(),
};
93 changes: 68 additions & 25 deletions JS/orm.js
Original file line number Diff line number Diff line change
@@ -1,31 +1,74 @@
// access config/env variables
//var config = require("./config.js");
require('dotenv').config();
console.log(`${process.env.URL}`);

// setting up ORM
var Sequelize = require('sequelize');
var sequelize = new Sequelize(`${process.env.URL}`);
const Sequelize = require("sequelize");
const { DB_URL } = require("./config.js");

const sequelize = new Sequelize(DB_URL);

// define basic model for a user
const Model = Sequelize.Model;
class User extends Model {}
User.init({
uid: Sequelize.INTEGER,
q_number: Sequelize.STRING,
last_login: Sequelize.DATE
}, { sequelize, modelName: 'user' });

// testing database connection
sequelize
.authenticate()
.then(() => {
console.log('Connection has been established successfully.');
})
.catch(err => {
console.error('Unable to connect to the database:', err);
});
User.init(
{
last_login: {
type: Sequelize.DATE,
defaultValue: Sequelize.NOW,
},
id: {
type: Sequelize.STRING,
primaryKey: true,
},
},
{
sequelize,
modelName: "user",
createdAt: "created_at",
updatedAt: "updated_at",
}
);
class UserAnswers extends Model {}
UserAnswers.init(
{
user_id: {
type: Sequelize.STRING,
allowNull: false,
},
question_number: {
type: Sequelize.INTEGER,
allowNull: false,
},
is_correct: {
type: Sequelize.BOOLEAN,
allowNull: false,
},
elapsed_time_ms: {
type: Sequelize.INTEGER,
allowNull: false,
},
},
{
sequelize,
modelName: "user_answers",
createdAt: 'created_at',
updatedAt: false,
indexes: [
{
fields: ['created_at', 'user_id', 'question_number']
},
{
fields: ['created_at', 'user_id']
}
]
}
);
User.hasMany(UserAnswers, { foreignKey: "user_id" });
UserAnswers.belongsTo(User, { foreignKey: "user_id" });
const connectToDb = async () => {
await sequelize.authenticate();
await sequelize.sync();
};

// TODO: make User model accessible from other files
// export { User };
module.exports = {
User,
connectToDb,
UserAnswers,
sequelize,
};
1 change: 0 additions & 1 deletion JS/router.js

This file was deleted.

10 changes: 9 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,15 @@ We discovered that our participants need an app similar to typing practice websi

This project should train and test users to use the quicker keyboard shortcuts instead of a mouse and the GUI. The app gets more challenging as you progress through the commands.

Our goal for the backend project is to create a persistant app where users can #, practice with the app, and save their progress. That way, the next time they #, they can pick up where they left off rather than starting at the beginning.
Our goal for the backend project is to create a persistent app where users
can #, practice with the app, and save their progress. That way, the next time they #, they can pick up where they left off rather than starting at the beginning.

# Setting up Auth0 and creating an account
1. Create a [free personal Auth0 account](https://auth0.com/)
1. Create a `Regular Web Application`
1. Run `cp .env.example .env` to create a .env file
1. From the settings page of your Auth0 web application fill in the environment variables, ensuring that the `AUTH0_ISSUER_BASE_URL` is the Domain URL starting with `https://`
1. The _Allowed Callback URLs_ for local development should be `http://localhost:3000/callback`

## Running the project

Expand Down
40 changes: 27 additions & 13 deletions app.js
Original file line number Diff line number Diff line change
@@ -1,26 +1,40 @@
const path = require('path');
const morgan = require('morgan');
require("dotenv").config();
const path = require("path");
const morgan = require("morgan");
const express = require("express");
const bodyParser = require("body-parser");
const { setupAuth } = require("./JS/auth-setup");
const { connectToDb } = require("./JS/orm");
const { port } = require("./JS/config");
const favicon = require("serve-favicon");

const app = express();
app.use(morgan('dev')); //morgan gives us useful logging
app.use(morgan("dev")); //morgan gives us useful logging

require('ejs');
app.set('view engine', 'ejs');
app.set('views', path.join(__dirname, 'views'));
require("ejs");
app.set("view engine", "ejs");
app.set("views", path.join(__dirname, "views"));

app.use(express.static('public'));
app.use(express.static("public"));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(favicon(__dirname + "/public/images/favicon.ico"));

setupAuth(app);
const routes = require("./routes/routes.js");
app.use('/', routes);
app.use("/", routes);

app.use((req, res) => {
res.status(404).render('not_found');
app.use((_, res) => {
res.status(404).render("not_found");
});

const startServer = async () => {
await connectToDb();
app.listen(port, () => {
console.log(`Listening on http://localhost:${port} :-D`);
});
};

startServer();

const server = app.listen(3000, function () {
console.log("Listening on http://localhost:" + server.address().port, ":-D");
});
module.exports = app;
Loading