- Add public organizers list page (/organisateurs) with neo-brutalist card grid, social icons, and logo display
- Add organizer detail page (/organisateur/{id}-{slug}) with company info, SIRET, email, address, social links, and events placeholder
- Add slug-based URLs with 301 redirect on wrong slug, getSlug() method on User entity
- Add "Voir les evenements" button on organizer cards linking to detail page
- Add JSON-LD BreadcrumbList to all 17 pages that were missing breadcrumbs (login, forgot_password, register_success, email_verified, legal/*, attestation/*, account/*)
- Add Open Graph meta tags (og:title, og:description, og:image, og:type, og:locale, og:site_name) in base.html.twig with automatic inheritance from title/description blocks
- Add og:image with organizer logo on detail page
- Update sitemap: add /organisateurs to sitemap-main, generate organizer detail URLs in sitemap-orgas with logo images
- Update navbar to highlight "Organisateurs" on detail pages
- Redesign homepage with hero section, marquee, stats counters, how-it-works, and CTA sections
- Add Tailwind v4 @source "../templates" directive to app.scss and admin.scss
- Migrate Flysystem from S3 to local storage (uploads/events, uploads/logos)
- Update Liip Imagine config with FormatExtensionResolver for webp conversion
- Add User entity social fields (website, facebook, instagram, twitter, tiktok), logo upload (Vich), __serialize/__unserialize for session safety
- Add account page settings tab with profile, logo upload, and social media for organizers
- Add Stripe Connect status display and sub-account management in account page
- Delete WebpExtensionSubscriber (replaced by FormatExtensionResolver)
- Add migration for social fields and logo columns
- Add deploy.yml chmod tasks for uploads directories
- Add HomeController tests (detail success, wrong slug redirect, 404 cases)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
282 lines
8.1 KiB
YAML
282 lines
8.1 KiB
YAML
---
|
|
# --- Cloudflare configuration ---
|
|
- name: Configure Cloudflare
|
|
hosts: localhost
|
|
connection: local
|
|
vars_files:
|
|
- vault.yml
|
|
|
|
vars:
|
|
zone_id: "{{ cloudflare_zone_id }}"
|
|
cloudflare_record: ticket.e-cosplay.fr
|
|
server_ip: 34.90.187.4
|
|
|
|
tasks:
|
|
# --- DNS ---
|
|
- name: Create or update DNS A record
|
|
uri:
|
|
url: "https://api.cloudflare.com/client/v4/zones/{{ zone_id }}/dns_records"
|
|
method: POST
|
|
headers:
|
|
Authorization: "Bearer {{ cloudflare_api_token }}"
|
|
Content-Type: application/json
|
|
body_format: json
|
|
body:
|
|
type: A
|
|
name: "{{ cloudflare_record }}"
|
|
content: "{{ server_ip }}"
|
|
ttl: 1
|
|
proxied: true
|
|
status_code: [200, 409]
|
|
register: dns_result
|
|
ignore_errors: true
|
|
|
|
- name: Update DNS A record if already exists
|
|
when: dns_result.status == 409 or (dns_result.json is defined and not dns_result.json.success)
|
|
block:
|
|
- name: Get existing DNS record
|
|
uri:
|
|
url: "https://api.cloudflare.com/client/v4/zones/{{ zone_id }}/dns_records?name={{ cloudflare_record }}&type=A"
|
|
method: GET
|
|
headers:
|
|
Authorization: "Bearer {{ cloudflare_api_token }}"
|
|
return_content: true
|
|
register: existing_dns
|
|
|
|
- name: Update DNS record
|
|
uri:
|
|
url: "https://api.cloudflare.com/client/v4/zones/{{ zone_id }}/dns_records/{{ existing_dns.json.result[0].id }}"
|
|
method: PUT
|
|
headers:
|
|
Authorization: "Bearer {{ cloudflare_api_token }}"
|
|
Content-Type: application/json
|
|
body_format: json
|
|
body:
|
|
type: A
|
|
name: "{{ cloudflare_record }}"
|
|
content: "{{ server_ip }}"
|
|
ttl: 1
|
|
proxied: true
|
|
|
|
# --- SSL/TLS ---
|
|
- name: Set SSL mode to Full (Strict)
|
|
uri:
|
|
url: "https://api.cloudflare.com/client/v4/zones/{{ zone_id }}/settings/ssl"
|
|
method: PATCH
|
|
headers:
|
|
Authorization: "Bearer {{ cloudflare_api_token }}"
|
|
Content-Type: application/json
|
|
body_format: json
|
|
body:
|
|
value: strict
|
|
|
|
- name: Enable Always Use HTTPS
|
|
uri:
|
|
url: "https://api.cloudflare.com/client/v4/zones/{{ zone_id }}/settings/always_use_https"
|
|
method: PATCH
|
|
headers:
|
|
Authorization: "Bearer {{ cloudflare_api_token }}"
|
|
Content-Type: application/json
|
|
body_format: json
|
|
body:
|
|
value: "on"
|
|
|
|
- name: Set minimum TLS version to 1.2
|
|
uri:
|
|
url: "https://api.cloudflare.com/client/v4/zones/{{ zone_id }}/settings/min_tls_version"
|
|
method: PATCH
|
|
headers:
|
|
Authorization: "Bearer {{ cloudflare_api_token }}"
|
|
Content-Type: application/json
|
|
body_format: json
|
|
body:
|
|
value: "1.2"
|
|
|
|
# --- Security headers ---
|
|
- name: Enable HSTS
|
|
uri:
|
|
url: "https://api.cloudflare.com/client/v4/zones/{{ zone_id }}/settings/security_header"
|
|
method: PATCH
|
|
headers:
|
|
Authorization: "Bearer {{ cloudflare_api_token }}"
|
|
Content-Type: application/json
|
|
body_format: json
|
|
body:
|
|
value:
|
|
strict_transport_security:
|
|
enabled: true
|
|
max_age: 31536000
|
|
include_subdomains: true
|
|
nosniff: true
|
|
|
|
# --- Performance ---
|
|
- name: Enable Brotli compression
|
|
uri:
|
|
url: "https://api.cloudflare.com/client/v4/zones/{{ zone_id }}/settings/brotli"
|
|
method: PATCH
|
|
headers:
|
|
Authorization: "Bearer {{ cloudflare_api_token }}"
|
|
Content-Type: application/json
|
|
body_format: json
|
|
body:
|
|
value: "on"
|
|
|
|
- name: Set browser cache TTL to 1 month
|
|
uri:
|
|
url: "https://api.cloudflare.com/client/v4/zones/{{ zone_id }}/settings/browser_cache_ttl"
|
|
method: PATCH
|
|
headers:
|
|
Authorization: "Bearer {{ cloudflare_api_token }}"
|
|
Content-Type: application/json
|
|
body_format: json
|
|
body:
|
|
value: 2592000
|
|
|
|
# --- Security ---
|
|
- name: Set security level to medium
|
|
uri:
|
|
url: "https://api.cloudflare.com/client/v4/zones/{{ zone_id }}/settings/security_level"
|
|
method: PATCH
|
|
headers:
|
|
Authorization: "Bearer {{ cloudflare_api_token }}"
|
|
Content-Type: application/json
|
|
body_format: json
|
|
body:
|
|
value: medium
|
|
|
|
- name: Enable bot fight mode
|
|
uri:
|
|
url: "https://api.cloudflare.com/client/v4/zones/{{ zone_id }}/bot_management"
|
|
method: PUT
|
|
headers:
|
|
Authorization: "Bearer {{ cloudflare_api_token }}"
|
|
Content-Type: application/json
|
|
body_format: json
|
|
body:
|
|
fight_mode: true
|
|
ignore_errors: true
|
|
|
|
# --- Allow SEO bots ---
|
|
- name: Allow SEO and social media bots
|
|
uri:
|
|
url: "https://api.cloudflare.com/client/v4/zones/{{ zone_id }}/firewall/rules"
|
|
method: POST
|
|
headers:
|
|
Authorization: "Bearer {{ cloudflare_api_token }}"
|
|
Content-Type: application/json
|
|
body_format: json
|
|
body:
|
|
- filter:
|
|
expression: '(cf.client.bot) or (http.user_agent contains "Googlebot") or (http.user_agent contains "Bingbot") or (http.user_agent contains "bingbot") or (http.user_agent contains "Yandex") or (http.user_agent contains "DuckDuckBot") or (http.user_agent contains "Baiduspider") or (http.user_agent contains "facebookexternalhit") or (http.user_agent contains "Twitterbot") or (http.user_agent contains "LinkedInBot")'
|
|
action: allow
|
|
description: "Allow SEO and social media bots"
|
|
status_code: [200, 409]
|
|
ignore_errors: true
|
|
|
|
# --- Server deployment ---
|
|
- name: Deploy e-ticket to production
|
|
hosts: production
|
|
become: true
|
|
vars_files:
|
|
- vault.yml
|
|
|
|
pre_tasks:
|
|
- name: Enable maintenance mode
|
|
command: make maintenance_on
|
|
args:
|
|
chdir: /var/www/e-ticket
|
|
|
|
tasks:
|
|
- name: Deploy .env.local
|
|
template:
|
|
src: env.local.j2
|
|
dest: /var/www/e-ticket/.env.local
|
|
owner: bot
|
|
group: bot
|
|
mode: "0600"
|
|
|
|
- name: Stop production containers
|
|
command: make stop_prod
|
|
args:
|
|
chdir: /var/www/e-ticket
|
|
|
|
- name: Install dependencies and build assets
|
|
command: make install_prod
|
|
args:
|
|
chdir: /var/www/e-ticket
|
|
|
|
- name: Start production containers
|
|
command: make start_prod
|
|
args:
|
|
chdir: /var/www/e-ticket
|
|
|
|
- name: Run migrations
|
|
command: make migrate_prod
|
|
args:
|
|
chdir: /var/www/e-ticket
|
|
|
|
- name: Clear cache
|
|
command: make clear_prod
|
|
args:
|
|
chdir: /var/www/e-ticket
|
|
|
|
- name: Ensure uploads directories exist with correct permissions
|
|
file:
|
|
path: "/var/www/e-ticket/public/uploads/{{ item }}"
|
|
state: directory
|
|
owner: "1000"
|
|
group: "1000"
|
|
mode: "0755"
|
|
recurse: true
|
|
loop:
|
|
- logos
|
|
|
|
- name: Ensure var/payouts directory exists
|
|
file:
|
|
path: /var/www/e-ticket/var/payouts
|
|
state: directory
|
|
owner: "1000"
|
|
group: "1000"
|
|
mode: "0755"
|
|
|
|
- name: Ensure Caddy sites directory exists
|
|
file:
|
|
path: /etc/caddy/sites
|
|
state: directory
|
|
owner: root
|
|
group: root
|
|
mode: "0755"
|
|
|
|
- name: Deploy Caddy config
|
|
template:
|
|
src: caddy.j2
|
|
dest: /etc/caddy/sites/e-ticket.conf
|
|
owner: root
|
|
group: root
|
|
mode: "0644"
|
|
notify: Reload Caddy
|
|
|
|
- name: Deploy Messenger supervisor config
|
|
template:
|
|
src: messenger.j2
|
|
dest: /etc/supervisor/conf.d/e-ticket.conf
|
|
owner: root
|
|
group: root
|
|
mode: "0644"
|
|
notify: Reload Supervisor
|
|
|
|
post_tasks:
|
|
- name: Disable maintenance mode
|
|
command: make maintenance_off
|
|
args:
|
|
chdir: /var/www/e-ticket
|
|
|
|
handlers:
|
|
- name: Reload Caddy
|
|
systemd:
|
|
name: caddy
|
|
state: reloaded
|
|
|
|
- name: Reload Supervisor
|
|
command: supervisorctl reread && supervisorctl update
|