Giter Site home page Giter Site logo

prolifode / deno_rest Goto Github PK

View Code? Open in Web Editor NEW
147.0 8.0 27.0 200 KB

A Boilerplate for deno RESTful apis

License: MIT License

Shell 0.19% TypeScript 99.56% Dockerfile 0.25%
deno rest-api oak mongodb typescript api-starter denon deno-rest jwt deno-mongo boilerplate deno-generator deno-boilerplate

deno_rest's Introduction

Deno REST - A Deno RESTful API Boilerplate

Deno Logo

CircleCI

Deno REST is a straightforward boilerplate project for creating RESTful APIs using Deno, Oak, and deno_mongo. Deno is a secure runtime for JavaScript and TypeScript that uses V8 and is built in Rust, Oak is a middleware framework for Deno's http server, and deno_mongo is a MongoDB driver for Deno.

Features

  • Organized by Model, Controller, Service structure: This project follows a clean architecture that separates concerns into different layers, making it easy to maintain and scale.
  • MongoDB integration: We utilize the deno_mongo library for seamless interaction with MongoDB databases.
  • JWT-based authentication: Securely authenticate users with JSON Web Tokens (JWTs).
  • User authorization: Implement role-based access control to restrict resources based on user roles.
  • CORS support: CORS middleware is integrated to handle cross-origin requests.
  • Environment management via .env: Manage different environments with ease using the .env file.
  • Request validation: Validate incoming requests to ensure they contain valid data.
  • Error handling: Gracefully handle errors and provide helpful error messages to the client.
  • Database seeding: Populate your database with initial data using our database seeding feature.
  • User roles and permissions: Manage user access and permissions efficiently.
  • User activity history: Keep track of user activities within your application.
  • Password hashing with BCrypt: Securely store user passwords with BCrypt hashing.
  • Denon Integration: Use Denon, a utility like nodemon for Deno, to automatically restart the server on file changes.
  • Integration tests: Test your application with our pre-written integration tests.
  • Docker and CircleCI integration: Containerize your application with Docker and set up continuous integration with CircleCI.

Libraries Utilized

  • Oak - Middleware framework for Deno's net server
  • deno_mongo - MongoDB driver for Deno
  • cors - CORS middleware for Deno
  • djwt - JSON Web Tokens in Deno, based on JWT and JWS specifications
  • yup - Schema builder for value parsing and validation
  • bcrypt - OpenBSD Blowfish password hashing algorithm

Getting Started

Installation / Upgrade

To get started with this project, you first need to have Deno installed. If you haven't installed it already, you can follow the official Installation Guide.

Environment Variables

Review the .environments/.env.example file and create a suitable .env file based on your needs. For example, create a .env.development file under the .environments directory for a development environment. For a test environment, create a .env.test file under the .environments directory. Then, add the necessary variables.

Install Denon

Follow this Denon Installation Guide: https://deno.land/x/denon

Database Seeding

We use a seeding script to populate the database with initial data. Run the following command to execute the seeding script:

denon run --allow-read --allow-write --allow-net --unstable seed.ts

Ensure that you have the necessary permissions by including the --allow-read and --allow-write flags.

Running the Project

After setting up everything, you can run the project using the following command:

denon start

The server will start and listen for incoming requests.

User Roles and Permissions

User roles and permissions are defined in the config/roles.ts file. You can add, modify, or remove roles and their associated permissions in this file.

To add a new role, follow these steps:

  1. Open the config/roles.ts file.
  2. Add a new role to the enum Role declaration. For example, to add a GUEST role, your enum Role might look like this:
export enum Role {
  USER = 'USER',
  ADMIN = 'ADMIN',
  GUEST = 'GUEST',
}
  1. Define permissions for the new role in the roleRights object. For example, to allow a GUEST to view users but not modify them, your roleRights object might look like this:
export const roleRights = new Map([
  [Role.USER, [
    PermissionList.GET_USER,
    PermissionList.POST_USER,
    PermissionList.PUT_USER,
    PermissionList.DELETE_USER,
  ]],
  [Role.ADMIN, [
    PermissionList.GET_USER,
    PermissionList.POST_USER,
    PermissionList.PUT_USER,
    PermissionList.DELETE_USER,
    PermissionList.MANAGE_ROLES,
  ]],
  [Role.GUEST, [PermissionList.GET_USER]],
]);

API Routes

This project comes with the following API routes:

  • GET /users: Fetch a list of all users.
  • GET /users/:id: Fetch a specific user by ID.
  • POST /users: Create a new user.
  • PUT /users/:id: Update a specific user by ID.
  • DELETE /users/:id: Delete a specific user by ID.

Each route is secured and requires appropriate permissions to access.

Contributing

We welcome contributions to this project. Please feel free to open an issue or submit a pull request.

License

This project is licensed under the MIT License.

deno_rest's People

Contributors

gamuisalreadytaken avatar gouravshdev avatar techieoriname avatar vicky-gonsalves avatar yuriytigiev avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

deno_rest's Issues

