diff --git a/.gitattributes b/.gitattributes index 9963dddc5e..1ebf0b221e 100644 --- a/.gitattributes +++ b/.gitattributes @@ -14,6 +14,7 @@ *.jpeg binary *.gif binary *.webp binary +*.avif binary *.ico binary *.mo binary *.pdf binary @@ -22,6 +23,7 @@ *.phar binary *.woff binary *.woff2 binary +*.ttc binary *.ttf binary *.otf binary *.eot binary diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6d5c698cd1..72059052dc 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -9,21 +9,22 @@ on: pull_request: branches: - '*' + workflow_dispatch: permissions: contents: read jobs: testsuite: - runs-on: ubuntu-18.04 + runs-on: ubuntu-22.04 strategy: fail-fast: false matrix: - php-version: ['7.4', '8.0', '8.1'] + php-version: ['7.4', '8.0', '8.1', '8.2'] name: PHP ${{ matrix.php-version }} steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Setup PHP uses: shivammathur/setup-php@v2 @@ -34,11 +35,7 @@ jobs: - name: Composer install run: | - if [[ ${{ matrix.php-version }} == '8.1' ]]; then - composer update --ignore-platform-reqs - else - composer update - fi + composer update composer run-script post-install-cmd --no-interaction - name: Run PHPUnit @@ -49,11 +46,11 @@ jobs: DATABASE_TEST_URL: sqlite://./testdb.sqlite coding-standard: - name: Coding Standard - runs-on: ubuntu-18.04 + name: Coding Standard & Static Analysis + runs-on: ubuntu-22.04 steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Setup PHP uses: shivammathur/setup-php@v2 @@ -61,29 +58,14 @@ jobs: php-version: '7.4' extensions: mbstring, intl coverage: none + tools: cs2pr, phpstan:1 - name: Composer install run: composer install - name: Run PHP CodeSniffer - run: composer cs-check - - static-analysis: - name: Static Analysis - runs-on: ubuntu-18.04 - - steps: - - uses: actions/checkout@v3 - - - name: Setup PHP - uses: shivammathur/setup-php@v2 - with: - php-version: '7.4' - extensions: mbstring, intl - coverage: none - - - name: Composer install - run: composer require --dev phpstan/phpstan:^1.0.0 + run: vendor/bin/phpcs --report=checkstyle | cs2pr - name: Run phpstan - run: vendor/bin/phpstan + if: always() + run: phpstan diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml index ebd280469c..69e7d139d4 100644 --- a/.github/workflows/stale.yml +++ b/.github/workflows/stale.yml @@ -16,7 +16,7 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/stale@v5 + - uses: actions/stale@v8 with: repo-token: ${{ secrets.GITHUB_TOKEN }} stale-issue-message: 'This issue is stale because it has been open for 120 days with no activity. Remove the `stale` label or comment or this will be closed in 15 days' diff --git a/.gitignore b/.gitignore index 25d7bb5718..beded96080 100644 --- a/.gitignore +++ b/.gitignore @@ -60,3 +60,5 @@ yarn-error.log # PHP Intel .phpintel *.mwb.bak +/cron.d/* +/ansible/roles/crontab/templates/*.txt diff --git a/README.md b/README.md index 8e58d5180d..f0b0e973ea 100644 --- a/README.md +++ b/README.md @@ -42,7 +42,7 @@ automated upgrades, so you have to do any updates manually. ## Configuration -Read and edit the environment specific `config/app_local.php` and setup the +Read and edit the environment specific `config/app_local.php` and set up the `'Datasources'` and any other configuration relevant for your application. Other environment agnostic settings can be changed in `config/app.php`. diff --git a/Vagrantfile b/Vagrantfile index 6b48aacbc1..fb410a63ea 100644 --- a/Vagrantfile +++ b/Vagrantfile @@ -4,6 +4,10 @@ def fail_with_message(msg) fail Vagrant::Errors::VagrantError.new, msg end +def is_arm64() + `uname -m` == "arm64" || `/usr/bin/arch -64 sh -c "sysctl -in sysctl.proc_translated"`.strip() == "0" +end + config_path = __dir__ config_file = File.join(config_path, 'vagrant.yml') @@ -21,14 +25,18 @@ Vagrant.configure("2") do |config| config.hostmanager.include_offline = true config.vm.define settings['name'] do |node| - node.vm.box = settings['box'] - node.vm.provider "vmware_fusion" do |v, override| - v.vmx["memsize"] = settings['memory'] - v.vmx["numvcpus"] = settings['cpus'] - v.whitelist_verified = true - v.ssh_info_public = true - v.port_forward_network_pause = 10 + if is_arm64() + node.vm.box = settings['arm64_box'] + else + node.vm.box = settings['box'] + end + + node.vm.provider "parallels" do |prl| + prl.name = settings['vm_name'] + prl.memory = settings['memory'] + prl.cpus = settings['cpus'] + prl.linked_clone = false end node.vm.provider "virtualbox" do |v, override| @@ -38,9 +46,18 @@ Vagrant.configure("2") do |config| v.customize ["modifyvm", :id, "--cpus", settings['cpus']] end - # Prefer vmware_fusion over virtualbox - node.vm.provider "vmware_fusion" + node.vm.provider "vmware_fusion" do |v, override| + v.vmx["memsize"] = settings['memory'] + v.vmx["numvcpus"] = settings['cpus'] + v.whitelist_verified = true + v.ssh_info_public = true + v.port_forward_network_pause = 10 + end + + # preference + node.vm.provider "parallels" node.vm.provider "virtualbox" + node.vm.provider "vmware_fusion" node.vm.network "private_network", type: "dhcp" node.vm.hostname = settings['hostname'] @@ -55,7 +72,7 @@ Vagrant.configure("2") do |config| #Add any alias: node.hostmanager.aliases = settings['aliases'] - node.vm.synced_folder ".", settings['app_path'], :nfs => true, :mount_options => ['nolock,vers=3,udp,noatime,actimeo=1'] + node.vm.synced_folder ".", settings['app_path'], type: "nfs", nfs_udp: false, mount_options: ['nolock,noatime,actimeo=1'] #Fix for Ansible bug resulting in an encoding error ENV['PYTHONIOENCODING'] = "utf-8" diff --git a/ansible/inventories/development/group_vars/all.yml b/ansible/inventories/development/group_vars/all.yml index 1effb1d800..789a4a7011 100644 --- a/ansible/inventories/development/group_vars/all.yml +++ b/ansible/inventories/development/group_vars/all.yml @@ -1,4 +1,5 @@ --- +mysql_environment: development nginx_environment: development nginx_ssl_crt: - cakephp.app.local.crt @@ -61,3 +62,7 @@ nginx_sites_available: - cakephp.app.local.conf nginx_sites_enabled: - cakephp.app.local.conf +active_crontab_files: + development: + - concat/initial.tab + - concat/clear_tmp_files.tab diff --git a/ansible/playbooks/development.yml b/ansible/playbooks/development.yml index 810469817e..231bd6156c 100644 --- a/ansible/playbooks/development.yml +++ b/ansible/playbooks/development.yml @@ -12,14 +12,17 @@ app_name: "cakephp-app" become_alternate_user: "vagrant" roles: - - system - - ntp - - php - - nginx - - mysql - - memcached - - wkhtmltopdf - - nodejs + - {role: "system", tags: "system"} + - {role: "libssl", tags: "libssl"} + - {role: "ntp", tags: "ntp"} + - {role: "php", tags: "php"} + - {role: "nginx", tags: "nginx"} + - {role: "wkhtmltopdf", tags: "wkhtmltopdf"} + - {role: "mysql", tags: "mysql"} + - {role: "memcached", tags: "memcached"} + - {role: "nodejs", tags: "nodejs"} + - {role: "crontab", tags: "crontab"} + - {role: "mailhog", tags: "mailhog"} tasks: - name: DONT PANIC NTP and VM Should Accept Traveling to the Future by more than 1000s lineinfile: @@ -29,7 +32,7 @@ - name: make a symbolic link for application crontab file file: - src: "{{ app_path }}/crontab" + src: "{{ app_path }}/cron.d/development" dest: "/etc/cron.d/{{ app_name }}" state: link @@ -53,6 +56,13 @@ args: executable: /bin/bash + - name: Create CakePHP dev config from default + copy: + src: "{{ app_path }}/config/app_local.example.php" + dest: "{{ app_path }}/config/app_local.php" + remote_src: yes + force: no + - name: Create /var/files/ file: path: "/var/files/" @@ -66,38 +76,43 @@ name: nginx state: restarted - - name: restart php8.1-fpm + - name: restart php8.3-fpm service: - name: php8.1-fpm + name: php8.3-fpm state: restarted - name: Create MySQL vagrant user shell: "mysql -e \"CREATE USER IF NOT EXISTS 'vagrant'@'%' IDENTIFIED WITH mysql_native_password BY 'vagrant'\";" become: yes become_user: root + when: mysql_server_installed - name: Grant the MySQL vagrant user some permissions shell: "mysql -e \"GRANT ALL on *.* to 'vagrant'@'%'WITH GRANT OPTION\";" become: yes become_user: root + when: mysql_server_installed - name: Flushing the MySQL Privileges shell: "mysql -e \"FLUSH PRIVILEGES\";" become: yes become_user: root + when: mysql_server_installed - name: Create the MySQL Database for the project shell: "mysql -e \"CREATE DATABASE IF NOT EXISTS cakephp_app DEFAULT CHARACTER SET utf8mb4 DEFAULT COLLATE utf8mb4_general_ci;\";" become: yes become_user: root + when: mysql_server_installed - name: Check if app migrations have already been ran shell: "mysql -e \"SELECT * FROM information_schema.tables WHERE table_schema = 'cakephp_app'\";" become: yes become_user: root - when: mysql_installed is defined + when: mysql_server_installed register: migrationran # above query returns nothing when no tables exist - name: Run app migrations command: "{{ app_path }}/bin/cake migrations migrate -vvvv" when: migrationran.stdout == "" # stdout of the variable we just registered will be empty when no tables exist + ignore_errors: yes diff --git a/ansible/roles/crontab/tasks/main.yml b/ansible/roles/crontab/tasks/main.yml new file mode 100644 index 0000000000..ee44bf90e9 --- /dev/null +++ b/ansible/roles/crontab/tasks/main.yml @@ -0,0 +1,12 @@ +--- +- name: Loop Over and Create temp Template for each desired crontab + template: + src: concat.j2 + dest: "{{ app_path }}/ansible/roles/crontab/templates/{{ item }}.txt" + loop: "{{ active_crontab_files | list }}" + +- name: Loop Over and Create final file for each crontab file + template: + src: "{{ item }}.txt" + dest: "{{ app_path }}/cron.d/{{ item }}" + loop: "{{ active_crontab_files | list }}" diff --git a/ansible/roles/crontab/templates/concat.j2 b/ansible/roles/crontab/templates/concat.j2 new file mode 100644 index 0000000000..447a5be0db --- /dev/null +++ b/ansible/roles/crontab/templates/concat.j2 @@ -0,0 +1,4 @@ +{% for i in active_crontab_files[item] %} +{{ lookup('file', i) }} + +{% endfor %} diff --git a/ansible/roles/crontab/templates/concat/clear_tmp_files.tab b/ansible/roles/crontab/templates/concat/clear_tmp_files.tab new file mode 100644 index 0000000000..11ef6db2e1 --- /dev/null +++ b/ansible/roles/crontab/templates/concat/clear_tmp_files.tab @@ -0,0 +1,2 @@ +# Every 30 minutes, delete tmp file uploads older than 6 hours +*/30 * * * * root find {{ app_path }}/tmp/files/* -mmin +360 ! -name "empty" -exec rm {} \; > /dev/null 2>&1 diff --git a/ansible/roles/crontab/templates/concat/initial.tab b/ansible/roles/crontab/templates/concat/initial.tab new file mode 100644 index 0000000000..1b59d38a96 --- /dev/null +++ b/ansible/roles/crontab/templates/concat/initial.tab @@ -0,0 +1,4 @@ +# Generated Crontab - Check Ansible Role/Playbook + +TZ="America/New_York" +MAILTO="" diff --git a/ansible/roles/libssl/tasks/main.yaml b/ansible/roles/libssl/tasks/main.yaml new file mode 100644 index 0000000000..691f78608a --- /dev/null +++ b/ansible/roles/libssl/tasks/main.yaml @@ -0,0 +1,19 @@ +--- +- name: 'Download libssl1.1 arm64' + get_url: + url: http://ports.ubuntu.com/pool/main/o/openssl/libssl1.1_1.1.1f-1ubuntu2.22_arm64.deb + dest: /root/libssl.deb + force: false + validate_certs: no # this is fucked up + when: ansible_architecture == 'aarch64' + +- name: 'Download libssl1.1 x86_64' + get_url: + url: http://security.ubuntu.com/ubuntu/pool/main/o/openssl/libssl1.1_1.1.1f-1ubuntu2.22_amd64.deb + dest: /root/libssl.deb + force: false + validate_certs: no # this is fucked up + when: ansible_architecture == 'x86_64' + +- name: 'Install libssl1.1' + command: dpkg -i /root/libssl.deb diff --git a/ansible/roles/mailhog/handlers/main.yml b/ansible/roles/mailhog/handlers/main.yml new file mode 100644 index 0000000000..df09debdc2 --- /dev/null +++ b/ansible/roles/mailhog/handlers/main.yml @@ -0,0 +1,16 @@ +--- +- name: start and enable mailhog + service: + name: mailhog + state: started + enabled: yes + +- name: restart mailhog + service: + name: mailhog + state: restarted + +- name: start mailhog + service: + name: mailhog + state: started \ No newline at end of file diff --git a/ansible/roles/mailhog/tasks/main.yml b/ansible/roles/mailhog/tasks/main.yml new file mode 100644 index 0000000000..950eb8aff5 --- /dev/null +++ b/ansible/roles/mailhog/tasks/main.yml @@ -0,0 +1,30 @@ +--- +- name: Install golang-go + apt: + pkg: + - golang-go + state: present + update_cache: yes + +- name: Install Mailhog + shell: "go install github.com/mailhog/MailHog@latest" + become: yes + become_user: root + +- name: Copy Mailhog to /usr/local/bin + copy: + src: /root/go/bin/MailHog + dest: /usr/local/bin/mailhog + owner: root + group: root + mode: 0755 + remote_src: yes + +- name: Create Service File + template: + src: "mailhog.service" + dest: /etc/systemd/system/mailhog.service + owner: root + group: root + mode: 0644 + notify: start and enable mailhog diff --git a/ansible/roles/mailhog/templates/mailhog.service b/ansible/roles/mailhog/templates/mailhog.service new file mode 100644 index 0000000000..e730275a9e --- /dev/null +++ b/ansible/roles/mailhog/templates/mailhog.service @@ -0,0 +1,11 @@ +[Unit] +Description=Mailhog +After=network.target +[Service] +ExecStart=/usr/local/bin/mailhog \ + -api-bind-addr 0.0.0.0:8025 \ + -ui-bind-addr 0.0.0.0:8025 \ + -smtp-bind-addr 0.0.0.0:1025 + +[Install] +WantedBy=multi-user.target \ No newline at end of file diff --git a/ansible/roles/memcached/defaults/main.yml b/ansible/roles/memcached/defaults/main.yml index cc5e768d91..892f66333b 100755 --- a/ansible/roles/memcached/defaults/main.yml +++ b/ansible/roles/memcached/defaults/main.yml @@ -1,5 +1,5 @@ --- -memory: 64 +memory: 512 tcp_port: 11_211 udp_port: 11_211 listen: 0.0.0.0 diff --git a/ansible/roles/mysql/handlers/main.yml b/ansible/roles/mysql/handlers/main.yml index 9ec0733d18..cdc2762168 100644 --- a/ansible/roles/mysql/handlers/main.yml +++ b/ansible/roles/mysql/handlers/main.yml @@ -3,3 +3,8 @@ service: name: mysql state: restarted + +- name: start mysql + service: + name: mysql + state: started diff --git a/ansible/roles/mysql/tasks/main.yml b/ansible/roles/mysql/tasks/main.yml index c09aa09656..44909d1f50 100755 --- a/ansible/roles/mysql/tasks/main.yml +++ b/ansible/roles/mysql/tasks/main.yml @@ -1,44 +1,45 @@ --- -- name: Download MySQL Apt Repo Setup Tool - get_url: - url: https://dev.mysql.com/get/mysql-apt-config_0.8.22-1_all.deb - dest: /tmp/mysql-apt-config.deb - force: false - -- name: ensure mysql upstream repository package is configured - debconf: - name: mysql-apt-config - question: "mysql-apt-config/{{ item.question }}" - value: "{{ item.value }}" - vtype: "{{ item.vtype | default ('select') }}" - with_items: - - question: select-server - value: "mysql-8.0" - become: yes - become_user: root - -- name: Run MySQL Apt Repo Setup Tool - apt: - deb: /tmp/mysql-apt-config.deb - become: yes - become_user: root - -- name: Apt Update +- name: Install MySQL Server & Client packages apt: + pkg: + - mysql-server + - mysql-client + state: present update_cache: yes - cache_valid_time: 3600 + when: mysql_environment != 'production' + environment: + DEBIAN_FRONTEND: noninteractive + register: mysql_server_installed + notify: start mysql -- name: Install MySQL packages +- name: Install MySQL Client Package apt: pkg: - - mysql-server - mysql-client state: present update_cache: yes + when: mysql_environment == 'production' environment: DEBIAN_FRONTEND: noninteractive + register: mysql_client_installed + +- name: MySQL configurations for XL AWS Instance + blockinfile: + path: /etc/mysql/mysql.conf.d/mysqld.cnf + block: | + max_allowed_packet=67108864 + key_buffer_size=64M + max_allowed_packet=64M + join_buffer_size=512K + max_connections=3000 + innodb_buffer_pool_size=12G + innodb_log_file_size=1G + innodb_buffer_pool_instances=12 + when: mysql_environment != 'production' -- name: start mysql - service: - name: mysql - state: started +- name: Install Alternative for /etc/alternatives/my.cnf + command: 'update-alternatives --install /etc/mysql/my.cnf my.cnf /etc/mysql/mysql.cnf 200' + when: mysql_environment != 'production' + become: yes + become_user: root + notify: restart mysql diff --git a/ansible/roles/nginx/tasks/main.yml b/ansible/roles/nginx/tasks/main.yml index c43fdc0830..0b45a58c58 100755 --- a/ansible/roles/nginx/tasks/main.yml +++ b/ansible/roles/nginx/tasks/main.yml @@ -1,7 +1,8 @@ --- - name: Add PPA - apt_repository: - repo: "ppa:ondrej/nginx-mainline" + shell: "add-apt-repository -y ppa:ondrej/nginx-mainline" + become: yes + become_user: root - name: Apt Update apt: @@ -9,9 +10,9 @@ - name: Install Nginx apt: - name: nginx - update_cache: yes - cache_valid_time: 3600 + pkg: + - nginx + state: present - name: Create SSL Directories (ssl.crt) file: @@ -34,6 +35,7 @@ mode: 0644 backup: yes with_items: "{{ nginx_ssl_crt }}" + when: nginx_environment == 'development' - name: COPY SSL KEYS copy: @@ -44,6 +46,7 @@ mode: 0644 backup: yes with_items: "{{ nginx_ssl_key }}" + when: nginx_environment == 'development' - name: Sites Available Configs template: diff --git a/ansible/roles/nginx/templates/development/sites-available/cakephp.app.local.conf b/ansible/roles/nginx/templates/development/sites-available/cakephp.app.local.conf index 23867c2b53..df68d196ca 100644 --- a/ansible/roles/nginx/templates/development/sites-available/cakephp.app.local.conf +++ b/ansible/roles/nginx/templates/development/sites-available/cakephp.app.local.conf @@ -26,7 +26,7 @@ server { # Pass the PHP scripts to FastCGI server location ~ \.php$ { - fastcgi_pass unix:/run/php/php8.1-fpm.sock; + fastcgi_pass unix:/run/php/php8.3-fpm.sock; fastcgi_index index.php; fastcgi_pass_header Set-Cookie; fastcgi_ignore_headers Cache-Control Expires; diff --git a/ansible/roles/nginx/templates/nginx.conf b/ansible/roles/nginx/templates/nginx.conf index 2286df7e07..3123840eed 100755 --- a/ansible/roles/nginx/templates/nginx.conf +++ b/ansible/roles/nginx/templates/nginx.conf @@ -41,7 +41,7 @@ http { # SSL Settings ## - ssl_protocols TLSv1.1 TLSv1.2; # Dropping SSLv3, ref: POODLE + ssl_protocols TLSv1.2 TLSv1.3; # Dropping SSLv3, ref: POODLE ssl_prefer_server_ciphers on; ssl_ciphers 'EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH'; ssl_session_cache shared:SSL:10m; diff --git a/ansible/roles/nodejs/defaults/main.yml b/ansible/roles/nodejs/defaults/main.yml index 4d1357ae8c..1db7ca7b4a 100755 --- a/ansible/roles/nodejs/defaults/main.yml +++ b/ansible/roles/nodejs/defaults/main.yml @@ -1,3 +1,3 @@ --- -nvm_version: v0.34.0 -nodejs_version: 12.10.0 +nvm_version: v0.39.7 +nodejs_version: 20.12.2 diff --git a/ansible/roles/ntp/tasks/main.yml b/ansible/roles/ntp/tasks/main.yml index bf012d1114..f44e92d727 100644 --- a/ansible/roles/ntp/tasks/main.yml +++ b/ansible/roles/ntp/tasks/main.yml @@ -7,5 +7,12 @@ - ntpdate state: present +- name: Copy configuration file + template: + src: ntp.conf + dest: /etc/ntp.conf + backup: yes + notify: restart ntp + - name: set timeone to UTC command: timedatectl set-timezone UTC diff --git a/ansible/roles/ntp/templates/ntp.conf b/ansible/roles/ntp/templates/ntp.conf new file mode 100644 index 0000000000..bc7e8f036e --- /dev/null +++ b/ansible/roles/ntp/templates/ntp.conf @@ -0,0 +1,63 @@ +# /etc/ntp.conf, configuration for ntpd; see ntp.conf(5) for help + +driftfile /var/lib/ntp/ntp.drift + +# Leap seconds definition provided by tzdata +leapfile /usr/share/zoneinfo/leap-seconds.list + +# Enable this if you want statistics to be logged. +#statsdir /var/log/ntpstats/ + +statistics loopstats peerstats clockstats +filegen loopstats file loopstats type day enable +filegen peerstats file peerstats type day enable +filegen clockstats file clockstats type day enable + +# Specify one or more NTP servers. + +# Use servers from the NTP Pool Project. Approved by Ubuntu Technical Board +# on 2011-02-08 (LP: #104525). See http://www.pool.ntp.org/join.html for +# more information. +pool tick.usno.navy.mil iburst +pool tock.usno.navy.mil iburst +pool time-a.nist.gov iburst +pool time-b.nist.gov iburst +pool time-c.nist.gov iburst +pool nist1.aol-va.symmetricom.com iburst +pool time-nw.nist.gov iburst + +# Use Ubuntu's ntp server as a fallback. +pool time.nist.gov + +# Access control configuration; see /usr/share/doc/ntp-doc/html/accopt.html for +# details. The web page +# might also be helpful. +# +# Note that "restrict" applies to both servers and clients, so a configuration +# that might be intended to block requests from certain clients could also end +# up blocking replies from your own upstream servers. + +# By default, exchange time with everybody, but don't allow configuration. +restrict -4 default kod notrap nomodify nopeer noquery limited +restrict -6 default kod notrap nomodify nopeer noquery limited + +# Local users may interrogate the ntp server more closely. +restrict 127.0.0.1 +restrict ::1 + +# Needed for adding pool entries +restrict source notrap nomodify noquery + +# Clients from this (example!) subnet have unlimited access, but only if +# cryptographically authenticated. +#restrict 192.168.123.0 mask 255.255.255.0 notrust + + +# If you want to provide time to your local subnet, change the next line. +# (Again, the address is an example only.) +#broadcast 192.168.123.255 + +# If you want to listen to time broadcasts on your local subnet, de-comment the +# next lines. Please do this only if you trust everybody on the network! +#disable auth +#broadcastclient diff --git a/ansible/roles/php/handlers/main.yml b/ansible/roles/php/handlers/main.yml index b285bd06eb..60e7ec0203 100755 --- a/ansible/roles/php/handlers/main.yml +++ b/ansible/roles/php/handlers/main.yml @@ -1,5 +1,5 @@ --- -- name: restart php8.1-fpm +- name: restart php8.3-fpm service: - name: php8.1-fpm + name: php8.3-fpm state: restarted diff --git a/ansible/roles/php/tasks/main.yml b/ansible/roles/php/tasks/main.yml index b45b022f34..426f807f48 100755 --- a/ansible/roles/php/tasks/main.yml +++ b/ansible/roles/php/tasks/main.yml @@ -1,7 +1,8 @@ --- - name: Add PPA - apt_repository: - repo: "ppa:ondrej/php" + shell: "add-apt-repository -y ppa:ondrej/php" + become: yes + become_user: root - name: Apt Update apt: @@ -10,41 +11,42 @@ - name: Install PHP and Dependencies apt: pkg: - - php8.1-fpm - - php8.1-cli - - php8.1-mysql - - php8.1-intl - - php8.1-ldap - - php8.1-sqlite3 - - php8.1-curl - - php8.1-xsl - - php8.1-imap - - php8.1-imagick - - php8.1-memcached - - php8.1-zip - - php8.1-mbstring + - php8.3-fpm + - php8.3-cli + - php8.3-mysql + - php8.3-intl + - php8.3-ldap + - php8.3-sqlite3 + - php8.3-curl + - php8.3-xsl + - php8.3-imap + - php8.3-imagick + - php8.3-memcached + - php8.3-zip + - php8.3-mbstring - php-json - - php8.1-soap - - php8.1-xml - - php8.1-gd + - php8.3-soap + - php8.3-xml + - php8.3-gd state: present - name: Install Composer get_url: - url: https://getcomposer.org/composer-stable.phar + url: https://getcomposer.org/composer.phar dest: /usr/local/bin/composer mode: 0755 validate_certs: no -- name: Configure php8.1-fpm pool. +- name: Configure php8.3-fpm pool. lineinfile: - dest: "/etc/php/8.1/fpm/pool.d/www.conf" + dest: "/etc/php/8.3/fpm/pool.d/www.conf" regexp: "{{ item.regexp }}" line: "{{ item.line }}" state: present + backrefs: yes with_items: - regexp: "^listen.?=.+$" - line: "listen = /run/php/php8.1-fpm.sock" + line: "listen = /run/php/php8.3-fpm.sock" - regexp: "^pm.max_children.?=.+$" line: "pm.max_children = 120" - regexp: "^pm.start_servers.?=.+$" @@ -56,15 +58,20 @@ - regexp: "^;pm.max_requests.?=.+$" line: "pm.max_requests = 500" -- name: Configure php8.1 php.ini +- name: Configure php8.3 php.ini lineinfile: - dest: "/etc/php/8.1/fpm/php.ini" + dest: "/etc/php/8.3/fpm/php.ini" regexp: "{{ item.regexp }}" line: "{{ item.line }}" state: present + backrefs: yes with_items: - regexp: "^post_max_size.?=.+$" line: "post_max_size = 108M" - regexp: "^upload_max_filesize.?=.+$" line: "upload_max_filesize = 100M" - notify: restart php8.1-fpm + - regexp: "^session.gc_probability.?=.+$" + line: "session.gc_probability = 1" + - regexp: "^;max_input_vars.?=.+$" + line: "max_input_vars = 3000" + notify: restart php8.3-fpm diff --git a/ansible/roles/system/tasks/main.yml b/ansible/roles/system/tasks/main.yml index 1282f467a5..13fea52216 100755 --- a/ansible/roles/system/tasks/main.yml +++ b/ansible/roles/system/tasks/main.yml @@ -14,7 +14,6 @@ apt: pkg: - curl - - python-pycurl - software-properties-common - htop - wget @@ -28,6 +27,9 @@ - libssl-dev - unzip - pandoc + - certbot + - python3-certbot-nginx + - run-one state: present - name: make a symbolic link for www diff --git a/ansible/roles/wkhtmltopdf/tasks/main.yml b/ansible/roles/wkhtmltopdf/tasks/main.yml index e65468d176..66d69fb62a 100755 --- a/ansible/roles/wkhtmltopdf/tasks/main.yml +++ b/ansible/roles/wkhtmltopdf/tasks/main.yml @@ -12,12 +12,21 @@ - xfonts-base state: present -- name: 'Download WkHtmlToPdf' +- name: 'Download WkHtmlToPdf arm64' + get_url: + url: https://github.com/wkhtmltopdf/packaging/releases/download/0.12.6-1/wkhtmltox_0.12.6-1.focal_arm64.deb + dest: /root/wkhtmltopdf.deb + force: false + validate_certs: no # this is fucked up + when: ansible_architecture == 'aarch64' + +- name: 'Download WkHtmlToPdf x86_64' get_url: url: https://github.com/wkhtmltopdf/packaging/releases/download/0.12.6-1/wkhtmltox_0.12.6-1.focal_amd64.deb dest: /root/wkhtmltopdf.deb force: false validate_certs: no # this is fucked up + when: ansible_architecture == 'x86_64' - name: 'Install WkHtmlToPdf' command: dpkg -i /root/wkhtmltopdf.deb diff --git a/composer.json b/composer.json index f89295b964..b290e48144 100644 --- a/composer.json +++ b/composer.json @@ -6,19 +6,19 @@ "license": "MIT", "require": { "php": ">=7.4", - "cakephp/cakephp": "4.4.*", - "cakephp/migrations": "^3.2", + "cakephp/cakephp": "^4.5.0", + "cakephp/migrations": "^3.7", "cakephp/plugin-installer": "^1.3", - "mobiledetect/mobiledetectlib": "^2.8", - "queencitycodefactory/butter-cream": "dev-cake-4.x" + "queencitycodefactory/butter-cream": "dev-cake-4.x", + "mobiledetect/mobiledetectlib": "^3.74" }, "require-dev": { - "cakephp/bake": "^2.6", + "cakephp/bake": "^2.8", "cakephp/cakephp-codesniffer": "^4.5", - "cakephp/debug_kit": "^4.5", - "josegonzalez/dotenv": "^3.2", + "cakephp/debug_kit": "^4.9", + "josegonzalez/dotenv": "^4.0", "phpstan/phpstan": "^0.12.7", - "phpunit/phpunit": "~8.5.0 || ^9.3", + "phpunit/phpunit": "^9.6", "psy/psysh": "@stable" }, "suggest": { diff --git a/config/app.php b/config/app.php index 7ef429f8e2..8dd829d4bc 100644 --- a/config/app.php +++ b/config/app.php @@ -426,7 +426,7 @@ * array with at least the `engine` key, being the name of the Session engine * class to use for managing the session. CakePHP bundles the `CacheSession` * and `DatabaseSession` engines. - * - `ini` - An associative array of additional ini values to set. + * - `ini` - An associative array of additional 'session.*` ini values to set. * * The built-in `defaults` options are: * @@ -435,7 +435,7 @@ * - 'database' - Uses CakePHP's database sessions. * - 'cache' - Use the Cache class to save sessions. * - * To define a custom session handler, save it at src/Network/Session/.php. + * To define a custom session handler, save it at src/Http/Session/.php. * Make sure the class implements PHP's `SessionHandlerInterface` and set * Session.handler to * @@ -459,4 +459,10 @@ //'Timezones' => [ // 'America/New_York' => 'Eastern', //], + + 'DebugKit' => [ + 'forceEnable' => filter_var(env('DEBUG_KIT_FORCE_ENABLE', false), FILTER_VALIDATE_BOOLEAN), + 'safeTld' => env('DEBUG_KIT_SAFE_TLD', null), + 'ignoreAuthorization' => env('DEBUG_KIT_IGNORE_AUTHORIZATION', false) + ], ]; diff --git a/config/app_local.example.php b/config/app_local.example.php index 200f89e531..76aeef9335 100644 --- a/config/app_local.example.php +++ b/config/app_local.example.php @@ -44,10 +44,10 @@ */ //'port' => 'non_standard_port_number', - 'username' => 'my_app', - 'password' => 'secret', + 'username' => 'vagrant', + 'password' => 'vagrant', - 'database' => 'my_app', + 'database' => 'cakephp_app', /* * If not using the default 'public' schema with the PostgreSQL driver * set it here. @@ -66,11 +66,11 @@ 'test' => [ 'host' => 'localhost', //'port' => 'non_standard_port_number', - 'username' => 'my_app', - 'password' => 'secret', - 'database' => 'test_myapp', + 'username' => 'vagrant', + 'password' => 'vagrant', + 'database' => 'test_cakephp_app', //'schema' => 'myapp', - 'url' => env('DATABASE_TEST_URL', 'sqlite://127.0.0.1/tests.sqlite'), + 'url' => env('DATABASE_TEST_URL', 'sqlite://127.0.0.1/tmp/tests.sqlite'), ], ], diff --git a/config/bootstrap.php b/config/bootstrap.php index 50d2b1fd78..150284a1cb 100644 --- a/config/bootstrap.php +++ b/config/bootstrap.php @@ -104,7 +104,7 @@ /* * Set the default server timezone. Using UTC makes time calculations / conversions easier. - * Check http://php.net/manual/en/timezones.php for list of valid timezone strings. + * Check https://php.net/manual/en/timezones.php for list of valid timezone strings. */ date_default_timezone_set(Configure::read('App.defaultTimezone')); @@ -234,3 +234,9 @@ //Inflector::rules('plural', ['/^(inflect)or$/i' => '\1ables']); //Inflector::rules('irregular', ['red' => 'redlings']); //Inflector::rules('uninflected', ['dontinflectme']); + +// set a custom date and time format +// see https://book.cakephp.org/4/en/core-libraries/time.html#setting-the-default-locale-and-format-string +// and https://unicode-org.github.io/icu/userguide/format_parse/datetime/#datetime-format-syntax +//\Cake\I18n\FrozenDate::setToStringFormat('dd.MM.yyyy'); +//\Cake\I18n\FrozenTime::setToStringFormat('dd.MM.yyyy HH:mm'); diff --git a/config/routes.php b/config/routes.php index 0c7a312730..5ef5694fa4 100644 --- a/config/routes.php +++ b/config/routes.php @@ -24,7 +24,12 @@ use Cake\Routing\Route\DashedRoute; use Cake\Routing\RouteBuilder; -return static function (RouteBuilder $routes) { +/* + * This file is loaded in the context of the `Application` class. + * So you can use `$this` to reference the application class instance + * if required. + */ +return function (RouteBuilder $routes): void { /* * The default class to use for all routes * @@ -44,7 +49,7 @@ */ $routes->setRouteClass(DashedRoute::class); - $routes->scope('/', function (RouteBuilder $builder) { + $routes->scope('/', function (RouteBuilder $builder): void { /* * Router Extensions */ @@ -86,7 +91,7 @@ * open new scope and define routes there. * * ``` - * $routes->scope('/api', function (RouteBuilder $builder) { + * $routes->scope('/api', function (RouteBuilder $builder): void { * // No $builder->applyMiddleware() here. * * // Parse specified extensions from URLs diff --git a/cron.d/empty b/cron.d/empty new file mode 100644 index 0000000000..e69de29bb2 diff --git a/gulpfile.js b/gulpfile.js index 4fde60e452..8db78ef0e2 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -9,7 +9,7 @@ const concat = require('gulp-concat'); const expectFile = require('gulp-expect-file'); const flatmap = require('gulp-flatmap'); const jshint = require('gulp-jshint'); -const sass = require('gulp-sass'); +const sass = require('gulp-sass')(require('sass')); const plumber = require('gulp-plumber'); const postcss = require('gulp-postcss'); const postcssImport = require('postcss-import'); diff --git a/package.json b/package.json index 3a7535af33..7450c77b4e 100644 --- a/package.json +++ b/package.json @@ -12,14 +12,14 @@ "author": "Willetts Technology, Inc.", "license": "UNLICENSED", "dependencies": { - "@fortawesome/fontawesome-free": "^5.13.0", + "@fortawesome/fontawesome-free": "^5.15.4", "@ttskch/select2-bootstrap4-theme": "^1.4.0", - "bootstrap": "^4.5.2", + "bootstrap": "^4.6.2", "inputmask": "^5.0.5", - "jquery": "^3.5.1", + "jquery": "^3.6.1", "jquery-countdown": "^2.2.0", "jsrender": "^1.0.6", - "moment": "^2.26.0", + "moment": "^2.29.4", "npm": "^6.14.8", "popper.js": "^1.16.1", "select2": "^4.0.13", @@ -43,15 +43,16 @@ "gulp-postcss": "^8.0.0", "gulp-rename": "^2.0.0", "gulp-replace": "^1.0.0", - "gulp-sass": "^4.1.0", + "gulp-sass": "^5.1.0", "gulp-sourcemaps": "^2.6.5", "gulp-uglify": "^3.0.2", "gulp-wait": "0.0.2", - "jshint": "^2.12.0", + "jshint": "^2.13.5", "jshint-stylish": "^2.2.1", "merge-stream": "^2.0.0", "path": "^0.12.7", "postcss-import": "^12.0.1", + "sass": "^1.57.1", "stream-switch": "^0.1.1", "through2": "^3.0.1" } diff --git a/phpcs.xml b/phpcs.xml index f58219da1c..9c508e896a 100644 --- a/phpcs.xml +++ b/phpcs.xml @@ -3,4 +3,7 @@ + + src/ + tests/ diff --git a/phpstan.neon b/phpstan.neon index 7bf37ab949..da361a890d 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -2,6 +2,7 @@ parameters: level: 8 checkMissingIterableValueType: false treatPhpDocTypesAsCertain: false + checkGenericClassInNonGenericObjectType: false paths: - src/ excludePaths: diff --git a/src/Application.php b/src/Application.php index f4a0508b61..2f5c686371 100644 --- a/src/Application.php +++ b/src/Application.php @@ -81,7 +81,7 @@ public function middleware(MiddlewareQueue $middlewareQueue): MiddlewareQueue $middlewareQueue // Catch any exceptions in the lower layers, // and make an error page/response - ->add(new ErrorHandlerMiddleware(Configure::read('Error'))) + ->add(new ErrorHandlerMiddleware(Configure::read('Error'), $this)) // Handle plugin/theme assets like CakePHP normally does. ->add(new AssetMiddleware([ @@ -90,10 +90,8 @@ public function middleware(MiddlewareQueue $middlewareQueue): MiddlewareQueue // Add routing middleware. // If you have a large number of routes connected, turning on routes - // caching in production could improve performance. For that when - // creating the middleware instance specify the cache config name by - // using it's second constructor argument: - // `new RoutingMiddleware($this, '_cake_routes_')` + // caching in production could improve performance. + // See https://github.com/CakeDC/cakephp-cached-routing ->add(new RoutingMiddleware($this)) // Parse various types of encoded request bodies so that they are @@ -130,7 +128,6 @@ public function services(ContainerInterface $container): void */ protected function bootstrapCli(): void { - $this->addOptionalPlugin('Cake/Repl'); $this->addOptionalPlugin('Bake'); $this->addPlugin('Migrations'); diff --git a/src/Controller/ErrorController.php b/src/Controller/ErrorController.php index 27dfde5012..aa7ee4e87f 100644 --- a/src/Controller/ErrorController.php +++ b/src/Controller/ErrorController.php @@ -38,7 +38,7 @@ public function initialize(): void /** * beforeFilter callback. * - * @param \Cake\Event\EventInterface $event Event. + * @param \Cake\Event\EventInterface<\App\Controller\ErrorController> $event Event. * @return \Cake\Http\Response|null|void */ public function beforeFilter(EventInterface $event) @@ -48,7 +48,7 @@ public function beforeFilter(EventInterface $event) /** * beforeRender callback. * - * @param \Cake\Event\EventInterface $event Event. + * @param \Cake\Event\EventInterface<\App\Controller\ErrorController> $event Event. * @return \Cake\Http\Response|null|void */ public function beforeRender(EventInterface $event) @@ -61,7 +61,7 @@ public function beforeRender(EventInterface $event) /** * afterFilter callback. * - * @param \Cake\Event\EventInterface $event Event. + * @param \Cake\Event\EventInterface<\App\Controller\ErrorController> $event Event. * @return \Cake\Http\Response|null|void */ public function afterFilter(EventInterface $event) diff --git a/templates/Error/error400.php b/templates/Error/error400.php index 68c0e63418..9ead1656c8 100644 --- a/templates/Error/error400.php +++ b/templates/Error/error400.php @@ -25,13 +25,14 @@

