Compare commits

..

10 Commits

Author SHA1 Message Date
Josepablo Cruz
507ca88641 chore(srs): Adding rest of endpoints and proposals 2026-04-09 09:15:42 -06:00
Josepablo Cruz
6938df70e4 chore(markdown): Adding main README and docs/software_requirements_specification.md 2026-04-07 08:19:52 -06:00
Josepablo Cruz
ebb8196be9 feat(SQL): Adding subscriptions and resource counter tables 2026-04-02 01:36:42 -06:00
Josepablo Cruz
0cc0a1cc92 feat(SQL): Adding document tables for vehicles and company and apikeys table 2026-04-01 17:39:53 -06:00
Josepablo Cruz
b73cdaa5ce feat(SQL): Adding alert groups and privacy groups 2026-04-01 14:59:24 -06:00
Josepablo Cruz
bd3fddbbc2 feat(Docker): Adding a working Dockerfile and compose to prototype 2026-04-01 14:03:20 -06:00
Josepablo Cruz
4fcd3f01a5 feat(SQL): Adding working schema script 2026-04-01 13:11:07 -06:00
Josepablo Cruz
005fad6048 feat(sql): RBAC model with api_keys and application tenants 2026-03-31 23:40:51 -06:00
Josepablo Cruz
0ca5423776 fix: end of line char 2026-03-31 21:01:07 -06:00
Josepablo C.
a95c4d023e feat: Adding openapi generated without server just models 2025-12-07 23:22:40 -06:00
32 changed files with 23736 additions and 2379 deletions

131
README.md Normal file
View File

@@ -0,0 +1,131 @@
# GoETAAPI
This repository contains the backend API and database layer for **ETA Viaporte** — a logistics marketplace platform.
> The project is currently at the **database design and infrastructure** stage. The sections below describe what is available and how to work with it.
---
## Repository Structure
```
GoETAAPI/
├── app/ # Go API source (in progress)
└── db/
├── Models/ # Schema design files (MySQL Workbench + SQL scripts)
├── container/ # Dockerfile for the MariaDB test container
└── service/ # Docker Compose + Makefile for local deployment
```
---
## DB
### Schema Design
The database schema is defined under `db/Models/` and targets the schema `u947463964_etaviaporte`.
| File | Description |
|---|---|
| `db/Models/eta_rbac.mwb` | MySQL Workbench model — open this to visualize the full schema diagram |
| `db/Models/schemas/eta_rbac.sql` | Forward-engineered SQL schema (generated from the `.mwb` model) |
| `db/Models/init/eta_rbac_init.sql` | Seed / initialization data |
| `db/Models/eta_rbac_requirements.md` | Human-readable data requirements derived from the schema constraints |
To inspect or modify the schema visually, open `db/Models/eta_rbac.mwb` with **MySQL Workbench**.
The schema covers:
- **Users & Authentication** — `users`, `auth_identities`, `verification_tokens`, `sessions`
- **RBAC** — `applications`, `roles`, `permissions`, `role_permissions`, `user_roles`
- **Companies & Locations** — `companies`, `locations`
- **Loads & Shipments** — `loads`, `vehicles`, `shipment_proposals`, `shipment_agreements`, `load_shipments`
---
### Docker Container
The image is built from `db/container/Dockerfile`. It uses **Alpine + MariaDB** and automatically generates a root password on first run. SQL files placed in `/docker-entrypoint-initdb.d` inside the container are executed on startup.
#### Build the image
Run from `db/container/`:
```sh
docker buildx build -t eta/eta-db .
```
#### Run the container (basic)
```sh
docker run --name eta-db -d -p 3306:3306 eta/eta-db
docker logs -f eta-db # root password is printed here on first boot
```
#### Run the container with a named database and user
```sh
docker run --name eta-db \
-e MYSQL_DATABASE=u947463964_etaviaporte \
-e MYSQL_USER=etaapi \
-e MYSQL_PASSWORD="secret_password" \
-d -p 3306:3306 eta/eta-db
```
#### Run with schema initialization scripts
Mount a directory of `.sql` files into `/docker-entrypoint-initdb.d` and they will be executed in order on first start:
```sh
docker run --name eta-db \
-e MYSQL_DATABASE=u947463964_etaviaporte \
-e MYSQL_USER=etaapi \
-e MYSQL_PASSWORD="secret_password" \
-v ./docker-entrypoint-initdb.d:/docker-entrypoint-initdb.d \
-d -p 3306:3306 eta/eta-db
```
> **Note:** Avoid using `"` (double quotes) in SQL scripts — use `'` (single quotes) instead. Inline comments at the end of SQL statements may also cause parsing errors.
---
### Docker Compose (local testing)
`db/service/compose.yml` deploys the `eta/eta-db` image with the schema and seed data pre-loaded. It mounts `db/service/initdb/` into the container's init directory.
Before deploying with Compose, populate `db/service/initdb/` by running `make prepare` (see below), then start the service:
```sh
cd db/service
docker compose up -d
```
The service exposes MariaDB on port `3306` with:
| Variable | Value |
|---|---|
| `MYSQL_DATABASE` | `u947463964_etaviaporte` |
| `MYSQL_USER` | `etaapi` |
| `MYSQL_PASSWORD` | `secret_password` |
> The `initdb/` volume uses the `:Z` SELinux label to avoid permission denied errors on SELinux-enabled systems.
---
### Makefile — Prepare init scripts
The `db/service/Makefile` copies the latest schema and seed files from `db/Models/` into `db/service/initdb/`, so they are picked up by Docker Compose on the next container start.
```sh
cd db/service
make prepare
```
This runs:
1. Clears any existing `.sql` files from `db/service/initdb/`.
2. Copies `db/Models/schemas/eta_rbac.sql``initdb/00-schema.sql`
3. Copies `db/Models/init/eta_rbac_init.sql``initdb/01-initdb.sql`
Always run `make prepare` after updating the schema model before bringing the Compose service up.

View File

@@ -22,3 +22,8 @@ The details on how to deploy are described here
SQL_DSN="{USER}:{PASS}@tcp({HOST}:{PORT})/{DB}?charset=utf8mb4&parseTime=true&loc=Local" SQL_DSN="{USER}:{PASS}@tcp({HOST}:{PORT})/{DB}?charset=utf8mb4&parseTime=true&loc=Local"
``` ```
# GPU information
https://en.wikipedia.org/wiki/Graphics_processing_unit ->
https://en.wikipedia.org/wiki/Shader -> https://en.wikipedia.org/wiki/RenderMan_Interface_Specification

View File

