Merge branch 'master' into turbo

This commit is contained in:
Jan Böhmer 2022-07-24 01:26:22 +02:00
commit 79a1715290
55 changed files with 3699 additions and 3329 deletions

3
.env
View file

@ -9,6 +9,7 @@
# Real environment variables win over .env files.
#
# DO NOT DEFINE PRODUCTION SECRETS IN THIS FILE NOR IN ANY OTHER COMMITTED FILES.
# https://symfony.com/doc/current/configuration/secrets.html
#
# 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
@ -82,5 +83,5 @@ HISTORY_SAVE_REMOVED_DATA=0
###> symfony/mailer ###
# MAILER_DSN=smtp://localhost
# MAILER_DSN=null://null
###< symfony/mailer ###

View file

@ -18,32 +18,38 @@ jobs:
steps:
-
name: Checkout
uses: actions/checkout@v2
uses: actions/checkout@v3
-
name: Docker meta
id: docker_meta
uses: crazy-max/ghaction-docker-meta@v1
uses: docker/metadata-action@v4
with:
# list of Docker images to use as base name for tags
images: |
jbtronics/part-db1
# Mark the image build from master as latest (as we dont have really releases yet)
tags: |
type=raw,value=latest,enable={{is_default_branch}}
type=ref,event=branch,
type=ref,event=tag,
-
name: Set up QEMU
uses: docker/setup-qemu-action@v1
uses: docker/setup-qemu-action@v2
-
name: Set up Docker Buildx
uses: docker/setup-buildx-action@v1
uses: docker/setup-buildx-action@v2
-
name: Login to DockerHub
if: github.event_name != 'pull_request'
uses: docker/login-action@v1
uses: docker/login-action@v2
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
-
name: Build and push
uses: docker/build-push-action@v2
uses: docker/build-push-action@v3
with:
context: .
push: ${{ github.event_name != 'pull_request' }}

View file

@ -12,14 +12,14 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v3
- name: Get Composer Cache Directory
id: composer-cache
run: |
echo "::set-output name=dir::$(composer config cache-files-dir)"
- uses: actions/cache@v1
- uses: actions/cache@v3
with:
path: ${{ steps.composer-cache.outputs.dir }}
key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }}

View file

@ -12,23 +12,34 @@ on:
jobs:
phpunit:
name: PHPUnit and coverage Test (${{ matrix.php-versions }})
name: PHPUnit and coverage Test (PHP ${{ matrix.php-versions }}, ${{ matrix.db-type }})
# Ubuntu 20.04 ships MySQL 8.0 which causes problems with login, so we just use ubuntu 18.04 for now...
runs-on: ubuntu-18.04
env:
APP_ENV: test
SYMFONY_DEPRECATIONS_HELPER: disabled
DATABASE_URL: 'mysql://root:root@127.0.0.1:3306/test'
PHP_VERSION: ${{ matrix.php-versions }}
strategy:
matrix:
php-versions: ['7.3', '7.4', '8.0', '8.1']
php-versions: [ '7.3', '7.4', '8.0', '8.1' ]
db-type: [ 'mysql', 'sqlite' ]
env:
# Note that we set DATABASE URL later based on our db-type matrix value
APP_ENV: test
SYMFONY_DEPRECATIONS_HELPER: disabled
PHP_VERSION: ${{ matrix.php-versions }}
DB_TYPE: ${{ matrix.db-type }}
steps:
- name: Set Database env for MySQL
run: echo "DATABASE_URL=mysql://root:root@127.0.0.1:3306/test" >> $GITHUB_ENV
if: matrix.db-type == 'mysql'
- name: Set Database env for SQLite
run: echo "DATABASE_URL="sqlite:///%kernel.project_dir%/var/app_test.db"" >> $GITHUB_ENV
if: matrix.db-type == 'sqlite'
- name: Checkout
uses: actions/checkout@v2
uses: actions/checkout@v3
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
@ -63,7 +74,7 @@ jobs:
id: yarn-cache-dir-path
run: echo "::set-output name=dir::$(yarn cache dir)"
- uses: actions/cache@v1
- uses: actions/cache@v3
id: yarn-cache # use this to check for `cache-hit` (`steps.yarn-cache.outputs.cache-hit != 'true'`)
with:
path: ${{ steps.yarn-cache-dir-path.outputs.dir }}
@ -75,9 +86,9 @@ jobs:
run: composer install --prefer-dist --no-progress
- name: Setup node
uses: actions/setup-node@v1
uses: actions/setup-node@v3
with:
node-version: '12'
node-version: '16'
- name: Install yarn dependencies
run: yarn install
@ -87,6 +98,12 @@ jobs:
- name: Create DB
run: php bin/console --env test doctrine:database:create --if-not-exists -n
if: matrix.db-type == 'mysql'
# Checkinf for existance is not supported for sqlite, so do it without it
- name: Create DB
run: php bin/console --env test doctrine:database:create -n
if: matrix.db-type == 'sqlite'
- name: Do migrations
run: php bin/console --env test doctrine:migrations:migrate -n
@ -98,9 +115,9 @@ jobs:
run: ./bin/phpunit --coverage-clover=coverage.xml
- name: Upload coverage
uses: codecov/codecov-action@v1
uses: codecov/codecov-action@v3
with:
env_vars: PHP_VERSION
env_vars: PHP_VERSION,DB_TYPE
- name: Test app:clean-attachments
run: php bin/console app:clean-attachments -n

