init
This commit is contained in:
84
.editorconfig
Normal file
84
.editorconfig
Normal file
@@ -0,0 +1,84 @@
|
|||||||
|
# EditorConfig helps developers define and maintain consistent
|
||||||
|
# coding styles between different editors and IDEs
|
||||||
|
# editorconfig.org
|
||||||
|
|
||||||
|
root = true
|
||||||
|
|
||||||
|
[*]
|
||||||
|
# Change these settings to your own preference
|
||||||
|
indent_style = space
|
||||||
|
indent_size = 4
|
||||||
|
|
||||||
|
# We recommend you to keep these unchanged
|
||||||
|
end_of_line = lf
|
||||||
|
charset = utf-8
|
||||||
|
trim_trailing_whitespace = true
|
||||||
|
insert_final_newline = true
|
||||||
|
|
||||||
|
[*.feature]
|
||||||
|
indent_style = space
|
||||||
|
indent_size = 2
|
||||||
|
|
||||||
|
[*.js]
|
||||||
|
indent_style = space
|
||||||
|
indent_size = 2
|
||||||
|
|
||||||
|
[*.json]
|
||||||
|
indent_style = space
|
||||||
|
indent_size = 2
|
||||||
|
|
||||||
|
[*.md]
|
||||||
|
trim_trailing_whitespace = false
|
||||||
|
|
||||||
|
[*.php]
|
||||||
|
indent_style = space
|
||||||
|
indent_size = 4
|
||||||
|
|
||||||
|
[*.sh]
|
||||||
|
indent_style = tab
|
||||||
|
indent_size = 4
|
||||||
|
|
||||||
|
[*.vcl]
|
||||||
|
indent_style = space
|
||||||
|
indent_size = 2
|
||||||
|
|
||||||
|
[*.xml]
|
||||||
|
indent_style = space
|
||||||
|
indent_size = 4
|
||||||
|
|
||||||
|
[*.{yaml,yml}]
|
||||||
|
indent_style = space
|
||||||
|
indent_size = 4
|
||||||
|
trim_trailing_whitespace = false
|
||||||
|
|
||||||
|
[.gitmodules]
|
||||||
|
indent_style = tab
|
||||||
|
indent_size = 4
|
||||||
|
|
||||||
|
[.php_cs{,.dist}]
|
||||||
|
indent_style = space
|
||||||
|
indent_size = 4
|
||||||
|
|
||||||
|
[.travis.yml]
|
||||||
|
indent_style = space
|
||||||
|
indent_size = 2
|
||||||
|
|
||||||
|
[composer.json]
|
||||||
|
indent_style = space
|
||||||
|
indent_size = 4
|
||||||
|
|
||||||
|
[docker-compose{,.override}.{yaml,yml}]
|
||||||
|
indent_style = space
|
||||||
|
indent_size = 2
|
||||||
|
|
||||||
|
[Dockerfile]
|
||||||
|
indent_style = tab
|
||||||
|
indent_size = 4
|
||||||
|
|
||||||
|
[package.json]
|
||||||
|
indent_style = space
|
||||||
|
indent_size = 2
|
||||||
|
|
||||||
|
[phpunit.xml{,.dist}]
|
||||||
|
indent_style = space
|
||||||
|
indent_size = 4
|
||||||
22
.gitattributes
vendored
Normal file
22
.gitattributes
vendored
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
* text=auto eol=lf
|
||||||
|
|
||||||
|
*.conf text eol=lf
|
||||||
|
*.html text eol=lf
|
||||||
|
*.ini text eol=lf
|
||||||
|
*.js text eol=lf
|
||||||
|
*.json text eol=lf
|
||||||
|
*.md text eol=lf
|
||||||
|
*.php text eol=lf
|
||||||
|
*.sh text eol=lf
|
||||||
|
*.yaml text eol=lf
|
||||||
|
*.yml text eol=lf
|
||||||
|
bin/console text eol=lf
|
||||||
|
|
||||||
|
*.ico binary
|
||||||
|
*.png binary
|
||||||
|
|
||||||
|
.github export-ignore
|
||||||
|
.travis.yml export-ignore
|
||||||
|
LICENSE export-ignore
|
||||||
|
README.md export-ignore
|
||||||
|
update-deps.sh export-ignore
|
||||||
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
/docker-compose.override.yaml
|
||||||
|
/docker-compose.override.yml
|
||||||
14
admin/.dockerignore
Normal file
14
admin/.dockerignore
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
**/*.log
|
||||||
|
**/*.md
|
||||||
|
**/._*
|
||||||
|
**/.dockerignore
|
||||||
|
**/.DS_Store
|
||||||
|
**/.git/
|
||||||
|
**/.gitattributes
|
||||||
|
**/.gitignore
|
||||||
|
**/.gitmodules
|
||||||
|
**/Dockerfile*
|
||||||
|
**/Thumbs.db
|
||||||
|
.env*
|
||||||
|
build/
|
||||||
|
node_modules/
|
||||||
1
admin/.env
Normal file
1
admin/.env
Normal file
@@ -0,0 +1 @@
|
|||||||
|
REACT_APP_API_ENTRYPOINT=https://localhost:8443
|
||||||
20
admin/.gitignore
vendored
Normal file
20
admin/.gitignore
vendored
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
# See https://help.github.com/ignore-files/ for more about ignoring files.
|
||||||
|
|
||||||
|
# dependencies
|
||||||
|
/node_modules
|
||||||
|
|
||||||
|
# testing
|
||||||
|
/coverage
|
||||||
|
|
||||||
|
# production
|
||||||
|
/build
|
||||||
|
|
||||||
|
# misc
|
||||||
|
.env.local
|
||||||
|
.env.development.local
|
||||||
|
.env.test.local
|
||||||
|
.env.production.local
|
||||||
|
|
||||||
|
npm-debug.log*
|
||||||
|
yarn-debug.log*
|
||||||
|
yarn-error.log*
|
||||||
19
admin/Dockerfile
Normal file
19
admin/Dockerfile
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
FROM node:11.5-alpine
|
||||||
|
|
||||||
|
RUN mkdir -p /usr/src/admin
|
||||||
|
|
||||||
|
WORKDIR /usr/src/admin
|
||||||
|
|
||||||
|
# Prevent the reinstallation of node modules at every changes in the source code
|
||||||
|
COPY package.json yarn.lock ./
|
||||||
|
|
||||||
|
RUN apk add --no-cache --virtual .gyp \
|
||||||
|
python \
|
||||||
|
make \
|
||||||
|
g++ \
|
||||||
|
&& yarn install \
|
||||||
|
&& apk del .gyp
|
||||||
|
|
||||||
|
COPY . ./
|
||||||
|
|
||||||
|
CMD yarn start
|
||||||
24
admin/package.json
Normal file
24
admin/package.json
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
{
|
||||||
|
"name": "admin",
|
||||||
|
"version": "0.1.0",
|
||||||
|
"private": true,
|
||||||
|
"dependencies": {
|
||||||
|
"@api-platform/admin": "^0.6.1",
|
||||||
|
"@babel/runtime": "7.0.0-beta.55",
|
||||||
|
"react": "^16.3.0",
|
||||||
|
"react-dom": "^16.3.0",
|
||||||
|
"react-scripts": "^2.1.2"
|
||||||
|
},
|
||||||
|
"scripts": {
|
||||||
|
"start": "react-scripts start",
|
||||||
|
"build": "react-scripts build",
|
||||||
|
"test": "react-scripts test",
|
||||||
|
"eject": "react-scripts eject"
|
||||||
|
},
|
||||||
|
"browserslist": [
|
||||||
|
">0.2%",
|
||||||
|
"not dead",
|
||||||
|
"not ie <= 11",
|
||||||
|
"not op_mini all"
|
||||||
|
]
|
||||||
|
}
|
||||||
BIN
admin/public/favicon.ico
Normal file
BIN
admin/public/favicon.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 31 KiB |
40
admin/public/index.html
Normal file
40
admin/public/index.html
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||||
|
<meta name="theme-color" content="#000000">
|
||||||
|
<!--
|
||||||
|
manifest.json provides metadata used when your web app is added to the
|
||||||
|
homescreen on Android. See https://developers.google.com/web/fundamentals/engage-and-retain/web-app-manifest/
|
||||||
|
-->
|
||||||
|
<link rel="manifest" href="%PUBLIC_URL%/manifest.json">
|
||||||
|
<link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico">
|
||||||
|
<!--
|
||||||
|
Notice the use of %PUBLIC_URL% in the tags above.
|
||||||
|
It will be replaced with the URL of the `public` folder during the build.
|
||||||
|
Only files inside the `public` folder can be referenced from the HTML.
|
||||||
|
|
||||||
|
Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
|
||||||
|
work correctly both with client-side routing and a non-root public URL.
|
||||||
|
Learn how to configure a non-root public URL by running `npm run build`.
|
||||||
|
-->
|
||||||
|
<title>API Platform Admin</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<noscript>
|
||||||
|
You need to enable JavaScript to run this app.
|
||||||
|
</noscript>
|
||||||
|
<div id="root"></div>
|
||||||
|
<!--
|
||||||
|
This HTML file is a template.
|
||||||
|
If you open it directly in the browser, you will see an empty page.
|
||||||
|
|
||||||
|
You can add webfonts, meta tags, or analytics to this file.
|
||||||
|
The build step will place the bundled scripts into the <body> tag.
|
||||||
|
|
||||||
|
To begin the development, run `npm start` or `yarn start`.
|
||||||
|
To create a production bundle, use `npm run build` or `yarn build`.
|
||||||
|
-->
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
15
admin/public/manifest.json
Normal file
15
admin/public/manifest.json
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
{
|
||||||
|
"short_name": "API Platform Admin",
|
||||||
|
"name": "Admin",
|
||||||
|
"icons": [
|
||||||
|
{
|
||||||
|
"src": "favicon.ico",
|
||||||
|
"sizes": "192x192",
|
||||||
|
"type": "image/png"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"start_url": "./index.html",
|
||||||
|
"display": "standalone",
|
||||||
|
"theme_color": "#000000",
|
||||||
|
"background_color": "#ffffff"
|
||||||
|
}
|
||||||
4
admin/src/App.js
Normal file
4
admin/src/App.js
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import { HydraAdmin } from '@api-platform/admin';
|
||||||
|
|
||||||
|
export default () => <HydraAdmin entrypoint={process.env.REACT_APP_API_ENTRYPOINT}/>;
|
||||||
9
admin/src/App.test.js
Normal file
9
admin/src/App.test.js
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import ReactDOM from 'react-dom';
|
||||||
|
import App from './App';
|
||||||
|
|
||||||
|
it('renders without crashing', () => {
|
||||||
|
const div = document.createElement('div');
|
||||||
|
ReactDOM.render(<App />, div);
|
||||||
|
ReactDOM.unmountComponentAtNode(div);
|
||||||
|
});
|
||||||
11
admin/src/index.js
Normal file
11
admin/src/index.js
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import ReactDOM from 'react-dom';
|
||||||
|
import App from './App';
|
||||||
|
import * as serviceWorker from './serviceWorker';
|
||||||
|
|
||||||
|
ReactDOM.render(<App />, document.getElementById('root'));
|
||||||
|
|
||||||
|
// If you want your app to work offline and load faster, you can change
|
||||||
|
// unregister() to register() below. Note this comes with some pitfalls.
|
||||||
|
// Learn more about service workers: http://bit.ly/CRA-PWA
|
||||||
|
serviceWorker.unregister();
|
||||||
135
admin/src/serviceWorker.js
Normal file
135
admin/src/serviceWorker.js
Normal file
@@ -0,0 +1,135 @@
|
|||||||
|
// This optional code is used to register a service worker.
|
||||||
|
// register() is not called by default.
|
||||||
|
|
||||||
|
// This lets the app load faster on subsequent visits in production, and gives
|
||||||
|
// it offline capabilities. However, it also means that developers (and users)
|
||||||
|
// will only see deployed updates on subsequent visits to a page, after all the
|
||||||
|
// existing tabs open on the page have been closed, since previously cached
|
||||||
|
// resources are updated in the background.
|
||||||
|
|
||||||
|
// To learn more about the benefits of this model and instructions on how to
|
||||||
|
// opt-in, read http://bit.ly/CRA-PWA
|
||||||
|
|
||||||
|
const isLocalhost = Boolean(
|
||||||
|
window.location.hostname === 'localhost' ||
|
||||||
|
// [::1] is the IPv6 localhost address.
|
||||||
|
window.location.hostname === '[::1]' ||
|
||||||
|
// 127.0.0.1/8 is considered localhost for IPv4.
|
||||||
|
window.location.hostname.match(
|
||||||
|
/^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
export function register(config) {
|
||||||
|
if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) {
|
||||||
|
// The URL constructor is available in all browsers that support SW.
|
||||||
|
const publicUrl = new URL(process.env.PUBLIC_URL, window.location.href);
|
||||||
|
if (publicUrl.origin !== window.location.origin) {
|
||||||
|
// Our service worker won't work if PUBLIC_URL is on a different origin
|
||||||
|
// from what our page is served on. This might happen if a CDN is used to
|
||||||
|
// serve assets; see https://github.com/facebook/create-react-app/issues/2374
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
window.addEventListener('load', () => {
|
||||||
|
const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`;
|
||||||
|
|
||||||
|
if (isLocalhost) {
|
||||||
|
// This is running on localhost. Let's check if a service worker still exists or not.
|
||||||
|
checkValidServiceWorker(swUrl, config);
|
||||||
|
|
||||||
|
// Add some additional logging to localhost, pointing developers to the
|
||||||
|
// service worker/PWA documentation.
|
||||||
|
navigator.serviceWorker.ready.then(() => {
|
||||||
|
console.log(
|
||||||
|
'This web app is being served cache-first by a service ' +
|
||||||
|
'worker. To learn more, visit http://bit.ly/CRA-PWA'
|
||||||
|
);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
// Is not localhost. Just register service worker
|
||||||
|
registerValidSW(swUrl, config);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function registerValidSW(swUrl, config) {
|
||||||
|
navigator.serviceWorker
|
||||||
|
.register(swUrl)
|
||||||
|
.then(registration => {
|
||||||
|
registration.onupdatefound = () => {
|
||||||
|
const installingWorker = registration.installing;
|
||||||
|
if (installingWorker == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
installingWorker.onstatechange = () => {
|
||||||
|
if (installingWorker.state === 'installed') {
|
||||||
|
if (navigator.serviceWorker.controller) {
|
||||||
|
// At this point, the updated precached content has been fetched,
|
||||||
|
// but the previous service worker will still serve the older
|
||||||
|
// content until all client tabs are closed.
|
||||||
|
console.log(
|
||||||
|
'New content is available and will be used when all ' +
|
||||||
|
'tabs for this page are closed. See http://bit.ly/CRA-PWA.'
|
||||||
|
);
|
||||||
|
|
||||||
|
// Execute callback
|
||||||
|
if (config && config.onUpdate) {
|
||||||
|
config.onUpdate(registration);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// At this point, everything has been precached.
|
||||||
|
// It's the perfect time to display a
|
||||||
|
// "Content is cached for offline use." message.
|
||||||
|
console.log('Content is cached for offline use.');
|
||||||
|
|
||||||
|
// Execute callback
|
||||||
|
if (config && config.onSuccess) {
|
||||||
|
config.onSuccess(registration);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
console.error('Error during service worker registration:', error);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function checkValidServiceWorker(swUrl, config) {
|
||||||
|
// Check if the service worker can be found. If it can't reload the page.
|
||||||
|
fetch(swUrl)
|
||||||
|
.then(response => {
|
||||||
|
// Ensure service worker exists, and that we really are getting a JS file.
|
||||||
|
const contentType = response.headers.get('content-type');
|
||||||
|
if (
|
||||||
|
response.status === 404 ||
|
||||||
|
(contentType != null && contentType.indexOf('javascript') === -1)
|
||||||
|
) {
|
||||||
|
// No service worker found. Probably a different app. Reload the page.
|
||||||
|
navigator.serviceWorker.ready.then(registration => {
|
||||||
|
registration.unregister().then(() => {
|
||||||
|
window.location.reload();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
// Service worker found. Proceed as normal.
|
||||||
|
registerValidSW(swUrl, config);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(() => {
|
||||||
|
console.log(
|
||||||
|
'No internet connection found. App is running in offline mode.'
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export function unregister() {
|
||||||
|
if ('serviceWorker' in navigator) {
|
||||||
|
navigator.serviceWorker.ready.then(registration => {
|
||||||
|
registration.unregister();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
11067
admin/yarn.lock
Normal file
11067
admin/yarn.lock
Normal file
File diff suppressed because it is too large
Load Diff
22
api/.dockerignore
Normal file
22
api/.dockerignore
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
**/*.log
|
||||||
|
**/*.md
|
||||||
|
**/*.php~
|
||||||
|
**/._*
|
||||||
|
**/.dockerignore
|
||||||
|
**/.DS_Store
|
||||||
|
**/.git/
|
||||||
|
**/.gitattributes
|
||||||
|
**/.gitignore
|
||||||
|
**/.gitmodules
|
||||||
|
**/Dockerfile
|
||||||
|
**/Thumbs.db
|
||||||
|
.editorconfig
|
||||||
|
.env.*
|
||||||
|
.php_cs.cache
|
||||||
|
bin/*
|
||||||
|
!bin/console
|
||||||
|
docker/db/data/
|
||||||
|
helm/
|
||||||
|
public/bundles/
|
||||||
|
var/
|
||||||
|
vendor/
|
||||||
40
api/.env
Normal file
40
api/.env
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
# In all environments, the following files are loaded if they exist,
|
||||||
|
# the later taking precedence over the former:
|
||||||
|
#
|
||||||
|
# * .env contains default values for the environment variables needed by the app
|
||||||
|
# * .env.local uncommitted file with local overrides
|
||||||
|
# * .env.$APP_ENV committed environment-specific defaults
|
||||||
|
# * .env.$APP_ENV.local uncommitted environment-specific overrides
|
||||||
|
#
|
||||||
|
# Real environment variables win over .env files.
|
||||||
|
#
|
||||||
|
# DO NOT DEFINE PRODUCTION SECRETS IN THIS FILE NOR IN ANY OTHER COMMITTED FILES.
|
||||||
|
#
|
||||||
|
# Run "composer dump-env prod" to compile .env files for production use (requires symfony/flex >=1.2).
|
||||||
|
# https://symfony.com/doc/current/best_practices/configuration.html#infrastructure-related-configuration
|
||||||
|
|
||||||
|
MERCURE_SUBSCRIBE_URL=http://localhost:1337/hub
|
||||||
|
VARNISH_URL=http://cache-proxy
|
||||||
|
|
||||||
|
###> symfony/framework-bundle ###
|
||||||
|
APP_ENV=dev
|
||||||
|
APP_SECRET=!ChangeMe!
|
||||||
|
TRUSTED_PROXIES=10.0.0.0/8,172.16.0.0/12,192.168.0.0/16
|
||||||
|
TRUSTED_HOSTS='^localhost|api$'
|
||||||
|
###< symfony/framework-bundle ###
|
||||||
|
|
||||||
|
###> doctrine/doctrine-bundle ###
|
||||||
|
# Format described at http://docs.doctrine-project.org/projects/doctrine-dbal/en/latest/reference/configuration.html#connecting-using-a-url
|
||||||
|
# For an SQLite database, use: "sqlite:///%kernel.project_dir%/var/data.db"
|
||||||
|
# Configure your db driver and server_version in config/packages/doctrine.yaml
|
||||||
|
DATABASE_URL=postgres://api-platform:!ChangeMe!@db/api
|
||||||
|
###< doctrine/doctrine-bundle ###
|
||||||
|
|
||||||
|
###> nelmio/cors-bundle ###
|
||||||
|
CORS_ALLOW_ORIGIN=^https?://localhost(:[0-9]+)?$
|
||||||
|
###< nelmio/cors-bundle ###
|
||||||
|
|
||||||
|
###> symfony/mercure-bundle ###
|
||||||
|
MERCURE_PUBLISH_URL=http://mercure/hub
|
||||||
|
MERCURE_JWT_SECRET=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJtZXJjdXJlIjp7InN1YnNjcmliZSI6WyJmb28iLCJiYXIiXSwicHVibGlzaCI6WyJmb28iXX19.LRLvirgONK13JgacQ_VbcjySbVhkSmHy3IznH3tA9PM
|
||||||
|
###< symfony/mercure-bundle ###
|
||||||
15
api/.gitignore
vendored
Normal file
15
api/.gitignore
vendored
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
/helm/api/charts
|
||||||
|
|
||||||
|
###> symfony/framework-bundle ###
|
||||||
|
/.env.local
|
||||||
|
/.env.local.php
|
||||||
|
/.env.*.local
|
||||||
|
/public/bundles/
|
||||||
|
/var/
|
||||||
|
/vendor/
|
||||||
|
###< symfony/framework-bundle ###
|
||||||
|
|
||||||
|
###> friendsofphp/php-cs-fixer ###
|
||||||
|
/.php_cs
|
||||||
|
/.php_cs.cache
|
||||||
|
###< friendsofphp/php-cs-fixer ###
|
||||||
14
api/.php_cs.dist
Normal file
14
api/.php_cs.dist
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
$finder = PhpCsFixer\Finder::create()
|
||||||
|
->in(__DIR__)
|
||||||
|
->exclude('var')
|
||||||
|
;
|
||||||
|
|
||||||
|
return PhpCsFixer\Config::create()
|
||||||
|
->setRules([
|
||||||
|
'@Symfony' => true,
|
||||||
|
'array_syntax' => ['syntax' => 'short'],
|
||||||
|
])
|
||||||
|
->setFinder($finder)
|
||||||
|
;
|
||||||
121
api/Dockerfile
Normal file
121
api/Dockerfile
Normal file
@@ -0,0 +1,121 @@
|
|||||||
|
# the different stages of this Dockerfile are meant to be built into separate images
|
||||||
|
# https://docs.docker.com/develop/develop-images/multistage-build/#stop-at-a-specific-build-stage
|
||||||
|
# https://docs.docker.com/compose/compose-file/#target
|
||||||
|
|
||||||
|
|
||||||
|
# https://docs.docker.com/engine/reference/builder/#understand-how-arg-and-from-interact
|
||||||
|
ARG PHP_VERSION=7.3
|
||||||
|
ARG NGINX_VERSION=1.15
|
||||||
|
ARG VARNISH_VERSION=6.2
|
||||||
|
|
||||||
|
|
||||||
|
# "php" stage
|
||||||
|
FROM php:${PHP_VERSION}-fpm-alpine AS api_platform_php
|
||||||
|
|
||||||
|
# persistent / runtime deps
|
||||||
|
RUN apk add --no-cache \
|
||||||
|
acl \
|
||||||
|
file \
|
||||||
|
gettext \
|
||||||
|
git \
|
||||||
|
;
|
||||||
|
|
||||||
|
ARG APCU_VERSION=5.1.17
|
||||||
|
RUN set -eux; \
|
||||||
|
apk add --no-cache --virtual .build-deps \
|
||||||
|
$PHPIZE_DEPS \
|
||||||
|
icu-dev \
|
||||||
|
libzip-dev \
|
||||||
|
postgresql-dev \
|
||||||
|
zlib-dev \
|
||||||
|
; \
|
||||||
|
\
|
||||||
|
docker-php-ext-configure zip --with-libzip; \
|
||||||
|
docker-php-ext-install -j$(nproc) \
|
||||||
|
intl \
|
||||||
|
pdo_pgsql \
|
||||||
|
zip \
|
||||||
|
; \
|
||||||
|
pecl install \
|
||||||
|
apcu-${APCU_VERSION} \
|
||||||
|
; \
|
||||||
|
pecl clear-cache; \
|
||||||
|
docker-php-ext-enable \
|
||||||
|
apcu \
|
||||||
|
opcache \
|
||||||
|
; \
|
||||||
|
\
|
||||||
|
runDeps="$( \
|
||||||
|
scanelf --needed --nobanner --format '%n#p' --recursive /usr/local/lib/php/extensions \
|
||||||
|
| tr ',' '\n' \
|
||||||
|
| sort -u \
|
||||||
|
| awk 'system("[ -e /usr/local/lib/" $1 " ]") == 0 { next } { print "so:" $1 }' \
|
||||||
|
)"; \
|
||||||
|
apk add --no-cache --virtual .api-phpexts-rundeps $runDeps; \
|
||||||
|
\
|
||||||
|
apk del .build-deps
|
||||||
|
|
||||||
|
COPY --from=composer:latest /usr/bin/composer /usr/bin/composer
|
||||||
|
RUN ln -s $PHP_INI_DIR/php.ini-production $PHP_INI_DIR/php.ini
|
||||||
|
COPY docker/php/conf.d/api-platform.ini $PHP_INI_DIR/conf.d/api-platform.ini
|
||||||
|
|
||||||
|
# https://getcomposer.org/doc/03-cli.md#composer-allow-superuser
|
||||||
|
ENV COMPOSER_ALLOW_SUPERUSER=1
|
||||||
|
# install Symfony Flex globally to speed up download of Composer packages (parallelized prefetching)
|
||||||
|
RUN set -eux; \
|
||||||
|
composer global require "symfony/flex" --prefer-dist --no-progress --no-suggest --classmap-authoritative; \
|
||||||
|
composer clear-cache
|
||||||
|
ENV PATH="${PATH}:/root/.composer/vendor/bin"
|
||||||
|
|
||||||
|
WORKDIR /srv/api
|
||||||
|
|
||||||
|
# build for production
|
||||||
|
ARG APP_ENV=prod
|
||||||
|
|
||||||
|
# prevent the reinstallation of vendors at every changes in the source code
|
||||||
|
COPY composer.json composer.lock symfony.lock ./
|
||||||
|
RUN set -eux; \
|
||||||
|
composer install --prefer-dist --no-dev --no-scripts --no-progress --no-suggest; \
|
||||||
|
composer clear-cache
|
||||||
|
|
||||||
|
# do not use .env files in production
|
||||||
|
COPY .env ./
|
||||||
|
RUN composer dump-env prod; \
|
||||||
|
rm .env
|
||||||
|
|
||||||
|
# copy only specifically what we need
|
||||||
|
COPY bin bin/
|
||||||
|
COPY config config/
|
||||||
|
COPY public public/
|
||||||
|
COPY src src/
|
||||||
|
|
||||||
|
RUN set -eux; \
|
||||||
|
mkdir -p var/cache var/log; \
|
||||||
|
composer dump-autoload --classmap-authoritative --no-dev; \
|
||||||
|
composer run-script --no-dev post-install-cmd; \
|
||||||
|
chmod +x bin/console; sync
|
||||||
|
VOLUME /srv/api/var
|
||||||
|
|
||||||
|
COPY docker/php/docker-entrypoint.sh /usr/local/bin/docker-entrypoint
|
||||||
|
RUN chmod +x /usr/local/bin/docker-entrypoint
|
||||||
|
|
||||||
|
ENTRYPOINT ["docker-entrypoint"]
|
||||||
|
CMD ["php-fpm"]
|
||||||
|
|
||||||
|
|
||||||
|
# "nginx" stage
|
||||||
|
# depends on the "php" stage above
|
||||||
|
FROM nginx:${NGINX_VERSION}-alpine AS api_platform_nginx
|
||||||
|
|
||||||
|
COPY docker/nginx/conf.d/default.conf /etc/nginx/conf.d/default.conf
|
||||||
|
|
||||||
|
WORKDIR /srv/api
|
||||||
|
|
||||||
|
COPY --from=api_platform_php /srv/api/public public/
|
||||||
|
|
||||||
|
|
||||||
|
# "varnish" stage
|
||||||
|
# does not depend on any of the above stages, but placed here to keep everything in one Dockerfile
|
||||||
|
FROM cooptilleuls/varnish:${VARNISH_VERSION}-alpine AS api_platform_varnish
|
||||||
|
|
||||||
|
COPY docker/varnish/conf/default.vcl /usr/local/etc/varnish/default.vcl
|
||||||
42
api/bin/console
Executable file
42
api/bin/console
Executable file
@@ -0,0 +1,42 @@
|
|||||||
|
#!/usr/bin/env php
|
||||||
|
<?php
|
||||||
|
|
||||||
|
use App\Kernel;
|
||||||
|
use Symfony\Bundle\FrameworkBundle\Console\Application;
|
||||||
|
use Symfony\Component\Console\Input\ArgvInput;
|
||||||
|
use Symfony\Component\Debug\Debug;
|
||||||
|
|
||||||
|
if (false === in_array(\PHP_SAPI, ['cli', 'phpdbg', 'embed'], true)) {
|
||||||
|
echo 'Warning: The console should be invoked via the CLI version of PHP, not the '.\PHP_SAPI.' SAPI'.\PHP_EOL;
|
||||||
|
}
|
||||||
|
|
||||||
|
set_time_limit(0);
|
||||||
|
|
||||||
|
require dirname(__DIR__).'/vendor/autoload.php';
|
||||||
|
|
||||||
|
if (!class_exists(Application::class)) {
|
||||||
|
throw new RuntimeException('You need to add "symfony/framework-bundle" as a Composer dependency.');
|
||||||
|
}
|
||||||
|
|
||||||
|
$input = new ArgvInput();
|
||||||
|
if (null !== $env = $input->getParameterOption(['--env', '-e'], null, true)) {
|
||||||
|
putenv('APP_ENV='.$_SERVER['APP_ENV'] = $_ENV['APP_ENV'] = $env);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($input->hasParameterOption('--no-debug', true)) {
|
||||||
|
putenv('APP_DEBUG='.$_SERVER['APP_DEBUG'] = $_ENV['APP_DEBUG'] = '0');
|
||||||
|
}
|
||||||
|
|
||||||
|
require dirname(__DIR__).'/config/bootstrap.php';
|
||||||
|
|
||||||
|
if ($_SERVER['APP_DEBUG']) {
|
||||||
|
umask(0000);
|
||||||
|
|
||||||
|
if (class_exists(Debug::class)) {
|
||||||
|
Debug::enable();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$kernel = new Kernel($_SERVER['APP_ENV'], (bool) $_SERVER['APP_DEBUG']);
|
||||||
|
$application = new Application($kernel);
|
||||||
|
$application->run($input);
|
||||||
67
api/composer.json
Normal file
67
api/composer.json
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
{
|
||||||
|
"type": "project",
|
||||||
|
"license": "proprietary",
|
||||||
|
"require": {
|
||||||
|
"php": "^7.1.3",
|
||||||
|
"ext-ctype": "*",
|
||||||
|
"ext-iconv": "*",
|
||||||
|
"api-platform/api-pack": "^1.1",
|
||||||
|
"guzzlehttp/guzzle": "^6.3",
|
||||||
|
"symfony/console": "4.3.*",
|
||||||
|
"symfony/dotenv": "4.3.*",
|
||||||
|
"symfony/flex": "^1.1",
|
||||||
|
"symfony/framework-bundle": "4.3.*",
|
||||||
|
"symfony/mercure-bundle": "*",
|
||||||
|
"symfony/yaml": "4.3.*"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"api-platform/schema-generator": "^2.1",
|
||||||
|
"symfony/maker-bundle": "^1.11",
|
||||||
|
"symfony/profiler-pack": "^1.0"
|
||||||
|
},
|
||||||
|
"config": {
|
||||||
|
"preferred-install": {
|
||||||
|
"*": "dist"
|
||||||
|
},
|
||||||
|
"sort-packages": true
|
||||||
|
},
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"App\\": "src/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"autoload-dev": {
|
||||||
|
"psr-4": {
|
||||||
|
"App\\Tests\\": "tests/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"replace": {
|
||||||
|
"paragonie/random_compat": "2.*",
|
||||||
|
"symfony/polyfill-ctype": "*",
|
||||||
|
"symfony/polyfill-iconv": "*",
|
||||||
|
"symfony/polyfill-php71": "*",
|
||||||
|
"symfony/polyfill-php70": "*",
|
||||||
|
"symfony/polyfill-php56": "*"
|
||||||
|
},
|
||||||
|
"scripts": {
|
||||||
|
"auto-scripts": {
|
||||||
|
"cache:clear": "symfony-cmd",
|
||||||
|
"assets:install %PUBLIC_DIR%": "symfony-cmd"
|
||||||
|
},
|
||||||
|
"post-install-cmd": [
|
||||||
|
"@auto-scripts"
|
||||||
|
],
|
||||||
|
"post-update-cmd": [
|
||||||
|
"@auto-scripts"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"conflict": {
|
||||||
|
"symfony/symfony": "*"
|
||||||
|
},
|
||||||
|
"extra": {
|
||||||
|
"symfony": {
|
||||||
|
"allow-contrib": false,
|
||||||
|
"require": "4.3.*"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
5874
api/composer.lock
generated
Normal file
5874
api/composer.lock
generated
Normal file
File diff suppressed because it is too large
Load Diff
23
api/config/bootstrap.php
Normal file
23
api/config/bootstrap.php
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Symfony\Component\Dotenv\Dotenv;
|
||||||
|
|
||||||
|
require dirname(__DIR__).'/vendor/autoload.php';
|
||||||
|
|
||||||
|
// Load cached env vars if the .env.local.php file exists
|
||||||
|
// Run "composer dump-env prod" to create it (requires symfony/flex >=1.2)
|
||||||
|
if (is_array($env = @include dirname(__DIR__).'/.env.local.php')) {
|
||||||
|
foreach ($env as $k => $v) {
|
||||||
|
$_ENV[$k] = $_ENV[$k] ?? (isset($_SERVER[$k]) && 0 !== strpos($k, 'HTTP_') ? $_SERVER[$k] : $v);
|
||||||
|
}
|
||||||
|
} elseif (!class_exists(Dotenv::class)) {
|
||||||
|
throw new RuntimeException('Please run "composer require symfony/dotenv" to load the ".env" files configuring the application.');
|
||||||
|
} else {
|
||||||
|
// load all the .env files
|
||||||
|
(new Dotenv(false))->loadEnv(dirname(__DIR__).'/.env');
|
||||||
|
}
|
||||||
|
|
||||||
|
$_SERVER += $_ENV;
|
||||||
|
$_SERVER['APP_ENV'] = $_ENV['APP_ENV'] = ($_SERVER['APP_ENV'] ?? $_ENV['APP_ENV'] ?? null) ?: 'dev';
|
||||||
|
$_SERVER['APP_DEBUG'] = $_SERVER['APP_DEBUG'] ?? $_ENV['APP_DEBUG'] ?? 'prod' !== $_SERVER['APP_ENV'];
|
||||||
|
$_SERVER['APP_DEBUG'] = $_ENV['APP_DEBUG'] = (int) $_SERVER['APP_DEBUG'] || filter_var($_SERVER['APP_DEBUG'], FILTER_VALIDATE_BOOLEAN) ? '1' : '0';
|
||||||
14
api/config/bundles.php
Normal file
14
api/config/bundles.php
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
return [
|
||||||
|
Symfony\Bundle\FrameworkBundle\FrameworkBundle::class => ['all' => true],
|
||||||
|
Symfony\Bundle\SecurityBundle\SecurityBundle::class => ['all' => true],
|
||||||
|
Symfony\Bundle\MercureBundle\MercureBundle::class => ['all' => true],
|
||||||
|
Symfony\Bundle\TwigBundle\TwigBundle::class => ['all' => true],
|
||||||
|
Doctrine\Bundle\DoctrineCacheBundle\DoctrineCacheBundle::class => ['all' => true],
|
||||||
|
Doctrine\Bundle\DoctrineBundle\DoctrineBundle::class => ['all' => true],
|
||||||
|
ApiPlatform\Core\Bridge\Symfony\Bundle\ApiPlatformBundle::class => ['all' => true],
|
||||||
|
Nelmio\CorsBundle\NelmioCorsBundle::class => ['all' => true],
|
||||||
|
Symfony\Bundle\WebProfilerBundle\WebProfilerBundle::class => ['dev' => true, 'test' => true],
|
||||||
|
Symfony\Bundle\MakerBundle\MakerBundle::class => ['dev' => true],
|
||||||
|
];
|
||||||
24
api/config/packages/api_platform.yaml
Normal file
24
api/config/packages/api_platform.yaml
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
parameters:
|
||||||
|
# Adds a fallback VARNISH_URL if the env var is not set.
|
||||||
|
# This allows you to run cache:warmup even if your
|
||||||
|
# environment variables are not available yet.
|
||||||
|
# You should not need to change this value.
|
||||||
|
env(VARNISH_URL): ''
|
||||||
|
|
||||||
|
api_platform:
|
||||||
|
mapping:
|
||||||
|
paths: ['%kernel.project_dir%/src/Entity']
|
||||||
|
title: Hello API Platform
|
||||||
|
version: 1.0.0
|
||||||
|
# Varnish integration, remove if unwanted
|
||||||
|
http_cache:
|
||||||
|
invalidation:
|
||||||
|
enabled: true
|
||||||
|
varnish_urls: ['%env(VARNISH_URL)%']
|
||||||
|
max_age: 0
|
||||||
|
shared_max_age: 3600
|
||||||
|
vary: ['Content-Type', 'Authorization']
|
||||||
|
public: true
|
||||||
|
# Mercure integration, remove if unwanted
|
||||||
|
mercure:
|
||||||
|
hub_url: '%env(MERCURE_SUBSCRIBE_URL)%'
|
||||||
19
api/config/packages/cache.yaml
Normal file
19
api/config/packages/cache.yaml
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
framework:
|
||||||
|
cache:
|
||||||
|
# Put the unique name of your app here: the prefix seed
|
||||||
|
# is used to compute stable namespaces for cache keys.
|
||||||
|
#prefix_seed: your_vendor_name/app_name
|
||||||
|
|
||||||
|
# The app cache caches to the filesystem by default.
|
||||||
|
# Other options include:
|
||||||
|
|
||||||
|
# Redis
|
||||||
|
#app: cache.adapter.redis
|
||||||
|
#default_redis_provider: redis://localhost
|
||||||
|
|
||||||
|
# APCu (not recommended with heavy random-write workloads as memory fragmentation can cause perf issues)
|
||||||
|
#app: cache.adapter.apcu
|
||||||
|
|
||||||
|
# Namespaced pools use the above "app" backend by default
|
||||||
|
#pools:
|
||||||
|
#my.dedicated.cache: ~
|
||||||
3
api/config/packages/dev/routing.yaml
Normal file
3
api/config/packages/dev/routing.yaml
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
framework:
|
||||||
|
router:
|
||||||
|
strict_requirements: true
|
||||||
6
api/config/packages/dev/web_profiler.yaml
Normal file
6
api/config/packages/dev/web_profiler.yaml
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
web_profiler:
|
||||||
|
toolbar: true
|
||||||
|
intercept_redirects: false
|
||||||
|
|
||||||
|
framework:
|
||||||
|
profiler: { only_exceptions: false }
|
||||||
18
api/config/packages/doctrine.yaml
Normal file
18
api/config/packages/doctrine.yaml
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
doctrine:
|
||||||
|
dbal:
|
||||||
|
# configure these for your database server
|
||||||
|
driver: 'pdo_pgsql'
|
||||||
|
server_version: '10'
|
||||||
|
|
||||||
|
url: '%env(resolve:DATABASE_URL)%'
|
||||||
|
orm:
|
||||||
|
auto_generate_proxy_classes: true
|
||||||
|
naming_strategy: doctrine.orm.naming_strategy.underscore
|
||||||
|
auto_mapping: true
|
||||||
|
mappings:
|
||||||
|
App:
|
||||||
|
is_bundle: false
|
||||||
|
type: annotation
|
||||||
|
dir: '%kernel.project_dir%/src/Entity'
|
||||||
|
prefix: 'App\Entity'
|
||||||
|
alias: App
|
||||||
16
api/config/packages/framework.yaml
Normal file
16
api/config/packages/framework.yaml
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
framework:
|
||||||
|
secret: '%env(APP_SECRET)%'
|
||||||
|
#csrf_protection: true
|
||||||
|
#http_method_override: true
|
||||||
|
|
||||||
|
# Enables session support. Note that the session will ONLY be started if you read or write from it.
|
||||||
|
# Remove or comment this section to explicitly disable session support.
|
||||||
|
session:
|
||||||
|
handler_id: ~
|
||||||
|
cookie_secure: auto
|
||||||
|
cookie_samesite: lax
|
||||||
|
|
||||||
|
#esi: true
|
||||||
|
#fragments: true
|
||||||
|
php_errors:
|
||||||
|
log: true
|
||||||
5
api/config/packages/mercure.yaml
Normal file
5
api/config/packages/mercure.yaml
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
mercure:
|
||||||
|
hubs:
|
||||||
|
default:
|
||||||
|
url: '%env(MERCURE_PUBLISH_URL)%'
|
||||||
|
jwt: '%env(MERCURE_JWT_SECRET)%'
|
||||||
10
api/config/packages/nelmio_cors.yaml
Normal file
10
api/config/packages/nelmio_cors.yaml
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
nelmio_cors:
|
||||||
|
defaults:
|
||||||
|
origin_regex: true
|
||||||
|
allow_origin: ['%env(CORS_ALLOW_ORIGIN)%']
|
||||||
|
allow_methods: ['GET', 'OPTIONS', 'POST', 'PUT', 'PATCH', 'DELETE']
|
||||||
|
allow_headers: ['Content-Type', 'Authorization']
|
||||||
|
expose_headers: ['Link']
|
||||||
|
max_age: 3600
|
||||||
|
paths:
|
||||||
|
'^/': ~
|
||||||
32
api/config/packages/prod/doctrine.yaml
Normal file
32
api/config/packages/prod/doctrine.yaml
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
doctrine:
|
||||||
|
orm:
|
||||||
|
auto_generate_proxy_classes: false
|
||||||
|
metadata_cache_driver:
|
||||||
|
type: service
|
||||||
|
id: doctrine.system_cache_provider
|
||||||
|
query_cache_driver:
|
||||||
|
type: service
|
||||||
|
id: doctrine.system_cache_provider
|
||||||
|
result_cache_driver:
|
||||||
|
type: service
|
||||||
|
id: doctrine.result_cache_provider
|
||||||
|
|
||||||
|
services:
|
||||||
|
doctrine.result_cache_provider:
|
||||||
|
class: Symfony\Component\Cache\DoctrineProvider
|
||||||
|
public: false
|
||||||
|
arguments:
|
||||||
|
- '@doctrine.result_cache_pool'
|
||||||
|
doctrine.system_cache_provider:
|
||||||
|
class: Symfony\Component\Cache\DoctrineProvider
|
||||||
|
public: false
|
||||||
|
arguments:
|
||||||
|
- '@doctrine.system_cache_pool'
|
||||||
|
|
||||||
|
framework:
|
||||||
|
cache:
|
||||||
|
pools:
|
||||||
|
doctrine.result_cache_pool:
|
||||||
|
adapter: cache.app
|
||||||
|
doctrine.system_cache_pool:
|
||||||
|
adapter: cache.system
|
||||||
4
api/config/packages/routing.yaml
Normal file
4
api/config/packages/routing.yaml
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
framework:
|
||||||
|
router:
|
||||||
|
strict_requirements: ~
|
||||||
|
utf8: true
|
||||||
22
api/config/packages/security.yaml
Normal file
22
api/config/packages/security.yaml
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
security:
|
||||||
|
# https://symfony.com/doc/current/security.html#where-do-users-come-from-user-providers
|
||||||
|
providers:
|
||||||
|
in_memory: { memory: ~ }
|
||||||
|
firewalls:
|
||||||
|
dev:
|
||||||
|
pattern: ^/(_(profiler|wdt)|css|images|js)/
|
||||||
|
security: false
|
||||||
|
main:
|
||||||
|
anonymous: true
|
||||||
|
|
||||||
|
# activate different ways to authenticate
|
||||||
|
# https://symfony.com/doc/current/security.html#firewalls-authentication
|
||||||
|
|
||||||
|
# https://symfony.com/doc/current/security/impersonating_user.html
|
||||||
|
# switch_user: true
|
||||||
|
|
||||||
|
# Easy way to control access for large sections of your site
|
||||||
|
# Note: Only the *first* access control that matches will be used
|
||||||
|
access_control:
|
||||||
|
# - { path: ^/admin, roles: ROLE_ADMIN }
|
||||||
|
# - { path: ^/profile, roles: ROLE_USER }
|
||||||
4
api/config/packages/test/framework.yaml
Normal file
4
api/config/packages/test/framework.yaml
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
framework:
|
||||||
|
test: true
|
||||||
|
session:
|
||||||
|
storage_id: session.storage.mock_file
|
||||||
3
api/config/packages/test/routing.yaml
Normal file
3
api/config/packages/test/routing.yaml
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
framework:
|
||||||
|
router:
|
||||||
|
strict_requirements: true
|
||||||
3
api/config/packages/test/validator.yaml
Normal file
3
api/config/packages/test/validator.yaml
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
framework:
|
||||||
|
validation:
|
||||||
|
not_compromised_password: false
|
||||||
6
api/config/packages/test/web_profiler.yaml
Normal file
6
api/config/packages/test/web_profiler.yaml
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
web_profiler:
|
||||||
|
toolbar: false
|
||||||
|
intercept_redirects: false
|
||||||
|
|
||||||
|
framework:
|
||||||
|
profiler: { collect: false }
|
||||||
4
api/config/packages/twig.yaml
Normal file
4
api/config/packages/twig.yaml
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
twig:
|
||||||
|
default_path: '%kernel.project_dir%/templates'
|
||||||
|
debug: '%kernel.debug%'
|
||||||
|
strict_variables: '%kernel.debug%'
|
||||||
8
api/config/packages/validator.yaml
Normal file
8
api/config/packages/validator.yaml
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
framework:
|
||||||
|
validation:
|
||||||
|
email_validation_mode: html5
|
||||||
|
|
||||||
|
# Enables validator auto-mapping support.
|
||||||
|
# For instance, basic validation constraints will be inferred from Doctrine's metadata.
|
||||||
|
#auto_mapping:
|
||||||
|
# App\Entity\: []
|
||||||
3
api/config/routes.yaml
Normal file
3
api/config/routes.yaml
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
#index:
|
||||||
|
# path: /
|
||||||
|
# controller: App\Controller\DefaultController::index
|
||||||
3
api/config/routes/annotations.yaml
Normal file
3
api/config/routes/annotations.yaml
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
controllers:
|
||||||
|
resource: ../../src/Controller/
|
||||||
|
type: annotation
|
||||||
3
api/config/routes/api_platform.yaml
Normal file
3
api/config/routes/api_platform.yaml
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
api_platform:
|
||||||
|
resource: .
|
||||||
|
type: api_platform
|
||||||
3
api/config/routes/dev/twig.yaml
Normal file
3
api/config/routes/dev/twig.yaml
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
_errors:
|
||||||
|
resource: '@TwigBundle/Resources/config/routing/errors.xml'
|
||||||
|
prefix: /_error
|
||||||
7
api/config/routes/dev/web_profiler.yaml
Normal file
7
api/config/routes/dev/web_profiler.yaml
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
web_profiler_wdt:
|
||||||
|
resource: '@WebProfilerBundle/Resources/config/routing/wdt.xml'
|
||||||
|
prefix: /_wdt
|
||||||
|
|
||||||
|
web_profiler_profiler:
|
||||||
|
resource: '@WebProfilerBundle/Resources/config/routing/profiler.xml'
|
||||||
|
prefix: /_profiler
|
||||||
27
api/config/services.yaml
Normal file
27
api/config/services.yaml
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
# This file is the entry point to configure your own services.
|
||||||
|
# Files in the packages/ subdirectory configure your dependencies.
|
||||||
|
|
||||||
|
# Put parameters here that don't need to change on each machine where the app is deployed
|
||||||
|
# https://symfony.com/doc/current/best_practices/configuration.html#application-related-configuration
|
||||||
|
parameters:
|
||||||
|
|
||||||
|
services:
|
||||||
|
# default configuration for services in *this* file
|
||||||
|
_defaults:
|
||||||
|
autowire: true # Automatically injects dependencies in your services.
|
||||||
|
autoconfigure: true # Automatically registers your services as commands, event subscribers, etc.
|
||||||
|
|
||||||
|
# makes classes in src/ available to be used as services
|
||||||
|
# this creates a service per class whose id is the fully-qualified class name
|
||||||
|
App\:
|
||||||
|
resource: '../src/*'
|
||||||
|
exclude: '../src/{DependencyInjection,Entity,Migrations,Tests,Kernel.php}'
|
||||||
|
|
||||||
|
# controllers are imported separately to make sure services can be injected
|
||||||
|
# as action arguments even if you don't extend any base controller class
|
||||||
|
App\Controller\:
|
||||||
|
resource: '../src/Controller'
|
||||||
|
tags: ['controller.service_arguments']
|
||||||
|
|
||||||
|
# add more service definitions when explicit configuration is needed
|
||||||
|
# please note that last definitions always *replace* previous ones
|
||||||
38
api/docker/nginx/conf.d/default.conf
Normal file
38
api/docker/nginx/conf.d/default.conf
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
server {
|
||||||
|
root /srv/api/public;
|
||||||
|
|
||||||
|
location / {
|
||||||
|
# try to serve file directly, fallback to index.php
|
||||||
|
try_files $uri /index.php$is_args$args;
|
||||||
|
}
|
||||||
|
|
||||||
|
location ~ ^/index\.php(/|$) {
|
||||||
|
# Comment the next line and uncomment the next to enable dynamic resolution (incompatible with Kubernetes)
|
||||||
|
fastcgi_pass php:9000;
|
||||||
|
#resolver 127.0.0.11;
|
||||||
|
#set $upstream_host php;
|
||||||
|
#fastcgi_pass $upstream_host:9000;
|
||||||
|
|
||||||
|
fastcgi_split_path_info ^(.+\.php)(/.*)$;
|
||||||
|
include fastcgi_params;
|
||||||
|
# When you are using symlinks to link the document root to the
|
||||||
|
# current version of your application, you should pass the real
|
||||||
|
# application path instead of the path to the symlink to PHP
|
||||||
|
# FPM.
|
||||||
|
# Otherwise, PHP's OPcache may not properly detect changes to
|
||||||
|
# your PHP files (see https://github.com/zendtech/ZendOptimizerPlus/issues/126
|
||||||
|
# for more information).
|
||||||
|
fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
|
||||||
|
fastcgi_param DOCUMENT_ROOT $realpath_root;
|
||||||
|
# Prevents URIs that include the front controller. This will 404:
|
||||||
|
# http://domain.tld/index.php/some-path
|
||||||
|
# Remove the internal directive to allow URIs like this
|
||||||
|
internal;
|
||||||
|
}
|
||||||
|
|
||||||
|
# return 404 for all other php files not matching the front controller
|
||||||
|
# this prevents access to other php files you don't want to be accessible.
|
||||||
|
location ~ \.php$ {
|
||||||
|
return 404;
|
||||||
|
}
|
||||||
|
}
|
||||||
11
api/docker/php/conf.d/api-platform.ini
Normal file
11
api/docker/php/conf.d/api-platform.ini
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
apc.enable_cli = 1
|
||||||
|
date.timezone = UTC
|
||||||
|
session.auto_start = Off
|
||||||
|
short_open_tag = Off
|
||||||
|
|
||||||
|
# http://symfony.com/doc/current/performance.html
|
||||||
|
opcache.interned_strings_buffer = 16
|
||||||
|
opcache.max_accelerated_files = 20000
|
||||||
|
opcache.memory_consumption = 256
|
||||||
|
realpath_cache_size = 4096K
|
||||||
|
realpath_cache_ttl = 600
|
||||||
34
api/docker/php/docker-entrypoint.sh
Executable file
34
api/docker/php/docker-entrypoint.sh
Executable file
@@ -0,0 +1,34 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
set -e
|
||||||
|
|
||||||
|
# first arg is `-f` or `--some-option`
|
||||||
|
if [ "${1#-}" != "$1" ]; then
|
||||||
|
set -- php-fpm "$@"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "$1" = 'php-fpm' ] || [ "$1" = 'php' ] || [ "$1" = 'bin/console' ]; then
|
||||||
|
PHP_INI_RECOMMENDED="$PHP_INI_DIR/php.ini-production"
|
||||||
|
if [ "$APP_ENV" != 'prod' ]; then
|
||||||
|
PHP_INI_RECOMMENDED="$PHP_INI_DIR/php.ini-development"
|
||||||
|
fi
|
||||||
|
ln -sf "$PHP_INI_RECOMMENDED" "$PHP_INI_DIR/php.ini"
|
||||||
|
|
||||||
|
mkdir -p var/cache var/log
|
||||||
|
setfacl -R -m u:www-data:rwX -m u:"$(whoami)":rwX var
|
||||||
|
setfacl -dR -m u:www-data:rwX -m u:"$(whoami)":rwX var
|
||||||
|
|
||||||
|
if [ "$APP_ENV" != 'prod' ]; then
|
||||||
|
composer install --prefer-dist --no-progress --no-suggest --no-interaction
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Waiting for db to be ready..."
|
||||||
|
until bin/console doctrine:query:sql "SELECT 1" > /dev/null 2>&1; do
|
||||||
|
sleep 1
|
||||||
|
done
|
||||||
|
|
||||||
|
if [ "$APP_ENV" != 'prod' ]; then
|
||||||
|
bin/console doctrine:schema:update --force --no-interaction
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
exec docker-php-entrypoint "$@"
|
||||||
95
api/docker/varnish/conf/default.vcl
Normal file
95
api/docker/varnish/conf/default.vcl
Normal file
@@ -0,0 +1,95 @@
|
|||||||
|
vcl 4.0;
|
||||||
|
|
||||||
|
import std;
|
||||||
|
|
||||||
|
backend default {
|
||||||
|
.host = "api";
|
||||||
|
.port = "80";
|
||||||
|
# Health check
|
||||||
|
#.probe = {
|
||||||
|
# .url = "/";
|
||||||
|
# .timeout = 5s;
|
||||||
|
# .interval = 10s;
|
||||||
|
# .window = 5;
|
||||||
|
# .threshold = 3;
|
||||||
|
#}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Hosts allowed to send BAN requests
|
||||||
|
acl invalidators {
|
||||||
|
"localhost";
|
||||||
|
"php";
|
||||||
|
# local Kubernetes network
|
||||||
|
"10.0.0.0"/8;
|
||||||
|
"172.16.0.0"/12;
|
||||||
|
"192.168.0.0"/16;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub vcl_recv {
|
||||||
|
if (req.restarts > 0) {
|
||||||
|
set req.hash_always_miss = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Remove the "Forwarded" HTTP header if exists (security)
|
||||||
|
unset req.http.forwarded;
|
||||||
|
|
||||||
|
# To allow API Platform to ban by cache tags
|
||||||
|
if (req.method == "BAN") {
|
||||||
|
if (client.ip !~ invalidators) {
|
||||||
|
return (synth(405, "Not allowed"));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (req.http.ApiPlatform-Ban-Regex) {
|
||||||
|
ban("obj.http.Cache-Tags ~ " + req.http.ApiPlatform-Ban-Regex);
|
||||||
|
|
||||||
|
return (synth(200, "Ban added"));
|
||||||
|
}
|
||||||
|
|
||||||
|
return (synth(400, "ApiPlatform-Ban-Regex HTTP header must be set."));
|
||||||
|
}
|
||||||
|
|
||||||
|
# For health checks
|
||||||
|
if (req.method == "GET" && req.url == "/healthz") {
|
||||||
|
return (synth(200, "OK"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sub vcl_hit {
|
||||||
|
if (obj.ttl >= 0s) {
|
||||||
|
# A pure unadulterated hit, deliver it
|
||||||
|
return (deliver);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (std.healthy(req.backend_hint)) {
|
||||||
|
# The backend is healthy
|
||||||
|
# Fetch the object from the backend
|
||||||
|
return (restart);
|
||||||
|
}
|
||||||
|
|
||||||
|
# No fresh object and the backend is not healthy
|
||||||
|
if (obj.ttl + obj.grace > 0s) {
|
||||||
|
# Deliver graced object
|
||||||
|
# Automatically triggers a background fetch
|
||||||
|
return (deliver);
|
||||||
|
}
|
||||||
|
|
||||||
|
# No valid object to deliver
|
||||||
|
# No healthy backend to handle request
|
||||||
|
# Return error
|
||||||
|
return (synth(503, "API is down"));
|
||||||
|
}
|
||||||
|
|
||||||
|
sub vcl_deliver {
|
||||||
|
# Don't send cache tags related headers to the client
|
||||||
|
unset resp.http.url;
|
||||||
|
# Comment the following line to send the "Cache-Tags" header to the client (e.g. to use CloudFlare cache tags)
|
||||||
|
unset resp.http.Cache-Tags;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub vcl_backend_response {
|
||||||
|
# Ban lurker friendly header
|
||||||
|
set beresp.http.url = bereq.url;
|
||||||
|
|
||||||
|
# Add a grace in case the backend is down
|
||||||
|
set beresp.grace = 1h;
|
||||||
|
}
|
||||||
22
api/helm/api/.helmignore
Normal file
22
api/helm/api/.helmignore
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
# Patterns to ignore when building packages.
|
||||||
|
# This supports shell glob matching, relative path matching, and
|
||||||
|
# negation (prefixed with !). Only one pattern per line.
|
||||||
|
.DS_Store
|
||||||
|
# Common VCS dirs
|
||||||
|
.git/
|
||||||
|
.gitignore
|
||||||
|
.bzr/
|
||||||
|
.bzrignore
|
||||||
|
.hg/
|
||||||
|
.hgignore
|
||||||
|
.svn/
|
||||||
|
# Common backup files
|
||||||
|
*.swp
|
||||||
|
*.bak
|
||||||
|
*.tmp
|
||||||
|
*~
|
||||||
|
# Various IDEs
|
||||||
|
.project
|
||||||
|
.idea/
|
||||||
|
*.tmproj
|
||||||
|
.vscode/
|
||||||
7
api/helm/api/Chart.yaml
Normal file
7
api/helm/api/Chart.yaml
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
appVersion: 0.1.0
|
||||||
|
description: A Helm chart for an API Platform API
|
||||||
|
name: api
|
||||||
|
version: 0.1.0
|
||||||
|
home: https://api-platform.com
|
||||||
|
icon: https://api-platform.com/logo-250x250.png
|
||||||
9
api/helm/api/requirements.lock
Normal file
9
api/helm/api/requirements.lock
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
dependencies:
|
||||||
|
- name: postgresql
|
||||||
|
repository: https://kubernetes-charts.storage.googleapis.com/
|
||||||
|
version: 3.9.5
|
||||||
|
- name: mercure
|
||||||
|
repository: https://kubernetes-charts.storage.googleapis.com/
|
||||||
|
version: 1.0.0
|
||||||
|
digest: sha256:6466d376987cc08b70fe36945dd93474836aab05edc155955951bcb0774a0896
|
||||||
|
generated: 2019-03-26T18:14:32.4074+01:00
|
||||||
9
api/helm/api/requirements.yaml
Normal file
9
api/helm/api/requirements.yaml
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
dependencies:
|
||||||
|
- name: postgresql
|
||||||
|
version: ~3.9.0
|
||||||
|
repository: https://kubernetes-charts.storage.googleapis.com/
|
||||||
|
condition: postgresql.enabled
|
||||||
|
- name: mercure
|
||||||
|
version: ~1.0.0
|
||||||
|
repository: https://kubernetes-charts.storage.googleapis.com/
|
||||||
|
condition: mercure.enabled
|
||||||
5
api/helm/api/templates/NOTES.txt
Normal file
5
api/helm/api/templates/NOTES.txt
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
API deployed.
|
||||||
|
|
||||||
|
To get the ingress's IP:
|
||||||
|
|
||||||
|
kubectl --namespace {{ .Release.Namespace }} get ingress -o jsonpath="{.items[0].status.loadBalancer.ingress[0].ip}"
|
||||||
27
api/helm/api/templates/_helpers.tpl
Normal file
27
api/helm/api/templates/_helpers.tpl
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
{{/* vim: set filetype=mustache: */}}
|
||||||
|
{{/*
|
||||||
|
Expand the name of the chart.
|
||||||
|
*/}}
|
||||||
|
{{- define "name" -}}
|
||||||
|
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}}
|
||||||
|
{{- end -}}
|
||||||
|
|
||||||
|
{{/*
|
||||||
|
Create a default fully qualified app name.
|
||||||
|
We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).
|
||||||
|
*/}}
|
||||||
|
{{- define "fullname" -}}
|
||||||
|
{{- $name := default .Chart.Name .Values.nameOverride -}}
|
||||||
|
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}}
|
||||||
|
{{- end -}}
|
||||||
|
|
||||||
|
{{- define "postgresql.fullname" -}}
|
||||||
|
{{- printf "%s-%s" .Release.Name "postgresql" | trunc 63 | trimSuffix "-" -}}
|
||||||
|
{{- end -}}
|
||||||
|
|
||||||
|
{{/*
|
||||||
|
Create chart name and version as used by the chart label.
|
||||||
|
*/}}
|
||||||
|
{{- define "chart" -}}
|
||||||
|
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}}
|
||||||
|
{{- end -}}
|
||||||
19
api/helm/api/templates/configmap.yaml
Normal file
19
api/helm/api/templates/configmap.yaml
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: ConfigMap
|
||||||
|
metadata:
|
||||||
|
name: {{ template "fullname" . }}
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/name: {{ include "name" . }}
|
||||||
|
app.kubernetes.io/part-of: {{ include "name" . }}
|
||||||
|
helm.sh/chart: {{ include "chart" . }}
|
||||||
|
app.kubernetes.io/instance: {{ .Release.Name }}
|
||||||
|
app.kubernetes.io/managed-by: {{ .Release.Service }}
|
||||||
|
data:
|
||||||
|
env: {{ .Values.php.env | quote }}
|
||||||
|
debug: {{ .Values.php.debug | quote }}
|
||||||
|
cors-allow-origin: {{ .Values.php.corsAllowOrigin | quote }}
|
||||||
|
varnish-url: {{ if .Values.varnish.enabled }}http://varnish{{ else }}{{ .Values.varnish.url | quote }}{{ end }}
|
||||||
|
trusted-hosts: {{ .Values.php.trustedHosts | quote }}
|
||||||
|
trusted-proxies: {{ join "," .Values.php.trustedProxies }}
|
||||||
|
mercure-publish-url: {{ .Values.mercure.publishUrl | quote }}
|
||||||
|
mercure-subscribe-url: {{ .Values.mercure.subscribeUrl | quote }}
|
||||||
35
api/helm/api/templates/ingress.yaml
Normal file
35
api/helm/api/templates/ingress.yaml
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
apiVersion: extensions/v1beta1
|
||||||
|
kind: Ingress
|
||||||
|
metadata:
|
||||||
|
name: {{ template "fullname" . }}
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/name: {{ include "name" . }}-ingress
|
||||||
|
app.kubernetes.io/part-of: {{ include "name" . }}
|
||||||
|
helm.sh/chart: {{ include "chart" . }}
|
||||||
|
app.kubernetes.io/instance: {{ .Release.Name }}
|
||||||
|
app.kubernetes.io/managed-by: {{ .Release.Service }}
|
||||||
|
{{- with .Values.ingress.annotations }}
|
||||||
|
annotations:
|
||||||
|
{{- toYaml . | nindent 4 }}
|
||||||
|
{{- end }}
|
||||||
|
spec:
|
||||||
|
{{- if .Values.ingress.tls }}
|
||||||
|
tls:
|
||||||
|
{{- range .Values.ingress.tls }}
|
||||||
|
- hosts:
|
||||||
|
{{- range .hosts }}
|
||||||
|
- {{ .host | quote }}
|
||||||
|
{{- end }}
|
||||||
|
secretName: {{ .secretName }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
rules:
|
||||||
|
{{- range .Values.ingress.hosts }}
|
||||||
|
- host: {{ .host | quote }}
|
||||||
|
http:
|
||||||
|
paths:
|
||||||
|
- path: /*
|
||||||
|
backend:
|
||||||
|
serviceName: {{ .serviceName }}
|
||||||
|
servicePort: {{ .servicePort | default 80 }}
|
||||||
|
{{- end }}
|
||||||
33
api/helm/api/templates/nginx-deployment.yaml
Normal file
33
api/helm/api/templates/nginx-deployment.yaml
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
apiVersion: extensions/v1beta1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: {{ template "fullname" . }}-nginx
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/name: {{ include "name" . }}-nginx
|
||||||
|
app.kubernetes.io/part-of: {{ include "name" . }}
|
||||||
|
helm.sh/chart: {{ include "chart" . }}
|
||||||
|
app.kubernetes.io/instance: {{ .Release.Name }}
|
||||||
|
app.kubernetes.io/managed-by: {{ .Release.Service }}
|
||||||
|
spec:
|
||||||
|
replicas: {{ .Values.nginx.replicaCount }}
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/name: {{ include "name" . }}-nginx
|
||||||
|
app.kubernetes.io/part-of: {{ include "name" . }}
|
||||||
|
helm.sh/chart: {{ include "chart" . }}
|
||||||
|
app.kubernetes.io/instance: {{ .Release.Name }}
|
||||||
|
app.kubernetes.io/managed-by: {{ .Release.Service }}
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: {{ .Chart.Name }}-nginx
|
||||||
|
image: "{{ .Values.nginx.repository }}:{{ .Values.nginx.tag }}"
|
||||||
|
imagePullPolicy: {{ .Values.nginx.pullPolicy }}
|
||||||
|
ports:
|
||||||
|
- containerPort: 80
|
||||||
|
resources:
|
||||||
|
{{ toYaml .Values.resources | indent 12 }}
|
||||||
|
{{- if .Values.nodeSelector }}
|
||||||
|
nodeSelector:
|
||||||
|
{{ toYaml .Values.nodeSelector | indent 8 }}
|
||||||
|
{{- end }}
|
||||||
19
api/helm/api/templates/nginx-service.yaml
Normal file
19
api/helm/api/templates/nginx-service.yaml
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: api
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/name: {{ include "name" . }}-nginx
|
||||||
|
app.kubernetes.io/part-of: {{ include "name" . }}
|
||||||
|
helm.sh/chart: {{ include "chart" . }}
|
||||||
|
app.kubernetes.io/instance: {{ .Release.Name }}
|
||||||
|
app.kubernetes.io/managed-by: {{ .Release.Service }}
|
||||||
|
spec:
|
||||||
|
type: NodePort
|
||||||
|
ports:
|
||||||
|
- port: 80
|
||||||
|
targetPort: 80
|
||||||
|
protocol: TCP
|
||||||
|
selector:
|
||||||
|
app.kubernetes.io/name: {{ include "name" . }}-nginx
|
||||||
|
app.kubernetes.io/instance: {{ .Release.Name }}
|
||||||
89
api/helm/api/templates/php-deployment.yaml
Normal file
89
api/helm/api/templates/php-deployment.yaml
Normal file
@@ -0,0 +1,89 @@
|
|||||||
|
apiVersion: extensions/v1beta1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: {{ template "fullname" . }}-php
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/name: {{ include "name" . }}-php
|
||||||
|
app.kubernetes.io/part-of: {{ include "name" . }}
|
||||||
|
helm.sh/chart: {{ include "chart" . }}
|
||||||
|
app.kubernetes.io/instance: {{ .Release.Name }}
|
||||||
|
app.kubernetes.io/managed-by: {{ .Release.Service }}
|
||||||
|
spec:
|
||||||
|
replicas: {{ .Values.php.replicaCount }}
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/name: {{ include "name" . }}-php
|
||||||
|
app.kubernetes.io/part-of: {{ include "name" . }}
|
||||||
|
helm.sh/chart: {{ include "chart" . }}
|
||||||
|
app.kubernetes.io/instance: {{ .Release.Name }}
|
||||||
|
app.kubernetes.io/managed-by: {{ .Release.Service }}
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: {{ .Chart.Name }}-php
|
||||||
|
image: "{{ .Values.php.repository }}:{{ .Values.php.tag }}"
|
||||||
|
imagePullPolicy: {{ .Values.php.pullPolicy }}
|
||||||
|
ports:
|
||||||
|
- containerPort: 9000
|
||||||
|
env:
|
||||||
|
- name: TRUSTED_HOSTS
|
||||||
|
valueFrom:
|
||||||
|
configMapKeyRef:
|
||||||
|
name: {{ template "fullname" . }}
|
||||||
|
key: trusted-hosts
|
||||||
|
- name: TRUSTED_PROXIES
|
||||||
|
valueFrom:
|
||||||
|
configMapKeyRef:
|
||||||
|
name: {{ template "fullname" . }}
|
||||||
|
key: trusted-proxies
|
||||||
|
- name: APP_ENV
|
||||||
|
valueFrom:
|
||||||
|
configMapKeyRef:
|
||||||
|
name: {{ template "fullname" . }}
|
||||||
|
key: env
|
||||||
|
- name: APP_DEBUG
|
||||||
|
valueFrom:
|
||||||
|
configMapKeyRef:
|
||||||
|
name: {{ template "fullname" . }}
|
||||||
|
key: debug
|
||||||
|
- name: CORS_ALLOW_ORIGIN
|
||||||
|
valueFrom:
|
||||||
|
configMapKeyRef:
|
||||||
|
name: {{ template "fullname" . }}
|
||||||
|
key: cors-allow-origin
|
||||||
|
- name: VARNISH_URL
|
||||||
|
valueFrom:
|
||||||
|
configMapKeyRef:
|
||||||
|
name: {{ template "fullname" . }}
|
||||||
|
key: varnish-url
|
||||||
|
- name: APP_SECRET
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: {{ template "fullname" . }}
|
||||||
|
key: secret
|
||||||
|
- name: DATABASE_URL
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: {{ template "fullname" . }}
|
||||||
|
key: database-url
|
||||||
|
- name: MERCURE_PUBLISH_URL
|
||||||
|
valueFrom:
|
||||||
|
configMapKeyRef:
|
||||||
|
name: {{ template "fullname" . }}
|
||||||
|
key: mercure-publish-url
|
||||||
|
- name: MERCURE_SUBSCRIBE_URL
|
||||||
|
valueFrom:
|
||||||
|
configMapKeyRef:
|
||||||
|
name: {{ template "fullname" . }}
|
||||||
|
key: mercure-subscribe-url
|
||||||
|
- name: MERCURE_JWT_SECRET
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: {{ template "fullname" . }}
|
||||||
|
key: mercure-jwt-secret
|
||||||
|
resources:
|
||||||
|
{{ toYaml .Values.resources | indent 12 }}
|
||||||
|
{{- if .Values.nodeSelector }}
|
||||||
|
nodeSelector:
|
||||||
|
{{ toYaml .Values.nodeSelector | indent 8 }}
|
||||||
|
{{- end }}
|
||||||
17
api/helm/api/templates/php-service.yaml
Normal file
17
api/helm/api/templates/php-service.yaml
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: php
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/name: {{ include "name" . }}-php
|
||||||
|
app.kubernetes.io/part-of: {{ include "name" . }}
|
||||||
|
helm.sh/chart: {{ include "chart" . }}
|
||||||
|
app.kubernetes.io/instance: {{ .Release.Name }}
|
||||||
|
app.kubernetes.io/managed-by: {{ .Release.Service }}
|
||||||
|
spec:
|
||||||
|
type: ClusterIP
|
||||||
|
ports:
|
||||||
|
- port: 9000
|
||||||
|
selector:
|
||||||
|
app.kubernetes.io/name: {{ include "name" . }}-php
|
||||||
|
app.kubernetes.io/instance: {{ .Release.Name }}
|
||||||
20
api/helm/api/templates/secrets.yaml
Normal file
20
api/helm/api/templates/secrets.yaml
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
{{- $postgresqlServiceName := include "postgresql.fullname" . -}}
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Secret
|
||||||
|
metadata:
|
||||||
|
name: {{ template "fullname" . }}
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/name: {{ include "name" . }}
|
||||||
|
app.kubernetes.io/part-of: {{ include "name" . }}
|
||||||
|
helm.sh/chart: {{ include "chart" . }}
|
||||||
|
app.kubernetes.io/instance: {{ .Release.Name }}
|
||||||
|
app.kubernetes.io/managed-by: {{ .Release.Service }}
|
||||||
|
type: Opaque
|
||||||
|
data:
|
||||||
|
{{ if .Values.postgresql.enabled }}
|
||||||
|
database-url: {{ printf "pgsql://%s:%s@%s/%s?serverVersion=9.6" .Values.postgresql.postgresqlUsername .Values.postgresql.postgresqlPassword $postgresqlServiceName .Values.postgresql.postgresqlDatabase | b64enc | quote }}
|
||||||
|
{{ else }}
|
||||||
|
database-url: {{ .Values.postgresql.url | b64enc | quote }}
|
||||||
|
{{ end }}
|
||||||
|
secret: {{ .Values.php.secret | default (randAlphaNum 40) | b64enc | quote }}
|
||||||
|
mercure-jwt-secret: {{ .Values.php.mercure.jwtSecret | b64enc | quote }}
|
||||||
44
api/helm/api/templates/varnish-deployment.yaml
Normal file
44
api/helm/api/templates/varnish-deployment.yaml
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
{{- if .Values.varnish.enabled -}}
|
||||||
|
apiVersion: extensions/v1beta1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: {{ template "fullname" . }}-varnish
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/name: {{ include "name" . }}-varnish
|
||||||
|
app.kubernetes.io/part-of: {{ include "name" . }}
|
||||||
|
helm.sh/chart: {{ include "chart" . }}
|
||||||
|
app.kubernetes.io/instance: {{ .Release.Name }}
|
||||||
|
app.kubernetes.io/managed-by: {{ .Release.Service }}
|
||||||
|
spec:
|
||||||
|
replicas: {{ .Values.varnish.replicaCount }}
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/name: {{ include "name" . }}-varnish
|
||||||
|
helm.sh/chart: {{ include "chart" . }}
|
||||||
|
app.kubernetes.io/instance: {{ .Release.Name }}
|
||||||
|
app.kubernetes.io/managed-by: {{ .Release.Service }}
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: {{ .Chart.Name }}-varnish
|
||||||
|
image: "{{ .Values.varnish.repository }}:{{ .Values.varnish.tag }}"
|
||||||
|
imagePullPolicy: {{ .Values.varnish.pullPolicy }}
|
||||||
|
command: ["varnishd"]
|
||||||
|
args: ["-F", "-f", "/usr/local/etc/varnish/default.vcl", "-p", "http_resp_hdr_len=65536", "-p", "http_resp_size=98304"]
|
||||||
|
ports:
|
||||||
|
- containerPort: 80
|
||||||
|
livenessProbe:
|
||||||
|
httpGet:
|
||||||
|
path: /healthz
|
||||||
|
port: 80
|
||||||
|
readinessProbe:
|
||||||
|
httpGet:
|
||||||
|
path: /healthz
|
||||||
|
port: 80
|
||||||
|
resources:
|
||||||
|
{{ toYaml .Values.resources | indent 12 }}
|
||||||
|
{{- if .Values.nodeSelector }}
|
||||||
|
nodeSelector:
|
||||||
|
{{ toYaml .Values.nodeSelector | indent 8 }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end -}}
|
||||||
21
api/helm/api/templates/varnish-service.yaml
Normal file
21
api/helm/api/templates/varnish-service.yaml
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
{{- if .Values.varnish.enabled -}}
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: varnish
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/name: {{ include "name" . }}-varnish
|
||||||
|
app.kubernetes.io/part-of: {{ include "name" . }}
|
||||||
|
helm.sh/chart: {{ include "chart" . }}
|
||||||
|
app.kubernetes.io/instance: {{ .Release.Name }}
|
||||||
|
app.kubernetes.io/managed-by: {{ .Release.Service }}
|
||||||
|
spec:
|
||||||
|
type: NodePort
|
||||||
|
ports:
|
||||||
|
- port: 80
|
||||||
|
targetPort: 80
|
||||||
|
protocol: TCP
|
||||||
|
selector:
|
||||||
|
app.kubernetes.io/name: {{ include "name" . }}-varnish
|
||||||
|
app.kubernetes.io/instance: {{ .Release.Name }}
|
||||||
|
{{- end -}}
|
||||||
92
api/helm/api/values.yaml
Normal file
92
api/helm/api/values.yaml
Normal file
@@ -0,0 +1,92 @@
|
|||||||
|
# Default values for api.
|
||||||
|
# This is a YAML-formatted file.
|
||||||
|
# Declare variables to be passed into your templates.
|
||||||
|
|
||||||
|
php:
|
||||||
|
repository: quay.io/api-platform/php
|
||||||
|
tag: latest
|
||||||
|
pullPolicy: Always
|
||||||
|
replicaCount: 1
|
||||||
|
mercure:
|
||||||
|
jwtSecret: ""
|
||||||
|
env: prod
|
||||||
|
debug: '0'
|
||||||
|
secret: ""
|
||||||
|
corsAllowOrigin: "^https?://.*?\\.example\\.com$"
|
||||||
|
trustedHosts: "^.*\\.example\\.com$"
|
||||||
|
trustedProxies:
|
||||||
|
- 10.0.0.0/8
|
||||||
|
- 172.16.0.0/12
|
||||||
|
- 192.168.0.0/16
|
||||||
|
|
||||||
|
nginx:
|
||||||
|
repository: quay.io/api-platform/nginx
|
||||||
|
tag: latest
|
||||||
|
pullPolicy: Always
|
||||||
|
replicaCount: 1
|
||||||
|
|
||||||
|
varnish:
|
||||||
|
enabled: true
|
||||||
|
#url: https://example.com
|
||||||
|
repository: quay.io/api-platform/varnish
|
||||||
|
tag: latest
|
||||||
|
pullPolicy: Always
|
||||||
|
replicaCount: 1
|
||||||
|
|
||||||
|
postgresql:
|
||||||
|
enabled: true
|
||||||
|
imageTag: 10-alpine
|
||||||
|
# If bringing your own PostgreSQL, the full uri to use
|
||||||
|
#url: pgsql://api-platform:!ChangeMe!@example.com/api?serverVersion=10.1
|
||||||
|
postgresqlUsername: "example"
|
||||||
|
postgresqlPassword: "!ChangeMe!"
|
||||||
|
postgresqlDatabase: "api"
|
||||||
|
# Persistent Volume Storage configuration.
|
||||||
|
# ref: https://kubernetes.io/docs/user-guide/persistent-volumes
|
||||||
|
persistence:
|
||||||
|
enabled: false
|
||||||
|
pullPolicy: IfNotPresent
|
||||||
|
# image:
|
||||||
|
# repository: postgres
|
||||||
|
# tag: alpine
|
||||||
|
|
||||||
|
mercure:
|
||||||
|
enabled: true
|
||||||
|
publishUrl: http://mercure/hub
|
||||||
|
subscribeUrl: https://mercure.example.com/hub
|
||||||
|
allowAnonymous: "1"
|
||||||
|
corsAllowedOrigins: "^https?://.*?\\.example\\.com$"
|
||||||
|
acmeHosts: "" # TODO: Fix the Mercure chart
|
||||||
|
service:
|
||||||
|
type: NodePort
|
||||||
|
port: 80
|
||||||
|
|
||||||
|
ingress:
|
||||||
|
annotations:
|
||||||
|
# kubernetes.io/ingress.global-static-ip-name: chart-ip
|
||||||
|
# kubernetes.io/ingress.class: gce
|
||||||
|
# kubernetes.io/tls-acme: "true"
|
||||||
|
tls:
|
||||||
|
# Secrets must be manually created in the namespace, you can also use cert-manager.
|
||||||
|
# - hosts:
|
||||||
|
# - example.com
|
||||||
|
# - mercure.example.com
|
||||||
|
hosts:
|
||||||
|
api:
|
||||||
|
host: example.com
|
||||||
|
serviceName: varnish
|
||||||
|
mercure:
|
||||||
|
host: mercure.example.com
|
||||||
|
serviceName: mercure
|
||||||
|
|
||||||
|
resources: {}
|
||||||
|
# We usually recommend not to specify default resources and to leave this as a conscious
|
||||||
|
# choice for the user. This also increases chances charts run on environments with little
|
||||||
|
# resources, such as Minikube. If you do want to specify resources, uncomment the following
|
||||||
|
# lines, adjust them as necessary, and remove the curly braces after 'resources:'.
|
||||||
|
# limits:
|
||||||
|
# cpu: 100m
|
||||||
|
# memory: 128Mi
|
||||||
|
# requests:
|
||||||
|
# cpu: 100m
|
||||||
|
# memory: 128Mi
|
||||||
BIN
api/public/favicon.ico
Normal file
BIN
api/public/favicon.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 31 KiB |
27
api/public/index.php
Normal file
27
api/public/index.php
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use App\Kernel;
|
||||||
|
use Symfony\Component\Debug\Debug;
|
||||||
|
use Symfony\Component\HttpFoundation\Request;
|
||||||
|
|
||||||
|
require dirname(__DIR__).'/config/bootstrap.php';
|
||||||
|
|
||||||
|
if ($_SERVER['APP_DEBUG']) {
|
||||||
|
umask(0000);
|
||||||
|
|
||||||
|
Debug::enable();
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($trustedProxies = $_SERVER['TRUSTED_PROXIES'] ?? $_ENV['TRUSTED_PROXIES'] ?? false) {
|
||||||
|
Request::setTrustedProxies(explode(',', $trustedProxies), Request::HEADER_X_FORWARDED_ALL);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($trustedHosts = $_SERVER['TRUSTED_HOSTS'] ?? $_ENV['TRUSTED_HOSTS'] ?? false) {
|
||||||
|
Request::setTrustedHosts([$trustedHosts]);
|
||||||
|
}
|
||||||
|
|
||||||
|
$kernel = new Kernel($_SERVER['APP_ENV'], (bool) $_SERVER['APP_DEBUG']);
|
||||||
|
$request = Request::createFromGlobals();
|
||||||
|
$response = $kernel->handle($request);
|
||||||
|
$response->send();
|
||||||
|
$kernel->terminate($request, $response);
|
||||||
0
api/src/Controller/.gitignore
vendored
Normal file
0
api/src/Controller/.gitignore
vendored
Normal file
0
api/src/Entity/.gitignore
vendored
Normal file
0
api/src/Entity/.gitignore
vendored
Normal file
38
api/src/Entity/Greeting.php
Normal file
38
api/src/Entity/Greeting.php
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Entity;
|
||||||
|
|
||||||
|
use ApiPlatform\Core\Annotation\ApiResource;
|
||||||
|
use Doctrine\ORM\Mapping as ORM;
|
||||||
|
use Symfony\Component\Validator\Constraints as Assert;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is a dummy entity. Remove it!
|
||||||
|
*
|
||||||
|
* @ApiResource
|
||||||
|
* @ORM\Entity
|
||||||
|
*/
|
||||||
|
class Greeting
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var int The entity Id
|
||||||
|
*
|
||||||
|
* @ORM\Id
|
||||||
|
* @ORM\GeneratedValue
|
||||||
|
* @ORM\Column(type="integer")
|
||||||
|
*/
|
||||||
|
private $id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string A nice person
|
||||||
|
*
|
||||||
|
* @ORM\Column
|
||||||
|
* @Assert\NotBlank
|
||||||
|
*/
|
||||||
|
public $name = '';
|
||||||
|
|
||||||
|
public function getId(): int
|
||||||
|
{
|
||||||
|
return $this->id;
|
||||||
|
}
|
||||||
|
}
|
||||||
53
api/src/Kernel.php
Normal file
53
api/src/Kernel.php
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App;
|
||||||
|
|
||||||
|
use Symfony\Bundle\FrameworkBundle\Kernel\MicroKernelTrait;
|
||||||
|
use Symfony\Component\Config\Loader\LoaderInterface;
|
||||||
|
use Symfony\Component\Config\Resource\FileResource;
|
||||||
|
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||||
|
use Symfony\Component\HttpKernel\Kernel as BaseKernel;
|
||||||
|
use Symfony\Component\Routing\RouteCollectionBuilder;
|
||||||
|
|
||||||
|
class Kernel extends BaseKernel
|
||||||
|
{
|
||||||
|
use MicroKernelTrait;
|
||||||
|
|
||||||
|
private const CONFIG_EXTS = '.{php,xml,yaml,yml}';
|
||||||
|
|
||||||
|
public function registerBundles(): iterable
|
||||||
|
{
|
||||||
|
$contents = require $this->getProjectDir().'/config/bundles.php';
|
||||||
|
foreach ($contents as $class => $envs) {
|
||||||
|
if ($envs[$this->environment] ?? $envs['all'] ?? false) {
|
||||||
|
yield new $class();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getProjectDir(): string
|
||||||
|
{
|
||||||
|
return \dirname(__DIR__);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function configureContainer(ContainerBuilder $container, LoaderInterface $loader): void
|
||||||
|
{
|
||||||
|
$container->addResource(new FileResource($this->getProjectDir().'/config/bundles.php'));
|
||||||
|
$container->setParameter('container.dumper.inline_class_loader', true);
|
||||||
|
$confDir = $this->getProjectDir().'/config';
|
||||||
|
|
||||||
|
$loader->load($confDir.'/{packages}/*'.self::CONFIG_EXTS, 'glob');
|
||||||
|
$loader->load($confDir.'/{packages}/'.$this->environment.'/**/*'.self::CONFIG_EXTS, 'glob');
|
||||||
|
$loader->load($confDir.'/{services}'.self::CONFIG_EXTS, 'glob');
|
||||||
|
$loader->load($confDir.'/{services}_'.$this->environment.self::CONFIG_EXTS, 'glob');
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function configureRoutes(RouteCollectionBuilder $routes): void
|
||||||
|
{
|
||||||
|
$confDir = $this->getProjectDir().'/config';
|
||||||
|
|
||||||
|
$routes->import($confDir.'/{routes}/'.$this->environment.'/**/*'.self::CONFIG_EXTS, '/', 'glob');
|
||||||
|
$routes->import($confDir.'/{routes}/*'.self::CONFIG_EXTS, '/', 'glob');
|
||||||
|
$routes->import($confDir.'/{routes}'.self::CONFIG_EXTS, '/', 'glob');
|
||||||
|
}
|
||||||
|
}
|
||||||
0
api/src/Repository/.gitignore
vendored
Normal file
0
api/src/Repository/.gitignore
vendored
Normal file
425
api/symfony.lock
Normal file
425
api/symfony.lock
Normal file
@@ -0,0 +1,425 @@
|
|||||||
|
{
|
||||||
|
"api-platform/api-pack": {
|
||||||
|
"version": "v1.2.0"
|
||||||
|
},
|
||||||
|
"api-platform/core": {
|
||||||
|
"version": "2.1",
|
||||||
|
"recipe": {
|
||||||
|
"repo": "github.com/symfony/recipes",
|
||||||
|
"branch": "master",
|
||||||
|
"version": "2.1",
|
||||||
|
"ref": "18727d8f229306860b46955f438e1897421da689"
|
||||||
|
},
|
||||||
|
"files": [
|
||||||
|
"config/packages/api_platform.yaml",
|
||||||
|
"config/routes/api_platform.yaml",
|
||||||
|
"src/Entity/.gitignore"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"api-platform/schema-generator": {
|
||||||
|
"version": "v2.1.0"
|
||||||
|
},
|
||||||
|
"composer/semver": {
|
||||||
|
"version": "1.5.0"
|
||||||
|
},
|
||||||
|
"composer/xdebug-handler": {
|
||||||
|
"version": "1.3.3"
|
||||||
|
},
|
||||||
|
"doctrine/annotations": {
|
||||||
|
"version": "1.0",
|
||||||
|
"recipe": {
|
||||||
|
"repo": "github.com/symfony/recipes",
|
||||||
|
"branch": "master",
|
||||||
|
"version": "1.0",
|
||||||
|
"ref": "cb4152ebcadbe620ea2261da1a1c5a9b8cea7672"
|
||||||
|
},
|
||||||
|
"files": [
|
||||||
|
"config/routes/annotations.yaml"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"doctrine/cache": {
|
||||||
|
"version": "v1.8.0"
|
||||||
|
},
|
||||||
|
"doctrine/collections": {
|
||||||
|
"version": "v1.6.2"
|
||||||
|
},
|
||||||
|
"doctrine/common": {
|
||||||
|
"version": "v2.10.0"
|
||||||
|
},
|
||||||
|
"doctrine/dbal": {
|
||||||
|
"version": "v2.9.2"
|
||||||
|
},
|
||||||
|
"doctrine/doctrine-bundle": {
|
||||||
|
"version": "1.6",
|
||||||
|
"recipe": {
|
||||||
|
"repo": "github.com/symfony/recipes",
|
||||||
|
"branch": "master",
|
||||||
|
"version": "1.6",
|
||||||
|
"ref": "02bc9e7994b70f4fda004131a0c78b7b1bf09789"
|
||||||
|
},
|
||||||
|
"files": [
|
||||||
|
"config/packages/doctrine.yaml",
|
||||||
|
"config/packages/prod/doctrine.yaml",
|
||||||
|
"src/Entity/.gitignore",
|
||||||
|
"src/Repository/.gitignore"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"doctrine/doctrine-cache-bundle": {
|
||||||
|
"version": "1.3.5"
|
||||||
|
},
|
||||||
|
"doctrine/event-manager": {
|
||||||
|
"version": "v1.0.0"
|
||||||
|
},
|
||||||
|
"doctrine/inflector": {
|
||||||
|
"version": "v1.3.0"
|
||||||
|
},
|
||||||
|
"doctrine/instantiator": {
|
||||||
|
"version": "1.2.0"
|
||||||
|
},
|
||||||
|
"doctrine/lexer": {
|
||||||
|
"version": "1.0.2"
|
||||||
|
},
|
||||||
|
"doctrine/orm": {
|
||||||
|
"version": "v2.6.3"
|
||||||
|
},
|
||||||
|
"doctrine/persistence": {
|
||||||
|
"version": "1.1.1"
|
||||||
|
},
|
||||||
|
"doctrine/reflection": {
|
||||||
|
"version": "v1.0.0"
|
||||||
|
},
|
||||||
|
"easyrdf/easyrdf": {
|
||||||
|
"version": "0.9.1"
|
||||||
|
},
|
||||||
|
"fig/link-util": {
|
||||||
|
"version": "1.0.0"
|
||||||
|
},
|
||||||
|
"friendsofphp/php-cs-fixer": {
|
||||||
|
"version": "2.2",
|
||||||
|
"recipe": {
|
||||||
|
"repo": "github.com/symfony/recipes",
|
||||||
|
"branch": "master",
|
||||||
|
"version": "2.2",
|
||||||
|
"ref": "cc05ab6abf6894bddb9bbd6a252459010ebe040b"
|
||||||
|
},
|
||||||
|
"files": [
|
||||||
|
".php_cs.dist"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"guzzlehttp/guzzle": {
|
||||||
|
"version": "6.3.3"
|
||||||
|
},
|
||||||
|
"guzzlehttp/promises": {
|
||||||
|
"version": "v1.3.1"
|
||||||
|
},
|
||||||
|
"guzzlehttp/psr7": {
|
||||||
|
"version": "1.5.2"
|
||||||
|
},
|
||||||
|
"jdorn/sql-formatter": {
|
||||||
|
"version": "v1.2.17"
|
||||||
|
},
|
||||||
|
"league/html-to-markdown": {
|
||||||
|
"version": "4.8.1"
|
||||||
|
},
|
||||||
|
"nelmio/cors-bundle": {
|
||||||
|
"version": "1.5",
|
||||||
|
"recipe": {
|
||||||
|
"repo": "github.com/symfony/recipes",
|
||||||
|
"branch": "master",
|
||||||
|
"version": "1.5",
|
||||||
|
"ref": "f0436fc35fca88eada758311f8de43bfb61f1980"
|
||||||
|
},
|
||||||
|
"files": [
|
||||||
|
"config/packages/nelmio_cors.yaml"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"nikic/php-parser": {
|
||||||
|
"version": "v4.2.2"
|
||||||
|
},
|
||||||
|
"php-cs-fixer/diff": {
|
||||||
|
"version": "v1.3.0"
|
||||||
|
},
|
||||||
|
"phpdocumentor/reflection-common": {
|
||||||
|
"version": "1.0.1"
|
||||||
|
},
|
||||||
|
"phpdocumentor/reflection-docblock": {
|
||||||
|
"version": "4.3.1"
|
||||||
|
},
|
||||||
|
"phpdocumentor/type-resolver": {
|
||||||
|
"version": "0.4.0"
|
||||||
|
},
|
||||||
|
"psr/cache": {
|
||||||
|
"version": "1.0.1"
|
||||||
|
},
|
||||||
|
"psr/container": {
|
||||||
|
"version": "1.0.0"
|
||||||
|
},
|
||||||
|
"psr/http-message": {
|
||||||
|
"version": "1.0.1"
|
||||||
|
},
|
||||||
|
"psr/link": {
|
||||||
|
"version": "1.0.0"
|
||||||
|
},
|
||||||
|
"psr/log": {
|
||||||
|
"version": "1.1.0"
|
||||||
|
},
|
||||||
|
"ralouphie/getallheaders": {
|
||||||
|
"version": "2.0.5"
|
||||||
|
},
|
||||||
|
"symfony/asset": {
|
||||||
|
"version": "v4.3.1"
|
||||||
|
},
|
||||||
|
"symfony/cache": {
|
||||||
|
"version": "v4.3.1"
|
||||||
|
},
|
||||||
|
"symfony/config": {
|
||||||
|
"version": "v4.3.1"
|
||||||
|
},
|
||||||
|
"symfony/console": {
|
||||||
|
"version": "3.3",
|
||||||
|
"recipe": {
|
||||||
|
"repo": "github.com/symfony/recipes",
|
||||||
|
"branch": "master",
|
||||||
|
"version": "3.3",
|
||||||
|
"ref": "482d233eb8de91ebd042992077bbd5838858890c"
|
||||||
|
},
|
||||||
|
"files": [
|
||||||
|
"bin/console",
|
||||||
|
"config/bootstrap.php"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"symfony/contracts": {
|
||||||
|
"version": "v1.1.3"
|
||||||
|
},
|
||||||
|
"symfony/debug": {
|
||||||
|
"version": "v4.3.1"
|
||||||
|
},
|
||||||
|
"symfony/dependency-injection": {
|
||||||
|
"version": "v4.3.1"
|
||||||
|
},
|
||||||
|
"symfony/doctrine-bridge": {
|
||||||
|
"version": "v4.3.1"
|
||||||
|
},
|
||||||
|
"symfony/dotenv": {
|
||||||
|
"version": "v4.3.1"
|
||||||
|
},
|
||||||
|
"symfony/event-dispatcher": {
|
||||||
|
"version": "v4.3.1"
|
||||||
|
},
|
||||||
|
"symfony/expression-language": {
|
||||||
|
"version": "v4.3.1"
|
||||||
|
},
|
||||||
|
"symfony/filesystem": {
|
||||||
|
"version": "v4.3.1"
|
||||||
|
},
|
||||||
|
"symfony/finder": {
|
||||||
|
"version": "v4.3.1"
|
||||||
|
},
|
||||||
|
"symfony/flex": {
|
||||||
|
"version": "1.0",
|
||||||
|
"recipe": {
|
||||||
|
"repo": "github.com/symfony/recipes",
|
||||||
|
"branch": "master",
|
||||||
|
"version": "1.0",
|
||||||
|
"ref": "dc3fc2e0334a4137c47cfd5a3ececc601fa61a0b"
|
||||||
|
},
|
||||||
|
"files": [
|
||||||
|
".env"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"symfony/framework-bundle": {
|
||||||
|
"version": "4.2",
|
||||||
|
"recipe": {
|
||||||
|
"repo": "github.com/symfony/recipes",
|
||||||
|
"branch": "master",
|
||||||
|
"version": "4.2",
|
||||||
|
"ref": "0dfae0b1cd8349ae47659b35602f772b4a7e2280"
|
||||||
|
},
|
||||||
|
"files": [
|
||||||
|
"config/bootstrap.php",
|
||||||
|
"config/packages/cache.yaml",
|
||||||
|
"config/packages/framework.yaml",
|
||||||
|
"config/packages/test/framework.yaml",
|
||||||
|
"config/services.yaml",
|
||||||
|
"public/index.php",
|
||||||
|
"src/Controller/.gitignore",
|
||||||
|
"src/Kernel.php"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"symfony/http-client": {
|
||||||
|
"version": "v4.3.1"
|
||||||
|
},
|
||||||
|
"symfony/http-foundation": {
|
||||||
|
"version": "v4.3.1"
|
||||||
|
},
|
||||||
|
"symfony/http-kernel": {
|
||||||
|
"version": "v4.3.1"
|
||||||
|
},
|
||||||
|
"symfony/inflector": {
|
||||||
|
"version": "v4.3.1"
|
||||||
|
},
|
||||||
|
"symfony/maker-bundle": {
|
||||||
|
"version": "1.0",
|
||||||
|
"recipe": {
|
||||||
|
"repo": "github.com/symfony/recipes",
|
||||||
|
"branch": "master",
|
||||||
|
"version": "1.0",
|
||||||
|
"ref": "fadbfe33303a76e25cb63401050439aa9b1a9c7f"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"symfony/mercure": {
|
||||||
|
"version": "v0.2.0"
|
||||||
|
},
|
||||||
|
"symfony/mercure-bundle": {
|
||||||
|
"version": "0.1",
|
||||||
|
"recipe": {
|
||||||
|
"repo": "github.com/symfony/recipes",
|
||||||
|
"branch": "master",
|
||||||
|
"version": "0.1",
|
||||||
|
"ref": "c78ab1f56e700004fc5cd675c26b3c1c26be281d"
|
||||||
|
},
|
||||||
|
"files": [
|
||||||
|
"config/packages/mercure.yaml"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"symfony/mime": {
|
||||||
|
"version": "v4.3.1"
|
||||||
|
},
|
||||||
|
"symfony/options-resolver": {
|
||||||
|
"version": "v4.3.1"
|
||||||
|
},
|
||||||
|
"symfony/polyfill-intl-idn": {
|
||||||
|
"version": "v1.11.0"
|
||||||
|
},
|
||||||
|
"symfony/polyfill-mbstring": {
|
||||||
|
"version": "v1.11.0"
|
||||||
|
},
|
||||||
|
"symfony/polyfill-php72": {
|
||||||
|
"version": "v1.11.0"
|
||||||
|
},
|
||||||
|
"symfony/polyfill-php73": {
|
||||||
|
"version": "v1.11.0"
|
||||||
|
},
|
||||||
|
"symfony/process": {
|
||||||
|
"version": "v4.3.1"
|
||||||
|
},
|
||||||
|
"symfony/profiler-pack": {
|
||||||
|
"version": "v1.0.4"
|
||||||
|
},
|
||||||
|
"symfony/property-access": {
|
||||||
|
"version": "v4.3.1"
|
||||||
|
},
|
||||||
|
"symfony/property-info": {
|
||||||
|
"version": "v4.3.1"
|
||||||
|
},
|
||||||
|
"symfony/routing": {
|
||||||
|
"version": "4.2",
|
||||||
|
"recipe": {
|
||||||
|
"repo": "github.com/symfony/recipes",
|
||||||
|
"branch": "master",
|
||||||
|
"version": "4.2",
|
||||||
|
"ref": "5374e24d508ba8fd6ba9eb15170255fdb778316a"
|
||||||
|
},
|
||||||
|
"files": [
|
||||||
|
"config/packages/dev/routing.yaml",
|
||||||
|
"config/packages/routing.yaml",
|
||||||
|
"config/packages/test/routing.yaml",
|
||||||
|
"config/routes.yaml"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"symfony/security-bundle": {
|
||||||
|
"version": "3.3",
|
||||||
|
"recipe": {
|
||||||
|
"repo": "github.com/symfony/recipes",
|
||||||
|
"branch": "master",
|
||||||
|
"version": "3.3",
|
||||||
|
"ref": "9a2034eca6d83d9cda632014e06995b8d9d9fd09"
|
||||||
|
},
|
||||||
|
"files": [
|
||||||
|
"config/packages/security.yaml"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"symfony/security-core": {
|
||||||
|
"version": "v4.3.1"
|
||||||
|
},
|
||||||
|
"symfony/security-csrf": {
|
||||||
|
"version": "v4.3.1"
|
||||||
|
},
|
||||||
|
"symfony/security-guard": {
|
||||||
|
"version": "v4.3.1"
|
||||||
|
},
|
||||||
|
"symfony/security-http": {
|
||||||
|
"version": "v4.3.1"
|
||||||
|
},
|
||||||
|
"symfony/serializer": {
|
||||||
|
"version": "v4.3.1"
|
||||||
|
},
|
||||||
|
"symfony/stopwatch": {
|
||||||
|
"version": "v4.3.1"
|
||||||
|
},
|
||||||
|
"symfony/twig-bridge": {
|
||||||
|
"version": "v4.3.1"
|
||||||
|
},
|
||||||
|
"symfony/twig-bundle": {
|
||||||
|
"version": "3.3",
|
||||||
|
"recipe": {
|
||||||
|
"repo": "github.com/symfony/recipes",
|
||||||
|
"branch": "master",
|
||||||
|
"version": "3.3",
|
||||||
|
"ref": "369b5b29dc52b2c190002825ae7ec24ab6f962dd"
|
||||||
|
},
|
||||||
|
"files": [
|
||||||
|
"config/packages/twig.yaml",
|
||||||
|
"config/routes/dev/twig.yaml",
|
||||||
|
"templates/base.html.twig"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"symfony/validator": {
|
||||||
|
"version": "4.3",
|
||||||
|
"recipe": {
|
||||||
|
"repo": "github.com/symfony/recipes",
|
||||||
|
"branch": "master",
|
||||||
|
"version": "4.3",
|
||||||
|
"ref": "d902da3e4952f18d3bf05aab29512eb61cabd869"
|
||||||
|
},
|
||||||
|
"files": [
|
||||||
|
"config/packages/test/validator.yaml",
|
||||||
|
"config/packages/validator.yaml"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"symfony/var-dumper": {
|
||||||
|
"version": "v4.3.1"
|
||||||
|
},
|
||||||
|
"symfony/var-exporter": {
|
||||||
|
"version": "v4.3.1"
|
||||||
|
},
|
||||||
|
"symfony/web-link": {
|
||||||
|
"version": "v4.3.1"
|
||||||
|
},
|
||||||
|
"symfony/web-profiler-bundle": {
|
||||||
|
"version": "3.3",
|
||||||
|
"recipe": {
|
||||||
|
"repo": "github.com/symfony/recipes",
|
||||||
|
"branch": "master",
|
||||||
|
"version": "3.3",
|
||||||
|
"ref": "6bdfa1a95f6b2e677ab985cd1af2eae35d62e0f6"
|
||||||
|
},
|
||||||
|
"files": [
|
||||||
|
"config/packages/dev/web_profiler.yaml",
|
||||||
|
"config/packages/test/web_profiler.yaml",
|
||||||
|
"config/routes/dev/web_profiler.yaml"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"symfony/yaml": {
|
||||||
|
"version": "v4.3.1"
|
||||||
|
},
|
||||||
|
"twig/twig": {
|
||||||
|
"version": "v2.11.3"
|
||||||
|
},
|
||||||
|
"webmozart/assert": {
|
||||||
|
"version": "1.4.0"
|
||||||
|
},
|
||||||
|
"willdurand/negotiation": {
|
||||||
|
"version": "v2.3.1"
|
||||||
|
}
|
||||||
|
}
|
||||||
12
api/templates/base.html.twig
Normal file
12
api/templates/base.html.twig
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<title>{% block title %}Welcome!{% endblock %}</title>
|
||||||
|
{% block stylesheets %}{% endblock %}
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
{% block body %}{% endblock %}
|
||||||
|
{% block javascripts %}{% endblock %}
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
14
client/.dockerignore
Normal file
14
client/.dockerignore
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
**/*.log
|
||||||
|
**/*.md
|
||||||
|
**/._*
|
||||||
|
**/.dockerignore
|
||||||
|
**/.DS_Store
|
||||||
|
**/.git/
|
||||||
|
**/.gitattributes
|
||||||
|
**/.gitignore
|
||||||
|
**/.gitmodules
|
||||||
|
**/Dockerfile*
|
||||||
|
**/Thumbs.db
|
||||||
|
.env*
|
||||||
|
build/
|
||||||
|
node_modules/
|
||||||
3
client/.env
Normal file
3
client/.env
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
REACT_APP_API_ENTRYPOINT=https://localhost:8443
|
||||||
|
API_PLATFORM_CLIENT_GENERATOR_ENTRYPOINT=http://api
|
||||||
|
API_PLATFORM_CLIENT_GENERATOR_OUTPUT=src
|
||||||
20
client/.gitignore
vendored
Normal file
20
client/.gitignore
vendored
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
# See https://help.github.com/ignore-files/ for more about ignoring files.
|
||||||
|
|
||||||
|
# dependencies
|
||||||
|
/node_modules
|
||||||
|
|
||||||
|
# testing
|
||||||
|
/coverage
|
||||||
|
|
||||||
|
# production
|
||||||
|
/build
|
||||||
|
|
||||||
|
# misc
|
||||||
|
.env.local
|
||||||
|
.env.development.local
|
||||||
|
.env.test.local
|
||||||
|
.env.production.local
|
||||||
|
|
||||||
|
npm-debug.log*
|
||||||
|
yarn-debug.log*
|
||||||
|
yarn-error.log*
|
||||||
15
client/Dockerfile
Normal file
15
client/Dockerfile
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
FROM node:11.5-alpine
|
||||||
|
|
||||||
|
RUN mkdir -p /usr/src/client
|
||||||
|
|
||||||
|
WORKDIR /usr/src/client
|
||||||
|
|
||||||
|
RUN yarn global add @api-platform/client-generator
|
||||||
|
|
||||||
|
# Prevent the reinstallation of node modules at every changes in the source code
|
||||||
|
COPY package.json yarn.lock ./
|
||||||
|
RUN yarn install
|
||||||
|
|
||||||
|
COPY . ./
|
||||||
|
|
||||||
|
CMD yarn start
|
||||||
36
client/package.json
Normal file
36
client/package.json
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
{
|
||||||
|
"name": "client",
|
||||||
|
"version": "0.1.0",
|
||||||
|
"private": true,
|
||||||
|
"dependencies": {
|
||||||
|
"bootstrap": "^4.1.3",
|
||||||
|
"connected-react-router": "^5.0.1",
|
||||||
|
"font-awesome": "^4.7.0",
|
||||||
|
"jest-junit": "^5.2.0",
|
||||||
|
"lodash.get": "^4.4.2",
|
||||||
|
"lodash.has": "^4.5.2",
|
||||||
|
"lodash.mapvalues": "^4.6.0",
|
||||||
|
"prettier": "^1.14.3",
|
||||||
|
"prop-types": "^15.6.2",
|
||||||
|
"react": "^16.6.0",
|
||||||
|
"react-dom": "^16.6.0",
|
||||||
|
"react-redux": "^5.1.0",
|
||||||
|
"react-router-dom": "^4.3.1",
|
||||||
|
"react-scripts": "^2.1.1",
|
||||||
|
"redux": "^4.0.1",
|
||||||
|
"redux-form": "^7.4.2",
|
||||||
|
"redux-thunk": "^2.3.0"
|
||||||
|
},
|
||||||
|
"scripts": {
|
||||||
|
"start": "react-scripts start",
|
||||||
|
"build": "react-scripts build",
|
||||||
|
"test": "react-scripts test",
|
||||||
|
"eject": "react-scripts eject"
|
||||||
|
},
|
||||||
|
"browserslist": [
|
||||||
|
">0.2%",
|
||||||
|
"not dead",
|
||||||
|
"not ie <= 11",
|
||||||
|
"not op_mini all"
|
||||||
|
]
|
||||||
|
}
|
||||||
BIN
client/public/favicon.ico
Normal file
BIN
client/public/favicon.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 31 KiB |
40
client/public/index.html
Normal file
40
client/public/index.html
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||||
|
<meta name="theme-color" content="#000000">
|
||||||
|
<!--
|
||||||
|
manifest.json provides metadata used when your web app is added to the
|
||||||
|
homescreen on Android. See https://developers.google.com/web/fundamentals/engage-and-retain/web-app-manifest/
|
||||||
|
-->
|
||||||
|
<link rel="manifest" href="%PUBLIC_URL%/manifest.json">
|
||||||
|
<link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico">
|
||||||
|
<!--
|
||||||
|
Notice the use of %PUBLIC_URL% in the tags above.
|
||||||
|
It will be replaced with the URL of the `public` folder during the build.
|
||||||
|
Only files inside the `public` folder can be referenced from the HTML.
|
||||||
|
|
||||||
|
Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
|
||||||
|
work correctly both with client-side routing and a non-root public URL.
|
||||||
|
Learn how to configure a non-root public URL by running `npm run build`.
|
||||||
|
-->
|
||||||
|
<title>Welcome to API Platform</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<noscript>
|
||||||
|
You need to enable JavaScript to run this app.
|
||||||
|
</noscript>
|
||||||
|
<div id="root"></div>
|
||||||
|
<!--
|
||||||
|
This HTML file is a template.
|
||||||
|
If you open it directly in the browser, you will see an empty page.
|
||||||
|
|
||||||
|
You can add webfonts, meta tags, or analytics to this file.
|
||||||
|
The build step will place the bundled scripts into the <body> tag.
|
||||||
|
|
||||||
|
To begin the development, run `npm start` or `yarn start`.
|
||||||
|
To create a production bundle, use `npm run build` or `yarn build`.
|
||||||
|
-->
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
15
client/public/manifest.json
Normal file
15
client/public/manifest.json
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
{
|
||||||
|
"short_name": "API Platform",
|
||||||
|
"name": "Client",
|
||||||
|
"icons": [
|
||||||
|
{
|
||||||
|
"src": "favicon.ico",
|
||||||
|
"sizes": "192x192",
|
||||||
|
"type": "image/png"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"start_url": "./index.html",
|
||||||
|
"display": "standalone",
|
||||||
|
"theme_color": "#000000",
|
||||||
|
"background_color": "#ffffff"
|
||||||
|
}
|
||||||
1801
client/src/Welcome.js
Normal file
1801
client/src/Welcome.js
Normal file
File diff suppressed because it is too large
Load Diff
1
client/src/config/entrypoint.js
Normal file
1
client/src/config/entrypoint.js
Normal file
@@ -0,0 +1 @@
|
|||||||
|
export const ENTRYPOINT = process.env.REACT_APP_API_ENTRYPOINT;
|
||||||
46
client/src/index.js
Normal file
46
client/src/index.js
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import ReactDOM from 'react-dom';
|
||||||
|
import { createStore, combineReducers, applyMiddleware } from 'redux';
|
||||||
|
import { Provider } from 'react-redux';
|
||||||
|
import thunk from 'redux-thunk';
|
||||||
|
import { reducer as form } from 'redux-form';
|
||||||
|
import { Route, Switch } from 'react-router-dom';
|
||||||
|
import createBrowserHistory from 'history/createBrowserHistory';
|
||||||
|
import {
|
||||||
|
ConnectedRouter,
|
||||||
|
connectRouter,
|
||||||
|
routerMiddleware
|
||||||
|
} from 'connected-react-router';
|
||||||
|
import 'bootstrap/dist/css/bootstrap.css';
|
||||||
|
import 'font-awesome/css/font-awesome.css';
|
||||||
|
import * as serviceWorker from './serviceWorker';
|
||||||
|
// Import your reducers and routes here
|
||||||
|
import Welcome from './Welcome';
|
||||||
|
|
||||||
|
const history = createBrowserHistory();
|
||||||
|
const store = createStore(
|
||||||
|
combineReducers({
|
||||||
|
router: connectRouter(history),
|
||||||
|
form,
|
||||||
|
/* Add your reducers here */
|
||||||
|
}),
|
||||||
|
applyMiddleware(routerMiddleware(history), thunk)
|
||||||
|
);
|
||||||
|
|
||||||
|
ReactDOM.render(
|
||||||
|
<Provider store={store}>
|
||||||
|
<ConnectedRouter history={history}>
|
||||||
|
<Switch>
|
||||||
|
<Route path="/" component={Welcome} strict={true} exact={true}/>
|
||||||
|
{/* Add your routes here */}
|
||||||
|
<Route render={() => <h1>Not Found</h1>} />
|
||||||
|
</Switch>
|
||||||
|
</ConnectedRouter>
|
||||||
|
</Provider>,
|
||||||
|
document.getElementById('root')
|
||||||
|
);
|
||||||
|
|
||||||
|
// If you want your app to work offline and load faster, you can change
|
||||||
|
// unregister() to register() below. Note this comes with some pitfalls.
|
||||||
|
// Learn more about service workers: http://bit.ly/CRA-PWA
|
||||||
|
serviceWorker.unregister();
|
||||||
135
client/src/serviceWorker.js
Normal file
135
client/src/serviceWorker.js
Normal file
@@ -0,0 +1,135 @@
|
|||||||
|
// This optional code is used to register a service worker.
|
||||||
|
// register() is not called by default.
|
||||||
|
|
||||||
|
// This lets the app load faster on subsequent visits in production, and gives
|
||||||
|
// it offline capabilities. However, it also means that developers (and users)
|
||||||
|
// will only see deployed updates on subsequent visits to a page, after all the
|
||||||
|
// existing tabs open on the page have been closed, since previously cached
|
||||||
|
// resources are updated in the background.
|
||||||
|
|
||||||
|
// To learn more about the benefits of this model and instructions on how to
|
||||||
|
// opt-in, read http://bit.ly/CRA-PWA
|
||||||
|
|
||||||
|
const isLocalhost = Boolean(
|
||||||
|
window.location.hostname === 'localhost' ||
|
||||||
|
// [::1] is the IPv6 localhost address.
|
||||||
|
window.location.hostname === '[::1]' ||
|
||||||
|
// 127.0.0.1/8 is considered localhost for IPv4.
|
||||||
|
window.location.hostname.match(
|
||||||
|
/^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
export function register(config) {
|
||||||
|
if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) {
|
||||||
|
// The URL constructor is available in all browsers that support SW.
|
||||||
|
const publicUrl = new URL(process.env.PUBLIC_URL, window.location.href);
|
||||||
|
if (publicUrl.origin !== window.location.origin) {
|
||||||
|
// Our service worker won't work if PUBLIC_URL is on a different origin
|
||||||
|
// from what our page is served on. This might happen if a CDN is used to
|
||||||
|
// serve assets; see https://github.com/facebook/create-react-app/issues/2374
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
window.addEventListener('load', () => {
|
||||||
|
const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`;
|
||||||
|
|
||||||
|
if (isLocalhost) {
|
||||||
|
// This is running on localhost. Let's check if a service worker still exists or not.
|
||||||
|
checkValidServiceWorker(swUrl, config);
|
||||||
|
|
||||||
|
// Add some additional logging to localhost, pointing developers to the
|
||||||
|
// service worker/PWA documentation.
|
||||||
|
navigator.serviceWorker.ready.then(() => {
|
||||||
|
console.log(
|
||||||
|
'This web app is being served cache-first by a service ' +
|
||||||
|
'worker. To learn more, visit http://bit.ly/CRA-PWA'
|
||||||
|
);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
// Is not localhost. Just register service worker
|
||||||
|
registerValidSW(swUrl, config);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function registerValidSW(swUrl, config) {
|
||||||
|
navigator.serviceWorker
|
||||||
|
.register(swUrl)
|
||||||
|
.then(registration => {
|
||||||
|
registration.onupdatefound = () => {
|
||||||
|
const installingWorker = registration.installing;
|
||||||
|
if (installingWorker == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
installingWorker.onstatechange = () => {
|
||||||
|
if (installingWorker.state === 'installed') {
|
||||||
|
if (navigator.serviceWorker.controller) {
|
||||||
|
// At this point, the updated precached content has been fetched,
|
||||||
|
// but the previous service worker will still serve the older
|
||||||
|
// content until all client tabs are closed.
|
||||||
|
console.log(
|
||||||
|
'New content is available and will be used when all ' +
|
||||||
|
'tabs for this page are closed. See http://bit.ly/CRA-PWA.'
|
||||||
|
);
|
||||||
|
|
||||||
|
// Execute callback
|
||||||
|
if (config && config.onUpdate) {
|
||||||
|
config.onUpdate(registration);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// At this point, everything has been precached.
|
||||||
|
// It's the perfect time to display a
|
||||||
|
// "Content is cached for offline use." message.
|
||||||
|
console.log('Content is cached for offline use.');
|
||||||
|
|
||||||
|
// Execute callback
|
||||||
|
if (config && config.onSuccess) {
|
||||||
|
config.onSuccess(registration);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
console.error('Error during service worker registration:', error);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function checkValidServiceWorker(swUrl, config) {
|
||||||
|
// Check if the service worker can be found. If it can't reload the page.
|
||||||
|
fetch(swUrl)
|
||||||
|
.then(response => {
|
||||||
|
// Ensure service worker exists, and that we really are getting a JS file.
|
||||||
|
const contentType = response.headers.get('content-type');
|
||||||
|
if (
|
||||||
|
response.status === 404 ||
|
||||||
|
(contentType != null && contentType.indexOf('javascript') === -1)
|
||||||
|
) {
|
||||||
|
// No service worker found. Probably a different app. Reload the page.
|
||||||
|
navigator.serviceWorker.ready.then(registration => {
|
||||||
|
registration.unregister().then(() => {
|
||||||
|
window.location.reload();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
// Service worker found. Proceed as normal.
|
||||||
|
registerValidSW(swUrl, config);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(() => {
|
||||||
|
console.log(
|
||||||
|
'No internet connection found. App is running in offline mode.'
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export function unregister() {
|
||||||
|
if ('serviceWorker' in navigator) {
|
||||||
|
navigator.serviceWorker.ready.then(registration => {
|
||||||
|
registration.unregister();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
312
client/src/welcome.css
Normal file
312
client/src/welcome.css
Normal file
@@ -0,0 +1,312 @@
|
|||||||
|
@import url('https://fonts.googleapis.com/css?family=Open+Sans:400,700|Roboto+Slab:300,700');
|
||||||
|
|
||||||
|
body {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/***** GLOBAL *****/
|
||||||
|
|
||||||
|
.welcome {
|
||||||
|
height: 100vh;
|
||||||
|
width: 100vw;
|
||||||
|
text-align: center;
|
||||||
|
color: #1d1e1c;
|
||||||
|
font-family: 'Open Sans', sans-serif;
|
||||||
|
font-size: 14px;
|
||||||
|
overflow: auto;
|
||||||
|
background-color: #ececec;
|
||||||
|
}
|
||||||
|
|
||||||
|
.welcome a {
|
||||||
|
text-decoration: none;
|
||||||
|
color: #38a9b4;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.welcome h1 {
|
||||||
|
font-family: 'Roboto Slab', serif;
|
||||||
|
font-weight: 300;
|
||||||
|
font-size: 36px;
|
||||||
|
margin: 0 0 10px;
|
||||||
|
line-height: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.welcome h1 strong {
|
||||||
|
font-weight: 700;
|
||||||
|
color: #38a9b4;
|
||||||
|
}
|
||||||
|
|
||||||
|
.welcome h2 {
|
||||||
|
text-transform: uppercase;
|
||||||
|
font-size: 18px;
|
||||||
|
font-weight: bold;
|
||||||
|
margin: 25px 0 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.welcome h3 {
|
||||||
|
text-transform: uppercase;
|
||||||
|
font-weight: 500;
|
||||||
|
color: #38a9b4;
|
||||||
|
font-size: 16px;
|
||||||
|
margin: 0 0 5px;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
/***** TOP *****/
|
||||||
|
|
||||||
|
.welcome__top {
|
||||||
|
background-color: #67cece;
|
||||||
|
padding-bottom: 40px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.welcome__flag {
|
||||||
|
transform: rotate(30deg);
|
||||||
|
position: fixed;
|
||||||
|
right: -190px;
|
||||||
|
top: 65px;
|
||||||
|
box-shadow: 0 2px 5px 0 rgba(0, 0, 0, 0.2);
|
||||||
|
z-index: 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
/***** MAIN *****/
|
||||||
|
|
||||||
|
.welcome__main {
|
||||||
|
box-shadow: 0 6px 10px 0 rgba(0, 0, 0, 0.14),
|
||||||
|
0 1px 18px 0 rgba(0, 0, 0, 0.12), 0 3px 5px -1px rgba(0, 0, 0, 0.3);
|
||||||
|
width: 80%;
|
||||||
|
max-width: 1100px;
|
||||||
|
margin-left: auto;
|
||||||
|
margin-right: auto;
|
||||||
|
transform: translateY(-50px);
|
||||||
|
background-color: white;
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
.main__aside {
|
||||||
|
background-color: #afe5e5;
|
||||||
|
width: 30%;
|
||||||
|
position: relative;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.aside__circle,
|
||||||
|
.main__aside svg {
|
||||||
|
position: absolute;
|
||||||
|
left: 50%;
|
||||||
|
top: 50%;
|
||||||
|
transform: translate(-50%, -50%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.aside__circle {
|
||||||
|
background-color: white;
|
||||||
|
border-radius: 50%;
|
||||||
|
width: 90%;
|
||||||
|
height: 0;
|
||||||
|
padding-bottom: 90%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.aside__circle:after {
|
||||||
|
content: '';
|
||||||
|
width: 4px;
|
||||||
|
left: calc(50% - 5px);
|
||||||
|
top: -50%;
|
||||||
|
position: absolute;
|
||||||
|
height: 100%;
|
||||||
|
background-color: #1d1e1c;
|
||||||
|
}
|
||||||
|
|
||||||
|
.main__aside svg {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.main__content {
|
||||||
|
padding: 30px;
|
||||||
|
text-align: left;
|
||||||
|
flex: auto;
|
||||||
|
}
|
||||||
|
.other__bloc {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
border: 4px solid #afe5e5;
|
||||||
|
padding: 10px 20px;
|
||||||
|
margin: 10px 0;
|
||||||
|
height: 170px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
text-align:left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.other__bloc:not(:last-of-type) {
|
||||||
|
margin-right: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.other__bloc h3:not(:first-child) {
|
||||||
|
margin-top: 15px;
|
||||||
|
padding-top: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.other__circle {
|
||||||
|
width: 110px;
|
||||||
|
height: 110px;
|
||||||
|
background-color: #afe5e5;
|
||||||
|
border-radius: 50%;
|
||||||
|
margin-right:20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.other__circle svg{
|
||||||
|
width: 110px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.buttons__group {
|
||||||
|
display: inline-flex;
|
||||||
|
vertical-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.buttons__group .buttons__or {
|
||||||
|
width: 4px;
|
||||||
|
position: relative;
|
||||||
|
text-align:center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.buttons__group .buttons__or:before {
|
||||||
|
content: 'or';
|
||||||
|
font-size: 12px;
|
||||||
|
color: #aaa;
|
||||||
|
line-height: 18px;
|
||||||
|
position: absolute;
|
||||||
|
border-radius: 50%;
|
||||||
|
top: 50%;
|
||||||
|
left: 50%;
|
||||||
|
transform: translate(-50%, -50%);
|
||||||
|
background-color: white;
|
||||||
|
width: 18px;
|
||||||
|
height: 18px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.buttons__group .other__button:first-child {
|
||||||
|
border-radius: 5px 0 0 5px;
|
||||||
|
padding-right: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.buttons__group .other__button:last-child {
|
||||||
|
border-radius: 0 5px 5px 0;
|
||||||
|
padding-left: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
a.other__button {
|
||||||
|
background-color: #e0e1e2;
|
||||||
|
font-size: 11px;
|
||||||
|
color: #686e63;
|
||||||
|
cursor: pointer;
|
||||||
|
padding: 5px 10px;
|
||||||
|
display: inline-block;
|
||||||
|
transition: all ease 0.2s;
|
||||||
|
text-transform: uppercase;
|
||||||
|
}
|
||||||
|
|
||||||
|
.other__button:hover {
|
||||||
|
background-color: #afe5e5;
|
||||||
|
color: #339ba5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.main__button {
|
||||||
|
display: inline-block;
|
||||||
|
padding: 10px 50px 10px 10px;
|
||||||
|
border: 3px solid #339ba5;
|
||||||
|
font-size: 22px;
|
||||||
|
color: #339ba5;
|
||||||
|
text-transform: uppercase;
|
||||||
|
margin: 15px 0;
|
||||||
|
overflow: hidden;
|
||||||
|
transition: all ease 0.3s;
|
||||||
|
cursor: pointer;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.main__button svg {
|
||||||
|
position: absolute;
|
||||||
|
right: 10px;
|
||||||
|
top: 50%;
|
||||||
|
transform: translateY(-50%);
|
||||||
|
transition: transform ease 0.2s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.main__button:hover {
|
||||||
|
background-color: #afe5e5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.main__button:hover svg {
|
||||||
|
transform: translateY(-50%) rotate(35deg);
|
||||||
|
}
|
||||||
|
|
||||||
|
/***** HELP *****/
|
||||||
|
|
||||||
|
.welcome__help {
|
||||||
|
background-color: white;
|
||||||
|
box-shadow: 0 2px 5px 0 rgba(0, 0, 0, 0.2);
|
||||||
|
padding: 10px;
|
||||||
|
position: fixed;
|
||||||
|
right: -5px;
|
||||||
|
top: 50%;
|
||||||
|
transform: translateY(-50%);
|
||||||
|
border-radius: 5px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.welcome__help h2 {
|
||||||
|
color: #aaa;
|
||||||
|
font-size: 12px;
|
||||||
|
margin: 10px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.help__circle {
|
||||||
|
width: 36px;
|
||||||
|
height: 36px;
|
||||||
|
border-radius: 50%;
|
||||||
|
border: 2px solid #ccc;
|
||||||
|
display: block;
|
||||||
|
margin: 10px auto;
|
||||||
|
transition: all ease 0.2s;
|
||||||
|
position:relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.help__circle svg {
|
||||||
|
position:absolute;
|
||||||
|
left: 50%;
|
||||||
|
top: 50%;
|
||||||
|
transform:translate(-50%, -50%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.help__circle:hover {
|
||||||
|
border-color: #67cece;
|
||||||
|
background-color: #afe5e5;
|
||||||
|
}
|
||||||
|
|
||||||
|
/***** MEDIAS *****/
|
||||||
|
|
||||||
|
@media (max-width: 1200px) {
|
||||||
|
.main__aside,
|
||||||
|
.welcome__help {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
.main__content {
|
||||||
|
width: 100%;
|
||||||
|
text-align: center;
|
||||||
|
padding: 20px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 600px) {
|
||||||
|
.welcome__main {
|
||||||
|
width: calc(100% - 40px);
|
||||||
|
}
|
||||||
|
.welcome h1 {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
.welcome__flag,
|
||||||
|
.main__other {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
.main__content {
|
||||||
|
padding: 10px;
|
||||||
|
}
|
||||||
|
}
|
||||||
10446
client/yarn.lock
Normal file
10446
client/yarn.lock
Normal file
File diff suppressed because it is too large
Load Diff
128
docker-compose.yml
Normal file
128
docker-compose.yml
Normal file
@@ -0,0 +1,128 @@
|
|||||||
|
version: '3.4'
|
||||||
|
|
||||||
|
x-cache:
|
||||||
|
&cache
|
||||||
|
cache_from:
|
||||||
|
- ${CONTAINER_REGISTRY_BASE}/php
|
||||||
|
- ${CONTAINER_REGISTRY_BASE}/nginx
|
||||||
|
- ${CONTAINER_REGISTRY_BASE}/varnish
|
||||||
|
|
||||||
|
services:
|
||||||
|
php:
|
||||||
|
image: ${CONTAINER_REGISTRY_BASE}/php
|
||||||
|
build:
|
||||||
|
context: ./api
|
||||||
|
target: api_platform_php
|
||||||
|
<<: *cache
|
||||||
|
depends_on:
|
||||||
|
- db
|
||||||
|
# Comment out these volumes in production
|
||||||
|
volumes:
|
||||||
|
- ./api:/srv/api:rw,cached
|
||||||
|
# If you develop on Linux, uncomment the following line to use a bind-mounted host directory instead
|
||||||
|
# - ./api/var:/srv/api/var:rw
|
||||||
|
|
||||||
|
api:
|
||||||
|
image: ${CONTAINER_REGISTRY_BASE}/nginx
|
||||||
|
build:
|
||||||
|
context: ./api
|
||||||
|
target: api_platform_nginx
|
||||||
|
<<: *cache
|
||||||
|
depends_on:
|
||||||
|
- php
|
||||||
|
# Comment out this volume in production
|
||||||
|
volumes:
|
||||||
|
- ./api/public:/srv/api/public:ro
|
||||||
|
ports:
|
||||||
|
- "8080:80"
|
||||||
|
|
||||||
|
cache-proxy:
|
||||||
|
image: ${CONTAINER_REGISTRY_BASE}/varnish
|
||||||
|
build:
|
||||||
|
context: ./api
|
||||||
|
target: api_platform_varnish
|
||||||
|
<<: *cache
|
||||||
|
depends_on:
|
||||||
|
- api
|
||||||
|
volumes:
|
||||||
|
- ./api/docker/varnish/conf:/usr/local/etc/varnish:ro
|
||||||
|
tmpfs:
|
||||||
|
- /usr/local/var/varnish:exec
|
||||||
|
ports:
|
||||||
|
- "8081:80"
|
||||||
|
|
||||||
|
db:
|
||||||
|
# In production, you may want to use a managed database service
|
||||||
|
image: postgres:10-alpine
|
||||||
|
environment:
|
||||||
|
- POSTGRES_DB=api
|
||||||
|
- POSTGRES_USER=api-platform
|
||||||
|
# You should definitely change the password in production
|
||||||
|
- POSTGRES_PASSWORD=!ChangeMe!
|
||||||
|
volumes:
|
||||||
|
- db-data:/var/lib/postgresql/data:rw
|
||||||
|
# You may use a bind-mounted host directory instead, so that it is harder to accidentally remove the volume and lose all your data!
|
||||||
|
# - ./docker/db/data:/var/lib/postgresql/data:rw
|
||||||
|
ports:
|
||||||
|
- "5432:5432"
|
||||||
|
|
||||||
|
mercure:
|
||||||
|
# In production, you may want to use the managed version of Mercure, https://mercure.rocks
|
||||||
|
image: dunglas/mercure
|
||||||
|
environment:
|
||||||
|
# You should definitely change all these values in production
|
||||||
|
- JWT_KEY=!UnsecureChangeMe!
|
||||||
|
- ALLOW_ANONYMOUS=1
|
||||||
|
- CORS_ALLOWED_ORIGINS=*
|
||||||
|
- PUBLISH_ALLOWED_ORIGINS=http://localhost:1337,https://localhost:1338
|
||||||
|
- DEMO=1
|
||||||
|
ports:
|
||||||
|
- "1337:80"
|
||||||
|
|
||||||
|
client:
|
||||||
|
# Use a static website hosting service in production
|
||||||
|
# See https://facebook.github.io/create-react-app/docs/deployment
|
||||||
|
image: ${CONTAINER_REGISTRY_BASE}/client
|
||||||
|
build:
|
||||||
|
context: ./client
|
||||||
|
cache_from:
|
||||||
|
- ${CONTAINER_REGISTRY_BASE}/client
|
||||||
|
env_file:
|
||||||
|
- ./client/.env
|
||||||
|
volumes:
|
||||||
|
- ./client:/usr/src/client:rw,cached
|
||||||
|
- /usr/src/client/node_modules
|
||||||
|
ports:
|
||||||
|
- "80:3000"
|
||||||
|
|
||||||
|
admin:
|
||||||
|
# Use a static website hosting service in production
|
||||||
|
# See https://facebook.github.io/create-react-app/docs/deployment
|
||||||
|
image: ${CONTAINER_REGISTRY_BASE}/admin
|
||||||
|
build:
|
||||||
|
context: ./admin
|
||||||
|
cache_from:
|
||||||
|
- ${CONTAINER_REGISTRY_BASE}/admin
|
||||||
|
volumes:
|
||||||
|
- ./admin:/usr/src/admin:rw,cached
|
||||||
|
- /usr/src/admin/node_modules
|
||||||
|
ports:
|
||||||
|
- "81:3000"
|
||||||
|
|
||||||
|
h2-proxy:
|
||||||
|
# Don't use this proxy in prod
|
||||||
|
build:
|
||||||
|
context: ./h2-proxy
|
||||||
|
depends_on:
|
||||||
|
- client
|
||||||
|
- admin
|
||||||
|
- api
|
||||||
|
- cache-proxy
|
||||||
|
ports:
|
||||||
|
- "443:443"
|
||||||
|
- "444:444"
|
||||||
|
- "8443:8443"
|
||||||
|
- "8444:8444"
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
db-data: {}
|
||||||
17
h2-proxy/Dockerfile
Normal file
17
h2-proxy/Dockerfile
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
FROM alpine:latest
|
||||||
|
|
||||||
|
RUN apk add --no-cache openssl
|
||||||
|
|
||||||
|
# Use this self-generated certificate only in dev, IT IS NOT SECURE!
|
||||||
|
RUN openssl genrsa -des3 -passout pass:NotSecure -out cert.pass.key 2048
|
||||||
|
RUN openssl rsa -passin pass:NotSecure -in cert.pass.key -out cert.key
|
||||||
|
RUN rm cert.pass.key
|
||||||
|
RUN openssl req -new -passout pass:NotSecure -key cert.key -out cert.csr \
|
||||||
|
-subj '/C=SS/ST=SS/L=Gotham City/O=API Platform Dev/CN=localhost'
|
||||||
|
RUN openssl x509 -req -sha256 -days 365 -in cert.csr -signkey cert.key -out cert.crt
|
||||||
|
|
||||||
|
FROM nginx:1.15-alpine
|
||||||
|
|
||||||
|
RUN mkdir -p /etc/nginx/ssl/
|
||||||
|
COPY --from=0 cert.key cert.crt /etc/nginx/ssl/
|
||||||
|
COPY conf.d /etc/nginx/conf.d/
|
||||||
85
h2-proxy/conf.d/default.conf
Normal file
85
h2-proxy/conf.d/default.conf
Normal file
@@ -0,0 +1,85 @@
|
|||||||
|
# client
|
||||||
|
server {
|
||||||
|
listen 443 ssl http2;
|
||||||
|
listen [::]:443 ssl http2;
|
||||||
|
|
||||||
|
ssl_certificate /etc/nginx/ssl/cert.crt;
|
||||||
|
ssl_certificate_key /etc/nginx/ssl/cert.key;
|
||||||
|
|
||||||
|
location / {
|
||||||
|
proxy_pass http://client:3000;
|
||||||
|
proxy_set_header Upgrade $http_upgrade;
|
||||||
|
proxy_set_header Connection "upgrade";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# admin
|
||||||
|
server {
|
||||||
|
listen 444 ssl http2;
|
||||||
|
listen [::]:444 ssl http2;
|
||||||
|
|
||||||
|
ssl_certificate /etc/nginx/ssl/cert.crt;
|
||||||
|
ssl_certificate_key /etc/nginx/ssl/cert.key;
|
||||||
|
|
||||||
|
location / {
|
||||||
|
proxy_pass http://admin:3000;
|
||||||
|
proxy_set_header Upgrade $http_upgrade;
|
||||||
|
proxy_set_header Connection "upgrade";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# api
|
||||||
|
server {
|
||||||
|
listen 8443 ssl http2;
|
||||||
|
listen [::]:8443 ssl http2;
|
||||||
|
|
||||||
|
ssl_certificate /etc/nginx/ssl/cert.crt;
|
||||||
|
ssl_certificate_key /etc/nginx/ssl/cert.key;
|
||||||
|
|
||||||
|
location / {
|
||||||
|
proxy_pass http://api;
|
||||||
|
proxy_http_version 1.1;
|
||||||
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
|
proxy_set_header X-Forwarded-Host $host;
|
||||||
|
proxy_set_header X-Forwarded-Proto $scheme;
|
||||||
|
proxy_set_header X-Forwarded-Port 8443;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# cache-proxy
|
||||||
|
server {
|
||||||
|
listen 8444 ssl http2;
|
||||||
|
listen [::]:8444 ssl http2;
|
||||||
|
|
||||||
|
ssl_certificate /etc/nginx/ssl/cert.crt;
|
||||||
|
ssl_certificate_key /etc/nginx/ssl/cert.key;
|
||||||
|
|
||||||
|
location / {
|
||||||
|
proxy_pass http://cache-proxy;
|
||||||
|
proxy_http_version 1.1;
|
||||||
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
|
proxy_set_header X-Forwarded-Host $host;
|
||||||
|
proxy_set_header X-Forwarded-Proto $scheme;
|
||||||
|
proxy_set_header X-Forwarded-Port 8444;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# mercure
|
||||||
|
server {
|
||||||
|
listen 1338 ssl http2;
|
||||||
|
listen [::]:1338 ssl http2;
|
||||||
|
|
||||||
|
ssl_certificate /etc/nginx/ssl/cert.crt;
|
||||||
|
ssl_certificate_key /etc/nginx/ssl/cert.key;
|
||||||
|
|
||||||
|
location / {
|
||||||
|
proxy_pass http://mercure;
|
||||||
|
proxy_read_timeout 24h;
|
||||||
|
proxy_http_version 1.1;
|
||||||
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
|
proxy_set_header X-Forwarded-Host $host;
|
||||||
|
proxy_set_header X-Forwarded-Proto $scheme;
|
||||||
|
proxy_set_header X-Forwarded-Port 1338;
|
||||||
|
proxy_set_header Connection "";
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user