Skip to content

Commit 958db2e

Browse files
authored
Merge pull request #15 from hotosm/login_hanko
Add: hanko login flow
2 parents 2a359ee + b6c3fef commit 958db2e

38 files changed

+3029
-479
lines changed

.env

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
export UMAP_OSM_KEY=<YOUR OSM KEY>
2+
export UMAP_OSM_SECRET=<YOUR OSM SECRET>
3+
export SITE_ADMIN_EMAIL=youremail@domain.org
4+
5+
# Auth Provider (legacy or hanko)
6+
export AUTH_PROVIDER=hanko
7+
8+
# Hanko SSO Configuration (required if AUTH_PROVIDER=hanko)
9+
export HANKO_API_URL=https://login.hotosm.test
10+
export COOKIE_SECRET=your-32-byte-secret-key-here
11+
export COOKIE_DOMAIN=.hotosm.test
12+
export COOKIE_SECURE=true
13+
14+
# Admin mappings email (for Hanko)
15+
export ADMIN_EMAILS=admin@hotosm.org
16+
17+

.env.example

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
export UMAP_OSM_KEY=<YOUR OSM KEY>
2+
export UMAP_OSM_SECRET=<YOUR OSM SECRET>
3+
export SITE_ADMIN_EMAIL=youremail@domain.org
4+
5+
# Auth Provider (legacy or hanko)
6+
export AUTH_PROVIDER=hanko
7+
8+
# Hanko SSO Configuration (required if AUTH_PROVIDER=hanko)
9+
export HANKO_API_URL=https://login.hotosm.test
10+
export COOKIE_SECRET=your-32-byte-secret-key-here
11+
export COOKIE_DOMAIN=.hotosm.test
12+
export COOKIE_SECURE=true
13+
14+
# Admin mappings email (for Hanko)
15+
export ADMIN_EMAILS=admin@hotosm.org
16+
17+

.github/workflows/build_and_deploy.yml

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,15 @@ jobs:
7474
APP_MEM_RES: ${{ vars.APP_MEM_RES }}
7575
REALTIME_ENABLED: ${{ vars.REALTIME_ENABLED }}
7676
UMAP_SOCIAL_AUTH_REDIRECT_IS_HTTPS: ${{ vars.UMAP_SOCIAL_AUTH_REDIRECT_IS_HTTPS }}
77+
# Hanko SSO
78+
AUTH_PROVIDER: ${{ vars.AUTH_PROVIDER }}
79+
HANKO_API_URL: ${{ vars.HANKO_API_URL }}
80+
JWT_ISSUER: ${{ vars.JWT_ISSUER }}
81+
LOGIN_URL: ${{ vars.LOGIN_URL }}
82+
COOKIE_SECRET: ${{ secrets.COOKIE_SECRET }}
83+
COOKIE_DOMAIN: ${{ vars.COOKIE_DOMAIN }}
84+
COOKIE_SECURE: ${{ vars.COOKIE_SECURE }}
85+
ADMIN_EMAILS: ${{ vars.ADMIN_EMAILS }}
7786
run: |
7887
ssh $EC2_USER@$EC2_HOST << ENDSSH
7988
set -e
@@ -93,24 +102,33 @@ jobs:
93102
export APP_MEM_RES="$APP_MEM_RES"
94103
export REALTIME_ENABLED="$REALTIME_ENABLED"
95104
export UMAP_SOCIAL_AUTH_REDIRECT_IS_HTTPS="$UMAP_SOCIAL_AUTH_REDIRECT_IS_HTTPS"
105+
# Hanko SSO
106+
export AUTH_PROVIDER="$AUTH_PROVIDER"
107+
export HANKO_API_URL="$HANKO_API_URL"
108+
export JWT_ISSUER="$JWT_ISSUER"
109+
export LOGIN_URL="$LOGIN_URL"
110+
export COOKIE_SECRET="$COOKIE_SECRET"
111+
export COOKIE_DOMAIN="$COOKIE_DOMAIN"
112+
export COOKIE_SECURE="$COOKIE_SECURE"
113+
export ADMIN_EMAILS="$ADMIN_EMAILS"
96114
APP_DIR="/home/$EC2_USER/umap.hotosm.org"
97115
# Initial setup if it doesn't exist
98116
if [ ! -d "\$APP_DIR" ]; then
99117
sudo mkdir -p \$APP_DIR
100118
sudo chown \$USER:\$USER \$APP_DIR
101119
git clone -b master https://github.com/hotosm/umap.git \$APP_DIR
102-
echo "Cloned repository"
120+
echo "Cloned repository"
103121
fi
104122
cd \$APP_DIR
105123
# Pull latest changes
106124
git fetch origin master
107125
git reset --hard origin/master
108-
echo "Updated to latest master"
126+
echo "Updated to latest master"
109127
# Pull and deploy
110128
docker compose -f compose.yml pull
111129
docker compose -f compose.yml up -d --force-recreate
112130
# Cleanup
113131
docker image prune -af
114-
echo "Deployment complete"
132+
echo "Deployment complete"
115133
ENDSSH
116134