@@ -3,10 +3,6 @@
// Code generated by github.com/deepmap/oapi-codegen version v1.16.3 DO NOT EDIT. // Code generated by github.com/deepmap/oapi-codegen version v1.16.3 DO NOT EDIT.
package openapi package openapi
import (
"github.com/gofiber/fiber/v2"
)
const ( const (
BearerAuthScopes = "bearerAuth.Scopes" BearerAuthScopes = "bearerAuth.Scopes"
) )
@@ -63,85 +59,3 @@ type PostAuthLogoutJSONRequestBody = RevokeRequest
// PostAuthRefreshJSONRequestBody defines body for PostAuthRefresh for application/json ContentType. // PostAuthRefreshJSONRequestBody defines body for PostAuthRefresh for application/json ContentType.
type PostAuthRefreshJSONRequestBody = RefreshRequest type PostAuthRefreshJSONRequestBody = RefreshRequest
// ServerInterface represents all server handlers.
type ServerInterface interface {
// Obtain access and refresh tokens
// (POST /auth/login)
PostAuthLogin(c *fiber.Ctx) error
// Revoke refresh token / logout
// (POST /auth/logout)
PostAuthLogout(c *fiber.Ctx) error
// Get current authenticated user
// (GET /auth/me)
GetAuthMe(c *fiber.Ctx) error
// Refresh access token using a refresh token
// (POST /auth/refresh)
PostAuthRefresh(c *fiber.Ctx) error
}
// ServerInterfaceWrapper converts contexts to parameters.
type ServerInterfaceWrapper struct {
Handler ServerInterface
}
type MiddlewareFunc fiber.Handler
// PostAuthLogin operation middleware
func (siw *ServerInterfaceWrapper) PostAuthLogin(c *fiber.Ctx) error {
return siw.Handler.PostAuthLogin(c)
}
// PostAuthLogout operation middleware
func (siw *ServerInterfaceWrapper) PostAuthLogout(c *fiber.Ctx) error {
c.Context().SetUserValue(BearerAuthScopes, []string{})
return siw.Handler.PostAuthLogout(c)
}
// GetAuthMe operation middleware
func (siw *ServerInterfaceWrapper) GetAuthMe(c *fiber.Ctx) error {
c.Context().SetUserValue(BearerAuthScopes, []string{})
return siw.Handler.GetAuthMe(c)
}
// PostAuthRefresh operation middleware
func (siw *ServerInterfaceWrapper) PostAuthRefresh(c *fiber.Ctx) error {
return siw.Handler.PostAuthRefresh(c)
}
// FiberServerOptions provides options for the Fiber server.
type FiberServerOptions struct {
BaseURL string
Middlewares []MiddlewareFunc
}
// RegisterHandlers creates http.Handler with routing matching OpenAPI spec.
func RegisterHandlers(router fiber.Router, si ServerInterface) {
RegisterHandlersWithOptions(router, si, FiberServerOptions{})
}
// RegisterHandlersWithOptions creates http.Handler with additional options
func RegisterHandlersWithOptions(router fiber.Router, si ServerInterface, options FiberServerOptions) {
wrapper := ServerInterfaceWrapper{
Handler: si,
}
for _, m := range options.Middlewares {
router.Use(m)
}
router.Post(options.BaseURL+"/auth/login", wrapper.PostAuthLogin)
router.Post(options.BaseURL+"/auth/logout", wrapper.PostAuthLogout)
router.Get(options.BaseURL+"/auth/me", wrapper.GetAuthMe)
router.Post(options.BaseURL+"/auth/refresh", wrapper.PostAuthRefresh)
}

View File

@@ -6,7 +6,6 @@ import (
"github.com/gofiber/fiber/v2/middleware/helmet" "github.com/gofiber/fiber/v2/middleware/helmet"
"github.com/gofiber/fiber/v2/middleware/logger" "github.com/gofiber/fiber/v2/middleware/logger"
"cloud.etaviaporte.com/api/libs/openapi"
"cloud.etaviaporte.com/api/libs/services/auth" "cloud.etaviaporte.com/api/libs/services/auth"
) )
@@ -30,7 +29,13 @@ func main() {
return c.SendString("Hello, World!") return c.SendString("Hello, World!")
}) })
openapi.RegisterHandlers(app, auth.Handler{}) handler := auth.Handler{}
// openapi.RegisterHandlers(app, auth.Handler{})
app.Post("/auth/login", handler.PostAuthLogin)
app.Post("/auth/logout", handler.PostAuthLogout)
app.Get("/auth/me", handler.GetAuthMe)
app.Post("/auth/refresh", handler.PostAuthRefresh)
app.Listen(":3000") app.Listen(":3000")
} }

View File

@@ -1,7 +1,6 @@
package: openapi package: openapi
output: libs/openapi/generated.go output: libs/openapi/generated.go
generate: generate:
fiber-server: true
models: true models: true
output-options: output-options:
skip-prune: true skip-prune: true

File diff suppressed because it is too large Load Diff

After

Width:  |  Height:  |  Size: 1.4 MiB

File diff suppressed because it is too large Load Diff

Before

Width:  |  Height:  |  Size: 159 KiB

BIN
db/Models/eta_rbac.mwb Normal file

Binary file not shown.

View File