password encryption

Hi,

i noticed that youre encrypting passwords using AES.
That is a really, really bad idea. One should only hash passwords.

Use argon2 or bcrypt to actually hash the password (with an salt)

Add feature for users to sign up

New Users should be able to sign up with Email and Password

Requirements

  • 1. API should accept following parameters as POST body in JSON format.
    NOTE Api should be public and not required any auth headers
    create a function named signup in user.service.ts
{
	"name":"User Name",
	"email":"[email protected]",
	"password":"123456",
}
  • 2. Once user requests above api, it should :
  • Validate all the parameters correctly
  • Send Email with sendgrid to user containing an email verification link in following format:

Hello [USER_NAME],
Please click on following link or Copy/Paste in your web browser to verify your email address.
http://domain.com/user/verify-email?token=[AES_ENCRYPTED_KEY]

  • Note that, AES_ENCRYPTED_KEY must be stored in a separate mongo collection called verification along with user reference to fetch it later.
  • AES_ENCRYPTED_KEY should be created using random characters and a SALT from the .env

example of verification document:

{
    "blacklisted": false,  // will be used later if we need to blacklist a key
    "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI1ZTZiNGZlOTc2NmE3YTFmMjgxZWQzYjIiLCJpYXQiOjE1ODQwOTExMjcsImV4cCI6MTU4NjY4MzEyN30.YVo52NeI-Aju02ENTUOg6ch5En_94i2G8rA7x1WjNDY",  // AES_ENCRYPTED_KEY
    "email": "[email protected]",  // User's Email
    "createdAt": "2020-03-13T09:18:47.247Z",
    "updatedAt":"2020-03-13T09:18:47.247Z",
    "__v": 0
}
  • 3. Add another field in user.model.ts to save status if user has verified his email address.
export interface UserSchema {
 ...
 ...
  isVerified : boolean;
 ...
 ...
}
  • 4. Save User in user collection with isVerified :false, role: config.roles[0] i.e. user

Email Verification API

  • 5. Once user clicks the link, We need to check if the token value in the URL query string EXISTS in the collection verification. This should be done via a service in auth.service.ts. In case it doesn't exists, it should throw an error with 404 HTTP status.

  • 6. If its valid AES_ENCRYPTED_KEY, and exists in the database, proceed next task,

  • 7. Now we have verification document in our hands. Now simply fetch user from the user model and update isVerified:true and delete the verification document and respond with 200 HTTP status.

At this stage we should have a new user successfully signed up.

use BDD from standard library

Deno version 1.21.0 is released, BDD is now part of standard library. Now external dependency for BDD style tests can be excluded

Add cli support

To enhance this boilerplate further add support for cli toolkit, which will act as a project generator and will be easier to maintain its features.

TODO - files

Could you add support to work with files? Upload/Download user-profiles picture(s).

[FEAT]: Improved Project Documentation

Improved Project Documentation

Description:

I am requesting more detailed documentation for the deno_rest project. The current documentation seems [brief], and I believe that providing more detailed information on

  • how to create new module
  • how to create new api
  • common api response structure for frontend
  • all api through postman,
  • more detailed code explanation
  • one click module creation, for example it will ask some information related to new module in form submit in vscode and all files related to that module will be created.
  • deeper WebSocket best practice example
  • api for multipart-form data (file upload)
  • pagination best practice example

would greatly benefit the community.

Thank you for your attention to this matter.

TypeError: crypto.subtle.importKey is not a function

After updating, Deno v1.11.0 I am getting typeError in encryption.

const aes = new AES(this.key, { mode: "cbc", iv: this.salt }); // This works proper
const cipher = await aes.encrypt(str); // Error genrates from here.