.github/workflows/build_and_deploy_dev.yml

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,15 @@ jobs:
7373
APP_MEM_RES: ${{ vars.APP_MEM_RES }}
7474
REALTIME_ENABLED: ${{ vars.REALTIME_ENABLED }}
7575
UMAP_SOCIAL_AUTH_REDIRECT_IS_HTTPS: ${{ vars.UMAP_SOCIAL_AUTH_REDIRECT_IS_HTTPS }}
76+
# Hanko SSO
77+
AUTH_PROVIDER: ${{ vars.AUTH_PROVIDER }}
78+
HANKO_API_URL: ${{ vars.HANKO_API_URL }}
79+
JWT_ISSUER: ${{ vars.JWT_ISSUER }}
80+
LOGIN_URL: ${{ vars.LOGIN_URL }}
81+
COOKIE_SECRET: ${{ secrets.COOKIE_SECRET }}
82+
COOKIE_DOMAIN: ${{ vars.COOKIE_DOMAIN }}
83+
COOKIE_SECURE: ${{ vars.COOKIE_SECURE }}
84+
ADMIN_EMAILS: ${{ vars.ADMIN_EMAILS }}
7685
run: |
7786
ssh $EC2_USER@$EC2_HOST << ENDSSH
7887
set -e
@@ -92,25 +101,34 @@ jobs:
92101
export APP_MEM_RES="$APP_MEM_RES"
93102
export REALTIME_ENABLED="$REALTIME_ENABLED"
94103
export UMAP_SOCIAL_AUTH_REDIRECT_IS_HTTPS="$UMAP_SOCIAL_AUTH_REDIRECT_IS_HTTPS"
104+
# Hanko SSO
105+
export AUTH_PROVIDER="$AUTH_PROVIDER"
106+
export HANKO_API_URL="$HANKO_API_URL"
107+
export JWT_ISSUER="$JWT_ISSUER"
108+
export LOGIN_URL="$LOGIN_URL"
109+
export COOKIE_SECRET="$COOKIE_SECRET"
110+
export COOKIE_DOMAIN="$COOKIE_DOMAIN"
111+
export COOKIE_SECURE="$COOKIE_SECURE"
112+
export ADMIN_EMAILS="$ADMIN_EMAILS"
95113
APP_DIR="/home/$EC2_USER/umap.hotosm.org"
96114
# Initial setup if it doesn't exist
97115
if [ ! -d "\$APP_DIR" ]; then
98116
sudo mkdir -p \$APP_DIR
99117
sudo chown \$USER:\$USER \$APP_DIR
100118
git clone -b develop https://github.com/hotosm/umap.git \$APP_DIR
101-
echo "Cloned repository"
119+
echo "Cloned repository"
102120
fi
103121
cd \$APP_DIR
104122
# Pull latest changes
105123
git fetch origin develop
106124
git reset --hard origin/develop
107-
echo "Updated to latest develop"
125+
echo "Updated to latest develop"
108126
# Pull and deploy
109127
sed -i -e 's/umap.hotosm.org/umap-dev.hotosm.org/g' nginx/conf.d/umap.conf
110128
docker compose -f compose.dev.yml pull
111129
docker compose -f compose.dev.yml up -d --force-recreate
112130
# Cleanup
113131
docker image prune -af
114-
echo "Deployment complete"
132+
echo "Deployment complete"
115133
ENDSSH
116134
Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
name: Deploy login-hanko to testlogin.umap.hotosm.org
2+
3+
on:
4+
push:
5+
branches:
6+
- login_hanko
7+
workflow_dispatch:
8+
9+
env:
10+
REGISTRY: ghcr.io
11+
IMAGE_PREFIX: hotosm/umap
12+
13+
jobs:
14+
build:
15+
runs-on: ubuntu-latest
16+
permissions:
17+
contents: read
18+
packages: write
19+
steps:
20+
- uses: actions/checkout@v4
21+
- uses: docker/setup-buildx-action@v3
22+
- uses: docker/login-action@v3
23+
with:
24+
registry: ghcr.io
25+
username: ${{ github.actor }}
26+
password: ${{ secrets.GITHUB_TOKEN }}
27+
28+
- name: Build and push app
29+
run: |
30+
docker build -t ghcr.io/${{ env.IMAGE_PREFIX }}/app:login-hanko \
31+
./app
32+
docker push ghcr.io/${{ env.IMAGE_PREFIX }}/app:login-hanko
33+
34+
deploy:
35+
needs: build
36+
runs-on: ubuntu-latest
37+
environment: testlogin
38+
steps:
39+
- uses: actions/checkout@v4
40+
- uses: webfactory/ssh-agent@v0.9.0
41+
with:
42+
ssh-private-key: ${{ secrets.EC2_SSH_KEY }}
43+
44+
- name: Add host to known_hosts
45+
run: ssh-keyscan -H ${{ secrets.EC2_HOST }} >> ~/.ssh/known_hosts
46+
47+
- name: Deploy
48+
env:
49+
EC2_HOST: ${{ secrets.EC2_HOST }}
50+
EC2_USER: ${{ secrets.EC2_USER }}
51+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
52+
GH_ACTOR: ${{ github.actor }}
53+
COOKIE_SECRET: ${{ secrets.COOKIE_SECRET }}
54+
AUTH_PROVIDER: ${{ vars.AUTH_PROVIDER || 'hanko' }}
55+
run: |
56+
ssh $EC2_USER@$EC2_HOST << ENDSSH
57+
set -e
58+
59+
# Ensure Traefik is running
60+
if ! docker ps | grep -q traefik; then
61+
echo "ERROR: Traefik not running. Run setup-test-server.sh first."
62+
exit 1
63+
fi
64+
65+
APP_DIR="/opt/umap-test"
66+
67+
# Setup inicial si no existe
68+
if [ ! -d "\$APP_DIR" ]; then
69+
sudo mkdir -p \$APP_DIR
70+
sudo chown \$USER:\$USER \$APP_DIR
71+
git clone -b login_hanko https://github.com/hotosm/umap.git \$APP_DIR
72+
echo "Cloned repository"
73+
fi
74+
75+
cd \$APP_DIR
76+
77+
# Pull latest changes
78+
git fetch origin login_hanko
79+
git reset --hard origin/login_hanko
80+
echo "Updated to latest login_hanko"
81+
82+
# Create .env with secrets
83+
cat > .env << EOF
84+
POSTGRES_USER=umap
85+
POSTGRES_PASSWORD=umap
86+
POSTGRES_DB=umap
87+
SECRET_KEY=test-secret-key-for-testing-only-min-32-chars
88+
COOKIE_SECRET=${COOKIE_SECRET}
89+
AUTH_PROVIDER=${AUTH_PROVIDER}
90+
EOF
91+
echo "Created .env"
92+
93+
# Login to GHCR
94+
echo "${GH_TOKEN}" | docker login ghcr.io -u ${GH_ACTOR} --password-stdin
95+
96+
# Stop app containers to ensure clean recreate
97+
docker compose -f compose.login-hanko.yaml stop app nginx || true
98+
99+
# Pull new images
100+
docker compose -f compose.login-hanko.yaml pull
101+
102+
# Remove old app containers
103+
docker compose -f compose.login-hanko.yaml rm -f app nginx || true
104+
105+
# Ensure db is running and volumes exist
106+
docker compose -f compose.login-hanko.yaml up -d --no-recreate db
107+
docker run --rm \
108+
-v umap-test_umap-static:/app/static \
109+
-v umap-test_umap-icons:/app/custom/icons \
110+
alpine chown -R 1000:1000 /app/static /app/custom/icons
111+
112+
# Start fresh app containers
113+
docker compose -f compose.login-hanko.yaml up -d
114+
115+
# Cleanup
116+
docker image prune -af
117+
118+
echo "Deployment complete"
119+
ENDSSH

