More tidying up, added category to invoices, invoice delete now deletes invoice, pyaments, history and items associated with invoice. Exclude Cancelled invoice under dashboard income recieveables

This commit is contained in:
root
2019-05-17 15:33:01 -04:00
parent 9683d9f9f0
commit 9634d7a1e4
29 changed files with 1195 additions and 45 deletions

103
vendor/otphp-10.0/src/Factory.php vendored Normal file
View File

@@ -0,0 +1,103 @@
<?php
declare(strict_types=1);
/*
* The MIT License (MIT)
*
* Copyright (c) 2014-2019 Spomky-Labs
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
namespace OTPHP;
use Assert\Assertion;
use InvalidArgumentException;
use function Safe\parse_url;
use function Safe\sprintf;
use Throwable;
/**
* This class is used to load OTP object from a provisioning Uri.
*/
final class Factory implements FactoryInterface
{
public static function loadFromProvisioningUri(string $uri): OTPInterface
{
try {
$parsed_url = parse_url($uri);
} catch (Throwable $throwable) {
throw new InvalidArgumentException('Not a valid OTP provisioning URI', $throwable->getCode(), $throwable);
}
Assertion::isArray($parsed_url, 'Not a valid OTP provisioning URI');
self::checkData($parsed_url);
$otp = self::createOTP($parsed_url);
self::populateOTP($otp, $parsed_url);
return $otp;
}
private static function populateParameters(OTPInterface &$otp, array $data): void
{
foreach ($data['query'] as $key => $value) {
$otp->setParameter($key, $value);
}
}
private static function populateOTP(OTPInterface &$otp, array $data): void
{
self::populateParameters($otp, $data);
$result = explode(':', rawurldecode(mb_substr($data['path'], 1)));
if (2 > \count($result)) {
$otp->setIssuerIncludedAsParameter(false);
return;
}
if (null !== $otp->getIssuer()) {
Assertion::eq($result[0], $otp->getIssuer(), 'Invalid OTP: invalid issuer in parameter');
$otp->setIssuerIncludedAsParameter(true);
}
$otp->setIssuer($result[0]);
}
private static function checkData(array &$data): void
{
foreach (['scheme', 'host', 'path', 'query'] as $key) {
Assertion::keyExists($data, $key, 'Not a valid OTP provisioning URI');
}
Assertion::eq('otpauth', $data['scheme'], 'Not a valid OTP provisioning URI');
parse_str($data['query'], $data['query']);
Assertion::keyExists($data['query'], 'secret', 'Not a valid OTP provisioning URI');
}
private static function createOTP(array $parsed_url): OTPInterface
{
switch ($parsed_url['host']) {
case 'totp':
$totp = TOTP::create($parsed_url['query']['secret']);
$totp->setLabel(self::getLabel($parsed_url['path']));
return $totp;
case 'hotp':
$hotp = HOTP::create($parsed_url['query']['secret']);
$hotp->setLabel(self::getLabel($parsed_url['path']));
return $hotp;
default:
throw new InvalidArgumentException(sprintf('Unsupported "%s" OTP type', $parsed_url['host']));
}
}
private static function getLabel(string $data): string
{
$result = explode(':', rawurldecode(mb_substr($data, 1)));
return 2 === \count($result) ? $result[1] : $result[0];
}
}

View File

@@ -0,0 +1,23 @@
<?php
declare(strict_types=1);
/*
* The MIT License (MIT)
*
* Copyright (c) 2014-2019 Spomky-Labs
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
namespace OTPHP;
interface FactoryInterface
{
/**
* This method is the unique public method of the class.
* It can load a provisioning Uri and convert it into an OTP object.
*/
public static function loadFromProvisioningUri(string $uri): OTPInterface;
}

100
vendor/otphp-10.0/src/HOTP.php vendored Normal file
View File