params)) : ?> - SQL Query Params: - params) ?> + SQL Query Params: + params) ?> -element('auto_table_warning') ?> + element('auto_table_warning'); -$this->end(); + $this->end(); endif; ?>

diff --git a/templates/Error/error500.php b/templates/Error/error500.php index 0295c760d8..4f08488e90 100644 --- a/templates/Error/error500.php +++ b/templates/Error/error500.php @@ -29,8 +29,10 @@ params) ?> + getFile() ?> + getLine() ?> Error in: - getFile()), $error->getLine()) ?> + Html->link(sprintf('%s, line %s', Debugger::trimPath($file), $line), Debugger::editorUrl($file, $line)); ?> element('auto_table_warning'); diff --git a/templates/Pages/home.php b/templates/Pages/home.php index 920fbfd75a..6d111cc4cf 100644 --- a/templates/Pages/home.php +++ b/templates/Pages/home.php @@ -36,6 +36,14 @@ $error .= '
' . $attributes['message']; } } + if ($name === 'debug_kit') { + $error = 'Try adding your current top level domain to the + DebugKit.safeTld + config and reload.'; + if (!in_array('sqlite', \PDO::getAvailableDrivers())) { + $error .= '
You need to install the PHP extension pdo_sqlite so DebugKit can work properly.'; + } + } } return compact('connected', 'error'); @@ -59,9 +67,7 @@ Html->meta('icon') ?> - - - Html->css(['normalize.min', 'milligram.min', 'cake', 'home']) ?> + Html->css(['normalize.min', 'milligram.min', 'fonts', 'cake', 'home']) ?> fetch('meta') ?> fetch('css') ?> @@ -179,7 +185,7 @@
  • DebugKit can connect to the database.
  • -
  • DebugKit is not able to connect to the database.
  • +
  • There are configuration problems present which need to be fixed:
  • DebugKit is not loaded.
  • @@ -200,9 +206,9 @@
    diff --git a/templates/email/html/default.php b/templates/email/html/default.php index bf4c13188a..70a6cd4492 100644 --- a/templates/email/html/default.php +++ b/templates/email/html/default.php @@ -11,7 +11,7 @@ * @link https://cakephp.org CakePHP(tm) Project * @since 0.10.0 * @license https://opensource.org/licenses/mit-license.php MIT License - * @var \App\View\AppView $this + * @var \Cake\View\View $this * @var string $content */ diff --git a/templates/email/text/default.php b/templates/email/text/default.php index bb8461e66b..cb1f378451 100644 --- a/templates/email/text/default.php +++ b/templates/email/text/default.php @@ -11,7 +11,7 @@ * @link https://cakephp.org CakePHP(tm) Project * @since 0.10.0 * @license https://opensource.org/licenses/mit-license.php MIT License - * @var \App\View\AppView $this + * @var \Cake\View\View $this * @var string $content */ diff --git a/templates/layout/error.php b/templates/layout/error.php index 28c09bac4e..2b26a16da0 100644 --- a/templates/layout/error.php +++ b/templates/layout/error.php @@ -23,9 +23,7 @@ Html->meta('icon') ?> - - - Html->css(['normalize.min', 'milligram.min', 'cake']) ?> + Html->css(['normalize.min', 'milligram.min', 'fonts', 'cake']) ?> fetch('meta') ?> fetch('css') ?> diff --git a/vagrant.yml b/vagrant.yml index 4fcbedf67f..57b050b62b 100644 --- a/vagrant.yml +++ b/vagrant.yml @@ -1,7 +1,9 @@ --- -box: "bento/ubuntu-20.04" +box: "bento/ubuntu-22.04" +arm64_box: "bento/ubuntu-22.04-arm64" name: cakephp-app hostname: "cakephp-app-vagrant-box" +vm_name: "CakePHP App" app_path: "/var/www/cakephp-app/" aliases: - cakephp.app.local diff --git a/webroot/css/cake.css b/webroot/css/cake.css index 10b9289371..f8da0bc1bf 100644 --- a/webroot/css/cake.css +++ b/webroot/css/cake.css @@ -67,6 +67,9 @@ body { font-weight: bold; padding: 0 0.4rem; } +.actions a:first-child { + padding-left: 0; +} th { white-space: nowrap; } diff --git a/webroot/css/fonts.css b/webroot/css/fonts.css new file mode 100644 index 0000000000..1ba4808f40 --- /dev/null +++ b/webroot/css/fonts.css @@ -0,0 +1,80 @@ +/* cyrillic-ext */ +@font-face { + font-family: 'Raleway'; + font-style: normal; + font-weight: 400; + src: url('../font/raleway-400-cyrillic-ext.woff2') format('woff2'); + unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F; +} +/* cyrillic */ +@font-face { + font-family: 'Raleway'; + font-style: normal; + font-weight: 400; + src: url('../font/raleway-400-cyrillic.woff2') format('woff2'); + unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; +} +/* vietnamese */ +@font-face { + font-family: 'Raleway'; + font-style: normal; + font-weight: 400; + src: url('../font/raleway-400-vietnamese.woff2') format('woff2'); + unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+1EA0-1EF9, U+20AB; +} +/* latin-ext */ +@font-face { + font-family: 'Raleway'; + font-style: normal; + font-weight: 400; + src: url('../font/raleway-400-latin-ext.woff2') format('woff2'); + unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF; +} +/* latin */ +@font-face { + font-family: 'Raleway'; + font-style: normal; + font-weight: 400; + src: url('../font/raleway-400-latin.woff2') format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; +} +/* cyrillic-ext */ +@font-face { + font-family: 'Raleway'; + font-style: normal; + font-weight: 700; + src: url('../font/raleway-700-cyrillic-ext.woff2') format('woff2'); + unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F; +} +/* cyrillic */ +@font-face { + font-family: 'Raleway'; + font-style: normal; + font-weight: 700; + src: url('../font/raleway-700-cyrillic.woff2') format('woff2'); + unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; +} +/* vietnamese */ +@font-face { + font-family: 'Raleway'; + font-style: normal; + font-weight: 700; + src: url('../font/raleway-700-vietnamese.woff2') format('woff2'); + unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+1EA0-1EF9, U+20AB; +} +/* latin-ext */ +@font-face { + font-family: 'Raleway'; + font-style: normal; + font-weight: 700; + src: url('../font/raleway-700-latin-ext.woff2') format('woff2'); + unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF; +} +/* latin */ +@font-face { + font-family: 'Raleway'; + font-style: normal; + font-weight: 700; + src: url('../font/raleway-700-latin.woff2') format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; +} diff --git a/webroot/font/raleway-400-cyrillic-ext.woff2 b/webroot/font/raleway-400-cyrillic-ext.woff2 new file mode 100644 index 0000000000..039269ecd6 Binary files /dev/null and b/webroot/font/raleway-400-cyrillic-ext.woff2 differ diff --git a/webroot/font/raleway-400-cyrillic.woff2 b/webroot/font/raleway-400-cyrillic.woff2 new file mode 100644 index 0000000000..48b9d896c2 Binary files /dev/null and b/webroot/font/raleway-400-cyrillic.woff2 differ diff --git a/webroot/font/raleway-400-latin-ext.woff2 b/webroot/font/raleway-400-latin-ext.woff2 new file mode 100644 index 0000000000..0eedc5bb67 Binary files /dev/null and b/webroot/font/raleway-400-latin-ext.woff2 differ diff --git a/webroot/font/raleway-400-latin.woff2 b/webroot/font/raleway-400-latin.woff2 new file mode 100644 index 0000000000..d0e6f01908 Binary files /dev/null and b/webroot/font/raleway-400-latin.woff2 differ diff --git a/webroot/font/raleway-400-vietnamese.woff2 b/webroot/font/raleway-400-vietnamese.woff2 new file mode 100644 index 0000000000..405fb25048 Binary files /dev/null and b/webroot/font/raleway-400-vietnamese.woff2 differ diff --git a/webroot/font/raleway-700-cyrillic-ext.woff2 b/webroot/font/raleway-700-cyrillic-ext.woff2 new file mode 100644 index 0000000000..039269ecd6 Binary files /dev/null and b/webroot/font/raleway-700-cyrillic-ext.woff2 differ diff --git a/webroot/font/raleway-700-cyrillic.woff2 b/webroot/font/raleway-700-cyrillic.woff2 new file mode 100644 index 0000000000..48b9d896c2 Binary files /dev/null and b/webroot/font/raleway-700-cyrillic.woff2 differ diff --git a/webroot/font/raleway-700-latin-ext.woff2 b/webroot/font/raleway-700-latin-ext.woff2 new file mode 100644 index 0000000000..0eedc5bb67 Binary files /dev/null and b/webroot/font/raleway-700-latin-ext.woff2 differ diff --git a/webroot/font/raleway-700-latin.woff2 b/webroot/font/raleway-700-latin.woff2 new file mode 100644 index 0000000000..d0e6f01908 Binary files /dev/null and b/webroot/font/raleway-700-latin.woff2 differ diff --git a/webroot/font/raleway-700-vietnamese.woff2 b/webroot/font/raleway-700-vietnamese.woff2 new file mode 100644 index 0000000000..405fb25048 Binary files /dev/null and b/webroot/font/raleway-700-vietnamese.woff2 differ