From 4bb56e9f11b4720e9869ce787bfd4d8ad9d43eed Mon Sep 17 00:00:00 2001 From: Abhijna Raghavendra Date: Wed, 3 Apr 2024 22:44:47 +0530 Subject: [PATCH 01/10] feat: add admin panel support on backend --- src/backend/.env.sample | 3 ++- src/backend/db.ts | 13 +++++++++---- src/backend/main.ts | 6 ++++-- 3 files changed, 15 insertions(+), 7 deletions(-) diff --git a/src/backend/.env.sample b/src/backend/.env.sample index 3070d10..547e5fa 100644 --- a/src/backend/.env.sample +++ b/src/backend/.env.sample @@ -5,4 +5,5 @@ GITLAB_OAUTH_CLIENT_SECRET=... MONGO_API_KEY=... MONGO_APP_ID=... SENTRY_DSN=... -FRONTEND=... \ No newline at end of file +FRONTEND=... +ADMIN_LIST=admin1|admin2 \ No newline at end of file diff --git a/src/backend/db.ts b/src/backend/db.ts index c5b4814..a50e02d 100644 --- a/src/backend/db.ts +++ b/src/backend/db.ts @@ -51,12 +51,13 @@ async function checkUser(accessToken: string, provider: string) { } // Get all content maps corresponding to user -async function getMaps(author: string) { +async function getMaps(author: string, ADMIN_LIST: string[]) { + const filter = ADMIN_LIST?.includes(author) ? {} : { "author": author }; const query = { collection: "content_maps", database: DATABASE, dataSource: DATA_SOURCE, - filter: { "author": author }, + filter: filter, }; options.body = JSON.stringify(query); const resp = await fetch(MONGO_URLs.find.toString(), options); @@ -96,12 +97,16 @@ async function addMaps(document: DfContentMap) { } // Delete content maps -async function deleteMaps(document: DfContentMap) { +async function deleteMaps(document: DfContentMap, ADMIN_LIST: string[]) { + const filter = JSON.parse(JSON.stringify(document)); + if (ADMIN_LIST.includes(document.author)) { + delete filter.author; + } const query = { collection: "content_maps", database: DATABASE, dataSource: DATA_SOURCE, - filter: document, + filter: filter, }; options.body = JSON.stringify(query); diff --git a/src/backend/main.ts b/src/backend/main.ts index 5dfc1ea..ca80438 100644 --- a/src/backend/main.ts +++ b/src/backend/main.ts @@ -3,6 +3,8 @@ import { addScript, deleteScript } from "./scripts.ts"; import { checkJWT } from "./utils/jwt.ts"; import { addMaps, deleteMaps, getMaps } from "./db.ts"; +const ADMIN_LIST = Deno.env.get("ADMIN_LIST")?.split("|"); + async function getSubdomains(ctx: Context) { const author = ctx.request.url.searchParams.get("user"); const token = ctx.request.url.searchParams.get("token"); @@ -10,7 +12,7 @@ async function getSubdomains(ctx: Context) { if (author != await checkJWT(provider!, token!)) { ctx.throw(401); } - const data = await getMaps(author); + const data = await getMaps(author, ADMIN_LIST!); ctx.response.headers.set("Access-Control-Allow-Origin", "*"); ctx.response.body = data.documents; } @@ -80,7 +82,7 @@ async function deleteSubdomain(ctx: Context) { if (author != await checkJWT(provider, token)) { ctx.throw(401); } - const data = await deleteMaps(document); + const data = await deleteMaps(document, ADMIN_LIST!); if (data.deletedCount) { deleteScript(document); Sentry.captureMessage( From ba5e2dccf9911f431494f717f96b25ac4bbc9d9f Mon Sep 17 00:00:00 2001 From: Abhijna Raghavendra Date: Wed, 3 Apr 2024 23:22:28 +0530 Subject: [PATCH 02/10] feat: add memory limit to container --- src/backend/.env.sample | 3 +- src/backend/scripts.ts | 6 +- src/backend/shell_scripts/container.sh | 100 ++++++++----------------- 3 files changed, 37 insertions(+), 72 deletions(-) diff --git a/src/backend/.env.sample b/src/backend/.env.sample index 547e5fa..012341a 100644 --- a/src/backend/.env.sample +++ b/src/backend/.env.sample @@ -6,4 +6,5 @@ MONGO_API_KEY=... MONGO_APP_ID=... SENTRY_DSN=... FRONTEND=... -ADMIN_LIST=admin1|admin2 \ No newline at end of file +ADMIN_LIST=admin1|admin2 +MEMORY_LIMIT=500m \ No newline at end of file diff --git a/src/backend/scripts.ts b/src/backend/scripts.ts index 4bf4fdb..3687c46 100644 --- a/src/backend/scripts.ts +++ b/src/backend/scripts.ts @@ -2,6 +2,8 @@ import { exec } from "./dependencies.ts"; import dockerize from "./utils/container.ts"; import DfContentMap from "./types/maps_interface.ts"; +const MEMORY_LIMIT = Deno.env.get("MEMORY_LIMIT"); + async function addScript( document: DfContentMap, env_content: string, @@ -21,14 +23,14 @@ async function addScript( } else if (document.resource_type === "GITHUB" && static_content == "Yes") { Deno.writeTextFile(`/hostpipe/.env`, env_content); await exec( - `bash -c "echo 'bash ../../src/backend/shell_scripts/container.sh -s ${document.subdomain} ${document.resource}' > /hostpipe/pipe"`, + `bash -c "echo 'bash ../../src/backend/shell_scripts/container.sh -s ${document.subdomain} ${document.resource} 80 ${MEMORY_LIMIT}' > /hostpipe/pipe"`, ); } else if (document.resource_type === "GITHUB" && static_content == "No") { const dockerfile = dockerize(stack, port, build_cmds); Deno.writeTextFile(`/hostpipe/Dockerfile`, dockerfile); Deno.writeTextFile(`/hostpipe/.env`, env_content); await exec( - `bash -c "echo 'bash ../../src/backend/shell_scripts/container.sh -g ${document.subdomain} ${document.resource} ${port}' > /hostpipe/pipe"`, + `bash -c "echo 'bash ../../src/backend/shell_scripts/container.sh -g ${document.subdomain} ${document.resource} ${port} ${MEMORY_LIMIT}' > /hostpipe/pipe"`, ); } } diff --git a/src/backend/shell_scripts/container.sh b/src/backend/shell_scripts/container.sh index 730460a..dc145b9 100644 --- a/src/backend/shell_scripts/container.sh +++ b/src/backend/shell_scripts/container.sh @@ -3,35 +3,9 @@ PORT_MAX=8099 flag=$1 name=$2 resource=$3 -exp_port=$4 - -available_ports=() - -for ((port=PORT_MIN; port<=PORT_MAX; port++)); do - if ! ss -ln src :$port | grep -q "\<$port\>"; then - available_ports+=($port) - fi -done - -echo "Available ports: ${available_ports[56]}" -AVAILABLE=0 -if [ $flag = "-g" ]; then - echo "Creating subdomain $name" - git clone $resource $name - sudo cp Dockerfile $name/ - sudo cp .env $name/ - cd $name - sudo docker build -t $name . - echo ${available_ports[$AVAILABLE]}; - sudo docker run --name=$name -d -p ${available_ports[$AVAILABLE]}:$exp_port $2 - cd .. - sudo rm -rf $name - sudo rm Dockerfile - sudo rm .env - - sudo touch /etc/nginx/sites-available/$2.conf - sudo chmod 666 /etc/nginx/sites-available/$2.conf - sudo echo "# Virtual Host configuration for example.com +exp_port=$4 +max_mem=$5 +server_block="# Virtual Host configuration for $2 server { listen 80; listen [::]:80; @@ -52,51 +26,39 @@ if [ $flag = "-g" ]; then ssl_certificate_key /etc/letsencrypt/live/df.mdgspace.org-0001/privkey.pem; include /etc/letsencrypt/options-ssl-nginx.conf; ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; - }" > /etc/nginx/sites-available/$2.conf - sudo ln -s /etc/nginx/sites-available/$2.conf /etc/nginx/sites-enabled/$2.conf - sudo systemctl reload nginx + }" +available_ports=() + +for ((port=PORT_MIN; port<=PORT_MAX; port++)); do + if ! ss -ln src :$port | grep -q "\<$port\>"; then + available_ports+=($port) + fi +done +echo "Available ports: ${available_ports[56]}" +AVAILABLE=0 +echo "Creating subdomain $name" +git clone $resource $name +sudo cp .env $name/ +cd $name + +if [ $flag = "-g" ]; then + sudo cp ../Dockerfile ./ else - echo "Creating subdomain $name" - git clone $resource $name - sudo cp .env $name/ - cd $name sudo echo " FROM nginx:alpine COPY . /usr/share/nginx/html " > Dockerfile - sudo docker build -t $name . - sudo docker run --name=$name -d -p ${available_ports[$AVAILABLE]}:80 $name - cd .. - sudo rm .env - sudo rm -rf $name - sudo touch /etc/nginx/sites-available/$2.conf - sudo chmod 666 /etc/nginx/sites-available/$2.conf - sudo echo "# Virtual Host configuration for example.com - server { - listen 80; - listen [::]:80; - listen 443 ssl; - listen [::]:443 ssl; - server_name $2; - location / { - proxy_pass http://localhost:${available_ports[$AVAILABLE]}; - proxy_http_version 1.1; - proxy_set_header Upgrade \$http_upgrade; - proxy_set_header Connection 'upgrade'; - proxy_set_header Host \$host; - proxy_cache_bypass \$http_upgrade; - } - charset utf-8; - client_max_body_size 20M; - ssl_certificate /etc/letsencrypt/live/df.mdgspace.org-0001/fullchain.pem; - ssl_certificate_key /etc/letsencrypt/live/df.mdgspace.org-0001/privkey.pem; - include /etc/letsencrypt/options-ssl-nginx.conf; - ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; - }" > /etc/nginx/sites-available/$2.conf; - sudo ln -s /etc/nginx/sites-available/$2.conf /etc/nginx/sites-enabled/$2.conf; - sudo systemctl reload nginx; fi - - +sudo docker build -t $name . +sudo docker run --memory=$max_mem --name=$name -d -p ${available_ports[$AVAILABLE]}:$exp_port $2 +cd .. +sudo rm -rf $name +sudo rm Dockerfile +sudo rm .env +sudo touch /etc/nginx/sites-available/$2.conf +sudo chmod 666 /etc/nginx/sites-available/$2.conf +sudo echo $server_block > /etc/nginx/sites-available/$2.conf +sudo ln -s /etc/nginx/sites-available/$2.conf /etc/nginx/sites-enabled/$2.conf +sudo systemctl reload nginx From e21cacb65ab1c4330c8dce6d663f82030e54b40d Mon Sep 17 00:00:00 2001 From: Abhijna Raghavendra Date: Wed, 3 Apr 2024 23:39:27 +0530 Subject: [PATCH 03/10] rfac: fix server block indentation --- src/backend/shell_scripts/container.sh | 46 +++++++++++++------------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/src/backend/shell_scripts/container.sh b/src/backend/shell_scripts/container.sh index dc145b9..b13a721 100644 --- a/src/backend/shell_scripts/container.sh +++ b/src/backend/shell_scripts/container.sh @@ -5,28 +5,7 @@ name=$2 resource=$3 exp_port=$4 max_mem=$5 -server_block="# Virtual Host configuration for $2 - server { - listen 80; - listen [::]:80; - listen 443 ssl; - listen [::]:443 ssl; - server_name $2; - location / { - proxy_pass http://localhost:${available_ports[$AVAILABLE]}; - proxy_http_version 1.1; - proxy_set_header Upgrade \$http_upgrade; - proxy_set_header Connection 'upgrade'; - proxy_set_header Host \$host; - proxy_cache_bypass \$http_upgrade; - } - charset utf-8; - client_max_body_size 20M; - ssl_certificate /etc/letsencrypt/live/df.mdgspace.org-0001/fullchain.pem; - ssl_certificate_key /etc/letsencrypt/live/df.mdgspace.org-0001/privkey.pem; - include /etc/letsencrypt/options-ssl-nginx.conf; - ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; - }" + available_ports=() for ((port=PORT_MIN; port<=PORT_MAX; port++)); do @@ -59,6 +38,27 @@ sudo rm Dockerfile sudo rm .env sudo touch /etc/nginx/sites-available/$2.conf sudo chmod 666 /etc/nginx/sites-available/$2.conf -sudo echo $server_block > /etc/nginx/sites-available/$2.conf +sudo echo "# Virtual Host configuration for $2 + server { + listen 80; + listen [::]:80; + listen 443 ssl; + listen [::]:443 ssl; + server_name $2; + location / { + proxy_pass http://localhost:${available_ports[$AVAILABLE]}; + proxy_http_version 1.1; + proxy_set_header Upgrade \$http_upgrade; + proxy_set_header Connection 'upgrade'; + proxy_set_header Host \$host; + proxy_cache_bypass \$http_upgrade; + } + charset utf-8; + client_max_body_size 20M; + ssl_certificate /etc/letsencrypt/live/df.mdgspace.org-0001/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/df.mdgspace.org-0001/privkey.pem; + include /etc/letsencrypt/options-ssl-nginx.conf; + ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; + }" > /etc/nginx/sites-available/$2.conf sudo ln -s /etc/nginx/sites-available/$2.conf /etc/nginx/sites-enabled/$2.conf sudo systemctl reload nginx From 8af6fcd141a7251977d1f03f1cd720d6c42725a5 Mon Sep 17 00:00:00 2001 From: Ubuntu Date: Fri, 5 Apr 2024 19:14:31 +0000 Subject: [PATCH 04/10] feat: dockerfile --- src/backend/main.ts | 3 +++ src/backend/scripts.ts | 11 ++++++++++- src/backend/shell_scripts/container.sh | 4 ++-- src/frontend/src/components/modal.vue | 12 +++++++++++- src/frontend/src/utils/create.ts | 2 ++ 5 files changed, 28 insertions(+), 4 deletions(-) mode change 100644 => 100755 src/backend/shell_scripts/container.sh diff --git a/src/backend/main.ts b/src/backend/main.ts index ca80438..eca17ba 100644 --- a/src/backend/main.ts +++ b/src/backend/main.ts @@ -35,9 +35,11 @@ async function addSubdomain(ctx: Context) { delete document.provider; delete document.port; delete document.build_cmds; + delete document.dockerfile_present; delete document.stack; delete document.env_content; delete document.static_content; + if (document.author != await checkJWT(provider, token)) { ctx.throw(401); } @@ -49,6 +51,7 @@ async function addSubdomain(ctx: Context) { document, copy.env_content, copy.static_content, + copy.dockerfile_present, copy.stack, copy.port, copy.build_cmds, diff --git a/src/backend/scripts.ts b/src/backend/scripts.ts index 3687c46..fcdb711 100644 --- a/src/backend/scripts.ts +++ b/src/backend/scripts.ts @@ -8,6 +8,7 @@ async function addScript( document: DfContentMap, env_content: string, static_content: string, + dockerfile_present:string, stack: string, port: string, build_cmds: string, @@ -26,12 +27,20 @@ async function addScript( `bash -c "echo 'bash ../../src/backend/shell_scripts/container.sh -s ${document.subdomain} ${document.resource} 80 ${MEMORY_LIMIT}' > /hostpipe/pipe"`, ); } else if (document.resource_type === "GITHUB" && static_content == "No") { - const dockerfile = dockerize(stack, port, build_cmds); + if(dockerfile_present === 'No'){ + const dockerfile = dockerize(stack, port, build_cmds); Deno.writeTextFile(`/hostpipe/Dockerfile`, dockerfile); Deno.writeTextFile(`/hostpipe/.env`, env_content); await exec( `bash -c "echo 'bash ../../src/backend/shell_scripts/container.sh -g ${document.subdomain} ${document.resource} ${port} ${MEMORY_LIMIT}' > /hostpipe/pipe"`, ); + }else if(dockerfile_present === 'Yes'){ + + await exec( + `bash -c "echo 'bash ../../src/backend/shell_scripts/container.sh -d ${document.subdomain} ${document.resource} ${port} ${MEMORY_LIMIT}' > /hostpipe/pipe"`, + ); + } + } } diff --git a/src/backend/shell_scripts/container.sh b/src/backend/shell_scripts/container.sh old mode 100644 new mode 100755 index b13a721..f92dd11 --- a/src/backend/shell_scripts/container.sh +++ b/src/backend/shell_scripts/container.sh @@ -23,11 +23,11 @@ cd $name if [ $flag = "-g" ]; then sudo cp ../Dockerfile ./ -else +elif [ $flag = "-s" ]; then sudo echo " FROM nginx:alpine COPY . /usr/share/nginx/html - " > Dockerfile + " > Dockerfile fi sudo docker build -t $name . diff --git a/src/frontend/src/components/modal.vue b/src/frontend/src/components/modal.vue index e329174..b14052c 100644 --- a/src/frontend/src/components/modal.vue +++ b/src/frontend/src/components/modal.vue @@ -21,12 +21,21 @@ No
+
+
+ Yes + No +
+