Error is:
TypeError: crypto.subtle.importKey is not a function at WebCryptoAES.loadKey (https://deno.land/x/[email protected]/src/aes/aes_wc.ts:24:39) at WebCryptoAES.encrypt (https://deno.land/x/[email protected]/src/aes/aes_wc.ts:37:28) at AES.encrypt (https://deno.land/x/[email protected]/src/aes/mod.ts:40:43)

JsonValue Error

I am trying to run this project in my local machine. Even after following all the instructions in the Readme.md, I am unable to run this app using "denon start" command. I'm getting following error:

error: TS2322 [ERROR]: Type 'string | undefined' is not assignable to type 'JsonValue'.
  Type 'undefined' is not assignable to type 'JsonValue'.
      id,
      ~~
    at file:///D:/Projects/deno_rest/helpers/jwt.helper.ts:30:7

    The expected type comes from this index signature.
      [key: string]: JsonValue;
      ~~~~~~~~~~~~~~~~~~~~~~~~~
        at https://deno.land/x/[email protected]/mod.ts:25:3

This error is caused by the following code in jwt.helper.ts

const payload: Payload = {
  iss: "deno_rest",
  iat: now,
  id, 
  exp,
};

Add Reset Password feature

User should be able to request reset password via an API.

Requirements:

Hello [USER_NAME],
Please click on following link or Copy/Paste in your web browser to reset your password.
http://domain.com/user/reset-password?reset=[AES_ENCRYPTED_KEY]

  • Note that, AES_ENCRYPTED_KEY must be stored in a separate mongo collection called reset-password along with user reference to fetch it later.
  • AES_ENCRYPTED_KEY should be created using random characters and a SALT from the .env
  • Each document must have an expiry date to later verify if link is expired or not.
  • Expiry duration should be stored in .env with variable name RESET_PASS_EXP=3600 with seconds as unit

example of reset-password document:

{
    "blacklisted": false,  // will be used later if we need to blacklist a key
    "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI1ZTZiNGZlOTc2NmE3YTFmMjgxZWQzYjIiLCJpYXQiOjE1ODQwOTExMjcsImV4cCI6MTU4NjY4MzEyN30.YVo52NeI-Aju02ENTUOg6ch5En_94i2G8rA7x1WjNDY",  // AES_ENCRYPTED_KEY
    "email": "[email protected]",  // User's Email
    "expires":"2020-04-12T09:18:47.233Z", // expiry date
    "createdAt": "2020-03-13T09:18:47.247Z",
    "updatedAt":"2020-03-13T09:18:47.247Z",
    "__v": 0
}

Reset Password Verification API

  • 4. Once user clicks the link, We need to check if the reset value in the URL query string EXISTS and NOT EXPIRED in the collection reset-password. This should be done via a service in auth.service.ts. In case it doesn't exists, it should throw an error with 404 HTTP status.

  • 5. If its valid AES_ENCRYPTED_KEY, and exists in the database, we should fetch user with avaialable email value from reset-password document. Then, we need to generate a n auth token and respond back with same response as we do in the login API.

  • 6. Now we have auth token in hands. We can send this auth token to a seperate API headers to change the password #13

Add Change Password Feature

User should be able to change password.

** Requirements**

  • 1. POST API should accept following headers and parameters:
// Headers:
bearer token in the auth headers - we generated from the reset-password api

// POST body should have these parameters:
newPassword:'SomenEWpAssWord'  
  • 2. Create a new service in auth.service.ts to change the password:
    It should first verify the auth token and if its valid and not expired, we should straight away update user's password with new AES_ENCRYPTED password and respond back with 200 HTTP status

Install dependencies issue

I had a problem when install dependencies by running script reload_deps.sh.
How to fix it?

##Deno i'm using

% deno --version
deno 1.13.2 (release, x86_64-apple-darwin)
v8 9.3.345.11
typescript 4.3.5
  • I had also tried deno 1.11.5, the error is same

##Here is the error:

Check file:///Volumes/Data/work/tokenomic/deno_rest/deps.ts
error: TS2345 [ERROR]: Argument of type '"jwk"' is not assignable to parameter of type '"raw"'.
        "jwk",
        ~~~~~
    at https://deno.land/x/[email protected]/src/aes/aes_wc.ts:25:9

TS2345 [ERROR]: Argument of type '"jwk"' is not assignable to parameter of type '"raw"'.
    "jwk",
    ~~~~~
    at https://deno.land/x/[email protected]/src/rsa/rsa_wc.ts:55:5

TS2304 [ERROR]: Cannot find name 'HmacKeyAlgorithm'.
): algorithm is HmacKeyAlgorithm | RsaHashedKeyAlgorithm {
                ~~~~~~~~~~~~~~~~
    at https://deno.land/x/[email protected]/algorithm.ts:24:17

TS2304 [ERROR]: Cannot find name 'RsaHashedKeyAlgorithm'.
): algorithm is HmacKeyAlgorithm | RsaHashedKeyAlgorithm {
                                   ~~~~~~~~~~~~~~~~~~~~~
    at https://deno.land/x/[email protected]/algorithm.ts:24:36

TS2304 [ERROR]: Cannot find name 'EcKeyAlgorithm'.
): algorithm is EcKeyAlgorithm {
                ~~~~~~~~~~~~~~
    at https://deno.land/x/[email protected]/algorithm.ts:30:17

TS2339 [ERROR]: Property 'hash' does not exist on type 'KeyAlgorithm'.
        return keyAlgorithm.hash.name === algAlgorithm.hash.name;
                            ~~~~
    at https://deno.land/x/[email protected]/algorithm.ts:47:29

TS2339 [ERROR]: Property 'namedCurve' does not exist on type 'never'.
        return keyAlgorithm.namedCurve === algAlgorithm.namedCurve;
                            ~~~~~~~~~~
    at https://deno.land/x/[email protected]/algorithm.ts:49:29

denon start

Hello,

Looks like something is missing.

PS C:\Users\yuriy\OneDrive\Documents\GitHub\deno_rest> denon start
denon : The term 'denon' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again.
At line:1 char:1

  • denon start
  •   + CategoryInfo          : ObjectNotFound: (denon:String) [], CommandNotFoundException
      + FullyQualifiedErrorId : CommandNotFoundException
    
    

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.