Code Monkey home page Code Monkey logo

api's Introduction

Staart API

Staart API is a Node.js backend starter for SaaS startups written in TypeScript. It has all the features you need to build a SaaS product, like user management and authentication, billing, organizations, GDPR tools, API keys, rate limiting, superadmin impersonation, and more.

Status
Build Node CI Snyk Vulnerabilities for GitHub Repo Dependencies Dev dependencies
PRs Pull Request Labeler PR Generator CI Merge PRs
Community Contributors GitHub Type definitions npm package version semantic-release

Staart API is build to work with Staart UI, the frontend PWA starter for SaaS startups.

โš ๏ธ v3 BETA WARNING: The master branch and all 3.x releases are currently in beta. For production, use v1.x instead.

โญ Features

๐Ÿ†• New in v2

  • Casbin-powered permission management
  • JWT-powered single-use coupon codes
  • Redis-powered queues for outbound emails and logs
  • Cloud agnostic, no longer specific to AWS
  • Staart scripts for building and deploying
  • Async JSON response and smart controller injection

๐Ÿ” Security

  • JWT-powered authentication and user management
  • TOTP-powered two-factor authentication (2FA)
  • OAuth2 login with third-party accounts
  • Location-based login verification
  • Security event logging and history

๐Ÿ’ณ SaaS

  • Stripe-powered recurring billing
  • Teams with managed user permissions
  • CRUD invoices, methods, transactions, etc.
  • Rich HTML transactional emails
  • GDPR-compliant data export and delete
  • API gateway with API keys and rate limiting
  • Domain verification with auto-approve members

๐Ÿ‘ฉโ€๐Ÿ’ป Developer utilities

  • OvernightJS-powered decorators and class syntax
  • Injection-proof helpers for querying databases
  • Data pagination and CRUD utilities for all tables
  • Authorization helpers
  • Caching and invalidation for common queries
  • User impersonation for super-admin
  • Easy redirect rules in YAML
  • ElasticSearch-powered server and event logs

๐Ÿ›  Usage

  1. Use this template or fork this repository
  2. Install dependencies with npm install
  3. Add a .env file based on config.ts.
  4. Create MariaDB/MySQL tables based on schema.sql
  5. Add your controllers in the ./src/controllers directory
  6. Generate your app.ts file using staart controllers
  7. Build with staart build and deploy with staart launch

Updating Staart

To update your installation of Staart, run the following:

staart update api

If you've used the "Use this template" option on GitHub, you might have to force pull from staart/api the first time since the histories wouldn't match. You can use the flag --allow-unrelated-histories in this case.

๐Ÿ’ป Docs

View docs site โ†’

View TypeDoc โ†’

View API demo โ†’

View frontend demo โ†’

๐Ÿ—๏ธ Built with Staart

The Staart ecosystem consists of open-source projects to build your SaaS startup, written in TypeScript.

Package
๐Ÿ› ๏ธ Staart API Node.js backend with RESTful APIs Build status Docs npm package version
๐ŸŒ Staart UI Frontend Vue.js Progressive Web App Build status Docs npm package version
๐Ÿ“‘ Staart Site Static site generator for docs/helpdesk Build status Docs npm package version
๐Ÿ“ฑ Staart Native React Native app for Android and iOS Build status Docs npm package version
๐ŸŽจ Staart.css Sass/CSS framework and utilities Build status Docs npm package version
๐Ÿ“ฆ Staart Packages Helper functions and utility packages Build status Custom badge

๐Ÿ’ Sponsors

The development of Staart projects is supported by these wonderful companies. Find us on OpenCollective


Oswald Labs

O15Y

Speakup

Netlify

Koj

๐Ÿ“„ License

api's People

Contributors

allcontributors[bot] avatar anandchowdhary avatar dependabot-preview[bot] avatar dependabot-support avatar dependabot[bot] avatar ektek avatar findinganand avatar imgbotapp avatar kuttim avatar semantic-release-bot avatar snyk-bot 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  avatar  avatar  avatar  avatar  avatar

api's Issues

Feature: Check input against regular expression

Regular expressions could be for Name (only alpha letters), Password (strong password with special characters, minimum length), Domain name (occurrence of dot) etc.

Better if we display the Password Strength meter.

Confirm password before performing security tasks

When performing actions like deleting your account, deleting your team, canceling a subscription, etc., the popup should ask for the user's password, and the API should check for password.

A helper function can be built and used:@Middleware(ConfirmPassword)

Trim the whitespace characters

For instance, Settings > Name Just Enter the whitespace characters and it allows them.

I believe we need to trim almost every input field.

Check TypeScript Babel compilation warning

Currently, TypeScript with Babel throws this warning during compilation:

โ˜  pending   Compiling TypeScript
.staart/src/__staart.ts(2,34): error TS7016: Could not find a declaration file for module 'regenerator-runtime'. '/Users/smoujami/projects/dukketta/staart/migration/api/.staart/node_modules/regenerator-runtime/runtime.js' implicitly has an 'any' type.
  Try `npm install @types/regenerator-runtime` if it exists or add a new declaration (.d.ts) file containing `declare module 'regenerator-runtime';`
