Skip to content

Commit 2b02541

Browse files
Create endpoint to get polices that should be accepted (#1198)
Bug: T429591 --------- Co-authored-by: dena <dena@wikimedia.de> Co-authored-by: dena <91744937+deer-wmde@users.noreply.github.com>
1 parent 8ce087c commit 2b02541

7 files changed

Lines changed: 159 additions & 0 deletions

File tree

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<?php
2+
3+
namespace App\Http\Controllers;
4+
5+
use App\Http\Resources\PoliciesCollection;
6+
use App\Policy;
7+
use Carbon\CarbonImmutable;
8+
9+
class PoliciesController extends Controller {
10+
public function getCurrentPolicies(): PoliciesCollection {
11+
$now = CarbonImmutable::now();
12+
13+
// This works based on the assumption that the latest policy has the highest id given that id is AUTO_INCREMENT
14+
$latestPolicyIds = Policy::where('active_from', '<', $now)
15+
->selectRaw('MAX(id) as id')
16+
->groupBy('policy_type')
17+
->pluck('id');
18+
19+
$currentPolicies = Policy::whereIn('id', $latestPolicyIds)->get();
20+
21+
return new PoliciesCollection($currentPolicies);
22+
}
23+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
<?php
2+
3+
namespace App\Http\Resources;
4+
5+
use Illuminate\Http\Request;
6+
use Illuminate\Http\Resources\Json\ResourceCollection;
7+
use Illuminate\Support\Collection;
8+
9+
class PoliciesCollection extends ResourceCollection {
10+
// per default Laravel wraps ResourceCollections in a `data` key: https://laravel.com/docs/11.x/eloquent-resources#data-wrapping
11+
// which is not wanted in this case: https://phabricator.wikimedia.org/T429591
12+
public static $wrap = 'items';
13+
14+
/**
15+
* Transform the resource collection into an array.
16+
*/
17+
public function toArray(Request $request): array {
18+
return $this->collection->mapInto(PolicyResource::class)->toArray();
19+
}
20+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
<?php
2+
3+
namespace App\Http\Resources;
4+
5+
use Illuminate\Http\Request;
6+
use Illuminate\Http\Resources\Json\JsonResource;
7+
use Illuminate\Support\Carbon;
8+
9+
class PolicyResource extends JsonResource {
10+
/**
11+
* Transform the resource into an array.
12+
*
13+
* @return array<string, mixed>
14+
*/
15+
public function toArray(Request $request): array {
16+
return [
17+
'metadata' => [
18+
'policy_id' => $this->id,
19+
'type' => $this->policy_type,
20+
'active_from' => Carbon::parse($this->active_from)->format('Y-m-d'),
21+
'content_vue_file' => $this->content_vue_file,
22+
],
23+
];
24+
}
25+
}

app/Policy.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
use Carbon\CarbonImmutable;
66
use Eloquent;
77
use Illuminate\Database\Eloquent\Builder;
8+
use Illuminate\Database\Eloquent\Factories\HasFactory;
89
use Illuminate\Database\Eloquent\Model;
910

1011
/**
@@ -24,10 +25,13 @@
2425
* @method static Builder<static>|Policy whereId($value)
2526
* @method static Builder<static>|Policy wherePolicyType($value)
2627
* @method static Builder<static>|Policy whereUpdatedAt($value)
28+
* @method static \Database\Factories\PolicyFactory factory(...$parameters)
2729
*
2830
* @mixin Eloquent
2931
*/
3032
class Policy extends Model {
33+
use HasFactory;
34+
3135
// define which attributes are mass assignable
3236
protected $fillable = [
3337
'policy_type',
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
<?php
2+
3+
namespace Database\Factories;
4+
5+
use App\Policy;
6+
use Illuminate\Database\Eloquent\Factories\Factory;
7+
8+
/**
9+
* @extends Factory<Policy>
10+
*/
11+
class PolicyFactory extends Factory {
12+
protected $model = Policy::class;
13+
14+
/**
15+
* Define the model's default state.
16+
*
17+
* @return array<string, mixed>
18+
*/
19+
public function definition(): array {
20+
return [
21+
'policy_type' => $this->faker->randomElement(['terms-of-use', 'hosting-policy']),
22+
'active_from' => now(),
23+
'content_vue_file' => fake()->slug() . '.vue',
24+
];
25+
}
26+
}

routes/api.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
$router->post('user/resetPassword', ['uses' => 'Auth\ResetPasswordController@reset']);
2222
$router->post('contact/sendMessage', ['uses' => 'ContactController@sendMessage']);
2323
$router->post('complaint/sendMessage', ['uses' => 'ComplaintController@sendMessage']);
24+
$router->get('v1/policies/current', ['uses' => 'PoliciesController@getCurrentPolicies']);
2425

2526
$router->post('auth/login', ['uses' => 'Auth\LoginController@postLogin'])->name('login');
2627
// Authed
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
<?php
2+
3+
namespace Tests\Http\Controllers;
4+
5+
use App\Policy;
6+
use Illuminate\Foundation\Testing\DatabaseTransactions;
7+
use Tests\TestCase;
8+
9+
class PoliciesControllerTest extends TestCase {
10+
use DatabaseTransactions;
11+
12+
public function testGetCurrentPolicies(): void {
13+
$currentTime = now();
14+
15+
// Future policy
16+
Policy::factory()->create([
17+
'policy_type' => 'terms-of-use',
18+
'active_from' => $currentTime->addDay(),
19+
]);
20+
// Old policy
21+
Policy::factory()->create([
22+
'policy_type' => 'hosting-policy',
23+
'active_from' => $currentTime->subMonth(),
24+
]);
25+
// Active policies
26+
$latestActiveToUPolicy = Policy::factory()->create([
27+
'policy_type' => 'terms-of-use',
28+
'active_from' => $currentTime->subMonth(),
29+
]);
30+
$latestActiveHostingPolicy = Policy::factory()->create([
31+
'policy_type' => 'hosting-policy',
32+
'active_from' => $currentTime->subWeek(),
33+
]);
34+
35+
$response = $this->getJson('/v1/policies/current');
36+
37+
$response->assertOk();
38+
$response->assertJsonStructure([
39+
'items' => [
40+
'*' => [
41+
'metadata' => [
42+
'policy_id',
43+
'active_from',
44+
'content_vue_file',
45+
'type',
46+
],
47+
],
48+
],
49+
]);
50+
51+
$response->assertJsonFragment([
52+
'policy_id' => $latestActiveToUPolicy->id,
53+
'active_from' => $latestActiveToUPolicy->active_from->format('Y-m-d'),
54+
]);
55+
$response->assertJsonFragment([
56+
'policy_id' => $latestActiveHostingPolicy->id,
57+
'active_from' => $latestActiveHostingPolicy->active_from->format('Y-m-d'),
58+
]);
59+
}
60+
}

0 commit comments

Comments
 (0)