Skip to content

Commit 87ee230

Browse files
committed
fixed issue with renewing licenses
1 parent d870346 commit 87ee230

File tree

6 files changed

+100
-43
lines changed

6 files changed

+100
-43
lines changed

app/Http/Controllers/NetifyLicenseController.php

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,19 @@ public function community(NetifydLicenseRepository $licenseProvider): JsonRespon
2020
private function run(NetifydLicenseRepository $licenseProvider, NetifydLicenseType $licenseType): JsonResponse
2121
{
2222
// If license is in cache, return it.
23-
if (Cache::has($licenseType->cacheLabel())) {
24-
Log::debug('Requested netifyd license found in cache, returning it.');
25-
26-
return response()->json(Cache::get($licenseType->cacheLabel()));
23+
$license = Cache::get($licenseType->cacheLabel());
24+
if ($license != null) {
25+
Log::debug('Requested netifyd license found in cache.');
26+
$expiration = Carbon::createFromTimestampUTC($license['expire_at']['unix'])->startOfDay()->toImmutable();
27+
// License is still valid, return it.
28+
if ($expiration > now()->utc()->startOfDay()) {
29+
return response()->json($license);
30+
}
31+
Log::warning('Found license expired in cache, pruning.');
32+
Cache::forget($licenseType->cacheLabel());
2733
}
2834

29-
Log::debug('Requested netifyd license not found in cache, checking remote server.');
35+
Log::debug('Checking remote server for license.');
3036
// Check if the community license is on the remote server.
3137
try {
3238
$licenses = $licenseProvider->listLicenses();
@@ -46,16 +52,18 @@ private function run(NetifydLicenseRepository $licenseProvider, NetifydLicenseTy
4652
// Got license, checking if everything is in place.
4753
Log::debug('Netifyd license recovered from remote server, checking if it can be renewed.');
4854
$expiration = Carbon::createFromTimestampUTC($license['expire_at']['unix'])->startOfDay()->toImmutable();
49-
$creation = Carbon::createFromTimestampUTC($license['created_at']['unix'])->startOfDay()->toImmutable();
50-
$diff = $creation->diff($expiration)->cascade()->totalDays;
51-
$renewalThreshold = $creation->addDays(ceil($diff / 2));
55+
$renewalThreshold = $expiration->subDays(floor($licenseType->durationDays() / 2));
5256
$now = now()->utc()->startOfDay();
5357
if ($renewalThreshold <= $now) {
5458
Log::debug('Netifyd license can be renewed, renewing it.');
5559
try {
5660
$license = $licenseProvider->renewLicense($licenseType, $license['serial']);
5761
} catch (Exception $e) {
58-
return response()->json(['message' => $e->getMessage()], 500);
62+
if ($expiration <= $now) {
63+
return response()->json(['message' => 'License has expired and could not be renewed: '.$e->getPrevious()?->getMessage()], 500);
64+
} else {
65+
Log::warning('License could not be renewed, but is still valid: '.$e->getPrevious()?->getMessage());
66+
}
5967
}
6068
}
6169
Cache::put($licenseType->cacheLabel(), $license, now()->addHour());

app/Http/Middleware/CommunityLicenceCheck.php

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,8 @@ public function handle(Request $request, Closure $next): Response
2020
{
2121
$systemId = $request->headers->get('php-auth-user');
2222
$secret = $request->headers->get('php-auth-pw');
23+
abort_unless($this->licenceVerification->communityCheck($systemId, $secret), 401, 'Unauthorized.');
2324

24-
if ($this->licenceVerification->communityCheck($systemId, $secret)) {
25-
return $next($request);
26-
}
27-
abort(401);
25+
return $next($request);
2826
}
2927
}

app/Http/Middleware/EnterpriseLicenceCheck.php

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,8 @@ public function handle(Request $request, Closure $next): Response
2020
{
2121
$systemId = $request->headers->get('php-auth-user');
2222
$secret = $request->headers->get('php-auth-pw');
23+
abort_unless($this->licenceVerification->enterpriseCheck($systemId, $secret), 401, 'Unauthorized.');
2324

24-
if ($this->licenceVerification->enterpriseCheck($systemId, $secret)) {
25-
return $next($request);
26-
}
27-
abort(401);
25+
return $next($request);
2826
}
2927
}

app/Logic/NetifydLicenseRepository.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ public function renewLicense(NetifydLicenseType $licenseType, string $serial): a
5858
try {
5959
return Http::withHeader('x-api-key', config('netifyd.api-key'))
6060
->post(config('netifyd.endpoint').'/api/v2/integrator/licenses/'.$serial.'/renew', [
61-
'duration_days' => $licenseType->durationDays(),
61+
'expire_at' => now()->utc()->startOfDay()->addDays($licenseType->durationDays())->subDay()->toDateString(),
6262
])->throw()
6363
->json('data');
6464

tests/Feature/Http/Controllers/NetifyLicenceControllerTest.php

Lines changed: 77 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,16 @@
2222
]);
2323

2424
it('can access free license without credentials', function () {
25-
Cache::expects('has')->with(NetifydLicenseType::COMMUNITY->cacheLabel())->andReturnTrue();
26-
Cache::expects('get')->with(NetifydLicenseType::COMMUNITY->cacheLabel())->andReturn(['license_key' => 'cache']);
25+
$fakeLicense = [
26+
'issued_to' => NetifydLicenseType::COMMUNITY->label(),
27+
'expire_at' => [
28+
'unix' => now()->addDays(2)->unix(),
29+
],
30+
];
31+
Cache::expects('get')->with(NetifydLicenseType::COMMUNITY->cacheLabel())->andReturn($fakeLicense);
2732
get('/api/netifyd/license')
2833
->assertOk()
29-
->assertJson(['license_key' => 'cache']);
34+
->assertJson($fakeLicense);
3035
});
3136
});
3237