Stack:

+

Port:

+

Build Commands:

+
@@ -48,6 +57,7 @@ export default { resource: '', env_content: 'key1 = value1', // Default prompt text static_content: 'No', + dockerfile_present :'No', port: '', stack: '', build_cmds: '', @@ -58,7 +68,7 @@ export default { methods: { submitForm() { console.log(this.subdomain, this.resource_type, this.resource); - create(this.subdomain, this.resource_type, this.resource, this.env_content, this.static_content, this.port, this.stack, this.build_cmds) + create(this.subdomain, this.resource_type, this.resource, this.env_content, this.static_content,this.dockerfile_present,this.port, this.stack, this.build_cmds) .then((res) => { console.log(res); if (res === 'Submitted') { diff --git a/src/frontend/src/utils/create.ts b/src/frontend/src/utils/create.ts index 018b9d6..f6633bf 100644 --- a/src/frontend/src/utils/create.ts +++ b/src/frontend/src/utils/create.ts @@ -60,6 +60,7 @@ export async function create( resource: string, env_content: string, static_content: string, + dockerfile_present:string, port: string, stack: string, build_cmds: string, @@ -85,6 +86,7 @@ export async function create( "resource": resource, "env_content": env_content, "static_content": static_content, + "dockerfile_present":dockerfile_present, "port": port, "build_cmds": build_cmds, "stack": stack, From e6cf44637c15c9808cd3b5ad7e3200ba3a61d75b Mon Sep 17 00:00:00 2001 From: Abhijna Raghavendra Date: Tue, 9 Apr 2024 12:59:34 +0530 Subject: [PATCH 05/10] rfac: move domain name to env --- src/frontend/.env.sample | 3 ++- src/frontend/src/components/modal.vue | 5 ++++- src/frontend/src/style.css | 1 - src/frontend/src/utils/create.ts | 3 ++- 4 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/frontend/.env.sample b/src/frontend/.env.sample index 5e4e420..7480e51 100644 --- a/src/frontend/.env.sample +++ b/src/frontend/.env.sample @@ -4,4 +4,5 @@ VITE_APP_GITHUB_OAUTH_REDIRECT_URL=.../login VITE_APP_GITLAB_OAUTH_CLIENT_ID=... VITE_APP_GITLAB_OAUTH_CLIENT_SECRET=... VITE_APP_GITLAB_OAUTH_REDIRECT_URL=.../login -VITE_APP_BACKEND=... \ No newline at end of file +VITE_APP_BACKEND=... +VITE_APP_DOMAIN=your-domain.com \ No newline at end of file diff --git a/src/frontend/src/components/modal.vue b/src/frontend/src/components/modal.vue index b14052c..70f8f4f 100644 --- a/src/frontend/src/components/modal.vue +++ b/src/frontend/src/components/modal.vue @@ -1,3 +1,6 @@ +