Start working on the invite system for users
This commit is contained in:
43
app/Commands/User/InviteTeamMemberCommand.php
Normal file
43
app/Commands/User/InviteTeamMemberCommand.php
Normal file
@@ -0,0 +1,43 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Cachet.
|
||||
*
|
||||
* (c) Alt Three Services Limited
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace CachetHQ\Cachet\Commands\User;
|
||||
|
||||
final class InviteTeamMemberCommand
|
||||
{
|
||||
/**
|
||||
* The invte emails.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $email;
|
||||
|
||||
/**
|
||||
* The validation rules.
|
||||
*
|
||||
* @var string[]
|
||||
*/
|
||||
public $rules = [
|
||||
'emails' => 'required|array|email',
|
||||
];
|
||||
|
||||
/**
|
||||
* Create a new invite team member command instance.
|
||||
*
|
||||
* @param array $email
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct($emails)
|
||||
{
|
||||
$this->emails = $emails;
|
||||
}
|
||||
}
|
||||
34
app/Events/User/UserWasInvitedEvent.php
Normal file
34
app/Events/User/UserWasInvitedEvent.php
Normal file
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Cachet.
|
||||
*
|
||||
* (c) Alt Three Services Limited
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace CachetHQ\Cachet\Events\User;
|
||||
|
||||
use CachetHQ\Cachet\Models\Invite;
|
||||
|
||||
final class UserWasInvitedEvent
|
||||
{
|
||||
/**
|
||||
* The invite that has been added.
|
||||
*
|
||||
* @var \CachetHQ\Cachet\Models\Invite
|
||||
*/
|
||||
public $invite;
|
||||
|
||||
/**
|
||||
* Create a new user was invite event instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(Invite $invite)
|
||||
{
|
||||
$this->invite = $invite;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Cachet.
|
||||
*
|
||||
* (c) Alt Three Services Limited
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace CachetHQ\Cachet\Handlers\Commands\User;
|
||||
|
||||
use CachetHQ\Cachet\Commands\User\InviteTeamMemberCommand;
|
||||
use CachetHQ\Cachet\Events\User\UserWasAddedEvent;
|
||||
use CachetHQ\Cachet\Models\Invite;
|
||||
|
||||
class InviteTeamMemberCommandHandler
|
||||
{
|
||||
/**
|
||||
* Handle the invite team member command.
|
||||
*
|
||||
* @param \CachetHQ\Cachet\Commands\User\InviteTeamMemberCommand $command
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function handle(InviteTeamMemberCommand $command)
|
||||
{
|
||||
foreach ($command->emails as $email) {
|
||||
$invite = Invite::create([
|
||||
'email' => $command->email,
|
||||
]);
|
||||
|
||||
event(new UserWasInvitedEvent($invite));
|
||||
}
|
||||
}
|
||||
}
|
||||
62
app/Handlers/Events/User/SendInviteUserEmailHandler.php
Normal file
62
app/Handlers/Events/User/SendInviteUserEmailHandler.php
Normal file
@@ -0,0 +1,62 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Cachet.
|
||||
*
|
||||
* (c) Alt Three Services Limited
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace CachetHQ\Cachet\Handlers\Events\User;
|
||||
|
||||
use CachetHQ\Cachet\Events\Subscriber\UserWasInvitedEvent;
|
||||
use Illuminate\Contracts\Mail\MailQueue;
|
||||
use Illuminate\Mail\Message;
|
||||
|
||||
class SendInviteUserEmailHandler
|
||||
{
|
||||
/**
|
||||
* The mailer instance.
|
||||
*
|
||||
* @var \Illuminate\Contracts\Mail\MailQueue
|
||||
*/
|
||||
protected $mailer;
|
||||
|
||||
/**
|
||||
* Create a new send invite user email handler.
|
||||
*
|
||||
* @param \Illuminate\Contracts\Mail\Mailer $mailer
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(MailQueue $mailer)
|
||||
{
|
||||
$this->mailer = $mailer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the event.
|
||||
*
|
||||
* @param \CachetHQ\Cachet\Events\UserWasInvitedEvent $event
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function handle(UserWasInvitedEvent $event)
|
||||
{
|
||||
$mail = [
|
||||
'email' => $event->invite->email,
|
||||
'subject' => 'You have been invited.',
|
||||
'link' => route('invite.signup', ['code' => $event->invite->code]),
|
||||
'app_url' => env('APP_URL'),
|
||||
];
|
||||
|
||||
$this->mailer->queue([
|
||||
'html' => 'emails.users.invite-html',
|
||||
'text' => 'emails.users.invite-text',
|
||||
], $mail, function (Message $message) use ($mail) {
|
||||
$message->to($mail['email'])->subject($mail['subject']);
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -62,6 +62,17 @@ class TeamController extends Controller
|
||||
->withPageTitle(trans('dashboard.team.add.title').' - '.trans('dashboard.dashboard'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows the invite team member view.
|
||||
*
|
||||
* @return \Illuminate\View\View
|
||||
*/
|
||||
public function showInviteTeamMemberView()
|
||||
{
|
||||
return View::make('dashboard.team.invite')
|
||||
->withPageTitle(trans('dashboard.team.invite.title').' - '.trans('dashboard.dashboard'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new team member.
|
||||
*
|
||||
@@ -111,6 +122,28 @@ class TeamController extends Controller
|
||||
->withSuccess(sprintf('%s %s', trans('dashboard.notifications.awesome'), trans('dashboard.team.edit.success')));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new team member.
|
||||
*
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function postInviteUser()
|
||||
{
|
||||
try {
|
||||
$this->dispatch(new InviteTeamMemberCommand(
|
||||
array_unique(array_filter((array) Binput::get('emails')))
|
||||
));
|
||||
} catch (ValidationException $e) {
|
||||
return Redirect::route('dashboard.team.invite')
|
||||
->withInput(Binput::except('password'))
|
||||
->withTitle(sprintf('%s %s', trans('dashboard.notifications.whoops'), trans('dashboard.team.invite.failure')))
|
||||
->withErrors($e->getMessageBag());
|
||||
}
|
||||
|
||||
return Redirect::route('dashboard.team.invite')
|
||||
->withSuccess(sprintf('%s %s', trans('dashboard.notifications.awesome'), trans('dashboard.team.invite.success')));
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a user.
|
||||
*
|
||||
|
||||
@@ -202,8 +202,13 @@ class DashboardRoutes
|
||||
'as' => 'add',
|
||||
'uses' => 'TeamController@showAddTeamMemberView',
|
||||
]);
|
||||
$router->get('invite', [
|
||||
'as' => 'invite',
|
||||
'uses' => 'TeamController@showInviteTeamMemberView',
|
||||
]);
|
||||
$router->get('{user}', 'TeamController@showTeamMemberView');
|
||||
$router->post('add', 'TeamController@postAddUser');
|
||||
$router->post('invite', 'TeamController@postInviteUser');
|
||||
$router->post('{user}', 'TeamController@postUpdateUser');
|
||||
$router->delete('{user}/delete', 'TeamController@deleteUser');
|
||||
});
|
||||
|
||||
48
app/Models/Invite.php
Normal file
48
app/Models/Invite.php
Normal file
@@ -0,0 +1,48 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Cachet.
|
||||
*
|
||||
* (c) Alt Three Services Limited
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace CachetHQ\Cachet\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
class Invite extends Model
|
||||
{
|
||||
/**
|
||||
* The attributes that should be casted to native types.
|
||||
*
|
||||
* @var string[]
|
||||
*/
|
||||
protected $casts = [
|
||||
'email' => 'string',
|
||||
];
|
||||
|
||||
/**
|
||||
* The fillable properties.
|
||||
*
|
||||
* @var string[]
|
||||
*/
|
||||
protected $fillable = ['email'];
|
||||
|
||||
/**
|
||||
* Overrides the models boot method.
|
||||
*/
|
||||
public static function boot()
|
||||
{
|
||||
parent::boot();
|
||||
|
||||
self::creating(function ($invite) {
|
||||
if (!$invite->code) {
|
||||
$invite->code = self::generateVerifyCode();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -30,6 +30,9 @@ class EventServiceProvider extends ServiceProvider
|
||||
'CachetHQ\Cachet\Events\Subscriber\SubscriberHasSubscribedEvent' => [
|
||||
'CachetHQ\Cachet\Handlers\Events\Subscriber\SendSubscriberVerificationEmailHandler',
|
||||
],
|
||||
'CachetHQ\Cachet\Events\User\UserWasInvitedEvent' => [
|
||||
'CachetHQ\Cachet\Handlers\Events\User\SendInviteEmailHandler',
|
||||
],
|
||||
'CachetHQ\Cachet\Events\User\UserWasAddedEvent' => [
|
||||
//
|
||||
],
|
||||
|
||||
35
database/migrations/2015_10_31_211944_CreateInvitesTable.php
Normal file
35
database/migrations/2015_10_31_211944_CreateInvitesTable.php
Normal file
@@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
|
||||
class CreateInvitesTable extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::create('invites', function (Blueprint $table) {
|
||||
$table->engine = 'InnoDB';
|
||||
|
||||
$table->increments('id');
|
||||
$table->string('code')->unique();
|
||||
$table->string('email');
|
||||
$table->timestamp('claimed_at')->nullable();
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::drop('invites');
|
||||
}
|
||||
}
|
||||
@@ -9,9 +9,14 @@
|
||||
<i class="icon icon ion-android-alert"></i> {{ trans('dashboard.team.team') }}
|
||||
</span>
|
||||
@if($current_user->isAdmin)
|
||||
<a class="btn btn-sm btn-success pull-right" href="{{ route('dashboard.team.add') }}">
|
||||
{{ trans('dashboard.team.add.title') }}
|
||||
</a>
|
||||
<div class="button-group pull-right">
|
||||
<a class="btn btn-sm btn-success" href="{{ route('dashboard.team.invite') }}">
|
||||
{{ trans('dashboard.team.invite.title') }}
|
||||
</a>
|
||||
<a class="btn btn-sm btn-success" href="{{ route('dashboard.team.add') }}">
|
||||
{{ trans('dashboard.team.add.title') }}
|
||||
</a>
|
||||
</div>
|
||||
@endif
|
||||
<div class="clearfix"></div>
|
||||
</div>
|
||||
|
||||
47
resources/views/dashboard/team/invite.blade.php
Normal file
47
resources/views/dashboard/team/invite.blade.php
Normal file
@@ -0,0 +1,47 @@
|
||||
@extends('layout.dashboard')
|
||||
|
||||
@section('content')
|
||||
<div class="header">
|
||||
<div class="sidebar-toggler visible-xs">
|
||||
<i class="icon ion-navicon"></i>
|
||||
</div>
|
||||
<span class="uppercase">
|
||||
<i class="icon ion-person"></i> {{ trans('dashboard.team.team') }}
|
||||
</span>
|
||||
</div>
|
||||
<div class="content-wrapper">
|
||||
<div class="row">
|
||||
<div class="col-sm-12">
|
||||
@include('dashboard.partials.errors')
|
||||
<form name="UserForm" class="form-vertical" role="form" action="/dashboard/team/invite" method="POST">
|
||||
<input type="hidden" name="_token" value="{{ csrf_token() }}">
|
||||
<fieldset>
|
||||
<div class="form-group">
|
||||
<label>{{ trans('forms.user.email') }}</label>
|
||||
<input type="email" class="form-control" name="emails[]" required>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<input type="email" class="form-control" name="emails[]">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<input type="email" class="form-control" name="emails[]">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<input type="email" class="form-control" name="emails[]">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<input type="email" class="form-control" name="emails[]">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<input type="email" class="form-control" name="emails[]">
|
||||
</div>
|
||||
</fieldset>
|
||||
|
||||
<div class="form-group">
|
||||
<button type="submit" class="btn btn-success">{{ trans('forms.invite') }}</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@stop
|
||||
13
resources/views/emails/users/invite-html.blade.php
Normal file
13
resources/views/emails/users/invite-html.blade.php
Normal file
@@ -0,0 +1,13 @@
|
||||
@extends('layout.emails')
|
||||
|
||||
@section('preheader')
|
||||
{!! trans('cachet.users.email.invite.html-preheader', ['app_name' => Setting::get('app_name')]) !!}
|
||||
@stop
|
||||
|
||||
@section('content')
|
||||
{!! trans('cachet.users.email.invite.html', ['app_name' => Setting::get('app_name'), 'link' => $link]) !!}
|
||||
|
||||
@if(Setting::get('show_support'))
|
||||
<p>{!! trans('cachet.powered_by', ['app' => Setting::get('app_name')]) !!}</p>
|
||||
@endif
|
||||
@stop
|
||||
5
resources/views/emails/users/invite-text.blade.php
Normal file
5
resources/views/emails/users/invite-text.blade.php
Normal file
@@ -0,0 +1,5 @@
|
||||
{{ trans('cachet.users.email.invite.text', ['app_name' => Setting::get('app_name'), 'link' => $link]) }}
|
||||
|
||||
@if(Setting::get('show_support'))
|
||||
{!! trans('cachet.powered_by', ['app' => Setting::get('app_name')]) !!}
|
||||
@endif
|
||||
Reference in New Issue
Block a user