diff --git a/app/Http/Controllers/AdminController.php b/app/Http/Controllers/AdminController.php new file mode 100644 index 00000000..3ee791fe --- /dev/null +++ b/app/Http/Controllers/AdminController.php @@ -0,0 +1,37 @@ +. + */ + +namespace Poniverse\Ponyfm\Http\Controllers; + +use Illuminate\Support\Facades\Redirect; +use View; + +class AdminController extends Controller +{ + public function getIndex() + { + return Redirect::to('AdminController@getGenres'); + } + + public function getGenres() + { + return View::make('shared.null'); + } +} diff --git a/app/Http/Controllers/Controller.php b/app/Http/Controllers/Controller.php index 8cbf7b33..32706ca0 100644 --- a/app/Http/Controllers/Controller.php +++ b/app/Http/Controllers/Controller.php @@ -20,11 +20,12 @@ namespace Poniverse\Ponyfm\Http\Controllers; +use Illuminate\Foundation\Auth\Access\AuthorizesRequests; use Illuminate\Foundation\Bus\DispatchesJobs; use Illuminate\Routing\Controller as BaseController; use Illuminate\Foundation\Validation\ValidatesRequests; abstract class Controller extends BaseController { - use DispatchesJobs, ValidatesRequests; + use DispatchesJobs, ValidatesRequests, AuthorizesRequests; } diff --git a/app/Http/Kernel.php b/app/Http/Kernel.php index d14b13ec..b66eae13 100644 --- a/app/Http/Kernel.php +++ b/app/Http/Kernel.php @@ -47,6 +47,7 @@ class Kernel extends HttpKernel protected $routeMiddleware = [ 'auth' => \Poniverse\Ponyfm\Http\Middleware\Authenticate::class, 'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class, + 'can' => \Poniverse\Ponyfm\Http\Middleware\Authorize::class, 'guest' => \Poniverse\Ponyfm\Http\Middleware\RedirectIfAuthenticated::class, 'csrf' => \Poniverse\Ponyfm\Http\Middleware\VerifyCsrfHeader::class, ]; diff --git a/app/Http/Middleware/Authorize.php b/app/Http/Middleware/Authorize.php new file mode 100644 index 00000000..0ba2586e --- /dev/null +++ b/app/Http/Middleware/Authorize.php @@ -0,0 +1,62 @@ +. + */ + +namespace Poniverse\Ponyfm\Http\Middleware; + +use Closure; +use Gate; +use Illuminate\Contracts\Auth\Guard; + +class Authorize +{ + /** + * The Guard implementation. + * + * @var Guard + */ + protected $auth; + + /** + * Create a new filter instance. + * + * @param Guard $auth + */ + public function __construct(Guard $auth) + { + $this->auth = $auth; + } + + /** + * Handle an incoming request. + * + * @param \Illuminate\Http\Request $request + * @param \Closure $next + * @param string + * @return mixed + */ + public function handle($request, Closure $next, $ability) + { + if (Gate::denies($ability)) { + abort(403); + } + + return $next($request); + } +} diff --git a/app/Http/routes.php b/app/Http/routes.php index a4e4cd07..bde3878a 100644 --- a/app/Http/routes.php +++ b/app/Http/routes.php @@ -166,6 +166,11 @@ Route::group(['prefix' => 'account'], function() { }); }); +Route::group(['prefix' => 'admin', 'middleware' => ['auth', 'can:access-admin-area']], function() { + Route::get('/genres', 'AdminController@getGenres'); + Route::get('/', 'AdminController@getIndex'); +}); + Route::get('u{id}', 'ArtistsController@getShortlink')->where('id', '\d+'); Route::get('users/{id}-{slug}', 'ArtistsController@getShortlink')->where('id', '\d+'); Route::get('{slug}', 'ArtistsController@getProfile'); diff --git a/app/Policies/GenrePolicy.php b/app/Policies/GenrePolicy.php new file mode 100644 index 00000000..098cc1d1 --- /dev/null +++ b/app/Policies/GenrePolicy.php @@ -0,0 +1,34 @@ +. + */ + +namespace Poniverse\Ponyfm\Policies; + +class GenrePolicy +{ + /** + * Create a new policy instance. + * + * @return void + */ + public function __construct() + { + // stub class + } +} diff --git a/app/Providers/AuthServiceProvider.php b/app/Providers/AuthServiceProvider.php new file mode 100644 index 00000000..7ee54f58 --- /dev/null +++ b/app/Providers/AuthServiceProvider.php @@ -0,0 +1,54 @@ +. + */ + +namespace Poniverse\Ponyfm\Providers; + +use Illuminate\Contracts\Auth\Access\Gate as GateContract; +use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider; +use Poniverse\Ponyfm\Genre; +use Poniverse\Ponyfm\Policies\GenrePolicy; +use Poniverse\Ponyfm\User; + +class AuthServiceProvider extends ServiceProvider +{ + /** + * The policy mappings for the application. + * + * @var array + */ + protected $policies = [ + Genre::class => GenrePolicy::class + ]; + + /** + * Register any application authentication / authorization services. + * + * @param \Illuminate\Contracts\Auth\Access\Gate $gate + * @return void + */ + public function boot(GateContract $gate) + { + $gate->define('access-admin-area', function(User $user) { + return $user->hasRole('admin'); + }); + + $this->registerPolicies($gate); + } +} diff --git a/app/Role.php b/app/Role.php new file mode 100644 index 00000000..35215138 --- /dev/null +++ b/app/Role.php @@ -0,0 +1,34 @@ +. + */ + +namespace Poniverse\Ponyfm; + +use Illuminate\Database\Eloquent\Model; + +class Role extends Model +{ + protected $table = 'roles'; + public $timestamps = false; + + public function users() + { + return $this->belongsToMany(User::class, 'role_user'); + } +} diff --git a/app/User.php b/app/User.php index 6fb45c93..b517138c 100644 --- a/app/User.php +++ b/app/User.php @@ -27,13 +27,14 @@ use Illuminate\Auth\Passwords\CanResetPassword; use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract; use Illuminate\Contracts\Auth\CanResetPassword as CanResetPasswordContract; use Illuminate\Database\Eloquent\Model; +use Illuminate\Foundation\Auth\Access\Authorizable; use Illuminate\Support\Facades\Auth; use Illuminate\Support\Facades\URL; use Illuminate\Support\Str; -class User extends Model implements AuthenticatableContract, CanResetPasswordContract +class User extends Model implements AuthenticatableContract, CanResetPasswordContract, \Illuminate\Contracts\Auth\Access\Authorizable { - use Authenticatable, CanResetPassword; + use Authenticatable, CanResetPassword, Authorizable; protected $table = 'users'; protected $hidden1 = ['password_hash', 'password_salt', 'bio']; @@ -61,6 +62,11 @@ class User extends Model implements AuthenticatableContract, CanResetPasswordCon return $this->hasMany('Poniverse\Ponyfm\ResourceUser', 'artist_id'); } + public function roles() + { + return $this->belongsToMany(Role::class, 'role_user'); + } + public function comments() { return $this->hasMany('Poniverse\Ponyfm\Comment', 'profile_id')->orderBy('created_at', 'desc'); @@ -167,4 +173,21 @@ class User extends Model implements AuthenticatableContract, CanResetPasswordCon { return "remember_token"; } + + /** + * Returns true if this user has the given role. + * + * @param $roleName + * @return bool + */ + public function hasRole($roleName) + { + foreach ($this->roles as $role) { + if ($role->name === $roleName) { + return true; + } + } + + return false; + } } diff --git a/config/app.php b/config/app.php index 8fb5bbcb..8fcbfdd7 100644 --- a/config/app.php +++ b/config/app.php @@ -143,6 +143,7 @@ return [ Poniverse\Ponyfm\Providers\AppServiceProvider::class, Poniverse\Ponyfm\Providers\EventServiceProvider::class, Poniverse\Ponyfm\Providers\RouteServiceProvider::class, + Poniverse\Ponyfm\Providers\AuthServiceProvider::class, Intouch\LaravelNewrelic\NewrelicServiceProvider::class, Barryvdh\LaravelIdeHelper\IdeHelperServiceProvider::class, @@ -175,6 +176,7 @@ return [ 'Eloquent' => Illuminate\Database\Eloquent\Model::class, 'Event' => Illuminate\Support\Facades\Event::class, // 'File' => Illuminate\Support\Facades\File::class, + 'Gate' => Illuminate\Support\Facades\Gate::class, 'Hash' => Illuminate\Support\Facades\Hash::class, 'Input' => Illuminate\Support\Facades\Input::class, 'Inspiring' => Illuminate\Foundation\Inspiring::class, diff --git a/public/templates/admin/_layout.html b/public/templates/admin/_layout.html new file mode 100644 index 00000000..75f5dfa4 --- /dev/null +++ b/public/templates/admin/_layout.html @@ -0,0 +1,5 @@ + + + diff --git a/public/templates/admin/genres.html b/public/templates/admin/genres.html new file mode 100644 index 00000000..d78ace18 --- /dev/null +++ b/public/templates/admin/genres.html @@ -0,0 +1,3 @@ +

Genre Editor

+ +

This is a stub page!

diff --git a/resources/assets/scripts/app/app.coffee b/resources/assets/scripts/app/app.coffee index de108507..8ef8afff 100644 --- a/resources/assets/scripts/app/app.coffee +++ b/resources/assets/scripts/app/app.coffee @@ -224,7 +224,18 @@ module.config [ url: '/register' templateUrl: '/templates/auth/register.html' - # Hompage + # Admin + + state.state 'admin', + abstract: true + url: '/admin' + templateUrl: '/templates/admin/_layout.html' + + state.state 'admin.genres', + url: '/genres', + templateUrl: '/templates/admin/genres.html' + + # Homepage if window.pfm.auth.isLogged state.state 'home', diff --git a/resources/views/shared/_app_layout.blade.php b/resources/views/shared/_app_layout.blade.php index e3c570b5..c000ebe1 100644 --- a/resources/views/shared/_app_layout.blade.php +++ b/resources/views/shared/_app_layout.blade.php @@ -85,6 +85,13 @@
  • Upload Music
  • + + @can('access-admin-area') +
  • + Admin Area +
  • + @endcan +