Passed
Push — master ( 9536d0...0dc3be )
by Jan
12:11
created

GroupHeaderHelper::__construct()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 10
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 2
eloc 5
nc 2
nop 2
dl 0
loc 10
rs 10
c 1
b 0
f 0
1
<?php
2
/*
3
 * Copyright (C) 2020  Jan Böhmer
4
 *
5
 * This program is free software: you can redistribute it and/or modify
6
 * it under the terms of the GNU Affero General Public License as published
7
 * by the Free Software Foundation, either version 3 of the License, or
8
 * (at your option) any later version.
9
 *
10
 * This program is distributed in the hope that it will be useful,
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 * GNU Affero General Public License for more details.
14
 *
15
 * You should have received a copy of the GNU Affero General Public License
16
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
17
 */
18
19
namespace App\Services\SEPAExport;
20
21
use App\Entity\User;
22
use Digitick\Sepa\GroupHeader;
23
use Symfony\Component\Security\Core\Security;
24
25
final class GroupHeaderHelper
26
{
27
    //A prefix that should be used for message IDs
28
    private const MSG_ID_PREFIX = "stura";
29
30
    //The maximum message id length
31
    private const MSG_ID_MAX_LENGTH = 27;
32
33
    private $current_user;
34
    private $app_version;
35
36
    public function __construct(Security $security, string $app_version)
37
    {
38
        //Ensure the entropy of random variables is long enough (we assume the worst case of a 11 chars BIC)
39
        $random_length = self::MSG_ID_MAX_LENGTH - strlen(self::MSG_ID_PREFIX) - 11;
40
        if ($random_length < 8) {
41
            throw new \RuntimeException('MSG_ID_PREFIX is too long! Message ID entropy would be too low!');
42
        }
43
44
        $this->current_user = $security->getUser();
45
        $this->app_version = $app_version;
46
    }
47
48
    /**
49
     * Generates a new random Message ID for the given initiating BIC
50
     * @param  string  $initiating_bic
51
     * @return string
52
     */
53
    public function getMessageID(string $initiating_bic): string
54
    {
55
        if (!$this->checkIsValidBIC($initiating_bic)) {
56
            throw new \InvalidArgumentException('The given initiating_bic is not a valid BIC!');
57
        }
58
59
        $random_length = self::MSG_ID_MAX_LENGTH - strlen(self::MSG_ID_PREFIX) - strlen($initiating_bic);
60
        $random = $this->getRandomString($random_length);
61
62
        return $initiating_bic . self::MSG_ID_PREFIX . $random;
63
    }
64
65
    /**
66
     * Returns the name of the initiating party used for SEPA Exports
67
     * @return string
68
     */
69
    public function getInitiatingPartyName(): string
70
    {
71
        $username = "NOT LOGGED IN";
72
        if ($this->current_user instanceof User) {
73
            $username = $this->current_user->getFullName();
74
        }
75
76
        return sprintf("%s via StuRa-Zahlungssystem v%s", $username, $this->app_version);
77
    }
78
79
    /**
80
     * Returns a group header with random message id for use with a new export.
81
     * @param  string  $initiating_bic
82
     * @return GroupHeader
83
     */
84
    public function getGroupHeader(string $initiating_bic): GroupHeader
85
    {
86
        return new GroupHeader(
87
            $this->getMessageID($initiating_bic),
88
            $this->getInitiatingPartyName()
89
        );
90
    }
91
92
    /**
93
     * Check if the given BIC is valid. Currently we just check the length of the BIC.
94
     * @param  string  $bic
95
     * @return bool
96
     */
97
    private function checkIsValidBIC(string $bic): bool
98
    {
99
        $len = strlen($bic);
100
        return $len === 8 || $len === 11;
101
    }
102
103
    private function getRandomString(int $length): string
104
    {
105
        if ($length > 32) {
106
            throw new \InvalidArgumentException('This function can not generate random strings longer than 32 characters!');
107
        }
108
        $bytes = random_bytes(40);
109
        return substr(md5($bytes), 0, $length);
110
    }
111
}