โœ”  success   Listening on 8080

Originally reported in #1046 by @simoami

Add `cuid` for all tables

Tables that have username, like organization and user, already have a human-readable key (apart from autoincrementing ID).

  • All tables apart from those can have cuid as the column name and default value cuid()
  • The default value for username can also be cuid unless a better one is available
  • API keys can use cuid instead of JWT etc.

REFERRER_CHECK_FAIL error verifying JWT token

Release: 1.0.130

I get an error REFERRER_CHECK_FAIL error when verifying the JWT Token.

Contents of apiKeyToken.referrerRestrictions:

0:"staart-demo.o15y.com"
1:"localhost"
2:"oswaldlabs.com"
3:"staart-ui.o15y.now.sh"

It tries to match 127.0.0.1 but fails.

What I don't understand is how and where these are set, since I can't find them searching the codebase.

MySQL: ER_NOT_SUPPORTED_AUTH_MODE

Leaving this for any user who comes across this (using MySQL 8.0=<). Be aware that the backend might throw the following error:

Error: ER_NOT_SUPPORTED_AUTH_MODE: Client does not support authentication protocol requested by server; consider upgrading MySQL client

You'll have to switch over to mysql_native_password

ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY 'password';
FLUSH PRIVILEGES;

Leaking email to Gravatar.

I have noticed that this leaks email hashes to gravatar. Given Gravatar is quite a old service, I wonder if it better to just allow users to upload thier own profile images (or not).

Check for conflicting usernames in register

Hi Anand, here is the behaviour we're seeing now

User registers and verifies email - works fine now
User tries to login - immediately presented with a "You dont have permission to perform this action"....
Press F5 to refresh and it looks like the user is logged in -
However, when I start to click on the user icon the top right and select team or user settings - it keeps presenting us with this "You dont have permission".

Must be something we are not doing?

image

{"error":"From is required"} after fresh install

I just install Staart and i get this error when i register the first user.

{"error":"From is required"}

I think is linked to problem with email. It is normal that the row primaryEmail have int(12) in staart-users ?

Ability to merge accounts

Hi @AnandChowdhary
Thanks for your great implementation! One area I was wondering about is the ability to merge 2 user accounts belonging to the same user. There are 2 scenarios in which a merge can apply.

1. Before joining an invite

You already have this covered through the email record resolution.

2. After joining an invite

Two or more user records would have been created by then. so it would be great to have to ability to allow the user to merge into one of the user records.

Coincidentally, I found a saas app with similar concept but I'm not convinced that their approach works in consolidating user data. From their steps, I guess they only map an email back to the first user. But that still leave the second user as a disconnected record.

https://help.clubhouse.io/hc/en-us/articles/211154966-Merging-User-Accounts-in-Clubhouse

Would love to hear your thoughts!

Admin View

There is some mention of a super user login, from what I can see this seems to allow this user to login and access all 'teams' is that correct?

Is there any plan to create a admin dashboard where members of the team can view summery data and make changes on behalf of users?

Implementing/Using a Reseller Model

Hi there,

I am working on extending some business logic so that resellers can be supported. In this case a Reseller can create a org, invite the end customer to be the org owner and then the reseller picks up the bill with billing disabled for the end user.

I noticed references to the naming of a role as reseller. I am curious if others are already doing something similar are if there are plans to build in reseller logic and roles which I can work on rather than starting from scratch.

Return created objects

As per the suggestion of @victorlap, methods which create a new organization/user/membership/etc., should return the newly created object.

This, combined with the right HTTP status code 201, can be better than just returning { created: true }.

Feature: Trial Period and Days Left

Hi

Looks like the work is in progress. Good job!

I believe an important feature is missing, There should be a flag in config file, namely, Trial Period. Let us say, we set it to 15 days. So the app should be accessible for free for that period.

Also, the system should notify (by email and instant notification both) that your subscription is about to expire in DAYS_LEFT time.

Thanks

logo contribution

Hi @AnandChowdhary I am a logo designer.

I contribute to open source projects that do not have logo. I have designed a logo for staart. The logo idea also represents the function of the software. What do you think?

staart

Use caching library instead of Redis

Use a Node.js caching library (like node-cache or node-cache-manager) for JWT invalidation, etc., instead of Redis directly, with Redis as the primary kv-store with in-memory as fallback

Cron to delete logs

Under the GDPR, it's a good idea to delete logs periodically, especially when they have information like IP address and user agent.

We use the same logs as both server logs for admins and API key logs for end users, and they can be limited to the past 3 months. A cron job to delete all logs before 3 months can run every day or every week etc.

API requests timing out (not returning JSON object)

@AnandChowdhary
My requests are hanging.

curl -X POST http://localhost:8080/v1/auth/login -H 'Content-Type: application/json' -d '{"email":"[email protected]","password":"..."}'

Not sure if this is work in progress for the migration to Nest, but currently returning payload causes requests to time out. Using the latest in master.

Overnightjs expects this response:

