Compare commits

...

16 Commits

Author SHA1 Message Date
William Hall 65681de5a3 🔖 actually 1.8.2 2022-03-22 16:11:07 +00:00
William Hall dc681e1ced Merge remote-tracking branch 'mpeveler/bugfix-endroid-4' 2022-02-14 17:14:18 +00:00
Matthew Peveler 5f2611cde2 Fix compatibility with endroid/qr-code 4 2022-02-14 11:09:10 -05:00
William Hall 5d36d4feb0 Merge remote-tracking branch 'origin/test-specific-provider' 2021-12-29 18:17:40 +00:00
William Hall cb45226800 🚨 test in php < 7.1 2021-12-19 19:50:25 +00:00
William Hall 2d1ec8d265 🐛 be more specific with hex colour handling 2021-12-19 19:44:10 +00:00
William Hall ae4da10ff1 🚨 test bacon qr code provider 2021-12-19 19:33:11 +00:00
William Hall 66e1e030ba ♻️ re arrange useful testing code for provider tests 2021-12-19 19:32:45 +00:00
Will Power e76f31e93b Merge pull request #83 from brainfoolong/master
convert issuer to string prevents php 8.1 errors
2021-12-19 18:21:51 +00:00
Will Power 4203749bd2 Merge pull request #85 from MasterOdin/mpeveler/chore-deprecations
Catch deprecations as part of test suite
2021-12-19 18:19:17 +00:00
William Hall 4f1543f782 🚨 add test to cover null issuer 2021-12-19 18:16:38 +00:00
Matthew Peveler 8a220fe37b Catch deprecations as part of test suite 2021-12-01 10:12:42 -05:00
William Hall 8a5cb24967 🔧 add 8.1 to testing to confirm issue 2021-12-01 09:34:38 +00:00
Roland Eigelsreiter dc9f168746 added 8.1 to builds 2021-11-29 10:25:23 +01:00
Roland Eigelsreiter 0096cce02d convert issuer to string prevents php 8.1 errors
By forcing $this->issuer to be string, even if null is set, it prevents throwing errors in PHP 8.1 is `rawurlencode` is not allowed to have null as parameter.

