Skip to content

Commit

Permalink
Episode 54
Browse files Browse the repository at this point in the history
  • Loading branch information
JeffreyWay committed Jul 5, 2017
1 parent ffad0f9 commit 21412ff
Show file tree
Hide file tree
Showing 7 changed files with 94 additions and 3 deletions.
7 changes: 7 additions & 0 deletions app/Http/Controllers/RepliesController.php
Expand Up @@ -4,6 +4,7 @@


use App\Reply; use App\Reply;
use App\Thread; use App\Thread;
use Illuminate\Support\Facades\Gate;


class RepliesController extends Controller class RepliesController extends Controller
{ {
Expand Down Expand Up @@ -35,6 +36,12 @@ public function index($channelId, Thread $thread)
*/ */
public function store($channelId, Thread $thread) public function store($channelId, Thread $thread)
{ {
if (Gate::denies('create', new Reply)) {
return response(
'You are posting too frequently. Please take a break. :)', 429
);
}

try { try {
$this->validate(request(), ['body' => 'required|spamfree']); $this->validate(request(), ['body' => 'required|spamfree']);


Expand Down
15 changes: 15 additions & 0 deletions app/Policies/ReplyPolicy.php
Expand Up @@ -21,4 +21,19 @@ public function update(User $user, Reply $reply)
{ {
return $reply->user_id == $user->id; return $reply->user_id == $user->id;
} }

/**
* Determine if the authenticated user has permission to create a new reply.
*
* @param User $user
* @return bool
*/
public function create(User $user)
{
if (! $lastReply = $user->fresh()->lastReply) {
return true;
}

return ! $lastReply->wasJustPublished();
}
} }
11 changes: 11 additions & 0 deletions app/Reply.php
Expand Up @@ -2,6 +2,7 @@


namespace App; namespace App;


use Carbon\Carbon;
use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Model;


class Reply extends Model class Reply extends Model
Expand Down Expand Up @@ -65,6 +66,16 @@ public function thread()
return $this->belongsTo(Thread::class); return $this->belongsTo(Thread::class);
} }


/**
* Determine if the reply was just published a moment ago.
*
* @return bool
*/
public function wasJustPublished()
{
return $this->created_at->gt(Carbon::now()->subMinute());
}

/** /**
* Determine the path to the reply. * Determine the path to the reply.
* *
Expand Down
12 changes: 11 additions & 1 deletion app/User.php
Expand Up @@ -48,9 +48,19 @@ public function threads()
return $this->hasMany(Thread::class)->latest(); return $this->hasMany(Thread::class)->latest();
} }


/**
* Fetch the last published reply for the user.
*
* @return \Illuminate\Database\Eloquent\Relations\HasOne
*/
public function lastReply()
{
return $this->hasOne(Reply::class)->latest();
}

/** /**
* Get all activity for the user. * Get all activity for the user.
* *
* @return \Illuminate\Database\Eloquent\Relations\HasMany * @return \Illuminate\Database\Eloquent\Relations\HasMany
*/ */
public function activity() public function activity()
Expand Down
18 changes: 16 additions & 2 deletions tests/Feature/ParticipateInThreadsTest.php
Expand Up @@ -109,8 +109,22 @@ function replies_that_contain_spam_may_not_be_created()
'body' => 'Yahoo Customer Support' 'body' => 'Yahoo Customer Support'
]); ]);


$this->expectException(\Exception::class); $this->post($thread->path() . '/replies', $reply->toArray())
->assertStatus(422);
}


$this->post($thread->path() . '/replies', $reply->toArray()); /** @test */
function users_may_only_reply_a_maximum_of_once_per_minute()
{
$this->signIn();

$thread = create('App\Thread');
$reply = make('App\Reply');

$this->post($thread->path() . '/replies', $reply->toArray())
->assertStatus(200);

$this->post($thread->path() . '/replies', $reply->toArray())
->assertStatus(429);
} }
} }
13 changes: 13 additions & 0 deletions tests/Unit/ReplyTest.php
Expand Up @@ -2,6 +2,7 @@


namespace Tests\Unit; namespace Tests\Unit;


use Carbon\Carbon;
use Illuminate\Foundation\Testing\DatabaseMigrations; use Illuminate\Foundation\Testing\DatabaseMigrations;
use Tests\TestCase; use Tests\TestCase;


Expand All @@ -16,4 +17,16 @@ function it_has_an_owner()


$this->assertInstanceOf('App\User', $reply->owner); $this->assertInstanceOf('App\User', $reply->owner);
} }

/** @test */
function it_knows_if_it_was_just_published()
{
$reply = create('App\Reply');

$this->assertTrue($reply->wasJustPublished());

$reply->created_at = Carbon::now()->subMonth();

$this->assertFalse($reply->wasJustPublished());
}
} }
21 changes: 21 additions & 0 deletions tests/Unit/UserTest.php
@@ -0,0 +1,21 @@
<?php

namespace Tests\Feature;

use Tests\TestCase;
use Illuminate\Foundation\Testing\DatabaseMigrations;

class UserTest extends TestCase
{
use DatabaseMigrations;

/** @test */
public function a_user_can_fetch_their_most_recent_reply()
{
$user = create('App\User');

$reply = create('App\Reply', ['user_id' => $user->id]);

$this->assertEquals($reply->id, $user->lastReply->id);
}
}

0 comments on commit 21412ff

Please sign in to comment.