View file

@ -1,14 +1,30 @@
FROM php:7-apache
FROM php:8.1-apache
# Install needed dependencies for PHP build
RUN apt-get update && apt-get install -y pkg-config curl libcurl4-openssl-dev libicu-dev \
libpng-dev libjpeg-dev libfreetype6-dev gnupg zip libzip-dev libonig-dev libxslt-dev vim \
libpng-dev libjpeg-dev libfreetype6-dev gnupg zip libzip-dev libjpeg62-turbo-dev libonig-dev libxslt-dev libwebp-dev vim \
&& apt-get -y autoremove && apt-get clean autoclean && rm -rf /var/lib/apt/lists/*
# Install GD (we have to configure GD first before installing it, see issue #115)
RUN docker-php-ext-configure gd --with-freetype --with-jpeg && docker-php-ext-install gd
# Install GD with support for multiple formats
RUN docker-php-ext-configure gd \
--with-webp \
--with-jpeg \
--with-freetype \
&& docker-php-ext-install gd
# Install other needed PHP extensions
RUN docker-php-ext-install pdo_mysql curl intl mbstring bcmath gd zip xml xsl
RUN docker-php-ext-install pdo_mysql curl intl mbstring bcmath zip xml xsl
# Enable opcache and configure it recommended for symfony (see https://symfony.com/doc/current/performance.html)
RUN docker-php-ext-enable opcache; \
{ \
echo 'opcache.memory_consumption=256'; \
echo 'opcache.max_accelerated_files=20000'; \
echo 'opcache.validate_timestamp=0'; \
# Configure Realpath cache for performance
echo 'realpath_cache_size=4096K'; \
echo 'realpath_cache_ttl=600'; \
} > /usr/local/etc/php/conf.d/symfony-recommended.ini
# Install yarn
RUN curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add -

View file

@ -7,6 +7,7 @@
![Docker Pulls](https://img.shields.io/docker/pulls/jbtronics/part-db1)
![Docker Build Status](https://github.com/Part-DB/Part-DB-symfony/workflows/Docker%20Image%20Build/badge.svg)
[![Crowdin](https://badges.crowdin.net/e/8325196085d4bee8c04b75f7c915452a/localized.svg)](https://part-db.crowdin.com/part-db)
# Part-DB
Part-DB is an Open-Source inventory managment system for your electronic components.
@ -67,6 +68,8 @@ See [UPGRADE](UPGRADE.md) for more infos.
*Hint:* A docker image is available under [jbtronics/part-db1](https://hub.docker.com/r/jbtronics/part-db1). How to setup Part-DB via docker is described [here](https://github.com/Part-DB/Part-DB-symfony/blob/master/docs/docker/docker-install.md).
**Below you find some general hints for installtion, see [here](docs/installation/installation_guide-debian.md) for a detailed guide how to install Part-DB on Debian/Ubuntu.**
1. Copy or clone this repository into a folder on your server.
2. Configure your webserver to serve from the `public/` folder. See [here](https://symfony.com/doc/current/setup/web_server_configuration.html)
for additional informations.
@ -74,7 +77,7 @@ for additional informations.
* Change the line `APP_ENV=dev` to `APP_ENV=prod`
* If you do not want to use SQLite, change the value of `DATABASE_URL=` to your needs (see [here](http://docs.doctrine-project.org/projects/doctrine-dbal/en/latest/reference/configuration.html#connecting-using-a-url)) for the format.
In bigger instances with concurrent accesses, MySQL is more performant. This can not be changed easily later, so choose wisely.
4. Install composer dependencies and generate autoload files: `composer install --no-dev`
4. Install composer dependencies and generate autoload files: `composer install -o --no-dev`
5. If you have put Part-DB into a sub-directory on your server (like `part-db/`), you have to edit the file
`webpack.config.js` and uncomment the lines (remove the `//` before the lines) `.setPublicPath('/part-db/build')` (line 43) and
`.setManifestKeyPrefix('build/')` (line 44). You have to replace `/part-db` with your own path on line 44.
@ -89,6 +92,10 @@ for additional informations.
When you want to upgrade to a newer version, then just copy the new files into the folder
and repeat the steps 4. to 7.
### Reverse proxy
If you are using a reverse proxy, you have to ensure that the proxies sets the `X-Forwarded-*` headers correctly, or you will get HTTP/HTTPS mixup and wrong hostnames.
If the reverse proxy is on a different server (or it cannot access Part-DB via localhost) you have to set the `TRUSTED_PROXIES` env variable to match your reverse proxies IP-address (or IP block). You can do this in your `.env.local` or (when using docker) in your `docker-compose.yml` file.
## Useful console commands
Part-DB provides some command consoles which can be invoked by `php bin/console [command]`. You can get help for every command with the parameter `--help`.
Useful commands are:

View file

@ -300,7 +300,7 @@ $(document).on("ajaxUI:start ajaxUI:reload", function() {
}
//@ts-ignore
var clipboard = new ClipboardJS('.btn');
var clipboard = new ClipboardJS('.btn[data-clipboard-target], .btn[data-clipboard-text], .btn[data-clipboard-action]');
clipboard.on('success', function(e) {
setTooltip(e.trigger, 'Copied!');
hideTooltip(e.trigger);

View file

@ -2,7 +2,7 @@
"type": "project",
"license": "AGPL-3.0-or-later",
"require": {
"php": "^7.3",
"php": "^7.3 || ^8.0",
"ext-ctype": "*",
"ext-gd": "*",
"ext-iconv": "*",
@ -16,7 +16,7 @@
"doctrine/doctrine-bundle": "^2.0",
"doctrine/doctrine-migrations-bundle": "^3.0",
"doctrine/orm": "^2.9",
"dompdf/dompdf": "^1.0.1",
"dompdf/dompdf": "^2.0.0",
"erusev/parsedown": "^1.7",
"florianv/swap": "^4.0",
"florianv/swap-bundle": "dev-master",
@ -71,7 +71,7 @@
"webmozart/assert": "^1.4"
},
"require-dev": {
"dama/doctrine-test-bundle": "^6.0",
"dama/doctrine-test-bundle": "^7.0",
"doctrine/doctrine-fixtures-bundle": "^3.2",
"ekino/phpstan-banned-code": "^v1.0.0",
"phpstan/extension-installer": "^1.0",
@ -87,7 +87,7 @@
"symfony/phpunit-bridge": "5.4.*",
"symfony/stopwatch": "^5.2",
"symfony/web-profiler-bundle": "^5.2",
"symplify/easy-coding-standard": "^10.1.1",
"symplify/easy-coding-standard": "^11.0",
"vimeo/psalm": "^4.3.2"
},
"suggest": {

1903
composer.lock generated

File diff suppressed because it is too large Load diff

View file

@ -2,7 +2,19 @@
framework:
secret: '%env(APP_SECRET)%'
csrf_protection: true
http_method_override: false
# Must be set to true, to enable the change of HTTP methhod via _method parameter, otherwise our delete routines does not work anymore
# TODO: Rework delete routines to work without _method parameter as it is not recommended anymore (see https://github.com/symfony/symfony/issues/45278)
http_method_override: true
# Allow users to configure trusted hosts via .env variables
# see https://symfony.com/doc/current/reference/configuration/framework.html#trusted-hosts
trusted_hosts: '%env(TRUSTED_HOSTS)%'
# Allow users to configure reverse proxies via .env variables. Default values are defined in parameters.yaml.
trusted_proxies: '%env(TRUSTED_PROXIES)%'
# Trust all headers by default. X-Forwared-Host can be a security risk if your reverse proxy doesn't set it.
trusted_headers: ['x-forwarded-for', 'x-forwarded-host', 'x-forwarded-proto', 'x-forwarded-port', 'x-forwarded-prefix']
# 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.

View file

@ -1,5 +1,7 @@
framework:
default_locale: '%partdb.locale%'
# Just enable the locales we need for performance reasons.
enabled_locale: '%partdb.locale_menu%'
translator:
default_path: '%kernel.project_dir%/translations'
fallbacks:

View file

@ -50,4 +50,5 @@ parameters:
env(DEMO_MODE): 0
env(ALLOW_ATTACHMENT_DOWNLOADS): 0
env(TRUSTED_PROXIES): '127.0.0.1' #By default trust only our own server
env(TRUSTED_HOSTS): '' # Trust all host names by default

3
docs/docker/.gitignore vendored Normal file
View file

@ -0,0 +1,3 @@
db/
public_media/
uploads/

View file

@ -9,5 +9,11 @@ services:
# By default
- ./uploads:/var/www/html/uploads
- ./public_media:/var/www/html/public/media
- ./db:/var/www/html/var/db
restart: unless-stopped
image: jbtronics/part-db1:master
image: jbtronics/part-db1:latest
environment:
# Put SQLite database in our mapped folder. You can configure some other kind of database here too.
- DATABASE_URL=sqlite:///%kernel.project_dir%/var/db/app.db
# In demo env logs will be redirected to stderr
- APP_ENV=demo

View file

@ -19,6 +19,9 @@ The docker image uses a SQLite database and all data (database, uploads and othe
## Direct use of docker image
You can use the `jbtronics/part-db1:master` image directly. You have to expose the port 80 to a host port and configure volumes for `/var/www/html/uploads` and `/var/www/html/public/media`.
If you want to use SQLite database (which is default), you have to configure Part-DB to put the database file in a mapped volume via the `DATABASE_URL` environment variable.
For example if you set `DATABASE_URL=sqlite:///%kernel.project_dir%/var/db/app.db` then you will have to map the `/var/www/html/var/db/` folder to the docker container (see docker-compose.yaml for example).
You also have to create the database like described above in step 4.
## Running console commands

View file

@ -0,0 +1,178 @@
# Part-DB installation guide for Debian 11 (Bullseye)
This guide shows you how to install Part-DB directly on Debian 11 using apache2 and SQLite. This guide should work with recent Ubuntu and other Debian based distributions with little to no changes.
Depending on what you want to do, using the prebuilt docker images may be a better choice, as you dont need to install this much dependencies. See **TODO** for more information of the docker installation.
**Caution: This guide shows you how to install Part-DB for use in a trusted local network. If you want to use Part-DB on the internet, you HAVE TO setup a SSL certificate for your connection!**
## Install prerequisites
For the installation of Part-DB, we need some prerequisites. They can be installed by running the following command:
```bash
sudo apt install git curl zip ca-certificates software-properties-common apt-transport-https lsb-release nano wget
```
## Install PHP and apache2
Part-DB is written in [PHP](https://php.net) and therefore needs an PHP interpreter to run. Part-DB needs PHP 7.3 or higher, however it is recommended to use the most recent version of PHP for performance reasons and future compatibility.
As Debian 11 does not ship PHP 8.1 in it's default repositories, we have to add a repository for it. You can skip this step if your distribution is shipping a recent version of PHP or you want to use the built-in PHP version.
```bash
# Add sury repository for PHP 8.1
sudo curl -sSL https://packages.sury.org/php/README.txt | sudo bash -x
# Update package list
sudo apt update && sudo apt upgrade
```
Now you can install PHP 8.1 and required packages (change the 8.1 in the package version according to the version you want to use):
```bash
sudo apt install php8.1 libapache2-mod-php8.1 php8.1-opcache php8.1-curl php8.1-gd php8.1-mbstring php8.1-xml php8.1-bcmath php8.1-intl php8.1-zip php8.1-xsl php8.1-sqlite3 php8.1-mysql
```
The apache2 webserver should be already installed with this command and configured basically.
## Install composer
Part-DB uses [composer](https://getcomposer.org/) to install required PHP libraries. As the versions shipped in the repositories is pretty old we install it manually:
```bash
# Download composer installer script
wget -O /tmp/composer-setup.php https://getcomposer.org/installer
# Install composer globally
php /tmp/composer-setup.php --install-dir=/usr/local/bin --filename=composer
# Make composer executable
chmod +x /usr/local/bin/composer
```
## Install yarn and nodejs
To build the frontend (the user interface) Part-DB uses [yarn](https://yarnpkg.com/). As it dependens on nodejs and the shipped versions are pretty old, we install new versions from offical nodejs repository:
```bash
# Add recent node repository (nodejs 18 is supported until 2025)
curl -sL https://deb.nodesource.com/setup_18.x | sudo -E bash -
# Install nodejs
sudo apt install nodejs
```
We can install yarn with the following commands:
```bash
# Add yarn repository
curl -sL https://dl.yarnpkg.com/debian/pubkey.gpg | gpg --dearmor | sudo tee /usr/share/keyrings/yarnkey.gpg >/dev/null
echo "deb [signed-by=/usr/share/keyrings/yarnkey.gpg] https://dl.yarnpkg.com/debian stable main" | sudo tee /etc/apt/sources.list.d/yarn.list
# Install yarn
sudo apt update && sudo apt install yarn
```
## Create a folder for Part-DB and download it
We now have all prerequisites installed and can start to install Part-DB. We will create a folder for Part-DB in a webfolder of apache2 and download it to this folder. The downloading is done via git, which allows you to update easily later.
```bash
# Download Part-DB into the new folder /var/www/partdb
git clone https://github.com/Part-DB/Part-DB-symfony.git /var/www/partdb
```
Change ownership of the files to the apache user:
```bash
chown -R www-data:www-data /var/www/partdb
```
For the next steps we should be in the Part-DB folder, so move into it:
```bash
cd /var/www/partdb
```
## Create configuration for Part-DB
The basic configuration of Part-DB is done by a `.env.local` file in the main directory. Create on by from the default configuration:
```bash
cp .env .env.local
```
In your `.env.local` you can configure Part-DB according to your wishes. A full list of configuration options can be found **TODO**.
Other configuration options like the default language or default currency can be found in `config/parameters.yaml`.
Please check that the `partdb.default_currency` value in `config/parameters.yaml` matches your mainly used currency, as this can not be changed after creating price informations.
## Install dependencies for Part-DB and build frontend
Part-DB depends on several other libraries and components. Install them by running the following commands:
```bash
# Install composer dependencies (please note the sudo command, to run it under the web server user)
sudo -u www-data composer install --no-dev -o
# Install yarn dependencies
sudo yarn install
# Build frontend
sudo yarn build
```
## Create a database for Part-DB
Part-DB by default uses a file based sqlite database to store the data. Use the following command to create the database. The database will normally created at `/var/www/partdb/var/app.db`.
```bash
sudo -u www-data php bin/console doctrine:migrations:migrate
```
The command will warn you about schema changes and potential data loss. Continue with typing `yes`.
The command will output several lines of informations. Somewhere should be a a yellow background message like `The initial password for the "admin" user is: f502481134`. Write down this password as you will need it later for inital login.
## Configure apache2 to show Part-DB
Part-DB is now configured, but we have to say apache2 to serve Part-DB as web application. This is done by creating a new apache site:
```bash
sudo nano /etc/apache2/sites-available/partdb.conf
```
and add the following content (change ServerName and ServerAlias to your needs):
```
<VirtualHost *:80>
ServerName partdb.lan
ServerAlias www.partdb.lan
DocumentRoot /var/www/partdb/public
<Directory /var/www/partdb/public>
AllowOverride All
Order Allow,Deny
Allow from All
</Directory>
ErrorLog /var/log/apache2/partdb_error.log
CustomLog /var/log/apache2/partdb_access.log combined
</VirtualHost>
```
Activate the new site by:
```bash
sudo ln -s /etc/apache2/sites-available/partdb.conf /etc/apache2/sites-enabled/partdb.conf
```
Configure apache to show pretty URL pathes for Part-DB (`/label/dialog` instead of `/index.php/label/dialog`):
```bash
sudo a2enmod rewrite
```
If you want to access Part-DB via the IP-Address of the server, instead of the domain name, you have to remove the apache2 default configuration with:
```bash
sudo rm /etc/apache2/sites-enabled/000-default.conf
```
Restart the apache2 webserver with:
```bash
sudo service apache2 restart
```
and Part-DB should now be available under `http://YourServerIP` (or `http://partdb.lan` if you configured DNS in your network to point on the server).
## Login to Part-DB
Navigate to the Part-DB web interface and login via the user icon in the top right corner. You can login using the username `admin` and the password you have written down earlier.
## Update Part-DB
If you want to update your existing Part-DB installation, you just have to run the following commands:
```bash
# Move into Part-DB folder
cd /var/www/partdb
# Pull latest Part-DB version from GitHub
git pull
# Apply correct permission
chown -R www-data:www-data .
# Install new composer dependencies
sudo -u www-data composer install --no-dev -o
# Install yarn dependencies and build new frontend
sudo yarn install
sudo yarn build
# Check if all your configurations in .env.local and /var/www/partdb/config/parameters.yaml are correct.
sudo nano config/parameters.yaml
# Apply new database schemas (you should do a backup of your database file /var/www/partdb/var/app.db before)
sudo -u www-data php bin/console doctrine:migrations:migrate
# Clear Part-DB cache
sudo u www-data php bin/console cache:clear
```

View file

@ -1,39 +1,29 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- https://phpunit.readthedocs.io/en/latest/configuration.html -->
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="bin/.phpunit/phpunit.xsd"
backupGlobals="false"
colors="true"
bootstrap="tests/bootstrap.php"
>
<php>
<ini name="error_reporting" value="-1" />
<server name="APP_ENV" value="test" force="true" />
<server name="SHELL_VERBOSITY" value="-1" />
<server name="SYMFONY_PHPUNIT_REMOVE" value="" />
<server name="SYMFONY_PHPUNIT_VERSION" value="8.5" />
<ini name="memory_limit" value="512M" />
<ini name="display_errors" value="1" />
</php>
<testsuites>
<testsuite name="Project Test Suite">
<directory>tests</directory>
</testsuite>
</testsuites>
<filter>
<whitelist processUncoveredFilesFromWhitelist="true">
<directory suffix=".php">src</directory>
</whitelist>
</filter>
<extensions>
<extension class="DAMA\DoctrineTestBundle\PHPUnit\PHPUnitExtension"/>
</extensions>
<listeners>
<listener class="Symfony\Bridge\PhpUnit\SymfonyTestsListener" />
</listeners>
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/9.3/phpunit.xsd" backupGlobals="false" colors="true" bootstrap="tests/bootstrap.php">
<coverage processUncoveredFiles="true">
<include>
<directory suffix=".php">src</directory>
</include>
</coverage>
<php>
<ini name="error_reporting" value="-1"/>
<server name="APP_ENV" value="test" force="true"/>
<server name="SHELL_VERBOSITY" value="-1"/>
<server name="SYMFONY_PHPUNIT_REMOVE" value=""/>
<server name="SYMFONY_PHPUNIT_VERSION" value="9"/>
<ini name="memory_limit" value="512M"/>
<ini name="display_errors" value="1"/>
</php>
<testsuites>
<testsuite name="Project Test Suite">
<directory>tests</directory>
</testsuite>
</testsuites>
<extensions>
<extension class="DAMA\DoctrineTestBundle\PHPUnit\PHPUnitExtension"/>
</extensions>
<listeners>
<listener class="Symfony\Bridge\PhpUnit\SymfonyTestsListener"/>
</listeners>
</phpunit>

View file

Before

Width:  |  Height:  |  Size: 744 B

After

Width:  |  Height:  |  Size: 744 B

Before After
Before After

View file

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 1.4 KiB

Before After
Before After

View file

Before

Width:  |  Height:  |  Size: 652 B

After

Width:  |  Height:  |  Size: 652 B

Before After
Before After

View file

Before

Width:  |  Height:  |  Size: 645 B

After

Width:  |  Height:  |  Size: 645 B

Before After
Before After

View file

Before

Width:  |  Height:  |  Size: 735 B

After

Width:  |  Height:  |  Size: 735 B

Before After
Before After

View file

Before

Width:  |  Height:  |  Size: 713 B

After

Width:  |  Height:  |  Size: 713 B

Before After
Before After

View file

Before

Width:  |  Height:  |  Size: 768 B

After

Width:  |  Height:  |  Size: 768 B

Before After
Before After

View file

Before

Width:  |  Height:  |  Size: 511 B

After

Width:  |  Height:  |  Size: 511 B

Before After
Before After

View file

Before

Width:  |  Height:  |  Size: 474 B

After

Width:  |  Height:  |  Size: 474 B

Before After
Before After

View file

Before

Width:  |  Height:  |  Size: 467 B

After

Width:  |  Height:  |  Size: 467 B

Before After
Before After

View file

Before

Width:  |  Height:  |  Size: 505 B

After

Width:  |  Height:  |  Size: 505 B

Before After
Before After

View file

Before

Width:  |  Height:  |  Size: 768 B

After

Width:  |  Height:  |  Size: 768 B

Before After
Before After

View file

@ -2,7 +2,7 @@
<browserconfig>
<msapplication>
<tile>
<square150x150logo src="/icons/mstile-150x150.png"/>
<square150x150logo src="/icon/mstile-150x150.png"/>
<TileColor>#00a300</TileColor>
</tile>
</msapplication>

View file

Before

Width:  |  Height:  |  Size: 338 B

After

Width:  |  Height:  |  Size: 338 B

Before After
Before After

View file

Before

Width:  |  Height:  |  Size: 420 B

After

Width:  |  Height:  |  Size: 420 B

Before After
Before After

View file

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 15 KiB

Before After
Before After

View file

Before

Width:  |  Height:  |  Size: 718 B

After

Width:  |  Height:  |  Size: 718 B

Before After
Before After

View file

Before

Width:  |  Height:  |  Size: 2.9 KiB

After

Width:  |  Height:  |  Size: 2.9 KiB

Before After
Before After

View file

@ -8,11 +8,11 @@
"theme_color": "#ffffff",
"icons": [
{
"src": "/icons/android-chrome-192x192.png",
"src": "/icon/android-chrome-192x192.png",
"sizes": "192x192"
},
{
"src": "/icons/android-chrome-384x384.png",
"src": "/icon/android-chrome-384x384.png",
"sizes": "384x384"
}
]

View file

@ -90,7 +90,7 @@ class ShowEventLogCommand extends Command
$total_count = $this->repo->count([]);
$max_page = (int) ceil($total_count / $limit);
if ($page > $max_page) {
if ($page > $max_page && $max_page > 0) {
$io->error("There is no page ${page}! The maximum page is ${max_page}.");
return 1;

View file

@ -25,6 +25,7 @@ namespace App\Entity\Attachments;
use App\Entity\Base\AbstractNamedDBElement;
use App\Validator\Constraints\Selectable;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
use function in_array;
use InvalidArgumentException;
use LogicException;
@ -105,6 +106,7 @@ abstract class Attachment extends AbstractNamedDBElement
* @ORM\ManyToOne(targetEntity="AttachmentType", inversedBy="attachments_with_type")
* @ORM\JoinColumn(name="type_id", referencedColumnName="id")
* @Selectable()
* @Assert\NotNull(message="validator.attachment.must_not_be_null")
*/
protected $attachment_type;

