Skip to content
Merged
Show file tree
Hide file tree
Changes from 20 commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
7193d25
feat(static): implement post layout (computer)
Marc-AntoineA Apr 9, 2025
9a88690
tmp(static): add some dummy article for temporary use
Marc-AntoineA Apr 9, 2025
5f325bc
wip: add oauth2 authentication for decapcms
Marc-AntoineA Apr 15, 2025
dc930ac
fix: debug code
Marc-AntoineA Apr 15, 2025
50300e0
devops: cms url should be passed to backend
Marc-AntoineA Apr 15, 2025
53db915
feat: deploy feature for showcase and add admin
Marc-AntoineA Apr 16, 2025
72eae90
clean: remove debug code
Marc-AntoineA Apr 16, 2025
f8c5e67
fix(cms): it finally works
Marc-AntoineA Apr 16, 2025
17a84b0
static: update config.yml
Marc-AntoineA Apr 16, 2025
c101936
static: move content to gitsubmodule
Marc-AntoineA Apr 16, 2025
233a6db
devops: set 'OAUTHLIB_INSECURE_TRANSPORT'
Marc-AntoineA Apr 16, 2025
e7ecf28
clean: remove useless code
Marc-AntoineA Apr 16, 2025
6bcf76a
devops(static): use latest version of git submodule
Marc-AntoineA Apr 16, 2025
378639b
devops: specify main branch for gitmodule
Marc-AntoineA Apr 16, 2025
8963e47
devops: fix git submodule update
Marc-AntoineA Apr 18, 2025
3b3fd6a
woops
Marc-AntoineA Apr 18, 2025
df88c88
clean
Marc-AntoineA Apr 18, 2025
c73a7cc
doc: more docs for decap_cms_auth
Marc-AntoineA Apr 18, 2025
967a21b
Merge branch 'dev' of github.com:TelesCoop/iarbre into feat-install-d…
Marc-AntoineA Apr 18, 2025
63c0b52
fix: use right cert
Marc-AntoineA Apr 18, 2025
9746e34
release: add changelog and change config.yml baseurl for sveltia
Marc-AntoineA Apr 18, 2025
c7cfbdf
merge
Marc-AntoineA Apr 18, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions .github/workflows/deploy-feature.yml
Original file line number Diff line number Diff line change
Expand Up @@ -56,3 +56,12 @@ jobs:
options: |
-l feature -e branch=${{ env.BRANCH_NAME }}
key: ${{ secrets.SSH_PRIVATE_KEY }}
- name: Deploy static
uses: dawidd6/action-ansible-playbook@v2
with:
playbook: showcase.yml
directory: deploy
vault_password: ${{secrets.ANSIBLE_VAULT_KEY}}
options: |
-l feature -e branch=${{ env.BRANCH_NAME }}
key: ${{ secrets.SSH_PRIVATE_KEY }}
Comment on lines +59 to +67
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Je ne suis pas sur de comprendre pourquoi on voudrait mettre à jour le site statique quand on merge sur main ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ces lignes spécifiquement permettent d’avoir un site statique à jour quand on est sur une branche. C’est utile parfois, en l'occurrence pour cette MR ça m’était indispensable de pouvoir disposer d’un environnement "feature".

On pourrait éventuellement vouloir désactiver cet environnement (ou le front ou le back) si notre PR n’y touche pas. Mais ça fait un peu de travail et de la complexité pour je pense, pas grand chose.

4 changes: 4 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
[submodule "static/content"]
path = static/content
url = git@github.com:TelesCoop/iarbre-showcase-content.git
branch = main
75 changes: 75 additions & 0 deletions back/decapcms_auth/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
# Sveltia CMS / Decap CMS Github Oauth Django Application

Add Github Authentication to DecapCMS through yor Django Application.

## Getting Started

### 1. Create and register your Github OAuth Application