@@ -0,0 +1,248 @@
# ETA RBAC and Domain Data Requirements
This document translates SQL constraints from the schema into software requirements language.
## 1. Global Requirements
1. The system shall store all data in the schema `u947463964_etaviaporte`.
2. Each table shall use an auto-generated unsigned integer `id` as primary key.
3. Every foreign-keyed record shall reference an existing parent record.
## 2. Users and Authentication
1. A user shall provide `name` and `last_name`.
2. A user record shall always include `created_at` and `updated_at` timestamps.
3. An auth identity shall always belong to an existing user.
4. An auth identity shall include `provider` and `identifier`.
5. The combination of `provider` and `identifier` shall be unique.
6. Auth identity flags `is_primary` and `is_verified` shall default to `0` (false).
7. Deleting a user shall delete the user auth identities.
## 3. Applications, Roles, and Permissions
1. An application shall include unique `name` and unique `slug`.
2. A role shall always belong to an existing application.
3. A role name shall be unique within its application.
4. A permission shall always belong to an existing application.
5. A permission name shall be unique within its application.
6. A permission record shall include `created_at` and `updated_at` timestamps.
7. A role-permission assignment shall reference an existing role and permission.
8. The pair `(role_id, permission_id)` shall be unique.
9. A role-permission assignment shall include `created_at` and `updated_at` timestamps.
10. Deleting an application, role, or permission shall delete related role-permission assignments.
11. A user-role assignment shall reference an existing user and role.
12. The pair `(user_id, role_id)` shall be unique.
13. A user-role assignment shall include `created_at` and `updated_at`, and may include `expires_at`.
14. Deleting a user, role, or application shall delete related user-role assignments.
15. A user shall be allowed to have multiple roles as long as each `(user_id, role_id)` pair is unique.
## 4. Verification and Sessions
1. A verification token shall belong to an existing auth identity.
2. A verification token shall include unique `token_hash`.
3. Verification token purpose shall be one of: `email_verification`, `phone_verification`, `password_reset`.
4. A verification token shall include `created_at`, `updated_at`, and `expires_at`.
5. Deleting an auth identity shall delete related verification tokens.
6. A session shall belong to an existing user.
7. A session shall include unique `session_token_hash`.
8. A session shall include `created_at`, `updated_at`, and `expires_at`.
9. Deleting a user shall delete related sessions.
## 5. Companies and Locations
1. A company shall include `name`.
2. Company type shall be one of: `NotSet`, `Shipper`, `Carrier`.
3. Company type shall default to `NotSet`.
4. Company `privacy_enabled` shall default to `0`.
5. Company `disabled` shall default to `0`.
6. Company `disabled_reason`, when present, shall be stored as up to 255 characters.
7. A location shall belong to an existing company.
8. A location shall include `state`, `city`, `country`, `zipcode`, and `address_line1`.
9. Location type shall be one of: `loading`, `unloading`, `both`.
10. Location type shall default to `both`.
11. Location coordinates, when present, shall be stored as decimal latitude and longitude values.
12. Deleting a company shall delete its locations.
## 6. Loads, Vehicles, and Shipment Lifecycle
1. A load shall belong to an existing company and an existing creator user.
2. Load status shall be one of: `Draft`, `Published`, `Completed`, `Closed`, `Cancelled`.
3. Load status shall default to `Draft`.
4. A load shall include `product`, `sector`, and `vehicle_type`.
5. Load `privacy_enabled` shall default to `0`.
6. Load `disabled` shall default to `0`.
7. If an origin or destination location is deleted, the corresponding load reference shall be set to `NULL`.
8. Deleting the load creator user shall delete the load.
9. Deleting the load company shall delete the load.
10. A vehicle shall belong to an existing company.
11. A vehicle shall include `VIN` and `vehicle_plate`.
12. Vehicle status shall be one of: `Available`, `Busy`.
13. Vehicle status shall default to `Available`.
14. A company shall not repeat the same vehicle VIN (`(company_id, VIN)` unique).
15. A company shall not repeat the same vehicle plate (`(company_id, vehicle_plate)` unique).
16. A driver shall be assigned to at most one vehicle at a time (`driver_id` unique).
17. A load shall be assigned to at most one vehicle at a time (`load_id` unique).
18. If a driver user is deleted, the vehicle driver reference shall be set to `NULL`.
19. If an assigned load is deleted, the vehicle load reference shall be set to `NULL`.
20. Deleting a company shall delete its vehicles.
21. A shipment proposal shall belong to an existing load and an existing user (`created_by`).
22. If a proposed vehicle is deleted, the shipment proposal vehicle reference shall be set to `NULL`.
23. Deleting a load shall delete shipment proposals.
24. Deleting the creator user shall delete shipment proposals.
25. A shipment agreement shall reference an existing load, shipment proposal, and accepting user.
26. A load shall have at most one shipment agreement (`load_id` unique).
27. Deleting a load, shipment proposal, or accepting user shall delete shipment agreements.
28. A load shipment shall belong to an existing load.
29. A load shipment status shall be one of: `Assigned`, `Loading`, `Transit`, `Unloading`, `Delivered`.
30. A load shipment status shall default to `Assigned`.
31. Shipment tracking coordinates, when present, shall be stored as decimal latitude and longitude values.
32. Each load shall have at most one load shipment (`load_id` unique).
33. Deleting a load shall delete related load shipments.
34. A shipment evidence record shall belong to an existing load.
35. Shipment evidence type shall be one of: `loading`, `unloading`.
36. A load shall have at most one evidence per evidence type (`(load_id, type)` unique).
37. Deleting a load shall delete related shipment evidences.
## 7. Master Data and Categorization
1. Sector names in `meta_sectors` shall be unique.
2. A sector record shall include `created_at` and `updated_at` timestamps.
3. Vehicle type names in `meta_vehicle_types` shall be unique.
4. A vehicle type record shall include `created_at` and `updated_at` timestamps.
5. Product names in `meta_products` shall be unique.
6. A product record shall include `created_at` and `updated_at` timestamps.
7. A city record shall include `city`, `state`, and `country`.
8. A city record shall include `created_at` and `updated_at` timestamps.
9. A company sector shall belong to an existing company.
10. A company shall not repeat the same sector (`(company_id, sector)` unique).
11. A company sector record shall include `created_at` and `updated_at` timestamps.
12. Deleting a company shall delete its company sectors.
13. A company vehicle type shall belong to an existing company.
14. A company shall not repeat the same vehicle type (`(company_id, vehicle_type)` unique).
15. A company vehicle type record shall include `created_at` and `updated_at` timestamps.
16. Deleting a company shall delete its company vehicle types.
17. A company-location-sector assignment shall reference an existing location and existing company sector.
18. A location shall not repeat the same sector (`(location_id, sector_id)` unique).
19. A company-location-sector record shall include `created_at` and `updated_at` timestamps.
20. Deleting a location or company sector shall delete related company-location-sector assignments.
21. A vehicle-type assignment shall reference an existing vehicle and existing company vehicle type.
22. A vehicle shall not repeat the same type (`(vehicle_id, type_id)` unique).
23. A vehicle-type assignment shall include `created_at` and `updated_at` timestamps.
24. Deleting a vehicle or company vehicle type shall delete related vehicle-type assignments.
25. A user-location assignment shall reference an existing user and existing location.
26. A user shall not repeat the same location (`(user_id, location_id)` unique).
27. A user-location assignment shall include `created_at` and `updated_at` timestamps.
28. Deleting a user or location shall delete related user-location assignments.
## 8. Templates, Memberships, and Privacy
1. A load template shall belong to an existing company and creator user.
2. A load template shall include `name`.
3. A user shall not create duplicate load template names inside the same company (`(company_id, created_by, name)` unique).
4. Deleting a company shall delete related load templates.
5. Deleting a creator user shall delete related load templates.
6. Deleting an origin or destination location referenced by a load template shall set that location reference to `NULL`.
7. A user-application assignment shall reference an existing user and existing application.
8. A user shall be allowed to be added to multiple applications.
9. A user shall not be assigned to the same application more than once (`(user_id, application_id)` unique).
10. A user-application assignment shall include `created_at` and `updated_at` timestamps.
11. Deleting a user or application shall delete related user-application assignments.
12. A company-user assignment shall reference an existing user and existing company.
13. A company-user assignment shall include `created_at` and `updated_at` timestamps.
14. A user shall be assigned to only one company (`user_id` unique in `company_users`).
15. Deleting a user or company shall delete related company-user assignments.
16. A privacy group shall belong to an existing company.
17. Privacy group names shall be unique per company (`(company_id, name)` unique).
18. Deleting a company shall delete its privacy groups.
19. A privacy group company rule shall reference an existing company, privacy group, and allowed company.
20. An allowed company shall not be repeated within the same privacy group (`(group_id, allowed_company_id)` unique).
21. A privacy group company rule shall include `created_at` and `updated_at` timestamps.
22. Deleting a company or privacy group shall delete related privacy group company rules.
## 9. Alert Email Constraints
1. A load alert email record shall belong to an existing load.
2. The same email shall not be repeated for the same load (`(load_id, email)` unique).
3. A load alert email record shall include `created_at` and `updated_at` timestamps.
4. Deleting a load shall delete load alert emails.
5. A warehouse alert email record shall belong to an existing warehouse location.
6. The same email shall not be repeated for the same warehouse (`(warehouse_id, email)` unique).
7. A warehouse alert email record shall include `created_at` and `updated_at` timestamps.
8. Deleting a warehouse location shall delete warehouse alert emails.
## 10. Identity and Access Interpretation
1. A user shall be authorized using an identity provider and identifier pair, such as email address or phone number.
2. A provider-specific identifier shall map to one and only one auth identity record.
3. A role and permission model shall be scoped by application.
## 11. Company Compliance and Documents
1. A company status record shall belong to an existing company.
2. A company shall have at most one company status record (`company_id` unique).
3. Company status shall be one of: `Registered`, `InReview`, `Enabled`, `Disabled`.
4. Company status shall default to `Registered`.
5. A company status record may include `notes`.
6. A company status record shall include `created_at` and `updated_at` timestamps.
7. Deleting a company shall delete related company status records.
8. A company document shall belong to an existing company.
9. A company document shall include `document_id` and `name`.
10. Company document status shall be one of: `New`, `InReview`, `Approved`, `Rejected`.
11. Company document status shall default to `New`.
12. A company document may include `status_notes`.
13. A company document record shall include `created_at` and `updated_at` timestamps.
14. A company shall not repeat document names (`(company_id, name)` unique).
15. Deleting a company shall delete related company documents.
## 12. API Key and User Permission Model
1. An API key record shall include `name` and `key_hash`.
2. API key hashes shall be globally unique.
3. An API key shall belong to an existing application and an existing user owner.
4. An API key record shall include `created_at` and `updated_at` timestamps.
5. API key `active` status shall default to `1` (true).
6. Deleting an application or user shall delete related API keys.
7. A user-permission assignment shall belong to an existing application, permission, and user.
8. A user-permission assignment shall include `created_at` and `updated_at`, and may include `expires_at`.
9. A user shall not repeat the same permission assignment (`(user_id, permission_id)` unique).
10. Deleting an application, permission, or user shall delete related user-permission assignments.
## 13. Vehicle Documents
1. A vehicle document shall belong to an existing company and an existing vehicle.
2. A vehicle document shall include `document_id` and `name`.
3. Vehicle document status shall be one of: `New`, `InReview`, `Approved`, `Rejected`.
4. Vehicle document status shall default to `New`.
5. A vehicle document may include `status_notes`.
6. A vehicle document record shall include `created_at` and `updated_at` timestamps.
7. A company shall not repeat vehicle document names (`(company_id, name)` unique).
8. Deleting a company or vehicle shall delete related vehicle documents.
## 14. Subscription and Billing Constraints
1. A subscription plan shall belong to an existing application.
2. A subscription plan shall include `provider`, `provider_plan_id`, and internal `name` unique within its application (`(application_id, name)` unique).
3. The pair `(provider, provider_plan_id)` shall be unique.
4. A subscription plan shall include `amount` with 4 decimal precision and default `0.0000`.
5. Subscription plan `currency` shall default to `MXN` when not provided.
6. Subscription plan limits shall default to: `limit_users=2`, `limit_loads=4`, `limit_shipments=4`, `limit_privacy_allowed=0`.
7. A subscription plan shall include `created_at` and `updated_at` timestamps.
8. A company subscription shall reference an existing company and subscription plan.
9. A company shall have at most one company subscription (`company_id` unique in `company_subscriptions`).
10. Company subscription status shall be one of: `Pending`, `Active`, `PastDue`, `Unpaid`, `Cancelled`, `Paused`.
11. Company subscription status shall default to `Unpaid`.
12. A company subscription shall include `provider_subscription_id`.
13. A company subscription may include `start_date`, `current_period_start`, `current_period_end`, `cancelled_at`, and `cancelled_at_period_end`.
14. A company subscription shall include `created_at` and `updated_at` timestamps.
15. Company and plan rows referenced by company subscriptions shall not be deletable while dependent subscriptions exist (`ON DELETE NO ACTION`).
16. A payment method shall belong to an existing company.
17. A payment method shall include `provider`, `provider_payment_id`, `last4`, `brand`, and `name`.
18. The pair `(provider, provider_payment_id)` shall be unique among payment methods.
19. Payment method `is_primary` shall default to `0`.
20. A payment method shall include `created_at` and `updated_at` timestamps.
21. A company row referenced by payment methods shall not be deletable while dependent payment methods exist (`ON DELETE NO ACTION`).
22. A company limits record shall belong to an existing company.
23. A company shall have at most one limits record (`company_id` unique).
24. Company limits shall default to: `available_users=2`, `available_shipments=4`, `available_loads=4`, `privacy_allowed=0`.
25. A company limits record shall include `created_at` and `updated_at` timestamps.
26. Deleting a company shall delete related company limits records.