@Post()
private handler(req: Request, res: Response) {
  return res.status(200).json({
    message: 'test',
  });
}

but the current code returns the raw payload:

@Post()
private handler(req: Request, res: Response) {
  return {
    message: 'test',
  }
}

Feature: Restricting the list of allowable domains

Email domain: Enter your company's domain, eg. oswaldlabs.com
We'll allow people with emails from this domain to join this organization automatically

Do not allow the public domains to be included in this list like gmail, hotmail, rediffmail, and many others.

New member cannot log into the system

Invite a team member [email protected]
A verification link is sent successfully and he verifies the link.
He is taken to a Login page where he is asked to enter a password but he doesn't have any password so far.

Probable Solution: Create another page where he can set his "new" password.

Use Casbin to manage user permissions

Hi @AnandChowdhary ,

At the moment the permissions hierarchy isn't well enforced as for example: when creating a new user on a organisation a manager can create an owner - so at any point anyone with permissions to CRUD team members can escalate themselves to owner by inviting one of their other email addresses. Would it be a reasonable idea to add some logic which says that users can only invite new members to a team with a permission level of lower than their own permission level, unless they are a team owner in which case that logic doesn't apply (i.e they can create other owners too)? This would mean say.. a business owner authorises/creates all new manager accounts, a manager authorises/creates all new 'basic employee' accounts? A business owner can add other business owners as they see fit, but a manager cannot add another manager or escalate himself or others to owner.

Also the edit member ui on that page is broken, I was thinking of coming back to that after I discussed the permissions with you.

Install on Ubuntu is failing at "npm run build"

hello

I've tried to install. First the use my template buttom gave an error about files being more than 10mb so I downloaded to my desktop and went through the manual process to get it setup;

I get this error though and npm run build stage. Any ideas?

root@staartsaas:/srv/staartapp# sudo npm run build

[email protected] build /srv/staartapp
touch .env && mkdir -p dist && cp .env dist/.env && npm run generate-routes && tsc && cp -r lfs dist/src

[email protected] generate-routes /srv/staartapp
node setup/controllers.js

โœ– error Error in setup [Error: ENOENT: no such file or directory, scandir '/srv/staartapp/src/controllers'] {
errno: -2,
code: 'ENOENT',
syscall: 'scandir',
path: '/srv/staartapp/src/controllers'
}

Include an .env.example

Altough it is easy to understand from the config.ts file which options are available, i always really like an example configuration file for clarity

Issues with Security Features

Hi there,
Thank you for all your work so far on this project.

I have come across a few issues with some security features that are included not functioning.
For example;

IP address restrictions - These are not actually restricting access to specified IP ranges (For example on the team view).
Invalidate session - Does not seem to 'log you out of this session in the next few minutes'.

The view for editing a users permissions with relation to a team also seems to not exist. Has anyone else come across these issues? If not I will examine in further detail and submit a PR for fixes, but I don't want to waste time if this is a known issue and someone else is working on a fix or it is a common config issue my side.

CORS config parameter parsing

Hi @AnandChowdhary
It took me a while to get the app set up locally after the recent updates. The issue was that all xhr requests were failing because CORS couldn't be enabled even with proper config.

curl -v 'http://localhost:8080/v1/auth/login' -X OPTIONS -H 'Access-Control-Request-Method: POST'
--
< HTTP/1.1 200 OK
< X-DNS-Prefetch-Control: off
< X-Frame-Options: SAMEORIGIN
< Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
< X-Download-Options: noopen
< X-Content-Type-Options: nosniff
< X-XSS-Protection: 1; mode=block
< X-Api-Version: 1.3.147
< X-RateLimit-Limit-Type: public
< X-RateLimit-Limit: 60
< X-RateLimit-Remaining: 59
< Date: Mon, 16 Mar 2020 17:36:24 GMT
< X-RateLimit-Reset: 1584380244
< Allow: POST
< Content-Type: text/html; charset=utf-8
< Content-Length: 4
< ETag: W/"4-Yf+Bwwqjx254r+pisuO9HfpJ6FQ"
< X-Response-Time: 6.500ms
< Connection: keep-alive

didn't return the necessary headers to allow requests to be sent from the UI.

My .env config:

# Remove CORS headers without API key
DISALLOW_OPEN_CORS = false

Upon close inspection, it looks like the value false was coming in as a string so it failed the condition here: https://github.com/staart/packages/blob/master/packages/server/index.ts#L52

Screen Shot 2020-03-16 at 1 40 52 PM

Also a side issue during compilation:

โ˜  pending   Compiling TypeScript
.staart/src/__staart.ts(2,34): error TS7016: Could not find a declaration file for module 'regenerator-runtime'. '/Users/smoujami/projects/dukketta/staart/migration/api/.staart/node_modules/regenerator-runtime/runtime.js' implicitly has an 'any' type.
  Try `npm install @types/regenerator-runtime` if it exists or add a new declaration (.d.ts) file containing `declare module 'regenerator-runtime';`
โœ”  success   Listening on 8080

Queue outbound emails

Use rsmq to queue ongoing Nodemailer messages if Redis is available, otherwise directly send!

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.