@rahmatsaeedi/miniurl
Version:
A full stack, light-weight, simplified, & minified version of bit.ly, that allows users to shorten long URLs
144 lines (117 loc) • 6.61 kB
Markdown
# [`miniURL`][miniurl] - a `TinyApp` Project
[`miniurl`][miniurl] is a full stack web application, built with [`Node`][node] and [`Express`][express], that allows users to shorten long URLs (simillar to [bit.ly][bit.ly]). This project was built as a *proof of concept* for for learning purposes.
**_BEWARE:_ This application _does not store_ Users and URL databases to hard disk or external databases. Once the application is restarted all changes are lost, thus changes to [lookupURL.js][lookupURL] and [lookupUser.js][lookupUser] are needed to store these values.**
# Usage
Install it:
```bash
npm install @rahmatsaeedi/miniurl
```
Run it:
```bash
node express_server
```
# Security Issues
The application uses unsigned cookies, with 32 alphanumeral-characters (a-z, A-Z, 0-9) as the session identity; hence, being vulnerable to [`Pass the Cookie`][passTheCookie] attack, and [`session hijacking`][sessionHijacking] if used without TLS/SSL connection.
Also, [lookupURL.js][lookupURL] and [lookupUser.js][lookupUser] contains two registered users ([`admin@example.com`][lookupUser] and [`example@example.com`][lookupUser]) and a session cookie ( [`sessionID`][lookupURL] ) for demonistration purposes. These `users`, their associated [`URLs`][lookupURL], and the `session` can be safely deleted.
# Dependencies
* [`Node.js`][node]
* [`Express`][express]
* [`EJS`][ejs]
* [`bcrypt`][bcrypt]
* [`body-parser`][bparser]
* [`cookie-parser`][cparser]
# Documentations
[`views`](/views) folder contain webpage templates.
[`express_server.js`](express_server.js) contain server logics, routing routes, and overall behaviours settings.
[`lookupURL.js`](lookupURL.js) contains logics related to processing stored shorcode for URLs, such as:
* `addURL (shortURL, longURL, userID)` : Stores the short/long url pair to URL database of the logged-in user with the session id `userID`.
* `removeURL (shortURL, userID) ` : Removes the stored URL with shortcode `shortURL` from URL database of the logged-in user with session id `userID`.
* `updateURL (shortURL, longURL, userID)` : Updates the short/long url pair of the logged-in user with the session id `userID`.
* `getURL (shortURL, incrementVisit = false)` : Returns the url object with the shortcode `shortURL`.
* Example of a URL object stored within the DB
```js
"g" : {
shortURL : "g",
longURL : "https://www.google.ca",
userID : "userID",
lastUpdated : Date.now(),
'visits' : 50
}
```
[`lookupUser.js`](lookupUser.js) : contains logics related to processing stored shorcode for URLs:
* `initSessions ()` : Sets an interval to delete expired sessions routinly. Cleaning happens once every _localVariables.sessionDuration_ minutes.
* `authenticate (email, pass)` : Authenticates plaintext password *pass* of user with email *email* against the stored hashed password.
* `createSession (email, pass)` : Creates and returns a session key for the user with given _email_ and plaintext _pass_.
* `destroySession (sessionID)` : Deletes the given session from _sessions_ object.
* `extendSession (sessionID)` : Changes the expiry time of the session with given session id to _Date.now() + localVariables.sessionDuration_.
* `getSessionUserID (sessionID)` : Returns _user id_ of the _session user_ with the given _session id_.
* `getUserEmailByID (userID)` : Returns _email address_ of the _session user_ with the given _session id_.
* `getSessionExpires (sessionID)` : Returns _expiry time_ of the _session_ with the given _session id_.
* `authenticateSession (sessionID)` : Returns a _boolean_ if the session exists and has not expired yet.
* `registerNewUser (email, pass)` : Adds a new _user object_ to the _users object_. `pass` is plaintext password, and the _user object_ contains the _hashe password_.
* `isRegistered (email)` : Returns a _true_, if a _user object_ with the given _email address_ exists. Else, returns _false_.
* `addToURI (uri, value, sessionID)` : Adds the object/array/value `value` to the _user object_ of the session-holder with the given _sessionID_. `uri` is a string, a key within the _user object_.
* `deleteFromURI (uri, value, sessionID)` : Removes the object/array/value `value` from the _user object_ of the session-holder with the given _sessionID_. `uri` is a string, a key within the _user object_.
* `getURI (uri, sessionID)` : For the session-holder `XYZ`, this returns the value of `XYZ[uri]`. _uri_ is a string, a key, within the _user object_.
[`generateRandomString.js`](generateRandomString.js) :
* `generateRandomString(length = 7)` generates a random string that starts with an alphabet and given _length_.
***Document Tree***
```
│
├─── doc
│ ├─── errors.PNG
│ ├─── login.PNG
│ ├─── register.PNG
│ ├─── urls.edit.PNG
│ └─── urls.PNG
│
├─── node_modules
│ ├─── ...
│ ...
│
├─── views
│ ├─── favicon.ico
│ ├─── urls_errors.ejs
│ ├─── urls_index.ejs
│ ├─── urls_login.ejs
│ ├─── urls_new.ejs
│ ├─── urls_register.ejs
│ ├─── urls_show.ejs
│ └─── _header.ejs
├─── .gitignore
├─── express_server.js
├─── generateRandomString.js
├─── lookupURL.js
├─── lookupUser.js
├─── package-lock.json
├─── package.json
└─── readme.md
```
# Final Product
## Login Page
![Login Page][login]
## Registeration Page
![Registeration Page][register]
## URLs Index
![Registered URLs][urls]
## URLs Edit / Show
![Edit / Show URLs][urls.edit]
## Example Errors
![Example Errors][errors]
[miniurl]: https://www.npmjs.com/package/@rahmatsaeedi/miniurl
[ejs]: https://www.npmjs.com/package/ejs
[bcrypt]: https://www.npmjs.com/package/bcrypt
[bparser]: https://www.npmjs.com/package/body-parser
[cparser]: https://www.npmjs.com/package/cookie-parser
[node]: https://github.com/nodejs/node
[express]: https://github.com/expressjs/express
[bit.ly]: https://bitly.com/
[passTheCookie]: https://wunderwuzzi23.github.io/blog/passthecookie.html
[sessionHijacking]: https://en.wikipedia.org/wiki/Session_hijacking
[login]: /doc/login.PNG
[register]: /doc/register.PNG
[urls]: /doc/urls.PNG
[urls.edit]: /doc/urls.edit.PNG
[errors]: /doc/errors.PNG
[lookupUser]: lookupUser.js
[lookupURL]: lookupURL.js