Please read [official doc](https://docs.github.com/en/apps/oauth-apps/building-oauth-apps/creating-an-oauth-app).

Authorization callback URL should be :

```
https://<your application url>/callback
```

Copy-paste application id and client secret.

### 2. Install Decap CMS in your Django Project

#### `settings.py` :

- Install application :

```py
INSTALLED_APPS = [
...,
"decapcms_auth",
]
```

- Set up required variables :

```py

DECAP_CMS_AUTH = {
Copy link
Contributor

@QuentinMadura QuentinMadura Apr 18, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

C'est pas très clair pour moi la manière dont on doit récupérer ce token ? Est-ce une valeur qu'on définit nous-mêmes ? À récupérer quelque part ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

J’ai ajouté plus de docs.

"OAUTH_CLIENT_ID": "<public application client id>",
"OAUTH_CLIENT_SECRET": "<private application client secret>"
"SCOPE": "repo,user"
}
```

⚠️ `OAUTH_CLIENT_SECRET` should not be publicly disclosed.

- Define this environment variable:

```py
os.environ["OAUTHLIB_INSECURE_TRANSPORT"] = "1"
```

#### `urls.py`

Include the Decap CMS urls :

```py

from decapcms_auth import urls as decapcmsauth_urls
...
urlpatterns = [
...
path("cms/", include(decapcmsauth_urls)),
...
]
```

### 3. In your Decap CMS config.yml

```yml
backend:
name: github
branch: main
repo: <your repo>
base_url: <base url of your application>
auth_endpoint: /cms/auth # /cms
```
Empty file added back/decapcms_auth/__init__.py
Empty file.
7 changes: 7 additions & 0 deletions back/decapcms_auth/apps.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
from django.apps import AppConfig


class DecapcmsAuthConfig(AppConfig):
default_auto_field = "django.db.models.BigAutoField"
name = "decapcms_auth"
verbose_name = "DecapCMS auth config"
Empty file.
22 changes: 22 additions & 0 deletions back/decapcms_auth/templates/decapcms_auth/callback.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<html>
<body>
<script>
(function () {
function recieveMessage(e) {
console.log("recieveMessage %o", e);
// send message to main window with da app
const provider = "github"
const state = "success"
window.opener.postMessage(
`authorization:${provider}:${state}:${JSON.stringify({{content | safe}})}`,
e.origin,
);
}
window.addEventListener("message", recieveMessage, false);
// Start handshare with parent
console.log("Sending message: %o", "github");
window.opener.postMessage("authorizing:github", "*");
})();
</script>
</body>
</html>
11 changes: 11 additions & 0 deletions back/decapcms_auth/urls.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
from django.urls import path
from rest_framework import routers

from .views import callback, auth

router = routers.DefaultRouter()

urlpatterns = [
path("auth/", auth),
path("callback/", callback),
]
34 changes: 34 additions & 0 deletions back/decapcms_auth/views.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
from requests_oauthlib import OAuth2Session
from django.conf import settings
from django.shortcuts import redirect, render
from django.http import HttpResponseBadRequest

AUTHORIZATION_BASE_URL = "https://github.com/login/oauth/authorize"
TOKEN_URL = "https://github.com/login/oauth/access_token"
CLIENT_ID = settings.DECAP_CMS_AUTH["OAUTH_CLIENT_ID"]
CLIENT_SECRET = settings.DECAP_CMS_AUTH["OAUTH_CLIENT_SECRET"]
SCOPE = settings.DECAP_CMS_AUTH["SCOPE"]


def auth(request):
"""Redirect to Github auth"""
github = OAuth2Session(client_id=CLIENT_ID, scope=SCOPE)
authorization_url, _ = github.authorization_url(AUTHORIZATION_BASE_URL)
return redirect(authorization_url)


def callback(request):
"""Retrieve access token"""
state = request.GET.get("state", "")
try:
github = OAuth2Session(CLIENT_ID, state=state, scope=SCOPE)
token = github.fetch_token(
TOKEN_URL,
client_secret=CLIENT_SECRET,
authorization_response=request.get_full_path(),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Je suis étonné du lint pour cette ligne

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

J’ai relancé sur l’intégralité du code et ça passe pour moi avec la configuration actuelle.

)
content = {"token": token.get("access_token", ""), "provider": "github"}
return render(request, "decapcms_auth/callback.html", {"content": content})

except BaseException:
return HttpResponseBadRequest()
15 changes: 15 additions & 0 deletions back/iarbre_data/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@
import getconf
from django.http import Http404

# Required for decap auth
os.environ["OAUTHLIB_INSECURE_TRANSPORT"] = "1"

# Build paths inside the project like this: BASE_DIR / 'subdir'.
BASE_DIR = Path(__file__).resolve().parent.parent
DATA_DIR = BASE_DIR / "file_data"
Expand Down Expand Up @@ -64,6 +67,7 @@
"django_extensions",
"telescoop_backup",
"rest_framework",
"decapcms_auth",
]

MIDDLEWARE = [
Expand All @@ -76,6 +80,10 @@
"django.middleware.clickjacking.XFrameOptionsMiddleware",
]

# Mandatory for Decap CMS Auth
# https://docs.djangoproject.com/en/5.1/ref/middleware/#cross-origin-opener-policy
SECURE_CROSS_ORIGIN_OPENER_POLICY = None

if IS_LOCAL_DEV:
CORS_ALLOW_ALL_ORIGINS = True
CORS_ALLOW_METHODS = [
Expand Down Expand Up @@ -233,6 +241,13 @@
"djangorestframework_camel_case.parser.CamelCaseJSONParser",
),
}

