Giter Site home page Giter Site logo

jkheadley / appy-backend Goto Github PK

View Code? Open in Web Editor NEW
108.0 14.0 31.0 127.01 MB

A user system to bootstrap your app.

Home Page: https://appyapp.io

License: MIT License

JavaScript 99.59% Dockerfile 0.27% Shell 0.14%
users hapi mongodb api api-server rest restful-api authentication authorization permissions

appy-backend's Introduction

appy logo

A user system leveraging rest-hapi to bootstrap your app.

appy-backend is the server portion of the appy project. It provides a boilerplate user system that leverages the powerful rest-hapi API generator. Inspired by the frame user system, the goal of appy-backend is to provide an easy to use user API that is also capable of supporting a wide range of applications. appy-backend is a great resource for starting almost any app. By leveraging rest-hapi, adding new endpoints is as simple as defining a new model, and model associations are a snap. Bootstrapping your app has never been easier!

Features

  • Registration and account activation flows
  • Login system with forgot password and reset password
  • Social login
  • Abusive login attempt detection
  • User permissions based on roles and groups
  • Three optional authentication strategies
  • Websocket chat via @hapi/nes
  • File upload api
  • Endpoint validation and query support
  • Swagger docs for easy endpoint access

Technologies

appy-backend implements a hapi framework server. appy-backend's RESTful API endpoints are generated through rest-hapi, which means models are based off of mongoose and data is stored in MongoDB.

Demos

View the swagger docs for the live demo:

https://api.appyapp.io

Starting appy-backend

appy_start

Logging in

appy_login

GET /users

appy_get_users

Filter Query and Populate Relationship

appy_permissions_filter

Readme contents

Requirements

Just Docker

OR

You need Node.js installed (>=12.14.1) and you'll need MongoDB installed and running.

Back to top

Getting Started

Download from GitHub:

$ git clone https://github.com/JKHeadley/appy-backend.git
$ cd appy-backend

Installation

Using Docker

None required.

Without Docker

$ npm install

Back to top

Configuration

appy configuration follows frame's configuration flow:

Simply edit config/index.js. The configuration uses confidence which makes it easy to manage configuration settings across environments. Don't store secrets in this file or commit them to your repository.

Instead, access secrets via environment variables. We use dotenv to help make setting local environment variables easy (not to be used in production).

Using Docker

Simply copy .env-docker-sample to .env-docker and edit as needed. Don't commit .env-docker to your repository.

Without Docker

Simply copy .env-sample to .env and edit as needed. Don't commit .env to your repository.

First time setup

