1
0
mirror of https://github.com/raseels-repos/golang-saas-starter-kit.git synced 2025-07-03 00:58:13 +02:00

Merge branch 'master' of gitlab.com:geeks-accelerator/oss/saas-starter-kit

This commit is contained in:
Lee Brown
2019-07-14 21:26:40 -08:00
3 changed files with 273 additions and 258 deletions

150
README.md
View File

@ -63,10 +63,21 @@ It contains the following features:
### Example project
With SaaS, a client subscribes to an online service you provide them. The example project provides functionality for
clients to subscribe and then once subscribed they can interact with your software service. For this example, *projects*
clients to subscribe and then once subscribed they can interact with your software service.
The initial contributors to this project are building this saas-starter-kit based on their years of experience building
building enterprise B2B SaaS. Particularily, this saas-starter-kit is based on their most recent experience building the
B2B SaaS for [standard operating procedure software](https://keeni.space) (100% Golang). Reference the Keeni.Space website,
its [SOP software pricing](https://keeni.space/pricing) and its signup process. The SaaS web app is then available at
[app.keeni.space](https://app.keeni.space). They plan on leveraging this experience and build it into a simplified set
example services for both a web API and a web app for SaaS businesses.
For this example, *projects*
will be the single business logic package that will be exposed to users for management based on their role. Additional
business logic packages can be added to support your project. It’s important at the beginning to minimize the connection
between business logic packages on the same horizontal level.
This project provides the following functionality to users:
New clients can sign up which creates an account and a user with role of admin.
@ -286,6 +297,9 @@ the API key for you Datadog account by setting the environmental variable: DD_AP
REST API available to clients for supporting deeper integrations. This API is also a foundation for third-party
integrations. The API implements JWT authentication that renders results as JSON to clients.
Once the web-app service is running it will be available on port 3001.
http://127.0.0.1:3001/
This web-api service is not directly used by the web-app service to prevent locking the functionally required for
internally development of the web-app service to the same functionality exposed to clients via this web-api service.
This separate web-api service can be exposed to clients and be maintained in a more rigid/structured process to manage
@ -297,19 +311,6 @@ the additional effort as the internal API can handle more flexible updates.
For more details on this service, read [web-api readme](https://gitlab.com/geeks-accelerator/oss/saas-starter-kit/blob/master/cmd/web-api/README.md)
### Making Requests to Web API
Once the web-api service is running it will be available on port 3000.
http://127.0.0.1:3001/
The easiest way to make requests to the web-api service is by using CURL via your CLI.
To make a request to the web-api service you must have an authenticated user. Users can be created with the API but an
initial admin user must first be created. The initial admin user can easily be created using the Swagger API documentation.
### API Documentation
Documentation for this API service is automatically generated using [swag](https://github.com/swaggo/swag). Once this
@ -318,84 +319,6 @@ web-api service is running, it can be accessed at /docs
http://127.0.0.1:3001/docs/
#### Initalize the database.
The database is created but does not include any schema when first started.
```bash
cd tools/schema/
source sample.env
go run main.go
```
#### Creating Initial User
Create an initial user service first using the signup endpoint documented at /docs
Find the endpoint for signup:
```
POST ​/signup Signup handles new account creation.
```
Click the button to Try it Out. Then adjust the values for the account and user objects accordingly.
```json
{
"account": {
"address1": "5445 Coolr Way",
"address2": "Box #1935",
"city": "Valdez",
"country": "USA",
"name": "Geeks on a Lake",
"region": "AK",
"timezone": "America/Anchorage",
"zipcode": "99686"
},
"user": {
"email": "twin@example.com",
"name": "Gabi May",
"password": "SecretString",
"password_confirm": "SecretString"
}
}
```
Then click button Execute, which will return the CURL command and execute the call.
Example CURL command:
```bash
curl -X POST "http://127.0.0.1:3001/v1/signup" -H "accept: application/json" -H "Content-Type: application/json" -d "{ \"account\": { \"address1\": \"221 Tatitlek Ave\", \"address2\": \"Box #1832\", \"city\": \"Valdez\", \"country\": \"USA\", \"name\": \"Geeks on a Lake\", \"region\": \"AK\", \"timezone\": \"America/Anchorage\", \"zipcode\": \"99686\" }, \"user\": { \"email\": \"twin@example.com\", \"name\": \"Gabi May\", \"password\": \"SecretString\", \"password_confirm\": \"SecretString\" }}"
```
If successful, data should be returned for code 201.
You will now be able to use the email and password credentials to generate an auth token with the web-api service.
#### Authenticating
Before any authenticated requests can be sent you must acquire an auth token. Make a request using HTTP Basic auth with
your email and password to get an auth token.
```bash
curl --user "twin@example.com:SecretString" -X POST http://127.0.0.1:3001/v1/oauth/token
```
It is best to put the resulting token in an environment variable like `$TOKEN`.
#### Adding Token as Environment Variable
```bash
export TOKEN="COPY TOKEN STRING FROM LAST CALL"
```
#### Authenticated Requests
To make authenticated requests put the token in the `Authorization` header with the `Bearer ` prefix.
```bash
curl -H "Authorization: Bearer ${TOKEN}" http://127.0.0.1:3001/v1/users
```
## Web App
[cmd/web-app](https://gitlab.com/geeks-accelerator/oss/saas-starter-kit/tree/master/cmd/web-app)
@ -404,7 +327,7 @@ direct interaction with clients and their users. It allows clients to sign up ne
authentication with HTTP sessions. The web app relies on the Golang business logic packages developed to provide an API
for internal requests.
Once the web-app service is running it will be available on port 80.
Once the web-app service is running it will be available on port 3000.
http://127.0.0.1:3000/
While the web-api service is rocking, this web-app service is still in development. Only the signup functionality works
@ -414,47 +337,6 @@ If you would like to help, please email twins@geeksinthewoods.com.
For more details on this service, read [web-app readme](https://gitlab.com/geeks-accelerator/oss/saas-starter-kit/blob/master/cmd/web-app/README.md)
### Functionality of Web App
The example web-app service is going to allow users to manage checklists. Users with role of admin will be allowed to
create new checklists (projects). Each checklist will have tasks (items) associated with it. Tasks can be assigned to
users with access to the checklist. Users can then update the status of a task.
We are referring to "checklists" as "projects" and "tasks" as "items" so this example web-app service will be generic
enough for you to leverage and build upon without lots of renaming.
This web-app service eventually will include the following functionality and corresponding web pages:
- authentication
- signup (creates user and account records)
- login
- with role-based access
- logout
- forgot password
- user management
- update user and password
- account management
- update account
- manage user
- view user
- create and invite user
- update user
- projects (checklists)
- index of projects
- browse, filter, search
- manage projects
- view project
- with project items
- create project
- update project
- user access
- project items (tasks)
- view item
- create item (adds task to checklist)
- update item
## Schema
[cmd/schema](https://gitlab.com/geeks-accelerator/oss/saas-starter-kit/tree/master/cmd/schema)

View File

@ -9,10 +9,31 @@ accelerator@geeksinthewoods.com.com
Web API is a client facing API. Standard response format is JSON.
**Not all CRUD methods are exposed as endpoints.** Only endpoints that clients may need should be exposed. Internal
services should communicate directly with the business logic packages or a new API should be created to support. This
services should communicate directly with the business logic packages or a new API should be created to support it. This
separation should help decouple client integrations from internal application development.
## Making Requests to Web API
Once the web-api service is running it will be available on port 3000.
http://127.0.0.1:3001/
The easiest way to make requests to the web-api service is by using CURL via your CLI.
To make a request to the web-api service you must have an authenticated user. Users can be created with the API but an
initial admin user must first be created. The initial admin user can easily be created using the Swagger API documentation.
## API Documentation
Documentation for this API service is automatically generated using [swag](https://github.com/swaggo/swag). Once this
web-api service is running, it can be accessed at /docs
http://127.0.0.1:3001/docs/
## Local Installation
### Build
@ -29,135 +50,189 @@ To build using the docker file, need to be in the project root directory. `Docke
docker build -f cmd/web-api/Dockerfile -t saas-web-api .
```
## Getting Started
1. Ensure postgres is running.
Navigate to the project root where `docker-compose.yaml` exists. There is only
###1. Ensure dependant services are running.
Navigate to the project root where `docker-compose.yaml` exists. There is only
one `docker-compose.yaml` file that is shared between all services.
*Start Postgres.*
```bash
docker-compose up -d postgres
```
*Start Services.*
```bash
docker-compose up -d
```
2. Set env variables.
*Copy the sample file to make your own copy.*
```bash
cp sample.env local.env
```
*Make any changes to your copy of the file if necessary and then add them to your env.
```bash
source local.env
```
1.1. Set env variables.
3. Start the web-api service.
*Invoke main.go directly or use `go build .`*
```bash
go run main.go
```
4. Open the Swagger UI.
*Copy the sample file to make your own copy.*
```bash
cp sample.env local.env
```
*Make any changes to your copy of the file if necessary and then add them to your env.
```bash
source local.env
```
Navigate your browser to [http://127.0.0.1:3001/docs](http://127.0.0.1:3001/docs).
5. Signup a new account.
1.2. Start the web-api service.
Find the `signup` endpoint in the Swagger UI.
Click `Try it out`. Example data has been prepopulated
to generate a valid POST request.
```json
{
"account": {
"address1": "221 Tatitlek Ave",
"address2": "Box #1832",
"city": "Valdez",
"country": "USA",
"name": "Company 895ff280-5ed9-4b09-b7bc-86ab0f0951d4",
"region": "AK",
"timezone": "America/Anchorage",
"zipcode": "99686"
},
"user": {
"email": "90873f61-663e-43d1-8f0c-00415e73f650@example.com",
"name": "Gabi May",
"password": "SecretString",
"password_confirm": "SecretString"
}
}
```
**Note the user email and password from the request to be used in the following steps.**
Click `Execute` and a response with status code 200 should have been returned.
```json
{
"account": {
"id": "baae6e0d-29ae-456f-9648-44c1e90ca8af",
"name": "Company 895ff280-5ed9-4b09-b7bc-86ab0f0951d4",
"address1": "221 Tatitlek Ave",
"address2": "Box #1832",
"city": "Valdez",
"region": "AK",
"country": "USA",
"zipcode": "99686",
"status": "active",
"timezone": "America/Anchorage",
"signup_user_id": {
"String": "bfdc5ca9-872c-4417-8030-e1b4962a107c",
"Valid": true
},
"billing_user_id": {
"String": "bfdc5ca9-872c-4417-8030-e1b4962a107c",
"Valid": true
},
"created_at": "2019-06-25T11:00:53.284Z",
"updated_at": "2019-06-25T11:00:53.284Z"
},
"user": {
"id": "bfdc5ca9-872c-4417-8030-e1b4962a107c",
"name": "Gabi May",
"email": "90873f61-663e-43d1-8f0c-00415e73f650@example.com",
"timezone": "America/Anchorage",
"created_at": "2019-06-25T11:00:53.284Z",
"updated_at": "2019-06-25T11:00:53.284Z"
}
}
```
6. Generate an Auth Token
An auth token is required for all other requests.
Near the top of the Swagger UI locate the button `Authorize` and click it.
Find the section `OAuth2Password (OAuth2, password)`
Enter the user email and password.
Change the type to `basic auth`
Click the button `Authorize` to generate a token that will be used by the Swagger UI for all future requests.
7. Test Auth Token
*Invoke main.go directly or use `go build .`*
```bash
go run main.go
```
Now that the Swagger UI is authorized, try running endpoint using the oauth token.
Find the endpoint GET `/accounts/{id}` endpoint in the Swagger UI. This endpoint should return the account by ID.
Click `Try it out` and enter the account ID from generated from signup (step 5).
Click `Execute`. The response should be of an Account.
## API Documentation
###2. Initialize the MySQL database.
When `docker-compose up` if first ran, as discussed in the main readme, the database is created but does not include
any schema.
Thus, you need to use the project's schema tool to initialize the database. To do this navigate the the tools/schema
folder. Add the source to your env. Then run the `main.go` file for schema.
```bash
cd tools/schema/
source sample.env
go run main.go
```
###3. Open the Swagger UI.
Navigate your browser to [http://127.0.0.1:3001/docs](http://127.0.0.1:3001/docs).
###4. Signup a new account.
Find the `signup` endpoint in the Swagger UI.
Click `Try it out`. Example data has been pre-populated to generate a valid POST request. Your can adjust the values
for the account and user objects accordingly.
```json
{
"account": {
"address1": "221 Tatitlek Ave",
"address2": "Box #1832",
"city": "Valdez",
"country": "USA",
"name": "Company 895ff280-5ed9-4b09-b7bc-86ab0f0951d4",
"region": "AK",
"timezone": "America/Anchorage",
"zipcode": "99686"
},
"user": {
"email": "90873f61-663e-43d1-8f0c-00415e73f650@example.com",
"name": "Gabi May",
"password": "SecretString",
"password_confirm": "SecretString"
}
}
```
**Note the user email and password from the above request will be used in the following steps.**
Click `Execute` and a response with status code 201 should have been returned.
```json
{
"account": {
"id": "baae6e0d-29ae-456f-9648-44c1e90ca8af",
"name": "Company 895ff280-5ed9-4b09-b7bc-86ab0f0951d4",
"address1": "221 Tatitlek Ave",
"address2": "Box #1832",
"city": "Valdez",
"region": "AK",
"country": "USA",
"zipcode": "99686",
"status": "active",
"timezone": "America/Anchorage",
"signup_user_id": {
"String": "bfdc5ca9-872c-4417-8030-e1b4962a107c",
"Valid": true
},
"billing_user_id": {
"String": "bfdc5ca9-872c-4417-8030-e1b4962a107c",
"Valid": true
},
"created_at": "2019-06-25T11:00:53.284Z",
"updated_at": "2019-06-25T11:00:53.284Z"
},
"user": {
"id": "bfdc5ca9-872c-4417-8030-e1b4962a107c",
"name": "Gabi May",
"email": "90873f61-663e-43d1-8f0c-00415e73f650@example.com",
"timezone": "America/Anchorage",
"created_at": "2019-06-25T11:00:53.284Z",
"updated_at": "2019-06-25T11:00:53.284Z"
}
}
```
If successful, data should be returned for code 201 for created.
Now you will now be able to use the email and password credentials to generate an auth token with the web-api service.
###5. Generate an Auth Token
An auth token is required for all other requests.
Near the top of the Swagger UI locate the button `Authorize` and click it.
Find the section `OAuth2Password (OAuth2, password)`
Enter the user email and password.
Change the type to `basic auth`
Click the button `Authorize` to generate a token that will be used by the Swagger UI for all future requests.
###6. Test Auth Token
Now that the Swagger UI is authorized, try running endpoint using the oauth token.
Find the endpoint GET `/accounts/{id}` endpoint in the Swagger UI. This endpoint should return the account by ID.
Click `Try it out` and enter the account ID from generated from signup (step 5).
Click `Execute`. The response should be of an Account.
###Authenticating Directly with Web API
If you want to authenticate directly with this web-api service and not via the Swagger UI, use the following steps.
####1. Authenticating
Before any authenticated requests can be sent you must acquire an auth token. Make a request using HTTP Basic auth with
your email and password to get an auth token.
```bash
curl --user "twin@example.com:SecretString" -X POST http://127.0.0.1:3001/v1/oauth/token
```
It is best to put the resulting token in an environment variable like `$TOKEN`.
####2. Adding Token as Environment Variable
```bash
export TOKEN="COPY TOKEN STRING FROM LAST CALL"
```
####3. Authenticated Requests
To make authenticated requests put the token in the `Authorization` header with the `Bearer ` prefix.
```bash
curl -H "Authorization: Bearer ${TOKEN}" http://127.0.0.1:3001/v1/users
```
## Update Swagger API Documentation
Documentation is generated using [swag](https://github.com/swaggo/swag)
Download swag by using:
If you are developing this web-api service and you want your changes reflected in the API documentation, you will need
to download Swag and then run it each time you want the API documentation to be updated.
Download Swag with this command:
```bash
go get -u github.com/swaggo/swag/cmd/swag
```
@ -167,7 +242,7 @@ Run `swag init` in the service's root folder which contains the main.go file. Th
swag init
```
### Additional Annotations
### Additional Swagger Annotations
Below are some additional example annotions that can be added to `main.go`
```go
@ -180,12 +255,10 @@ Below are some additional example annotions that can be added to `main.go`
// @contact.url http://example.com/support
```
### Trouble shooting
### Troubleshooting Swag
If you run into errors running `swag init` try the following:
#### cannot find package
Try to install the packages to your $GOPATH.
@ -213,4 +286,6 @@ sudo chown -R $(whoami):staff ${HOME}/go/pkg
sudo chmod -R 755 ${HOME}/go/pkg
```

View File

@ -1,12 +1,70 @@
# SaaS Web App
Copyright 2019, Geeks Accelerator
accelerator@geeksinthewoods.com.com
accelerator@geeksinthewoods.com
## Description
Provides an http service.
Responsive web application that renders HTML using the `html/template` package from the standard library to enable
direct interaction with clients and their users. It allows clients to sign up new accounts and provides user
authentication with HTTP sessions. The web app relies on the Golang business logic packages developed to provide an API
for internal requests.
Once the web-app service is running it will be available on port 3000.
http://127.0.0.1:3000/
While the web-api service has
significant functionality, this web-app service is still in development. Currently this web-app services only resizes
an image and displays resvised versions of it on the index page. See section below on Future Functionality.
If you would like to help, please email twins@geeksinthewoods.com.
### Future Functionality
This example Web App is going to allow users to manage checklists. Users with role of admin will be allowed to
create new checklists (projects). Each checklist will have tasks (items) associated with it. Tasks can be assigned to
users with access to the checklist. Users can then update the status of a task.
We are referring to "checklists" as "projects" and "tasks" as "items" so this example web-app service will be generic
enough for you to leverage and build upon without lots of renaming.
The initial contributors to this project created a similar service like this: [standard operating procedure software](https://keeni.space/procedures/software)
for Keeni.Space. Its' Golang web app for [standard operating procedures software](https://keeni.space/procedures/software) is available at [app.keeni.space](https://app.keeni.space) They plan on leveraging this experience and boil it down into a simplified set of functionality
and corresponding web pages that will be a solid examples for building enterprise SaaS web apps with Golang.
This web-app service eventually will include the following:
- authentication
- signup (creates user and account records)
- login
- with role-based access
- logout
- forgot password
- user management
- update user and password
- account management
- update account
- manage user
- view user
- create and invite user
- update user
- projects (checklists)
- index of projects
- browse, filter, search
- manage projects
- view project
- with project items
- create project
- update project
- user access
- project items (tasks)
- view item
- create item (adds task to checklist)
- update item
## Local Installation