DECAP_CMS_AUTH = {
"OAUTH_CLIENT_ID": config.getstr("github_oauth.client_id"),
"OAUTH_CLIENT_SECRET": config.getstr("github_oauth.client_secret"),
"SCOPE": "repo,user",
}

# For macOS users, we need to set the GDAL_LIBRARY_PATH and GEOS_LIBRARY_PATH to the path of the libraries
if sys.platform == "darwin":
GDAL_LIBRARY_PATH = os.environ.get("GDAL_LIBRARY_PATH")
Expand Down
2 changes: 2 additions & 0 deletions back/iarbre_data/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,11 @@
"""
from django.contrib import admin
from django.urls import path, include
from decapcms_auth import urls as decapcmsauth_urls

urlpatterns = [
path("admin/", admin.site.urls),
path("api/", include("api.urls")),
path("backup/", include("telescoop_backup.urls")),
path("cms/", include(decapcmsauth_urls)),
]
1 change: 1 addition & 0 deletions back/requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ numpy==2.0.1
protobuf==5.28.2
psycopg2==2.9.9
pyproj==3.7.0
requests_oauthlib==2.0.0
rollbar==1.1.0
shapely==2.0.5
telescoop_backup==0.5.3
Expand Down
62 changes: 34 additions & 28 deletions deploy/group_vars/all/cross_env_vault.yml
Original file line number Diff line number Diff line change
@@ -1,29 +1,35 @@
$ANSIBLE_VAULT;1.1;AES256
37643939363936323039323662313262616665376532366639366234333833373032323830323562
3161633961646239663933343933333338326466626435610a646537393039373737623465356662
62333566626533633136383535373634373232613133633330376336303331316139383631376162
3633653564613939390a376665623932366264333865383931623361333764313664326637343566
35393434636239333766353162303630326237303631643534363765653538643162373632316564
34373136333933373934393533633564656633323838363261333065653066386137353936646666
32306530383865303736383762636364306432626563303837663566316430343465636436383531
64656136666635633136376636323164303535643339303862633037623966373635333238306237
32393732633237363736333134636161323163333439626331663461633437646534356635633230
64383531633963613161643063343837326665656239633836613361303732666136616365646562
62613030633961643666643139626632623036653532626666323839303038633435383766643962
30666565633137316361656639613263303532656461393066643939333835643037323336386664
64303835313961313831363461313934396133303136636633613832626439343762633131353164
62343263663461643861306431393866376532326233353136353963376161316463363364656230
62316239643561376636323461636136313762376665356433323934366265313935363063633764
63316161323365313032363432653763646439386365656239383566633063363835323039366139
66383432323364333837373830643439343361646365353333303466343330323031343232333636
36633430623637366539393730663835386466316537613135663537353733386631396564653066
30633534323965346464663337623664333466313361343531373131393666653662346530396134
62353932646434666566336463666337643330376630303466626561366263633164383162663563
37613631376230633562633565616134636237643565323334643263333431343562646532663130
36393337366433623330343765356635373033363335353933333166383465323430613665326430
65383862346462373930323938303032316634623961356565613039643237313063333331386162
37613462633566326433366161343766316637323065386532333236316637366462336333623932
34323538643238383665393463646636613036363332353362646237386232353932346332306331
65613534313837376232373632313438653037306630346638616433373133353534306430616234
33633339376333356266663634653765323039623730366635373632636333363966353139636532
63363339666337633138
62393734386563303834643531386666653633303134393830663666656234373662323464346432
3534343536613637356431393464363662653631306161390a646162343535653635383263653838
32326132636132336662356230356531383733313061313737643736633931303637633566353537
3433343439623439350a313131393861386336333965366461336230616462323630306432356463
65613433323064623739633832323238376536323038656235313237623437363164323466633832
61383435656237343438373163316139346136346436346131333439303534393964666631363964
37313661383230306363373065663132363336653962363064656435373439333964336632306239
64363665376537313233363234656238636236306166393838663863323930356665643864636562
62626466333863333866633034616662346330613461303866346432623834316238346537383265
31373961326435313736643464353766316162396566363462393431366133613965366430336338
37653063303132643330663938346533653065346131336164323831623030326631353464373130
35303062366261393362316434326665643263383133356131313162343863656435313063663836
39663235356336643432336663396436373165633463616232303061336239633739643433303866
66353737373832383962626232363336643630343036366336626234323037393037363537326365
35343232396436396633623966323234353533396237376235396635306264313339653331346338
65326131393430316362656662653231393630636266653931316364333938633335633235636136
33616336313831626163356337303666323132396434386566376161366563663666613537383062
32653266656163306437616530336461653164383537663663313739633761366361663462653538
36363433323064616533623339313262653332656130323766613132636232653435643065663735
32656137333366313832346536623130666265343566653134663038636232646461373236396661
37613561343831633734373063343564626234616235303266393664303631306464613061643530
62396635353365643631623862323132396636303863336464353862366537653234623265356663
30336539393662383765653132643431303938373062373937623261393361393466373136393437
32383365343161303937346539333264353236303737323962646631653433316566623061633831
63616364376438616238336262666165353638303065383765393035383537353236353039633662
35353063663037633037643731663864373530366638373833636365366338316534636230326539
32376533653232653930373335393564616332393138656335376633623762383135613530626131
32643863306434303534373335666437303963626238636363663136643633353463373031323362
64336535393761353831346635656530633330353234653762326438623437646234663530616336
64633161393239356231663064353737313135373135393066303638306530373136346636363264
38663261363062623736623664633439626132393030623839666237633363633431333265363030
37343232326639306565333539373165343965616664323634663135343633633138393262376362
66303365303536626166333333613332353934366365346261656634373937653439363334633939
3964363465313663373064393566396234356439373131653463
6 changes: 6 additions & 0 deletions deploy/group_vars/feature/vars.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,11 @@ public_hostnames:
- "{{ main_hostname }}"
# hostnames mentioned here are redirected to the main hostname
redirect_hostnames: []

showcase_hostname: "feature-{{ branch_slug[:20] }}-showcase.iarbre.fr"
showcase_redirect_hostnames: []
showcase_certificate_hostname: "iarbre.fr-0001"

all_hostnames: "{{ public_hostnames + redirect_hostnames }}"
# the certificate that you see in /etc/nginx/sites-enabled/{{ project_slug }},
# in the line like /etc/letsencrypt/live/[certificate_hostname]/fullchain.pem
Expand All @@ -26,6 +31,7 @@ backend_static_path: "{{ project_dir }}/backend_static"
branch_slug: "{{ branch | replace('/','-') }}"
frontend_branch: "{{ branch }}"
backend_branch: "{{ branch }}"
showcase_branch: "{{ branch }}"

environment_name: "feature-{{ branch_slug }}"

Expand Down
7 changes: 7 additions & 0 deletions deploy/group_vars/preprod/vars.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,11 @@ project_slug: "{{ base_project_slug }}{{ environment_suffix }}"
main_hostname: "preprod-carte.iarbre.fr"
public_hostnames:
- "{{ main_hostname }}"

showcase_hostname: "preprod-showcase.iarbre.fr"
showcase_redirect_hostnames: []
showcase_certificate_hostname: "iarbre.fr-0001"

# hostnames mentioned here are redirected to the main hostname
redirect_hostnames: []
all_hostnames: "{{ public_hostnames + redirect_hostnames }}"
Expand All @@ -21,5 +26,7 @@ backend_static_path: "{{ project_dir }}/backend_static"

frontend_branch: dev
backend_branch: dev
showcase_branch: dev
docs_branch: dev

environment_name: production
14 changes: 10 additions & 4 deletions deploy/group_vars/prod/vars.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,20 +8,26 @@ public_hostnames:
- "{{ main_hostname }}"
# hostnames mentioned here are redirected to the main hostname
redirect_hostnames: []

showcase_hostname: "iarbre.fr"
showcase_redirect_hostnames:
- "www.iarbre.fr"

all_hostnames: "{{ public_hostnames + redirect_hostnames }}"
# the certificate that you see in /etc/nginx/sites-enabled/{{ project_slug }},
# in the line like /etc/letsencrypt/live/[certificate_hostname]/fullchain.pem
certificate_hostname: "iarbre.fr-0001"
showcase_certificate_hostname: "iarbre.fr-0002"
# only change this variable after having:
# - run the playbook at least once with the value `false`
# - run `certbot --nginx` manually on the server
https_enabled: true
project_dir: "{{project_base_dir}}{{ environment_suffix }}"
backend_static_path: "{{ project_dir }}/backend_static"

frontend_branch: dev
backend_branch: dev
showcase_branch: dev
docs_branch: dev
frontend_branch: main
backend_branch: main
showcase_branch: main
docs_branch: main

environment_name: production
4 changes: 4 additions & 0 deletions deploy/roles/backend/templates/settings.ini.j2
Original file line number Diff line number Diff line change
Expand Up @@ -34,3 +34,7 @@ password = {{ database_password|default('') }}

[environment]
environment = {{ environment_name }}

[github_oauth]
client_id= {{ vault_github_oauth_client_id }}
client_secret= {{ vault_github_oauth_client_secret }}
1 change: 1 addition & 0 deletions deploy/roles/frontend/vars/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,4 @@ server_uris_passed_to_backend:
- api
- backup
- hijack
- cms
Loading
Loading