It would be better to force string to be already in `__construct`, but this may create a breaking change for existing users.
2021-11-29 06:50:54 +01:00
Rob Janssen 042f347666 Update LICENSE 2021-11-02 15:07:43 +01:00
14 changed files with 267 additions and 35 deletions
+30
View File
@@ -0,0 +1,30 @@
name: Test Bacon QR Code Provider
on:
push:
pull_request:
jobs:
build:
runs-on: ubuntu-latest
strategy:
matrix:
php-version: ['5.6', '7.0', '7.1', '7.2', '7.3', '7.4', '8.0', '8.1']
steps:
- uses: actions/checkout@v2
- uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php-version }}
tools: composer
coverage: xdebug
ini-values: error_reporting=E_ALL
- uses: ramsey/composer-install@v1
- run: composer require bacon/bacon-qr-code
- run: composer lint
- run: composer test testsDependency/BaconQRCodeTest.php
+46
View File
@@ -0,0 +1,46 @@
name: Test Endroid QR Code Provider
on:
push:
pull_request:
jobs:
build:
runs-on: ubuntu-latest
strategy:
matrix:
php-version: ['8.0', '8.1']
endroid-version: ["^4"]
include:
- php-version: 5.6
# earliest supported version
endroid-version: 2.2.1
- php-version: 7.0
endroid-version: 2.5.1
- php-version: 7.1
# this version is 7.1+
endroid-version: 3.0.0
- php-version: 7.2
# all later versions are 7.3+
endroid-version: 3.5.9
- php-version: 7.3
endroid-version: 3.9.7
- php-version: 7.4
endroid-version: 4.0.0
steps:
- uses: actions/checkout@v2
- uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php-version }}
tools: composer
coverage: xdebug
ini-values: error_reporting=E_ALL
- uses: ramsey/composer-install@v1
- run: composer require endroid/qrcode:${{ matrix.endroid-version }}
- run: composer test testsDependency/EndroidQRCodeTest.php
+2 -1
View File
@@ -10,7 +10,7 @@ jobs:
strategy:
matrix:
php-version: ['5.6', '7.0', '7.1', '7.2', '7.3', '7.4', '8.0']
php-version: ['5.6', '7.0', '7.1', '7.2', '7.3', '7.4', '8.0', '8.1']
steps:
- uses: actions/checkout@v2
@@ -20,6 +20,7 @@ jobs:
php-version: ${{ matrix.php-version }}
tools: composer
coverage: xdebug
ini-values: error_reporting=E_ALL
- uses: ramsey/composer-install@v1
+1 -1
View File
@@ -1,6 +1,6 @@
The MIT License (MIT)
Copyright (c) 2014-2015 Rob Janssen
Copyright (c) 2014-2021 Rob Janssen and contributors
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
+1 -1
View File
@@ -1,7 +1,7 @@
{
"name": "robthree/twofactorauth",
"description": "Two Factor Authentication",
"version": "1.8.1",
"version": "1.8.2",
"type": "library",
"keywords": [ "Authentication", "Two Factor Authentication", "Multi Factor Authentication", "TFA", "MFA", "PHP", "Authenticator", "Authy" ],
"homepage": "https://github.com/RobThree/TwoFactorAuth",
+10 -3
View File
@@ -125,12 +125,19 @@ class BaconQrCodeProvider implements IQRCodeProvider
{
if (is_string($colour) && $colour[0] == '#') {
$hexToRGB = function ($input) {
// ensure input no longer has a # for more predictable division
// PHP 8.1 does not like implicitly casting a float to an int
$input = trim($input, '#');
if (strlen($input) != 3 && strlen($input) != 6) {
throw new \RuntimeException('Colour should be a 3 or 6 character value after the #');
}
// split the array into three chunks
$split = str_split(trim($input, '#'), strlen($input) / 3);
$split = str_split($input, strlen($input) / 3);
// cope with three character hex reference
// three characters plus a # = 4
if (strlen($input) == 4) {
if (strlen($input) == 3) {
array_walk($split, function (&$character) {
$character = str_repeat($character, 2);
});
+21 -7
View File
@@ -1,8 +1,14 @@
<?php
namespace RobThree\Auth\Providers\Qr;
use Endroid\QrCode\Color\Color;
use Endroid\QrCode\ErrorCorrectionLevel;
use Endroid\QrCode\ErrorCorrectionLevel\ErrorCorrectionLevelHigh;
use Endroid\QrCode\ErrorCorrectionLevel\ErrorCorrectionLevelLow;
use Endroid\QrCode\ErrorCorrectionLevel\ErrorCorrectionLevelMedium;
use Endroid\QrCode\ErrorCorrectionLevel\ErrorCorrectionLevelQuartile;
use Endroid\QrCode\QrCode;
use Endroid\QrCode\Writer\PngWriter;
class EndroidQrCodeProvider implements IQRCodeProvider
{
@@ -11,8 +17,12 @@ class EndroidQrCodeProvider implements IQRCodeProvider
public $margin;
public $errorcorrectionlevel;
protected $endroid4 = false;
public function __construct($bgcolor = 'ffffff', $color = '000000', $margin = 0, $errorcorrectionlevel = 'H')
{
$this->endroid4 = method_exists(QrCode::class, 'create');
$this->bgcolor = $this->handleColor($bgcolor);
$this->color = $this->handleColor($color);
$this->margin = $margin;
@@ -26,7 +36,12 @@ class EndroidQrCodeProvider implements IQRCodeProvider
public function getQRCodeImage($qrtext, $size)
{
return $this->qrCodeInstance($qrtext, $size)->writeString();
if (!$this->endroid4) {
return $this->qrCodeInstance($qrtext, $size)->writeString();
}
$writer = new PngWriter();
return $writer->write($this->qrCodeInstance($qrtext, $size))->getString();
}
protected function qrCodeInstance($qrtext, $size)
@@ -49,22 +64,21 @@ class EndroidQrCodeProvider implements IQRCodeProvider
$g = hexdec($split[1]);
$b = hexdec($split[2]);
return ['r' => $r, 'g' => $g, 'b' => $b, 'a' => 0];
return $this->endroid4 ? new Color($r, $g, $b, 0) : ['r' => $r, 'g' => $g, 'b' => $b, 'a' => 0];
}
private function handleErrorCorrectionLevel($level)
{
switch ($level) {
case 'L':
return ErrorCorrectionLevel::LOW();
return $this->endroid4 ? new ErrorCorrectionLevelLow() : ErrorCorrectionLevel::LOW();
case 'M':
return ErrorCorrectionLevel::MEDIUM();
return $this->endroid4 ? new ErrorCorrectionLevelMedium() : ErrorCorrectionLevel::MEDIUM();
case 'Q':
return ErrorCorrectionLevel::QUARTILE();
return $this->endroid4 ? new ErrorCorrectionLevelQuartile() : ErrorCorrectionLevel::QUARTILE();
case 'H':
return ErrorCorrectionLevel::HIGH();
default:
return ErrorCorrectionLevel::HIGH();
return $this->endroid4 ? new ErrorCorrectionLevelHigh() : ErrorCorrectionLevel::HIGH();
}
}
}
@@ -1,8 +1,8 @@
<?php
namespace RobThree\Auth\Providers\Qr;
use Endroid\QrCode\ErrorCorrectionLevel;
use Endroid\QrCode\QrCode;
use Endroid\QrCode\Logo\Logo;
use Endroid\QrCode\Writer\PngWriter;
class EndroidQrCodeWithLogoProvider extends EndroidQrCodeProvider
{
@@ -20,13 +20,33 @@ class EndroidQrCodeWithLogoProvider extends EndroidQrCodeProvider
$this->logoSize = (array)$size;
}
public function getQRCodeImage($qrtext, $size)
{
if (!$this->endroid4) {
return $this->qrCodeInstance($qrtext, $size)->writeString();
}
$logo = null;
if ($this->logoPath) {
$logo = Logo::create($this->logoPath);
if ($this->logoSize) {
$logo->setResizeToWidth($this->logoSize[0]);
if (isset($this->logoSize[1])) {
$logo->setResizeToHeight($this->logoSize[1]);
}
}
}
$writer = new PngWriter();
return $writer->write($this->qrCodeInstance($qrtext, $size), $logo)->getString();
}
protected function qrCodeInstance($qrtext, $size) {
$qrCode = parent::qrCodeInstance($qrtext, $size);
if ($this->logoPath) {
if (!$this->endroid4 && $this->logoPath) {
$qrCode->setLogoPath($this->logoPath);
if ($this->logoSize) {
$qrCode->setLogoSize($this->logoSize[0], $this->logoSize[1]);
$qrCode->setLogoSize($this->logoSize[0], isset($this->logoSize[1]) ? $this->logoSize[1] : null);
}
}
+24
View File
@@ -0,0 +1,24 @@
<?php
namespace RobThree\Auth\Providers\Qr;
trait HandlesDataUri
{
/**
* @param string $datauri
*
* @return null|array
*/
private function DecodeDataUri($datauri)
{
if (preg_match('/data:(?P<mimetype>[\w\.\-\+\/]+);(?P<encoding>\w+),(?P<data>.*)/', $datauri, $m) === 1) {
return array(
'mimetype' => $m['mimetype'],
'encoding' => $m['encoding'],
'data' => base64_decode($m['data'])
);
}
return null;
}
}
+1 -1
View File
@@ -272,7 +272,7 @@ class TwoFactorAuth
{
return 'otpauth://totp/' . rawurlencode($label)
. '?secret=' . rawurlencode($secret)
. '&issuer=' . rawurlencode($this->issuer)
. '&issuer=' . rawurlencode((string)$this->issuer)
. '&period=' . intval($this->period)
. '&algorithm=' . rawurlencode(strtoupper($this->algorithm))
. '&digits=' . intval($this->digits);
+1
View File
@@ -2,6 +2,7 @@
<phpunit backupGlobals="false"
backupStaticAttributes="false"
colors="true"
convertDeprecationsToExceptions="true"
convertErrorsToExceptions="true"
convertNoticesToExceptions="true"
convertWarningsToExceptions="true"
+21 -17
View File
@@ -5,26 +5,11 @@ namespace Tests\Providers\Qr;
use PHPUnit\Framework\TestCase;
use RobThree\Auth\TwoFactorAuth;
use RobThree\Auth\TwoFactorAuthException;
use RobThree\Auth\Providers\Qr\HandlesDataUri;
class IQRCodeProviderTest extends TestCase
{
/**
* @param string $datauri
*
* @return null|array
*/
private function DecodeDataUri($datauri)
{
if (preg_match('/data:(?P<mimetype>[\w\.\-\/]+);(?P<encoding>\w+),(?P<data>.*)/', $datauri, $m) === 1) {
return array(
'mimetype' => $m['mimetype'],
'encoding' => $m['encoding'],
'data' => base64_decode($m['data'])
);
}
return null;
}
use HandlesDataUri;
/**
* @return void
@@ -40,6 +25,25 @@ class IQRCodeProviderTest extends TestCase
$this->assertEquals('otpauth://totp/Test%26Label?secret=VMR466AB62ZBOKHE&issuer=Test%26Issuer&period=30&algorithm=SHA1&digits=6@200', $data['data']);
}
/**
* @return void
*/
public function testTotpUriIsCorrectNoIssuer()
{
$qr = new TestQrProvider();
/**
* The library specifies the issuer is null by default however in PHP 8.1
* there is a deprecation warning for passing null as a string argument to rawurlencode
*/
$tfa = new TwoFactorAuth(null, 6, 30, 'sha1', $qr);
$data = $this->DecodeDataUri($tfa->getQRCodeImageAsDataUri('Test&Label', 'VMR466AB62ZBOKHE'));
$this->assertEquals('test/test', $data['mimetype']);
$this->assertEquals('base64', $data['encoding']);
$this->assertEquals('otpauth://totp/Test%26Label?secret=VMR466AB62ZBOKHE&issuer=&period=30&algorithm=SHA1&digits=6@200', $data['data']);
}
/**
* @return void
*/
+61
View File
@@ -0,0 +1,61 @@
<?php
namespace TestsDependency;
use BaconQrCode\Renderer\Image\ImagickImageBackEnd;
use PHPUnit\Framework\TestCase;
use RobThree\Auth\Providers\Qr\BaconQrCodeProvider;
use RobThree\Auth\TwoFactorAuth;
use RobThree\Auth\Providers\Qr\HandlesDataUri;
class BaconQRCodeTest extends TestCase
{
use HandlesDataUri;
public function testDependency()
{
// php < 7.1 will install an older Bacon QR Code
if (! class_exists(ImagickImageBackEnd::class)) {
$this->expectException(\RuntimeException::class);
$qr = new BaconQrCodeProvider(1, '#000', '#FFF', 'svg');
} else {
$qr = new BaconQrCodeProvider(1, '#000', '#FFF', 'svg');
$tfa = new TwoFactorAuth('Test&Issuer', 6, 30, 'sha1', $qr);
$data = $this->DecodeDataUri($tfa->getQRCodeImageAsDataUri('Test&Label', 'VMR466AB62ZBOKHE'));
$this->assertEquals('image/svg+xml', $data['mimetype']);
}
}
public function testBadTextColour()
{
$this->expectException(\RuntimeException::class);
new BaconQrCodeProvider(1, 'not-a-colour', '#FFF');
}
public function testBadBackgroundColour()
{
$this->expectException(\RuntimeException::class);
new BaconQrCodeProvider(1, '#000', 'not-a-colour');
}
public function testBadTextColourHexRef()
{
$this->expectException(\RuntimeException::class);
new BaconQrCodeProvider(1, '#AAAA', '#FFF');
}
public function testBadBackgroundColourHexRef()
{
$this->expectException(\RuntimeException::class);
new BaconQrCodeProvider(1, '#000', '#AAAA');
}
}
+24
View File
@@ -0,0 +1,24 @@
<?php
namespace TestsDependency;
use PHPUnit\Framework\TestCase;
use RobThree\Auth\TwoFactorAuth;
use RobThree\Auth\Providers\Qr\EndroidQrCodeProvider;
use RobThree\Auth\Providers\Qr\HandlesDataUri;
class EndroidQRCodeTest extends TestCase
{
use HandlesDataUri;
public function testDependency()
{
$qr = new EndroidQrCodeProvider();
$tfa = new TwoFactorAuth('Test&Issuer', 6, 30, 'sha1', $qr);
$data = $this->DecodeDataUri($tfa->getQRCodeImageAsDataUri('Test&Label', 'VMR466AB62ZBOKHE'));
$this->assertEquals('image/png', $data['mimetype']);
$this->assertEquals('base64', $data['encoding']);
$this->assertNotEmpty($data['data']);
}
}