diff --git a/app/application/.env.example b/app/application/.env.example index 0f7ae55..61089d6 100644 --- a/app/application/.env.example +++ b/app/application/.env.example @@ -11,7 +11,6 @@ CAPTCHA_STATIC_PATH=http://your-domain-captcha-or-IP:8081/captcha CAPTCHA_PUBLIC_TOKEN= APP_FORCE_HTTPS=false -#UNIT_SOURCE="\"172.16.0.0/12\"" APP_DEFAULT_LOCALE=ru APP_FAKER_LOCALE=ru_RU diff --git a/app/application/.gitignore b/app/application/.gitignore index 7fe978f..c4d4373 100644 --- a/app/application/.gitignore +++ b/app/application/.gitignore @@ -8,6 +8,7 @@ .env .env.backup .env.production +.env.testing .phpunit.result.cache Homestead.json Homestead.yaml diff --git a/app/application/app/Exceptions/Services/Rule/RoleSyncPermissionsCommandHandlerException.php b/app/application/app/Exceptions/Services/Rule/RoleSyncPermissionsCommandHandlerException.php new file mode 100644 index 0000000..41c4196 --- /dev/null +++ b/app/application/app/Exceptions/Services/Rule/RoleSyncPermissionsCommandHandlerException.php @@ -0,0 +1,8 @@ + - + diff --git a/app/application/resources/views/private/profile/profile.blade.php b/app/application/resources/views/private/profile/profile.blade.php index 6ebc1c5..c61b2fc 100644 --- a/app/application/resources/views/private/profile/profile.blade.php +++ b/app/application/resources/views/private/profile/profile.blade.php @@ -23,8 +23,8 @@
@csrf @method('PUT') - - + + diff --git a/app/application/resources/volt/js/volt.js b/app/application/resources/volt/js/volt.js index 6a9ba93..900fcf7 100644 --- a/app/application/resources/volt/js/volt.js +++ b/app/application/resources/volt/js/volt.js @@ -19,53 +19,10 @@ const d = document; import * as bootstrap from 'bootstrap'; -import Swal from 'sweetalert2'; import SmoothScroll from 'smooth-scroll'; -import Chartist from 'chartist'; -import 'chartist-plugin-tooltips'; d.addEventListener("DOMContentLoaded", function(event) { - const swalWithBootstrapButtons = Swal.mixin({ - customClass: { - confirmButton: 'btn btn-primary me-3', - cancelButton: 'btn btn-gray' - }, - buttonsStyling: false - }); - - var themeSettingsEl = document.getElementById('theme-settings'); - var themeSettingsExpandEl = document.getElementById('theme-settings-expand'); - - if(themeSettingsEl) { - - var themeSettingsCollapse = new bootstrap.Collapse(themeSettingsEl, { - show: true, - toggle: false - }); - - if (window.localStorage.getItem('settings_expanded') === 'true') { - themeSettingsCollapse.show(); - themeSettingsExpandEl.classList.remove('show'); - } else { - themeSettingsCollapse.hide(); - themeSettingsExpandEl.classList.add('show'); - } - - themeSettingsEl.addEventListener('hidden.bs.collapse', function () { - themeSettingsExpandEl.classList.add('show'); - window.localStorage.setItem('settings_expanded', false); - }); - - themeSettingsExpandEl.addEventListener('click', function () { - themeSettingsExpandEl.classList.remove('show'); - window.localStorage.setItem('settings_expanded', true); - setTimeout(function() { - themeSettingsCollapse.show(); - }, 300); - }); - } - // options const breakpoints = { sm: 540, @@ -84,13 +41,6 @@ d.addEventListener("DOMContentLoaded", function(event) { }); } - var iconNotifications = d.querySelector('.notification-bell'); - if (iconNotifications) { - iconNotifications.addEventListener('shown.bs.dropdown', function () { - iconNotifications.classList.remove('unread'); - }); - } - [].slice.call(d.querySelectorAll('[data-background]')).map(function(el) { el.style.background = 'url(' + el.getAttribute('data-background') + ')'; }); @@ -112,17 +62,15 @@ d.addEventListener("DOMContentLoaded", function(event) { //Tooltips var tooltipTriggerList = [].slice.call(document.querySelectorAll('[data-bs-toggle="tooltip"]')) var tooltipList = tooltipTriggerList.map(function (tooltipTriggerEl) { - return new bootstrap.Tooltip(tooltipTriggerEl) + return new bootstrap.Tooltip(tooltipTriggerEl) }) - // Popovers var popoverTriggerList = [].slice.call(document.querySelectorAll('[data-bs-toggle="popover"]')) var popoverList = popoverTriggerList.map(function (popoverTriggerEl) { return new bootstrap.Popover(popoverTriggerEl) }) - // Datepicker var datepickers = [].slice.call(d.querySelectorAll('[data-datepicker]')) var datepickersList = datepickers.map(function (el) { @@ -131,164 +79,6 @@ d.addEventListener("DOMContentLoaded", function(event) { }); }) - if(d.querySelector('.input-slider-container')) { - [].slice.call(d.querySelectorAll('.input-slider-container')).map(function(el) { - var slider = el.querySelector(':scope .input-slider'); - var sliderId = slider.getAttribute('id'); - var minValue = slider.getAttribute('data-range-value-min'); - var maxValue = slider.getAttribute('data-range-value-max'); - - var sliderValue = el.querySelector(':scope .range-slider-value'); - var sliderValueId = sliderValue.getAttribute('id'); - var startValue = sliderValue.getAttribute('data-range-value-low'); - - var c = d.getElementById(sliderId), - id = d.getElementById(sliderValueId); - - noUiSlider.create(c, { - start: [parseInt(startValue)], - connect: [true, false], - //step: 1000, - range: { - 'min': [parseInt(minValue)], - 'max': [parseInt(maxValue)] - } - }); - }); - } - - if (d.getElementById('input-slider-range')) { - var c = d.getElementById("input-slider-range"), - low = d.getElementById("input-slider-range-value-low"), - e = d.getElementById("input-slider-range-value-high"), - f = [d, e]; - - noUiSlider.create(c, { - start: [parseInt(low.getAttribute('data-range-value-low')), parseInt(e.getAttribute('data-range-value-high'))], - connect: !0, - tooltips: true, - range: { - min: parseInt(c.getAttribute('data-range-value-min')), - max: parseInt(c.getAttribute('data-range-value-max')) - } - }), c.noUiSlider.on("update", function (a, b) { - f[b].textContent = a[b] - }); - } - - //Chartist - - if(d.querySelector('.ct-chart-sales-value')) { - //Chart 5 - new Chartist.Line('.ct-chart-sales-value', { - labels: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'], - series: [ - [0, 10, 30, 40, 80, 60, 100] - ] - }, { - low: 0, - showArea: true, - fullWidth: true, - plugins: [ - Chartist.plugins.tooltip() - ], - axisX: { - // On the x-axis start means top and end means bottom - position: 'end', - showGrid: true - }, - axisY: { - // On the y-axis start means left and end means right - showGrid: false, - showLabel: false, - labelInterpolationFnc: function(value) { - return '$' + (value / 1) + 'k'; - } - } - }); - } - - if(d.querySelector('.ct-chart-ranking')) { - var chart = new Chartist.Bar('.ct-chart-ranking', { - labels: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'], - series: [ - [1, 5, 2, 5, 4, 3], - [2, 3, 4, 8, 1, 2], - ] - }, { - low: 0, - showArea: true, - plugins: [ - Chartist.plugins.tooltip() - ], - axisX: { - // On the x-axis start means top and end means bottom - position: 'end' - }, - axisY: { - // On the y-axis start means left and end means right - showGrid: false, - showLabel: false, - offset: 0 - } - }); - - chart.on('draw', function(data) { - if(data.type === 'line' || data.type === 'area') { - data.element.animate({ - d: { - begin: 2000 * data.index, - dur: 2000, - from: data.path.clone().scale(1, 0).translate(0, data.chartRect.height()).stringify(), - to: data.path.clone().stringify(), - easing: Chartist.Svg.Easing.easeOutQuint - } - }); - } - }); - } - - if(d.querySelector('.ct-chart-traffic-share')) { - var data = { - series: [70, 20, 10] - }; - - var sum = function(a, b) { return a + b }; - - new Chartist.Pie('.ct-chart-traffic-share', data, { - labelInterpolationFnc: function(value) { - return Math.round(value / data.series.reduce(sum) * 100) + '%'; - }, - low: 0, - high: 8, - donut: true, - donutWidth: 20, - donutSolid: true, - fullWidth: false, - showLabel: false, - plugins: [ - Chartist.plugins.tooltip() - ], - }); - } - - if (d.getElementById('loadOnClick')) { - d.getElementById('loadOnClick').addEventListener('click', function () { - var button = this; - var loadContent = d.getElementById('extraContent'); - var allLoaded = d.getElementById('allLoadedText'); - - button.classList.add('btn-loading'); - button.setAttribute('disabled', 'true'); - - setTimeout(function () { - loadContent.style.display = 'block'; - button.style.display = 'none'; - allLoaded.style.display = 'block'; - }, 1500); - }); - } - var scroll = new SmoothScroll('a[href*="#"]', { speed: 500, speedAsDuration: true @@ -297,68 +87,4 @@ d.addEventListener("DOMContentLoaded", function(event) { if(d.querySelector('.current-year')){ d.querySelector('.current-year').textContent = new Date().getFullYear(); } - - // Glide JS - - if (d.querySelector('.glide')) { - new Glide('.glide', { - type: 'carousel', - startAt: 0, - perView: 3 - }).mount(); - } - - if (d.querySelector('.glide-testimonials')) { - new Glide('.glide-testimonials', { - type: 'carousel', - startAt: 0, - perView: 1, - autoplay: 2000 - }).mount(); - } - - if (d.querySelector('.glide-clients')) { - new Glide('.glide-clients', { - type: 'carousel', - startAt: 0, - perView: 5, - autoplay: 2000 - }).mount(); - } - - if (d.querySelector('.glide-news-widget')) { - new Glide('.glide-news-widget', { - type: 'carousel', - startAt: 0, - perView: 1, - autoplay: 2000 - }).mount(); - } - - if (d.querySelector('.glide-autoplay')) { - new Glide('.glide-autoplay', { - type: 'carousel', - startAt: 0, - perView: 3, - autoplay: 2000 - }).mount(); - } - - // Pricing countup - var billingSwitchEl = d.getElementById('billingSwitch'); - if(billingSwitchEl) { - const countUpStandard = new countUp.CountUp('priceStandard', 99, { startVal: 199 }); - const countUpPremium = new countUp.CountUp('pricePremium', 199, { startVal: 299 }); - - billingSwitchEl.addEventListener('change', function() { - if(billingSwitch.checked) { - countUpStandard.start(); - countUpPremium.start(); - } else { - countUpStandard.reset(); - countUpPremium.reset(); - } - }); - } - }); diff --git a/app/docker/docker-entrypoint_dev.sh b/app/docker/docker-entrypoint_dev.sh index a885fa2..c447b67 100644 --- a/app/docker/docker-entrypoint_dev.sh +++ b/app/docker/docker-entrypoint_dev.sh @@ -5,6 +5,7 @@ set -euo pipefail WAITLOOPS=5 SLEEPSEC=1 unitd="unitd" +role=${CONTAINER_ROLE:-app} curl_put() { @@ -22,7 +23,7 @@ curl_put() return 0 } -if [ "$unitd" = "unitd" ] || [ "$unitd" = "unitd-debug" ]; then +if [ "$role" = "app" ]; then echo "$0: Launching Unit daemon to perform initial configuration..." /usr/sbin/$unitd --control unix:/var/run/control.unit.sock for i in $(/usr/bin/seq $WAITLOOPS); do @@ -61,7 +62,7 @@ if [ "$unitd" = "unitd" ] || [ "$unitd" = "unitd-debug" ]; then if [ ! -z ${UNIT_SOURCE+x} ] then - echo "[${UNIT_SOURCE}]" > /docker-entrypoint.d/unit_source.json + echo $UNIT_SOURCE > /docker-entrypoint.d/unit_source.json curl_put "/docker-entrypoint.d/unit_source.json" "config/listeners/*:9000/forwarded/source" fi diff --git a/app/docker/docker-entrypoint_prod.sh b/app/docker/docker-entrypoint_prod.sh index 0ea0a31..b066f56 100644 --- a/app/docker/docker-entrypoint_prod.sh +++ b/app/docker/docker-entrypoint_prod.sh @@ -5,6 +5,7 @@ set -euo pipefail WAITLOOPS=5 SLEEPSEC=1 unitd="unitd" +role=${CONTAINER_ROLE:-app} curl_put() { @@ -22,7 +23,7 @@ curl_put() return 0 } -if [ "$unitd" = "unitd" ] || [ "$unitd" = "unitd-debug" ]; then +if [ "$role" = "app" ]; then echo "$0: Launching Unit daemon to perform initial configuration..." /usr/sbin/$unitd --control unix:/var/run/control.unit.sock for i in $(/usr/bin/seq $WAITLOOPS); do @@ -61,7 +62,7 @@ if [ "$unitd" = "unitd" ] || [ "$unitd" = "unitd-debug" ]; then if [ ! -z ${UNIT_SOURCE+x} ] then - echo "[${UNIT_SOURCE}]" > /docker-entrypoint.d/unit_source.json + echo $UNIT_SOURCE > /docker-entrypoint.d/unit_source.json curl_put "/docker-entrypoint.d/unit_source.json" "config/listeners/*:9000/forwarded/source" fi @@ -102,8 +103,10 @@ php artisan config:cache php artisan event:cache php artisan route:cache php artisan view:cache -php artisan migrate --force - +php artisan storage:link +if [ "$role" = "app" ]; then + php artisan migrate --force +fi chown -R unit:unit /var/www/html chown -R www-data:www-data /var/www/html/storage /var/www/html/bootstrap/cache chmod -R 777 /var/www/html/storage /var/www/html/bootstrap/cache diff --git a/captcha-app/redis/.gitignore b/captcha-app/redis/.gitignore new file mode 100644 index 0000000..adbb97d --- /dev/null +++ b/captcha-app/redis/.gitignore @@ -0,0 +1 @@ +data/ \ No newline at end of file diff --git a/docker-compose-prod.yml b/docker-compose-prod.yml index 05ef617..d24169c 100644 --- a/docker-compose-prod.yml +++ b/docker-compose-prod.yml @@ -14,12 +14,17 @@ services: - ${DOCKER_APP_PORT}:9000 volumes: - ./app/application:/var/www/html + environment: + CONTAINER_ROLE: app + UNIT_SOURCE: '["172.16.0.0/12"]' app-redis: image: redis:3.0-alpine # restart: always + volumes: + - ./redis/data:/data captcha-app: - image: korelf/service-captcha:0.8.1 + image: korelf/service-captcha:0.8.2 # restart: always cap_drop: - ALL @@ -32,10 +37,13 @@ services: - db - captcha-redis env_file: captcha-app/.env + environment: + CONTAINER_ROLE: app + UNIT_SOURCE: '["172.16.0.0/12"]' ports: - ${DOCKER_CAPTCHA_PORT}:9000 captcha-queue: - image: korelf/service-captcha:0.8.1 + image: korelf/service-captcha:0.8.2 # restart: always depends_on: - db @@ -44,7 +52,7 @@ services: CONTAINER_ROLE: queue env_file: captcha-app/.env captcha-reverb: - image: korelf/service-captcha:0.8.1 + image: korelf/service-captcha:0.8.2 # restart: always depends_on: - db @@ -55,7 +63,7 @@ services: ports: - ${DOCKER_CAPTCHA_WEBSOCKET_PORT}:9000 captcha-scheduler: - image: korelf/service-captcha:0.8.1 + image: korelf/service-captcha:0.8.2 # restart: always depends_on: - db @@ -66,6 +74,8 @@ services: captcha-redis: image: redis:3.0-alpine # restart: always + volumes: + - ./captcha-app/redis/data:/data db: image: docker.io/mysql:8.0.33 command: --default-authentication-plugin=mysql_native_password diff --git a/docker-compose-prod_docker-hub.yml b/docker-compose-prod_docker-hub.yml index 8f9f639..dd535ea 100644 --- a/docker-compose-prod_docker-hub.yml +++ b/docker-compose-prod_docker-hub.yml @@ -1,7 +1,7 @@ version: '3.7' services: app: - image: korelf/my-projects-website:0.1.0 + image: korelf/my-projects-website:0.2.1 # restart: always depends_on: - db @@ -10,15 +10,20 @@ services: ports: - ${DOCKER_APP_PORT}:9000 env_file: app/.env + environment: + CONTAINER_ROLE: app + UNIT_SOURCE: '["172.16.0.0/12"]' volumes: - ./app/storage/app:/var/www/html/storage/app - ./app/storage/logs:/var/www/html/storage/logs app-redis: image: redis:3.0-alpine # restart: always + volumes: + - ./redis/data:/data captcha-app: - image: korelf/service-captcha:0.8.1 + image: korelf/service-captcha:0.8.2 # restart: always cap_drop: - ALL @@ -33,8 +38,11 @@ services: env_file: captcha-app/.env ports: - ${DOCKER_CAPTCHA_PORT}:9000 + environment: + CONTAINER_ROLE: app + UNIT_SOURCE: '["172.16.0.0/12"]' captcha-queue: - image: korelf/service-captcha:0.8.1 + image: korelf/service-captcha:0.8.2 # restart: always depends_on: - db @@ -43,7 +51,7 @@ services: CONTAINER_ROLE: queue env_file: captcha-app/.env captcha-reverb: - image: korelf/service-captcha:0.8.1 + image: korelf/service-captcha:0.8.2 # restart: always depends_on: - db @@ -54,7 +62,7 @@ services: ports: - ${DOCKER_CAPTCHA_WEBSOCKET_PORT}:9000 captcha-scheduler: - image: korelf/service-captcha:0.8.1 + image: korelf/service-captcha:0.8.2 # restart: always depends_on: - db @@ -65,6 +73,8 @@ services: captcha-redis: image: redis:3.0-alpine # restart: always + volumes: + - ./captcha-app/redis/data:/data db: image: docker.io/mysql:8.0.33 command: --default-authentication-plugin=mysql_native_password diff --git a/docker-compose.yml b/docker-compose.yml index 5b39030..f04c3a3 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -15,6 +15,8 @@ services: - ./app/application:/var/www/html app-redis: image: redis:3.0-alpine + volumes: + - ./redis/data:/data captcha-app: image: korelf/service-captcha:0.8.1 @@ -62,6 +64,8 @@ services: env_file: captcha-app/.env captcha-redis: image: redis:3.0-alpine + volumes: + - ./captcha-app/redis/data:/data db: image: docker.io/mysql:8.0.33 command: --default-authentication-plugin=mysql_native_password diff --git a/redis/.gitignore b/redis/.gitignore new file mode 100644 index 0000000..adbb97d --- /dev/null +++ b/redis/.gitignore @@ -0,0 +1 @@ +data/ \ No newline at end of file