forked from wallabag/wallabag
Compare commits
138 Commits
2.6.0
...
fix-instal
| Author | SHA1 | Date | |
|---|---|---|---|
| 357ce8f7c3 | |||
| e185e03c6e | |||
| 2c688daf2a | |||
| 911e0238b7 | |||
| 5fe5551972 | |||
| 90631abe46 | |||
| ce88e7aaab | |||
| a339fcd137 | |||
| f74571e750 | |||
| 0f44b2b75c | |||
| 382272c51c | |||
| 78cddcafd7 | |||
| 594770bdf4 | |||
| 2dcdb4e23c | |||
| 76617f0440 | |||
| 192fa3ea2e | |||
| 72eef910d9 | |||
| 8508b92f98 | |||
| 839a3ddbf2 | |||
| 3904543a96 | |||
| af7cd960dd | |||
| b58b6ca9f3 | |||
| 7098fd6193 | |||
| 070f5e1cf4 | |||
| 8e05fd0a3f | |||
| 931f665bc7 | |||
| 7615a29095 | |||
| 1a01323002 | |||
| 724fea0aea | |||
| 13a3a5596c | |||
| e2857a1ffe | |||
| 8c39d2aca1 | |||
| 8c82b42338 | |||
| 24a0ec60bf | |||
| fc95d812dd | |||
| 8b9fd04c74 | |||
| df56bfe94e | |||
| 11617ca7e1 | |||
| 90281b8786 | |||
| 91b47be5a9 | |||
| 8146b4180e | |||
| f1fb885ca6 | |||
| cf42b834d7 | |||
| b2b2627817 | |||
| 8c56a40d38 | |||
| 9484f3d2ce | |||
| d835f03f15 | |||
| 81403edb00 | |||
| c75d3e6961 | |||
| 2c1687ce91 | |||
| 5ca4df1585 | |||
| 241955a317 | |||
| 193953f75d | |||
| c535e291d5 | |||
| d9b4e0791d | |||
| edc2194ead | |||
| 3d36ccf8dd | |||
| 65b621da9e | |||
| 0e0de8578c | |||
| 2241d77304 | |||
| 54e3801cfe | |||
| 9cc23c615a | |||
| 80a3447d20 | |||
| e07b13fd38 | |||
| da3e9a2fb2 | |||
| 8b79bc654b | |||
| f8c834db0f | |||
| 0596633a29 | |||
| c8190c8a5a | |||
| f315552825 | |||
| a8ade4bb39 | |||
| 530fc289f2 | |||
| 21a8d427e7 | |||
| 1be3dc91b9 | |||
| 74f8acca3e | |||
| a4d2957c54 | |||
| 112c9e1b7c | |||
| 908e44f9b9 | |||
| b22a6feed2 | |||
| 13a7f1bc80 | |||
| 24887f4ad6 | |||
| 5b1230a909 | |||
| 31566fb6eb | |||
| 183c5248f3 | |||
| 738ff474a6 | |||
| 81022c3089 | |||
| 2486f42c09 | |||
| 4fc21d08f2 | |||
| 8814eaa03b | |||
| 303cdffe36 | |||
| 27b7ce9479 | |||
| 39bed07622 | |||
| cb1082904b | |||
| ee5de3b491 | |||
| 5acab2b264 | |||
| 4c797162bf | |||
| 0a6826cb4c | |||
| 49e81d8952 | |||
| 4af2abf0b7 | |||
| 84bbeed4f0 | |||
| 6639f7da6d | |||
| 131ef532c7 | |||
| dc02c679d2 | |||
| 0fff56ea68 | |||
| e9054bbd41 | |||
| 36c3a7d505 | |||
| 05c04cc509 | |||
| 2e3ca273c8 | |||
| bc8c7cd7ca | |||
| 513337c1fa | |||
| 103386c66a | |||
| 74848a4794 | |||
| 32c901f7cd | |||
| 1d9709db08 | |||
| 5905b0c12f | |||
| e776c9bc9d | |||
| 3a691e8ddd | |||
| dc36da99c0 | |||
| b05464ffd1 | |||
| 28d3a5655c | |||
| 696ee80de7 | |||
| 8bf4222bdb | |||
| f58c656a08 | |||
| 391f346cc3 | |||
| 6c3118951b | |||
| c833141942 | |||
| 4f162fff64 | |||
| 1413772bca | |||
| bf59e8aad3 | |||
| d33e3d64d2 | |||
| a6c78f0039 | |||
| c8c6ed2ea3 | |||
| 73682283e4 | |||
| 67e86d8881 | |||
| 2a1493e1b3 | |||
| 4d52e6fd8c | |||
| 679dc32885 | |||
| f511af6fda |
14
.github/CONTRIBUTING.md
vendored
14
.github/CONTRIBUTING.md
vendored
@ -45,3 +45,17 @@ Note : If you have large portions of text, use [Github's Gist service](https://g
|
||||
|
||||
## You want to fix a bug or to add a feature
|
||||
Please fork wallabag and work with **the master branch**.
|
||||
|
||||
## Run Tests and PHP formatter
|
||||
|
||||
All pull requests need to pass the tests and the code needs match the style guide.
|
||||
|
||||
To run the tests locally run:
|
||||
|
||||
- when testing using Docker: `docker-compose run --rm php make test`
|
||||
- otherwise: `make test`
|
||||
|
||||
To run the PHP formatter:
|
||||
|
||||
- when testing using Docker: `docker-compose run --rm php bin/php-cs-fixer fix`
|
||||
- otherwise: `php bin/php-cs-fixer fix`
|
||||
|
||||
3
.github/workflows/coding-standards.yml
vendored
3
.github/workflows/coding-standards.yml
vendored
@ -49,3 +49,6 @@ jobs:
|
||||
|
||||
- name: "Run TwigCS"
|
||||
run: "php bin/twigcs --severity=error --display=blocking --reporter checkstyle app/ src/ | cs2pr"
|
||||
|
||||
- name: "Run ergebnis/composer-normalize"
|
||||
run: "composer normalize --dry-run --no-check-lock"
|
||||
|
||||
126
.github/workflows/continuous-integration.yml
vendored
126
.github/workflows/continuous-integration.yml
vendored
@ -80,3 +80,129 @@ jobs:
|
||||
|
||||
- name: "Run PHPUnit"
|
||||
run: "php bin/simple-phpunit -v"
|
||||
|
||||
phpunit_no_prefix:
|
||||
name: "PHP ${{ matrix.php }} using ${{ matrix.database }} without prefix"
|
||||
runs-on: "ubuntu-20.04"
|
||||
services:
|
||||
rabbitmq:
|
||||
image: rabbitmq:3-alpine
|
||||
ports:
|
||||
- 5672:5672
|
||||
redis:
|
||||
image: redis:6-alpine
|
||||
ports:
|
||||
- 6379:6379
|
||||
|
||||
strategy:
|
||||
fail-fast: true
|
||||
matrix:
|
||||
php:
|
||||
- "8.2"
|
||||
database:
|
||||
- "sqlite"
|
||||
- "mysql"
|
||||
- "pgsql"
|
||||
|
||||
steps:
|
||||
- name: "Checkout"
|
||||
uses: "actions/checkout@v3"
|
||||
with:
|
||||
fetch-depth: 2
|
||||
|
||||
- name: "Install PHP"
|
||||
uses: "shivammathur/setup-php@v2"
|
||||
with:
|
||||
php-version: "${{ matrix.php }}"
|
||||
coverage: none
|
||||
tools: pecl
|
||||
extensions: json, pdo, pdo_mysql, pdo_sqlite, pdo_pgsql, curl, imagick, pgsql, gd, tidy
|
||||
ini-values: "date.timezone=Europe/Paris"
|
||||
|
||||
- name: "Remove database prefix"
|
||||
run: |
|
||||
pip install --user yq
|
||||
yq -Y --in-place '.parameters.database_table_prefix = ""' app/config/parameters.yml.dist
|
||||
|
||||
- name: "Setup MySQL"
|
||||
if: "${{ matrix.database == 'mysql' }}"
|
||||
run: |
|
||||
sudo systemctl start mysql.service
|
||||
sudo mysql -u root -proot -h 127.0.0.1 -e "CREATE DATABASE wallabag_test"
|
||||
|
||||
- name: "Setup PostgreSQL"
|
||||
if: "${{ matrix.database == 'pgsql' }}"
|
||||
run: |
|
||||
sudo systemctl start postgresql
|
||||
sudo -u postgres psql -d template1 -c "CREATE USER wallabag WITH PASSWORD 'wallabagrocks' CREATEDB"
|
||||
createdb -h localhost -p 5432 -U wallabag wallabag_test
|
||||
pg_isready -d wallabag_test -h localhost -p 5432 -U wallabag
|
||||
|
||||
- name: "Install dependencies with Composer"
|
||||
uses: "ramsey/composer-install@v2"
|
||||
with:
|
||||
composer-options: "--optimize-autoloader --prefer-dist"
|
||||
|
||||
- name: "Prepare database"
|
||||
run: "make prepare DB=${{ matrix.database }}"
|
||||
|
||||
- name: "Prepare fixtures"
|
||||
run: "make fixtures"
|
||||
|
||||
- name: "Run PHPUnit"
|
||||
run: "php bin/simple-phpunit -v"
|
||||
|
||||
phpunit_no_database:
|
||||
name: "PHP ${{ matrix.php }} using ${{ matrix.database }} without DB created"
|
||||
runs-on: "ubuntu-20.04"
|
||||
services:
|
||||
rabbitmq:
|
||||
image: rabbitmq:3-alpine
|
||||
ports:
|
||||
- 5672:5672
|
||||
redis:
|
||||
image: redis:6-alpine
|
||||
ports:
|
||||
- 6379:6379
|
||||
|
||||
strategy:
|
||||
fail-fast: true
|
||||
matrix:
|
||||
php:
|
||||
- "8.2"
|
||||
database:
|
||||
- "mysql"
|
||||
|
||||
steps:
|
||||
- name: "Checkout"
|
||||
uses: "actions/checkout@v3"
|
||||
with:
|
||||
fetch-depth: 2
|
||||
|
||||
- name: "Install PHP"
|
||||
uses: "shivammathur/setup-php@v2"
|
||||
with:
|
||||
php-version: "${{ matrix.php }}"
|
||||
coverage: none
|
||||
tools: pecl
|
||||
extensions: json, pdo, pdo_mysql, pdo_sqlite, pdo_pgsql, curl, imagick, pgsql, gd, tidy
|
||||
ini-values: "date.timezone=Europe/Paris"
|
||||
|
||||
- name: "Setup MySQL"
|
||||
if: "${{ matrix.database == 'mysql' }}"
|
||||
run: |
|
||||
sudo systemctl start mysql.service
|
||||
|
||||
- name: "Install dependencies with Composer"
|
||||
uses: "ramsey/composer-install@v2"
|
||||
with:
|
||||
composer-options: "--optimize-autoloader --prefer-dist"
|
||||
|
||||
- name: "Install wallabag"
|
||||
run: "php bin/console wallabag:install --env=test"
|
||||
|
||||
- name: "Prepare fixtures"
|
||||
run: "make fixtures"
|
||||
|
||||
- name: "Run PHPUnit"
|
||||
run: "php bin/simple-phpunit -v"
|
||||
|
||||
@ -12,7 +12,7 @@ jobs:
|
||||
steps:
|
||||
- name: Dependabot metadata
|
||||
id: metadata
|
||||
uses: dependabot/fetch-metadata@v1.5.1
|
||||
uses: dependabot/fetch-metadata@v1.6.0
|
||||
with:
|
||||
github-token: '${{ secrets.GITHUB_TOKEN }}'
|
||||
- name: Approve and merge minor updates
|
||||
|
||||
27
CHANGELOG.md
27
CHANGELOG.md
@ -1,5 +1,32 @@
|
||||
# Changelog
|
||||
|
||||
## [2.6.2](https://github.com/wallabag/wallabag/tree/2.6.2)
|
||||
[Full Changelog](https://github.com/wallabag/wallabag/compare/2.6.1...2.6.2)
|
||||
|
||||
### Fixes
|
||||
* Fix mass action input on dark theme by @simounet https://github.com/wallabag/wallabag/pull/6673
|
||||
* Fix undefined variable by @nicosomb https://github.com/wallabag/wallabag/pull/6672
|
||||
* Fix table name in migration by @nicosomb https://github.com/wallabag/wallabag/pull/6653
|
||||
|
||||
### Technical stuff
|
||||
* Add a new build to test when no database table prefix are defined by @j0k3r https://github.com/wallabag/wallabag/pull/6731
|
||||
* Keep escaped table name while migrating by @Glandos https://github.com/wallabag/wallabag/pull/6710
|
||||
* Remove twofactor_auth parameter by @nicosomb https://github.com/wallabag/wallabag/pull/6723
|
||||
* ApiDoc: Add response description to UserRestController by @caspermeijn https://github.com/wallabag/wallabag/pull/6684
|
||||
* ApiDoc: Add response description to WallabagRestController by @caspermeijn https://github.com/wallabag/wallabag/pull/6102
|
||||
* Skip migration if the table was already renamed by @gramakri https://github.com/wallabag/wallabag/pull/6678
|
||||
|
||||
### Meta
|
||||
* Document how to run tests and formatter for new contributors by @caspermeijn https://github.com/wallabag/wallabag/pull/6685
|
||||
* Add link to wallabag ecosystem resources by @nicosomb https://github.com/wallabag/wallabag/pull/6700
|
||||
|
||||
## [2.6.1](https://github.com/wallabag/wallabag/tree/2.6.1)
|
||||
[Full Changelog](https://github.com/wallabag/wallabag/compare/2.6.0...2.6.1)
|
||||
|
||||
### Fixes
|
||||
* Do not autoload fixtures by @j0k3r https://github.com/wallabag/wallabag/pull/6648
|
||||
* Add confirmation alert when deleting articles from list view by @nicosomb https://github.com/wallabag/wallabag/pull/6644
|
||||
|
||||
## [2.6.0](https://github.com/wallabag/wallabag/tree/2.6.0)
|
||||
[Full Changelog](https://github.com/wallabag/wallabag/compare/2.5.4...2.6.0)
|
||||
|
||||
|
||||
@ -40,7 +40,7 @@ ifdef DB
|
||||
endif
|
||||
-php bin/console doctrine:database:drop --force --env=test
|
||||
php bin/console doctrine:database:create --env=test
|
||||
php bin/console doctrine:migrations:migrate --no-interaction --env=test
|
||||
php bin/console doctrine:migrations:migrate --no-interaction --env=test -vv
|
||||
|
||||
fixtures: ## Load fixtures into database
|
||||
php bin/console doctrine:fixtures:load --no-interaction --env=test
|
||||
|
||||
@ -18,6 +18,7 @@ You can install it on your own server, or you can create an account on [wallabag
|
||||
* iOS app: [wallabag/ios-app](https://github.com/wallabag/ios-app)
|
||||
* Browser extension: [wallabag/wallabagger](https://github.com/wallabag/wallabagger)
|
||||
* GNOME (Linux) app: [read-it-later](https://gitlab.gnome.org/World/read-it-later) (not maintained by this project)
|
||||
* All resources about wallabag ecosystem are listed here: https://github.com/wallabag/wallabag/wiki/wallabag-ecosystem
|
||||
|
||||
## Documentation
|
||||
|
||||
|
||||
@ -17,9 +17,8 @@ During this documentation, we assume the release is `$LAST_WALLABAG_RELEASE` (li
|
||||
#### Create a new release on GitHub
|
||||
|
||||
- [Create the new release on GitHub](https://github.com/wallabag/wallabag/releases/new) by targetting the `master` branch or any appropriate branch (for instance backports).
|
||||
- Update [website](https://github.com/wallabag/website) to change the redirect rule for `/latest-v2-package` & `/latest-v2`. They both should redirect to the asset of the GitHub release.
|
||||
- Update [website](https://github.com/wallabag/website) to change MD5 sum and create the release blog post (based on the changelog).
|
||||
- Update Dockerfile https://github.com/wallabag/docker (and create a new tag)
|
||||
- Update [website](https://github.com/wallabag/website) website (downloads, MD5 sum, releases and new blog post)
|
||||
- Put the next patch version suffixed with `-dev` in `app/config/wallabag.yml` (`wallabag_core.version`)
|
||||
- Drink a :beer:!
|
||||
|
||||
|
||||
@ -13,6 +13,8 @@ class Version20170606155640 extends WallabagMigration
|
||||
{
|
||||
public function up(Schema $schema): void
|
||||
{
|
||||
$this->skipIf(!$schema->hasTable($this->getTable('craue_config_setting')), 'Table already renamed');
|
||||
|
||||
$apiUserRegistration = $this->container
|
||||
->get('doctrine.orm.default_entity_manager')
|
||||
->getConnection()
|
||||
|
||||
@ -12,48 +12,50 @@ final class Version20221221092957 extends WallabagMigration
|
||||
{
|
||||
public function up(Schema $schema): void
|
||||
{
|
||||
$userTable = $this->getTable('user');
|
||||
switch ($this->connection->getDatabasePlatform()->getName()) {
|
||||
case 'sqlite':
|
||||
$this->addSql('CREATE TEMPORARY TABLE __temp__wallabag_user AS SELECT id, username, username_canonical, email, email_canonical, enabled, password, last_login, password_requested_at, name, created_at, updated_at, authCode, emailTwoFactor, salt, confirmation_token, roles, googleAuthenticatorSecret, backupCodes FROM wallabag_user');
|
||||
$this->addSql('DROP TABLE wallabag_user');
|
||||
$this->addSql('CREATE TABLE "wallabag_user" (id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, username VARCHAR(180) NOT NULL, username_canonical VARCHAR(180) NOT NULL, email VARCHAR(180) NOT NULL, email_canonical VARCHAR(180) NOT NULL, enabled BOOLEAN NOT NULL, salt VARCHAR(255) DEFAULT NULL, password VARCHAR(255) NOT NULL, last_login DATETIME DEFAULT NULL, confirmation_token VARCHAR(180) DEFAULT NULL, password_requested_at DATETIME DEFAULT NULL, roles CLOB NOT NULL --(DC2Type:array)
|
||||
$this->addSql('CREATE TEMPORARY TABLE __temp__wallabag_user AS SELECT id, username, username_canonical, email, email_canonical, enabled, password, last_login, password_requested_at, name, created_at, updated_at, authCode, emailTwoFactor, salt, confirmation_token, roles, googleAuthenticatorSecret, backupCodes FROM ' . $userTable);
|
||||
$this->addSql('DROP TABLE ' . $userTable);
|
||||
$this->addSql('CREATE TABLE ' . $userTable . ' (id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, username VARCHAR(180) NOT NULL, username_canonical VARCHAR(180) NOT NULL, email VARCHAR(180) NOT NULL, email_canonical VARCHAR(180) NOT NULL, enabled BOOLEAN NOT NULL, salt VARCHAR(255) DEFAULT NULL, password VARCHAR(255) NOT NULL, last_login DATETIME DEFAULT NULL, confirmation_token VARCHAR(180) DEFAULT NULL, password_requested_at DATETIME DEFAULT NULL, roles CLOB NOT NULL --(DC2Type:array)
|
||||
, name CLOB DEFAULT NULL, created_at DATETIME NOT NULL, updated_at DATETIME NOT NULL, authCode INTEGER DEFAULT NULL, googleAuthenticatorSecret VARCHAR(255) DEFAULT NULL, backupCodes CLOB DEFAULT NULL --(DC2Type:json)
|
||||
, emailTwoFactor BOOLEAN NOT NULL)');
|
||||
$this->addSql('INSERT INTO wallabag_user (id, username, username_canonical, email, email_canonical, enabled, password, last_login, password_requested_at, name, created_at, updated_at, authCode, emailTwoFactor, salt, confirmation_token, roles, googleAuthenticatorSecret, backupCodes) SELECT id, username, username_canonical, email, email_canonical, enabled, password, last_login, password_requested_at, name, created_at, updated_at, authCode, emailTwoFactor, salt, confirmation_token, roles, googleAuthenticatorSecret, backupCodes FROM __temp__wallabag_user');
|
||||
$this->addSql('INSERT INTO ' . $userTable . ' (id, username, username_canonical, email, email_canonical, enabled, password, last_login, password_requested_at, name, created_at, updated_at, authCode, emailTwoFactor, salt, confirmation_token, roles, googleAuthenticatorSecret, backupCodes) SELECT id, username, username_canonical, email, email_canonical, enabled, password, last_login, password_requested_at, name, created_at, updated_at, authCode, emailTwoFactor, salt, confirmation_token, roles, googleAuthenticatorSecret, backupCodes FROM __temp__wallabag_user');
|
||||
$this->addSql('DROP TABLE __temp__wallabag_user');
|
||||
$this->addSql('CREATE UNIQUE INDEX UNIQ_1D63E7E592FC23A8 ON wallabag_user (username_canonical)');
|
||||
$this->addSql('CREATE UNIQUE INDEX UNIQ_1D63E7E5A0D96FBF ON wallabag_user (email_canonical)');
|
||||
$this->addSql('CREATE UNIQUE INDEX UNIQ_1D63E7E5C05FB297 ON wallabag_user (confirmation_token)');
|
||||
$this->addSql('CREATE UNIQUE INDEX UNIQ_1D63E7E592FC23A8 ON ' . $userTable . ' (username_canonical)');
|
||||
$this->addSql('CREATE UNIQUE INDEX UNIQ_1D63E7E5A0D96FBF ON ' . $userTable . ' (email_canonical)');
|
||||
$this->addSql('CREATE UNIQUE INDEX UNIQ_1D63E7E5C05FB297 ON ' . $userTable . ' (confirmation_token)');
|
||||
break;
|
||||
case 'mysql':
|
||||
$this->addSql('ALTER TABLE wallabag_user CHANGE backupCodes backupCodes JSON DEFAULT NULL');
|
||||
$this->addSql('ALTER TABLE ' . $userTable . ' CHANGE backupCodes backupCodes JSON DEFAULT NULL');
|
||||
break;
|
||||
case 'postgresql':
|
||||
$this->addSql('ALTER TABLE wallabag_user ALTER backupcodes TYPE JSON USING backupcodes::json');
|
||||
$this->addSql('ALTER TABLE ' . $userTable . ' ALTER backupcodes TYPE JSON USING backupcodes::json');
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public function down(Schema $schema): void
|
||||
{
|
||||
$userTable = $this->getTable('user');
|
||||
switch ($this->connection->getDatabasePlatform()->getName()) {
|
||||
case 'sqlite':
|
||||
$this->addSql('CREATE TEMPORARY TABLE __temp__wallabag_user AS SELECT id, username, username_canonical, email, email_canonical, enabled, salt, password, last_login, confirmation_token, password_requested_at, roles, name, created_at, updated_at, authCode, googleAuthenticatorSecret, backupCodes, emailTwoFactor FROM "wallabag_user"');
|
||||
$this->addSql('DROP TABLE "wallabag_user"');
|
||||
$this->addSql('CREATE TABLE "wallabag_user" (id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, username VARCHAR(180) NOT NULL, username_canonical VARCHAR(180) NOT NULL, email VARCHAR(180) NOT NULL, email_canonical VARCHAR(180) NOT NULL, enabled BOOLEAN NOT NULL, salt VARCHAR(255) DEFAULT NULL, password VARCHAR(255) NOT NULL, last_login DATETIME DEFAULT NULL, confirmation_token VARCHAR(180) DEFAULT NULL, password_requested_at DATETIME DEFAULT NULL, roles CLOB NOT NULL --(DC2Type:array)
|
||||
$this->addSql('CREATE TEMPORARY TABLE __temp__wallabag_user AS SELECT id, username, username_canonical, email, email_canonical, enabled, salt, password, last_login, confirmation_token, password_requested_at, roles, name, created_at, updated_at, authCode, googleAuthenticatorSecret, backupCodes, emailTwoFactor FROM ' . $userTable);
|
||||
$this->addSql('DROP TABLE ' . $userTable);
|
||||
$this->addSql('CREATE TABLE ' . $userTable . ' (id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, username VARCHAR(180) NOT NULL, username_canonical VARCHAR(180) NOT NULL, email VARCHAR(180) NOT NULL, email_canonical VARCHAR(180) NOT NULL, enabled BOOLEAN NOT NULL, salt VARCHAR(255) DEFAULT NULL, password VARCHAR(255) NOT NULL, last_login DATETIME DEFAULT NULL, confirmation_token VARCHAR(180) DEFAULT NULL, password_requested_at DATETIME DEFAULT NULL, roles CLOB NOT NULL --(DC2Type:array)
|
||||
, name CLOB DEFAULT NULL, created_at DATETIME NOT NULL, updated_at DATETIME NOT NULL, authCode INTEGER DEFAULT NULL, googleAuthenticatorSecret VARCHAR(255) DEFAULT NULL, backupCodes CLOB DEFAULT NULL --(DC2Type:json_array)
|
||||
, emailTwoFactor BOOLEAN NOT NULL)');
|
||||
$this->addSql('INSERT INTO "wallabag_user" (id, username, username_canonical, email, email_canonical, enabled, salt, password, last_login, confirmation_token, password_requested_at, roles, name, created_at, updated_at, authCode, googleAuthenticatorSecret, backupCodes, emailTwoFactor) SELECT id, username, username_canonical, email, email_canonical, enabled, salt, password, last_login, confirmation_token, password_requested_at, roles, name, created_at, updated_at, authCode, googleAuthenticatorSecret, backupCodes, emailTwoFactor FROM __temp__wallabag_user');
|
||||
$this->addSql('INSERT INTO ' . $userTable . ' (id, username, username_canonical, email, email_canonical, enabled, salt, password, last_login, confirmation_token, password_requested_at, roles, name, created_at, updated_at, authCode, googleAuthenticatorSecret, backupCodes, emailTwoFactor) SELECT id, username, username_canonical, email, email_canonical, enabled, salt, password, last_login, confirmation_token, password_requested_at, roles, name, created_at, updated_at, authCode, googleAuthenticatorSecret, backupCodes, emailTwoFactor FROM __temp__wallabag_user');
|
||||
$this->addSql('DROP TABLE __temp__wallabag_user');
|
||||
$this->addSql('CREATE UNIQUE INDEX UNIQ_1D63E7E592FC23A8 ON "wallabag_user" (username_canonical)');
|
||||
$this->addSql('CREATE UNIQUE INDEX UNIQ_1D63E7E5A0D96FBF ON "wallabag_user" (email_canonical)');
|
||||
$this->addSql('CREATE UNIQUE INDEX UNIQ_1D63E7E5C05FB297 ON "wallabag_user" (confirmation_token)');
|
||||
$this->addSql('CREATE UNIQUE INDEX UNIQ_1D63E7E592FC23A8 ON ' . $userTable . ' (username_canonical)');
|
||||
$this->addSql('CREATE UNIQUE INDEX UNIQ_1D63E7E5A0D96FBF ON ' . $userTable . ' (email_canonical)');
|
||||
$this->addSql('CREATE UNIQUE INDEX UNIQ_1D63E7E5C05FB297 ON ' . $userTable . ' (confirmation_token)');
|
||||
break;
|
||||
case 'mysql':
|
||||
$this->addSql('ALTER TABLE `wallabag_user`CHANGE backupCodes backupCodes JSON DEFAULT NULL COMMENT \'(DC2Type:json_array)\'');
|
||||
$this->addSql('ALTER TABLE ' . $userTable . ' CHANGE backupCodes backupCodes JSON DEFAULT NULL COMMENT \'(DC2Type:json_array)\'');
|
||||
break;
|
||||
case 'postgresql':
|
||||
$this->addSql('ALTER TABLE "wallabag_user" ALTER backupCodes TYPE TEXT');
|
||||
$this->addSql('ALTER TABLE ' . $userTable . ' ALTER backupCodes TYPE TEXT');
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -52,6 +52,7 @@
|
||||
height: 100%;
|
||||
vertical-align: middle;
|
||||
opacity: initial;
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
.toggle-checkbox:not(:checked) + .mass-action,
|
||||
|
||||
@ -201,15 +201,15 @@ scheb_two_factor:
|
||||
lifetime: 2592000
|
||||
|
||||
backup_codes:
|
||||
enabled: "%twofactor_auth%"
|
||||
enabled: true
|
||||
|
||||
google:
|
||||
enabled: "%twofactor_auth%"
|
||||
enabled: true
|
||||
issuer: "%server_name%"
|
||||
template: "@WallabagUser/Authentication/form.html.twig"
|
||||
|
||||
email:
|
||||
enabled: "%twofactor_auth%"
|
||||
enabled: true
|
||||
sender_email: "%twofactor_sender%"
|
||||
digits: 6
|
||||
template: "@WallabagUser/Authentication/form.html.twig"
|
||||
|
||||
@ -34,7 +34,6 @@ parameters:
|
||||
secret: CHANGE_ME_TO_SOMETHING_SECRET_AND_RANDOM
|
||||
|
||||
# two factor stuff
|
||||
twofactor_auth: true
|
||||
twofactor_sender: no-reply@wallabag.org
|
||||
|
||||
# fosuser stuff
|
||||
|
||||
@ -33,7 +33,7 @@ services:
|
||||
|
||||
Wallabag\AnnotationBundle\:
|
||||
resource: '../../src/Wallabag/AnnotationBundle/*'
|
||||
exclude: '../../src/Wallabag/AnnotationBundle/{Controller,Entity}'
|
||||
exclude: '../../src/Wallabag/AnnotationBundle/{Controller,Entity,DataFixtures}'
|
||||
|
||||
Wallabag\ApiBundle\:
|
||||
resource: '../../src/Wallabag/ApiBundle/*'
|
||||
@ -41,7 +41,7 @@ services:
|
||||
|
||||
Wallabag\CoreBundle\:
|
||||
resource: '../../src/Wallabag/CoreBundle/*'
|
||||
exclude: ['../../src/Wallabag/CoreBundle/{Controller,Entity}', '../../src/Wallabag/CoreBundle/Event/*Event.php']
|
||||
exclude: ['../../src/Wallabag/CoreBundle/{Controller,Entity,DataFixtures}', '../../src/Wallabag/CoreBundle/Event/*Event.php']
|
||||
|
||||
# controllers are imported separately to make sure services can be injected
|
||||
# as action arguments even if you don't extend any base controller class
|
||||
@ -122,7 +122,7 @@ services:
|
||||
|
||||
Wallabag\UserBundle\:
|
||||
resource: '../../src/Wallabag/UserBundle/*'
|
||||
exclude: '../../src/Wallabag/UserBundle/{Controller,Entity}'
|
||||
exclude: '../../src/Wallabag/UserBundle/{Controller,Entity,DataFixtures}'
|
||||
|
||||
Doctrine\DBAL\Connection:
|
||||
alias: doctrine.dbal.default_connection
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
wallabag_core:
|
||||
version: 2.6.0
|
||||
version: 2.6.2
|
||||
paypal_url: "https://liberapay.com/wallabag/donate"
|
||||
languages:
|
||||
en: 'English'
|
||||
|
||||
@ -1,33 +1,38 @@
|
||||
{
|
||||
"name": "wallabag/wallabag",
|
||||
"type": "project",
|
||||
"description": "open source self hostable read-it-later web application",
|
||||
"license": "MIT",
|
||||
"type": "project",
|
||||
"keywords": [
|
||||
"poche",
|
||||
"wallabag",
|
||||
"read-it-later",
|
||||
"read it later"
|
||||
],
|
||||
"homepage": "https://github.com/wallabag/wallabag",
|
||||
"license": "MIT",
|
||||
"authors": [
|
||||
{
|
||||
"name": "Nicolas Lœuillet",
|
||||
"email": "nicolas@loeuillet.org",
|
||||
"homepage": "http://www.cdetc.fr",
|
||||
"homepage": "https://nicolas.loeuillet.org",
|
||||
"role": "Developer"
|
||||
},
|
||||
{
|
||||
"name": "Thomas Citharel",
|
||||
"homepage": "http://tcit.fr",
|
||||
"homepage": "https://tcit.fr",
|
||||
"role": "Developer"
|
||||
},
|
||||
{
|
||||
"name": "Jérémy Benoist",
|
||||
"homepage": "https://www.j0k3r.net",
|
||||
"role": "Developer"
|
||||
},
|
||||
{
|
||||
"name": "Kevin Decherf",
|
||||
"homepage": "https://kdecherf.com/",
|
||||
"role": "Developer"
|
||||
}
|
||||
],
|
||||
"homepage": "https://github.com/wallabag/wallabag",
|
||||
"support": {
|
||||
"email": "hello@wallabag.org",
|
||||
"issues": "https://github.com/wallabag/wallabag/issues"
|
||||
@ -130,6 +135,7 @@
|
||||
"require-dev": {
|
||||
"dama/doctrine-test-bundle": "^7.1",
|
||||
"doctrine/doctrine-fixtures-bundle": "~3.0",
|
||||
"ergebnis/composer-normalize": "^2.28",
|
||||
"friendsofphp/php-cs-fixer": "~3.4",
|
||||
"friendsoftwig/twigcs": "^6.0",
|
||||
"m6web/redis-mock": "^5.0",
|
||||
@ -145,25 +151,8 @@
|
||||
"suggest": {
|
||||
"ext-imagick": "To keep GIF animation when downloading image is enabled"
|
||||
},
|
||||
"scripts": {
|
||||
"post-cmd": [
|
||||
"Incenteev\\ParameterHandler\\ScriptHandler::buildParameters",
|
||||
"bin/console cache:clear --no-warmup",
|
||||
"bin/console assets:install web --symlink --relative"
|
||||
],
|
||||
"post-install-cmd": [
|
||||
"@post-cmd"
|
||||
],
|
||||
"post-update-cmd": [
|
||||
"@post-cmd"
|
||||
]
|
||||
},
|
||||
"extra": {
|
||||
"incenteev-parameters": {
|
||||
"file": "app/config/parameters.yml"
|
||||
},
|
||||
"public-dir": "web"
|
||||
},
|
||||
"minimum-stability": "dev",
|
||||
"prefer-stable": true,
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Wallabag\\": "src/Wallabag/"
|
||||
@ -182,16 +171,34 @@
|
||||
]
|
||||
},
|
||||
"config": {
|
||||
"allow-plugins": {
|
||||
"phpstan/extension-installer": true,
|
||||
"php-http/discovery": true,
|
||||
"ergebnis/composer-normalize": true
|
||||
},
|
||||
"bin-dir": "bin",
|
||||
"platform": {
|
||||
"php": "7.4.29"
|
||||
},
|
||||
"sort-packages": true,
|
||||
"allow-plugins": {
|
||||
"phpstan/extension-installer": true,
|
||||
"php-http/discovery": true
|
||||
}
|
||||
"sort-packages": true
|
||||
},
|
||||
"minimum-stability": "dev",
|
||||
"prefer-stable": true
|
||||
"extra": {
|
||||
"incenteev-parameters": {
|
||||
"file": "app/config/parameters.yml"
|
||||
},
|
||||
"public-dir": "web"
|
||||
},
|
||||
"scripts": {
|
||||
"post-install-cmd": [
|
||||
"@post-cmd"
|
||||
],
|
||||
"post-update-cmd": [
|
||||
"@post-cmd"
|
||||
],
|
||||
"post-cmd": [
|
||||
"Incenteev\\ParameterHandler\\ScriptHandler::buildParameters",
|
||||
"bin/console cache:clear --no-warmup",
|
||||
"bin/console assets:install web --symlink --relative"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
613
composer.lock
generated
613
composer.lock
generated
File diff suppressed because it is too large
Load Diff
@ -1,4 +1,4 @@
|
||||
FROM php:7.4-fpm AS rootless
|
||||
FROM php:8.1-fpm AS rootless
|
||||
|
||||
ARG DEBIAN_FRONTEND=noninteractive
|
||||
ARG NODE_VERSION=16
|
||||
@ -33,7 +33,8 @@ RUN apt-get update && apt-get install -y \
|
||||
zlib1g-dev \
|
||||
git \
|
||||
build-essential \
|
||||
nodejs
|
||||
nodejs \
|
||||
npm
|
||||
RUN docker-php-ext-configure gd --with-freetype --with-jpeg --with-webp
|
||||
RUN docker-php-ext-install -j "$(nproc)" \
|
||||
bcmath \
|
||||
|
||||
@ -22,7 +22,6 @@ parameters:
|
||||
secret: ${SECRET:-~}
|
||||
|
||||
# two factor stuff
|
||||
twofactor_auth: ${TWOFACTOR_AUTH:-true}
|
||||
twofactor_sender: ${TWOFACTOR_SENDER:-no-reply@wallabag.org}
|
||||
|
||||
# fosuser stuff
|
||||
|
||||
22
package.json
22
package.json
@ -36,13 +36,13 @@
|
||||
"url": "https://github.com/wallabag/wallabag/issues"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.22.5",
|
||||
"@babel/eslint-parser": "^7.22.5",
|
||||
"@babel/preset-env": "^7.22.5",
|
||||
"@babel/core": "^7.22.9",
|
||||
"@babel/eslint-parser": "^7.22.9",
|
||||
"@babel/preset-env": "^7.22.9",
|
||||
"autoprefixer": "^10.4.14",
|
||||
"babel-loader": "^9.1.2",
|
||||
"babel-loader": "^9.1.3",
|
||||
"css-loader": "^6.8.1",
|
||||
"eslint": "^8.43.0",
|
||||
"eslint": "^8.45.0",
|
||||
"eslint-config-airbnb-base": "^15.0.0",
|
||||
"eslint-plugin-import": "^2.27.5",
|
||||
"eslint-webpack-plugin": "^4.0.1",
|
||||
@ -50,20 +50,20 @@
|
||||
"lato-font": "^3.0.0",
|
||||
"mini-css-extract-plugin": "^2.7.6",
|
||||
"node-sass": "^9.0.0",
|
||||
"postcss": "^8.4.24",
|
||||
"postcss": "^8.4.27",
|
||||
"postcss-loader": "^7.3.3",
|
||||
"postcss-scss": "^4.0.6",
|
||||
"sass": "^1.63.4",
|
||||
"sass": "^1.64.1",
|
||||
"sass-loader": "^13.3.2",
|
||||
"style-loader": "^3.3.3",
|
||||
"stylelint": "^15.8.0",
|
||||
"stylelint-config-standard": "^33.0.0",
|
||||
"stylelint-config-standard-scss": "^9.0.0",
|
||||
"stylelint": "^15.10.2",
|
||||
"stylelint-config-standard": "^34.0.0",
|
||||
"stylelint-config-standard-scss": "^10.0.0",
|
||||
"stylelint-scss": "^5.0.1",
|
||||
"stylelint-webpack-plugin": "^4.1.1",
|
||||
"terser-webpack-plugin": "^5.3.9",
|
||||
"url-loader": "^4.1.1",
|
||||
"webpack": "^5.87.0",
|
||||
"webpack": "^5.88.2",
|
||||
"webpack-cli": "^5.1.4",
|
||||
"webpack-dev-server": "^4.15.1",
|
||||
"webpack-manifest-plugin": "^5.0.0",
|
||||
|
||||
@ -8,6 +8,7 @@ use FOS\UserBundle\Event\UserEvent;
|
||||
use FOS\UserBundle\FOSUserEvents;
|
||||
use FOS\UserBundle\Model\UserManagerInterface;
|
||||
use JMS\Serializer\SerializationContext;
|
||||
use Nelmio\ApiDocBundle\Annotation\Model;
|
||||
use Nelmio\ApiDocBundle\Annotation\Operation;
|
||||
use OpenApi\Annotations as OA;
|
||||
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
||||
@ -28,7 +29,8 @@ class UserRestController extends WallabagRestController
|
||||
* summary="Retrieve current logged in user informations.",
|
||||
* @OA\Response(
|
||||
* response="200",
|
||||
* description="Returned when successful"
|
||||
* description="Returned when successful",
|
||||
* @Model(type=User::class, groups={"user_api"}))
|
||||
* )
|
||||
* )
|
||||
*
|
||||
@ -52,32 +54,45 @@ class UserRestController extends WallabagRestController
|
||||
* @OA\RequestBody(
|
||||
* @OA\JsonContent(
|
||||
* type="object",
|
||||
* required={"username", "password", "email", "client_name"},
|
||||
* required={"username", "password", "email"},
|
||||
* @OA\Property(
|
||||
* property="username",
|
||||
* description="The user's username",
|
||||
* @OA\Schema(type="string")
|
||||
* type="string",
|
||||
* example="wallabag",
|
||||
* ),
|
||||
* @OA\Property(
|
||||
* property="password",
|
||||
* description="The user's password",
|
||||
* @OA\Schema(type="string")
|
||||
* type="string",
|
||||
* example="hidden_value",
|
||||
* ),
|
||||
* @OA\Property(
|
||||
* property="email",
|
||||
* description="The user's email",
|
||||
* @OA\Schema(type="string")
|
||||
* type="string",
|
||||
* example="wallabag@wallabag.io",
|
||||
* ),
|
||||
* @OA\Property(
|
||||
* property="client_name",
|
||||
* description="The client name (to be used by your app)",
|
||||
* @OA\Schema(type="string")
|
||||
* type="string",
|
||||
* example="Fancy App",
|
||||
* ),
|
||||
* )
|
||||
* ),
|
||||
* @OA\Response(
|
||||
* response="200",
|
||||
* description="Returned when successful"
|
||||
* response="201",
|
||||
* description="Returned when successful",
|
||||
* @Model(type=User::class, groups={"user_api_with_client"})),
|
||||
* ),
|
||||
* @OA\Response(
|
||||
* response="403",
|
||||
* description="Server doesn't allow registrations"
|
||||
* ),
|
||||
* @OA\Response(
|
||||
* response="400",
|
||||
* description="Request is incorrectly formatted"
|
||||
* )
|
||||
* )
|
||||
*
|
||||
|
||||
@ -7,6 +7,7 @@ use Doctrine\ORM\EntityManagerInterface;
|
||||
use FOS\RestBundle\Controller\AbstractFOSRestController;
|
||||
use JMS\Serializer\SerializationContext;
|
||||
use JMS\Serializer\SerializerInterface;
|
||||
use Nelmio\ApiDocBundle\Annotation\Model;
|
||||
use Nelmio\ApiDocBundle\Annotation\Operation;
|
||||
use OpenApi\Annotations as OA;
|
||||
use Symfony\Component\HttpFoundation\JsonResponse;
|
||||
@ -15,6 +16,7 @@ use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInt
|
||||
use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface;
|
||||
use Symfony\Component\Security\Core\Exception\AccessDeniedException;
|
||||
use Symfony\Contracts\Translation\TranslatorInterface;
|
||||
use Wallabag\ApiBundle\Entity\ApplicationInfo;
|
||||
use Wallabag\UserBundle\Entity\User;
|
||||
|
||||
class WallabagRestController extends AbstractFOSRestController
|
||||
@ -38,11 +40,16 @@ class WallabagRestController extends AbstractFOSRestController
|
||||
* Retrieve version number.
|
||||
*
|
||||
* @Operation(
|
||||
* tags={"Informations"},
|
||||
* tags={"Information"},
|
||||
* summary="Retrieve version number.",
|
||||
* @OA\Response(
|
||||
* response="200",
|
||||
* description="Returned when successful"
|
||||
* description="Returned when successful",
|
||||
* @OA\JsonContent(
|
||||
* description="Version number of the application.",
|
||||
* type="string",
|
||||
* example="2.5.2",
|
||||
* )
|
||||
* )
|
||||
* )
|
||||
*
|
||||
@ -61,14 +68,13 @@ class WallabagRestController extends AbstractFOSRestController
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve information about the wallabag instance.
|
||||
*
|
||||
* @Operation(
|
||||
* tags={"Informations"},
|
||||
* summary="Retrieve information about the wallabag instance.",
|
||||
* tags={"Information"},
|
||||
* summary="Retrieve information about the running wallabag application.",
|
||||
* @OA\Response(
|
||||
* response="200",
|
||||
* description="Returned when successful"
|
||||
* description="Returned when successful",
|
||||
* @Model(type=ApplicationInfo::class),
|
||||
* )
|
||||
* )
|
||||
*
|
||||
@ -78,11 +84,10 @@ class WallabagRestController extends AbstractFOSRestController
|
||||
*/
|
||||
public function getInfoAction(Config $craueConfig)
|
||||
{
|
||||
$info = [
|
||||
'appname' => 'wallabag',
|
||||
'version' => $this->getParameter('wallabag_core.version'),
|
||||
'allowed_registration' => $this->getParameter('fosuser_registration') && $craueConfig->get('api_user_registration'),
|
||||
];
|
||||
$info = new ApplicationInfo(
|
||||
$this->getParameter('wallabag_core.version'),
|
||||
$this->getParameter('fosuser_registration') && $craueConfig->get('api_user_registration'),
|
||||
);
|
||||
|
||||
return (new JsonResponse())->setJson($this->serializer->serialize($info, 'json'));
|
||||
}
|
||||
|
||||
44
src/Wallabag/ApiBundle/Entity/ApplicationInfo.php
Normal file
44
src/Wallabag/ApiBundle/Entity/ApplicationInfo.php
Normal file
@ -0,0 +1,44 @@
|
||||
<?php
|
||||
|
||||
namespace Wallabag\ApiBundle\Entity;
|
||||
|
||||
use OpenApi\Annotations as OA;
|
||||
|
||||
class ApplicationInfo
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
* @OA\Property(
|
||||
* description="Name of the application.",
|
||||
* type="string",
|
||||
* example="wallabag",
|
||||
* )
|
||||
*/
|
||||
public $appname;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
* @OA\Property(
|
||||
* description="Version number of the application.",
|
||||
* type="string",
|
||||
* example="2.5.2",
|
||||
* )
|
||||
*/
|
||||
public $version;
|
||||
|
||||
/**
|
||||
* @var bool
|
||||
* @OA\Property(
|
||||
* description="Indicates whether registration is allowed. See PUT /api/user.",
|
||||
* type="boolean"
|
||||
* )
|
||||
*/
|
||||
public $allowed_registration;
|
||||
|
||||
public function __construct($version, $allowed_registration)
|
||||
{
|
||||
$this->appname = 'wallabag';
|
||||
$this->version = $version;
|
||||
$this->allowed_registration = $allowed_registration;
|
||||
}
|
||||
}
|
||||
@ -7,6 +7,7 @@ use FOS\OAuthServerBundle\Entity\Client as BaseClient;
|
||||
use JMS\Serializer\Annotation\Groups;
|
||||
use JMS\Serializer\Annotation\SerializedName;
|
||||
use JMS\Serializer\Annotation\VirtualProperty;
|
||||
use OpenApi\Annotations as OA;
|
||||
use Wallabag\UserBundle\Entity\User;
|
||||
|
||||
/**
|
||||
@ -27,6 +28,12 @@ class Client extends BaseClient
|
||||
*
|
||||
* @ORM\Column(name="name", type="text", nullable=false)
|
||||
*
|
||||
* @OA\Property(
|
||||
* description="Name of the API client",
|
||||
* type="string",
|
||||
* example="Default Client",
|
||||
* )
|
||||
*
|
||||
* @Groups({"user_api_with_client"})
|
||||
*/
|
||||
protected $name;
|
||||
@ -44,6 +51,12 @@ class Client extends BaseClient
|
||||
/**
|
||||
* @var string
|
||||
*
|
||||
* @OA\Property(
|
||||
* description="Client secret used for authorization",
|
||||
* type="string",
|
||||
* example="2lmubx2m9vy80ss8c4wwcsg8ok44s88ocwcc8wo0w884oc8440",
|
||||
* )
|
||||
*
|
||||
* @SerializedName("client_secret")
|
||||
* @Groups({"user_api_with_client"})
|
||||
*/
|
||||
@ -94,6 +107,13 @@ class Client extends BaseClient
|
||||
|
||||
/**
|
||||
* @VirtualProperty
|
||||
*
|
||||
* @OA\Property(
|
||||
* description="Client secret used for authorization",
|
||||
* type="string",
|
||||
* example="3_1lpybsn0od40css4w4ko8gsc8cwwskggs8kgg448ko0owo4c84",
|
||||
* )
|
||||
*
|
||||
* @SerializedName("client_id")
|
||||
* @Groups({"user_api_with_client"})
|
||||
*/
|
||||
|
||||
@ -372,24 +372,25 @@ class InstallCommand extends Command
|
||||
private function isDatabasePresent()
|
||||
{
|
||||
$connection = $this->entityManager->getConnection();
|
||||
$databaseName = $connection->getDatabase();
|
||||
|
||||
try {
|
||||
$schemaManager = $connection->getSchemaManager();
|
||||
$databaseName = $connection->getDatabase();
|
||||
} catch (\Exception $exception) {
|
||||
// mysql & sqlite
|
||||
if (false !== strpos($exception->getMessage(), sprintf("Unknown database '%s'", $databaseName))) {
|
||||
if (false !== strpos($exception->getMessage(), 'Unknown database')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// pgsql
|
||||
if (false !== strpos($exception->getMessage(), sprintf('database "%s" does not exist', $databaseName))) {
|
||||
if (false !== strpos($exception->getMessage(), 'does not exist')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
throw $exception;
|
||||
}
|
||||
|
||||
$schemaManager = $connection->getSchemaManager();
|
||||
|
||||
// custom verification for sqlite, since `getListDatabasesSQL` doesn't work for sqlite
|
||||
if ('sqlite' === $schemaManager->getDatabasePlatform()->getName()) {
|
||||
$params = $connection->getParams();
|
||||
|
||||
@ -246,7 +246,6 @@ class ConfigController extends AbstractController
|
||||
'username' => $user->getUsername(),
|
||||
'token' => $config->getFeedToken(),
|
||||
],
|
||||
'twofactor_auth' => $this->getParameter('twofactor_auth'),
|
||||
'wallabag_url' => $this->getParameter('domain_name'),
|
||||
'enabled_users' => $userRepository->getSumEnabledUsers(),
|
||||
]);
|
||||
@ -259,10 +258,6 @@ class ConfigController extends AbstractController
|
||||
*/
|
||||
public function disableOtpEmailAction()
|
||||
{
|
||||
if (!$this->getParameter('twofactor_auth')) {
|
||||
return $this->createNotFoundException('two_factor not enabled');
|
||||
}
|
||||
|
||||
$user = $this->getUser();
|
||||
$user->setEmailTwoFactor(false);
|
||||
|
||||
@ -283,10 +278,6 @@ class ConfigController extends AbstractController
|
||||
*/
|
||||
public function otpEmailAction()
|
||||
{
|
||||
if (!$this->getParameter('twofactor_auth')) {
|
||||
return $this->createNotFoundException('two_factor not enabled');
|
||||
}
|
||||
|
||||
$user = $this->getUser();
|
||||
|
||||
$user->setGoogleAuthenticatorSecret(null);
|
||||
@ -310,10 +301,6 @@ class ConfigController extends AbstractController
|
||||
*/
|
||||
public function disableOtpAppAction()
|
||||
{
|
||||
if (!$this->getParameter('twofactor_auth')) {
|
||||
return $this->createNotFoundException('two_factor not enabled');
|
||||
}
|
||||
|
||||
$user = $this->getUser();
|
||||
|
||||
$user->setGoogleAuthenticatorSecret('');
|
||||
@ -336,10 +323,6 @@ class ConfigController extends AbstractController
|
||||
*/
|
||||
public function otpAppAction(GoogleAuthenticatorInterface $googleAuthenticator)
|
||||
{
|
||||
if (!$this->getParameter('twofactor_auth')) {
|
||||
return $this->createNotFoundException('two_factor not enabled');
|
||||
}
|
||||
|
||||
$user = $this->getUser();
|
||||
$secret = $googleAuthenticator->generateSecret();
|
||||
|
||||
@ -377,10 +360,6 @@ class ConfigController extends AbstractController
|
||||
*/
|
||||
public function otpAppCancelAction()
|
||||
{
|
||||
if (!$this->getParameter('twofactor_auth')) {
|
||||
return $this->createNotFoundException('two_factor not enabled');
|
||||
}
|
||||
|
||||
$user = $this->getUser();
|
||||
$user->setGoogleAuthenticatorSecret(null);
|
||||
$user->setBackupCodes(null);
|
||||
|
||||
@ -61,13 +61,21 @@ class ExportController extends AbstractController
|
||||
*
|
||||
* @return Response
|
||||
*/
|
||||
public function downloadEntriesAction(Request $request, EntryRepository $entryRepository, TagRepository $tagRepository, EntriesExport $entriesExport, string $format, string $category)
|
||||
public function downloadEntriesAction(Request $request, EntryRepository $entryRepository, TagRepository $tagRepository, EntriesExport $entriesExport, string $format, string $category, int $entry = 0)
|
||||
{
|
||||
$method = ucfirst($category);
|
||||
$methodBuilder = 'getBuilderFor' . $method . 'ByUser';
|
||||
$title = $method;
|
||||
|
||||
if ('tag_entries' === $category) {
|
||||
if ('same_domain' === $category) {
|
||||
$entries = $entryRepository->getBuilderForSameDomainByUser(
|
||||
$this->getUser()->getId(),
|
||||
$request->get('entry')
|
||||
)->getQuery()
|
||||
->getResult();
|
||||
|
||||
$title = 'Same domain';
|
||||
} elseif ('tag_entries' === $category) {
|
||||
$tag = $tagRepository->findOneBySlug($request->query->get('tag'));
|
||||
|
||||
$entries = $entryRepository->findAllByTagId(
|
||||
|
||||
@ -209,38 +209,36 @@
|
||||
|
||||
{{ form_widget(form.user.save, {'attr': {'class': 'btn waves-effect waves-light'}}) }}
|
||||
|
||||
{% if twofactor_auth %}
|
||||
<br/>
|
||||
<br/>
|
||||
<div class="row">
|
||||
<h5>{{ 'config.otp.page_title'|trans }}</h5>
|
||||
<br/>
|
||||
<br/>
|
||||
<div class="row">
|
||||
<h5>{{ 'config.otp.page_title'|trans }}</h5>
|
||||
|
||||
<p>{{ 'config.form_user.two_factor_description'|trans }}</p>
|
||||
<p>{{ 'config.form_user.two_factor_description'|trans }}</p>
|
||||
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>{{ 'config.form_user.two_factor.table_method'|trans }}</th>
|
||||
<th>{{ 'config.form_user.two_factor.table_state'|trans }}</th>
|
||||
<th>{{ 'config.form_user.two_factor.table_action'|trans }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>{{ 'config.form_user.two_factor.table_method'|trans }}</th>
|
||||
<th>{{ 'config.form_user.two_factor.table_state'|trans }}</th>
|
||||
<th>{{ 'config.form_user.two_factor.table_action'|trans }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>{{ 'config.form_user.two_factor.emailTwoFactor_label'|trans }}</td>
|
||||
<td>{% if app.user.isEmailTwoFactor %}<b>{{ 'config.form_user.two_factor.state_enabled'|trans }}</b>{% else %}{{ 'config.form_user.two_factor.state_disabled'|trans }}{% endif %}</td>
|
||||
<td><a href="{{ path('config_otp_email') }}" class="waves-effect waves-light btn{% if app.user.isEmailTwoFactor %} disabled{% endif %}">{{ 'config.form_user.two_factor.action_email'|trans }}</a> {% if app.user.isEmailTwoFactor %}<a href="{{ path('disable_otp_email') }}" class="waves-effect waves-light btn red">Disable</a>{% endif %}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>{{ 'config.form_user.two_factor.googleTwoFactor_label'|trans }}</td>
|
||||
<td>{% if app.user.isGoogleTwoFactor %}<b>{{ 'config.form_user.two_factor.state_enabled'|trans }}</b>{% else %}{{ 'config.form_user.two_factor.state_disabled'|trans }}{% endif %}</td>
|
||||
<td><a href="{{ path('config_otp_app') }}" class="waves-effect waves-light btn{% if app.user.isGoogleTwoFactor %} disabled{% endif %}">{{ 'config.form_user.two_factor.action_app'|trans }}</a> {% if app.user.isGoogleTwoFactor %}<a href="{{ path('disable_otp_app') }}" class="waves-effect waves-light btn red">Disable</a>{% endif %}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
{% endif %}
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>{{ 'config.form_user.two_factor.emailTwoFactor_label'|trans }}</td>
|
||||
<td>{% if app.user.isEmailTwoFactor %}<b>{{ 'config.form_user.two_factor.state_enabled'|trans }}</b>{% else %}{{ 'config.form_user.two_factor.state_disabled'|trans }}{% endif %}</td>
|
||||
<td><a href="{{ path('config_otp_email') }}" class="waves-effect waves-light btn{% if app.user.isEmailTwoFactor %} disabled{% endif %}">{{ 'config.form_user.two_factor.action_email'|trans }}</a> {% if app.user.isEmailTwoFactor %}<a href="{{ path('disable_otp_email') }}" class="waves-effect waves-light btn red">Disable</a>{% endif %}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>{{ 'config.form_user.two_factor.googleTwoFactor_label'|trans }}</td>
|
||||
<td>{% if app.user.isGoogleTwoFactor %}<b>{{ 'config.form_user.two_factor.state_enabled'|trans }}</b>{% else %}{{ 'config.form_user.two_factor.state_disabled'|trans }}{% endif %}</td>
|
||||
<td><a href="{{ path('config_otp_app') }}" class="waves-effect waves-light btn{% if app.user.isGoogleTwoFactor %} disabled{% endif %}">{{ 'config.form_user.two_factor.action_app'|trans }}</a> {% if app.user.isGoogleTwoFactor %}<a href="{{ path('disable_otp_app') }}" class="waves-effect waves-light btn red">Disable</a>{% endif %}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
{{ form_widget(form.user._token) }}
|
||||
</form>
|
||||
</div>
|
||||
|
||||
@ -18,7 +18,7 @@
|
||||
<a title="{{ 'entry.list.toogle_as_star'|trans }}" class="tool grey-text" href="{{ path('star_entry', {'id': entry.id}) }}" data-action="star" data-entry-id="{{ entry.id }}"><i class="material-icons">{% if entry.isStarred == 0 %}star_border{% else %}star{% endif %}</i></a>
|
||||
</li>
|
||||
<li>
|
||||
<a title="{{ 'entry.list.delete'|trans }}" data-action-confirm="{{ 'entry.confirm.delete'|trans }}" class="tool grey-text delete" href="{{ path('delete_entry', {'id': entry.id}) }}" data-action="delete" data-entry-id="{{ entry.id }}"><i class="material-icons">delete</i></a>
|
||||
<a title="{{ 'entry.list.delete'|trans }}" onclick="return confirm('{{ 'entry.confirm.delete'|trans|escape('js') }}')" data-action-confirm="{{ 'entry.confirm.delete'|trans }}" class="tool grey-text delete" href="{{ path('delete_entry', {'id': entry.id}) }}" data-action="delete" data-entry-id="{{ entry.id }}"><i class="material-icons">delete</i></a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
@ -9,6 +9,6 @@
|
||||
{% set feed_route = feed_route ~ '_feed' %}
|
||||
{% set slug = null %}
|
||||
{% endif %}
|
||||
{% if feed_route %}
|
||||
{% if feed_route is defined %}
|
||||
<a rel="alternate" type="application/atom+xml" href="{{ path(feed_route, {'username': app.user.username, 'token': app.user.config.feedToken, 'slug': slug}) }}" class="results-item"><i class="material-icons">rss_feed</i></a>
|
||||
{% endif %}
|
||||
|
||||
@ -96,16 +96,17 @@
|
||||
{% if searchTerm is defined %}
|
||||
{% set export_search_term = searchTerm %}
|
||||
{% endif %}
|
||||
{% set entry = app.request.attributes.get('id') %}
|
||||
{% set previous_route = app.request.attributes.get('currentRoute') %}
|
||||
<h4 class="center">{{ 'entry.list.export_title'|trans }}</h4>
|
||||
<ul>
|
||||
{% if craue_setting('export_epub') %}<li class="bold"><a class="waves-effect" href="{{ path('export_entries', {'category': current_route, 'format': 'epub', 'tag': current_tag, 'search_entry[term]': export_search_term, 'currentRoute': previous_route}) }}">EPUB</a></li>{% endif %}
|
||||
{% if craue_setting('export_mobi') %}<li class="bold"><a class="waves-effect" href="{{ path('export_entries', {'category': current_route, 'format': 'mobi', 'tag': current_tag, 'search_entry[term]': export_search_term, 'currentRoute': previous_route}) }}">MOBI (deprecated)</a></li>{% endif %}
|
||||
{% if craue_setting('export_pdf') %}<li class="bold"><a class="waves-effect" href="{{ path('export_entries', {'category': current_route, 'format': 'pdf', 'tag': current_tag, 'search_entry[term]': export_search_term, 'currentRoute': previous_route}) }}">PDF</a></li>{% endif %}
|
||||
{% if craue_setting('export_json') %}<li class="bold"><a class="waves-effect" href="{{ path('export_entries', {'category': current_route, 'format': 'json', 'tag': current_tag, 'search_entry[term]': export_search_term, 'currentRoute': previous_route}) }}">JSON</a></li>{% endif %}
|
||||
{% if craue_setting('export_csv') %}<li class="bold"><a class="waves-effect" href="{{ path('export_entries', {'category': current_route, 'format': 'csv', 'tag': current_tag, 'search_entry[term]': export_search_term, 'currentRoute': previous_route}) }}">CSV</a></li>{% endif %}
|
||||
{% if craue_setting('export_txt') %}<li class="bold"><a class="waves-effect" href="{{ path('export_entries', {'category': current_route, 'format': 'txt', 'tag': current_tag, 'search_entry[term]': export_search_term, 'currentRoute': previous_route}) }}">TXT</a></li>{% endif %}
|
||||
{% if craue_setting('export_xml') %}<li class="bold"><a class="waves-effect" href="{{ path('export_entries', {'category': current_route, 'format': 'xml', 'tag': current_tag, 'search_entry[term]': export_search_term, 'currentRoute': previous_route}) }}">XML</a></li>{% endif %}
|
||||
{% if craue_setting('export_epub') %}<li class="bold"><a class="waves-effect" href="{{ path('export_entries', {'category': current_route, 'format': 'epub', 'tag': current_tag, 'search_entry[term]': export_search_term, 'currentRoute': previous_route, 'entry': entry}) }}">EPUB</a></li>{% endif %}
|
||||
{% if craue_setting('export_mobi') %}<li class="bold"><a class="waves-effect" href="{{ path('export_entries', {'category': current_route, 'format': 'mobi', 'tag': current_tag, 'search_entry[term]': export_search_term, 'currentRoute': previous_route, 'entry': entry}) }}">MOBI (deprecated)</a></li>{% endif %}
|
||||
{% if craue_setting('export_pdf') %}<li class="bold"><a class="waves-effect" href="{{ path('export_entries', {'category': current_route, 'format': 'pdf', 'tag': current_tag, 'search_entry[term]': export_search_term, 'currentRoute': previous_route, 'entry': entry}) }}">PDF</a></li>{% endif %}
|
||||
{% if craue_setting('export_json') %}<li class="bold"><a class="waves-effect" href="{{ path('export_entries', {'category': current_route, 'format': 'json', 'tag': current_tag, 'search_entry[term]': export_search_term, 'currentRoute': previous_route, 'entry': entry}) }}">JSON</a></li>{% endif %}
|
||||
{% if craue_setting('export_csv') %}<li class="bold"><a class="waves-effect" href="{{ path('export_entries', {'category': current_route, 'format': 'csv', 'tag': current_tag, 'search_entry[term]': export_search_term, 'currentRoute': previous_route, 'entry': entry}) }}">CSV</a></li>{% endif %}
|
||||
{% if craue_setting('export_txt') %}<li class="bold"><a class="waves-effect" href="{{ path('export_entries', {'category': current_route, 'format': 'txt', 'tag': current_tag, 'search_entry[term]': export_search_term, 'currentRoute': previous_route, 'entry': entry}) }}">TXT</a></li>{% endif %}
|
||||
{% if craue_setting('export_xml') %}<li class="bold"><a class="waves-effect" href="{{ path('export_entries', {'category': current_route, 'format': 'xml', 'tag': current_tag, 'search_entry[term]': export_search_term, 'currentRoute': previous_route, 'entry': entry}) }}">XML</a></li>{% endif %}
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
|
||||
@ -85,19 +85,17 @@ class ManageController extends AbstractController
|
||||
$form->handleRequest($request);
|
||||
|
||||
// `googleTwoFactor` isn't a field within the User entity, we need to define it's value in a different way
|
||||
if ($this->getParameter('twofactor_auth') && true === $user->isGoogleAuthenticatorEnabled() && false === $form->isSubmitted()) {
|
||||
if (true === $user->isGoogleAuthenticatorEnabled() && false === $form->isSubmitted()) {
|
||||
$form->get('googleTwoFactor')->setData(true);
|
||||
}
|
||||
|
||||
if ($form->isSubmitted() && $form->isValid()) {
|
||||
// handle creation / reset of the OTP secret if checkbox changed from the previous state
|
||||
if ($this->getParameter('twofactor_auth')) {
|
||||
if (true === $form->get('googleTwoFactor')->getData() && false === $user->isGoogleAuthenticatorEnabled()) {
|
||||
$user->setGoogleAuthenticatorSecret($googleAuthenticator->generateSecret());
|
||||
$user->setEmailTwoFactor(false);
|
||||
} elseif (false === $form->get('googleTwoFactor')->getData() && true === $user->isGoogleAuthenticatorEnabled()) {
|
||||
$user->setGoogleAuthenticatorSecret(null);
|
||||
}
|
||||
if (true === $form->get('googleTwoFactor')->getData() && false === $user->isGoogleAuthenticatorEnabled()) {
|
||||
$user->setGoogleAuthenticatorSecret($googleAuthenticator->generateSecret());
|
||||
$user->setEmailTwoFactor(false);
|
||||
} elseif (false === $form->get('googleTwoFactor')->getData() && true === $user->isGoogleAuthenticatorEnabled()) {
|
||||
$user->setGoogleAuthenticatorSecret(null);
|
||||
}
|
||||
|
||||
$userManager->updateUser($user);
|
||||
@ -114,7 +112,6 @@ class ManageController extends AbstractController
|
||||
'user' => $user,
|
||||
'edit_form' => $form->createView(),
|
||||
'delete_form' => $deleteForm->createView(),
|
||||
'twofactor_auth' => $this->getParameter('twofactor_auth'),
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
@ -8,6 +8,8 @@ use FOS\UserBundle\Model\User as BaseUser;
|
||||
use JMS\Serializer\Annotation\Accessor;
|
||||
use JMS\Serializer\Annotation\Groups;
|
||||
use JMS\Serializer\Annotation\XmlRoot;
|
||||
use Nelmio\ApiDocBundle\Annotation\Model;
|
||||
use OpenApi\Annotations as OA;
|
||||
use Scheb\TwoFactorBundle\Model\BackupCodeInterface;
|
||||
use Scheb\TwoFactorBundle\Model\Email\TwoFactorInterface as EmailTwoFactorInterface;
|
||||
use Scheb\TwoFactorBundle\Model\Google\TwoFactorInterface as GoogleTwoFactorInterface;
|
||||
@ -40,6 +42,12 @@ class User extends BaseUser implements EmailTwoFactorInterface, GoogleTwoFactorI
|
||||
* @ORM\Id
|
||||
* @ORM\GeneratedValue(strategy="AUTO")
|
||||
*
|
||||
* @OA\Property(
|
||||
* description="The unique numeric id of the user",
|
||||
* type="int",
|
||||
* example=12,
|
||||
* )
|
||||
*
|
||||
* @Groups({"user_api", "user_api_with_client"})
|
||||
*/
|
||||
protected $id;
|
||||
@ -49,6 +57,12 @@ class User extends BaseUser implements EmailTwoFactorInterface, GoogleTwoFactorI
|
||||
*
|
||||
* @ORM\Column(name="name", type="text", nullable=true)
|
||||
*
|
||||
* @OA\Property(
|
||||
* description="The personal Name of the user",
|
||||
* type="string",
|
||||
* example="Walla Baggger",
|
||||
* )
|
||||
*
|
||||
* @Groups({"user_api", "user_api_with_client"})
|
||||
*/
|
||||
protected $name;
|
||||
@ -56,6 +70,12 @@ class User extends BaseUser implements EmailTwoFactorInterface, GoogleTwoFactorI
|
||||
/**
|
||||
* @var string
|
||||
*
|
||||
* @OA\Property(
|
||||
* description="The unique username of the user",
|
||||
* type="string",
|
||||
* example="wallabag",
|
||||
* )
|
||||
*
|
||||
* @Groups({"user_api", "user_api_with_client"})
|
||||
*/
|
||||
protected $username;
|
||||
@ -63,6 +83,12 @@ class User extends BaseUser implements EmailTwoFactorInterface, GoogleTwoFactorI
|
||||
/**
|
||||
* @var string
|
||||
*
|
||||
* @OA\Property(
|
||||
* description="E-mail address of the user",
|
||||
* type="string",
|
||||
* example="wallabag@wallabag.io",
|
||||
* )
|
||||
*
|
||||
* @Groups({"user_api", "user_api_with_client"})
|
||||
*/
|
||||
protected $email;
|
||||
@ -72,6 +98,12 @@ class User extends BaseUser implements EmailTwoFactorInterface, GoogleTwoFactorI
|
||||
*
|
||||
* @ORM\Column(name="created_at", type="datetime")
|
||||
*
|
||||
* @OA\Property(
|
||||
* description="Creation date of the user account. (In ISO 8601 format)",
|
||||
* type="string",
|
||||
* example="2023-06-27T19:25:44+0000",
|
||||
* )
|
||||
*
|
||||
* @Groups({"user_api", "user_api_with_client"})
|
||||
*/
|
||||
protected $createdAt;
|
||||
@ -81,6 +113,12 @@ class User extends BaseUser implements EmailTwoFactorInterface, GoogleTwoFactorI
|
||||
*
|
||||
* @ORM\Column(name="updated_at", type="datetime")
|
||||
*
|
||||
* @OA\Property(
|
||||
* description="Update date of the user account. (In ISO 8601 format)",
|
||||
* type="string",
|
||||
* example="2023-06-27T19:37:30+0000",
|
||||
* )
|
||||
*
|
||||
* @Groups({"user_api", "user_api_with_client"})
|
||||
*/
|
||||
protected $updatedAt;
|
||||
@ -112,6 +150,11 @@ class User extends BaseUser implements EmailTwoFactorInterface, GoogleTwoFactorI
|
||||
/**
|
||||
* @see getFirstClient() below
|
||||
*
|
||||
* @OA\Property(
|
||||
* description="Default client created during user registration. Used for further authorization",
|
||||
* ref=@Model(type=Client::class, groups={"user_api_with_client"})
|
||||
* )
|
||||
*
|
||||
* @Groups({"user_api_with_client"})
|
||||
* @Accessor(getter="getFirstClient")
|
||||
*/
|
||||
|
||||
@ -47,7 +47,6 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% if twofactor_auth %}
|
||||
<div class="row">
|
||||
<div class="input-field col s12">
|
||||
{{ form_widget(edit_form.emailTwoFactor) }}
|
||||
@ -60,7 +59,6 @@
|
||||
{{ form_errors(edit_form.googleTwoFactor) }}
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<br/>
|
||||
|
||||
|
||||
@ -10,6 +10,8 @@ class ExportControllerTest extends WallabagCoreTestCase
|
||||
{
|
||||
private $adminEntry;
|
||||
private $bobEntry;
|
||||
private $sameDomainEntry;
|
||||
private $sameDomainEntry2;
|
||||
|
||||
public function testLogin()
|
||||
{
|
||||
@ -326,6 +328,26 @@ class ExportControllerTest extends WallabagCoreTestCase
|
||||
$this->assertNotEmpty('updated_at', (string) $content->entry[0]->updated_at);
|
||||
}
|
||||
|
||||
public function testJsonExportFromSameDomain()
|
||||
{
|
||||
$this->logInAs('admin');
|
||||
$client = $this->getTestClient();
|
||||
|
||||
ob_start();
|
||||
$crawler = $client->request('GET', '/export/same_domain.json?entry=1');
|
||||
ob_end_clean();
|
||||
|
||||
$this->assertSame(200, $client->getResponse()->getStatusCode());
|
||||
|
||||
$headers = $client->getResponse()->headers;
|
||||
$this->assertSame('application/json', $headers->get('content-type'));
|
||||
$this->assertSame('attachment; filename="Same domain articles.json"', $headers->get('content-disposition'));
|
||||
$this->assertSame('UTF-8', $headers->get('content-transfer-encoding'));
|
||||
|
||||
$content = json_decode($client->getResponse()->getContent(), true);
|
||||
$this->assertCount(4, $content);
|
||||
}
|
||||
|
||||
private function setUpForJsonExportFromSearch()
|
||||
{
|
||||
$client = $this->getTestClient();
|
||||
|
||||
@ -237,14 +237,18 @@ class FeedControllerTest extends WallabagCoreTestCase
|
||||
$entry1->setCreatedAt($day1);
|
||||
$entry4->setCreatedAt($day2);
|
||||
|
||||
$property = (new \ReflectionObject($entry1))->getProperty('updatedAt');
|
||||
$property->setAccessible(true);
|
||||
$property->setValue($entry1, $day4);
|
||||
|
||||
$property = (new \ReflectionObject($entry4))->getProperty('updatedAt');
|
||||
$property->setAccessible(true);
|
||||
$property->setValue($entry4, $day3);
|
||||
|
||||
// We have to flush and sleep here to be sure that $entry1 and $entry4 have different updatedAt values
|
||||
$em->flush();
|
||||
sleep(2);
|
||||
|
||||
$property = (new \ReflectionObject($entry1))->getProperty('updatedAt');
|
||||
$property->setAccessible(true);
|
||||
$property->setValue($entry1, $day4);
|
||||
|
||||
$em->flush();
|
||||
|
||||
$client = $this->getTestClient();
|
||||
|
||||
@ -32,12 +32,6 @@ class SecurityControllerTest extends WallabagCoreTestCase
|
||||
{
|
||||
$client = $this->getTestClient();
|
||||
|
||||
if (!$client->getContainer()->getParameter('twofactor_auth')) {
|
||||
$this->markTestSkipped('twofactor_auth is not enabled.');
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$client->followRedirects();
|
||||
|
||||
$em = $client->getContainer()->get(EntityManagerInterface::class);
|
||||
@ -65,12 +59,6 @@ class SecurityControllerTest extends WallabagCoreTestCase
|
||||
{
|
||||
$client = $this->getTestClient();
|
||||
|
||||
if (!$client->getContainer()->getParameter('twofactor_auth')) {
|
||||
$this->markTestSkipped('twofactor_auth is not enabled.');
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$client->followRedirects();
|
||||
|
||||
$em = $client->getContainer()->get(EntityManagerInterface::class);
|
||||
|
||||
@ -88,6 +88,8 @@ config:
|
||||
help_reading_speed: wallabag calcule une durée de lecture pour chaque article. Vous pouvez définir ici, grâce à cette liste déroulante, si vous lisez plus ou moins vite. wallabag recalculera la durée de lecture de chaque article.
|
||||
help_language: Vous pouvez définir la langue de l’interface de wallabag.
|
||||
help_pocket_consumer_key: Nécessaire pour l’import depuis Pocket. Vous pouvez le créer depuis votre compte Pocket.
|
||||
help_display_thumbnails: Vous pouvez décidez d'afficher ou non les miniatures des articles. Utile pour les connexions lentes.
|
||||
display_thumbnails_label: Afficher les miniatures des articles (utile pour les connexions lentes).
|
||||
form_feed:
|
||||
description: "Les flux Atom fournis par wallabag vous permettent de lire vos articles sauvegardés dans votre lecteur de flux préféré. Pour pouvoir les utiliser, vous devez d’abord créer un jeton."
|
||||
token_label: "Jeton de flux"
|
||||
@ -145,7 +147,7 @@ config:
|
||||
card:
|
||||
new_tagging_rule: Créer une règle d'étiquetage
|
||||
import_tagging_rules: Importer des règles
|
||||
import_tagging_rules_detail: Vous devez sélectionné un fichier JSON que vous avez précédemment exporté.
|
||||
import_tagging_rules_detail: Vous devez sélectionner un fichier JSON que vous avez précédemment exporté.
|
||||
export_tagging_rules: Exporter les règles
|
||||
export_tagging_rules_detail: Un fichier JSON sera téléchargé et vous pourrez l'utiliser pour ré-importer les règles ou comme sauvegarde.
|
||||
file_label: Fichier JSON
|
||||
@ -412,7 +414,7 @@ quickstart:
|
||||
configure:
|
||||
title: Configurez l’application
|
||||
description: Pour voir une application qui vous correspond, allez voir du côté de la configuration de wallabag.
|
||||
language: Changez la langue et le design de l’application
|
||||
language: Changez la langue et l'interface
|
||||
rss: Activez les flux RSS
|
||||
tagging_rules: Écrivez des règles pour classer automatiquement vos articles
|
||||
feed: Activer les flux RSS
|
||||
@ -499,7 +501,7 @@ import:
|
||||
description: Cet outil va importer tous vos articles d’une autre instance de wallabag v2. Allez dans tous vos articles, puis, sur la barre latérale, cliquez sur « JSON ». Vous allez récupérer un fichier « All articles.json ».
|
||||
readability:
|
||||
page_title: Importer > Readability
|
||||
description: Cet outil va importer toutes vos données de Readability. Sur la page des outils (https://www.readability.com/tools/), cliquez sur « Export your data » dans la section « Data Export ». Vous allez recevoir un courriel avec un lien pour télécharger le json (qui ne se finit pas par .json).
|
||||
description: Cet outil va importer toutes vos données de Readability.
|
||||
how_to: Choisissez le fichier de votre export Readability et cliquez sur le bouton ci-dessous pour l’importer.
|
||||
worker:
|
||||
enabled: 'Les imports sont asynchrones. Une fois l’import commencé un worker externe traitera les messages un par un. Le service activé est :'
|
||||
@ -521,7 +523,7 @@ import:
|
||||
description: Sur la page « Backup » (https://pinboard.in/settings/backup), cliquez sur « JSON » dans la section « Bookmarks ». Un fichier json (sans extension) sera téléchargé (« pinboard_export »).
|
||||
how_to: Choisissez le fichier de votre export Pinboard et cliquez sur le bouton ci-dessous pour l’importer.
|
||||
elcurator:
|
||||
description: Cet outil va importer tous vos articles depuis elCurator. Allez dans vos préférences sur elCurator et exportez vos contenus. Vous allez récupérer un fichier JSON.
|
||||
description: Cet outil va importer tous vos articles depuis elCurator.
|
||||
page_title: Importer > elCurator
|
||||
delicious:
|
||||
page_title: Importer > del.icio.us
|
||||
|
||||
@ -451,10 +451,10 @@ import:
|
||||
enabled: 'A importación faise de xeito asíncrono. Unha vez se inicia a tarefa de importación, un servizo externo ocuparase delas dunha en unha. O servizo actual é:'
|
||||
readability:
|
||||
how_to: Escolle o teu ficheiro de Readability e preme no botón inferior para subilo e importalo.
|
||||
description: Este importador vai traer todos os teus artigos Readability. Nas ferramentas (https://www.readability.com/tools/), preme en "Exporta os teus datos" na sección "Exportar Datos". Obterás un email para descargar un json (que en realidade non remata en .json).
|
||||
description: Este importador traerá todos os teus artigos en Readability.
|
||||
page_title: Importar > Readability
|
||||
elcurator:
|
||||
description: Este importador traerá todos os teus ficheiros de elCurator. Vai ós axustes na túa conta elCurator e após exporta o teu contido. Obterás un ficheiro JSON.
|
||||
description: Este importador traerá todos os teus artigos de elCurator.
|
||||
page_title: Importar > elCurator
|
||||
delicious:
|
||||
page_title: Importar > del.icio.us
|
||||
@ -519,7 +519,7 @@ quickstart:
|
||||
configure:
|
||||
tagging_rules: Establece regras para etiquetar automáticamente os artigos
|
||||
feed: Activar fontes
|
||||
language: Cambiar o idioma e deseño
|
||||
language: Cambiar o idioma e interface
|
||||
description: Para poder adaptar a aplicación ás túas preferencias, entra nos axustes de wallabag.
|
||||
title: Configurar a aplicación
|
||||
intro:
|
||||
|
||||
@ -64,7 +64,7 @@ import:
|
||||
readability:
|
||||
how_to: Odaberi Readability izvoz i pritisni donji gumb za slanje i uvoz datoteke.
|
||||
page_title: Uvoz > Readability
|
||||
description: Ovaj uvoznik uvozi sve tvoje Readability članke. Na stranici alata (https://www.readability.com/tools/), pritisni „Izvezi svoje podatke” u odjeljku „Izvoz podataka”. Primit ćeš e-mail za preuzimanje json-a (što zapravo ne završava s .json).
|
||||
description: Ovaj će uvoznik uvesti sve tvoje Readability članke.
|
||||
worker:
|
||||
enabled: 'Uvoz se vrši asinkrono. Nakon što se uvoz zadatak pokrene, jedna vanjska usluga obradit će poslove jedan po jedan. Trenutačna usluga je:'
|
||||
download_images_warning: Aktivirao(la) si preuzimanje slika za članke. U kombinaciji s klasičnim uvozom, postupak može potrajati godinama (ili možda ne uspije). <strong>Preporučujemo</strong> aktivirati asinkroniziran uvoz za izbjegavanje grešaka.
|
||||
@ -98,7 +98,7 @@ import:
|
||||
action:
|
||||
import_contents: Sadržaj uvoza
|
||||
elcurator:
|
||||
description: Ovaj će uvoznik uvesti sve tvoje elCurator članke. Prijeđi na postavke na tvom elCurator računu, a zatim izvezi sadržaj. Dobit ćete JSON datoteku.
|
||||
description: Ovaj će uvoznik uvesti sve tvoje elCurator članke.
|
||||
page_title: Uvezi > elCurator
|
||||
delicious:
|
||||
page_title: Uvoz > del.icio.us
|
||||
@ -107,7 +107,7 @@ import:
|
||||
about:
|
||||
helping:
|
||||
description: 'wallabag je slobodan softver otvorenog koda. Možeš nam pomoći:'
|
||||
by_paypal: putem PayPal-a
|
||||
by_paypal: putem Liberapay
|
||||
who_behind_wallabag:
|
||||
license: Licenca
|
||||
website: web-stranica
|
||||
@ -215,6 +215,8 @@ config:
|
||||
items_per_page_label: Broj stavki po stranici
|
||||
help_reading_speed: wallabag izračunava vrijeme čitanja za svaki članak. Ovdje možeš definirati, zahvaljujući ovom popisu, jesi li brz ili spor čitač. wallabag će izračunati vrijeme čitanja za svaki članak.
|
||||
language_label: Jezik
|
||||
help_display_thumbnails: Možeš odlučiti želiš li prikazivati minijature članaka. Korisno za spore veze.
|
||||
display_thumbnails_label: Prikaži minijatue članaka (korisno za spore veze).
|
||||
form_user:
|
||||
delete:
|
||||
confirm: Sigurno? (OVO JE NEPOVRATNA RADNJA)
|
||||
@ -428,6 +430,7 @@ flashes:
|
||||
notice:
|
||||
tag_added: Oznaka dodana
|
||||
tag_renamed: Oznaka preimenovana
|
||||
too_much_tags: Za izbjegavanje problem s performansama, ne možeš dodati više od %tags% oznaka odjednom ili oznake koje imaju više od %characters% znakova.
|
||||
ignore_origin_instance_rule:
|
||||
notice:
|
||||
deleted: Globalno pravilo za zanemarivanje izvora izbrisano
|
||||
@ -495,6 +498,7 @@ entry:
|
||||
assign_search_tag: Dodijeli ovo pretraživanje kao oznaku svakom rezultatu
|
||||
mass_action_tags_input_placeholder: oznaka1, oznaka2, oznaka3
|
||||
toggle_mass_action: Uklj./Isklj. grupne radnje
|
||||
add_tags: Dodaj oznake
|
||||
view:
|
||||
left_menu:
|
||||
set_as_starred: Uklj/Isklj omiljene
|
||||
@ -614,7 +618,7 @@ quickstart:
|
||||
description: Za dobivanje programa koji tebi najviše odgovara, pogledaj konfiguraciju wallabaga.
|
||||
tagging_rules: Odredi pravila za automatsko označivanje članaka
|
||||
title: Konfiguriraj program
|
||||
language: Promijeni jezik i dizajn
|
||||
language: Promijeni jezik i sučelje
|
||||
feed: Aktiviraj feedove
|
||||
developer:
|
||||
description: 'Mislili smo i na pregramere: Docker, sučelje (API), prijevodi itd.'
|
||||
|
||||
@ -430,7 +430,7 @@ quickstart:
|
||||
configure:
|
||||
title: Configurar l'aplicacion
|
||||
description: Per fin d'aver una aplicacion que vos va ben, anatz veire la configuracion de wallabag.
|
||||
language: Cambiar la lenga e l'estil de l'aplicacion
|
||||
language: Cambiar la lenga e l'intterfàcia
|
||||
rss: Activatz los fluxes RSS
|
||||
tagging_rules: Escrivètz de règlas per classar automaticament vòstres articles
|
||||
feed: Activar los flux RSS
|
||||
@ -517,7 +517,7 @@ import:
|
||||
description: Aquesta aisina importarà totas vòstras donadas d'una instància mai de wallabag v2. Anatz dins totes vòstres articles, puèi, sus la barra laterala, clicatz sus "JSON". Traparetz un fichièr "All articles.json".
|
||||
readability:
|
||||
page_title: Importar > Readability
|
||||
description: Aquesta aisina importarà totas vòstres articles de Readability. Sus la pagina de l'aisina (https://www.readability.com/tools/), clicatz sus "Export your data" dins la seccion "Data Export". Recebretz un corrièl per telecargar un json (qu'acaba pas amb un .json de fach).
|
||||
description: Aquesta aisina importarà totas vòstres articles de Readability.
|
||||
how_to: Mercés de seleccionar vòstre Readability fichièr e de clicar sul boton dejós per lo telecargar e l'importar.
|
||||
worker:
|
||||
enabled: "L'importacion se fa de manièra asincròna. Un còp l'importacion lançada, una aisina extèrna s'ocuparà dels articles un per un. Lo servici actual es :"
|
||||
@ -544,7 +544,7 @@ import:
|
||||
how_to: Causissètz lo fichièr de vòstra exportacion Delicious e clicatz lo boton çai jos per l’importar.
|
||||
elcurator:
|
||||
page_title: Importar > elCurator
|
||||
description: Aquesta aisina importarà totes vòstres articles a partir de elCurator. Anatz a las preferéncias de elCurator e exportatz vòstres contenguts. Recuperaretz un fichièr JSON.
|
||||
description: Aquesta aisina importarà totes vòstres articles a partir de elCurator.
|
||||
developer:
|
||||
page_title: Gestion dels clients API
|
||||
welcome_message: Vos desirem la benvenguda sus l'API de wallabag
|
||||
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user