View file

@ -87,7 +87,7 @@ abstract class AbstractDBElement implements \JsonSerializable
return $this->id;
}
public function jsonSerialize()
public function jsonSerialize(): array
{
return ['@id' => $this->getID()];
}

View file

@ -113,6 +113,7 @@ class Orderdetail extends AbstractDBElement implements TimeStampableInterface, N
* @var Supplier
* @ORM\ManyToOne(targetEntity="App\Entity\Parts\Supplier", inversedBy="orderdetails")
* @ORM\JoinColumn(name="id_supplier", referencedColumnName="id")
* @Assert\NotNull(message="validator.orderdetail.supplier_must_not_be_null")
*/
protected $supplier;

View file

@ -62,7 +62,7 @@ final class StructuralDBElementIterator extends ArrayIterator implements Recursi
return !empty($element->getSubelements());
}
public function getChildren()
public function getChildren(): StructuralDBElementIterator
{
/** @var AbstractStructuralDBElement $element */
$element = $this->current();

View file

@ -233,7 +233,7 @@ final class TreeViewNode implements JsonSerializable
return $this;
}
public function jsonSerialize()
public function jsonSerialize(): array
{
$ret = [
'text' => $this->text,

View file

@ -63,7 +63,7 @@ final class TreeViewNodeIterator extends ArrayIterator implements RecursiveItera
return !empty($element->getNodes());
}
public function getChildren()
public function getChildren(): TreeViewNodeIterator
{
/** @var TreeViewNode $element */
$element = $this->current();

View file

@ -8,6 +8,9 @@ use Doctrine\DBAL\Driver\AbstractMySQLDriver;
use Doctrine\DBAL\Driver\AbstractSQLiteDriver;
use Doctrine\DBAL\Exception;
use Doctrine\DBAL\Platforms\AbstractMySQLPlatform;
use Doctrine\DBAL\Platforms\MariaDBPlatform;
use Doctrine\DBAL\Platforms\MySQLPlatform;
use Doctrine\DBAL\Platforms\SqlitePlatform;
use Doctrine\DBAL\Schema\Schema;
use Doctrine\Migrations\AbstractMigration;
use Psr\Log\LoggerInterface;
@ -124,11 +127,11 @@ abstract class AbstractMultiPlatformMigration extends AbstractMigration
*/
public function getDatabaseType(): ?string
{
if ($this->connection->getDriver() instanceof AbstractMySQLDriver) {
if ($this->connection->getDatabasePlatform() instanceof AbstractMySQLPlatform) {
return 'mysql';
}
if ($this->connection->getDriver() instanceof AbstractSQLiteDriver) {
if ($this->connection->getDatabasePlatform() instanceof SqlitePlatform) {
return 'sqlite';
}

View file

@ -45,6 +45,7 @@ namespace App\Services\Attachments;
use App\Entity\Attachments\Attachment;
use InvalidArgumentException;
use Liip\ImagineBundle\Service\FilterService;
use Psr\Log\LoggerInterface;
use RuntimeException;
use function strlen;
use Symfony\Component\Asset\Packages;
@ -59,15 +60,18 @@ class AttachmentURLGenerator
protected $attachmentHelper;
protected $filterService;
protected $logger;
public function __construct(Packages $assets, AttachmentPathResolver $pathResolver,
UrlGeneratorInterface $urlGenerator, AttachmentManager $attachmentHelper,
FilterService $filterService)
FilterService $filterService, LoggerInterface $logger)
{
$this->assets = $assets;
$this->pathResolver = $pathResolver;
$this->urlGenerator = $urlGenerator;
$this->attachmentHelper = $attachmentHelper;
$this->filterService = $filterService;
$this->logger = $logger;
//Determine a normalized path to the public folder (assets are relative to this folder)
$this->public_path = $this->pathResolver->parameterToAbsolutePath('public');
@ -168,8 +172,14 @@ class AttachmentURLGenerator
return $this->assets->getUrl($asset_path);
}
//Otherwise we can serve the relative path via Asset component
return $this->filterService->getUrlOfFilteredImage($asset_path, $filter_name);
try {
//Otherwise we can serve the relative path via Asset component
return $this->filterService->getUrlOfFilteredImage($asset_path, $filter_name);
} catch (\Imagine\Exception\RuntimeException $e) {
//If the filter fails, we can not serve the thumbnail and fall back to the original image and log an warning
$this->logger->warning('Could not open thumbnail for attachment with ID ' . $attachment->getID() . ': ' . $e->getMessage());
return $this->assets->getUrl($asset_path);
}
}
/**

View file

@ -512,15 +512,15 @@
"version": "v4.2.3"
},
"symfony/flex": {
"version": "1.0",
"version": "1.19",
"recipe": {
"repo": "github.com/symfony/recipes",
"branch": "master",
"branch": "main",
"version": "1.0",
"ref": "c0eeb50665f0f77226616b6038a9b06c03752d8e"
"ref": "146251ae39e06a95be0fe3d13c807bcf3938b172"
},
"files": [
"./.env"
".env"
]
},
"symfony/form": {
@ -561,15 +561,15 @@
"version": "v4.2.3"
},
"symfony/mailer": {
"version": "4.3",
"version": "5.4",
"recipe": {
"repo": "github.com/symfony/recipes",
"branch": "master",
"branch": "main",
"version": "4.3",
"ref": "bbfc7e27257d3a3f12a6fb0a42540a42d9623a37"
"ref": "97a61eabb351d7f6cb7702039bcfe07fe9d7e03c"
},
"files": [
"./config/packages/mailer.yaml"
"config/packages/mailer.yaml"
]
},
"symfony/maker-bundle": {

View file

@ -17,13 +17,13 @@
{# <img src="..." class="rounded mr-2" alt="...">#}
<i class="fas fa-fw {{ flash_symbol }} mr-2"></i>
<strong class="mr-auto">{{ flash_title|trans }}</strong>
<small class="text-muted">{{ "now" | format_datetime("short", "short") }}</small>
<small class="{% if "text-white" in flash_bg %}text-white{% else %}text-muted{% endif %}">{{ "now" | format_datetime("short", "short") }}</small>
<button type="button" class="ml-2 mb-1 close" data-dismiss="toast" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="toast-body {{ flash_bg }}">
{{ message | trans}}
{{ message | trans }}
</div>
</div>
{% endfor %}

View file

@ -10,7 +10,7 @@
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="application-name" content="Part-DB">
<meta name="apple-mobile-web-app-title" content="Part-DB">
<meta name="msapplication-config" content="{{ asset('icons/browserconfig.xml') }}">
<meta name="msapplication-config" content="{{ asset('icon/browserconfig.xml') }}">
<meta name="theme-color" content="#ffffff">
<meta name="theme-color" content="#ffffff">
<meta name="msapplication-navbutton-color" content="#ffffff">
@ -18,11 +18,11 @@
<meta name="msapplication-starturl" content="/en/">
<link rel="shortcut icon" type="image/x-icon" href="{{ asset('icons/favicon.ico') }}">
<link rel="apple-touch-icon" sizes="180x180" href="{{ asset('icons/apple-touch-icon.png') }}">
<link rel="icon" type="image/png" href="{{ asset('icons/favicon-32x32.png') }}" sizes="32x32">
<link rel="icon" type="image/png" href="{{ asset('icons/favicon-16x16.png') }}" sizes="16x16">
<link rel="mask-icon" href="{{ asset('icons/safari-pinned-tab.svg') }}" color="#5bbad5">
<link rel="shortcut icon" type="image/x-icon" href="{{ asset('icon/favicon.ico') }}">
<link rel="apple-touch-icon" sizes="180x180" href="{{ asset('icon/apple-touch-icon.png') }}">
<link rel="icon" type="image/png" href="{{ asset('icon/favicon-32x32.png') }}" sizes="32x32">
<link rel="icon" type="image/png" href="{{ asset('icon/favicon-16x16.png') }}" sizes="16x16">
<link rel="mask-icon" href="{{ asset('icon/safari-pinned-tab.svg') }}" color="#5bbad5">
<title>{% apply trim %}{% block title %}{{ partdb_title}}{% endblock %}{% endapply %}</title>

View file

@ -19,9 +19,10 @@
<li>Run <kbd>yarn install</kbd> and <kbd>yarn build</kbd> in Part-DB folder.</li>
<li>Run <kbd>php bin/console cache:clear</kbd></li>
</ul>
{% elseif exception.class == "Doctrine\\DBAL\\Exception\\InvalidFieldNameException" %}
<i>Invalid database schema.</i> Try following things:
{% elseif exception.class == "Doctrine\\DBAL\\Exception\\InvalidFieldNameException" or exception.class == "Doctrine\\DBAL\\Exception\\TableNotFoundException" %}
<i>Invalid or not existing database schema.</i> Try following things:
<ul>
<li>Check if the <code>DATABASE_URL</code> in <code>.env.local</code> is correct</li>
<li>Run <kbd>php bin/console doctrine:migrations:migrate</kbd> to upgrade database schema</li>
<li>Run <kbd>php bin/console cache:clear</kbd></li>
</ul>

View file

@ -22,7 +22,7 @@
<h4><i class="fa fa-book fa-fw" aria-hidden="true"></i> {% trans %}homepage.license{% endtrans %}</h4>
</div>
<div class="card-body">
<p>Part-DB, Copyright &copy; 2019 - 2020 of <strong>
<p>Part-DB, Copyright &copy; 2019 - 2022 of <strong>
<a class="link-external" rel="noopener" target="_blank" href="https://github.com/jbtronics/">Jan Böhmer</a>
</strong>. <br> Part-DB is published under the <strong>GNU Affero General Public License v3.0 (or later)</strong>, so it comes with <strong>ABSOLUTELY NO WARRANTY</strong>.
This is free software, and you are welcome to redistribute it under certain conditions.

View file

@ -88,10 +88,12 @@ class UserTest extends TestCase
public function testSetBackupCodes(): void
{
$user = new User();
$this->assertNull($user->getBackupCodesGenerationDate());
$codes = ['test', 'invalid', 'test'];
$user->setBackupCodes($codes);
// Backup Codes generation date must be changed!
$this->assertEqualsWithDelta(new DateTime(), $user->getBackupCodesGenerationDate(), 0.1);
$this->assertInstanceOf(\DateTime::class, $user->getBackupCodesGenerationDate());
$this->assertSame($codes, $user->getBackupCodes());
//Test what happens if we delete the backup keys

View file

@ -77,7 +77,7 @@ class BackupCodeGeneratorTest extends TestCase
public function testGenerateSingleCode(int $code_length): void
{
$generator = new BackupCodeGenerator($code_length, 10);
$this->assertRegExp("/^([a-f0-9]){{$code_length}}\$/", $generator->generateSingleCode());
$this->assertMatchesRegularExpression("/^([a-f0-9]){{$code_length}}\$/", $generator->generateSingleCode());
}
public function codeCountDataProvider(): array

File diff suppressed because it is too large Load diff

View file

@ -215,5 +215,17 @@
<target>This location can only contain a single part and it is already full!</target>
</segment>
</unit>
<unit id="4gPskOG" name="validator.attachment.must_not_be_null">
<segment>
<source>validator.attachment.must_not_be_null</source>
<target>You must select an attachment type!</target>
</segment>
</unit>
<unit id="cDDVrWT" name="validator.orderdetail.supplier_must_not_be_null">
<segment>
<source>validator.orderdetail.supplier_must_not_be_null</source>
<target>You must select an supplier!</target>
</segment>
</unit>
</file>
</xliff>

2758
yarn.lock

File diff suppressed because it is too large Load diff