View File

@@ -0,0 +1,47 @@
-- Creation of init content. Scheme assumed to be empty
--
USE `u947463964_etaviaporte` ;
INSERT INTO `applications` (`name`, `slug`, `description`) VALUES ('ETAConsole','console','ETA logistics console for Carriers and Shippers');
INSERT INTO `applications` (`name`, `slug`, `description`) VALUES ('ETADriver','driver','ETA driver application');
INSERT INTO `applications` (`name`, `slug`, `description`) VALUES ('ETAObserverClient','client','ETA observer console for clients');
INSERT INTO `applications` (`name`, `slug`, `description`) VALUES ('ETAObserverWarehouse','warehouse','ETA observer console for warehouse');
-- Roles for ETAConsole application (1)
INSERT INTO `roles` (`application_id`,`name`, `description`) VALUES (1,'owner', '(ETAConsole): Owner of the company');
INSERT INTO `roles` (`application_id`,`name`, `description`) VALUES (1,'manager', '(ETAConsole): Manager of the company');
INSERT INTO `roles` (`application_id`,`name`, `description`) VALUES (1,'driver', '(ETAConsole): Driver user type');
INSERT INTO `roles` (`application_id`,`name`, `description`) VALUES (1,'staff', '(ETAConsole): Member of the staff');
INSERT INTO `roles` (`application_id`,`name`, `description`) VALUES (1,'warehouse', '(ETAConsole): Observer type of member');
-- Roles for ETADriver application (2)
INSERT INTO `roles` (`application_id`,`name`, `description`) VALUES (2,'driver', '(ETADriver): Driver user type');
-- Roles for ETAObserverClient application (3)
INSERT INTO `roles` (`application_id`,`name`, `description`) VALUES (3,'client', '(ETAObserverClient): Client user type');
-- Roles for ETAObserverWarehouse application (4)
INSERT INTO `roles` (`application_id`,`name`, `description`) VALUES (4,'warehouse', '(ETAObserverWarehouse):Warehouse user type');
-- Permissions for ETAConsole application (1)
INSERT INTO `permissions` (`application_id`,`name`, `description`) VALUES (1,'owner', '(ETAConsole): Compatibility with Legacy while refactor in progress');
INSERT INTO `permissions` (`application_id`,`name`, `description`) VALUES (1,'manager', '(ETAConsole): Compatibility with Legacy while refactor in progress');
INSERT INTO `permissions` (`application_id`,`name`, `description`) VALUES (1,'driver', '(ETAConsole): Compatibility with Legacy while refactor in progress');
INSERT INTO `permissions` (`application_id`,`name`, `description`) VALUES (1,'staff', '(ETAConsole): Compatibility with Legacy while refactor in progress');
INSERT INTO `permissions` (`application_id`,`name`, `description`) VALUES (1,'warehouse', '(ETAConsole): Compatibility with Legacy while refactor in progress');
-- Permissions for ETADriver application (2)
INSERT INTO `permissions` (`application_id`,`name`, `description`) VALUES (2,'driver', '(ETADriver): Compatibility with Legacy while refactor in progress');
-- Permissions for ETAObserverClient application (3)
INSERT INTO `permissions` (`application_id`,`name`, `description`) VALUES (3,'client', '(ETAObserverClient): Compatibility with Legacy while refactor in progress');
-- Permissions for ETAObserverWarehouse application (4)
INSERT INTO `permissions` (`application_id`,`name`, `description`) VALUES (4,'warehouse', '(ETAObserverWarehouse): Compatibility with Legacy while refactor in progress');
-- Role-Permissions link for ETAConsole application (1)
INSERT INTO `role_permissions` (`role_id`, `permission_id`) VALUES (1,1);
INSERT INTO `role_permissions` (`role_id`, `permission_id`) VALUES (2,2);
INSERT INTO `role_permissions` (`role_id`, `permission_id`) VALUES (3,3);
INSERT INTO `role_permissions` (`role_id`, `permission_id`) VALUES (4,4);
INSERT INTO `role_permissions` (`role_id`, `permission_id`) VALUES (5,5);
-- Role-Permissions link for ETADriver application (2)
INSERT INTO `role_permissions` (`role_id`, `permission_id`) VALUES (6,6);
-- Role-Permissions link for ETAObserverClient application (3)
INSERT INTO `role_permissions` (`role_id`, `permission_id`) VALUES (7,7);
-- Role-Permissions link for ETAObserverWarehouse application (4)
INSERT INTO `role_permissions` (`role_id`, `permission_id`) VALUES (8,8);

Binary file not shown.

File diff suppressed because it is too large Load Diff

View File

