Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve the README.md and Enhanced Integration Tests #51

Open
wants to merge 18 commits into
base: dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 26 additions & 3 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,5 +1,28 @@
# Build and up targets for all profiles in development environment
dev-all: dev-up-all

integration-test: ### Run docker-compose with integration test
bash ./integration-test.sh
dev-up-all:
@./dev-env.sh all

.PHONY: integration-test
dev-up-starlabs:
@./dev-env.sh starlabs

dev-up-tests:
@./dev-env.sh tests

dev-up-kafka:
@./dev-env.sh kafka

dev-up-backend:
@./dev-env.sh backend

dev-up-frontend:
@./dev-env.sh frontend

dev-stop:
docker-compose -f dev.docker-compose.yml down --remove-orphans

dev-destroy:
docker-compose -f dev.docker-compose.yml down -v --remove-orphans

.PHONY: dev-all dev-up-all dev-up-starlabs dev-up-tests dev-up-kafka dev-up-backend dev-up-frontend dev-stop dev-destroy
73 changes: 64 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ enterprise-grade token management. Dive deep into the core
functionalities of the Stellar network, specifically tailored for
asset issuance.


Stellar Asset Sandbox is composed by:

- [Postgres](https://www.postgresql.org/): relational database
- [Apache Kafka](https://kafka.apache.org/): Distributed event store
- [UI for Apache Kafka](https://github.com/provectus/kafka-ui): open-source web UI to monitor and manage Apache Kafka clusters
Expand All @@ -29,6 +29,7 @@ Stellar Asset Sandbox is composed by:
- [Docker Desktop Recommendations](#docker-desktop-recommendations)
- [Git Submodules](#git-submodules)
- [Running application locally](#running-application-locally)
- [Kafka Topics & Communication Flows](#kafka-topics-&-communication-flows)
- [Features](#features)
- [Role-based Access and Custody](#role-based-access-and-custody)
- [Token Management in the Sandbox](#token-management-in-the-sandbox)
Expand All @@ -47,14 +48,16 @@ Stellar Asset Sandbox is composed by:
## Docker Desktop Recommendations

To run this project, there are some recommendations about the Docker Desktop resources configuration. You can find how to edit the resources settings [here](https://docs.docker.com/desktop/settings/mac/#resources).
* CPUs: 4
* Memory: 8GB

- CPUs: 4
- Memory: 8GB

## Git Submodules

This project is using Git Submodules, that allow to keep a Git repository as a subdirectory of another Git repository. Currently, there is one submodule used in this project:
* [Starlabs](./starlabs/)
* [Stellar-KMS](./stellar-kms/)

- [Starlabs](./starlabs/)
- [Stellar-KMS](./stellar-kms/)

### Pull

Expand All @@ -75,7 +78,7 @@ git commit -m "Upgrade to latest version"

```bash
cd packages/starlabs
git checkout <version>
git checkout <version>
git add .
git commit -m "Upgrade to specific version"
```
Expand All @@ -91,9 +94,10 @@ To start all the applications locally, follow these steps:
```bash
$ docker-compose -f dev.docker-compose.yml --profile starlabs build
$ docker-compose -f dev.docker-compose.yml --profile starlabs up
```
```

**3.** Run the backend from the `backend` folder:

```bash
$ go run .
```
Expand All @@ -108,7 +112,7 @@ $ make start_dev

```bash
$ POST http://127.0.0.1:8080/v1/wallets
$ Body:
$ Body:
{
"type" : "sponsor"
}
Expand All @@ -118,12 +122,62 @@ $ Body:

```bash
$ POST http://127.0.0.1:8080/v1/wallets/fund
$ Body:
$ Body:
{
"id" : 1
}
```

### **Kafka Topics & Communication Flows**

Apache Kafka plays a vital role in the Cheesecake Stellar Token Factory - V2 by enabling asynchronous data processing and efficient communication among components. Below are key Kafka topics and their communication pathways:

#### **Backend to Stellar KMS**:

- **`generateKeypair`**:
- **Purpose**: Generate a new Stellar key pair.
- **Usage**: Triggered when a new key pair is required.

#### **Stellar KMS to Backend**:

- **`generatedKeypairs`**:
- **Purpose**: Announce a newly generated key pair.
- **Usage**: Used after a key pair is stored securely.

#### **Backend to Starlabs**:

- **`createEnvelope`**:

- **Purpose**: Handle transaction envelope creation.
- **Usage**: Process messages detailing transactions for envelope generation.

- **`horizonRequest`**:
- **Purpose**: Manage GET requests to the Stellar Horizon server.
- **Usage**: Fetch account or transaction details.

#### **Starlabs to KMS**:

- **`signEnvelope`**:
- **Purpose**: Handle transaction envelope signing requests.
- **Usage**: Process unsigned transaction envelopes awaiting signatures.

#### **KMS to Starlabs**:

- **`signedEnvelopes`**:
- **Purpose**: Communicate signed transaction envelopes.
- **Usage**: Services monitoring signed envelopes use this topic.

#### **Starlabs to Backend**:

- **`horizonResponse`**:

- **Purpose**: Relay Stellar Horizon server responses.
- **Usage**: Communicate fetched account data and other Horizon responses.

- **`submitResponse`**:
- **Purpose**: Report transaction results from the Stellar network.
- **Usage**: Communicate transaction results.

## Features

## Role-based Access and Custody
Expand Down Expand Up @@ -166,6 +220,7 @@ managing tokens on the Stellar network, demonstrating the flexibility
and potential of the platform.

## Treasury Management in the Sandbox

The Stellar Asset Issuance Sandbox introduces a robust treasury
management system, empowering treasurers with the tools they need to
efficiently handle assets:
Expand Down
193 changes: 193 additions & 0 deletions backend/integration-test/01_users_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,193 @@
package integration_test

import (
"bytes"
"encoding/json"
"net/http"
"testing"

"github.com/CheesecakeLabs/token-factory-v2/backend/internal/entity"
"github.com/stretchr/testify/assert"
)

var _user = entity.User{
Name: "User Test",
Password: "123456",
RoleId: 1,
Email: "[email protected]",
}

type UserLoginResponse struct {
User entity.User `json:"user"`
}

func TestCreateUserSuccess(t *testing.T) {
createUserPath := basePath + "/users/create"

requestBodyBytes, err := json.Marshal(_user)
assert.NoError(t, err)

// Create the HTTP request
req, err := http.NewRequest(http.MethodPost, createUserPath, bytes.NewBuffer(requestBodyBytes))
assert.NoError(t, err)
req.Header.Set("Content-Type", "application/json")

// Execute the request
client := &http.Client{}
resp, err := client.Do(req)

assert.NoError(t, err)
defer resp.Body.Close()

// Verify the status code
assert.Equal(t, http.StatusOK, resp.StatusCode)

// Parsing the response into an expected structure
var response UserLoginResponse
err = json.NewDecoder(resp.Body).Decode(&response)
assert.NoError(t, err)
}

func TestUserLoginSuccess(t *testing.T) {
// URL for logging in a user
loginUserPath := basePath + "/users/login"

// Test user credentials
email := _user.Email
password := _user.Password

// Request body
requestBody := map[string]string{
"email": email,
"password": password,
}
requestBodyBytes, err := json.Marshal(requestBody)
assert.NoError(t, err)

// Create the HTTP request
req, err := http.NewRequest(http.MethodPost, loginUserPath, bytes.NewBuffer(requestBodyBytes))
assert.NoError(t, err)
req.Header.Set("Content-Type", "application/json")

// Execute the request
client := &http.Client{}
resp, err := client.Do(req)
assert.NoError(t, err)
defer resp.Body.Close()

// Verify the status code
assert.Equal(t, http.StatusOK, resp.StatusCode)

var loginResponse UserLoginResponse
err = json.NewDecoder(resp.Body).Decode(&loginResponse)
assert.NoError(t, err)

assert.NoError(t, err)
assert.Equal(t, _user.Name, loginResponse.User.Name)
assert.Equal(t, _user.Email, loginResponse.User.Email)
assert.Equal(t, _user.RoleId, loginResponse.User.RoleId)
assert.NotEmpty(t, loginResponse.User.Token)
_user.Token = loginResponse.User.Token
}

func TestCreateUserFailedUserAlreadyInDatabase(t *testing.T) {
createUserPath := basePath + "/users/create"

requestBodyBytes, err := json.Marshal(_user)
assert.NoError(t, err)

// Create the HTTP request
req, err := http.NewRequest(http.MethodPost, createUserPath, bytes.NewBuffer(requestBodyBytes))
assert.NoError(t, err)
req.Header.Set("Content-Type", "application/json")

// Execute the request
client := &http.Client{}
resp, err := client.Do(req)

assert.NoError(t, err)
defer resp.Body.Close()

// Verify the status code
assert.Equal(t, http.StatusInternalServerError, resp.StatusCode)

// Parsing the response into an expected structure
var response errorResponse
err = json.NewDecoder(resp.Body).Decode(&response)
assert.NoError(t, err)

// Verifying the response content
assert.Equal(t, "database problems", response.Message)
assert.Contains(t, response.Error, "duplicate key value violates unique constraint \"useraccount_email_key\"")
}

func TestCreateUserFailedPasswordIsEmpty(t *testing.T) {
createUserPath := basePath + "/users/create"

// Create a request body with an empty password
requestBody := entity.User{
Name: "User Test",
Password: "",
RoleId: 1,
Email: "",
}

requestBodyBytes, err := json.Marshal(requestBody)
assert.NoError(t, err)

// Create the HTTP request
req, err := http.NewRequest(http.MethodPost, createUserPath, bytes.NewBuffer(requestBodyBytes))
assert.NoError(t, err)
req.Header.Set("Content-Type", "application/json")

// Execute the request
client := &http.Client{}
resp, err := client.Do(req)
assert.NoError(t, err)
defer resp.Body.Close()

// Verify the status code
assert.Equal(t, http.StatusBadRequest, resp.StatusCode) // Adjust the status code as per your application's behavior

// Parsing the response into an expected structure
var response errorResponse
err = json.NewDecoder(resp.Body).Decode(&response)
assert.NoError(t, err)

// Verifying the response content
assert.Equal(t, "password is required", response.Message)
}

func TestUserLoginFailed(t *testing.T) {
// URL for logging in a user
loginUserPath := basePath + "/users/login"

// Request body
requestBody := entity.User{
Email: "[email protected]",
Password: "testpassword",
}
requestBodyBytes, err := json.Marshal(requestBody)
assert.NoError(t, err)

// Create the HTTP request
req, err := http.NewRequest(http.MethodPost, loginUserPath, bytes.NewBuffer(requestBodyBytes))
assert.NoError(t, err)
req.Header.Set("Content-Type", "application/json")

// Execute the request
client := &http.Client{}
resp, err := client.Do(req)
assert.NoError(t, err)
defer resp.Body.Close()

// Verify the status code
assert.Equal(t, http.StatusUnauthorized, resp.StatusCode)

// Parse and verify the response body
var response errorResponse
err = json.NewDecoder(resp.Body).Decode(&response)
assert.NoError(t, err)
assert.Equal(t, "database problems", response.Message)
assert.Equal(t, "email or password incorrect", response.Error)
}
Loading
Loading