#3: User permissions can now be specified for an album. Added a new config to the User class that allows users to login and manage albums without needing full admin access
This commit is contained in:
parent
6be31c9b7e
commit
fd19c9db55
@ -35,11 +35,6 @@ class Album extends Model
|
||||
return $this->belongsToMany(Permission::class, 'album_anonymous_permissions');
|
||||
}
|
||||
|
||||
public function doesAnonymousHavePermission(Permission $permission)
|
||||
{
|
||||
return $this->anonymousPermissions()->where(['permission_id' => $permission->id])->count() > 0;
|
||||
}
|
||||
|
||||
public function doesGroupHavePermission(Group $group, Permission $permission)
|
||||
{
|
||||
return $this->groupPermissions()->where([
|
||||
@ -48,6 +43,22 @@ class Album extends Model
|
||||
])->count() > 0;
|
||||
}
|
||||
|
||||
public function doesUserHavePermission($user, Permission $permission)
|
||||
{
|
||||
// User will be null for anonymous users
|
||||
if (is_null($user))
|
||||
{
|
||||
return $this->anonymousPermissions()->where(['permission_id' => $permission->id])->count() > 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
return $this->userPermissions()->where([
|
||||
'user_id' => $user->id,
|
||||
'permission_id' => $permission->id
|
||||
])->count() > 0;
|
||||
}
|
||||
}
|
||||
|
||||
public function generateAlias()
|
||||
{
|
||||
$this->url_alias = ucfirst(preg_replace('/[^a-z0-9\-]/', '-', strtolower($this->name)));
|
||||
@ -107,4 +118,9 @@ class Album extends Model
|
||||
{
|
||||
return route('viewAlbum', $this->url_alias);
|
||||
}
|
||||
|
||||
public function userPermissions()
|
||||
{
|
||||
return $this->belongsToMany(Permission::class, 'album_user_permissions');
|
||||
}
|
||||
}
|
@ -4,35 +4,60 @@ namespace App\Helpers;
|
||||
|
||||
use App\Album;
|
||||
use App\Facade\UserConfig;
|
||||
use Illuminate\Database\Query\Builder;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
|
||||
class DbHelper
|
||||
{
|
||||
public static function getAlbumsForCurrentUser()
|
||||
{
|
||||
$albumsQuery = Album::query();
|
||||
$user = Auth::user();
|
||||
$userId = is_null($user) ? 0 : $user->id;
|
||||
|
||||
$albums = Album::where('is_private', false)
|
||||
->orWhere(function ($query) use ($userId)
|
||||
if (!is_null($user) && $user->is_admin)
|
||||
{
|
||||
$query->where('is_private', true)
|
||||
->where('user_id', $userId);
|
||||
})
|
||||
/* Admin users always get everything, therefore no filters are necessary */
|
||||
}
|
||||
else if (is_null($user))
|
||||
{
|
||||
/* Anonymous users need to check the album_anonymous_permissions table. If not in this table, you're not allowed! */
|
||||
|
||||
$albumsQuery = Album::join('album_anonymous_permissions', 'album_anonymous_permissions.album_id', '=', 'albums.id')
|
||||
->join('permissions', 'permissions.id', '=', 'album_anonymous_permissions.permission_id')
|
||||
->where([
|
||||
['permissions.section', 'album'],
|
||||
['permissions.description', 'list']
|
||||
]);
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
Other users need to check either the album_group_permissions or album_user_permissions table. If not in either of these tables,
|
||||
you're not allowed!
|
||||
*/
|
||||
|
||||
$albumsQuery = Album::leftJoin('album_group_permissions', 'album_group_permissions.album_id', '=', 'albums.id')
|
||||
->leftJoin('album_user_permissions', 'album_user_permissions.album_id', '=', 'albums.id')
|
||||
->leftJoin('permissions AS group_permissions', 'group_permissions.id', '=', 'album_group_permissions.permission_id')
|
||||
->leftJoin('permissions AS user_permissions', 'user_permissions.id', '=', 'album_user_permissions.permission_id')
|
||||
->leftJoin('user_groups', 'user_groups.group_id', '=', 'album_group_permissions.group_id')
|
||||
->where('albums.user_id', $user->id)
|
||||
->orWhere([
|
||||
['group_permissions.section', 'album'],
|
||||
['group_permissions.description', 'list'],
|
||||
['user_groups.user_id', $user->id]
|
||||
])
|
||||
->orWhere([
|
||||
['user_permissions.section', 'album'],
|
||||
['user_permissions.description', 'list'],
|
||||
['album_user_permissions.user_id', $user->id]
|
||||
]);
|
||||
}
|
||||
|
||||
return $albumsQuery->select('albums.*')
|
||||
->distinct()
|
||||
->orderBy('name')
|
||||
->withCount('photos')
|
||||
->paginate(UserConfig::get('items_per_page'));
|
||||
|
||||
return $albums;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches an album using its URL alias.
|
||||
* @param string $urlAlias URL alias of the album to fetch.
|
||||
* @return Album|null
|
||||
*/
|
||||
public static function loadAlbumByUrlAlias($urlAlias)
|
||||
{
|
||||
return Album::where('url_alias', $urlAlias)->first();
|
||||
}
|
||||
}
|
@ -7,6 +7,7 @@ use App\AlbumGroupPermission;
|
||||
use App\Facade\Theme;
|
||||
use App\Facade\UserConfig;
|
||||
use App\Group;
|
||||
use App\Helpers\DbHelper;
|
||||
use App\Helpers\FileHelper;
|
||||
use App\Helpers\MiscHelper;
|
||||
use App\Http\Controllers\Controller;
|
||||
@ -16,6 +17,7 @@ use App\Photo;
|
||||
use App\Services\PhotoService;
|
||||
use App\Storage;
|
||||
use App\Upload;
|
||||
use App\User;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\App;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
@ -32,7 +34,7 @@ class AlbumController extends Controller
|
||||
|
||||
public function analyse($id, $queue_token)
|
||||
{
|
||||
$this->authorize('admin-access');
|
||||
$this->authorizeAccessToAdminPanel();
|
||||
|
||||
$album = $this->loadAlbum($id);
|
||||
$photos = $album->photos()
|
||||
@ -55,7 +57,7 @@ class AlbumController extends Controller
|
||||
*/
|
||||
public function create(Request $request)
|
||||
{
|
||||
$this->authorize('admin-access');
|
||||
$this->authorizeAccessToAdminPanel();
|
||||
|
||||
$albumSources = [];
|
||||
foreach (Storage::where('is_active', true)->orderBy('name')->get() as $storage)
|
||||
@ -79,7 +81,7 @@ class AlbumController extends Controller
|
||||
|
||||
public function delete($id)
|
||||
{
|
||||
$this->authorize('admin-access');
|
||||
$this->authorizeAccessToAdminPanel();
|
||||
|
||||
$album = $this->loadAlbum($id);
|
||||
|
||||
@ -94,7 +96,7 @@ class AlbumController extends Controller
|
||||
*/
|
||||
public function destroy($id)
|
||||
{
|
||||
$this->authorize('admin-access');
|
||||
$this->authorizeAccessToAdminPanel();
|
||||
|
||||
$album = $this->loadAlbum($id);
|
||||
|
||||
@ -120,7 +122,7 @@ class AlbumController extends Controller
|
||||
*/
|
||||
public function edit($id)
|
||||
{
|
||||
$this->authorize('admin-access');
|
||||
$this->authorizeAccessToAdminPanel();
|
||||
|
||||
$album = $this->loadAlbum($id);
|
||||
|
||||
@ -134,11 +136,9 @@ class AlbumController extends Controller
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
$this->authorize('admin-access');
|
||||
$this->authorizeAccessToAdminPanel();
|
||||
|
||||
$albums = Album::orderBy('name')
|
||||
->withCount('photos')
|
||||
->paginate(UserConfig::get('items_per_page'));
|
||||
$albums = DbHelper::getAlbumsForCurrentUser();
|
||||
|
||||
return Theme::render('admin.list_albums', [
|
||||
'albums' => $albums
|
||||
@ -147,7 +147,7 @@ class AlbumController extends Controller
|
||||
|
||||
public function setGroupPermissions(Request $request, $id)
|
||||
{
|
||||
$this->authorize('admin-access');
|
||||
$this->authorizeAccessToAdminPanel();
|
||||
|
||||
/** @var Album $album */
|
||||
$album = $this->loadAlbum($id);
|
||||
@ -167,10 +167,12 @@ class AlbumController extends Controller
|
||||
/** @var Permission $permission */
|
||||
foreach (Permission::where(['section' => 'album', 'is_default' => true])->get() as $permission)
|
||||
{
|
||||
$album->groupPermissions()->attach($permission->id, ['group_id' => $group->id]);
|
||||
$album->groupPermissions()->attach($permission->id, [
|
||||
'group_id' => $group->id,
|
||||
'created_at' => new \DateTime(),
|
||||
'updated_at' => new \DateTime()
|
||||
]);
|
||||
}
|
||||
|
||||
$album->save();
|
||||
}
|
||||
else if ($request->get('action') == 'update_group_permissions')
|
||||
{
|
||||
@ -193,10 +195,46 @@ class AlbumController extends Controller
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$album->save();
|
||||
|
||||
return redirect(route('albums.show', [$album->id, 'tab' => 'permissions']));
|
||||
}
|
||||
|
||||
public function setUserPermissions(Request $request, $id)
|
||||
{
|
||||
$this->authorizeAccessToAdminPanel();
|
||||
|
||||
/** @var Album $album */
|
||||
$album = $this->loadAlbum($id);
|
||||
|
||||
if ($request->get('action') == 'add_user' && $request->has('user_id'))
|
||||
{
|
||||
/* Add a new user to the permission list for this album */
|
||||
|
||||
/** @var User $user */
|
||||
$user = User::where('id', $request->get('user_id'))->first();
|
||||
if (is_null($user))
|
||||
{
|
||||
App::abort(404);
|
||||
}
|
||||
|
||||
// Link all default permissions to the group
|
||||
/** @var Permission $permission */
|
||||
foreach (Permission::where(['section' => 'album', 'is_default' => true])->get() as $permission)
|
||||
{
|
||||
$album->userPermissions()->attach($permission->id, [
|
||||
'user_id' => $user->id,
|
||||
'created_at' => new \DateTime(),
|
||||
'updated_at' => new \DateTime()
|
||||
]);
|
||||
}
|
||||
}
|
||||
else if ($request->get('action') == 'update_user_permissions')
|
||||
{
|
||||
/* Update existing user and anonymous permissions for this album */
|
||||
$album->anonymousPermissions()->detach();
|
||||
$album->userPermissions()->detach();
|
||||
|
||||
$permissions = $request->get('permissions');
|
||||
if (is_array($permissions))
|
||||
@ -211,8 +249,29 @@ class AlbumController extends Controller
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($permissions as $key => $value)
|
||||
{
|
||||
$userID = intval($key);
|
||||
if ($userID == 0)
|
||||
{
|
||||
// Skip non-numeric IDs (e.g. anonymous)
|
||||
continue;
|
||||
}
|
||||
|
||||
foreach ($value as $permissionID)
|
||||
{
|
||||
$album->userPermissions()->attach($permissionID, [
|
||||
'user_id' => $userID,
|
||||
'created_at' => new \DateTime(),
|
||||
'updated_at' => new \DateTime()
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$album->save();
|
||||
|
||||
return redirect(route('albums.show', [$album->id, 'tab' => 'permissions']));
|
||||
}
|
||||
@ -225,7 +284,7 @@ class AlbumController extends Controller
|
||||
*/
|
||||
public function show(Request $request, $id)
|
||||
{
|
||||
$this->authorize('admin-access');
|
||||
$this->authorizeAccessToAdminPanel();
|
||||
|
||||
$album = $this->loadAlbum($id);
|
||||
$photos = $album->photos()
|
||||
@ -258,6 +317,15 @@ class AlbumController extends Controller
|
||||
}
|
||||
}
|
||||
|
||||
$existingUsers = [];
|
||||
foreach (User::orderBy('name')->get() as $user)
|
||||
{
|
||||
if ($album->userPermissions()->where('user_id', $user->id)->count() > 0)
|
||||
{
|
||||
$existingUsers[] = $user;
|
||||
}
|
||||
}
|
||||
|
||||
$activeTab = $request->get('tab');
|
||||
|
||||
return Theme::render('admin.show_album', [
|
||||
@ -280,6 +348,7 @@ class AlbumController extends Controller
|
||||
],
|
||||
'error' => $request->session()->get('error'),
|
||||
'existing_groups' => $existingGroups,
|
||||
'existing_users' => $existingUsers,
|
||||
'file_upload_limit' => $fileUploadLimit,
|
||||
'is_upload_enabled' => $isUploadEnabled,
|
||||
'max_post_limit' => $postLimit,
|
||||
@ -299,7 +368,7 @@ class AlbumController extends Controller
|
||||
*/
|
||||
public function store(Requests\StoreAlbumRequest $request)
|
||||
{
|
||||
$this->authorize('admin-access');
|
||||
$this->authorizeAccessToAdminPanel();
|
||||
|
||||
$album = new Album();
|
||||
$album->fill($request->only(['name', 'description', 'storage_id']));
|
||||
@ -323,7 +392,7 @@ class AlbumController extends Controller
|
||||
*/
|
||||
public function update(Requests\StoreAlbumRequest $request, $id)
|
||||
{
|
||||
$this->authorize('admin-access');
|
||||
$this->authorizeAccessToAdminPanel();
|
||||
|
||||
$album = $this->loadAlbum($id);
|
||||
$album->fill($request->only(['name', 'description']));
|
||||
|
@ -8,6 +8,7 @@ use App\Facade\Theme;
|
||||
use App\Facade\UserConfig;
|
||||
use App\Group;
|
||||
use App\Helpers\ConfigHelper;
|
||||
use App\Helpers\DbHelper;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Requests\SaveSettingsRequest;
|
||||
use App\Mail\TestMailConfig;
|
||||
@ -30,9 +31,9 @@ class DefaultController extends Controller
|
||||
|
||||
public function index()
|
||||
{
|
||||
$this->authorize('admin-access');
|
||||
$this->authorizeAccessToAdminPanel();
|
||||
|
||||
$albumCount = Album::all()->count();
|
||||
$albumCount = DbHelper::getAlbumsForCurrentUser()->count();
|
||||
$photoCount = Photo::all()->count();
|
||||
$groupCount = Group::all()->count();
|
||||
$userCount = User::where('is_activated', true)->count();
|
||||
|
@ -88,6 +88,7 @@ class UserController extends Controller
|
||||
$user->password = bcrypt($user->password);
|
||||
$user->is_activated = true;
|
||||
$user->is_admin = (strtolower($request->get('is_admin')) == 'on');
|
||||
$user->can_create_albums = (strtolower($request->get('can_create_albums')) == 'on');
|
||||
$user->save();
|
||||
|
||||
return redirect(route('users.index'));
|
||||
@ -168,6 +169,8 @@ class UserController extends Controller
|
||||
$user->is_admin = (strtolower($request->get('is_admin')) == 'on');
|
||||
}
|
||||
|
||||
$user->can_create_albums = (strtolower($request->get('can_create_albums')) == 'on');
|
||||
|
||||
// Manually activate account if requested
|
||||
if (strtolower($request->get('is_activated')) == 'on')
|
||||
{
|
||||
@ -238,4 +241,33 @@ class UserController extends Controller
|
||||
|
||||
return redirect(route('users.index'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of users in JSON format - either all users or users matching the "q" query string parameter
|
||||
*
|
||||
* @param string $q Search term
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function searchJson(Request $request)
|
||||
{
|
||||
$this->authorize('admin-access');
|
||||
|
||||
$limit = intval($request->get('n'));
|
||||
if ($limit == 0)
|
||||
{
|
||||
$limit = 100;
|
||||
}
|
||||
|
||||
$q = $request->get('q');
|
||||
if (strlen($q) == 0)
|
||||
{
|
||||
return User::limit($limit)->get()->toJson();
|
||||
}
|
||||
|
||||
return User::where('name', 'like', '%' . $q . '%')
|
||||
->limit($limit)
|
||||
->orderBy('name')
|
||||
->get()
|
||||
->toJson();
|
||||
}
|
||||
}
|
||||
|
@ -16,6 +16,16 @@ class Controller extends BaseController
|
||||
{
|
||||
use AuthorizesRequests, DispatchesJobs, ValidatesRequests;
|
||||
|
||||
protected function authorizeAccessToAdminPanel()
|
||||
{
|
||||
// A user can access the admin panel if they are either an administrator, or are allowed to create albums
|
||||
// Further checks within the admin panel determine what a user can do within the panel
|
||||
if (!Auth::user()->can('admin-access') && !Auth::user()->can('admin-create-albums'))
|
||||
{
|
||||
App::abort(403);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets either the authenticated user, or a user object representing the anonymous user.
|
||||
* @return User
|
||||
|
@ -17,7 +17,7 @@ class AlbumController extends Controller
|
||||
{
|
||||
public function index(Request $request, $albumUrlAlias)
|
||||
{
|
||||
$album = DbHelper::loadAlbumByUrlAlias($albumUrlAlias);
|
||||
$album = DbHelper::getAlbumByAliasForCurrentUser($albumUrlAlias);
|
||||
if (is_null($album))
|
||||
{
|
||||
App::abort(404);
|
||||
|
@ -36,6 +36,10 @@ class AuthServiceProvider extends ServiceProvider
|
||||
{
|
||||
return $user->is_admin;
|
||||
});
|
||||
Gate::define('admin-create-albums', function ($user)
|
||||
{
|
||||
return $user->can_create_albums;
|
||||
});
|
||||
Gate::define('photo.download_original', function ($user, Photo $photo)
|
||||
{
|
||||
if (!UserConfig::get('restrict_original_download'))
|
||||
|
@ -15,7 +15,7 @@ class User extends Authenticatable
|
||||
* @var array
|
||||
*/
|
||||
protected $fillable = [
|
||||
'name', 'email', 'password', 'is_admin', 'is_activated', 'activation_token'
|
||||
'name', 'email', 'password', 'is_admin', 'is_activated', 'activation_token', 'can_create_albums'
|
||||
];
|
||||
|
||||
/**
|
||||
|
@ -18,6 +18,7 @@ class CreatePermissionsTable extends Migration
|
||||
$table->string('section');
|
||||
$table->string('description');
|
||||
$table->boolean('is_default');
|
||||
$table->integer('sort_order');
|
||||
|
||||
$table->timestamps();
|
||||
});
|
||||
|
@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
|
||||
class AddUserUploadFlag extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::table('users', function (Blueprint $table) {
|
||||
$table->boolean('can_create_albums')->default(0);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::table('users', function (Blueprint $table) {
|
||||
$table->dropColumn('can_create_albums');
|
||||
});
|
||||
}
|
||||
}
|
@ -15,14 +15,24 @@ class PermissionsSeeder extends Seeder
|
||||
DatabaseSeeder::createOrUpdate('permissions', [
|
||||
'section' => 'album',
|
||||
'description' => 'list-gallery',
|
||||
'is_default' => true
|
||||
'is_default' => true,
|
||||
'sort_order' => 0
|
||||
]);
|
||||
|
||||
// album:view = controls if the album can be viewed
|
||||
DatabaseSeeder::createOrUpdate('permissions', [
|
||||
'section' => 'album',
|
||||
'description' => 'view',
|
||||
'is_default' => true
|
||||
'is_default' => true,
|
||||
'sort_order' => 20
|
||||
]);
|
||||
|
||||
// album:edit = controls if the album is visible and can be edited in the admin panel
|
||||
DatabaseSeeder::createOrUpdate('permissions', [
|
||||
'section' => 'album',
|
||||
'description' => 'edit',
|
||||
'is_default' => true,
|
||||
'sort_order' => 10
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
@ -1,98 +0,0 @@
|
||||
<?php
|
||||
|
||||
/* START EXISTING LICENSE CHECK */
|
||||
/* For security reasons, don't allow use of this page if a license file already exists */
|
||||
$licenseFile = sprintf('%s/blue-twilight.lic', dirname(__DIR__));
|
||||
if (file_exists($licenseFile))
|
||||
{
|
||||
header('Location: index.php');
|
||||
exit();
|
||||
}
|
||||
/* END EXISTING LICENSE CHECK */
|
||||
|
||||
/* START LANGUAGE */
|
||||
$lang = 'en';
|
||||
if (isset($_GET['lang']))
|
||||
{
|
||||
$lang = trim(strtolower(stripslashes($_GET['lang'])));
|
||||
}
|
||||
|
||||
$langFile = sprintf('%s/raw/lang.%s.php', __DIR__, $lang);
|
||||
if (!file_exists($langFile))
|
||||
{
|
||||
$langFile = sprintf('%s/raw/lang.en.php', __DIR__);
|
||||
}
|
||||
|
||||
$lang = include $langFile;
|
||||
/* END LANGUAGE */
|
||||
|
||||
/* START UPLOAD PROCESSING */
|
||||
$uploadError = null;
|
||||
if (strtolower($_SERVER['REQUEST_METHOD']) == 'post' && isset($_FILES['upload-license-file']))
|
||||
{
|
||||
if ($_FILES['upload-license-file']['error'] != 0)
|
||||
{
|
||||
$uploadError = $lang['upload_errors'][$_FILES['upload-license-file']['error']];
|
||||
}
|
||||
elseif (!move_uploaded_file($_FILES['upload-license-file']['tmp_name'], $licenseFile))
|
||||
{
|
||||
$uploadError = $lang['upload_errors'][99];
|
||||
}
|
||||
else
|
||||
{
|
||||
header('Location: index.php');
|
||||
exit();
|
||||
}
|
||||
}
|
||||
/* END UPLOAD PROCESSING */
|
||||
|
||||
/* START LICENSE ERROR */
|
||||
$licenseError = null;
|
||||
if (isset($_GET['licerror']))
|
||||
{
|
||||
$licenseErrorNumber = intval($_GET['licerror']);
|
||||
|
||||
if (isset($lang['license_errors'][$licenseErrorNumber]))
|
||||
{
|
||||
$licenseError = $lang['license_errors'][$licenseErrorNumber];
|
||||
}
|
||||
else
|
||||
{
|
||||
$licenseError = $lang['license_errors'][99];
|
||||
}
|
||||
}
|
||||
/* END LICENSE ERROR */
|
||||
|
||||
ob_start();
|
||||
?>
|
||||
|
||||
<h1><?php echo $lang['license_required_title']; ?></h1>
|
||||
<p><?php echo $lang['license_required_p1']; ?></p>
|
||||
<p><?php echo str_replace(':host_name', sprintf('<b>%s</b>', $_SERVER['SERVER_NAME']), $lang['license_required_p2']); ?></p>
|
||||
<hr/>
|
||||
|
||||
<?php if (!is_null($uploadError)): ?>
|
||||
<div class="alert alert-danger">
|
||||
<p><?php echo $uploadError; ?></p>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
<?php if (!is_null($licenseError)): ?>
|
||||
<div class="alert alert-danger">
|
||||
<p><?php echo $licenseError; ?></p>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
<form action="license-required.php" method="post" enctype="multipart/form-data">
|
||||
<div class="form-group">
|
||||
<label class="control-label"><?php echo $lang['upload_license_label']; ?></label>
|
||||
<input type="file" name="upload-license-file"/>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<button class="btn btn-success" type="submit"><?php echo $lang['upload_action']; ?></button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<?php
|
||||
$content = ob_get_clean();
|
||||
require sprintf('%s/raw/layout.php', __DIR__);
|
||||
?>
|
@ -1,49 +0,0 @@
|
||||
<?php
|
||||
|
||||
/* START LOADER CHECK */
|
||||
/* For security reasons, don't allow use of this page if a loader is already installed */
|
||||
if (function_exists('sg_get_const'))
|
||||
{
|
||||
header('Location: index.php');
|
||||
exit();
|
||||
}
|
||||
/* END LOADER CHECK */
|
||||
|
||||
/* START PHPINFO REQUEST */
|
||||
if (isset($_GET['phpinfo']))
|
||||
{
|
||||
phpinfo();
|
||||
exit();
|
||||
}
|
||||
/* END PHPINFO REQUEST */
|
||||
|
||||
/* START LANGUAGE */
|
||||
$lang = 'en';
|
||||
if (isset($_GET['lang']))
|
||||
{
|
||||
$lang = trim(strtolower(stripslashes($_GET['lang'])));
|
||||
}
|
||||
|
||||
$langFile = sprintf('%s/raw/lang.%s.php', __DIR__, $lang);
|
||||
if (!file_exists($langFile))
|
||||
{
|
||||
$langFile = sprintf('%s/raw/lang.en.php', __DIR__);
|
||||
}
|
||||
|
||||
$lang = include $langFile;
|
||||
/* END LANGUAGE */
|
||||
|
||||
ob_start();
|
||||
?>
|
||||
|
||||
<h1><?php echo $lang['loader_required_title']; ?></h1>
|
||||
<p><?php echo $lang['loader_required_p1']; ?></p>
|
||||
<p><?php echo $lang['loader_required_p2']; ?></p>
|
||||
<?php $url = ((isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') ? "https" : "http") . "://$_SERVER[HTTP_HOST]$_SERVER[REQUEST_URI]?phpinfo=1"; ?>
|
||||
<p><b><a href="<?php echo $url; ?>" target="_blank"><?php echo $url ?></a></b></p>
|
||||
|
||||
<p style="margin-top: 30px;"><a class="btn btn-primary" href="javascript:window.location.reload();"><?php echo $lang['loader_required_retry']; ?></a></p>
|
||||
<?php
|
||||
$content = ob_get_clean();
|
||||
require sprintf('%s/raw/layout.php', __DIR__);
|
||||
?>
|
@ -1,36 +0,0 @@
|
||||
<?php
|
||||
return [
|
||||
'app_name' => 'Blue Twilight - Install',
|
||||
'copyright' => sprintf('© %s <a href="http://www.andyheathershaw.uk/" target="_blank">Andy Heathershaw</a>.', (date('Y') == 2016 ? 2016 : '2016-' . date('Y'))),
|
||||
'license_errors' => [
|
||||
1 => 'The application is not licensed to run on this machine or domain.',
|
||||
2 => 'The application is not licensed to run on this machine or domain.',
|
||||
3 => 'The application is not licensed to run on this machine or domain.',
|
||||
6 => 'The license file provided is invalid.',
|
||||
7 => 'This version of PHP is not supported. Please upgrade to a supported version of PHP or contact support.',
|
||||
9 => 'The application/license has expired.',
|
||||
13 => 'No license is currently available.',
|
||||
20 => 'The application requires an Internet connection that was not available.',
|
||||
99 => 'An unexpected error occurred, please contact support.'
|
||||
],
|
||||
'license_required_p1' => 'Blue Twilight requires a license to run correctly. You can generate and download a license file from the <a href="http://shop.andyheathershaw.uk/user/orders" target="_blank">My Orders</a> page.',
|
||||
'license_required_p2' => 'Your license file must match the hostname: :host_name.',
|
||||
'license_required_title' => 'License Required',
|
||||
'loader_required_p1' => 'Blue Twilight uses the Source Guardian source code protection system which requires a small "loader" to be installed on your system.',
|
||||
'loader_required_p2' => 'Please see <a href="https://www.sourceguardian.com/loaders.html" target="_blank">this web page</a> to download the loader for your system. You can use the "loader assistant" and provide the following URL for the PHP information:',
|
||||
'loader_required_retry' => 'Click here to retry',
|
||||
'loader_required_title' => 'Source Guardian Loader Required',
|
||||
'powered_by' => 'Powered by <a href="http://www.andyheathershaw.uk/blue-twilight" target="_blank">Blue Twilight</a> - the self-hosted photo gallery software.',
|
||||
'upload_action' => 'Upload',
|
||||
'upload_errors' => [
|
||||
1 => 'The uploaded file exceeds the upload_max_filesize directive in php.ini.',
|
||||
2 => 'The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form.',
|
||||
3 => 'The uploaded file was only partially uploaded.',
|
||||
4 => 'No file was uploaded.',
|
||||
6 => 'Missing a temporary folder.',
|
||||
7 => 'Failed to write file to disk.',
|
||||
8 => 'A PHP extension blocked the file upload - please contact your system administrator.',
|
||||
99 => 'Failed to write the license file - please check file permissions in Blue Twilight\'s root directory.'
|
||||
],
|
||||
'upload_license_label' => 'Please locate your license file to upload:'
|
||||
];
|
@ -1,60 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<meta name="generator" content="{{ config('app.name') }} v{{ config('app.version') }} (framework v{{ App::VERSION() }})">
|
||||
|
||||
<title><?php echo $lang['app_name']; ?></title>
|
||||
|
||||
<link href="themes/base/bootstrap/css/bootstrap.min.css" rel="stylesheet">
|
||||
<link href="themes/base/font-awesome/css/font-awesome.min.css" rel="stylesheet">
|
||||
<link href="themes/base/css/app.css" rel="stylesheet">
|
||||
<link href="themes/bootstrap3/theme.css" rel="stylesheet">
|
||||
</head>
|
||||
<body>
|
||||
<nav class="navbar navbar-inverse navbar-static-top">
|
||||
<div class="container">
|
||||
<!-- Brand and toggle get grouped for better mobile display -->
|
||||
<div class="navbar-header">
|
||||
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1" aria-expanded="false">
|
||||
<span class="sr-only">Toggle navigation</span>
|
||||
<span class="icon-bar"></span>
|
||||
<span class="icon-bar"></span>
|
||||
<span class="icon-bar"></span>
|
||||
</button>
|
||||
<a class="navbar-brand" href="index.php"><i class="fa fa-fw fa-photo"></i> <?php echo $lang['app_name']; ?></a>
|
||||
</div>
|
||||
|
||||
<!-- Collect the nav links, forms, and other content for toggling -->
|
||||
<div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
|
||||
<ul class="nav navbar-nav">
|
||||
</ul>
|
||||
</div><!-- /.navbar-collapse -->
|
||||
</div><!-- /.container-fluid -->
|
||||
</nav>
|
||||
|
||||
<div class="container-fluid">
|
||||
<div class="container">
|
||||
<?php echo $content; ?>
|
||||
</div>
|
||||
|
||||
<div class="container" style="margin-top: 40px;">
|
||||
<div class="row">
|
||||
<div class="col-xs-12">
|
||||
<hr/>
|
||||
<p style="font-size: smaller;">
|
||||
<b><?php echo $lang['powered_by']; ?></b><br/>
|
||||
<?php echo $lang['copyright']; ?>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script src="themes/base/js/jquery.min.js"></script>
|
||||
<script src="themes/base/bootstrap/js/bootstrap.min.js"></script>
|
||||
<script src="themes/base/js/app.js"></script>
|
||||
</body>
|
||||
</html>
|
@ -1,37 +0,0 @@
|
||||
<?php
|
||||
if (!function_exists('btw_license_error'))
|
||||
{
|
||||
function btw_license_error($code, $message)
|
||||
{
|
||||
// Remove an invalid license file - relevant to index.php as that's the main entry script
|
||||
$licenseFile = sprintf('%s/blue-twilight.lic', dirname(__DIR__));
|
||||
|
||||
if (file_exists($licenseFile))
|
||||
{
|
||||
$number = 0;
|
||||
do
|
||||
{
|
||||
$backupFilename = sprintf('%s_invalid.%d', $licenseFile, $number++);
|
||||
} while (file_exists($backupFilename));
|
||||
|
||||
// Rename or remove the invalid file
|
||||
if (!rename($licenseFile, $backupFilename))
|
||||
{
|
||||
@unlink($licenseFile);
|
||||
}
|
||||
}
|
||||
|
||||
header(sprintf('Location: license-required.php?licerror=%d', $code));
|
||||
exit();
|
||||
}
|
||||
}
|
||||
|
||||
if (!function_exists('btw_loader_error'))
|
||||
{
|
||||
function btw_loader_error()
|
||||
{
|
||||
header('Location: loader-required.php');
|
||||
exit();
|
||||
}
|
||||
}
|
||||
?>
|
4
public/themes/base/css/app.css
vendored
4
public/themes/base/css/app.css
vendored
@ -18,3 +18,7 @@
|
||||
.no-padding {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
span.twitter-typeahead {
|
||||
width: 100%;
|
||||
}
|
30
public/themes/base/css/typeahead.css
vendored
Normal file
30
public/themes/base/css/typeahead.css
vendored
Normal file
@ -0,0 +1,30 @@
|
||||
.tt-hint {
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.tt-menu {
|
||||
width: 422px;
|
||||
margin-top: 12px;
|
||||
padding: 8px 0;
|
||||
background-color: #fff;
|
||||
border: 1px solid #ccc;
|
||||
border: 1px solid rgba(0, 0, 0, 0.2);
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 5px 10px rgba(0,0,0,.2);
|
||||
}
|
||||
|
||||
.tt-suggestion {
|
||||
padding: 3px 20px;
|
||||
font-size: 18px;
|
||||
line-height: 24px;
|
||||
}
|
||||
|
||||
.tt-suggestion.tt-cursor {
|
||||
color: #fff;
|
||||
background-color: #0097cf;
|
||||
|
||||
}
|
||||
|
||||
.tt-suggestion p {
|
||||
margin: 0;
|
||||
}
|
@ -1,120 +0,0 @@
|
||||
<?php
|
||||
|
||||
define('PROJECT_ID', 'blue-twilight');
|
||||
define('PROJECT_KEY', 's7Ebes37ChACHeC8A8AzAXUswestuZ8v');
|
||||
define('LICENSE_FILE', 'blue-twilight.lic');
|
||||
|
||||
// Regex patterns of files we don't want to ship
|
||||
$ignoredFiles = [
|
||||
'.env*',
|
||||
'.git*',
|
||||
'.idea/*',
|
||||
'artisan',
|
||||
'build.php',
|
||||
'composer.phar',
|
||||
'gulpfile.js',
|
||||
'package.json',
|
||||
'phpunit.xml',
|
||||
'readme.md',
|
||||
'server.php',
|
||||
'storage/app/*',
|
||||
'storage/framework/*',
|
||||
'storage/logs/*',
|
||||
'tests/*'
|
||||
];
|
||||
|
||||
echo 'Blue Twilight Packaging Script' . PHP_EOL;
|
||||
echo '(c) Andy Heathershaw 2016-2017' . PHP_EOL;
|
||||
echo '------------------------------' . PHP_EOL . PHP_EOL;
|
||||
|
||||
if ($argc != 2)
|
||||
{
|
||||
echo sprintf('Usage: %s [version_number]', $argv[0]) . PHP_EOL . PHP_EOL;
|
||||
exit(1);
|
||||
}
|
||||
|
||||
echo 'Checking current folder...' . PHP_EOL . PHP_EOL;
|
||||
$appRoot = dirname(dirname(__DIR__));
|
||||
if (getcwd() != $appRoot)
|
||||
{
|
||||
echo sprintf('The build script must be run in the application root - %s', $appRoot) . PHP_EOL;
|
||||
exit();
|
||||
}
|
||||
|
||||
echo 'Updating app.version config value...' . PHP_EOL . PHP_EOL;
|
||||
$appConfigFile = sprintf('%s/config/app.php', $appRoot);
|
||||
file_put_contents($appConfigFile, str_replace('**DEV**', $argv[1], file_get_contents($appConfigFile)));
|
||||
|
||||
/*echo 'Downloading Composer...' . PHP_EOL . PHP_EOL;
|
||||
|
||||
copy('https://getcomposer.org/installer', 'composer-setup.php');
|
||||
if (hash_file('SHA384', 'composer-setup.php') === trim(file_get_contents('https://composer.github.io/installer.sig'))) { echo 'Installer verified'; } else { echo 'Installer corrupt'; unlink('composer-setup.php'); exit; } echo PHP_EOL;
|
||||
system('php composer-setup.php');
|
||||
unlink('composer-setup.php');
|
||||
|
||||
echo 'Installing dependencies using Composer...' . PHP_EOL . PHP_EOL;
|
||||
system('./composer.phar install');
|
||||
echo PHP_EOL;
|
||||
|
||||
echo 'Licensing and encoding the application using Source Guardian...' . PHP_EOL . PHP_EOL;
|
||||
$sgCommand = sprintf(
|
||||
'/usr/local/sourceguardian/bin/sourceguardian --phpversion "5.6" --phpversion "7.0" --external "%s" --projid "%s" --projkey "%s" ' .
|
||||
'--stop-on-error --strict-errors --deprec-errors -x "build.php" -x "*.blade.php" -x "vendor/*.php" -x "public/raw/*.php" ' .
|
||||
'-x public/license-required.php -x public/loader-required.php -x "storage/*" -r -b- ' .
|
||||
'-p @./public/raw/sg-license-error.php -j "<?php btw_loader_error(); ?>" --catch ERR_ALL="btw_license_error" "*.php"',
|
||||
LICENSE_FILE,
|
||||
PROJECT_ID,
|
||||
PROJECT_KEY
|
||||
);
|
||||
system($sgCommand);*/
|
||||
|
||||
echo 'Creating the release archive...' . PHP_EOL . PHP_EOL;
|
||||
|
||||
// Initialize archive object
|
||||
$zip = new ZipArchive();
|
||||
$zip->open(sprintf('%s/blue-twilight_%s.zip', dirname($appRoot), $argv[1]), ZipArchive::CREATE | ZipArchive::OVERWRITE);
|
||||
|
||||
/** @var SplFileInfo[] $files */
|
||||
$files = new RecursiveIteratorIterator(
|
||||
new RecursiveDirectoryIterator($appRoot),
|
||||
RecursiveIteratorIterator::LEAVES_ONLY
|
||||
);
|
||||
|
||||
foreach ($files as $name => $file)
|
||||
{
|
||||
// Skip directories (they will be added automatically) and unnecessary files
|
||||
if (!$file->isDir())
|
||||
{
|
||||
// Get real and relative path for current file
|
||||
$filePath = $file->getRealPath();
|
||||
$relativePath = substr($filePath, strlen($appRoot) + 1);
|
||||
|
||||
// See if the file matches any of ignore patterns
|
||||
$includeFile = true;
|
||||
if (
|
||||
strlen($relativePath) < strlen('vendor') ||
|
||||
substr($relativePath, 0, strlen('vendor')) != 'vendor'
|
||||
)
|
||||
{
|
||||
array_walk($ignoredFiles, function ($value) use ($relativePath, &$includeFile)
|
||||
{
|
||||
$includeFile &= !(preg_match('/^' . preg_quote($value, '/') . '$/', $relativePath));
|
||||
});
|
||||
}
|
||||
|
||||
// Add to the archive
|
||||
if ($includeFile)
|
||||
{
|
||||
$zip->addFile($filePath, sprintf('blue-twilight_%s/%s', $argv[1], $relativePath));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$zip->close();
|
||||
|
||||
echo PHP_EOL . PHP_EOL;
|
||||
echo 'All done!';
|
||||
echo PHP_EOL . PHP_EOL;
|
||||
exit();
|
||||
|
||||
?>
|
@ -7,6 +7,7 @@ return [
|
||||
'apply_action' => 'Apply',
|
||||
'bulk_edit_photos_label' => 'Bulk edit selected photos:',
|
||||
'bulk_edit_photos_placeholder' => 'Select an action',
|
||||
'can_create_albums_label' => 'User can create new albums',
|
||||
'cancel_action' => 'Cancel',
|
||||
'continue_action' => 'Continue',
|
||||
'create_action' => 'Create',
|
||||
|
@ -86,6 +86,13 @@
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div class="checkbox">
|
||||
<label>
|
||||
<input type="checkbox" name="can_create_albums">
|
||||
<strong>@lang('forms.can_create_albums_label')</strong>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div class="form-actions">
|
||||
<a href="{{ route('users.index') }}" class="btn btn-default">@lang('forms.cancel_action')</a>
|
||||
<button type="submit" class="btn btn-success"><i class="fa fa-fw fa-check"></i> @lang('forms.create_action')</button>
|
||||
|
@ -97,6 +97,13 @@
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div class="checkbox">
|
||||
<label>
|
||||
<input type="checkbox" name="can_create_albums"@if ($user->can_create_albums) checked="checked"@endif>
|
||||
<strong>@lang('forms.can_create_albums_label')</strong>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
@if (!$user->is_activated)
|
||||
<div class="checkbox">
|
||||
<label>
|
||||
|
@ -180,43 +180,35 @@
|
||||
@if (count($existing_groups) > 0)
|
||||
<div class="panel-group" id="groups-accordion" role="tablist" aria-multiselectable="true">
|
||||
@foreach ($existing_groups as $group)
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading" role="tab" id="heading-{{ $group->id }}">
|
||||
<h4 class="panel-title">
|
||||
<a class="collapsed" role="button" data-toggle="collapse" data-parent="#groups-accordion" href="#collapse-{{ $group->id }}" aria-expanded="true" aria-controls="collapse-{{ $group->id }}">
|
||||
{{ $group->name }}
|
||||
</a>
|
||||
</h4>
|
||||
</div>
|
||||
<div id="collapse-{{ $group->id }}" class="panel-collapse collapse" role="tabpanel" aria-labelledby="heading-{{ $group->id }}">
|
||||
<div class="panel-body">
|
||||
<p style="margin-bottom: 20px;"><a class="select-all" href="#">Select All</a> · <a class="select-none" href="">Select None</a></p>
|
||||
|
||||
@foreach ($all_permissions as $permission)
|
||||
<div class="checkbox">
|
||||
<label for="permission|{{ $group->id }}|{{ $permission->id }}">
|
||||
<input id="permission|{{ $group->id }}|{{ $permission->id }}" name="permissions[{{ $group->id }}][]" value="{{ $permission->id }}" type="checkbox"{{ $album->doesGroupHavePermission($group, $permission) ? ' checked="checked"' : '' }} /> {{ trans(sprintf('permissions.%s.%s', $permission->section, $permission->description)) }}
|
||||
</label>
|
||||
</div>
|
||||
@endforeach
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@include(Theme::viewName('partials.album_permissions'), [
|
||||
'key_id' => 'group_' . $group->id,
|
||||
'object_id' => $group->id,
|
||||
'title' => $group->name,
|
||||
'callback' => [$album, 'doesGroupHavePermission'],
|
||||
'callback_object' => $group,
|
||||
'parent_id' => 'groups-accordion'
|
||||
])
|
||||
@endforeach
|
||||
</div>
|
||||
@endif
|
||||
|
||||
<div class="form-group">
|
||||
<select class="form-control" name="group_id" style="width: auto; display: inline;"@if (count($add_new_groups) == 0) disabled="disabled"@endif>
|
||||
<div class="row">
|
||||
<div class="col-md-4">
|
||||
<select class="form-control" name="group_id" style="margin-bottom: 2px;"@if (count($add_new_groups) == 0) disabled="disabled"@endif>
|
||||
@foreach ($add_new_groups as $group)
|
||||
<option value="{{ $group->id }}">{{ $group->name }}</option>
|
||||
@endforeach
|
||||
</select>
|
||||
<button type="submit" name="action" value="add_group" class="btn btn-primary"@if (count($add_new_groups) == 0) disabled="disabled"@endif>Assign Permissions</button>
|
||||
<button type="submit" name="action" value="update_group_permissions" class="btn btn-success pull-right">
|
||||
</div>
|
||||
<div class="col-md-2">
|
||||
<button type="submit" name="action" value="add_group" class="btn btn-primary">Assign Permissions</button>
|
||||
</div>
|
||||
<div class="col-md-6 text-right">
|
||||
<button type="submit" name="action" value="update_group_permissions" class="btn btn-success">
|
||||
<i class="fa fa-fw fa-check"></i> @lang('forms.save_action')
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
<hr/>
|
||||
|
||||
@ -227,39 +219,41 @@
|
||||
|
||||
<div class="panel-group" id="users-accordion" role="tablist" aria-multiselectable="true">
|
||||
{{-- Anonymous users --}}
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading" role="tab" id="heading-anonymous">
|
||||
<h4 class="panel-title">
|
||||
<a class="collapsed" role="button" data-toggle="collapse" data-parent="#users-accordion" href="#collapse-anonymous" aria-expanded="true" aria-controls="collapse-anonymous">
|
||||
@lang('admin.anonymous_users')
|
||||
</a>
|
||||
</h4>
|
||||
</div>
|
||||
<div id="collapse-anonymous" class="panel-collapse collapse" role="tabpanel" aria-labelledby="heading-anonymous">
|
||||
<div class="panel-body">
|
||||
<p style="margin-bottom: 20px;"><a class="select-all" href="#">Select All</a> · <a class="select-none" href="">Select None</a></p>
|
||||
@include(Theme::viewName('partials.album_permissions'), [
|
||||
'key_id' => 'anonymous',
|
||||
'object_id' => 'anonymous',
|
||||
'title' => trans('admin.anonymous_users'),
|
||||
'callback' => [$album, 'doesUserHavePermission'],
|
||||
'callback_object' => null,
|
||||
'parent_id' => 'users-accordion'
|
||||
])
|
||||
|
||||
@foreach ($all_permissions as $permission)
|
||||
<div class="checkbox">
|
||||
<label for="permission|anonymous|{{ $permission->id }}">
|
||||
<input id="permission|anonymous|{{ $permission->id }}" name="permissions[anonymous][]" value="{{ $permission->id }}" type="checkbox"{{ $album->doesAnonymousHavePermission($permission) ? ' checked="checked"' : '' }} /> {{ trans(sprintf('permissions.%s.%s', $permission->section, $permission->description)) }}
|
||||
</label>
|
||||
</div>
|
||||
@foreach ($existing_users as $user)
|
||||
@include(Theme::viewName('partials.album_permissions'), [
|
||||
'key_id' => 'user_' . $user->id,
|
||||
'object_id' => $user->id,
|
||||
'title' => $user->name,
|
||||
'callback' => [$album, 'doesUserHavePermission'],
|
||||
'callback_object' => $user,
|
||||
'parent_id' => 'users-accordion'
|
||||
])
|
||||
@endforeach
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<input class="form-control" name="user_id" size="20" style="width: auto; display: inline;" />
|
||||
<div class="row">
|
||||
<div class="col-md-4">
|
||||
<input class="form-control" name="user_name" id="user-search-textbox" size="20" style="margin-bottom: 2px;" />
|
||||
<input type="hidden" name="user_id" id="user-id-field" />
|
||||
</div>
|
||||
<div class="col-md-2">
|
||||
<button type="submit" name="action" value="add_user" class="btn btn-primary">Assign Permissions</button>
|
||||
|
||||
<button type="submit" name="action" value="update_user_permissions" class="btn btn-success pull-right">
|
||||
</div>
|
||||
<div class="col-md-6 text-right">
|
||||
<button type="submit" name="action" value="update_user_permissions" class="btn btn-success">
|
||||
<i class="fa fa-fw fa-check"></i> @lang('forms.save_action')
|
||||
</button>
|
||||
</div>
|
||||
<div class="clearfix"><!-- --></div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
@ -455,6 +449,26 @@
|
||||
return false;
|
||||
});
|
||||
|
||||
{{-- Type-ahead support for users textbox on the permissions tab --}}
|
||||
var userDataSource = new Bloodhound({
|
||||
datumTokenizer: Bloodhound.tokenizers.obj.whitespace('value'),
|
||||
queryTokenizer: Bloodhound.tokenizers.whitespace,
|
||||
//prefetch: '../data/films/post_1960.json',
|
||||
remote: {
|
||||
url: '{{ route('users.searchJson') }}?q=%QUERY',
|
||||
wildcard: '%QUERY'
|
||||
}
|
||||
});
|
||||
|
||||
$('#user-search-textbox').typeahead(null, {
|
||||
name: 'user-search',
|
||||
display: 'name',
|
||||
source: userDataSource
|
||||
});
|
||||
$('#user-search-textbox').bind('typeahead:select', function(ev, suggestion) {
|
||||
$('#user-id-field').val(suggestion.id);
|
||||
});
|
||||
|
||||
// Bind the view models to the relevant tab
|
||||
ko.applyBindings(editViewModel, document.getElementById('photos-tab'));
|
||||
ko.applyBindings(viewModel, document.getElementById('upload-tab'));
|
||||
|
@ -15,6 +15,7 @@
|
||||
{{-- As these files are shipped with core (not a theme) use the main app.version instead of the current theme's version --}}
|
||||
<link href="themes/base/bootstrap/css/bootstrap.min.css?v={{ urlencode(config('app.version')) }}" rel="stylesheet">
|
||||
<link href="themes/base/font-awesome/css/font-awesome.min.css?v={{ urlencode(config('app.version')) }}" rel="stylesheet">
|
||||
<link href="themes/base/css/typeahead.css?v={{ urlencode(config('app.version')) }}" rel="stylesheet">
|
||||
<link href="themes/base/css/app.css?v={{ urlencode(config('app.version')) }}" rel="stylesheet">
|
||||
|
||||
@if (\App\Facade\Theme::hasStylesheet())
|
||||
@ -76,6 +77,7 @@
|
||||
<script src="themes/base/bootstrap/js/bootstrap.min.js?v={{ urlencode(config('app.version')) }}"></script>
|
||||
<script src="themes/base/js/bootbox.min.js?v={{ urlencode(config('app.version')) }}"></script>
|
||||
<script src="themes/base/js/knockout.min.js?v={{ urlencode(config('app.version')) }}"></script>
|
||||
<script src="themes/base/js/typeahead.bundle.js?v={{ urlencode(config('app.version')) }}"></script>
|
||||
<script src="themes/base/js/app.js?v={{ urlencode(config('app.version')) }}"></script>
|
||||
<script type="text/javascript">
|
||||
function _bt_showLoadingModal() {
|
||||
|
@ -3,10 +3,13 @@
|
||||
<div class="panel-body">
|
||||
<ul class="nav nav-pills">
|
||||
<li role="presentation"><a href="{{ route('albums.index') }}"><i class="fa fa-fw fa-picture-o"></i> @lang('navigation.breadcrumb.albums')</a></li>
|
||||
|
||||
@can('admin-access')
|
||||
<li role="presentation"><a href="{{ route('users.index') }}"><i class="fa fa-fw fa-user"></i> @lang('navigation.breadcrumb.users')</a></li>
|
||||
<li role="presentation"><a href="{{ route('groups.index') }}"><i class="fa fa-fw fa-users"></i> @lang('navigation.breadcrumb.groups')</a></li>
|
||||
<li role="presentation"><a href="{{ route('storage.index') }}"><i class="fa fa-fw fa-folder"></i> @lang('navigation.breadcrumb.storage')</a></li>
|
||||
<li role="presentation"><a href="{{ route('admin.settings') }}"><i class="fa fa-fw fa-cog"></i> @lang('navigation.breadcrumb.settings')</a></li>
|
||||
@endcan
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
@ -3,8 +3,11 @@
|
||||
<div class="panel-body">
|
||||
<p>
|
||||
<b>{{ $album_count }}</b> {{ trans_choice('admin.stats_widget.albums', $album_count) }}<br/>
|
||||
<b>{{ $photo_count }}</b> {{ trans_choice('admin.stats_widget.photos', $photo_count) }}<br/>
|
||||
<b>{{ $photo_count }}</b> {{ trans_choice('admin.stats_widget.photos', $photo_count) }}
|
||||
@can('admin-access')
|
||||
<br/>
|
||||
<b>{{ $user_count }}</b> {{ trans_choice('admin.stats_widget.users', $user_count) }} / <b>{{ $group_count }}</b> {{ trans_choice('admin.stats_widget.groups', $group_count) }}
|
||||
@endcan
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
@ -0,0 +1,20 @@
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading" role="tab" id="heading-{{ $key_id }}">
|
||||
<h4 class="panel-title">
|
||||
<a class="collapsed" role="button" data-toggle="collapse" data-parent="#{{ $parent_id }}" href="#collapse-{{ $key_id }}" aria-expanded="true" aria-controls="collapse-{{ $key_id }}">{{ $title }}</a>
|
||||
</h4>
|
||||
</div>
|
||||
<div id="collapse-{{ $key_id }}" class="panel-collapse collapse" role="tabpanel" aria-labelledby="heading-{{ $key_id }}">
|
||||
<div class="panel-body">
|
||||
<p style="margin-bottom: 20px;"><a class="select-all" href="#">Select All</a> · <a class="select-none" href="">Select None</a></p>
|
||||
|
||||
@foreach ($all_permissions as $permission)
|
||||
<div class="checkbox">
|
||||
<label for="permission|{{ $key_id }}|{{ $permission->id }}">
|
||||
<input id="permission|{{ $key_id }}|{{ $permission->id }}" name="permissions[{{ $object_id }}][]" value="{{ $permission->id }}" type="checkbox"{{ call_user_func($callback, $callback_object, $permission) ? ' checked="checked"' : '' }} /> {{ trans(sprintf('permissions.%s.%s', $permission->section, $permission->description)) }}
|
||||
</label>
|
||||
</div>
|
||||
@endforeach
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
@ -16,7 +16,6 @@
|
||||
])
|
||||
</p>
|
||||
<p style="font-size: smaller;">
|
||||
@lang('global.licensed_to', ['name' => $license_name, 'number' => $license_no])<br/>
|
||||
@lang('global.version_number', ['version' => config('app.version')])
|
||||
</p>
|
||||
</div>
|
||||
|
@ -25,9 +25,9 @@
|
||||
</li>
|
||||
@endif
|
||||
|
||||
@can('admin-access')
|
||||
@if (!Auth::guest() && (Auth::user()->can('admin-access') || Auth::user()->can('admin-create-albums')))
|
||||
<li><a href="{{ route('admin') }}"><i class="fa fa-fw fa-cog"></i> @lang('navigation.navbar.admin')</a></li>
|
||||
@endcan
|
||||
@endif
|
||||
</ul>
|
||||
|
||||
<ul class="nav navbar-nav navbar-right">
|
||||
|
@ -42,7 +42,7 @@ Route::group(['prefix' => 'admin'], function () {
|
||||
Route::get('albums/{id}/analyse/{queue_token}', 'Admin\AlbumController@analyse')->name('albums.analyse');
|
||||
Route::get('albums/{id}/delete', 'Admin\AlbumController@delete')->name('albums.delete');
|
||||
Route::post('albums/{id}/set-group-permissions', 'Admin\AlbumController@setGroupPermissions')->name('albums.set_group_permissions');
|
||||
Route::post('albums/{id}/set-user-permissions', 'Admin\AlbumController@setGroupPermissions')->name('albums.set_user_permissions');
|
||||
Route::post('albums/{id}/set-user-permissions', 'Admin\AlbumController@setUserPermissions')->name('albums.set_user_permissions');
|
||||
Route::resource('albums', 'Admin\AlbumController');
|
||||
|
||||
// Photo management
|
||||
@ -61,6 +61,7 @@ Route::group(['prefix' => 'admin'], function () {
|
||||
|
||||
// User management
|
||||
Route::get('users/{id}/delete', 'Admin\UserController@delete')->name('users.delete');
|
||||
Route::get('users.json', 'Admin\UserController@searchJson')->name('users.searchJson');
|
||||
Route::resource('users', 'Admin\UserController');
|
||||
|
||||
// Group management
|
||||
|
Loading…
Reference in New Issue
Block a user