@@ -0,0 +1,100 @@
<?php
declare(strict_types=1);
/*
* The MIT License (MIT)
*
* Copyright (c) 2014-2019 Spomky-Labs
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
namespace OTPHP;
use Assert\Assertion;
final class HOTP extends OTP implements HOTPInterface
{
protected function __construct(?string $secret, int $counter, string $digest, int $digits)
{
parent::__construct($secret, $digest, $digits);
$this->setCounter($counter);
}
public static function create(?string $secret = null, int $counter = 0, string $digest = 'sha1', int $digits = 6): HOTPInterface
{
return new self($secret, $counter, $digest, $digits);
}
protected function setCounter(int $counter): void
{
$this->setParameter('counter', $counter);
}
public function getCounter(): int
{
return $this->getParameter('counter');
}
private function updateCounter(int $counter): void
{
$this->setCounter($counter);
}
public function getProvisioningUri(): string
{
return $this->generateURI('hotp', ['counter' => $this->getCounter()]);
}
/**
* If the counter is not provided, the OTP is verified at the actual counter.
*/
public function verify(string $otp, ?int $counter = null, ?int $window = null): bool
{
Assertion::greaterOrEqualThan($counter, 0, 'The counter must be at least 0.');
if (null === $counter) {
$counter = $this->getCounter();
} elseif ($counter < $this->getCounter()) {
return false;
}
return $this->verifyOtpWithWindow($otp, $counter, $window);
}
private function getWindow(?int $window): int
{
return abs($window ?? 0);
}
private function verifyOtpWithWindow(string $otp, int $counter, ?int $window): bool
{
$window = $this->getWindow($window);
for ($i = $counter; $i <= $counter + $window; ++$i) {
if ($this->compareOTP($this->at($i), $otp)) {
$this->updateCounter($i + 1);
return true;
}
}
return false;
}
protected function getParameterMap(): array
{
$v = array_merge(
parent::getParameterMap(),
['counter' => function ($value) {
Assertion::greaterOrEqualThan((int) $value, 0, 'Counter must be at least 0.');
return (int) $value;
}]
);
return $v;
}
}

29
vendor/otphp-10.0/src/HOTPInterface.php vendored Normal file
View File

@@ -0,0 +1,29 @@
<?php
declare(strict_types=1);
/*
* The MIT License (MIT)
*
* Copyright (c) 2014-2019 Spomky-Labs
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
namespace OTPHP;
interface HOTPInterface extends OTPInterface
{
/**
* The initial counter (a positive integer).
*/
public function getCounter(): int;
/**
* Create a new TOTP object.
*
* If the secret is null, a random 64 bytes secret will be generated.
*/
public static function create(?string $secret = null, int $counter = 0, string $digest = 'sha1', int $digits = 6): self;
}

111
vendor/otphp-10.0/src/OTP.php vendored Normal file
View File