@@ -1,55 +0,0 @@
-- Creation of basic User Types
INSERT INTO user_types (name, description) VALUES ('root','An easy way to identify the root user of the system');
INSERT INTO user_types (name, description) VALUES ('company_owner','Company Owner');
INSERT INTO user_types (name, description) VALUES ('company_manager','Company Level manager');
INSERT INTO user_types (name, description) VALUES ('company_staff','Company Level Staff Memeber');
INSERT INTO user_types (name, description) VALUES ('company_driver','Company Level Driver Member');
INSERT INTO user_types (name, description) VALUES ('company_observer','Company Level Driver Member');
-- Creation of first user
INSERT INTO users (user_type,name,last_name,created_at,updated_at) VALUES (1,'Pablo','Cruz',NOW(),NOW()); -- root -> root
-- Creation of basic roles
INSERT INTO roles (name, description, created_at, updated_at) VALUES ("root","Root role with no restricted access",NOW(),NOW());
INSERT INTO roles (name, description, created_at, updated_at) VALUES ("system_admin","System Level Admin",NOW(),NOW());
INSERT INTO roles (name, description, created_at, updated_at) VALUES ("system_developer","System Level Developer",NOW(),NOW());
INSERT INTO roles (name, description, created_at, updated_at) VALUES ("system_reader","System Level Read Only",NOW(),NOW());
INSERT INTO roles (name, description, created_at, updated_at) VALUES ("system_staff","System Level staff member",NOW(),NOW());
INSERT INTO roles (name, description, created_at, updated_at) VALUES ("company_owner","Unrestricted access to company resources",NOW(),NOW());
INSERT INTO roles (name, description, created_at, updated_at) VALUES ("company_manager","Access as manager to company resources",NOW(),NOW());
INSERT INTO roles (name, description, created_at, updated_at) VALUES ("company_staff","Access as staff to company resources",NOW(),NOW());
INSERT INTO roles (name, description, created_at, updated_at) VALUES ("company_driver","Simple access to company resources",NOW(),NOW());
INSERT INTO roles (name, description, created_at, updated_at) VALUES ("company_observer","Limited access to company resources",NOW(),NOW());
-- Creation of basic permissions
INSERT INTO permissions (name, description) VALUES ("root","Root role with no restricted access");
INSERT INTO permissions (name, description) VALUES ("system.admin","System Level Admin");
INSERT INTO permissions (name, description) VALUES ("system.developer","System Level Developer");
INSERT INTO permissions (name, description) VALUES ("system.reader","System Level Reader");
INSERT INTO permissions (name, description) VALUES ("system.staff","System Level Staff Member");
INSERT INTO permissions (name, description) VALUES ("company.owner","Unrestricted access to company resources");
INSERT INTO permissions (name, description) VALUES ("company.manager","Admin access to company resources");
INSERT INTO permissions (name, description) VALUES ("company.staff","Staff access to company resources");
INSERT INTO permissions (name, description) VALUES ("company.driver","Driver with simple access to company resources");
INSERT INTO permissions (name, description) VALUES ("company.observer","Observer with simple access to company resources");
-- Link of basic roles with its permissions
INSERT INTO role_permissions (role_id, permission_id) VALUES( 1, 1 ); -- root -> root
INSERT INTO role_permissions (role_id, permission_id) VALUES( 2, 2 );
INSERT INTO role_permissions (role_id, permission_id) VALUES( 3, 3 );
INSERT INTO role_permissions (role_id, permission_id) VALUES( 4, 4 );
INSERT INTO role_permissions (role_id, permission_id) VALUES( 5, 5 );
INSERT INTO role_permissions (role_id, permission_id) VALUES( 6, 6 );
INSERT INTO role_permissions (role_id, permission_id) VALUES( 7, 7 );
INSERT INTO role_permissions (role_id, permission_id) VALUES( 8, 8 );
INSERT INTO role_permissions (role_id, permission_id) VALUES( 9, 9 );
INSERT INTO role_permissions (role_id, permission_id) VALUES( 10, 10 );
-- Link of Root User with its role
INSERT INTO user_roles (user_id, role_id, created_at ) VALUES (1,1,NOW()); -- root -> root
-- Create Root Auth Identity and credentials
INSERT INTO auth_identities (user_id, provider, identifier, is_primary, is_verified, created_at, updated_at ) VALUES (1,"email","josepablo134@gmail.com",1,1,NOW(),NOW()); -- root access with email
INSERT INTO auth_credentials (identity_id, password, created_at, updated_at) VALUES (1, "PasswordGoesHere", NOW(), NOW());

View File

@@ -1,174 +0,0 @@
-- MySQL Script generated by MySQL Workbench
-- Sun Dec 7 08:38:42 2025
-- Model: New Model Version: 1.0
-- MySQL Workbench Forward Engineering
SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0;
SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0;
SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION';
-- -----------------------------------------------------
-- Schema u947463964_etaviaporte
-- -----------------------------------------------------
-- -----------------------------------------------------
-- Schema u947463964_etaviaporte
-- -----------------------------------------------------
CREATE SCHEMA IF NOT EXISTS `u947463964_etaviaporte` DEFAULT CHARACTER SET utf8 ;
USE `u947463964_etaviaporte` ;
-- -----------------------------------------------------
-- Table `u947463964_etaviaporte`.`user_types`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `u947463964_etaviaporte`.`user_types` (
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
`name` TEXT NOT NULL,
`description` TEXT NULL,
PRIMARY KEY (`id`),
UNIQUE INDEX `id_UNIQUE` (`id` ASC) VISIBLE)
ENGINE = InnoDB;
-- -----------------------------------------------------
-- Table `u947463964_etaviaporte`.`users`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `u947463964_etaviaporte`.`users` (
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
`user_type` INT UNSIGNED NOT NULL,
`name` TEXT NOT NULL,
`last_name` TEXT NOT NULL,
`created_at` DATETIME NOT NULL,
`updated_at` DATETIME NOT NULL,
UNIQUE INDEX `id_UNIQUE` (`id` ASC) VISIBLE,
PRIMARY KEY (`id`),
INDEX `fk_users_user_types1_idx` (`user_type` ASC) VISIBLE,
CONSTRAINT `fk_users_user_types1`
FOREIGN KEY (`user_type`)
REFERENCES `u947463964_etaviaporte`.`user_types` (`id`)
ON DELETE NO ACTION
ON UPDATE NO ACTION)
ENGINE = InnoDB;
-- -----------------------------------------------------
-- Table `u947463964_etaviaporte`.`auth_identities`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `u947463964_etaviaporte`.`auth_identities` (
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
`user_id` INT UNSIGNED NOT NULL,
`provider` TEXT NOT NULL,
`identifier` TEXT NOT NULL COMMENT 'email, phone google, facebook, etc.',
`is_primary` TINYINT NOT NULL DEFAULT 0,
`is_verified` TINYINT NOT NULL DEFAULT 0,
`created_at` DATETIME NOT NULL,
`updated_at` DATETIME NOT NULL,
PRIMARY KEY (`id`),
UNIQUE INDEX `id_UNIQUE` (`id` ASC) VISIBLE,
INDEX `fk_auth_identities_users_idx` (`user_id` ASC) VISIBLE,
CONSTRAINT `fk_auth_identities_users`
FOREIGN KEY (`user_id`)
REFERENCES `u947463964_etaviaporte`.`users` (`id`)
ON DELETE CASCADE
ON UPDATE NO ACTION)
ENGINE = InnoDB;
-- -----------------------------------------------------
-- Table `u947463964_etaviaporte`.`auth_credentials`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `u947463964_etaviaporte`.`auth_credentials` (
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
`identity_id` INT UNSIGNED NOT NULL,
`password` TEXT NOT NULL,
`created_at` DATETIME NOT NULL,
`updated_at` DATETIME NOT NULL,
PRIMARY KEY (`id`),
UNIQUE INDEX `id_UNIQUE` (`id` ASC) VISIBLE,
INDEX `fk_auth_credentials_auth_identities1_idx` (`identity_id` ASC) VISIBLE,
CONSTRAINT `fk_auth_credentials_auth_identities1`
FOREIGN KEY (`identity_id`)
REFERENCES `u947463964_etaviaporte`.`auth_identities` (`id`)
ON DELETE CASCADE
ON UPDATE NO ACTION)
ENGINE = InnoDB;
-- -----------------------------------------------------
-- Table `u947463964_etaviaporte`.`roles`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `u947463964_etaviaporte`.`roles` (
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
`name` TEXT NOT NULL,
`description` TEXT NULL,
`created_at` DATETIME NOT NULL,
`updated_at` DATETIME NOT NULL,
PRIMARY KEY (`id`),
UNIQUE INDEX `id_UNIQUE` (`id` ASC) VISIBLE)
ENGINE = InnoDB;
-- -----------------------------------------------------
-- Table `u947463964_etaviaporte`.`permissions`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `u947463964_etaviaporte`.`permissions` (
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
`name` TEXT NOT NULL,
`description` TEXT NULL,
PRIMARY KEY (`id`),
UNIQUE INDEX `id_UNIQUE` (`id` ASC) VISIBLE)
ENGINE = InnoDB;
-- -----------------------------------------------------
-- Table `u947463964_etaviaporte`.`role_permissions`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `u947463964_etaviaporte`.`role_permissions` (
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
`role_id` INT UNSIGNED NOT NULL,
`permission_id` INT UNSIGNED NOT NULL,
PRIMARY KEY (`id`),
UNIQUE INDEX `id_UNIQUE` (`id` ASC) VISIBLE,
INDEX `fk_role_permissions_roles1_idx` (`role_id` ASC) VISIBLE,
INDEX `fk_role_permissions_permissions1_idx` (`permission_id` ASC) VISIBLE,
CONSTRAINT `fk_role_permissions_roles1`
FOREIGN KEY (`role_id`)
REFERENCES `u947463964_etaviaporte`.`roles` (`id`)
ON DELETE CASCADE
ON UPDATE NO ACTION,
CONSTRAINT `fk_role_permissions_permissions1`
FOREIGN KEY (`permission_id`)
REFERENCES `u947463964_etaviaporte`.`permissions` (`id`)
ON DELETE CASCADE
ON UPDATE NO ACTION)
ENGINE = InnoDB;
-- -----------------------------------------------------
-- Table `u947463964_etaviaporte`.`user_roles`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `u947463964_etaviaporte`.`user_roles` (
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
`user_id` INT UNSIGNED NOT NULL,
`role_id` INT UNSIGNED NOT NULL,
`created_at` DATETIME NOT NULL,
`expires_at` DATETIME NULL,
PRIMARY KEY (`id`),
UNIQUE INDEX `id_UNIQUE` (`id` ASC) VISIBLE,
INDEX `fk_user_roles_users1_idx` (`user_id` ASC) VISIBLE,
INDEX `fk_user_roles_roles1_idx` (`role_id` ASC) VISIBLE,
CONSTRAINT `fk_user_roles_users1`
FOREIGN KEY (`user_id`)
REFERENCES `u947463964_etaviaporte`.`users` (`id`)
ON DELETE CASCADE
ON UPDATE NO ACTION,
CONSTRAINT `fk_user_roles_roles1`
FOREIGN KEY (`role_id`)
REFERENCES `u947463964_etaviaporte`.`roles` (`id`)
ON DELETE CASCADE
ON UPDATE NO ACTION)
ENGINE = InnoDB;
SET SQL_MODE=@OLD_SQL_MODE;
SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS;
SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS;

