diff --git a/databases/migrations/2016_09_26_174220_create_permissions_table.php b/databases/migrations/2016_09_26_174220_create_permissions_table.php new file mode 100644 index 0000000000000000000000000000000000000000..858949320e4646a923b8735f7b4f7a44e260044f --- /dev/null +++ b/databases/migrations/2016_09_26_174220_create_permissions_table.php @@ -0,0 +1,48 @@ +schema->create('permissions', function (Blueprint $table) { + $table->increments('id'); + $table->string('name')->unique(); + $table->string('display_name')->nullable(); + $table->string('description')->nullable(); + $table->timestamps(); + }); + + $this->schema->create('member_permission', function (Blueprint $table) { + $table->unsignedInteger('member_id'); + $table->unsignedInteger('permission_id'); + $table->primary(['member_id', 'permission_id']); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + $this->schema->dropIfExists('member_permission'); + $this->schema->dropIfExists('permissions'); + } +} diff --git a/src/Member/Member.php b/src/Member/Member.php index 2cd188d96b00f161ef1da15186a791634679d95a..e07420fd46cc3aadd79f71311cb66eba65b1f153 100644 --- a/src/Member/Member.php +++ b/src/Member/Member.php @@ -9,6 +9,7 @@ namespace Notadd\Foundation\Member; use Laravel\Passport\HasApiTokens; +use Illuminate\Support\Facades\Cache; use Notadd\Foundation\Auth\User as Authenticatable; /** @@ -35,6 +36,16 @@ class Member extends Authenticatable 'remember_token', ]; + /** + * 用户的权限 + * + * @return \Illuminate\Database\Eloquent\Relations\BelongsToMany + */ + public function permissions() + { + return $this->belongsToMany(Permission::class, 'member_permission', 'member_id', 'permission_id'); + } + /** * Get member instance for passport. * @@ -46,4 +57,167 @@ class Member extends Authenticatable { return $this->newQuery()->where('name', $name)->first(); } + + public function cachedPermissions() + { + $memberPrimaryKey = $this->primaryKey; + $cacheKey = 'permissions_for_member_' . $this->$memberPrimaryKey; + + return Cache::tags('member_permission')->remember($cacheKey, 60, function () { + return $this->permissions()->get(); + }); + } + + public function save(array $options = []) + { + //both inserts and updates + $result = parent::save($options); + + Cache::tags('member_permission')->flush(); + + return $result; + } + + public function delete() + { + //soft or hard + $result = parent::delete(); + + Cache::tags('member_permission')->flush(); + + return $result; + } + + public function restore() + { + //soft delete undo's + $result = parent::restore(); + + Cache::tags('member_permission')->flush(); + + return $result; + } + + /** + * Boot the role model + * Attach event listener to remove the many-to-many records when trying to delete + * Will NOT delete any records if the role model uses soft deletes. + * + * @return void|bool + */ + public static function boot() + { + parent::boot(); + + static::deleting(function($member) { + + if (! method_exists(static::class, 'bootSoftDeletes')) { + $member->permissions()->sync([]); + } + + return true; + }); + } + + /** + * Checks if the member has a permission by its name. + *cachedPermissions + * @param string|array $name Permission name or array of permission names. + * @param bool $requireAll All permissions in the array are required. + * + * @return bool + */ + public function hasPermission($name, $requireAll = false) + { + if (is_array($name)) { + foreach ($name as $permissionName) { + $hasPermission = $this->hasPermission($permissionName); + + if ($hasPermission && ! $requireAll) { + return true; + } elseif (! $hasPermission && $requireAll) { + return false; + } + } + + // If we've made it this far and $requireAll is FALSE, then NONE of the permissions were found + // If we've made it this far and $requireAll is TRUE, then ALL of the permissions were found. + // Return the value of $requireAll; + return $requireAll; + } else { + foreach ($this->cachedPermissions() as $permission) { + if ($permission->name == $name) { + return true; + } + } + } + + return false; + } + + /** + * Attach permission to current role. + * + * @param object|array $permission + * + * @return void + */ + public function attachPermission($permission) + { + if (is_object($permission)) { + $permission = $permission->getKey(); + } + + if (is_array($permission)) { + $permission = $permission['id']; + } + + $this->permissions()->attach($permission); + } + + /** + * Detach permission from current role. + * + * @param object|array $permission + * + * @return void + */ + public function detachPermission($permission) + { + if (is_object($permission)) + $permission = $permission->getKey(); + + if (is_array($permission)) + $permission = $permission['id']; + + $this->permissions()->detach($permission); + } + + /** + * Attach multiple permissions to current role. + * + * @param mixed $permissions + * + * @return void + */ + public function attachPermissions($permissions) + { + foreach ($permissions as $permission) { + $this->attachPermission($permission); + } + } + + /** + * Detach multiple permissions from current role + * + * @param mixed $permissions + * + * @return void + */ + public function detachPermissions($permissions) + { + foreach ($permissions as $permission) { + $this->detachPermission($permission); + } + } } diff --git a/src/Member/Permission.php b/src/Member/Permission.php new file mode 100644 index 0000000000000000000000000000000000000000..ad47b7d8a41abde5a65a0f90ffbb63247c6b45ee --- /dev/null +++ b/src/Member/Permission.php @@ -0,0 +1,56 @@ + + * @copyright (c) 2017, iBenchu.org + * @datetime 2017-02-14 16:04 + */ + +namespace Notadd\Foundation\Member; + +use Notadd\Foundation\Database\Model; + +/** + * Class Permission + * + * @property integer $id + * @property string $name + * @property string $display_name + * @property string $description + * @property \Carbon\Carbon|null $created_at + * @property \Carbon\Carbon|null $updated_at + * + * @package Notadd\Foundation\Member + */ +class Permission extends Model +{ + protected $table = 'permissions'; + + protected $fillable = [ + 'name', 'display_name', 'description', + ]; + + /** + * @return \Illuminate\Database\Eloquent\Relations\BelongsToMany + */ + public function members() + { + return $this->belongsToMany(Member::class, 'member_permission', 'permission_id', 'member_id'); + } + + public static function addPermission($name, $display_name = null, $description = null) + { + $permission = static::where('name', $name)->first(); + + if (! $permission || ! $permission->exists) { + $permission = new static(['name' => $name]); + } + + $permission->display_name = $display_name; + $permission->description = $description; + $permission->save(); + + return $permission; + } +}