Passed
Push — master ( 9cc9e4...79f76b )
by frey
04:31
created

GetFederationTokenV3::getCustomPolicy()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 1
Bugs 0 Features 1
Metric Value
cc 1
eloc 3
c 1
b 0
f 1
nc 1
nop 2
dl 0
loc 6
ccs 0
cts 5
cp 0
crap 2
rs 10
1
<?php
2
3
namespace Freyo\Flysystem\QcloudCOSv5\Plugins;
4
5
use Closure;
6
use League\Flysystem\Plugin\AbstractPlugin;
7
8
/**
9
 * Class GetFederationToken.
10
 */
11
class GetFederationTokenV3 extends AbstractPlugin
12
{
13
    /**
14
     * Get the method name.
15
     *
16
     * @return string
17
     */
18
    public function getMethod()
19
    {
20
        return 'getFederationTokenV3';
21
    }
22
23
    /**
24
     * @see https://cloud.tencent.com/document/product/598/33416
25
     *
26
     * @param string $path
27
     * @param int $seconds
28
     * @param Closure $customPolicy
29
     * @param string $name
30
     *
31
     * @return bool|array
32
     */
33
    public function handle($path = '*', $seconds = 7200, Closure $customPolicy = null, $name = 'cos')
34
    {
35
        $policy = !is_null($customPolicy)
36
            ? $this->getCustomPolicy($customPolicy, $path)
37
            : $this->getPolicy($path);
38
39
        $params = [
40
            'DurationSeconds' => $seconds,
41
            'Name' => $name,
42
            'Policy' => urlencode($policy),
43
        ];
44
45
        return $this->request($params, 'GetFederationToken');
46
    }
47
48
    /**
49
     * @param Closure $callable
50
     * @param $path
51
     *
52
     * @return string
53
     */
54
    protected function getCustomPolicy(Closure $callable, $path)
55
    {
56
        $policy = call_user_func($callable, $path, $this->getConfig());
57
58
        return \GuzzleHttp\json_encode(
59
            $policy, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE
60
        );
61
    }
62
63
    /**
64
     * @see https://cloud.tencent.com/document/product/436/31923
65
     *
66
     * @param $path
67
     *
68
     * @return string
69
     */
70
    protected function getPolicy($path)
71
    {
72
        $appId = $this->getCredentials()['appId'];
73
74
        $region = $this->getConfig()->get('region');
75
        $bucket = $this->getConfig()->get('bucket');
76
77
        $policy = [
78
            'version' => '2.0',
79
            'statement' => [
80
                'action' => [
81
                    // 简单上传
82
                    'name/cos:PutObject',
83
                    'name/cos:PostObject',
84
                    // 分片上传
85
                    'name/cos:InitiateMultipartUpload',
86
                    'name/cos:ListParts',
87
                    'name/cos:UploadPart',
88
                    'name/cos:CompleteMultipartUpload',
89
                    'name/cos:AbortMultipartUpload',
90
                ],
91
                'effect' => 'allow',
92
                'resource' => [
93
                    "qcs::cos:$region:uid/$appId:prefix//$appId/$bucket/$path",
94
                ],
95
            ],
96
        ];
97
98
        return \GuzzleHttp\json_encode(
99
            $policy, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE
100
        );
101
    }
102
103
    /**
104
     * @return \League\Flysystem\Config
105
     */
106
    protected function getConfig()
107
    {
108
        return $this->filesystem->getConfig();
109
    }
110
111
    /**
112
     * @return array
113
     */
114
    protected function getCredentials()
115
    {
116
        return $this->getConfig()->get('credentials');
117
    }
118
119
    /**
120
     * @param array $args
121
     * @param $action
122
     * @param null $timestamp
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $timestamp is correct as it would always require null to be passed?
Loading history...
123
     *
124
     * @return bool|array
125
     */
126
    protected function request(array $args, $action, $timestamp = null)
127
    {
128
        $client = $this->getHttpClient();
129
130
        $response = $client->post('/', [
131
            'headers' => [
132
                'X-TC-Action' => $action,
133
                'X-TC-Region' => $this->getConfig()->get('region'),
134
                'X-TC-Timestamp' => $timestamp = $timestamp ?: time(),
0 ignored issues
show
introduced by
$timestamp is of type null, thus it always evaluated to false.
Loading history...
135
                'X-TC-Version' => '2018-08-13',
136
                'Authorization' => $this->getAuthorization($args, $timestamp),
137
            ],
138
            'json' => $args,
139
        ]);
140
141
        $contents = $response->getBody()->getContents();
142
143
        return $this->normalize($contents);
144
    }
145
146
    /**
147
     * @return \GuzzleHttp\Client
148
     */
149
    protected function getHttpClient()
150
    {
151
        return new \GuzzleHttp\Client([
152
            'base_uri' => 'https://sts.tencentcloudapi.com',
153
        ]);
154
    }
155
156
    /**
157
     * @param string $contents
158
     *
159
     * @return bool|array
160
     */
161
    protected function normalize($contents)
162
    {
163
        $data = json_decode($contents, true);
164
165
        if (json_last_error() !== JSON_ERROR_NONE || !isset($data['Response'])) {
166
            return false;
167
        }
168
169
        return $data['Response'];
170
    }
171
172
    /**
173
     * @param $args
174
     * @param $timestamp
175
     *
176
     * @return string
177
     */
178
    protected function getAuthorization($args, $timestamp)
179
    {
180
        return sprintf(
181
            '%s Credential=%s/%s, SignedHeaders=%s, Signature=%s',
182
            'TC3-HMAC-SHA256',
183
            $this->getCredentials()['secretId'],
184
            date('Y-m-d', $timestamp) . '/sts/tc3_request',
185
            'content-type;host',
186
            hash_hmac(
187
                'SHA256',
188
                $this->getSignatureString($args, $timestamp),
189
                $this->getRequestKey($timestamp)
190
            )
191
        );
192
    }
193
194
    /**
195
     * @param $timestamp
196
     *
197
     * @return string
198
     */
199
    protected function getRequestKey($timestamp)
200
    {
201
        return hash_hmac('SHA256', 'tc3_request',
202
            hash_hmac('SHA256', 'sts',
203
                hash_hmac('SHA256', date('Y-m-d', $timestamp),
204
                    'TC3' . $this->getCredentials()['secretKey'], true
205
                ), true
206
            ), true
207
        );
208
    }
209
210
    /**
211
     * @param $args
212
     *
213
     * @return string
214
     */
215
    protected function getCanonicalRequest($args)
216
    {
217
        return implode("\n", [
218
            'POST',
219
            '/',
220
            '',
221
            'content-type:application/json',
222
            'host:sts.tencentcloudapi.com',
223
            '',
224
            'content-type;host',
225
            hash("SHA256", \GuzzleHttp\json_encode(
226
                $args, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE
227
            ))
228
        ]);
229
    }
230
231
    /**
232
     * @param $args
233
     * @param $timestamp
234
     *
235
     * @return string
236
     */
237
    protected function getSignatureString($args, $timestamp)
238
    {
239
        return implode("\n", [
240
            'TC3-HMAC-SHA256',
241
            $timestamp,
242
            date('Y-m-d', $timestamp) . '/sts/tc3_request',
243
            hash('SHA256', $this->getCanonicalRequest($args)),
244
        ]);
245
    }
246
}
247