Skip to content

Commit d865064

Browse files
committed
license experiments
1 parent 8f2ae5e commit d865064

11 files changed

Lines changed: 424 additions & 24 deletions

File tree

.vscode/launch.json

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,28 @@
2626
"justMyCode": false,
2727
"console": "integratedTerminal"
2828
},
29+
{
30+
"name": " - license generator",
31+
"type": "debugpy",
32+
"request": "launch",
33+
"cwd": "${workspaceFolder}/docker/webgenie_docker/webgen_ai_docker/license",
34+
"env": {"APILOGICSERVER_AUTO_OPEN": ""},
35+
"program": "license_generator.py",
36+
"redirectOutput": true,
37+
"justMyCode": false,
38+
"console": "integratedTerminal"
39+
},
40+
{
41+
"name": " - license checker",
42+
"type": "debugpy",
43+
"request": "launch",
44+
"cwd": "${workspaceFolder}/docker/webgenie_docker/webgen_ai_docker/license",
45+
"env": {"APILOGICSERVER_AUTO_OPEN": ""},
46+
"program": "license_checker.py",
47+
"redirectOutput": true,
48+
"justMyCode": false,
49+
"console": "integratedTerminal"
50+
},
2951
{
3052
"name": " - GenAI tests",
3153
"type": "debugpy",
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
# Run WebGenAI locally from docker container
2+
3+
# Before running, update ./system/genai/webg_local/webg_config/web_genai.txt
4+
# See: https://apilogicserver.github.io/Docs/WebGenAI-CLI/#configuration
5+
6+
# cd <manager>
7+
8+
# docker-compose -f system/genai/webg_local/docker-compose-webg.yml up
9+
# docker-compose -f system/genai/webg_local/docker-compose-webg.yml down
10+
11+
# if you have run docker compose up (above), you must run docker compose down to run directly:
12+
# docker run -it --rm --name webgenie -p 8282:80 --env-file ./system/genai/webg_local/webg_config/web_genai.txt -v ./system/genai/webg_local/webg_temp:/tmp -v ./system/genai/webg_local/webg_projects:/opt/projects apilogicserver/web_genai
13+
14+
name: webgenie
15+
services:
16+
web_genai:
17+
stdin_open: true
18+
tty: true
19+
container_name: webgenai
20+
ports:
21+
- 8282:80
22+
env_file:
23+
- ./../webg_local/webg_config/web_genai.txt
24+
volumes:
25+
- ./../webg_local/webg_temp:/tmp
26+
- ./../webg_local/webg_projects:/opt/projects
27+
image: apilogicserver/web_genai

api_logic_server_cli/prototypes/manager/system/genai/webg_local/webg_config/web_genai.txt

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,8 @@ APILOGICSERVER_CHATGPT_APIKEY=sk-proj-< your api key >
55

66
# WebGenAI security configuration
77
# login password for the admin user
8-
# ADMIN_PASSWORD=password
8+
# ADMIN_PASSWORD=password
9+
10+
# WebGenAI GitHub configuration
11+
GH_TOKEN={personal access token from github}
12+
GH_ORG=github.com/<gh-user-name>
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
#!/bin/bash
2+
3+
set -e # exit on error
4+
5+
contains()
6+
# echo contains check $1 in $2
7+
case "$1" in
8+
(*"$2"*) true;;
9+
(*) false;;
10+
esac
11+
12+
ostype=$(uname -a)
13+
if contains "Ubuntu" $ostype; then
14+
ostype="ubuntu"
15+
fi
16+
# if contains "ubuntu" $ostype; then
17+
# echo $ostype contains ubuntu
18+
# fi
19+
20+
webgen_ai_docker='webgen_ai_docker'
21+
22+
SRC_DIR=$(pwd)
23+
24+
echo "\n\nBuild Web/GenAI Docker locally (no push to docker hub)"
25+
26+
if [ $# -eq 0 ]
27+
then
28+
echo " "
29+
# echo "shell: $SHELL"
30+
echo " on $ostype (version 7.0.15)\n"
31+
echo " "
32+
echo " Note: creates a folder at pwd: $webgen_ai_docker"
33+
echo " "
34+
echo " > cd ~/dev/ApiLogicServer/ApiLogicServer-dev/org_git/ApiLogicServer-src"
35+
echo " > sh docker/webgenie_docker/build_web_genie_local.sh local "
36+
echo " "
37+
exit 0
38+
fi
39+
40+
echo " "
41+
# ls
42+
echo "pwd: $(pwd)\n"
43+
echo "To build api_logic_server_local image:"
44+
echo ".. 1. BLT (with tomato), or"
45+
echo ".. 2. See 'Internal' at docker/api_logic_server.Dockerfile"
46+
read -p "Verify pwd = ApiLogicServer-src, local image ready (see above)> "
47+
echo " "
48+
49+
cd ..
50+
ORG_GIT_DIR=$(pwd)
51+
echo "pwd: $(pwd)"
52+
53+
echo " "
54+
echo "\nClean $webgen_ai_docker\n"
55+
set -x
56+
57+
rm -rf $webgen_ai_docker
58+
cp -r $SRC_DIR/docker/webgenie_docker/$webgen_ai_docker ./
59+
cd $webgen_ai_docker
60+
touch webgenai_env
61+
62+
# Build wg:
63+
git clone https://github.com/ApiLogicServer/sra --depth=1
64+
git clone https://github.com/ApiLogicServer/webgenai
65+
cd webgenai
66+
git pull
67+
# git checkout so_release
68+
cd ..
69+
70+
if [ "$1" = "local" ]
71+
then
72+
docker build -f $SRC_DIR/docker/webgenie_docker/webgen_ai_docker/webgenie_local_license.Dockerfile -t apilogicserver/web_genai --no-cache --rm .
73+
fi
74+
75+
set +x
76+
77+
# cd ~/dev/ApiLogicServer/ApiLogicServer-dev/org_git/ApiLogicServer-src
78+
# sh docker/webgenie_docker/build_web_genie_local_license.sh local
79+
80+
# docker run -it --rm --name webgenie -p 8282:80 --env-file ./../../webg-local/webg-config/web_genai.txt -v ./../../webg-local/webg-temp:/tmp -v ./../../webg-local/webg-projects:/opt/projects apilogicserver/web_genai
81+
82+
cd $SRC_DIR
83+
echo "\npwd: $(pwd)\n"
84+
echo " (wg-temp formerly at: docker cp webgenie:/tmp ~/Desktop/wg-temp \n"
85+
echo "projects, temp at ./../../webg-local -- eg, drag it to manager workspace"
86+
echo "you can 'clean' the webgenie_docker folder\n"
87+
echo " .. delete it: rm -rf ./../../webg-local \n"
88+
echo " .. cp -r docker/webgenie_docker/webgen_ai_docker/webg-local_proto ./../../webg-local \n"
89+
echo " .. AND, you will need 2 magic files under docker/webgenie_docker/webgen_ai_docker/webg-local_proto/webg-config"
90+
echo "Browse to: http://localhost:8282/"
91+
echo "\nrun: docker run -it --rm --name webgenai -p 8282:80 --env-file ./../../webg-local/webg-config/web_genai.txt -v ./../../webg-local/webg-projects:/opt/projects -v ./../../webg-local/webg-temp:/tmp apilogicserver/web_genai \n "
92+
93+
exit 0
Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
#!/usr/bin/env bash
2+
#
3+
# Start the webgenie admin interface
4+
#
5+
6+
function monitor() {
7+
[[ -z ${MONITOR} ]] && return
8+
# Run the monitor script to check project health
9+
10+
while true; do
11+
date
12+
python database/manager.py -m
13+
sleep 250
14+
done
15+
}
16+
17+
function start_dev() {
18+
[[ -z ${VITE_DEV} ]] && return
19+
# Start the web dev server
20+
cd /opt/webgenai/simple-spa
21+
if [[ ! -e node_modules ]]; then
22+
echo "$PWD/node_modules does not exist"
23+
24+
read -p "Do you want to continue? (y/n): " answer
25+
if [ "$answer" != "${answer#[Nn]}" ] ;then
26+
return
27+
fi
28+
npm i
29+
fi
30+
VITE_PORT=5174 npm run dev &
31+
}
32+
33+
function update_schema() {
34+
# Update the schema
35+
set +e
36+
cd /opt/webgenai
37+
bash database/update_schema.sh "${DB_URI}"
38+
set -e
39+
}
40+
41+
function start_nginx() {
42+
NGINX_PORT=${WG_NGINX_PORT:-80}
43+
sed -i "s/80 default_server/${NGINX_PORT} default_server/" /etc/nginx/sites-available/default
44+
sed -i "s/80 default_server/${NGINX_PORT} default_server/" /etc/nginx/wg.conf
45+
set +e
46+
rm /opt/projects/wgadmin/nginx/*conf
47+
set -e
48+
# Start the nginx server
49+
nginx -g 'daemon off;' &
50+
echo "Nginx started"
51+
}
52+
53+
set -e
54+
set -x
55+
cd /opt/webgenai
56+
[[ -f extra_scripts.sh ]] && source extra_scripts.sh
57+
58+
export APILOGICPROJECT_SWAGGER_PORT=${APILOGICPROJECT_SWAGGER_PORT:-8282}
59+
export APILOGICPROJECT_EXTERNAL_PORT=${APILOGICPROJECT_EXTERNAL_PORT:-8282}
60+
61+
export APILOGICPROJECT_SWAGGER_HOST=${APILOGICPROJECT_EXTERNAL_HOST:-localhost}
62+
export APILOGICPROJECT_PORT=${APILOGICPROJECT_PORT:-5657}
63+
export PROJ_ROOT="/opt/projects"
64+
export UPLOAD_FOLDER="${PROJ_ROOT}/wgupload"
65+
66+
mkdir -p "${UPLOAD_FOLDER}" "${PROJ_ROOT}/wgadmin/nginx"
67+
68+
RED='\033[0;31m'
69+
GREEN='\033[0;32m'
70+
NC='\033[0m' # No Color
71+
72+
start_nginx
73+
74+
75+
start_dev &
76+
77+
# Enable security if password is set in container environment
78+
[[ -n "${ADMIN_PASSWORD}" ]] && export SECURITY_ENABLED="true"
79+
80+
if [[ -z ${SECURITY_ENABLED} || ${SECURITY_ENABLED} == "false" || ${SECURITY_ENABLED} == "no" ]] ; then
81+
echo -e "${RED}Authentication disabled (\$SECURITY_ENABLED=${SECURITY_ENABLED}) ${NC}"
82+
export SECURITY_ENABLED="false"
83+
else
84+
echo -e "${GREEN}Authentication enabled ${NC}"
85+
export JWT_SECRET_KEY=${JWT_SECRET_KEY:-$(openssl rand -hex 32)}
86+
fi
87+
88+
if [[ -z ${APILOGICSERVER_CHATGPT_APIKEY} ]]; then
89+
echo 'No $APILOGICSERVER_CHATGPT_APIKEY, Please provide a valid key if you want to use GenAI'
90+
echo -n '> '
91+
read APILOGICSERVER_CHATGPT_APIKEY
92+
export APILOGICSERVER_CHATGPT_APIKEY
93+
fi
94+
95+
export PYTHONPATH=$PWD
96+
# Database
97+
export DB_URI=${DB_URI:-"${PROJ_ROOT}/wgadmin/db.sqlite"}
98+
export SQLALCHEMY_DATABASE_URI="sqlite:///${DB_URI}"
99+
export WG_SQLALCHEMY_DATABASE_URI="${SQLALCHEMY_DATABASE_URI}"
100+
( update_schema ${DB_URI} )
101+
# if [[ ! -e "${DB_URI}" ]]; then
102+
# echo "Creating database at ${DB_URI}"
103+
# python database/manager.py -c 2>/dev/null
104+
# fi
105+
106+
python database/manager.py -c 2>/dev/null
107+
# Kill any running project / set "running" to false
108+
python database/manager.py -K &
109+
ln -sfr /opt/projects/by-ulid ~
110+
111+
# Temp fix - ignore optlocking
112+
export OPT_LOCKING=${OPT_LOCKING:-ignored}
113+
#> /home/api_logic_server/api_logic_server_cli/templates/opt_locking.txt
114+
115+
116+
monitor &
117+
118+
echo WG BUILD: $(cat build_ts.txt)
119+
export GUNICORN_CMD_ARGS=" --worker-tmp-dir=/dev/shm -b 0.0.0.0:${APILOGICPROJECT_PORT} --timeout 60 --workers 3 --threads 2 --reload"
120+
gunicorn api_logic_server_run:flask_app
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"license_key": "ABCD-1234-EFGH-5678",
3+
"license_type": "PRO",
4+
"expiry": "2025-12-31",
5+
"signature": "ExPd5FL9VI6jOpDruwgBUF3knikbD9xAxNgq0Yneah0"
6+
}
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
import json
2+
import os
3+
import datetime
4+
import base64
5+
import hashlib
6+
import hmac
7+
8+
# Secret key for signing (store securely!)
9+
SECRET_KEY = b"your-secure-secret-key"
10+
11+
def load_license(license_path="license.json"):
12+
"""Load the license file from disk."""
13+
if not os.path.exists(license_path):
14+
print("License file not found.")
15+
return None
16+
try:
17+
with open(license_path, "r") as file:
18+
return json.load(file)
19+
except json.JSONDecodeError:
20+
print("Invalid license file format.")
21+
return None
22+
23+
def verify_signature(license_data):
24+
"""Verify that the license signature is valid."""
25+
signature = license_data.pop("signature", None) # Extract signature
26+
if not signature:
27+
print("Missing signature.")
28+
return False
29+
30+
# Create a hash-based message authentication code (HMAC)
31+
license_string = json.dumps(license_data, sort_keys=True).encode()
32+
expected_signature = base64.b64encode(hmac.new(SECRET_KEY, license_string, hashlib.sha256).digest()).decode()
33+
34+
if signature != expected_signature:
35+
print("Invalid license signature. Possible tampering detected.")
36+
return False
37+
38+
return True
39+
40+
def is_license_valid(license_data):
41+
"""Check if the license is still valid (not expired)."""
42+
expiry_date = license_data.get("expiry")
43+
if not expiry_date:
44+
print("No expiry date found in license.")
45+
return False
46+
47+
try:
48+
expiry_date = datetime.datetime.strptime(expiry_date, "%Y-%m-%d")
49+
except ValueError:
50+
print("Invalid expiry date format.")
51+
return False
52+
53+
if expiry_date < datetime.datetime.now():
54+
print("License expired.")
55+
return False
56+
57+
return True
58+
59+
def check_license():
60+
"""Main function to validate the license."""
61+
license_data = load_license()
62+
if not license_data:
63+
exit(1)
64+
65+
if not verify_signature(license_data):
66+
print("License verification failed.")
67+
exit(1)
68+
69+
if not is_license_valid(license_data):
70+
print("License expired or invalid.")
71+
exit(1)
72+
73+
print(f"License is valid! Type: {license_data['license_type']}, Expiry: {license_data['expiry']}")
74+
75+
if __name__ == "__main__":
76+
check_license()

0 commit comments

Comments
 (0)