@@ -0,0 +1,111 @@
<?php
declare(strict_types=1);
/*
* The MIT License (MIT)
*
* Copyright (c) 2014-2019 Spomky-Labs
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
namespace OTPHP;
use Assert\Assertion;
use ParagonIE\ConstantTime\Base32;
use RuntimeException;
use function Safe\ksort;
use function Safe\sprintf;
abstract class OTP implements OTPInterface
{
use ParameterTrait;
protected function __construct(?string $secret, string $digest, int $digits)
{
$this->setSecret($secret);
$this->setDigest($digest);
$this->setDigits($digits);
}
public function getQrCodeUri(string $uri, string $placeholder): string
{
$provisioning_uri = urlencode($this->getProvisioningUri());
return str_replace($placeholder, $provisioning_uri, $uri);
}
/**
* The OTP at the specified input.
*/
protected function generateOTP(int $input): string
{
$hash = hash_hmac($this->getDigest(), $this->intToByteString($input), $this->getDecodedSecret());
$hmac = [];
foreach (str_split($hash, 2) as $hex) {
$hmac[] = hexdec($hex);
}
$offset = $hmac[\count($hmac) - 1] & 0xF;
$code = ($hmac[$offset + 0] & 0x7F) << 24 | ($hmac[$offset + 1] & 0xFF) << 16 | ($hmac[$offset + 2] & 0xFF) << 8 | ($hmac[$offset + 3] & 0xFF);
$otp = $code % 10 ** $this->getDigits();
return str_pad((string) $otp, $this->getDigits(), '0', STR_PAD_LEFT);
}
public function at(int $timestamp): string
{
return $this->generateOTP($timestamp);
}
protected function filterOptions(array &$options): void
{
foreach (['algorithm' => 'sha1', 'period' => 30, 'digits' => 6] as $key => $default) {
if (isset($options[$key]) && $default === $options[$key]) {
unset($options[$key]);
}
}
ksort($options);
}
protected function generateURI(string $type, array $options): string
{
$label = $this->getLabel();
Assertion::string($label, 'The label is not set.');
Assertion::false($this->hasColon($label), 'Label must not contain a colon.');
$options = array_merge($options, $this->getParameters());
$this->filterOptions($options);
$params = str_replace(['+', '%7E'], ['%20', '~'], http_build_query($options));
return sprintf('otpauth://%s/%s?%s', $type, rawurlencode((null !== $this->getIssuer() ? $this->getIssuer().':' : '').$label), $params);
}
private function getDecodedSecret(): string
{
try {
$secret = Base32::decodeUpper($this->getSecret());
} catch (\Exception $e) {
throw new RuntimeException('Unable to decode the secret. Is it correctly base32 encoded?');
}
return $secret;
}
private function intToByteString(int $int): string
{
$result = [];
while (0 !== $int) {
$result[] = \chr($int & 0xFF);
$int >>= 8;
}
return str_pad(implode(array_reverse($result)), 8, "\000", STR_PAD_LEFT);
}
protected function compareOTP(string $safe, string $user): bool
{
return hash_equals($safe, $user);
}
}

94
vendor/otphp-10.0/src/OTPInterface.php vendored Normal file
View File

@@ -0,0 +1,94 @@
<?php
declare(strict_types=1);
/*
* The MIT License (MIT)
*
* Copyright (c) 2014-2019 Spomky-Labs
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
namespace OTPHP;
interface OTPInterface
{
/**
* @return string Return the OTP at the specified timestamp
*/
public function at(int $timestamp): string;
/**
* Verify that the OTP is valid with the specified input.
* If no input is provided, the input is set to a default value or false is returned.
*/
public function verify(string $otp, ?int $input = null, ?int $window = null): bool;
/**
* @return string The secret of the OTP
*/
public function getSecret(): string;
/**
* @param string $label The label of the OTP
*/
public function setLabel(string $label): void;
/**
* @return string|null The label of the OTP
*/
public function getLabel(): ?string;
/**
* @return string|null The issuer
*/
public function getIssuer(): ?string;
public function setIssuer(string $issuer): void;
/**
* @return bool If true, the issuer will be added as a parameter in the provisioning URI
*/
public function isIssuerIncludedAsParameter(): bool;
public function setIssuerIncludedAsParameter(bool $issuer_included_as_parameter): void;
/**
* @return int Number of digits in the OTP
*/
public function getDigits(): int;
/**
* @return string Digest algorithm used to calculate the OTP. Possible values are 'md5', 'sha1', 'sha256' and 'sha512'
*/
public function getDigest(): string;
/**
* @return mixed|null
*/
public function getParameter(string $parameter);
public function hasParameter(string $parameter): bool;
public function getParameters(): array;
/**
* @param mixed|null $value
*/
public function setParameter(string $parameter, $value): void;
/**
* Get the provisioning URI.
*/
public function getProvisioningUri(): string;
/**
* Get the provisioning URI.
*
* @param string $uri The Uri of the QRCode generator with all parameters. This Uri MUST contain a placeholder that will be replaced by the method.
* @param string $placeholder the placeholder to be replaced in the QR Code generator URI
*/
public function getQrCodeUri(string $uri, string $placeholder): string;
}