View File

@@ -1,20 +0,0 @@
# ETAv2SQL
# MySQL Databse schema
![etaviaporte](./Models/assets/Modelv2.0.0.png)
# Docker
## Build Docker image
docker buildx build -t eta/eta-db
## Run Docker container
```{.sh}
docker run --name eta-db -d -p3306:3306 eta/eta-db
docker logs -f eta-db
```
Container will generate automatically a SQL root password

View File

@@ -1,5 +1,5 @@
# Original author : https://github.com/yobasystems/alpine-mariadb.git # Original author : https://github.com/yobasystems/alpine-mariadb.git
FROM alpine:latest FROM alpine:3.23.3
ARG BUILD_DATE ARG BUILD_DATE
ARG VCS_REF ARG VCS_REF
@@ -7,14 +7,18 @@ ARG VCS_REF
RUN apk add --no-cache mariadb mysql-client mariadb-server-utils pwgen && \ RUN apk add --no-cache mariadb mysql-client mariadb-server-utils pwgen && \
rm -f /var/cache/apk/* rm -f /var/cache/apk/*
RUN mkdir /schemas RUN mkdir /schemas && mkdir /scripts
COPY schemas /schemas
ADD scripts/run.sh /scripts/run.sh
RUN mkdir /docker-entrypoint-initdb.d && \ RUN mkdir /docker-entrypoint-initdb.d && \
mkdir /scripts/pre-exec.d && \ mkdir /scripts/pre-exec.d && \
mkdir /scripts/pre-init.d && \ mkdir /scripts/pre-init.d
chmod -R 755 /scripts
#
# Populate content here
#
ADD scripts/run.sh /scripts/run.sh
# COPY docker-entrypoint-initdb.d/ /docker-entrypoint-initdb.d/
RUN chmod -R 755 /scripts
EXPOSE 3306 EXPOSE 3306

42
db/container/README.md Normal file
View File

@@ -0,0 +1,42 @@
# ETAv2SQL
# Docker Container to deploy MySQL with schema and content init
## Build Docker image
```{.sh}
docker buildx build -t eta/eta-db .
```
## Run Docker container
```{.sh}
docker run --name eta-db -d -p3306:3306 eta/eta-db
docker logs -f eta-db
```
Container will generate automatically a SQL root password
### Environment Variables
You can setup a database name and grant access to it with user/password using the following env vars
- MYSQL_DATABASE
- MYSQL_USER
- MYSQL_PASSWORD
```{.sh}
docker run --name eta-db -e MYSQL_DATABASE=u947463964_etaviaporte -e MYSQL_USER=etaapi -e MYSQL_PASSWORD="secret_password" -d -p3306:3306 eta/eta-db
```
### Schemas and SQL scripts
You can add schemas and sql scripts to the container to setup the database on startup by mounting a directory with sql scripts on `/docker-entrypoint-initdb.d`
```{.sh}
docker run --name eta-db -e MYSQL_DATABASE=u947463964_etaviaporte -e MYSQL_USER=etaapi -e MYSQL_PASSWORD="secret_password" -v ./docker-entrypoint-initdb.d:/docker-entrypoint-initdb.d -d -p3306:3306 eta/eta-db
```
### Known Issues
- When loading a script, errors my araise when using `"` instead of `'` and when comments appear at the end of a command

View File

@@ -70,13 +70,14 @@ EOF
fi fi
fi fi
/usr/bin/mysqld --user=mysql --bootstrap --verbose=0 --skip-name-resolve --skip-networking=0 < $tfile /usr/bin/mariadbd --user=mysql --bootstrap --verbose=0 --skip-name-resolve --skip-networking=0 < $tfile
rm -f $tfile rm -f $tfile
for f in /docker-entrypoint-initdb.d/*; do for f in /docker-entrypoint-initdb.d/*; do
echo
case "$f" in case "$f" in
*.sql) echo "$0: running $f"; /usr/bin/mysqld --user=mysql --bootstrap --verbose=0 --skip-name-resolve --skip-networking=0 < "$f"; echo ;; *.sql) echo "$0: running $f"; /usr/bin/mariadbd --user=mysql --bootstrap --verbose=0 --skip-name-resolve --skip-networking=0 < "$f"; echo ;;
*.sql.gz) echo "$0: running $f"; gunzip -c "$f" | /usr/bin/mysqld --user=mysql --bootstrap --verbose=0 --skip-name-resolve --skip-networking=0 < "$f"; echo ;; *.sql.gz) echo "$0: running $f"; gunzip -c "$f" | /usr/bin/mariadbd --user=mysql --bootstrap --verbose=0 --skip-name-resolve --skip-networking=0 < "$f"; echo ;;
*) echo "$0: ignoring or entrypoint initdb empty $f" ;; *) echo "$0: ignoring or entrypoint initdb empty $f" ;;
esac esac
echo echo
@@ -86,17 +87,10 @@ EOF
echo 'MySQL init process done. Ready for start up.' echo 'MySQL init process done. Ready for start up.'
echo echo
echo "exec /usr/bin/mysqld --user=mysql --console --skip-name-resolve --skip-networking=0" "$@" echo "exec /usr/bin/mariadbd --user=mysql --console --skip-name-resolve --skip-networking=0" "$@"
# Saving plain password # Saving plain password
echo $MYSQL_ROOT_PASSWORD > /schemas/password.txt echo $MYSQL_ROOT_PASSWORD > /schemas/password.txt
# # After 5 seconds (once mysql is up) create schema.
# $(sleep 5 && /usr/bin/mysql -uroot -p$MYSQL_ROOT_PASSWORD < /schemas/wincify.sql &&\
# /usr/bin/mysql -uroot -p$MYSQL_ROOT_PASSWORD < /schemas/wincify_zones.sql &&\
# /usr/bin/mysql -uroot -p$MYSQL_ROOT_PASSWORD < /schemas/wincify_categories.sql &&\
# /usr/bin/mysql -uroot -p$MYSQL_ROOT_PASSWORD < /schemas/system.sql &&\
# /usr/bin/mysql -uroot -p$MYSQL_ROOT_PASSWORD wincify_system < /schemas/wincifySystem_init.sql ) &\
fi fi
# execute any pre-exec scripts # execute any pre-exec scripts
@@ -108,4 +102,4 @@ do
fi fi
done done
exec /usr/bin/mysqld --user=mysql --console --skip-name-resolve --skip-networking=0 $@ exec /usr/bin/mariadbd --user=mysql --console --skip-name-resolve --skip-networking=0 $@

5
db/service/Makefile Normal file
View File

@@ -0,0 +1,5 @@
.PHONY: prepare
prepare:
rm initdb/*.sql
cp ../Models/schemas/eta_rbac.sql ./initdb/00-schema.sql
cp ../Models/init/eta_rbac_init.sql ./initdb/01-initdb.sql

13
db/service/compose.yml Normal file
View File

@@ -0,0 +1,13 @@
services:
eta-db:
image: eta/eta-db
container_name: eta-db
ports:
- "3306:3306"
environment:
MYSQL_DATABASE: u947463964_etaviaporte
MYSQL_USER: etaapi
MYSQL_PASSWORD: secret_password
volumes:
# Solve problems related to SELinux `permission denied` when accessing the path
- ./initdb:/docker-entrypoint-initdb.d:Z

View File

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,47 @@
-- Creation of init content. Scheme assumed to be empty
--
USE `u947463964_etaviaporte` ;
INSERT INTO `applications` (`name`, `slug`, `description`) VALUES ('ETAConsole','console','ETA logistics console for Carriers and Shippers');
INSERT INTO `applications` (`name`, `slug`, `description`) VALUES ('ETADriver','driver','ETA driver application');
INSERT INTO `applications` (`name`, `slug`, `description`) VALUES ('ETAObserverClient','client','ETA observer console for clients');
INSERT INTO `applications` (`name`, `slug`, `description`) VALUES ('ETAObserverWarehouse','warehouse','ETA observer console for warehouse');
-- Roles for ETAConsole application (1)
INSERT INTO `roles` (`application_id`,`name`, `description`) VALUES (1,'owner', '(ETAConsole): Owner of the company');
INSERT INTO `roles` (`application_id`,`name`, `description`) VALUES (1,'manager', '(ETAConsole): Manager of the company');
INSERT INTO `roles` (`application_id`,`name`, `description`) VALUES (1,'driver', '(ETAConsole): Driver user type');
INSERT INTO `roles` (`application_id`,`name`, `description`) VALUES (1,'staff', '(ETAConsole): Member of the staff');
INSERT INTO `roles` (`application_id`,`name`, `description`) VALUES (1,'warehouse', '(ETAConsole): Observer type of member');
-- Roles for ETADriver application (2)
INSERT INTO `roles` (`application_id`,`name`, `description`) VALUES (2,'driver', '(ETADriver): Driver user type');
-- Roles for ETAObserverClient application (3)
INSERT INTO `roles` (`application_id`,`name`, `description`) VALUES (3,'client', '(ETAObserverClient): Client user type');
-- Roles for ETAObserverWarehouse application (4)
INSERT INTO `roles` (`application_id`,`name`, `description`) VALUES (4,'warehouse', '(ETAObserverWarehouse):Warehouse user type');
-- Permissions for ETAConsole application (1)
INSERT INTO `permissions` (`application_id`,`name`, `description`) VALUES (1,'owner', '(ETAConsole): Compatibility with Legacy while refactor in progress');
INSERT INTO `permissions` (`application_id`,`name`, `description`) VALUES (1,'manager', '(ETAConsole): Compatibility with Legacy while refactor in progress');
INSERT INTO `permissions` (`application_id`,`name`, `description`) VALUES (1,'driver', '(ETAConsole): Compatibility with Legacy while refactor in progress');
INSERT INTO `permissions` (`application_id`,`name`, `description`) VALUES (1,'staff', '(ETAConsole): Compatibility with Legacy while refactor in progress');
INSERT INTO `permissions` (`application_id`,`name`, `description`) VALUES (1,'warehouse', '(ETAConsole): Compatibility with Legacy while refactor in progress');
-- Permissions for ETADriver application (2)
INSERT INTO `permissions` (`application_id`,`name`, `description`) VALUES (2,'driver', '(ETADriver): Compatibility with Legacy while refactor in progress');
-- Permissions for ETAObserverClient application (3)
INSERT INTO `permissions` (`application_id`,`name`, `description`) VALUES (3,'client', '(ETAObserverClient): Compatibility with Legacy while refactor in progress');
-- Permissions for ETAObserverWarehouse application (4)
INSERT INTO `permissions` (`application_id`,`name`, `description`) VALUES (4,'warehouse', '(ETAObserverWarehouse): Compatibility with Legacy while refactor in progress');
-- Role-Permissions link for ETAConsole application (1)
INSERT INTO `role_permissions` (`role_id`, `permission_id`) VALUES (1,1);
INSERT INTO `role_permissions` (`role_id`, `permission_id`) VALUES (2,2);
INSERT INTO `role_permissions` (`role_id`, `permission_id`) VALUES (3,3);
INSERT INTO `role_permissions` (`role_id`, `permission_id`) VALUES (4,4);
INSERT INTO `role_permissions` (`role_id`, `permission_id`) VALUES (5,5);
-- Role-Permissions link for ETADriver application (2)
INSERT INTO `role_permissions` (`role_id`, `permission_id`) VALUES (6,6);
-- Role-Permissions link for ETAObserverClient application (3)
INSERT INTO `role_permissions` (`role_id`, `permission_id`) VALUES (7,7);
-- Role-Permissions link for ETAObserverWarehouse application (4)
INSERT INTO `role_permissions` (`role_id`, `permission_id`) VALUES (8,8);

View File

@@ -0,0 +1,193 @@
# ETA's Core API (Draft)
The following is a draft model for the list of resources the core API exposes:
- The list will give an idea of the interaction with the API from the clients perspective.
- The list gives an idea of the resources and operations available within the system, to use that information to create the permissions for every resource for every operation.
- This list will be translated into user stories in a document shared in a sharepoint for traceability and reproducibility.
## API Principles
- Applications are the main element of the RBAC system, each application has certain access to the ETA Core resources, like loads, companies directory, among others.
- Each Application has it's own set of permissions.
- Each Application has it's own set of roles with permissions associated.
- Each Application has it's own set of user_sessions.
- New users shall be created and directly assigned to an application.
- Any user shall be able to exists in more than one application at the same time.
- Users may have permissions assigned within an application where it belongs to.
- Users shall have roles assigned within an application where it belongs to.
- Users may have apikeys assigned within an application where it belongs to.
- Users may have sessions assigned within an application where it belongs to.
- Users may have multiple identities, but only one of each category (phone, email).
- Only one identity shall be the main user's identity.
- All resources shall have a list of operations allowed.
- System shall allow an operation to be perform over a resource only if the permission allows it.
- No resource is modified without any type of permission validation:
- User identified by JWT: The JWT is used to retrive the permissions list and use it to validate the authorization.
- User identified by APIKey: The APIKey is used to retrive the permissions list and use it to validate the authorization.
### Identified resources:
- **Companies**: A company is represented with a name and description of their operations, it belongs to one of the types: Shipper, Carrier.
- **Company_Documents**: A company documentation stored in an external BLOB solution, this documentation is part of company register procress.
- **Vehicles**: A vehicle to transport goods, used by the Carrier company to make a proposal. An employee can be assigned to only one vehicle at a time.
- **Vehicle_Documents**: Vehicle's documents to legally register it into the system. (Determine if a vehicle requires a registration process).
- **Locations**: A geographical location important to the company, represents warehouses, either owned warehouses or client's warehouses where the goods need to arraive or be loaded.
- **Company_Employees**: User's assigned to the company, the employees shall have at most one of the following predefined roles: `admin`, `staff`, `readonly`, `driver`.
- **Proposals**: A shipment proposal made by the Carrier company, which exposes the public information about the vehicle and the company itself.
- **Loads**: It represents a publication of load to be transported, created by a Shipper company. A load shall be able to receive many proposals, but only accept one. Accepting a proposal creates the unique `shipment_agreement` resource into the load.
- **Load_Templates**: It holds common values to help the user quickly create loads on the front-end.
- **Shipments**: It represents the transport operation of the goods, it is always linked and identified (searched) using the loads identifier.
- When a load is published, the load object is modifiable by the Shipper company only. (Created by)
- When a proposal is sent, the proposal object is modifiable by the Carrier company only. (Created by)
- When an accepted proposal creates the agreement, the agreement is modified by the Shipper only, the load then exposes the agreement and the rest of the shipment details as part of the view, but in read only mode. For example: Loads.shipment, Loads.shipment_evidences, etc.
- The Shipment is always associated to a load, when the user cancels the shipment with a Carrier, the shipment is not deleted, but reused for the next agreement.
- The user that has the role of driver, reads the associated Load, but only modifies the shipment related tables/objects: load_shipment (GPS tracking, and transport state), shipment_evidences.
## Proposal of endpoints to expose the resources.
Draft of software requirements specification (SRS) to model API endpoints and its responsabilities.
- **/meta/applications**:
- **Operations**:
- Create application. (idempotency through client UUID)
- Read applications
- Update applications
- Delete applications
- **/apps/{app_id}/roles**:
- **Operations**:
- Create application roles. (idempotency through client UUID)
- Read application roles
- Update application roles
- Delete application roles
- **/apps/{app_id}/permissions**:
- **Operations**:
- Create application permissions. (idempotency through client UUID)
- Read application permissions
- Update application permissions
- Delete application permissions
- **/apps/{app_id}/users/{user_id}/roles**:
- **Operations**:
- Assign roles to user
- Delete roles from user
- Read roles from user
- **/apps/{app_id}/users/{user_id}/permissions**:
- **Operations**:
- Assign permission to user
- Delete permission to user
- Read permissions assigned to user
- **/apps/{app_id}/users/{user_id}/apikeys**:
- **Operations**:
- Create apikeys. (idempotency through client UUID)
- Read apikeys
- Delete apikeys
- **/apps/{app_id}/auth**:
- **Operations**:
- Manage authentication of user:
- **/app/{app_id}/auth/identity/[phone,email]**:
- Identify user and return JWT.
- Create user and assign to application. (idempotency through client UUID)
- **/app/{app_id}/auth/identity/[phone,email]/verify**:
- Verify identity and assign to application. (idempotency through client UUID)
- **/app/{app_id}/auth/logout**:
- **/app/{app_id}/auth/refresh**:
- **/app/{app_id}/auth/me**:
- **/companies/{company_id}** -> Specific company data or own company updates
- **/companies/{company_id}/documents**
- **/companies/{company_id}/vehicles**
- **/companies/{company_id}/vehicles/{vehicle_id}/documents**
- **/companies/{company_id}/locations**
- **/companies/{company_id}/sectors**
- **/companies/{company_id}/vehicle_types**
- **/companies/{company_id}/privacy_groups**
- **/companies/{company_id}/privacy_groups/{group_id}**
- **/companies/{company_id}/employees** <> Search for users, and add/remove users to the company. Create identities or create users.
- **/companies/{company_id}/loads** <> Available resources expected on Shippers only
- **/companies/{company_id}/loads/templates**
- **/companies/{company_id}/loads/templates/{template_id}**
- **/companies/{company_id}/loads/{load_id}**
- **/companies/{company_id}/proposals** <> Available resources expected on Carriers only
- **/companies/{company_id}/proposals/{proposal_id}**
- **/shipments** <> Availble resources for both Shipper and Carrier. (TODO: How to split for writing operations, reading and sharing among companies?)
- **/shipments/{shipment_id}**
- **/shipments/{shipment_id}/evidences**
- **/shipments/{shipment_id}/evidences/{evidence_id}**
- **/shipments/{shipment_id}/proposal**
- **/shipments/{shipment_id}/agreement**
- **/directories/companies** <> Search for public companies
- **/directories/loads** <> Search for private companies
# Admin Authorization Strategy:
The system shall have a predefined system application to control all resources.
The system application can't be removed.
The system application shall have predefined permissions and roles to control the access to all resources at different granularity levels:
- CRUD of applications.
- CRUD of applications' roles.
- CRUD of applications' permissions.
- CRUD of applications' users.
- CRUD of applications' apikeys.
- etc.
The system application shall have an admin user with only apikeys and no identities.
The system application's admin user shall have permissions assigned to manage applications.
The system application's admin user shall have permissions assigned to manage users.
The system application's admin user shall have permissions assigned to manage roles and permissions within applications.
The system application's admin user shall have permissions assigned to manage apikeys within applications.
The system application's admin user shall not have full control over the system resources.* (No other resource than users, roles, permissions)
Every application shall have an admin user with only apikeys and no identities.
Every application shall have an admin user to manage application resources.
Every application shall have an admin user to manage users within applications:
- Shall allow assigning or removing existing users to/from applications.
- Shall allow create and assign users to applications.
The application's admin user shall not have full control over the application resources.* (No other resource than users, roles, permissions)
Every application shall have it's own API that serves as an API wrapper to consume system resources.
Every application shall have it's own API that serves as an API wrapper to consume application resources.
Every application specific API shall use the user's authorization token or apikey to consume application's resources.
(Admin Portal shall have it's own API that communicates with the core API to manage system resources associated to the system and the application components).
(Admin Portal shall have it's own API key to only create users and assign roles to it).
(Admin Portal shall modify system resources by the usage of a JWT of an identified user to enable audit logs of resources manipulation).
# Idempotency Strategy:
When a resource requires "idempotency", the HTTP header `X-Idempotency-Key` must be provided with an UUID generated from the client.
# Authorization Tokens (Core API):
When API Key is used, the HTTP header `x-api-key: <apikey>` shall be used.*
When JWT is used, the HTTP header `Authorization: Bearer <jwt>` shall be used.
When JWT refresh is used, the HTTP header `x-refresh-token: <refresh_token>` shall be used.
Every application's specific API (also known as API wrapper) shall use it's own authorization mechanisms.