@@ -41,25 +46,60 @@
4146
});
4247

4348
it('can access enterprise license with credentials', function () {
44-
Cache::expects('has')->with(NetifydLicenseType::ENTERPRISE->cacheLabel())->andReturnTrue();
45-
Cache::expects('get')->with(NetifydLicenseType::ENTERPRISE->cacheLabel())->andReturn(['license_key' => 'cache']);
49+
$fakeLicense = [
50+
'issued_to' => NetifydLicenseType::ENTERPRISE->label(),
51+
'expire_at' => [
52+
'unix' => now()->addDays(2)->unix(),
53+
],
54+
];
55+
Cache::expects('get')->with(NetifydLicenseType::ENTERPRISE->cacheLabel())->andReturn($fakeLicense);
4656
withBasicAuth('', '')
4757
->get('/api/netifyd/community/license')
4858
->assertOk()
49-
->assertJson(['license_key' => 'cache']);
59+
->assertJson($fakeLicense);
5060
});
5161

52-
it('serves correctly cache if present', function () {
53-
Cache::expects('has')->with(NetifydLicenseType::ENTERPRISE->cacheLabel())->andReturnTrue();
54-
Cache::expects('get')->with(NetifydLicenseType::ENTERPRISE->cacheLabel())->andReturn(['license_key' => 'cached-license-key']);
62+
it('serves correctly cache if present and not expired', function () {
63+
$fakeLicense = [
64+
'issued_to' => NetifydLicenseType::ENTERPRISE->label(),
65+
'expire_at' => [
66+
'unix' => now()->addDays(2)->unix(),
67+
],
68+
];
69+
Cache::expects('get')->with(NetifydLicenseType::ENTERPRISE->cacheLabel())->andReturn($fakeLicense);
5570
Http::preventStrayRequests();
5671
Http::fake();
5772
withBasicAuth('system-id', 'secret')
5873
->get('/api/netifyd/community/license')
5974
->assertOk()
60-
->assertJson([
61-
'license_key' => 'cached-license-key',
62-
]);
75+
->assertJson($fakeLicense);
76+
});
77+
78+
it('throws away the cache if license is expired', function () {
79+
$fakeLicense = [
80+
'issued_to' => NetifydLicenseType::ENTERPRISE->label(),
81+
'expire_at' => [
82+
'unix' => now()->subDay()->unix(),
83+
],
84+
];
85+
Cache::expects('get')->with(NetifydLicenseType::ENTERPRISE->cacheLabel())->andReturn($fakeLicense);
86+
Cache::expects('forget')->with(NetifydLicenseType::ENTERPRISE->cacheLabel());
87+
$license = [
88+
'issued_to' => NetifydLicenseType::ENTERPRISE->label(),
89+
'serial' => 'EXAMPLE-ENTERPRISE-SERIAL',
90+
'expire_at' => [
91+
'unix' => now()->addDays(2)->unix(),
92+
],
93+
];
94+
Cache::expects('put')->withSomeOfArgs(NetifydLicenseType::ENTERPRISE->cacheLabel(), $license);
95+
partialMock(NetifydLicenseRepository::class, function (MockInterface $mock) use ($license) {
96+
$mock->expects('listLicenses')
97+
->andReturn([$license]);
98+
});
99+
withBasicAuth('system-id', 'secret')
100+
->get('/api/netifyd/community/license')
101+
->assertOk()
102+
->json($license);
63103
});
64104

65105
it('handles errors from netifyd server', function () {
@@ -82,15 +122,12 @@
82122
'expire_at' => [
83123
'unix' => now()->addDays(2)->unix(),
84124
],
85-
'created_at' => [
86-
'unix' => now()->subDay()->unix(),
87-
],
88125
];
89126
partialMock(NetifydLicenseRepository::class, function (MockInterface $mock) use ($license) {
90127
$mock->expects('listLicenses')
91128
->andReturn([$license]);
92129
});
93-
Cache::expects('has')->with(NetifydLicenseType::ENTERPRISE->cacheLabel())->andReturnFalse();
130+
Cache::expects('get')->with(NetifydLicenseType::ENTERPRISE->cacheLabel())->andReturnNull();
94131
Cache::expects('put')->withSomeOfArgs(NetifydLicenseType::ENTERPRISE->cacheLabel(), $license);
95132
withBasicAuth('system-id', 'secret')
96133
->get('/api/netifyd/community/license')
@@ -130,9 +167,6 @@
130167
'expire_at' => [
131168
'unix' => now()->addDay()->unix(),
132169
],
133-
'created_at' => [
134-
'unix' => now()->subDays(3)->unix(),
135-
],
136170
];
137171
partialMock(NetifydLicenseRepository::class, function (MockInterface $mock) use ($license) {
138172
$mock->expects('listLicenses')
@@ -148,15 +182,35 @@
148182
->assertOk();
149183
});
150184

151-
it('cannot renew license', function () {
185+
it('cannot renew license, but it\'s not expired', function () {
152186
$license = [
153187
'issued_to' => NetifydLicenseType::ENTERPRISE->label(),
154188
'serial' => 'EXAMPLE-ENTERPRISE-SERIAL',
155189
'expire_at' => [
156190
'unix' => now()->addDay()->unix(),
157191
],
158-
'created_at' => [
159-
'unix' => now()->subDays(3)->unix(),
192+
];
193+
partialMock(NetifydLicenseRepository::class, function (MockInterface $mock) use ($license) {
194+
$mock->expects('listLicenses')
195+
->andReturn([
196+
$license,
197+
]);
198+
$mock->expects('renewLicense')
199+
->with(NetifydLicenseType::ENTERPRISE, 'EXAMPLE-ENTERPRISE-SERIAL')
200+
->andThrow(new Exception('Cannot renew license'));
201+
});
202+
withBasicAuth('', '')
203+
->get('/api/netifyd/community/license')
204+
->assertOk()
205+
->assertJson($license);
206+
});
207+
208+
it('cannot renew license, but it\'s expired', function () {
209+
$license = [
210+
'issued_to' => NetifydLicenseType::ENTERPRISE->label(),
211+
'serial' => 'EXAMPLE-ENTERPRISE-SERIAL',
212+
'expire_at' => [
213+
'unix' => now()->subDay()->unix(),
160214
],
161215
];
162216
partialMock(NetifydLicenseRepository::class, function (MockInterface $mock) use ($license) {
@@ -170,8 +224,7 @@
170224
});
171225
withBasicAuth('', '')
172226
->get('/api/netifyd/community/license')
173-
->assertInternalServerError()
174-
->assertJson(['message' => 'Cannot renew license']);
227+
->assertInternalServerError();
175228
});
176229

177230
});

tests/Feature/Logic/NetifydLicenceRepositoryTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,6 @@
4141
Http::fake([
4242
'*' => Http::response(json_encode(['error' => 'error']), 500),
4343
]);
44-
$repository->renewLicense($licenseType, 'dummy');
44+
$repository->renewLicense($licenseType, 'example serial', now());
4545
})->throws('Could not renew license on netifyd:')
4646
->with(NetifydLicenseType::cases());

0 commit comments

Comments
 (0)