Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • pub/pnm-public/camino
1 result
Show changes
Commits on Source (23)
Showing
with 1109 additions and 40 deletions
ENV=ENC[AES256_GCM,data:wo80,iv:KTiTD6K0zzarG5SfXMv8MYOHbaxBhRpAWrNYLjO8CuA=,tag:F40SGZqrt7+LBEYlPi7x7g==,type:str]
#ENC[AES256_GCM,data:FQbnHuo=,iv:whMNIziAx6SieHJLuCaZzp6YouQQm/y9peu+CDib51I=,tag:plLEZwL3eL4Tz0oBevGaDA==,type:comment]
NODE_ENV=ENC[AES256_GCM,data:WsY3mdb/0IAy8g==,iv:qsRfjqnWBu59ndQmkFDSgBTEcoz5cgLACXVB9/SDfjY=,tag:omu6dgcdAOatq9NqhFDEcA==,type:str]
API_PORT=ENC[AES256_GCM,data:SkusJA==,iv:rlGM12T/ZpqZV0NXrRJxEavmT/9EXwWl6RWj9q6I+xg=,tag:1tYhYrjxpp1m187mE0sV9w==,type:str]
UI_PORT=ENC[AES256_GCM,data:zY3byQ==,iv:tiE2sHRBWlHNGDk7TLPWR/UBz1eghyIUneraZL9E0E0=,tag:328JR5vyic7K9Y4EJioYDA==,type:str]
DOC_PORT=ENC[AES256_GCM,data:6Q0=,iv:bf9ZrFQZgV0KAUxMDOuxGsmoX25U7nE//eNtrCLlKiE=,tag:hW9TNvg87XtjfjaLtoxL0w==,type:str]
STORYBOOK_PORT=ENC[AES256_GCM,data:A4U=,iv:kX8VcAWCIY5JAMU67c/H9PUUDtKw+fQCq5HyKcYTIXw=,tag:KNsFsQcDP/+wxicjFCctww==,type:str]
OAUTH_PORT=ENC[AES256_GCM,data:b9IRig==,iv:Nzk37lcwpSKxMx5ccMsOFOrlBa+Vugeg/Oa4Zpx5Qw4=,tag:dnZRLIAUb3BF/j2xtWq+LQ==,type:str]
KEYCLOAK_PORT=ENC[AES256_GCM,data:ABxBGA==,iv:veeqIgzc7phEsAn3XdlsaOzH1GTbIg225bPF/xs2Jho=,tag:NZ/+jnjoC7cO/xAjcfqgIA==,type:str]
#ENC[AES256_GCM,data:n7AjF8rjywSw9ZfdmA8be4hHR9P5gvA03jh9nJRGm9c=,iv:pz6Z9VSYZMBlT7ib8mUPchfTcRrDXpoP8WuSgzvLFLU=,tag:oNMDmqpALhHDE+9WT2QvGA==,type:comment]
API_HOST=ENC[AES256_GCM,data:BtrlbrB1/zi7ulhYqrB3xE95j1mGLAPfh9sz,iv:BnvAwM+2f7sJ6CVL6NeZnNWRkqX9fYhO8Hthbf7Polc=,tag:nI9AIe/qNUIfkQRklWXgmw==,type:str]
API_URL=ENC[AES256_GCM,data:UhCyQKeCO8qvj7clORjQoUR5H8DqkJUsviCI4rnII4PHQqs=,iv:qnBD0XFhNc1PLp0EhUbNUlkhUV6VPRimvEB6+ez/S6U=,tag:3fS+Hv2tnhjnp79z/sbbAw==,type:str]
OAUTH_HOST=ENC[AES256_GCM,data:M9/SH8mc0GLyW/O6bxuuwln9iGZxveQ=,iv:jmRfBe9T8qOIMQdJRmru2YY+1jl8jZU0iF1EezseCoU=,tag:NZP7dyoKouwYf9ml5h3sRQ==,type:str]
OAUTH_URL=ENC[AES256_GCM,data:LF5ZIRXG6U0omwSdF2UcJlIqqkkOUmuVJaZ1MfpE0Q==,iv:hNPjmW7KxZ4E/WEqGiZXy/7p/0PXinwQGWsJjnuFOV0=,tag:UNxjuvhNYA1moAtfUDxdAw==,type:str]
KEYCLOAK_HOST=ENC[AES256_GCM,data:+JQMmo2jx2rQps4igh7waNzB30SZJ4uQ4gu+ZQ==,iv:lnbcjSnbmgxdgGl1dLq+bT3Z0u/WiLfCJf0U/xbIgNo=,tag:5cz3UK+Wib/0OGFrvhJYOQ==,type:str]
KEYCLOAK_LOGOUT_URL=ENC[AES256_GCM,data:MK22PJRrPOItah05shIQjL162iwimz6Riv/dJQCH3HOr5IxgxdlpO0LphQdidl8Mq5/kXPDjSF97zndKJSGYT5tYzDIw+WYKH8XFVCdJSn+4,iv:ZHYTkZfX2d/Xm45adzVx+kivOQQOSOLe+Qx4KGKxUe0=,tag:TPQz9q+UqdWe5DmmsdNOtw==,type:str]
KEYCLOAK_RESET_PASSWORD_URL=ENC[AES256_GCM,data:5n1tmpOq8sp4JByFMaXg4MFPuTcg1vzkkkwsOSeC0vap2YTbk8zLTq9hKBIq8se5Xu4+U5IAH/NJ6y9ZnlOTxErbfVyYqyUYhOjJlpRN1A==,iv:I9OZpeUCGG8AoS4mlKCysRbkGKOpa9E4W4XPwy52x8o=,tag:S4J2YxycYmcNA7vm3MYPXQ==,type:str]
#ENC[AES256_GCM,data:N9lt1ku0kWezOzU=,iv:5LexmCvP6OURTVL6h4AIhvMJ2N36A4zmS5INVP3c0Zg=,tag:014R0t4JdmD4b+Y3eInTAw==,type:comment]
#ENC[AES256_GCM,data:gRq6YCJi2PBbXL6tfT1BiRCTEmhBNvUjJlOb9W4gHXy5UdiG+t9nEd16454fK0IAs1hMtPQR4CM6vOS1IMOwSs6SH49jbsNMYfj0VFJbQ/0vIemCnBxXxirQDcsnteA=,iv:CzY3YXa/OeovbpPm9W6fl4dHWN6qQ7d7rRdOirSfFmA=,tag:6/SqZW/B5wzApINeGNricA==,type:comment]
JWT_SECRET=ENC[AES256_GCM,data:6ZVN1QdhLGD1XvT1nBqQ0krTJZzMvBYco3L9avPGPSKI5Je9LEZPobmmduB7M+huEr6Pf78Cwjtco4c8YPzlCJy5UGKPmVCcbKRW28lg2SEOkFfX2EGgnH8+gQI3FwqVhSh+Ytvxa1SbYki4Vxt/JSNAEye4IkPOVy6pJsGacXKIlxpW0/t2elFd4opN5AXyIz10DpKh0l4BcJyPclJwBf2xrhevBtImFQAOhMnKzNC4d1v1H0MOkk582Divhqy+6LyqcuLnViKVeGW80C5PAkgTl0b40ICiv9wbEx95zs5GHubAkTvr55Of/j9QCJVAqgcQbyZ4kvVhepmH59lPOBIQmo9LbYIXeatvuL3eXWbg30pKMr138iyveHvZKqD4C+1nQpyGP8j0oTVHLwoDaVYE8Zci5zmAye/IlbmiIo4kJ7nJ/+01P/naDJ3VN1JAQh0l+tAJL0ljjaI5z08RDELYmHjX85EoTQE2lK3JcrPsRxFpweOyZ0URnsSi8S6GScUsNsS9p4PxYyPm9qHTA883Vf8ynazSDwUORrLNdkDYYD//J6E7TH/0+rzCr1+6NoKuVJQa3w+JpmvOalo=,iv:R2mo7zgN6qFWHOtAS6edRhG4rqzqWPMPZhZW6aiPR08=,tag:+aHl7jALGJIRV6O+PdZ4jQ==,type:str]
JWT_SECRET_ALGORITHM=ENC[AES256_GCM,data:XDRz9iIE3g==,iv:Cc5MgIzqrEaurbf+Le5j6uIxJHgMpIJUxZXGJXskxPg=,tag:qSrIC+a/4vTjHV2rfWqWFw==,type:str]
KEYCLOAK_CLIENT_ID=ENC[AES256_GCM,data:m8H4GoIpRUkaLg==,iv:8OCwpszD+hZB9vlg6YadjbVH54vGoUgsOf2o6ddxxSU=,tag:vdL40B4IFkKmJiTfZZOssg==,type:str]
KEYCLOAK_CLIENT_SECRET=ENC[AES256_GCM,data:+HdIXIiufW46r4jStwDYowB4bzrh5qHCKQctVeeSrAQ=,iv:Rv3yGiE5V0iwIJGYQtFLEWalsOVNYDGyJrvVJJhyKZs=,tag:KIPXVmor/7ZT75vUvf7Cjw==,type:str]
KEYCLOAK_API_CLIENT_ID=ENC[AES256_GCM,data:l57fjJriIsm0Kw==,iv:crO5L4M2QjqeaXjreHHkBlMXQcdakvEd/Bk06Msx54Y=,tag:0vsbeUMe6h7CoPa3gqW5tg==,type:str]
KEYCLOAK_API_CLIENT_SECRET=ENC[AES256_GCM,data:MOjNv+b+Y/opn1x2+XbNQUQxWGjqX6boe6edB32WO68=,iv:4FQlIJYyLesJ6s5V4jkmAnmGrnvNZr40bFuZDgKusFY=,tag:Flg+z9lxYqK4Sfgjkszbqw==,type:str]
KEYCLOAK_URL=ENC[AES256_GCM,data:ULHj2RkmWInX2NXUyejyWKFnEVQ/KogImeMBf7FhloIN47wn,iv:ASPZ8TQEPhP0eEMSgqWLaptuPVghVNuC/zrcMbQdMJw=,tag:qOddEqa3r3qwFmNf7X2zlg==,type:str]
OAUTH2_COOKIE_SECRET=ENC[AES256_GCM,data:soU8zuT0NGuUvvya/IHN+trz/rYuTPd6zSYuLO+X8X+183CU5ucc0OyRlQI=,iv:COHi9/CfFTTLZsCbtiFzr1GmgmwYCWzwxq+mtihzdXU=,tag:mLPEdVTAgRo2fw28O20/nA==,type:str]
DOC_HOST=ENC[AES256_GCM,data:Texra/onfGrk0ZzVEGnPpouNEfN8ARpN2nm+gw==,iv:yMTTLdp08cM79/LAxg4IAx8jfsZpdmhEEGNtvvyI+aI=,tag:pIYU2jLaBF/ghqqlqcOrkw==,type:str]
DOC_URL=ENC[AES256_GCM,data:JSopzUEWEUqlriyChx7l71ytx2Qo/E5hIJyQ6gvKAfNXhY+p,iv:pI+fRxhkj8XNdBQD3vQtYeEufJiOHyYBTaU1EfKN1k0=,tag:Qi3k+wgc7+0J8bZonbf6Lw==,type:str]
#ENC[AES256_GCM,data:S90vOmHJTHvS,iv:f4+I/J76teIcKhOAf+FynNAEgwazfbE2KG6XTnPMIWY=,tag:xTT2JyLi5cClaMoBQPvEnA==,type:comment]
PGHOST=ENC[AES256_GCM,data:wCdK7rAREeaR,iv:4ib2xK5XvJGf0ey6SFxLhd6rD8OrAgnptcWsfASZ9o4=,tag:VEUg0SeIZyywih1rS8KnvQ==,type:str]
PGPORT=ENC[AES256_GCM,data:NwsRQw==,iv:lZvNtghMe69nq8QihKLGD9UO/WNWim+zCv4uwJd6ifI=,tag:lNavbqN7jsvGHckSYo39xA==,type:str]
PGDATABASE=ENC[AES256_GCM,data:oD436Mfh,iv:wf8lpQje1Y2HQhC7WJNoN/fSsGKoCbgxcSBWLhqO8yE=,tag:1nViiB69qsoX6kyNWxZDlg==,type:str]
PGUSER=ENC[AES256_GCM,data:Txu3icEoJDI=,iv:kRB+0UuphXHQyD2rrI91acvrkIiyuY6rpZVXve2VVzo=,tag:sTkEyUNaEULY8j8ORIKAuQ==,type:str]
PGPASSWORD=ENC[AES256_GCM,data:iU8I6bmY+Fw=,iv:FFkKhmV3y8CMlcEXI3xH65eAEaHfrHSVSLFKxwxDHBE=,tag:jwJ53i8utKEW6dRDS6alpg==,type:str]
#ENC[AES256_GCM,data:td44/NdM,iv:IinYlBRhaqHH6f4Z74E3YLmo+bNHICvxmlf4GtUd7KU=,tag:XKyJhY3NZn2j2/d98pSg4A==,type:comment]
ADMIN_EMAIL=ENC[AES256_GCM,data:dDLl601wvPiv7qJpJA4lcX3oyA==,iv:7JH9gTtMh2si9zllW9jv8+ZIttN6G/MpdrPNGyXFgws=,tag:OKSJbnqs6OiVInXjYnkUKA==,type:str]
#ENC[AES256_GCM,data:iPvUezMqJ50XFKAk,iv:kK64crlHqHFKLiaIeaxYLUUrYuoYiJ0MbZzPgsgvk2I=,tag:lIwhh+KyvKZXGH/ou2DPRA==,type:comment]
API_MAILJET_REPLY_TO_EMAIL=ENC[AES256_GCM,data:rFEUjqXVctv06K7bSiNPbzfERQ==,iv:R/nhYKG75n7z671I8eXCsK0nSIZ23SJgB0Y2QiG9nJc=,tag:OodzfMsk36Qq9TVFnh1GKg==,type:str]
API_MAILJET_EMAIL=ENC[AES256_GCM,data:beS46BHcIcfeVFXzQ8x4WoankZ94rGpVDV5t,iv:7mThXDLURvNsccrq6vpvO8EHts044KcI/HvmVH2jqKo=,tag:x3iMT5tPCAjwi9XThspf2w==,type:str]
API_MAILJET_KEY=ENC[AES256_GCM,data:R10dswVdPyZR9uSB2WvU6nofVZL5QeiotNNtJSIh96U=,iv:ttS7Lh550WdJJoQTKUCnrwQDsCG5KciCIPIIeeZ4dCQ=,tag:mthQFM0Mpmh9szU1IwOX5g==,type:str]
API_MAILJET_SECRET=ENC[AES256_GCM,data:S5eyfuwqchmk/KaYPXUKBiO6kQQUYleaAXd60CE6fZk=,iv:GOeGt+teA//u12CJ8d8SS4j5cDuj3fqMEv03giqCm8Y=,tag:tvsEsBg5MoWdE/lj0f3iKA==,type:str]
API_MAILJET_SERVER=ENC[AES256_GCM,data:ImbAdFHdvdT8FrVBrEzrgtg=,iv:YhIZvkysQayurmw8kwc4MtzLvQFIW4Eg1b7MSW4nvL0=,tag:xI8Sz0RbHTOB92tlJPGagg==,type:str]
API_MAILJET_CONTACTS_LIST_ID=ENC[AES256_GCM,data:CSet5r7yuo8=,iv:LitklZZraH7HHKpzQG3SwI9GVHs5rtNDw2zOsgsRiq4=,tag:cW6N72PCPRVFSzzylMSTIQ==,type:str]
API_MAILJET_EXPLOITANTS_GUYANE_LIST_ID=ENC[AES256_GCM,data:SQih7xecTxo=,iv:fGsQT3BbgGvcvh4VKepKeT4cRpuznScnry47/NrKG70=,tag:FzU4108utxTw7zLPfBaIfA==,type:str]
#ENC[AES256_GCM,data:zMa3/6vIVKCtHd40lO5a4qdy0Q==,iv:vwaTetd4NQCewMwXYjprhYfbsZp4TcDwIQKScK4mt1s=,tag:TT7gXNeUOB5v2XeqpuK+cQ==,type:comment]
API_ADMINISTRATION_URL=ENC[AES256_GCM,data:xVZo2FCPbMD78cHOhu8f64p6Q4cOnlFzPZ4iUlF2kAwDd65AcnmD4ofLSP0=,iv:XCo/32mUUc0MVBaZF7TfGoLdIRCZMs/38q53e1gcyxo=,tag:Ffo0FjKCcODj4BXa5sOR6g==,type:str]
#ENC[AES256_GCM,data:/wV9P1nOIPKRBA==,iv:ygqkC6U4NqKQpFqwhGWRmxE00VniCNdA1aJ9trsbohs=,tag:tnEjXU6+GgHXNuBkq4/cFg==,type:comment]
API_INSEE_KEY=ENC[AES256_GCM,data:WS5baZ02ZU/bpyQ2YkgWquD8rAhmydYSxipmmQ==,iv:vh9kOBKlov2NzpK5bzEEyPDb0VralVjEgwVrmFjTsic=,tag:Fn1DWOFEQjQvZdgx5Utm2w==,type:str]
API_INSEE_SECRET=ENC[AES256_GCM,data:j8sbpzNx25yFIcSzOVbghNuNH/wC4wKNcpjTOA==,iv:Km6N284lAWppFZoBvHo97t+Y8WxA+4mlvku+zT/oOwU=,tag:XZU9vfXZYhrgFfKEviZ9vA==,type:str]
API_INSEE_URL=ENC[AES256_GCM,data:C5q29yRp3luk04KCnHbnAC/G8vsfqg==,iv:FdJyGrdACpRT6m+jjJ7MbF4RmRSZ7QONdcnGFwGgjDc=,tag:BMa9FfNaVgyjJGZvao10Xg==,type:str]
#ENC[AES256_GCM,data:rPVjfWEdGaltqFU=,iv:brvmIBHlHugODEW/gv2gCPf3TD54Nqr9DpzusH3iBhQ=,tag:MgnCgB2CTiGrjgEVX9aa0w==,type:comment]
API_MATOMO_URL=ENC[AES256_GCM,data:E0PYMVISt5Uh9YVjWW+CXJ389xnzOS0878mnYSARFufMfR6tNioy6XQJXvRojHLVq0L1TSkz/VqHxA==,iv:nsQdPfee8Mr8RQY/sYDLdKD5ZNbuu7DIyky1tk+wXY8=,tag:sS57EumrgCuk4jFcgRIgxg==,type:str]
API_MATOMO_ID=ENC[AES256_GCM,data:KHEjUQ==,iv:uDP2/XAp8SFnzngZ+IPuiFETpNCy0elzqFD0koJXwq0=,tag:sL98l8vjH3DC5Zn0EMzRuQ==,type:str]
API_SENTRY_URL=ENC[AES256_GCM,data:AX/qmOey1LhQgoZT/HtTuEJuAVWDMzmTWAyC2v0ai8Lz2zqJE5zI71VxMD4CEgksFQvVkbWrDWrO7LW3Nz4of4M=,iv:uLknqApzdYDe4lUJynYTONRfGeXVick2XyHB5ewRyCY=,tag:qv3su4VKCHJSPvWYsfFP5A==,type:str]
#ENC[AES256_GCM,data:lpwwbAt7EA==,iv:otZ1UbTLgaC7IBc0BbhQbPjPvHZbqDf1P0XhqHiTBQ8=,tag:eVeDHCtES+y6f8swGkw/+A==,type:comment]
RESTIC_REPOSITORY=ENC[AES256_GCM,data:613maV9BpmfqX1CzsxZ3KCCKKIVdJikYzHeImifeX081AtCkhCqOAZVnaZpj1Y/rIMYr835p5Afp2uOCWFBE5x8BBaWQY7AwuY00Q/G3uszV39uhEy45,iv:UmiNCq9gJYSYXM7iqYmoLDkje5mv8+u26q43WzVndVI=,tag:CNBWbzKoOJabPD8+vsxxXQ==,type:str]
RESTIC_PASSWORD=ENC[AES256_GCM,data:0JMrOZHcl1O73gjszMiNgJgivWC+SM/9bKXskXfRNX+o067sR+lK3Kbwc71tANvsNuEBUo72v1OBwT0O0v9NnoXkGgCEx/Frv0ZKSgedEnL5if1i3Ei+F+ZiKq2SgUFP8bu/uBXFWccC0p+5EoXH8++Gg5r1uNzvSMF7C5lSnxc=,iv:ThSxl1SUCZn4f7cqQnLwv9YFnM9br+dKwLRZ9S+Wf/I=,tag:nLtU8pzV4H0LHxW1VU2oxg==,type:str]
AWS_ACCESS_KEY_ID=ENC[AES256_GCM,data:VNOivS/vFrj5Z5A2Tsqp27xV6VUMFG+3jq6ODjOeuuY=,iv:akcXpNsgIwYHfadXQ91kYOf5v2X9xuyDOlnLIkrFgcY=,tag:4vNUgkLSIBQe8VH7qAp6/A==,type:str]
AWS_SECRET_ACCESS_KEY=ENC[AES256_GCM,data:CF7DrPZaAU8AydLQaT9nuqHVLYHhmnpcn8h1qP0IBug=,iv:nTSgI1Tw2djoZ3jQyfUffKofqJ0lqqEXPYGL6ruTTjk=,tag:RzNaonM872eac9GSYM76RQ==,type:str]
TCHAP_HOOK=ENC[AES256_GCM,data:VEL2aatRIwVKveanTSg6l8cRaPkTg8iHB0799yGmITopnMqkuzmEAUt/69PGAayykdjkw2DS04sW68Wv1nty7oU8DCFV7t4Mw1nm7zn/3nshKjXTi4qX/aghNSQ8ewvRiw5pIJsjQpXa7FOZTqFDrQ8QhAWmOF1n5/OSdZ8+poYIcMWvdggffWwbw7bIkla0HHuyHslWwOb0Yw==,iv:7NPlWwxeq9oIJHw8LxvyGQygf0Rdfx8IjZHrHsajX7I=,tag:yKQ53RDHVO/6ahb7bh5aJQ==,type:str]
sops_age__list_0__map_enc=-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSB1WS9NZTk3L2l2ZGpIbTFE\nL0s5R21Pd1FFZnEwYTgrUFFlNnlqbU9pNWprCjFKajFUa0t5ZW5UalZ0SFpMRFFa\nZDBKNFRIMXhkV1hqVWlRNnpqTUI3Z0EKLS0tIGtnZlpQWnlTWjZpaDBrRytKSlhO\nUENPS3pKenIvSG5PN1NaazI0c05xUkkKHdBa/RdOrUzmRNLCz18T3HukuEvlWRUU\n5Vb7mm5LEqEy694R7c+u0rM0y5fVyXTf9QEtrRLnBJNqE+LJxVhatg==\n-----END AGE ENCRYPTED FILE-----\n
sops_age__list_0__map_recipient=age1m0v4x0c32qjqs6rl3y6h2vee3sdm5y6rvzwyccl306n48d8lzvhse52hp4
sops_age__list_1__map_enc=-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBhT0MzUkhOWldCNmZuUnpi\nNVp6U1VOREEyclkzUlNmSXRnc3NOZWQ4NEZZCmdLTThVNm55aGswYUo1UkNoVERQ\nR0FVaHk0VElSOFd5UnFxeFA4ZFBPVFUKLS0tIC9ETUQxUjFhTHUzMWxIY2JGcUg3\nTVJjaGlBd0FPN0dlSXhhNzJzRit0RGMKY6jgyXgRioXPFhe9lSZhipBtNl9p3ssm\niN2GL1YJkwTP51GjaRS3SkbkzV498SC+EwRSE6rufNj4ykzFejLaTQ==\n-----END AGE ENCRYPTED FILE-----\n
sops_age__list_1__map_recipient=age1z4cm6tk86r05u84w8rxf4c04ndnuc7wj03psqugfwy03uwqutv0s88wz6f
sops_lastmodified=2024-10-17T15:39:24Z
sops_mac=ENC[AES256_GCM,data:A4Jy/QlZhG1kQ55R2sh0WHT2zTsxD7WVZ8m8ceyd13dH0KNi4H1gxtQSZwAN1zo/vwFWKYWPzbgOOwcTFrqrG9dDTVNCmMefQSnbn/r/D5uA8DEab98kLi7TOvs1S+GeU7++ec2bBpLIclK1cUh/GGSPdViG/svlifvzAgPBMLk=,iv:eZZXxEfv9//2CCvDoU0x7ZoZRJCi97visHgjGzVzKDc=,tag:8y6bFDn/OPSKVK14m5Leeg==,type:str]
sops_unencrypted_suffix=_unencrypted
sops_version=3.9.1
......@@ -12,3 +12,5 @@ packages/ui/storybook-static/
.vscode
**/coverage
.cargo
team.age
*.no-commit.env
......@@ -2,27 +2,49 @@ default:
tags: [global, shared]
interruptible: true
stages:
- prepare
- test
- build
- deploy
include:
- project: 'share/devops/squelettes/gitlab/eco'
file: 'deploy_eco_compose.yaml'
ref: 'main'
build-ci-image:
stage: prepare
image:
name: gcr.io/kaniko-project/executor:debug
entrypoint: [""]
script: .gitlab/build-ci-image.sh
get_camino_tag:
stage: deploy
# FIXME
# script: echo "CAMINO_TAG=${CI_COMMIT_SHA}" > out.env
script: echo "CAMINO_TAG=267ad27021581c7c23b1d7c1dff0e61cbc18649e" > out.env
artifacts:
reports:
dotenv: out.env
retry:
max: 2
deploy_app_via_compose:
tags: [dnum-paas-eco]
needs: [get_camino_tag]
extends: .deploy_eco_compose
stage: deploy
script:
- paas-docker-down-and-up --compose-path docker-compose.yml --dotenv-path .dev.env --vars CAMINO_TAG
include:
- local: .gitlab/global.yml
- local: .gitlab/deploy.yml
- local: .gitlab/ci/*.yml
rules:
- if: $CI_COMMIT_BRANCH && $CI_COMMIT_BRANCH != "prod" && $CI_COMMIT_BRANCH != "preprod"
stages:
# - prepare
# - test
# - build
- deploy
# build-ci-image:
# stage: prepare
# image:
# name: gcr.io/kaniko-project/executor:debug
# entrypoint: [""]
# script: .gitlab/build-ci-image.sh
# artifacts:
# reports:
# dotenv: out.env
# retry:
# max: 2
# include:
# - local: .gitlab/global.yml
# - local: .gitlab/deploy.yml
# - local: .gitlab/ci/*.yml
# rules:
# - if: $CI_COMMIT_BRANCH && $CI_COMMIT_BRANCH != "prod" && $CI_COMMIT_BRANCH != "preprod"
FROM mcuadros/ofelia:0.3.13
RUN apk add -U restic postgresql16-client postgresql16-contrib docker-cli bash
COPY restore-last-backup /
COPY config.ini /etc/ofelia/config.ini
FROM quay.io/keycloak/keycloak:25.0.5
# Utiliser le makefile, mettre à jour la version à la main
COPY keycloak-franceconnect-6.2.0.jar /opt/keycloak/providers/keycloak-franceconnect-6.2.0.jar
COPY keycloak-bcrypt-1.6.0.jar /opt/keycloak/providers/keycloak-bcrypt-1.6.0.jar
COPY keycloak_theme/ /opt/keycloak/themes/camino/
FROM nginxproxy/nginx-proxy:1.6.1
# Utiliser le makefile, mettre à jour la version à la main
COPY proxy.conf /etc/nginx/proxy.conf
......@@ -21,6 +21,7 @@ docs/generate-schema:
daily:
ifdef CAMINO_STAGE
npm run daily -w packages/api
@curl -i -X POST -H 'Content-Type: application/json' -d "{\"message\": \":tada: daily fini sur ${ENV} :tada:\"}" ${TCHAP_HOOK}
else
@echo 'lancement du daily en mode local avec la migration'
npm run db:migrate -w packages/api
......@@ -240,3 +241,29 @@ graphql/check:
echo $$f; \
graphql-inspector validate --noStrictFragments "$$f" packages/api/src/api/graphql/schemas/index.graphql || exit 1; \
done
dev/chiffre:
SOPS_AGE_RECIPIENTS=$$(cat team.age.pub ecocompose.age.pub | sed -z 's/\n/,/g;s/,$$/\n/') sops --encrypt --input-type dotenv --output-type dotenv .dev.no-commit.env > .dev.env
dev/dechiffre:
SOPS_AGE_KEY_FILE=team.age sops -d --input-type dotenv --output-type dotenv .dev.env
# TOTO 2024-10-21 une fois tout migré sur ecoCompose, il faudra supprimer tout ce qu'il y a dans infra sauf le dossier ecocompose
keycloak/build:
docker build -t caminofr/camino-keycloak:25.0.5 -f Dockerfile.keycloak infra/ecocompose/keycloak/
keycloak/push:
docker push caminofr/camino-keycloak:25.0.5
nginx-proxy/build:
docker build -t caminofr/camino-nginx-proxy:1.6.1 -f Dockerfile.nginx-proxy infra/ecocompose/nginx-proxy/
nginx-proxy/push:
docker push caminofr/camino-nginx-proxy:1.6.1
cron/build:
docker build -t caminofr/cron:1.0.0 -f Dockerfile.cron infra/ecocompose/crons/
cron/push:
docker push caminofr/cron:1.0.0
......@@ -11,13 +11,11 @@ services:
APPLICATION_VERSION: ${CAMINO_TAG}
VIRTUAL_HOST: ${API_HOST}
VIRTUAL_PORT: ${API_PORT}
LETSENCRYPT_HOST: ${API_HOST}
LETSENCRYPT_EMAIL: ${LETSENCRYPT_EMAIL}
PGHOST: db
expose:
- ${API_PORT}
volumes:
- ./files:/project/packages/api/files
- $EDCS_DATA_STACK/files:/project/packages/api/files
- ./.env:/project/.env
networks:
- default
......@@ -31,13 +29,16 @@ services:
POSTGRES_USER: ${PGUSER}
POSTGRES_PASSWORD: ${PGPASSWORD}
POSTGRES_DB: ${PGDATABASE}
# from https://github.com/docker-library/docs/blob/master/postgres/README.md
# On autorise tout, on part du principe que la vm est sécurisée et que les conteneurs qui ont accès à cette VM ne peuvent être que les notres
POSTGRES_HOST_AUTH_METHOD: trust
expose:
- ${PGPORT}
networks:
- default
volumes:
- ./postgresql:/var/lib/postgresql/data
- /srv/backups/dump/:/dump/
- $EDCS_DATA_STACK/postgresql:/var/lib/postgresql/data
- $EDCS_DATA_STACK/backups/dump/:/dump/
restart: unless-stopped
docs:
container_name: camino_docs
......@@ -45,8 +46,6 @@ services:
environment:
VIRTUAL_HOST: ${DOC_HOST}
VIRTUAL_PORT: ${DOC_PORT}
LETSENCRYPT_HOST: ${DOC_HOST}
LETSENCRYPT_EMAIL: ${LETSENCRYPT_EMAIL}
expose:
- ${DOC_PORT}
networks:
......@@ -68,6 +67,23 @@ services:
- default
- nginx-proxy
restart: unless-stopped
cron:
container_name: camino_cron
image: caminofr/cron:1.0.0
environment:
ENV: ${ENV}
TCHAP_HOOK: ${TCHAP_HOOK}
DOCKER_HOST: unix://tmp/docker.sock
RESTIC_REPOSITORY: ${RESTIC_REPOSITORY}
RESTIC_PASSWORD: ${RESTIC_PASSWORD}
AWS_ACCESS_KEY_ID: ${AWS_ACCESS_KEY_ID}
AWS_SECRET_ACCESS_KEY: ${AWS_SECRET_ACCESS_KEY}
networks:
- default
restart: unless-stopped
volumes:
- $EDCS_DATA_STACK/backups/:/srv/backups/
- /var/run/docker.sock:/tmp/docker.sock:ro
oauth2:
container_name: camino_oauth2
image: quay.io/oauth2-proxy/oauth2-proxy:v7.6.0
......@@ -77,8 +93,6 @@ services:
environment:
VIRTUAL_HOST: ${OAUTH_HOST}
VIRTUAL_PORT: ${OAUTH_PORT}
LETSENCRYPT_HOST: ${OAUTH_HOST}
LETSENCRYPT_EMAIL: ${LETSENCRYPT_EMAIL}
OAUTH2_PROXY_PROVIDER: 'keycloak-oidc'
OAUTH2_PROXY_CLIENT_ID: ${KEYCLOAK_CLIENT_ID}
OAUTH2_PROXY_CLIENT_SECRET: ${KEYCLOAK_CLIENT_SECRET}
......@@ -86,11 +100,13 @@ services:
OAUTH2_PROXY_OIDC_ISSUER_URL: https://${KEYCLOAK_HOST}/realms/Camino
OAUTH2_PROXY_REDIRECT_URL: https://${OAUTH_HOST}
OAUTH2_PROXY_HTTP_ADDRESS: 0.0.0.0:${OAUTH_PORT}
OAUTH2_PROXY_UPSTREAMS: http://ui:${UI_PORT}
OAUTH2_PROXY_UPSTREAMS: http://camino_ui_app:${UI_PORT}
OAUTH2_PROXY_EMAIL_DOMAINS: "*"
OAUTH2_PROXY_SKIP_PROVIDER_BUTTON: true
OAUTH2_PROXY_PASS_ACCESS_TOKEN: true
OAUTH2_PROXY_SKIP_AUTH_ROUTES: "/*"
NO_PROXY: ${EDCS_PROXY_NO},camino_ui_app
no_proxy: ${EDCS_PROXY_NO},camino_ui_app
# nécessaire pour garder le basic auth
OAUTH2_PROXY_PASS_BASIC_AUTH: true
OAUTH2_PROXY_SKIP_AUTH_STRIP_HEADERS: false
......@@ -108,7 +124,7 @@ services:
- nginx-proxy
keycloak:
container_name: camino_keycloak
image: quay.io/keycloak/keycloak:25.0.5
image: caminofr/camino-keycloak:25.0.5
depends_on:
- db
environment:
......@@ -121,14 +137,6 @@ services:
KC_PROXY: "edge"
VIRTUAL_HOST: ${KEYCLOAK_HOST}
VIRTUAL_PORT: ${KEYCLOAK_PORT}
LETSENCRYPT_HOST: ${KEYCLOAK_HOST}
LETSENCRYPT_EMAIL: ${LETSENCRYPT_EMAIL}
volumes:
# A Synchroniser avec ansible infra/roles/camino/tasks
- ./keycloak-franceconnect-6.2.0.jar:/opt/keycloak/providers/keycloak-franceconnect-6.2.0.jar
# FROM https://github.com/leroyguillaume/keycloak-bcrypt
- ./keycloak-bcrypt-1.6.0.jar:/opt/keycloak/providers/keycloak-bcrypt-1.6.0.jar
- ./keycloak_theme/:/opt/keycloak/themes/camino/
command: "start"
expose:
- ${KEYCLOAK_PORT}
......@@ -136,7 +144,19 @@ services:
networks:
- default
- nginx-proxy
nginx-proxy:
image: caminofr/camino-nginx-proxy:1.6.1
container_name: nginx-proxy
restart: unless-stopped
logging:
options:
max-size: "10m"
max-file: "3"
ports:
- "80:80"
volumes:
- $EDCS_DATA_STACK/nginx_vhost:/etc/nginx/vhost.d
- $EDCS_DATA_STACK/nginx_html:/usr/share/nginx/html
- /var/run/docker.sock:/tmp/docker.sock:ro
networks:
nginx-proxy:
external: true
age1z4cm6tk86r05u84w8rxf4c04ndnuc7wj03psqugfwy03uwqutv0s88wz6f
#!/bin/bash
set -eufo pipefail
source /srv/scripts/restic_data
if [ "$(id -u)" != "{{camino_user_uid}}" ]; then
echo "This script must be run as user 'camino'" 1>&2
exit 1
fi
# backup
USER_GROUP_ID=$(getent group users | cut -d: -f3)
docker exec camino_api_db pg_dump --clean --if-exists --no-owner --no-privileges -B --dbname=camino --format c > /srv/backups/dump_without_files.backup
docker exec camino_api_db /bin/bash -c 'rm -rf /dump/*'
docker exec camino_api_db vacuumlo camino
docker exec camino_api_db pg_dump --clean --if-exists --format=d --no-owner --no-privileges --dbname=camino -f /dump
docker exec camino_api_db chown -R "{{camino_user_uid}}:${USER_GROUP_ID}" /dump
chown camino:users -R /srv/backups/
restic backup /srv/backups/
[job-exec "daily"]
schedule = 0 0 4 * * *
container = camino_api_app
command = make daily
tty = true
[job-exec "monthly"]
schedule = 0 0 6 1 * *
container = camino_api_app
command = make monthly
tty = true
[job-exec "cleanup_downloads"]
schedule = 0 0 5 * * *
container = camino_api_app
command = rm -rf /project/packages/api/files/downloads/*
tty = true
[job-exec "cleanup_temp_files"]
schedule = 0 30 5 * * *
container = camino_api_app
command = find /project/packages/api/files/tmp/ -mtime +7 -type f -delete
tty = true
[job-local "restore_backup"]
schedule = 0 0 6 * * 0
command = /restore-last-backup
#!/bin/bash
set -eufo pipefail
if [ "${ENV}" = "prod" ]; then
echo "This script must not run in production" 1>&2
exit 1
fi
echo 'Mise en place des fichiers de prod'
restic restore latest --no-lock -t /
echo "Arrêt de l'api et de keycloak"
docker stop camino_api_app camino_keycloak
echo "Insertion du dump de la BDD"
docker exec -i camino_api_db dropdb --username=postgres camino
docker exec -i camino_api_db createdb --username=postgres camino
docker exec -i camino_api_db pg_restore --clean --if-exists --no-owner --no-privileges --dbname=camino /dump
echo "Redémarrage de l'api et de keycloak"
docker restart camino_api_app camino_keycloak camino_ui_app
curl -i -X POST -H 'Content-Type: application/json' -d "{\"message\": \":tada: Dernier backup appliqué sur ${ENV} $(restic snapshots --no-lock | tail -3 | head -1 | cut -d' ' -f3) :tada:\"}" ${TCHAP_HOOK}
File added
File added
<#import "template.ftl" as layout>
<@layout.registrationLayout displayInfo=true displayMessage=!messagesPerField.existsError('username'); section>
<#if section = "form">
<main class="fr-pt-md-14v" role="main" id="content">
<div class="fr-container fr-container--fluid fr-mb-md-14v">
<div class="fr-grid-row fr-grid-row-gutters fr-grid-row--center">
<div class="fr-col-12 fr-col-md-8 fr-col-lg-6">
<div class="fr-container">
<h1>Récupération de mot de passe sur Camino</h1>
</div>
<div class="fr-container fr-background-alt--grey fr-px-md-0 fr-py-10v fr-py-md-14v">
<div class="fr-grid-row fr-grid-row-gutters fr-grid-row--center">
<div class="fr-col-12 fr-col-md-9 fr-col-lg-8">
<div>
<form id="login-1760" onsubmit="login.disabled = true; return true;" action="${url.loginAction}" method="post">
<fieldset class="fr-fieldset" id="login-1760-fieldset" aria-labelledby="login-1760-fieldset-legend">
<legend class="fr-fieldset__legend" id="login-1760-fieldset-legend">
<h2>Récupérer le mot de passe de votre compte</h2>
</legend>
<div class="fr-fieldset__element">
<p class="fr-text--sm">Description — Veuillez saisir l’adresse électronique associée à votre compte. Nous vous enverrons plus d’informations pour réinitialiser votre mot de passe.</p>
</div>
<div class="fr-fieldset__element">
<#if messagesPerField.existsError('username')>
<div class="fr-alert fr-alert--error fr-mb-3w">
<h3 class="fr-alert__title">${kcSanitize(messagesPerField.getFirstError('username'))?no_esc}</h3>
</div>
</#if>
<fieldset class="fr-fieldset" id="credentials">
<div class="fr-fieldset__element">
<div class="fr-input-group">
<label class="fr-label" for="username-1757">
${msg("email")}
<span class="fr-hint-text">Format attendu : nom@domaine.fr</span>
</label>
<input tabindex="1" autofocus class="fr-input" autocomplete="username" aria-required="true" name="username" id="username-1757" type="text" value="${(login.username!'')}" aria-invalid="<#if messagesPerField.existsError('username')>true</#if>">
</div>
</div>
</fieldset>
</div>
<div class="fr-fieldset__element">
<ul class="fr-btns-group">
<li>
<button tabindex="2" class="fr-mt-2v fr-btn" name="login" type="submit">
Valider
</button>
</li>
</ul>
</div>
<div class="fr-fieldset__element">
<a class='fr-link fr-link--icon-left fr-icon-arrow-left-line' href="${url.loginUrl}">${kcSanitize(msg("backToLogin"))?no_esc}</a>
</div>
</fieldset>
</form>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</main>
</#if>
</@layout.registrationLayout>
<#import "template.ftl" as layout>
<#import "password-commons.ftl" as passwordCommons>
<@layout.registrationLayout displayMessage=!messagesPerField.existsError('password','password-confirm'); section>
<#if section = "form">
<main class="fr-pt-md-14v" role="main" id="content">
<div class="fr-container fr-container--fluid fr-mb-md-14v">
<div class="fr-grid-row fr-grid-row-gutters fr-grid-row--center">
<div class="fr-col-12 fr-col-md-8 fr-col-lg-6">
<div class="fr-container">
<h1>Mise à jour du mot de passe</h1>
</div>
<div class="fr-container fr-background-alt--grey fr-px-md-0 fr-py-10v fr-py-md-14v">
<div class="fr-grid-row fr-grid-row-gutters fr-grid-row--center">
<div class="fr-col-12 fr-col-md-9 fr-col-lg-8">
<div>
<form id="login-1760" action="${url.loginAction}" method="post">
<input type="text" id="username" name="username" value="${username}" autocomplete="username" readonly="readonly" style="display:none;"/>
<input type="password" id="password" name="password" autocomplete="current-password" style="display:none;"/>
<fieldset class="fr-fieldset" id="login-1760-fieldset" aria-labelledby="login-1760-fieldset-legend">
<legend class="fr-fieldset__legend" id="login-1760-fieldset-legend">
<h2>Changer votre mot de passe</h2>
</legend>
<div class="fr-fieldset__element">
<#if messagesPerField.existsError('password', 'password-confirm')>
<div class="fr-alert fr-alert--error fr-mb-3w">
<h3 class="fr-alert__title">${kcSanitize(messagesPerField.getFirstError('password', 'password-confirm'))?no_esc}</h3>
</div>
</#if>
<fieldset class="fr-fieldset" id="credentials">
<div class="fr-fieldset__element">
<div class="fr-input-group">
<label class="fr-label" for="password-new-1757">
${msg("passwordNew")}
</label>
<input tabindex="1" class="fr-input" id="password-new-1757" type="password" name="password-new"
autofocus autocomplete="new-password"
aria-invalid="<#if messagesPerField.existsError('password','password-confirm')>true</#if>"
>
</div>
</div>
</fieldset>
<fieldset class="fr-fieldset" id="credentials">
<div class="fr-fieldset__element">
<div class="fr-input-group">
<label class="fr-label" for="password-confirm-1201">
${msg("passwordConfirm")}
</label>
<input tabindex="2" class="fr-input" id="password-confirm-1201" type="password" name="password-confirm"
autocomplete="new-password"
aria-invalid="<#if messagesPerField.existsError('password-confirm')>true</#if>"
>
</div>
</div>
</fieldset>
</div>
<div class="fr-fieldset__element">
<ul class="fr-btns-group">
<li>
<button tabindex="3" class="fr-mt-2v fr-btn" name="login" type="submit">
Valider
</button>
</li>
<#if isAppInitiatedAction??>
<li>
<button type="submit" tabindex="4" class="fr-mt-2v fr-btn fr-btn--secondary" name="cancel-aia">
${msg("doCancel")}
</button>
</li>
</#if>
</ul>
</div>
</fieldset>
</form>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</main>
</#if>
</@layout.registrationLayout>
<#import "template.ftl" as layout>
<@layout.registrationLayout displayInfo=true; section>
<#if section = "form">
<div class="fr-alert fr-alert--info fr-mt-3w">
<h3 class="fr-alert__title">${msg("emailVerifyInstruction1",user.email)}</h3>
</div>
</#if>
</@layout.registrationLayout>
\ No newline at end of file
<#import "template.ftl" as layout>
<@layout.registrationLayout displayMessage=!messagesPerField.existsError('username','password') displayInfo=realm.password && realm.registrationAllowed && !registrationDisabled??; section>
<#if section = "form">
<main class="fr-pt-md-14v" role="main" id="content">
<div class="fr-container fr-container--fluid fr-mb-md-14v">
<div class="fr-grid-row fr-grid-row-gutters fr-grid-row--center">
<div class="fr-col-12 fr-col-md-8 fr-col-lg-6">
<div class="fr-container">
<h1>Connexion à Camino</h1>
</div>
<div class="fr-container fr-background-alt--grey fr-px-md-0 fr-py-10v fr-py-md-14v">
<div class="fr-grid-row fr-grid-row-gutters fr-grid-row--center">
<div class="fr-col-12 fr-col-md-9 fr-col-lg-8">
<div>
<form id="login-1760" onsubmit="login.disabled = true; return true;" action="${url.loginAction}" method="post">
<fieldset class="fr-fieldset" id="login-1760-fieldset" aria-labelledby="login-1760-fieldset-legend">
<legend class="fr-fieldset__legend" id="login-1760-fieldset-legend">
<h2>Se connecter avec son compte</h2>
</legend>
<div class="fr-fieldset__element">
<#if messagesPerField.existsError('username','password')>
<div class="fr-alert fr-alert--error fr-mb-3w">
<h3 class="fr-alert__title">${kcSanitize(messagesPerField.getFirstError('username','password'))?no_esc}</h3>
</div>
</#if>
<fieldset class="fr-fieldset" id="credentials">
<div class="fr-fieldset__element">
<div class="fr-input-group">
<label class="fr-label" for="username-1757">
${msg("email")}
<span class="fr-hint-text">Format attendu : nom@domaine.fr</span>
</label>
<input tabindex="1" autofocus class="fr-input" autocomplete="username" aria-required="true" name="username" id="username-1757" type="text" value="${(login.username!'')}" aria-invalid="<#if messagesPerField.existsError('username','password')>true</#if>">
</div>
</div>
<div class="fr-fieldset__element">
<div class="fr-password" id="password-1758">
<label class="fr-label" for="password-1758-input">
Mot de passe
</label>
<div class="fr-input-wrap">
<input tabindex="2" class="fr-password__input fr-input" aria-required="true" name="password" autocomplete="current-password" id="password-1758-input" type="password" aria-invalid="<#if messagesPerField.existsError('username','password')>true</#if>">
</div>
<p>
<a tabindex="4" href="${url.loginResetCredentialsUrl}" class="fr-link">${msg("doForgotPassword")}</a>
</p>
</div>
</div>
</fieldset>
</div>
<div class="fr-fieldset__element">
<ul class="fr-btns-group">
<li>
<button tabindex="3" class="fr-mt-2v fr-btn" name="login" type="submit">
Se connecter
</button>
</li>
</ul>
</div>
</fieldset>
</form>
</div>
<#if social.providers??>
<div class="${properties.kcFormSocialAccountSectionClass!} fr-mb-3w">
<p class="fr-hr-or">ou</p>
<h3>Se connecter avec Cerbère</h3>
<#list social.providers as p>
<a title="Se connecter avec Cerbère - Lien externe" id="social-${p.alias}" class="fr-link fr-link--lg fr-link--icon-right fr-icon-external-link-line fr-grid-row--right" rel="noopener"
href="${p.loginUrl}">${p.displayName!}</a>
</#list>
</div>
</#if>
<hr>
<h2>Vous n’avez pas de compte ?</h2>
<ul class="fr-btns-group">
<li>
<a tabindex="6" class="fr-btn fr-btn--secondary"
href="${url.registrationUrl}">${msg("doRegister")}</a>
</li>
</ul>
</div>
</div>
</div>
</div>
</div>
</div>
</main>
</#if>
</@layout.registrationLayout>
<#import "template.ftl" as layout>
<#import "register-commons.ftl" as registerCommons>
<@layout.registrationLayout displayMessage=!messagesPerField.existsError('firstName','lastName','email','password','password-confirm'); section>
<#if section = "form">
<#if messagesPerField.existsError('email')>
<div class="fr-alert fr-alert--info fr-mt-3w">
<h3 class="fr-alert__title">${msg("emailVerifyInstruction1",(register.formData.email!''))}</h3>
<p>Si vous pensez avoir déjà créé votre compte sur Camino, utilisez la fonctionnalité "Mot de passe oublié"</p>
</div>
<#else>
<main class="fr-pt-md-14v" role="main" id="content">
<div class="fr-container fr-container--fluid fr-mb-md-14v">
<div class="fr-grid-row fr-grid-row-gutters fr-grid-row--center">
<div class="fr-col-12 fr-col-md-8 fr-col-lg-6">
<div class="fr-container">
<h1>Création de compte sur Camino</h1>
</div>
<div class="fr-container fr-background-alt--grey fr-px-md-0 fr-py-10v fr-py-md-14v">
<div class="fr-grid-row fr-grid-row-gutters fr-grid-row--center">
<div class="fr-col-12 fr-col-md-9 fr-col-lg-8">
<div>
<form action="${url.registrationAction}" method="post">
<fieldset class="fr-fieldset" aria-labelledby="register-1760-fieldset-legend">
<legend class="fr-fieldset__legend" id="register-1760-fieldset-legend">
<h2>Coordonnées personnelles</h2>
</legend>
<div class="fr-fieldset__element">
<fieldset class="fr-fieldset" id="credentials">
<div class="fr-fieldset__element">
<div class="fr-input-group <#if messagesPerField.existsError('firstName')>fr-input-group--error</#if>" aria-describedby="<#if messagesPerField.existsError('firstName')>text-input-firstName-error-desc-error</#if>">
<label class="fr-label" for="firstName">
${msg("firstName")}
</label>
<input tabindex="1"
class="fr-input" autocomplete="firstName" aria-required="true"
type="text" id="firstName" name="firstName"
value="${(register.formData.firstName!'')}"
aria-invalid="<#if messagesPerField.existsError('firstName')>true</#if>">
<#if messagesPerField.existsError('firstName')>
<p id="text-input-firstName-error-desc-error" class="fr-error-text">
${kcSanitize(messagesPerField.getFirstError('firstName'))?no_esc}
</p>
</#if>
</div>
</div>
<div class="fr-fieldset__element">
<div class="fr-input-group <#if messagesPerField.existsError('lastName')>fr-input-group--error</#if>" aria-describedby="<#if messagesPerField.existsError('lastName')>text-input-lastName-error-desc-error</#if>">
<label class="fr-label" for="lastName">
${msg("lastName")}
</label>
<input tabindex="2"
class="fr-input" autocomplete="lastName" aria-required="true"
type="text" id="lastName" name="lastName"
value="${(register.formData.lastName!'')}"
aria-invalid="<#if messagesPerField.existsError('lastName')>true</#if>">
<#if messagesPerField.existsError('lastName')>
<p id="text-input-lastName-error-desc-error" class="fr-error-text">
${kcSanitize(messagesPerField.getFirstError('lastName'))?no_esc}
</p>
</#if>
</div>
</div>
<div class="fr-fieldset__element">
<div class="fr-input-group <#if messagesPerField.existsError('email')>fr-input-group--error</#if>" aria-describedby="<#if messagesPerField.existsError('email')>text-input-email-error-desc-error</#if>">
<label class="fr-label" for="email">
${msg("email")}
</label>
<input tabindex="3"
class="fr-input" autocomplete="email" aria-required="true"
type="text" id="email" name="email"
value="${(register.formData.email!'')}"
aria-invalid="<#if messagesPerField.existsError('email')>true</#if>">
<#if messagesPerField.existsError('email')>
<p id="text-input-email-error-desc-error" class="fr-error-text">
${kcSanitize(messagesPerField.getFirstError('email'))?no_esc}
</p>
</#if>
</div>
</div>
<div class="fr-fieldset__element">
<div class="fr-input-group <#if messagesPerField.existsError('password')>fr-input-group--error</#if>" aria-describedby="<#if messagesPerField.existsError('password')>text-input-password-error-desc-error</#if>">
<label class="fr-label" for="password">
${msg("password")}
</label>
<input tabindex="4"
class="fr-input" autocomplete="off" aria-required="true"
type="password" id="password" name="password"
aria-invalid="<#if messagesPerField.existsError('password')>true</#if>">
<#if messagesPerField.existsError('password')>
<p id="text-input-password-error-desc-error" class="fr-error-text">
${kcSanitize(messagesPerField.getFirstError('password'))?no_esc}
</p>
</#if>
</div>
</div>
<div class="fr-fieldset__element">
<div class="fr-input-group <#if messagesPerField.existsError('password-confirm')>fr-input-group--error</#if>" aria-describedby="<#if messagesPerField.existsError('password-confirm')>text-input-password-confirm-error-desc-error</#if>">
<label class="fr-label" for="password-confirm">
${msg("passwordConfirm")}
</label>
<input tabindex="5"
class="fr-input" autocomplete="off" aria-required="true"
type="password" id="password-confirm" name="password-confirm"
aria-invalid="<#if messagesPerField.existsError('password-confirm')>true</#if>">
<#if messagesPerField.existsError('password-confirm')>
<p id="text-input-password-confirm-error-desc-error" class="fr-error-text">
${kcSanitize(messagesPerField.getFirstError('password-confirm'))?no_esc}
</p>
</#if>
</div>
</div>
</fieldset>
</div>
<div class="fr-fieldset__element">
<ul class="fr-btns-group">
<li>
<button tabindex="3" class="fr-mt-2v fr-btn" name="login" type="submit">
Créer mon compte
</button>
</li>
</ul>
</div>
<div class="fr-fieldset__element">
<a class='fr-link fr-link--icon-left fr-icon-arrow-left-line' href="${url.loginUrl}">${kcSanitize(msg("backToLogin"))?no_esc}</a>
</div>
</fieldset>
</form>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</main>
</#if>
</#if>
</@layout.registrationLayout>