190
vendor/otphp-10.0/src/ParameterTrait.php vendored Normal file
View File

@@ -0,0 +1,190 @@
<?php
declare(strict_types=1);
/*
* The MIT License (MIT)
*
* Copyright (c) 2014-2019 Spomky-Labs
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
namespace OTPHP;
use Assert\Assertion;
use InvalidArgumentException;
use ParagonIE\ConstantTime\Base32;
use function Safe\sprintf;
trait ParameterTrait
{
/**
* @var array
*/
private $parameters = [];
/**
* @var string|null
*/
private $issuer;
/**
* @var string|null
*/
private $label;
/**
* @var bool
*/
private $issuer_included_as_parameter = true;
public function getParameters(): array
{
$parameters = $this->parameters;
if (null !== $this->getIssuer() && true === $this->isIssuerIncludedAsParameter()) {
$parameters['issuer'] = $this->getIssuer();
}
return $parameters;
}
public function getSecret(): string
{
return $this->getParameter('secret');
}
private function setSecret(?string $secret): void
{
$this->setParameter('secret', $secret);
}
public function getLabel(): ?string
{
return $this->label;
}
public function setLabel(string $label): void
{
$this->setParameter('label', $label);
}
public function getIssuer(): ?string
{
return $this->issuer;
}
public function setIssuer(string $issuer): void
{
$this->setParameter('issuer', $issuer);
}
public function isIssuerIncludedAsParameter(): bool
{
return $this->issuer_included_as_parameter;
}
public function setIssuerIncludedAsParameter(bool $issuer_included_as_parameter): void
{
$this->issuer_included_as_parameter = $issuer_included_as_parameter;
}
public function getDigits(): int
{
return $this->getParameter('digits');
}
private function setDigits(int $digits): void
{
$this->setParameter('digits', $digits);
}
public function getDigest(): string
{
return $this->getParameter('algorithm');
}
private function setDigest(string $digest): void
{
$this->setParameter('algorithm', $digest);
}
public function hasParameter(string $parameter): bool
{
return \array_key_exists($parameter, $this->parameters);
}
public function getParameter(string $parameter)
{
if ($this->hasParameter($parameter)) {
return $this->getParameters()[$parameter];
}
throw new InvalidArgumentException(sprintf('Parameter "%s" does not exist', $parameter));
}
public function setParameter(string $parameter, $value): void
{
$map = $this->getParameterMap();
if (true === \array_key_exists($parameter, $map)) {
$callback = $map[$parameter];
$value = $callback($value);
}
if (property_exists($this, $parameter)) {
$this->$parameter = $value;
} else {
$this->parameters[$parameter] = $value;
}
}
protected function getParameterMap(): array
{
return [
'label' => function ($value) {
Assertion::false($this->hasColon($value), 'Label must not contain a colon.');
return $value;
},
'secret' => function ($value) {
if (null === $value) {
$value = Base32::encodeUpper(random_bytes(64));
}
$value = trim(mb_strtoupper($value), '=');
return $value;
},
'algorithm' => function ($value) {
$value = mb_strtolower($value);
Assertion::inArray($value, hash_algos(), sprintf('The "%s" digest is not supported.', $value));
return $value;
},
'digits' => function ($value) {
Assertion::greaterThan($value, 0, 'Digits must be at least 1.');
return (int) $value;
},
'issuer' => function ($value) {
Assertion::false($this->hasColon($value), 'Issuer must not contain a colon.');
return $value;
},
];
}
private function hasColon(string $value): bool
{
$colons = [':', '%3A', '%3a'];
foreach ($colons as $colon) {
if (false !== mb_strpos($value, $colon)) {
return true;
}
}
return false;
}
}

153
vendor/otphp-10.0/src/TOTP.php vendored Normal file
View File

