diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..6792c6d --- /dev/null +++ b/.env.example @@ -0,0 +1,5 @@ +AUTH_SECRET="pkUz8HbyyGXXPVjic4M5I++dGEkrHr6tr9o9O7ZmyUg=" +PASSWORD_SALT= +GH_CLIENT_ID= +GH_CLIENT_SECRET= +RESEND_API_KEY= \ No newline at end of file diff --git a/.github/workflows/deploy-docs.yml b/.github/workflows/deploy-docs.yml index 762dec0..337fcd3 100644 --- a/.github/workflows/deploy-docs.yml +++ b/.github/workflows/deploy-docs.yml @@ -30,13 +30,13 @@ jobs: - name: Build Docusaurus website run: | - cd apps/fabriclaunch-docs + cd apps/docs bun run build - name: Deploy to GitHub Pages uses: peaceiris/actions-gh-pages@v3 with: github_token: ${{ secrets.GITHUB_TOKEN }} - publish_dir: ./apps/fabriclaunch-docs/build + publish_dir: ./apps/docs/build user_name: 'github-actions[bot]' user_email: 'github-actions[bot]@users.noreply.github.com' \ No newline at end of file diff --git a/README.md b/README.md index ab3674f..6f8d46b 100644 --- a/README.md +++ b/README.md @@ -152,4 +152,4 @@ We focus on baremetal deployment because: ## Next Steps -Documentation coming soon. You can find the markdowns on the [GitHub repository](https://github.com/kfsoftware/fabriclaunch/tree/main/apps/fabriclaunch-docs/docs). +Documentation coming soon. You can find the markdowns on the [GitHub repository](https://github.com/kfsoftware/fabriclaunch/tree/main/apps/docs/docs). diff --git a/apps/fabriclaunch-docs/.gitignore b/apps/docs/.gitignore similarity index 100% rename from apps/fabriclaunch-docs/.gitignore rename to apps/docs/.gitignore diff --git a/apps/fabriclaunch-docs/README.md b/apps/docs/README.md similarity index 100% rename from apps/fabriclaunch-docs/README.md rename to apps/docs/README.md diff --git a/apps/fabriclaunch-docs/babel.config.js b/apps/docs/babel.config.js similarity index 100% rename from apps/fabriclaunch-docs/babel.config.js rename to apps/docs/babel.config.js diff --git a/apps/fabriclaunch-docs/blog/2019-05-28-first-blog-post.md b/apps/docs/blog/2019-05-28-first-blog-post.md similarity index 100% rename from apps/fabriclaunch-docs/blog/2019-05-28-first-blog-post.md rename to apps/docs/blog/2019-05-28-first-blog-post.md diff --git a/apps/fabriclaunch-docs/blog/2019-05-29-long-blog-post.md b/apps/docs/blog/2019-05-29-long-blog-post.md similarity index 100% rename from apps/fabriclaunch-docs/blog/2019-05-29-long-blog-post.md rename to apps/docs/blog/2019-05-29-long-blog-post.md diff --git a/apps/fabriclaunch-docs/blog/2021-08-01-mdx-blog-post.mdx b/apps/docs/blog/2021-08-01-mdx-blog-post.mdx similarity index 100% rename from apps/fabriclaunch-docs/blog/2021-08-01-mdx-blog-post.mdx rename to apps/docs/blog/2021-08-01-mdx-blog-post.mdx diff --git a/apps/fabriclaunch-docs/blog/2021-08-26-welcome/docusaurus-plushie-banner.jpeg b/apps/docs/blog/2021-08-26-welcome/docusaurus-plushie-banner.jpeg similarity index 100% rename from apps/fabriclaunch-docs/blog/2021-08-26-welcome/docusaurus-plushie-banner.jpeg rename to apps/docs/blog/2021-08-26-welcome/docusaurus-plushie-banner.jpeg diff --git a/apps/fabriclaunch-docs/blog/2021-08-26-welcome/index.md b/apps/docs/blog/2021-08-26-welcome/index.md similarity index 100% rename from apps/fabriclaunch-docs/blog/2021-08-26-welcome/index.md rename to apps/docs/blog/2021-08-26-welcome/index.md diff --git a/apps/fabriclaunch-docs/blog/authors.yml b/apps/docs/blog/authors.yml similarity index 100% rename from apps/fabriclaunch-docs/blog/authors.yml rename to apps/docs/blog/authors.yml diff --git a/apps/fabriclaunch-docs/blog/tags.yml b/apps/docs/blog/tags.yml similarity index 100% rename from apps/fabriclaunch-docs/blog/tags.yml rename to apps/docs/blog/tags.yml diff --git a/apps/fabriclaunch-docs/bun.lockb b/apps/docs/bun.lockb similarity index 100% rename from apps/fabriclaunch-docs/bun.lockb rename to apps/docs/bun.lockb diff --git a/apps/docs/docs/deployments/_category_.json b/apps/docs/docs/deployments/_category_.json new file mode 100644 index 0000000..e0e8c7c --- /dev/null +++ b/apps/docs/docs/deployments/_category_.json @@ -0,0 +1,3 @@ +{ + "label": "Deployment options" +} \ No newline at end of file diff --git a/infra/digitalocean/main.tf b/apps/docs/docs/deployments/digitalocean.md similarity index 68% rename from infra/digitalocean/main.tf rename to apps/docs/docs/deployments/digitalocean.md index 871f04e..8de3e3e 100644 --- a/infra/digitalocean/main.tf +++ b/apps/docs/docs/deployments/digitalocean.md @@ -1,3 +1,16 @@ +--- +sidebar_position: 1 +--- + +# Deployment on DigitalOcean + +## Terraform project + +### main.tf + +To provision virtual machines on DigitalOcean, you can use Terraform. Terraform is an open-source infrastructure as code software tool that provides a consistent CLI workflow to manage hundreds of cloud services. Terraform codifies cloud APIs into declarative configuration files. + +```hcl title="main.tf" terraform { required_providers { digitalocean = { @@ -130,3 +143,60 @@ output "droplet_ips" { droplet.name => droplet.ipv4_address } } + +``` +### variables.tf + +Then, you need to declare the variables in a `variables.tf` file: + +```hcl title="variables.tf" +variable "do_token" { + description = "DigitalOcean API Token" + type = string + sensitive = true +} + +variable "regions" { + description = "List of regions for droplet deployment" + type = list(string) + default = ["nyc1", "fra1", "blr1"] +} +variable "vm_names" { + description = "List of VM names" + type = list(string) +} +``` + +To avoid hardcoding the DigitalOcean API token in the `terraform.tfvars` file, you can use the `TF_VAR_do_token` environment variable: + +```bash +export TF_VAR_do_token="your_digitalocean_api_token" +``` + +Finally, you can create a `terraform.tfvars` file to specify the values for the variables: + +```hcl title="terraform.tfvars" +regions = ["nyc1", "fra1", "blr1"] + +vm_names = ["org1", "org2", "org3"] +``` + +## Execute Terraform + +To execute the Terraform project, you can run the following commands: + +```bash +terraform init +terraform apply +``` + +Then, you can access the virtual machines using the private key file `id_rsa`: + +```bash +ssh -i id_rsa root@ +``` + +Each of the virtual machines will have the FabricLaunch CLI installed. You can use the FabricLaunch CLI to create nodes and networks on the virtual machines. + + +You can see the [`Getting started`](../getting-started.md) guide to learn how to deploy the FabricLaunch CLI. The IPs is the only thing that changes, apart from not using the 'localho.st' domain, in this case, you need to use the ip as the domain. \ No newline at end of file diff --git a/apps/fabriclaunch-docs/docs/getting-started.md b/apps/docs/docs/getting-started.md similarity index 95% rename from apps/fabriclaunch-docs/docs/getting-started.md rename to apps/docs/docs/getting-started.md index a520629..e485aff 100644 --- a/apps/fabriclaunch-docs/docs/getting-started.md +++ b/apps/docs/docs/getting-started.md @@ -221,16 +221,14 @@ fabriclaunch channel propose multilocation \ # at this point, a notification should be sent to the other organizations to accept the channel proposal -export CHANNEL_PROPOSAL_ID="prop_multilocation_1721134780228" +export CHANNEL_PROPOSAL_ID="" + fabriclaunch channel accept "${CHANNEL_PROPOSAL_ID}" -o NYCMSP --tenant ${TENANT_NAME} -export CHANNEL_PROPOSAL_ID="prop_multilocation_1721134780228" fabriclaunch channel accept "${CHANNEL_PROPOSAL_ID}" -o FRAMSP --tenant ${TENANT_NAME} -export CHANNEL_PROPOSAL_ID="prop_multilocation_1721134780228" fabriclaunch channel accept "${CHANNEL_PROPOSAL_ID}" -o BLRMSP --tenant ${TENANT_NAME} -export CHANNEL_PROPOSAL_ID="prop_multilocation_1721134780228" fabriclaunch consensus create "${CHANNEL_PROPOSAL_ID}" -o NYCMSP --tenant ${TENANT_NAME} fabriclaunch consensus create "${CHANNEL_PROPOSAL_ID}" -o FRAMSP --tenant ${TENANT_NAME} @@ -254,7 +252,7 @@ fabriclaunch chaincode propose fabcar --mspId=NYCMSP --chaincodePath=$PWD/chainc --pdc="$PWD/pdc.json" -export CH_PROPOSAL_ID="prop_multilocation_fabcar_7_1720979349091" +export CH_PROPOSAL_ID="" fabriclaunch chaincode accept ${CH_PROPOSAL_ID} -o NYCMSP --chaincodeAddress="127.0.0.1:20000" --tenant ${TENANT_NAME} fabriclaunch chaincode accept ${CH_PROPOSAL_ID} -o FRAMSP --chaincodeAddress="127.0.0.1:20000" --tenant ${TENANT_NAME} @@ -263,13 +261,10 @@ fabriclaunch chaincode accept ${CH_PROPOSAL_ID} -o BLRMSP --chaincodeAddress="12 # this line commits the chaincode to the channel fabriclaunch chaincode commit ${CH_PROPOSAL_ID} -o NYCMSP --tenant ${TENANT_NAME} -export CH_PROPOSAL_ID="prop_multilocation_fabcar_7_1720979349091" fabriclaunch chaincode run ${CH_PROPOSAL_ID} --tenant ${TENANT_NAME} --mode=systemd --download --org=NYCMSP --chaincodeAddress="127.0.0.1:20000" -export CH_PROPOSAL_ID="prop_multilocation_fabcar_7_1720979349091" fabriclaunch chaincode run ${CH_PROPOSAL_ID} --tenant ${TENANT_NAME} --mode=systemd --download --org=FRAMSP --chaincodeAddress="127.0.0.1:20000" -export CH_PROPOSAL_ID="prop_multilocation_fabcar_7_1720979349091" fabriclaunch chaincode run ${CH_PROPOSAL_ID} --tenant ${TENANT_NAME} --mode=systemd --download --org=BLRMSP --chaincodeAddress="127.0.0.1:20000" diff --git a/apps/docs/docs/installation.md b/apps/docs/docs/installation.md new file mode 100644 index 0000000..9e8f86c --- /dev/null +++ b/apps/docs/docs/installation.md @@ -0,0 +1,68 @@ +--- +sidebar_position: 3 +--- +# Installation + +At the time of writing, fabriclaunch has only been tested with Ubuntu 22.04 and 24.04. + +These are the tools you'll need to install: + +- **cfssl**: to generate certificates and certificate authorities (CAs) +- **Golang**: to run chaincodes +- **Fabric tools**: to interact with the Hyperledger Fabric network, including: + + **peer**: to run peers + + **orderer**: to run orderers + + **osnadmin**: to join the ordering service nodes to the channel + + **discover**: to discover peers in the channel +- **fabriclaunch**: to create and manage your Hyperledger Fabric network + + +## Install cfssl + +To install cfssl, run the following commands: + +```bash{"title": "xx"} +wget https://github.com/cloudflare/cfssl/releases/download/v1.6.5/cfssl_1.6.5_linux_amd64 -O /usr/local/bin/cfssl +wget https://github.com/cloudflare/cfssl/releases/download/v1.6.5/cfssljson_1.6.5_linux_amd64 -O /usr/local/bin/cfssljson +chmod +x /usr/local/bin/cfssl +chmod +x /usr/local/bin/cfssljson +``` + +## Install Golang + +To install Golang, run the following commands: + +```bash +wget "https://go.dev/dl/go1.22.5.linux-amd64.tar.gz" +sudo tar -C /usr/local -xzf go*.tar.gz +export PATH=$PATH:/usr/local/go/bin +``` + +## Install Fabric tools + +To install the Fabric tools, run the following commands: + +```bash +curl -sSLO https://raw.githubusercontent.com/hyperledger/fabric/main/scripts/install-fabric.sh +chmod +x install-fabric.sh +./install-fabric.sh --fabric-version 2.5.9 binary + +# and then move the binaries to your PATH + +mv bin/discover /usr/local/bin/discover +mv bin/orderer /usr/local/bin/orderer +mv bin/osnadmin /usr/local/bin/osnadmin +mv bin/peer /usr/local/bin/peer +``` + + +## Install fabriclaunch + +To install fabriclaunch, run the following commands: + +```bash +wget https://fabriclaunch.com/fabriclaunch +chmod +x fabriclaunch +mv fabriclaunch /usr/local/bin/fabriclaunch +``` + diff --git a/apps/fabriclaunch-docs/docs/introduction.md b/apps/docs/docs/introduction.md similarity index 100% rename from apps/fabriclaunch-docs/docs/introduction.md rename to apps/docs/docs/introduction.md diff --git a/apps/docs/docs/platform/_category_.json b/apps/docs/docs/platform/_category_.json new file mode 100644 index 0000000..56a80a3 --- /dev/null +++ b/apps/docs/docs/platform/_category_.json @@ -0,0 +1,3 @@ +{ + "label": "Platform deployment" +} \ No newline at end of file diff --git a/apps/docs/docs/platform/docker-compose.md b/apps/docs/docs/platform/docker-compose.md new file mode 100644 index 0000000..94df575 --- /dev/null +++ b/apps/docs/docs/platform/docker-compose.md @@ -0,0 +1,89 @@ +--- +sidebar_position: 2 +--- + +# Using Docker Compose + +## Prerequisites: + +1. Ensure Docker and Docker Compose are installed on your system. +2. Git should be installed to clone the repository. + +## Step-by-step Instructions: + +1. Clone the repository: + ```bash + git clone https://github.com/kfsoftware/fabriclaunch.git + cd fabriclaunch + ``` + +2. Set up environment variables: + ```bash + cp .env.example .env + ``` + Edit the `.env` file and fill in the required values: + - `AUTH_SECRET` is already set, but you can generate a new one with: + ```bash + openssl rand -hex 32 + ``` + - Set `PASSWORD_SALT` (you can use the same method as `AUTH_SECRET`) + - Add your GitHub OAuth credentials for `GH_CLIENT_ID` and `GH_CLIENT_SECRET` + - Add your Resend API key for `RESEND_API_KEY` + +3. Build the Docker images: + ```bash + docker-compose build + ``` + +4. Start the services: + ```bash + docker-compose up + ``` + Or in detached mode: + ```bash + docker-compose up -d + ``` + +5. Wait for the services to start up. You should see logs indicating that the services are ready. + +6. Open a web browser and navigate to: + ``` + http://localhost:3000/dashboard + ``` + +7. If everything is working correctly, you should see the dashboard of your FabricLaunch application. + +## Troubleshooting: + +- Check Docker logs: + ```bash + docker-compose logs + ``` +- Check logs for a specific service: + ```bash + docker-compose logs web + ``` +- Ensure ports 3000, 5432, 9000, and 9001 are not in use by other applications. +- If you make changes, rebuild the images: + ```bash + docker-compose build + docker-compose up + ``` + +## Platform-specific notes: + +- Windows: Use PowerShell or Command Prompt. Ensure Docker Desktop is running. +- Mac: Use Terminal. Ensure Docker Desktop is running. +- Linux: You might need to use `sudo` before docker commands, depending on your setup. + +## Stopping the services: + +```bash +docker-compose down +``` +To remove volumes as well: +```bash +docker-compose down -v +``` + +By following these steps, you should be able to launch FabricLaunch on any machine (Linux, Windows, or Mac) and access the dashboard at http://localhost:3000/dashboard to verify that it's working correctly. diff --git a/apps/fabriclaunch-docs/docusaurus.config.ts b/apps/docs/docusaurus.config.ts similarity index 98% rename from apps/fabriclaunch-docs/docusaurus.config.ts rename to apps/docs/docusaurus.config.ts index 8370b57..d9f9e9f 100644 --- a/apps/fabriclaunch-docs/docusaurus.config.ts +++ b/apps/docs/docusaurus.config.ts @@ -130,7 +130,7 @@ const config: Config = { copyright: `Copyright © ${new Date().getFullYear()} FabricLaunch. Built with Docusaurus.`, }, prism: { - additionalLanguages: ['bash'], + additionalLanguages: ['bash', 'hcl'], theme: prismThemes.github, darkTheme: prismThemes.dracula, }, diff --git a/apps/fabriclaunch-docs/package.json b/apps/docs/package.json similarity index 100% rename from apps/fabriclaunch-docs/package.json rename to apps/docs/package.json diff --git a/apps/fabriclaunch-docs/sidebars.ts b/apps/docs/sidebars.ts similarity index 100% rename from apps/fabriclaunch-docs/sidebars.ts rename to apps/docs/sidebars.ts diff --git a/apps/fabriclaunch-docs/src/components/HomepageFeatures/index.tsx b/apps/docs/src/components/HomepageFeatures/index.tsx similarity index 100% rename from apps/fabriclaunch-docs/src/components/HomepageFeatures/index.tsx rename to apps/docs/src/components/HomepageFeatures/index.tsx diff --git a/apps/fabriclaunch-docs/src/components/HomepageFeatures/styles.module.css b/apps/docs/src/components/HomepageFeatures/styles.module.css similarity index 100% rename from apps/fabriclaunch-docs/src/components/HomepageFeatures/styles.module.css rename to apps/docs/src/components/HomepageFeatures/styles.module.css diff --git a/apps/fabriclaunch-docs/src/css/custom.css b/apps/docs/src/css/custom.css similarity index 100% rename from apps/fabriclaunch-docs/src/css/custom.css rename to apps/docs/src/css/custom.css diff --git a/apps/fabriclaunch-docs/src/pages/index.module.css b/apps/docs/src/pages/index.module.css similarity index 100% rename from apps/fabriclaunch-docs/src/pages/index.module.css rename to apps/docs/src/pages/index.module.css diff --git a/apps/fabriclaunch-docs/src/pages/index.tsx b/apps/docs/src/pages/index.tsx similarity index 100% rename from apps/fabriclaunch-docs/src/pages/index.tsx rename to apps/docs/src/pages/index.tsx diff --git a/apps/fabriclaunch-docs/src/pages/markdown-page.md b/apps/docs/src/pages/markdown-page.md similarity index 100% rename from apps/fabriclaunch-docs/src/pages/markdown-page.md rename to apps/docs/src/pages/markdown-page.md diff --git a/apps/fabriclaunch-docs/static/.nojekyll b/apps/docs/static/.nojekyll similarity index 100% rename from apps/fabriclaunch-docs/static/.nojekyll rename to apps/docs/static/.nojekyll diff --git a/apps/fabriclaunch-docs/static/img/docusaurus-social-card.jpg b/apps/docs/static/img/docusaurus-social-card.jpg similarity index 100% rename from apps/fabriclaunch-docs/static/img/docusaurus-social-card.jpg rename to apps/docs/static/img/docusaurus-social-card.jpg diff --git a/apps/fabriclaunch-docs/static/img/docusaurus.png b/apps/docs/static/img/docusaurus.png similarity index 100% rename from apps/fabriclaunch-docs/static/img/docusaurus.png rename to apps/docs/static/img/docusaurus.png diff --git a/apps/fabriclaunch-docs/static/img/fabriclaunch.png b/apps/docs/static/img/fabriclaunch.png similarity index 100% rename from apps/fabriclaunch-docs/static/img/fabriclaunch.png rename to apps/docs/static/img/fabriclaunch.png diff --git a/apps/fabriclaunch-docs/static/img/fabriclaunch_2.jpeg b/apps/docs/static/img/fabriclaunch_2.jpeg similarity index 100% rename from apps/fabriclaunch-docs/static/img/fabriclaunch_2.jpeg rename to apps/docs/static/img/fabriclaunch_2.jpeg diff --git a/apps/fabriclaunch-docs/static/img/fabriclaunch_2.png b/apps/docs/static/img/fabriclaunch_2.png similarity index 100% rename from apps/fabriclaunch-docs/static/img/fabriclaunch_2.png rename to apps/docs/static/img/fabriclaunch_2.png diff --git a/apps/fabriclaunch-docs/static/img/fabriclaunch_social.png b/apps/docs/static/img/fabriclaunch_social.png similarity index 100% rename from apps/fabriclaunch-docs/static/img/fabriclaunch_social.png rename to apps/docs/static/img/fabriclaunch_social.png diff --git a/apps/fabriclaunch-docs/static/img/favicon.ico b/apps/docs/static/img/favicon.ico similarity index 100% rename from apps/fabriclaunch-docs/static/img/favicon.ico rename to apps/docs/static/img/favicon.ico diff --git a/apps/fabriclaunch-docs/static/img/logo.svg b/apps/docs/static/img/logo.svg similarity index 100% rename from apps/fabriclaunch-docs/static/img/logo.svg rename to apps/docs/static/img/logo.svg diff --git a/apps/fabriclaunch-docs/static/img/undraw_docusaurus_mountain.svg b/apps/docs/static/img/undraw_docusaurus_mountain.svg similarity index 100% rename from apps/fabriclaunch-docs/static/img/undraw_docusaurus_mountain.svg rename to apps/docs/static/img/undraw_docusaurus_mountain.svg diff --git a/apps/fabriclaunch-docs/static/img/undraw_docusaurus_react.svg b/apps/docs/static/img/undraw_docusaurus_react.svg similarity index 100% rename from apps/fabriclaunch-docs/static/img/undraw_docusaurus_react.svg rename to apps/docs/static/img/undraw_docusaurus_react.svg diff --git a/apps/fabriclaunch-docs/static/img/undraw_docusaurus_tree.svg b/apps/docs/static/img/undraw_docusaurus_tree.svg similarity index 100% rename from apps/fabriclaunch-docs/static/img/undraw_docusaurus_tree.svg rename to apps/docs/static/img/undraw_docusaurus_tree.svg diff --git a/apps/fabriclaunch-docs/tsconfig.json b/apps/docs/tsconfig.json similarity index 100% rename from apps/fabriclaunch-docs/tsconfig.json rename to apps/docs/tsconfig.json diff --git a/apps/hlf-manager/.gitignore b/apps/hlf-manager/.gitignore deleted file mode 100644 index 9b1ee42..0000000 --- a/apps/hlf-manager/.gitignore +++ /dev/null @@ -1,175 +0,0 @@ -# Based on https://raw.githubusercontent.com/github/gitignore/main/Node.gitignore - -# Logs - -logs -_.log -npm-debug.log_ -yarn-debug.log* -yarn-error.log* -lerna-debug.log* -.pnpm-debug.log* - -# Caches - -.cache - -# Diagnostic reports (https://nodejs.org/api/report.html) - -report.[0-9]_.[0-9]_.[0-9]_.[0-9]_.json - -# Runtime data - -pids -_.pid -_.seed -*.pid.lock - -# Directory for instrumented libs generated by jscoverage/JSCover - -lib-cov - -# Coverage directory used by tools like istanbul - -coverage -*.lcov - -# nyc test coverage - -.nyc_output - -# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) - -.grunt - -# Bower dependency directory (https://bower.io/) - -bower_components - -# node-waf configuration - -.lock-wscript - -# Compiled binary addons (https://nodejs.org/api/addons.html) - -build/Release - -# Dependency directories - -node_modules/ -jspm_packages/ - -# Snowpack dependency directory (https://snowpack.dev/) - -web_modules/ - -# TypeScript cache - -*.tsbuildinfo - -# Optional npm cache directory - -.npm - -# Optional eslint cache - -.eslintcache - -# Optional stylelint cache - -.stylelintcache - -# Microbundle cache - -.rpt2_cache/ -.rts2_cache_cjs/ -.rts2_cache_es/ -.rts2_cache_umd/ - -# Optional REPL history - -.node_repl_history - -# Output of 'npm pack' - -*.tgz - -# Yarn Integrity file - -.yarn-integrity - -# dotenv environment variable files - -.env -.env.development.local -.env.test.local -.env.production.local -.env.local - -# parcel-bundler cache (https://parceljs.org/) - -.parcel-cache - -# Next.js build output - -.next -out - -# Nuxt.js build / generate output - -.nuxt -dist - -# Gatsby files - -# Comment in the public line in if your project uses Gatsby and not Next.js - -# https://nextjs.org/blog/next-9-1#public-directory-support - -# public - -# vuepress build output - -.vuepress/dist - -# vuepress v2.x temp and cache directory - -.temp - -# Docusaurus cache and generated files - -.docusaurus - -# Serverless directories - -.serverless/ - -# FuseBox cache - -.fusebox/ - -# DynamoDB Local files - -.dynamodb/ - -# TernJS port file - -.tern-port - -# Stores VSCode versions used for testing VSCode extensions - -.vscode-test - -# yarn v2 - -.yarn/cache -.yarn/unplugged -.yarn/build-state.yml -.yarn/install-state.gz -.pnp.* - -# IntelliJ based IDEs -.idea - -# Finder (MacOS) folder config -.DS_Store diff --git a/apps/hlf-manager/README.md b/apps/hlf-manager/README.md deleted file mode 100644 index 08339f9..0000000 --- a/apps/hlf-manager/README.md +++ /dev/null @@ -1,15 +0,0 @@ -# hlf-manager - -To install dependencies: - -```bash -bun install -``` - -To run: - -```bash -bun run index.ts -``` - -This project was created using `bun init` in bun v1.1.18. [Bun](https://bun.sh) is a fast all-in-one JavaScript runtime. diff --git a/apps/hlf-manager/package.json b/apps/hlf-manager/package.json deleted file mode 100644 index b5f4c23..0000000 --- a/apps/hlf-manager/package.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "name": "hlf-manager", - "module": "index.ts", - "type": "module", - "devDependencies": { - "@types/bun": "latest" - }, - "peerDependencies": { - "typescript": "^5.0.0" - }, - "dependencies": { - "@repo/hlf-node": "*", - "@types/express": "^4.17.21", - "express": "^4.19.2" - } -} \ No newline at end of file diff --git a/apps/hlf-manager/src/index.ts b/apps/hlf-manager/src/index.ts deleted file mode 100644 index 69614ff..0000000 --- a/apps/hlf-manager/src/index.ts +++ /dev/null @@ -1,13 +0,0 @@ -import express from 'express'; - -const app = express(); - -const PORT = process.env.PORT || 3060; - -app.get("/", (req, res) => { - res.send("Hello World!"); -}) - -app.listen(PORT, () => { - console.log(`Server is running on port ${PORT}`); -}) \ No newline at end of file diff --git a/apps/hlf-manager/tsconfig.json b/apps/hlf-manager/tsconfig.json deleted file mode 100644 index 238655f..0000000 --- a/apps/hlf-manager/tsconfig.json +++ /dev/null @@ -1,27 +0,0 @@ -{ - "compilerOptions": { - // Enable latest features - "lib": ["ESNext", "DOM"], - "target": "ESNext", - "module": "ESNext", - "moduleDetection": "force", - "jsx": "react-jsx", - "allowJs": true, - - // Bundler mode - "moduleResolution": "bundler", - "allowImportingTsExtensions": true, - "verbatimModuleSyntax": true, - "noEmit": true, - - // Best practices - "strict": true, - "skipLibCheck": true, - "noFallthroughCasesInSwitch": true, - - // Some stricter flags (disabled by default) - "noUnusedLocals": false, - "noUnusedParameters": false, - "noPropertyAccessFromIndexSignature": false - } -} diff --git a/apps/web/.env.example b/apps/web/.env.example index c29e2d2..6aeee49 100644 --- a/apps/web/.env.example +++ b/apps/web/.env.example @@ -1,4 +1,4 @@ -AUTH_SECRET= +AUTH_SECRET="pkUz8HbyyGXXPVjic4M5I++dGEkrHr6tr9o9O7ZmyUg=" # example, don't use this in production AUTH_DRIZZLE_URL=postgres://postgres:postgres@127.0.0.1:5432/fabriclaunch POSTGRES_URL=postgres://postgres:postgres@127.0.0.1:5432/fabriclaunch NEXT_PUBLIC_EXTERNAL_URL=http://localhost:3000 diff --git a/apps/web/Dockerfile b/apps/web/Dockerfile index 95d5b59..504e20b 100644 --- a/apps/web/Dockerfile +++ b/apps/web/Dockerfile @@ -83,6 +83,11 @@ COPY --from=build --chown=node:node /build/turbo.json ./turbo.json COPY --from=build --chown=node:node /build/package.json ./package.json # RUN chown -R node:node /app +COPY ./apps/web/start-with-migrate.sh ./apps/web/ WORKDIR /app/apps/web -CMD [ "npm", "start" ] +# Make the start script executable +RUN chmod +x start-with-migrate.sh + +# Use the start script as the CMD +CMD ["./start-with-migrate.sh"] \ No newline at end of file diff --git a/apps/web/src/auth/index.ts b/apps/web/src/auth/index.ts index 200d5d0..a9f361c 100644 --- a/apps/web/src/auth/index.ts +++ b/apps/web/src/auth/index.ts @@ -1,16 +1,110 @@ import NextAuth, { CredentialsSignin, NextAuthConfig } from "next-auth" -// Your own logic for dealing with plaintext password strings; be careful! import { accountsTable, authenticatorsTable, db, sessionsTable, usersTable, verificationTokensTable } from "@/db" -import { getOrCreateDefaultTenantForUser, getUserByEmail, getUserById } from "@/lib/logic" +import { getUserByEmail, getUserById } from "@/lib/logic" import { DrizzleAdapter } from "@auth/drizzle-adapter" +import bcrypt from "bcrypt" import { and, eq } from "drizzle-orm" -import GitHubProvider, { GitHubEmail } from "next-auth/providers/github" +import { Provider } from "next-auth/providers" import CredentialsProvider from "next-auth/providers/credentials" -import bcrypt from "bcrypt" +import GitHubProvider, { GitHubEmail } from "next-auth/providers/github" const githubApiBaseUrl = "https://api.github.com" class InvalidCredentials extends CredentialsSignin { code = "credentials" } +const providers: Provider[] = [ + CredentialsProvider({ + name: 'Credentials', + credentials: { + email: { label: "Email", type: "text", placeholder: "dviejo@kfs.es" }, + password: { label: "Password", type: "password" } + }, + async authorize(credentials) { + if (!credentials?.email || !credentials?.password) { + return null + } + const email = credentials.email as string + const user = await getUserByEmail(email) + if (!user) { + // If user doesn't exist, create a new one + const hashedPassword = await bcrypt.hash(credentials.password as string, 10) + const [{ id: userId }] = await db.insert(usersTable).values({ + email: email, + name: email.split('@')[0], // Use part of email as name + password: hashedPassword, + }).returning({ + id: usersTable.id, + }) + const newUser = await getUserById(userId) + return newUser + } + const isValid = await bcrypt.compare(credentials.password as string, user.password) + if (!isValid) { + throw new InvalidCredentials("Invalid credentials", {}) + } + return user + } + }), + +] +if (process.env.GITHUB_CLIENT_ID && process.env.GITHUB_CLIENT_SECRET) { + providers.push(GitHubProvider({ + allowDangerousEmailAccountLinking: true, + userinfo: { + url: `${githubApiBaseUrl}/user`, + async request({ tokens, provider }) { + const profile = await fetch(provider.userinfo?.url as URL, { + headers: { + Authorization: `Bearer ${tokens.access_token}`, + "User-Agent": "authjs", + }, + }).then(async (res) => await res.json() as any) + if (!profile.email) { + // If the user does not have a public email, get another via the GitHub API + // See https://docs.github.com/en/rest/users/emails#list-public-email-addresses-for-the-authenticated-user + const res = await fetch(`${githubApiBaseUrl}/user/emails`, { + headers: { + Authorization: `Bearer ${tokens.access_token}`, + "User-Agent": "authjs", + }, + }) + const responseText = await res.text() + if (res.ok) { + const emails: GitHubEmail[] = JSON.parse(responseText) + profile.email = (emails.find((e) => e.primary) ?? emails[0]).email + } + } + return profile + }, + }, + account(account) { + const refresh_token_expires_at = account.refresh_token_expires_in ? + Math.floor(Date.now() / 1000) + Number(account.refresh_token_expires_in) : null + return { + access_token: account.access_token, + expires_at: account.expires_at, + refresh_token: account.refresh_token, + refresh_token_expires_at + } + }, + profile(profile) { + return { + id: profile.id.toString(), + name: profile.name ?? profile.login, + login: profile.login, + email: profile.email, + image: profile.avatar_url, + } + }, + clientId: process.env.GH_CLIENT_ID, + clientSecret: process.env.GH_CLIENT_SECRET, + authorization: { + url: `https://github.com/login/oauth/authorize`, + params: { + scope: 'read:user,user:email,repo', + }, + }, + })) +} export const nextAuthConfig: NextAuthConfig = { adapter: DrizzleAdapter(db, { accountsTable, @@ -67,96 +161,6 @@ export const nextAuthConfig: NextAuthConfig = { return session } }, - providers: [ - CredentialsProvider({ - name: 'Credentials', - credentials: { - email: { label: "Email", type: "text", placeholder: "dviejo@kfs.es" }, - password: { label: "Password", type: "password" } - }, - async authorize(credentials) { - if (!credentials?.email || !credentials?.password) { - return null - } - const email = credentials.email as string - const user = await getUserByEmail(email) - if (!user) { - // If user doesn't exist, create a new one - const hashedPassword = await bcrypt.hash(credentials.password as string, 10) - const [{ id: userId }] = await db.insert(usersTable).values({ - email: email, - name: email.split('@')[0], // Use part of email as name - password: hashedPassword, - }).returning({ - id: usersTable.id, - }) - const newUser = await getUserById(userId) - return newUser - } - const isValid = await bcrypt.compare(credentials.password as string, user.password) - if (!isValid) { - throw new InvalidCredentials("Invalid credentials", {}) - } - return user - } - }), - GitHubProvider({ - allowDangerousEmailAccountLinking: true, - userinfo: { - url: `${githubApiBaseUrl}/user`, - async request({ tokens, provider }) { - const profile = await fetch(provider.userinfo?.url as URL, { - headers: { - Authorization: `Bearer ${tokens.access_token}`, - "User-Agent": "authjs", - }, - }).then(async (res) => await res.json() as any) - if (!profile.email) { - // If the user does not have a public email, get another via the GitHub API - // See https://docs.github.com/en/rest/users/emails#list-public-email-addresses-for-the-authenticated-user - const res = await fetch(`${githubApiBaseUrl}/user/emails`, { - headers: { - Authorization: `Bearer ${tokens.access_token}`, - "User-Agent": "authjs", - }, - }) - const responseText = await res.text() - if (res.ok) { - const emails: GitHubEmail[] = JSON.parse(responseText) - profile.email = (emails.find((e) => e.primary) ?? emails[0]).email - } - } - return profile - }, - }, - account(account) { - const refresh_token_expires_at = account.refresh_token_expires_in ? - Math.floor(Date.now() / 1000) + Number(account.refresh_token_expires_in) : null - return { - access_token: account.access_token, - expires_at: account.expires_at, - refresh_token: account.refresh_token, - refresh_token_expires_at - } - }, - profile(profile) { - return { - id: profile.id.toString(), - name: profile.name ?? profile.login, - login: profile.login, - email: profile.email, - image: profile.avatar_url, - } - }, - clientId: process.env.GH_CLIENT_ID, - clientSecret: process.env.GH_CLIENT_SECRET, - authorization: { - url: `https://github.com/login/oauth/authorize`, - params: { - scope: 'read:user,user:email,repo', - }, - }, - }), - ], + providers, } export const { handlers, signIn, signOut, auth } = NextAuth(nextAuthConfig) \ No newline at end of file diff --git a/apps/web/start-with-migrate.sh b/apps/web/start-with-migrate.sh new file mode 100755 index 0000000..f817e5e --- /dev/null +++ b/apps/web/start-with-migrate.sh @@ -0,0 +1,21 @@ +#!/bin/bash + +# Set environment variables (if needed) +export NODE_ENV=production + +# Function to check if a command was successful +check_success() { + if [ $? -ne 0 ]; then + echo "Error: $1 failed" + exit 1 + fi +} + +# Run database migrations +echo "Running database migrations..." +npx drizzle-kit migrate +check_success "Database migration" + +# Start the Next.js server +echo "Starting Next.js server..." +npm start diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..8effe67 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,53 @@ +version: '3.8' + +services: + postgres: + image: postgres:16 + environment: + POSTGRES_DB: fabriclaunch + POSTGRES_USER: postgres + POSTGRES_PASSWORD: postgres + volumes: + - postgres_data:/var/lib/postgresql/data + + minio: + image: minio/minio + command: server /data --console-address ":9001" + environment: + MINIO_ROOT_USER: minioadmin + MINIO_ROOT_PASSWORD: miniosecret + volumes: + - minio_data:/data + + web: + build: + dockerfile: ./apps/web/Dockerfile + ports: + - "3000:3000" + env_file: + - .env + environment: + AUTH_SECRET: ${AUTH_SECRET} + AUTH_DRIZZLE_URL: postgres://postgres:postgres@postgres:5432/fabriclaunch + POSTGRES_URL: postgres://postgres:postgres@postgres:5432/fabriclaunch + NEXT_PUBLIC_EXTERNAL_URL: http://localhost:3000 + AUTH_URL: http://localhost:3000 + PASSWORD_SALT: ${PASSWORD_SALT} + GH_CLIENT_ID: ${GH_CLIENT_ID} + GH_CLIENT_SECRET: ${GH_CLIENT_SECRET} + RESEND_API_KEY: ${RESEND_API_KEY} + EMAIL_FROM: noreply@fabriclaunch.com + MINIO_ACCESS_KEY: minioadmin + MINIO_SECRET_KEY: miniosecret + MINIO_ENDPOINT: minio + MINIO_PORT: 9000 + MINIO_USE_SSL: "false" + MINIO_REGION: us-east-1 + MINIO_BUCKET_NAME: fabriclaunch + depends_on: + - postgres + - minio + +volumes: + postgres_data: + minio_data: diff --git a/infra/digitalocean/.gitignore b/infra/digitalocean/.gitignore deleted file mode 100644 index fd2feaa..0000000 --- a/infra/digitalocean/.gitignore +++ /dev/null @@ -1,5 +0,0 @@ -id_rsa -id_rsa.pub -.terraform -terraform.tfstate -terraform.tfstate.backup \ No newline at end of file diff --git a/infra/digitalocean/.terraform.lock.hcl b/infra/digitalocean/.terraform.lock.hcl deleted file mode 100644 index 0f4b03a..0000000 --- a/infra/digitalocean/.terraform.lock.hcl +++ /dev/null @@ -1,83 +0,0 @@ -# This file is maintained automatically by "terraform init". -# Manual edits may be lost in future updates. - -provider "registry.terraform.io/digitalocean/digitalocean" { - version = "2.39.2" - constraints = "~> 2.0" - hashes = [ - "h1:ojDhFhOI7lFZfmG2vMyDfVr2cQoqxN3q+hwM+R9frzM=", - "zh:00380bd275cdb15645d03880a5c219a6826a9edba43099f5c09475465f87eb5f", - "zh:1e40f4aa51ba898cf64b1f296450b2ae85e77af6e2706536242093550aa605b0", - "zh:3f5f0c9f8c0cad64a757e38c1098633904786db998ab772e44f5f981b1acc06f", - "zh:511d02b9cad7946cab21b5bab30c15edf92610b0316a5a035771c4681df848ee", - "zh:5e56c038b16c97ea33d94e105ad5db4ccec01e957dd6adf4572e9414b499d2ea", - "zh:763b49a44a911fcba6e4d6773951cb6a612f93faf504cebdcc548c09b65790e5", - "zh:848079d6e125c2491d980d96c2e1ff59e81b19cf05e7c0b338054f27ba90ee9e", - "zh:9f54e4bbf89e051ef8cad73e39f505ff054b155b87b5b1fd578e7709ad0d2eeb", - "zh:c14e8e0f989e68338ff2ec6230b9ec846ebc33a1d3a858a662d77f162cf45761", - "zh:d30792eff5441c26f47cb2181b6eb1f0340c2c330378bec726f40f88dba49ab9", - "zh:d660a22bb43427d9ceff604e28d5d8a3b4f21639c85614f6134b39e43ca58ecf", - "zh:de8b42065fe420127e430dbd0c5aa5bd2c51e76ceeabd436e7e1137627b2a720", - "zh:eec0295a9c24af2c00436fea5e40fef13f7104fcd15eab30025d81096eb59fad", - "zh:ef8602f1deb8bd522ceb17de950864f2432e2e3ef2fa467caffe79b10e60f2c0", - "zh:f28a340515ac9cd0eb21bf2a0d2dcbaa58ccb2996d1e30e18ceb9ae79caab87f", - "zh:f30ce538e6beb13c9fe7712c543ad6cfed5d079d7e2bd050fdbeac3cc356b1ba", - ] -} - -provider "registry.terraform.io/hashicorp/local" { - version = "2.5.1" - hashes = [ - "h1:/GAVA/xheGQcbOZEq0qxANOg+KVLCA7Wv8qluxhTjhU=", - "zh:0af29ce2b7b5712319bf6424cb58d13b852bf9a777011a545fac99c7fdcdf561", - "zh:126063ea0d79dad1f68fa4e4d556793c0108ce278034f101d1dbbb2463924561", - "zh:196bfb49086f22fd4db46033e01655b0e5e036a5582d250412cc690fa7995de5", - "zh:37c92ec084d059d37d6cffdb683ccf68e3a5f8d2eb69dd73c8e43ad003ef8d24", - "zh:4269f01a98513651ad66763c16b268f4c2da76cc892ccfd54b401fff6cc11667", - "zh:51904350b9c728f963eef0c28f1d43e73d010333133eb7f30999a8fb6a0cc3d8", - "zh:73a66611359b83d0c3fcba2984610273f7954002febb8a57242bbb86d967b635", - "zh:78d5eefdd9e494defcb3c68d282b8f96630502cac21d1ea161f53cfe9bb483b3", - "zh:7ae387993a92bcc379063229b3cce8af7eaf082dd9306598fcd42352994d2de0", - "zh:9e0f365f807b088646db6e4a8d4b188129d9ebdbcf2568c8ab33bddd1b82c867", - "zh:b5263acbd8ae51c9cbffa79743fbcadcb7908057c87eb22fd9048268056efbc4", - "zh:dfcd88ac5f13c0d04e24be00b686d069b4879cc4add1b7b1a8ae545783d97520", - ] -} - -provider "registry.terraform.io/hashicorp/null" { - version = "3.2.2" - hashes = [ - "h1:IMVAUHKoydFrlPrl9OzasDnw/8ntZFerCC9iXw1rXQY=", - "zh:3248aae6a2198f3ec8394218d05bd5e42be59f43a3a7c0b71c66ec0df08b69e7", - "zh:32b1aaa1c3013d33c245493f4a65465eab9436b454d250102729321a44c8ab9a", - "zh:38eff7e470acb48f66380a73a5c7cdd76cc9b9c9ba9a7249c7991488abe22fe3", - "zh:4c2f1faee67af104f5f9e711c4574ff4d298afaa8a420680b0cb55d7bbc65606", - "zh:544b33b757c0b954dbb87db83a5ad921edd61f02f1dc86c6186a5ea86465b546", - "zh:696cf785090e1e8cf1587499516b0494f47413b43cb99877ad97f5d0de3dc539", - "zh:6e301f34757b5d265ae44467d95306d61bef5e41930be1365f5a8dcf80f59452", - "zh:78d5eefdd9e494defcb3c68d282b8f96630502cac21d1ea161f53cfe9bb483b3", - "zh:913a929070c819e59e94bb37a2a253c228f83921136ff4a7aa1a178c7cce5422", - "zh:aa9015926cd152425dbf86d1abdbc74bfe0e1ba3d26b3db35051d7b9ca9f72ae", - "zh:bb04798b016e1e1d49bcc76d62c53b56c88c63d6f2dfe38821afef17c416a0e1", - "zh:c23084e1b23577de22603cff752e59128d83cfecc2e6819edadd8cf7a10af11e", - ] -} - -provider "registry.terraform.io/hashicorp/tls" { - version = "4.0.5" - hashes = [ - "h1:zeG5RmggBZW/8JWIVrdaeSJa0OG62uFX5HY1eE8SjzY=", - "zh:01cfb11cb74654c003f6d4e32bbef8f5969ee2856394a96d127da4949c65153e", - "zh:0472ea1574026aa1e8ca82bb6df2c40cd0478e9336b7a8a64e652119a2fa4f32", - "zh:1a8ddba2b1550c5d02003ea5d6cdda2eef6870ece86c5619f33edd699c9dc14b", - "zh:1e3bb505c000adb12cdf60af5b08f0ed68bc3955b0d4d4a126db5ca4d429eb4a", - "zh:6636401b2463c25e03e68a6b786acf91a311c78444b1dc4f97c539f9f78de22a", - "zh:76858f9d8b460e7b2a338c477671d07286b0d287fd2d2e3214030ae8f61dd56e", - "zh:a13b69fb43cb8746793b3069c4d897bb18f454290b496f19d03c3387d1c9a2dc", - "zh:a90ca81bb9bb509063b736842250ecff0f886a91baae8de65c8430168001dad9", - "zh:c4de401395936e41234f1956ebadbd2ed9f414e6908f27d578614aaa529870d4", - "zh:c657e121af8fde19964482997f0de2d5173217274f6997e16389e7707ed8ece8", - "zh:d68b07a67fbd604c38ec9733069fbf23441436fecf554de6c75c032f82e1ef19", - "zh:f569b65999264a9416862bca5cd2a6177d94ccb0424f3a4ef424428912b9cb3c", - ] -} diff --git a/infra/digitalocean/terraform.tfvars b/infra/digitalocean/terraform.tfvars deleted file mode 100644 index 259dd95..0000000 --- a/infra/digitalocean/terraform.tfvars +++ /dev/null @@ -1,4 +0,0 @@ - -regions = ["nyc1", "fra1", "blr1"] - -vm_names = ["org1", "org2", "org3"] \ No newline at end of file diff --git a/infra/digitalocean/variables.tf b/infra/digitalocean/variables.tf deleted file mode 100644 index 93e7a66..0000000 --- a/infra/digitalocean/variables.tf +++ /dev/null @@ -1,15 +0,0 @@ -variable "do_token" { - description = "DigitalOcean API Token" - type = string - sensitive = true -} - -variable "regions" { - description = "List of regions for droplet deployment" - type = list(string) - default = ["nyc1", "fra1", "blr1"] -} -variable "vm_names" { - description = "List of VM names" - type = list(string) -}