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