@@ -0,0 +1,153 @@
<?php
declare(strict_types=1);
/*
* The MIT License (MIT)
*
* Copyright (c) 2014-2019 Spomky-Labs
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
namespace OTPHP;
use Assert\Assertion;
use function Safe\ksort;
final class TOTP extends OTP implements TOTPInterface
{
protected function __construct(?string $secret, int $period, string $digest, int $digits, int $epoch = 0)
{
parent::__construct($secret, $digest, $digits);
$this->setPeriod($period);
$this->setEpoch($epoch);
}
public static function create(?string $secret = null, int $period = 30, string $digest = 'sha1', int $digits = 6, int $epoch = 0): TOTPInterface
{
return new self($secret, $period, $digest, $digits, $epoch);
}
protected function setPeriod(int $period): void
{
$this->setParameter('period', $period);
}
public function getPeriod(): int
{
return $this->getParameter('period');
}
private function setEpoch(int $epoch): void
{
$this->setParameter('epoch', $epoch);
}
public function getEpoch(): int
{
return $this->getParameter('epoch');
}
public function at(int $timestamp): string
{
return $this->generateOTP($this->timecode($timestamp));
}
public function now(): string
{
return $this->at(time());
}
/**
* If no timestamp is provided, the OTP is verified at the actual timestamp.
*/
public function verify(string $otp, ?int $timestamp = null, ?int $window = null): bool
{
$timestamp = $this->getTimestamp($timestamp);
if (null === $window) {
return $this->compareOTP($this->at($timestamp), $otp);
}
return $this->verifyOtpWithWindow($otp, $timestamp, $window);
}
private function verifyOtpWithWindow(string $otp, int $timestamp, int $window): bool
{
$window = abs($window);
for ($i = 0; $i <= $window; ++$i) {
$next = $i * $this->getPeriod() + $timestamp;
$previous = -$i * $this->getPeriod() + $timestamp;
$valid = $this->compareOTP($this->at($next), $otp) ||
$this->compareOTP($this->at($previous), $otp);
if ($valid) {
return true;
}
}
return false;
}
private function getTimestamp(?int $timestamp): int
{
$timestamp = $timestamp ?? time();
Assertion::greaterOrEqualThan($timestamp, 0, 'Timestamp must be at least 0.');
return $timestamp;
}
public function getProvisioningUri(): string
{
$params = [];
if (30 !== $this->getPeriod()) {
$params['period'] = $this->getPeriod();
}
if (0 !== $this->getEpoch()) {
$params['epoch'] = $this->getEpoch();
}
return $this->generateURI('totp', $params);
}
private function timecode(int $timestamp): int
{
return (int) floor(($timestamp - $this->getEpoch()) / $this->getPeriod());
}
protected function getParameterMap(): array
{
$v = array_merge(
parent::getParameterMap(),
[
'period' => function ($value) {
Assertion::greaterThan((int) $value, 0, 'Period must be at least 1.');
return (int) $value;
},
'epoch' => function ($value) {
Assertion::greaterOrEqualThan((int) $value, 0, 'Epoch must be greater than or equal to 0.');
return (int) $value;
},
]
);
return $v;
}
protected function filterOptions(array &$options): void
{
parent::filterOptions($options);
if (isset($options['epoch']) && 0 === $options['epoch']) {
unset($options['epoch']);
}
ksort($options);
}
}

36
vendor/otphp-10.0/src/TOTPInterface.php vendored Normal file
View File

@@ -0,0 +1,36 @@
<?php
declare(strict_types=1);
/*
* The MIT License (MIT)
*
* Copyright (c) 2014-2019 Spomky-Labs
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
namespace OTPHP;
interface TOTPInterface extends OTPInterface
{
/**
* Create a new TOTP object.
*
* If the secret is null, a random 64 bytes secret will be generated.
*/
public static function create(?string $secret = null, int $period = 30, string $digest = 'sha1', int $digits = 6): self;
/**
* Return the TOTP at the current time.
*/
public function now(): string;
/**
* Get the period of time for OTP generation (a non-null positive integer, in second).
*/
public function getPeriod(): int;
public function getEpoch(): int;
}