.github/workflows/issue-label.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# We add a label `repo:repo-name` to each new issue,
22
# for easier tracking in external systems
33

4-
name: 🏷️ Issue Label
4+
name: Issue Label
55

66
on:
77
issues:

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@ env.local
88
env.docker
99
env.prod
1010

11+
.env
12+
env
13+
1114
.DS_Store
1215

1316
certbot

app/.dockerignore

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,28 @@
33
**/*.pyc
44
**/__pypackages__
55
**/__pycache__
6+
7+
# Python
8+
.venv/
9+
venv/
10+
*.egg-info/
11+
dist/
12+
build/
13+
.pytest_cache/
14+
.mypy_cache/
15+
.coverage
16+
17+
# Development
18+
.vscode/
19+
.idea/
20+
*.md
21+
LICENSE*
22+
23+
# Data (persistent, not needed in image)
24+
data/
25+
backups/
26+
27+
# Misc
28+
.DS_Store
29+
*.log
30+
tmp/

app/Dockerfile

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,23 +4,32 @@ FROM umap/umap:3.6.1
44

55
WORKDIR /app
66

7-
# Install uv
7+
# Install system dependencies
88
RUN apt-get update && \
9-
apt-get install -y --no-install-recommends curl ca-certificates postgresql-client && \
10-
curl -LsSf https://astral.sh/uv/install.sh | sh -s -- --no-modify-path && \
11-
cp /root/.local/bin/uv /usr/local/bin/uv && \
12-
chmod 755 /usr/local/bin/uv
9+
apt-get install -y --no-install-recommends \
10+
curl \
11+
ca-certificates \
12+
postgresql-client \
13+
git && \
14+
rm -rf /var/lib/apt/lists/*
1315

14-
# Copy app
15-
COPY . .
16+
# Copy uv binary from official image
17+
COPY --from=ghcr.io/astral-sh/uv:0.9 /uv /usr/local/bin/uv
1618

19+
RUN chmod 755 /usr/local/bin/uv
20+
21+
# Create user
1722
RUN adduser --disabled-password --gecos "" appuser && \
1823
chown -R appuser:appuser /app
1924
USER appuser
2025

21-
# Install dependencies
26+
# Install dependencies first (cached independently from source code)
27+
COPY --chown=appuser:appuser pyproject.toml uv.lock ./
2228
RUN uv sync --locked
2329

30+
# Copy application code
31+
COPY --chown=appuser:appuser . .
32+
2433
EXPOSE 8000
2534

2635
# Healthcheck
@@ -33,5 +42,6 @@ RUN mkdir -p /app/static && \
3342
chmod -R 755 /app/static
3443

3544
# App entrypoint
36-
RUN chmod +x ./start.sh
45+
RUN chmod +x /app/start.sh && \
46+
chmod +x /app/scripts/wait-for-db.sh
3747
ENTRYPOINT ["./start.sh"]

0 commit comments

Comments
 (0)