WARNING: This will clear all data in the MongoDB database defined in restHapiConfig.mongo.URI (default mongodb://localhost/appy).

If you would like to seed your database with some data, run:

Using Docker

$ sh seed_data.sh

Without Docker

$ npm run seed

NOTE: The password for all seed users is root.

Back to top

Running appy-backend

To quickly run the app locally, simply run:

Using Docker

$ sh run_server.sh

Without Docker

$ npm start

Once the app is running point your browser to http://localhost:8080/ to view the Swagger docs.

Back to top

Wiki

For detailed explanations on many of the topics covered in this readme, including authentication, authorization, and logging in and testing endpoints, please refer to the wiki pages.

Back to top

Swagger documentation

Swagger documentation is automatically generated for all endpoints and can be viewed by pointing a browser at the server URL. By default this will be http://localhost:8080/. The swagger docs provide quick access to testing your endpoints along with model schema descriptions and query options.

Back to top

Authentication

There are three optional authentication strategies in appy and each make use of javascript web tokens (JWT) and the hapi-auth-jwt2 scheme. The three strategies are:

  1. Standard token
  2. Session
  3. Session with refresh token

The strategy used is determined by the restHapiConfig.authStrategy config property.

For a more in-depth description of these strategies, please view the wiki.

Back to top

Authorization

Authorization in appy is enforced via the hapi scope endpoint property. Endpoints generated through rest-hapi come prepopulated with scope values. See the rest-hapi docs for more info.

User scope values are populated based on appy's permission system. User's gain permissions based on three associations:

  1. User defined permissions
  2. Group defined permissions
  3. Role defined permissions

Users must belong to at least one role and can belong to multiple groups. Each permission association carries with it a state property that can be set to Included, Excluded, or Forbidden. This property allows permissions to override each other based on priority. User permissions have the highest priority, followed by Group permissions and lastly Role permissions:

User->Group->Role

This allows easy and specific configuration of user endpoint access. In general, a user will gain the majority of it's permissions through it's role. Those permissions will be further defined by any groups the user belongs to. Finally a user might have a few specific permissions assigned directly to them. A user's scope final scope is a combination of the user's role, groups, and effective permissions. See below for an example:

User: '[email protected]' Role: 'Admin' Role Permissions:

[
  { name:'readUser', state:'Included' },
  { name:'updateUser', state:'Included' },
  { name:'addUserPermissions', state:'Included' },
  { name:'removeUserPermissions', state:'Included' }
]

User's Groups: ['Managers'] Group Permissions:

[
  { name:'updateUser', state:'Excluded' },
]

User Permissions:

[
  { name:'removeUserPermissions', state:'Excluded' },
]

Final User Scope:

['Admin','Managers','readUser','addUserPermissions']

For a more in-depth description of authorization within appy, please view the wiki

Back to top

License

MIT

Back to top

Questions?

If you have any questions/issues/feature requests, please feel free to open an issue. We'd love to hear from you!

Back to top

Contributing

Please reference the contributing doc: https://github.com/JKHeadley/appy-backend/blob/master/CONTRIBUTING.md

Back to top

Thanks!

We hope you enjoy appy-backend!

appy-backend's People

Contributors

afgallo avatar isaacmtz90 avatar ivanmihov avatar jkheadley 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  avatar  avatar  avatar  avatar  avatar  avatar

appy-backend's Issues

POST /login/forgot - "statusCode": 504, "error": "Gateway Timeout", "message": "An error occurred."

Hi @JKHeadley,
I was following the flow of registering a new user which I did it using POST /login but when trying to test the flow for forgot password /login/forgot I got the following:

[05:54:13.539] 28930 ERROR server/api/login.js:338:15 api/Forgot Password — Error: Invalid login: 535-5.7.8 Username and Password not accepted. Learn more at
[05:54:13.539] 28930 ERROR server/api/login.js:338:15 api/Forgot Password — 535 5.7.8 https://support.google.com/mail/?p=BadCredentials e16sm13427923qtk.32 - gsmtp
[05:54:13.539] 28930 ERROR server/api/login.js:338:15 api/Forgot Password — at SMTPConnection._formatError (/Users/jadsam/Documents/VestraHub/appy/node_modules/smtp-connection/lib/smtp-connection.js:528:15)
[05:54:13.539] 28930 ERROR server/api/login.js:338:15 api/Forgot Password — at SMTPConnection._actionAUTHComplete (/Users/jadsam/Documents/VestraHub/appy/node_modules/smtp-connection/lib/smtp-connection.js:1231:30)
[05:54:13.539] 28930 ERROR server/api/login.js:338:15 api/Forgot Password — at SMTPConnection. (/Users/jadsam/Documents/VestraHub/appy/node_modules/smtp-connection/lib/smtp-connection.js:319:22)
[05:54:13.539] 28930 ERROR server/api/login.js:338:15 api/Forgot Password — at SMTPConnection._processResponse (/Users/jadsam/Documents/VestraHub/appy/node_modules/smtp-connection/lib/smtp-connection.js:669:16)
[05:54:13.539] 28930 ERROR server/api/login.js:338:15 api/Forgot Password — at SMTPConnection._onData (/Users/jadsam/Documents/VestraHub/appy/node_modules/smtp-connection/lib/smtp-connection.js:493:10)
[05:54:13.539] 28930 ERROR server/api/login.js:338:15 api/Forgot Password — at emitOne (events.js:116:13)
[05:54:13.539] 28930 ERROR server/api/login.js:338:15 api/Forgot Password — at TLSSocket.emit (events.js:211:7)
[05:54:13.539] 28930 ERROR server/api/login.js:338:15 api/Forgot Password — at addChunk (_stream_readable.js:263:12)
[05:54:13.539] 28930 ERROR server/api/login.js:338:15 api/Forgot Password — at readableAddChunk (_stream_readable.js:250:11)
[05:54:13.539] 28930 ERROR server/api/login.js:338:15 api/Forgot Password — at TLSSocket.Readable.push (_stream_readable.js:208:10)
[05:54:13.539] 28930 ERROR server/api/login.js:338:15 api/Forgot Password — at TLSWrap.onread (net.js:594:20)
Debug: handler, error
{"msec":1230.931826978922,"error":"An error occurred.","data":{"isBoom":true,"isServer":true,"output":{"statusCode":504,"payload":{"statusCode":504,"error":"Gateway Timeout","message":"An error occurred."},"headers":{}}}}

Adding authorizeDocumentCreator

So I am at the point where I want to set authorizeDocumentCreator to true.
I have done so by adding enableDocumentScopes: true and authorizeDocumentCreator: true to the config.js file, I have also dumped the database and reseeded it. I have created a simple model object for demonstration.

'use strict';

module.exports = function (mongoose) {
    var modelName = "task";
    var Types = mongoose.Schema.Types;
    var Schema = new mongoose.Schema({
        description: {
            type: Types.String,
            required: true
        },
        complete: {
            type: Types.Boolean,
            required: true
        }
    }, { collection: modelName });

    Schema.statics = {
        collectionName:modelName,
        routeOptions: {}
    };

    return Schema;
};

When I log in and post a new task I am returned this

[
    {
        "_id": "5a061eee5cf6bb24a63a54d4",
        "description": "Hello world!",
        "complete": false,
        "scope": {
            "rootScope": [
                "user-5a061e8b51742324957e72bb"
            ]
        },
        "createdAt": "2017-11-10T21:49:34.685Z",
        "isDeleted": false
    }
]

But when I try to get the task I encounter an error!

{
    "docs": [
        {
            "error": "Insufficient document scope."
        }
    ],
    "pages": {
        "current": 1,
        "prev": 0,
        "hasPrev": false,
        "next": 2,
        "hasNext": false,
        "total": null
    },
    "items": {
        "begin": null,
        "end": null,
        "total": 1
    }
}

I don't know why I am getting "error": "Insufficient document scope." since I am using the same user account!
Thanks,
Kyle Pfromer

Adding a front end

Hi. Would it be possible to add a wiki page or some pointers in the readme on some ideas about how to add a front end. I am a bit overwhelmed with all the different files.

I am guessing it has something to do with adding a front end file to server folder and making some adjustments to the manifest.js?

Debugging

Hello, i have a begginers question: How may i debug the code, for example, i'am using Visual Studio Code and have the following configuration file

{
"version": "0.2.0",
"configurations": [
{
"type": "node",
"request": "launch",
"name": "Gulp task",
"program": "${workspaceRoot}/node_modules/gulp/bin/gulp.js",
"args": [
"serve:development", "--colors"
]
}
]
}

with this i can see that for example, the Gulp code inside node_modules is debuggable cause the breakpoint stops there, but the code server.js and server/register are not stoping...

And inside the server/models/my.model.js i have a create:pre function defined, the function is executed as well but the debug is not being fired

Thanks!

hoek dependency interrupts gulp

appy\node_modules\hapi-auth-jwt2\node_modules\boom\node_modules\hoek\lib\index.js:719
exports.assert = function (condition, ...args){

SyntaxError: Unexpected token ...

I guess this is technically a hoek issue. Is there a specific version you typically run that I should install?

Unable to run

Hi,

I'm running node v8.4.0 on OSX 10.12.4. I'm running the latest version of mongodb (v3.4.7). I just installed appy via npm install and get the following:


npm WARN deprecated [email protected]: All versions below 4.0.1 of Nodemailer are deprecated. See https://nodemailer.com/status/
npm WARN deprecated [email protected]: Use uuid module instead
npm WARN deprecated [email protected]: Please upgrade to 2.2.19 or higher
npm WARN deprecated [email protected]: This package is discontinued. Use lodash@^4.0.0.
npm WARN deprecated [email protected]: Please update to minimatch 3.0.2 or higher to avoid a RegExp DoS issue
npm WARN deprecated [email protected]: Please update to minimatch 3.0.2 or higher to avoid a RegExp DoS issue
npm WARN deprecated [email protected]: graceful-fs v3.0.0 and before will fail on node releases >= v7.0. Please update to graceful-fs@^4.0.0 as soon as possible. Use 'npm ls graceful-fs' to find it in the tree.

> [email protected] install /Users/tom/dev/hapi/appy/node_modules/fsevents
> node install

[fsevents] Success: "/Users/tom/dev/hapi/appy/node_modules/fsevents/lib/binding/Release/node-v57-darwin-x64/fse.node" already installed
Pass --update-binary to reinstall or --build-from-source to recompile
npm notice created a lockfile as package-lock.json. You should commit this file.
npm WARN [email protected] No repository field.
npm WARN [email protected] No license field.

When I run "gulp seed" I get the following:


/Users/tom/dev/hapi/appy/node_modules/require-dir/index.js:93
            if (!require.extensions.hasOwnProperty(ext)) {
                                    ^

TypeError: require.extensions.hasOwnProperty is not a function
    at requireDir (/Users/tom/dev/hapi/appy/node_modules/require-dir/index.js:93:37)
    at Object.<anonymous> (/Users/tom/dev/hapi/appy/gulpfile.js:9:23)
    at Module._compile (module.js:573:30)
    at Object.Module._extensions..js (module.js:584:10)
    at Module.load (module.js:507:32)
    at tryModuleLoad (module.js:470:12)
    at Function.Module._load (module.js:462:3)
    at Module.require (module.js:517:17)
    at require (internal/module.js:11:18)
    at execute (/usr/local/lib/node_modules/gulp-cli/lib/versioned/^3.7.0/index.js:26:18)

I would appreciate any suggestions on this.

Tom

Issue with Pagination

I have created some API's in the backend and now in the UI when the records open the pagination is not implemented on them . For example if there are total 70 documents , in the first page i get all 70 documents and it is written like showing 1 to 10 of 70 documents . Please help me out to implement the pagination in the Client side when i am making a API in the backend . I mean how will i use params in the backend API ?

Emails not working

Hi @JKHeadley, thanks for this boilerplate. It has come in pretty handy!

I realised when testing that emails weren't working due to a wrong folder path you had in server/mailer.js. I made the change bellow and it worked!

image

Let me know if you would like a PR for this.

Cheers!

TypeError: require.extensions.hasOwnProperty is not a function

gulp seed

dev/appy/node_modules/require-dir/index.js:93
if (!require.extensions.hasOwnProperty(ext)) {
^

TypeError: require.extensions.hasOwnProperty is not a function
at requireDir (/home/koelzdj/dev/appy/node_modules/require-dir/index.js:93:37)
at Object. (/home/koelzdj/dev/appy/gulpfile.js:9:23)
at Module._compile (module.js:569:30)
at Object.Module._extensions..js (module.js:580:10)
at Module.load (module.js:503:32)
at tryModuleLoad (module.js:466:12)
at Function.Module._load (module.js:458:3)
at Module.require (module.js:513:17)
at require (internal/module.js:11:18)
at Liftoff.handleArguments (/usr/local/lib/node_modules/gulp/bin/gulp.js:116:3)

Seems to be an issue with using nodejs version 8.
Reference the following https://stackoverflow.com/questions/44298322/node-8-0-0-and-npm-4-2-0-error-express-load-require-extensions-hasownproperty-is

createdBy field

Hello Justin and al,
First of all congratulations on the outstanding repository you shared! Very useful, thanks very much.
I was wondering if you planned to develop a createdBy and updatedBy functionality so we can keep track on the authors of the documents. I guess this could be linked with the automatic logging/auditing thing that is already on the rest-hapi roadmap?
Thanks!
Pierre

/register endpoint returning 504 Gateway timeout

Hi, I'm using your framework for some testing, and I can't guess what happens with the /register endpoint:

When I give this payload to the body:

{
  "user": {
    "firstName": "Test",
    "lastName": "Tester",
    "email": "[email protected]",
    "role": "Admin",
    "password": "testtest"
  },
  "registerType": "Register"
}

The server always returns:

{
"msec":228.90566400438547,"error":"An error occurred GenerateKey.","data":{"isBoom":true,"isServer":true,"output":
{"statusCode":504,"payload":{"statusCode":504,"error":"Gateway Timeout","message":"An error occurred."},"he
aders":{}}}}

Keep the good work btw!
Thanks

mysql

Hi, how is difficult to convert this prj to use mysql?

Gulp seed not working on first go. Windows 10

.env file =
SMTP_PASSWORD=secret
PORT=8000

typed in command gulp seed

C:\xampp\htdocs\angular4\hapi\hapi-university\appy\node_modules\require-dir\index.js:93
if (!require.extensions.hasOwnProperty(ext)) {
^

TypeError: require.extensions.hasOwnProperty is not a function
at requireDir (C:\xampp\htdocs\angular4\hapi\hapi-university\appy\node_modules\require-dir\index.js:93:37)
at Object. (C:\xampp\htdocs\angular4\hapi\hapi-university\appy\gulpfile.js:9:23)
at Module._compile (module.js:573:30)
at Object.Module._extensions..js (module.js:584:10)
at Module.load (module.js:507:32)
at tryModuleLoad (module.js:470:12)
at Function.Module._load (module.js:462:3)
at Module.require (module.js:517:17)
at require (internal/module.js:11:18)
at Liftoff.handleArguments (C:\Users\Owner\AppData\Roaming\npm\node_modules\gulp\bin\gulp.js:116:3)

Adding a new model object

I am having troubles adding a new model object to the appy server. I am creating a new simple model called models/task.model.js

'use strict';

module.exports = function (mongoose) {
    var modelName = "task";
    var Types = mongoose.Schema.Types;
    var Schema = new mongoose.Schema({
        description: {
            type: Types.String,
            required: true
        },
        complete: {
            type: Types.Boolean,
            required: true
        }
    }, { collection: modelName });

    Schema.statics = {
        collectionName:modelName,
        routeOptions: {

        }
    };

    return Schema;
};

And I then authenticate myself using the superadmin account and create a task like by posting the following

{
"description": "hello",
"complete": false
}

And I get this error

{
    "statusCode": 409,
    "error": "Conflict",
    "message": "There was a duplicate key error."
}

What am I doing wrong?

Thanks,
Kyle Pfromer

/login/forgot issue

Hello,
When I run api /login/forgot for the 1st time it works OK and mailed is received.
when I post again getting the following error message:

[16:46:45.291] 9613 ERROR server/api/login.js:351:15 api/Forgot Password — TypeError: internals.renderTemplate(...).then is not a function [16:46:45.291] 9613 ERROR server/api/login.js:351:15 api/Forgot Password — at Object.internals.sendEmail (/server/mailer.js:50:6) [16:46:45.291] 9613 ERROR server/api/login.js:351:15 api/Forgot Password — at /server/api/login.js:345:25 [16:46:45.291] 9613 ERROR server/api/login.js:351:15 api/Forgot Password — at process._tickDomainCallback (internal/process/next_tick.js:135:7)

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.