Skip to content
This repository was archived by the owner on Jun 29, 2021. It is now read-only.

Commit 1c2bdea

Browse files
authored
Resolves #52 - A guest cannot submit Links for existing author_email (#54)
* Update CHANGELOG.md * Implemented funcionality Refactored test: moved payload and file creation to setUp(). * Apply rule only when guest
1 parent 5d90a21 commit 1c2bdea

File tree

3 files changed

+63
-47
lines changed

3 files changed

+63
-47
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ All notable changes to `laravel-portugal/api` will be documented in this file
99
- An authenticated user can delete a question (#30)
1010
- A guest or an authenticated user can see details of a question (#48)
1111
- A guest or an authenticated user can list questions (#26)
12+
- Guest cannot submit Links for existing author_email (#52)
1213

1314
### Changed
1415

domains/Links/Controllers/LinksStoreController.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ public function __invoke(Request $request): Response
2525
'title' => ['required', 'string'],
2626
'description' => ['required', 'string'],
2727
'author_name' => ['required', 'string'],
28-
'author_email' => ['required', 'email'],
28+
'author_email' => ['required', 'email', $request->user() ? null : 'unique:users,email'],
2929
'cover_image' => ['required', 'image'],
3030
'tags' => ['required', 'array'],
3131
'tags.*.id' => ['required', 'integer', 'exists:tags'],
@@ -40,8 +40,8 @@ public function __invoke(Request $request): Response
4040
'link' => $request->input('link'),
4141
'title' => $request->input('title'),
4242
'description' => $request->input('description'),
43-
'author_name' => $request->input('author_name'),
44-
'author_email' => $request->input('author_email'),
43+
'author_name' => optional($request->user())->name ?? $request->input('author_name'),
44+
'author_email' => optional($request->user())->email ?? $request->input('author_email'),
4545
'cover_image' => $request->file('cover_image')->store('cover_images'),
4646
]);
4747

domains/Links/Tests/Feature/LinksStoreTest.php

Lines changed: 59 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
namespace Domains\Links\Tests\Feature;
44

5+
use Domains\Accounts\Database\Factories\UserFactory;
56
use Domains\Tags\Database\Factories\TagFactory;
67
use Domains\Tags\Models\Tag;
78
use Faker\Factory;
@@ -18,20 +19,17 @@ class LinksStoreTest extends TestCase
1819
private Tag $tag;
1920
private Generator $faker;
2021

22+
private array $payload;
23+
private array $files;
24+
2125
protected function setUp(): void
2226
{
2327
parent::setUp();
2428

2529
$this->tag = TagFactory::new()->create();
2630
$this->faker = Factory::create();
27-
}
28-
29-
/** @test */
30-
public function it_stores_resources(): void
31-
{
32-
Storage::fake('local');
3331

34-
$payload = [
32+
$this->payload = [
3533
'link' => $this->faker->url,
3634
'title' => $this->faker->title,
3735
'description' => $this->faker->paragraph,
@@ -41,21 +39,26 @@ public function it_stores_resources(): void
4139
['id' => $this->tag->id],
4240
],
4341
];
44-
45-
$files = [
42+
$this->files = [
4643
'cover_image' => UploadedFile::fake()->image('cover_image.jpg'),
4744
];
4845

49-
$response = $this->call('POST', '/links', $payload, [], $files);
46+
Storage::fake('local');
47+
}
48+
49+
/** @test */
50+
public function it_stores_resources(): void
51+
{
52+
$response = $this->call('POST', '/links', $this->payload, [], $this->files);
5053
self::assertTrue($response->isEmpty());
5154

5255
$this->seeInDatabase('links', [
53-
'link' => $payload['link'],
54-
'title' => $payload['title'],
55-
'description' => $payload['description'],
56-
'author_name' => $payload['author_name'],
57-
'author_email' => $payload['author_email'],
58-
'cover_image' => 'cover_images/' . $files['cover_image']->hashName(),
56+
'link' => $this->payload['link'],
57+
'title' => $this->payload['title'],
58+
'description' => $this->payload['description'],
59+
'author_name' => $this->payload['author_name'],
60+
'author_email' => $this->payload['author_email'],
61+
'cover_image' => 'cover_images/' . $this->files['cover_image']->hashName(),
5962
'approved_at' => null,
6063
]);
6164

@@ -66,7 +69,7 @@ public function it_stores_resources(): void
6669
]
6770
);
6871

69-
Storage::assertExists('cover_images/' . $files['cover_image']->hashName());
72+
Storage::assertExists('cover_images/' . $this->files['cover_image']->hashName());
7073
}
7174

7275
/** @test */
@@ -87,18 +90,9 @@ public function it_fails_to_store_resources_on_validation_errors(): void
8790
/** @test */
8891
public function it_fails_to_store_resources_with_invalid_link(): void
8992
{
90-
$payload = [
91-
'link' => 'this_is_not_a_valid_url',
92-
'title' => $this->faker->title,
93-
'description' => $this->faker->paragraph,
94-
'author_name' => $this->faker->name,
95-
'author_email' => $this->faker->safeEmail,
96-
'tags' => [
97-
['id' => $this->tag->id],
98-
],
99-
];
93+
$this->payload['link'] = 'this_is_not_a_valid_url';
10094

101-
$this->post('/links', $payload)
95+
$this->post('/links', $this->payload)
10296
->seeJsonStructure([
10397
'link',
10498
]);
@@ -107,26 +101,47 @@ public function it_fails_to_store_resources_with_invalid_link(): void
107101
/** @test */
108102
public function it_stores_resources_with_unregistered_link_domain(): void
109103
{
110-
Storage::fake('local');
104+
$this->payload['link'] = 'http://unregistered.laravel.pt';
111105

112-
$payload = [
113-
'link' => 'http://unregistered.laravel.pt',
114-
'title' => $this->faker->title,
115-
'description' => $this->faker->paragraph,
116-
'author_name' => $this->faker->name,
117-
'author_email' => $this->faker->safeEmail,
118-
'tags' => [
119-
['id' => $this->tag->id],
120-
],
121-
];
106+
$response = $this->call('POST', '/links', $this->payload, [], $this->files);
122107

123-
$files = [
124-
'cover_image' => UploadedFile::fake()->image('cover_image.jpg'),
125-
];
108+
self::assertEquals(204, $response->getStatusCode());
109+
self::assertTrue($response->isEmpty());
110+
}
111+
112+
/** @test */
113+
public function it_forbids_guest_to_use_a_registered_users_email_when_submitting_a_link(): void
114+
{
115+
$user = UserFactory::new(['email' => $this->faker->safeEmail])
116+
->create();
126117

127-
$response = $this->call('POST', '/links', $payload, [], $files);
118+
$this->payload['author_email'] = $user->email;
119+
120+
$this->post('/links', $this->payload)
121+
->seeJsonStructure(['author_email']);
122+
}
123+
124+
/** @test */
125+
public function it_uses_logged_in_user_email_and_name_when_submitting_a_link(): void
126+
{
127+
// create a random user
128+
$randomUser = UserFactory::new(['email' => $this->faker->safeEmail])->create();
129+
// create a user and login
130+
$user = UserFactory::new(['email' => $this->faker->safeEmail])->create();
131+
$this->actingAs($user);
132+
133+
// use an existing user's email and it should go OK since we're logged in.
134+
$this->payload['author_email'] = $randomUser->email;
135+
136+
$response = $this->call('POST', '/links', $this->payload, [], $this->files);
128137

129138
self::assertEquals(204, $response->getStatusCode());
130-
self::assertTrue($response->isEmpty());
139+
$this->seeInDatabase(
140+
'links',
141+
[
142+
'author_email' => $user->email,
143+
'author_name' => $user->name,
144+
]
145+
);
131146
}
132147
}

0 commit comments

Comments
 (0)