This commit is contained in:
Richard Dern
2022-01-12 00:35:37 +01:00
commit 400e3d01f1
1363 changed files with 57778 additions and 0 deletions

View File

@@ -0,0 +1,24 @@
<?php
namespace App\Http\Controllers;
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
use Illuminate\Foundation\Bus\DispatchesJobs;
use Illuminate\Foundation\Validation\ValidatesRequests;
use Illuminate\Http\Request;
use Illuminate\Routing\Controller as BaseController;
use Illuminate\Support\Facades\Storage;
class Controller extends BaseController
{
use AuthorizesRequests;
use DispatchesJobs;
use ValidatesRequests;
public function s3resource(Request $request, $path)
{
return response(Storage::get($path), 200, [
'Content-Type' => Storage::mimeType($path)
]);
}
}

View File

@@ -0,0 +1,136 @@
<?php
namespace App\Http\Controllers;
use App\Http\Requests\Documents\StoreRequest;
use App\Models\Document;
use App\Models\Folder;
use App\Notifications\UnreadItemsChanged;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Notification;
use Storage;
class DocumentController extends Controller
{
public function __construct()
{
$this->authorizeResource(Document::class, 'document');
}
/**
* Store a newly created resource in storage.
*
* @param App\Http\Requests\Documents\StoreRequest $request
*
* @return \Illuminate\Http\Response
*/
public function store(StoreRequest $request)
{
$validated = $request->validated();
$user = $request->user();
$url = $validated['url'];
$folder = Folder::find($validated['folder_id']);
$document = Document::firstOrCreate(['url' => $url]);
$folder->documents()->save($document, [
'initial_url' => $url,
]);
return $folder->listDocuments($user);
}
/**
* Display the specified resource.
*
* @return \Illuminate\Http\Response
*/
public function show(Request $request, Document $document)
{
$user = $request->user();
$document->findDupplicatesFor($user);
$document->loadMissing('feeds')->loadCount(['feedItemStates' => function ($query) use ($user) {
$query->where('is_read', false)->where('user_id', $user->id);
}]);
if (Storage::exists($document->getStoragePath().'/meta.json')) {
$document->meta_data = \json_decode(Storage::get($document->getStoragePath().'/meta.json'));
}
if (Storage::exists($document->getStoragePath().'/response.json')) {
$document->response = \json_decode(Storage::get($document->getStoragePath().'/response.json'));
}
return $document;
}
/**
* Move document into specified folder.
*
* @param Folder $folder
*
* @return \Illuminate\Http\Response
*/
public function move(Request $request, Folder $sourceFolder, Folder $targetFolder)
{
$this->authorize('createBookmarkIn', $targetFolder);
$this->authorize('deleteBookmarkFrom', $sourceFolder);
$bookmarks = $sourceFolder->documents()->whereIn('documents.id', $request->input('documents'))->get();
foreach ($bookmarks as $bookmark) {
$sourceFolder->documents()->updateExistingPivot($bookmark->id, ['folder_id' => $targetFolder->id]);
}
$usersToNotify = $sourceFolder->group->activeUsers->merge($targetFolder->group->activeUsers);
Notification::send($usersToNotify, new UnreadItemsChanged([
'folders' => [
$sourceFolder->id,
$targetFolder->id,
],
]));
return $request->user()->countUnreadItems([
'folders' => [
$sourceFolder->id,
$targetFolder->id,
],
]);
}
/**
* Remove documents from specified folder.
*
* @return \Illuminate\Http\Response
*/
public function destroyBookmarks(Request $request, Folder $folder)
{
$this->authorize('deleteBookmarkFrom', $folder);
$user = $request->user();
$documents = $folder->documents()->whereIn('documents.id', $request->input('documents'))->get();
foreach ($documents as $document) {
$folder->documents()->detach($document);
}
Notification::send($folder->group->activeUsers()->get(), new UnreadItemsChanged(['folders' => [$folder]]));
return $folder->listDocuments($user);
}
/**
* Increment visits for specified document in specified folder.
*
* @return \Illuminate\Http\Response
*/
public function visit(Request $request, Document $document)
{
++$document->visits;
$document->save();
return $this->show($request, $document);
}
}

View File

@@ -0,0 +1,43 @@
<?php
namespace App\Http\Controllers;
use App\Models\Feed;
use App\Models\IgnoredFeed;
use Illuminate\Http\Request;
class FeedController extends Controller
{
/**
* Ignore specified feed.
*
* @return \Illuminate\Http\Response
*/
public function ignore(Request $request, Feed $feed)
{
$ignoredFeed = IgnoredFeed::where('user_id', $request->user()->id)->where('feed_id', $feed->id)->first();
if (!$ignoredFeed) {
$ignoredFeed = new IgnoredFeed();
$ignoredFeed->user()->associate($request->user());
$ignoredFeed->feed()->associate($feed);
$ignoredFeed->save();
}
}
/**
* Follow specified feed.
*
* @return \Illuminate\Http\Response
*/
public function follow(Request $request, Feed $feed)
{
$ignoredFeed = IgnoredFeed::where('user_id', $request->user()->id)->where('feed_id', $feed->id)->first();
if ($ignoredFeed) {
$ignoredFeed->delete();
}
}
}

View File

@@ -0,0 +1,81 @@
<?php
namespace App\Http\Controllers;
use App\Models\Feed;
use App\Models\FeedItem;
use Illuminate\Http\Request;
class FeedItemController extends Controller
{
/**
* Display a listing of the resource.
*
* @return \Illuminate\Http\Response
*/
public function index(Request $request)
{
$feedIds = $request->input('feeds', []);
if (empty($feedIds)) {
return [];
}
$user = $request->user();
$folder = $user->selectedFolder();
$queryBuilder = FeedItem::with('feeds:feeds.id,title', 'feeds.documents:documents.id')->inFeeds($feedIds);
$queryBuilder->select([
'feed_items.id',
'url',
'title',
'published_at',
'created_at',
'updated_at',
]);
if ($folder->type === 'unread_items') {
$queryBuilder->unreadFor($user);
}
return $queryBuilder->countStates($user)->orderBy('published_at', 'desc')->simplePaginate(15);
}
/**
* Display the specified resource.
*
* @return \Illuminate\Http\Response
*/
public function show(Request $request, FeedItem $feedItem)
{
$feedItem->loadCount(['feedItemStates' => function ($query) use ($request) {
$query->where('is_read', false)->where('user_id', $request->user()->id);
}]);
$feedItem->loadMissing('feeds');
return $feedItem;
}
/**
* Mark feed items as read.
*/
public function markAsRead(Request $request)
{
$user = $request->user();
if ($request->has('folders')) {
return $user->markFeedItemsReadInFolders($request->input('folders'));
}
if ($request->has('documents')) {
return $user->markFeedItemsReadInDocuments($request->input('documents'));
}
if ($request->has('feeds')) {
return $user->markFeedItemsReadInFeeds($request->input('feeds'));
}
if ($request->has('feed_items')) {
return $user->markFeedItemsRead($request->input('feed_items'));
}
}
}

View File

@@ -0,0 +1,253 @@
<?php
namespace App\Http\Controllers;
use App\Http\Requests\Folders\SetPermissionsRequest;
use App\Http\Requests\Folders\StoreRequest;
use App\Http\Requests\Folders\UpdateRequest;
use App\Models\Folder;
use App\Models\Group;
use App\Models\User;
use Illuminate\Http\Request;
class FolderController extends Controller
{
public function __construct()
{
$this->authorizeResource(Folder::class, 'folder');
}
/**
* Display a listing of the resource.
*
* @return \Illuminate\Http\Response
*/
public function index(Request $request)
{
$user = $request->user();
return $user->getFlatTree();
}
/**
* Store a newly created resource in storage.
*
* @param \App\Http\Requests\Folder\StoreRequest $request
*
* @return \Illuminate\Http\Response
*/
public function store(StoreRequest $request)
{
$validated = $request->validated();
$user = $request->user();
$parentFolder = Folder::find($validated['parent_id']);
$group = Group::find($validated['group_id']);
$user->createdFolders()->save(new Folder([
'title' => $validated['title'],
'parent_id' => $parentFolder->id,
'group_id' => $group->id,
]));
$user->setFolderExpandedState(true, $parentFolder);
return $user->getFlatTree($group);
}
/**
* Display the specified resource.
*
* @return \Illuminate\Http\Response
*/
public function show(Request $request, Folder $folder)
{
$user = $request->user();
$user->setSelectedFolder($folder);
return $folder->listDocuments($user);
}
/**
* Load every details of specified folder.
*
* @return \Illuminate\Http\Response
*/
public function details(Request $request, Folder $folder)
{
$user = $request->user();
if (!$user->can('view', $folder)) {
abort(404);
}
if ($folder->type === 'unread_items') {
$folder->feed_item_states_count = $folder->group->feedItemStatesCount;
} else {
$folder->user_permissions = $folder->getUserPermissions($user);
$folder->default_permissions = $folder->getDefaultPermissions();
$folder->loadCount(['feedItemStates' => function ($query) use ($user) {
$query->where('is_read', false)->where('user_id', $user->id);
}]);
$folder->group->loadCount('activeUsers');
}
return $folder;
}
/**
* Load per-user permissions for specified folder.
*
* @return \Illuminate\Http\Response
*/
public function perUserPermissions(Request $request, Folder $folder)
{
if (!$request->user()->can('setPermission', $folder)) {
abort(404);
}
$users = $folder->group->activeUsers()->whereNotIn('users.id', [$request->user()->id])
->whereHas('permissions', function ($query) use ($folder) {
$query->where('folder_id', $folder->id);
})
->with(['permissions'=> function ($query) use ($folder) {
$query->where('folder_id', $folder->id);
}])
->select(['users.id', 'users.name', 'users.email'])
->get();
return $users;
}
/**
* Load list of users with no expicit permissions for specified folder.
*
* @return \Illuminate\Http\Response
*/
public function usersWithoutPermissions(Request $request, Folder $folder)
{
if (!$request->user()->can('setPermission', $folder)) {
abort(404);
}
$users = $folder->group->activeUsers()->whereNotIn('users.id', [$request->user()->id])
->whereDoesntHave('permissions', function ($query) use ($folder) {
$query->where('folder_id', $folder->id);
})
->select(['users.id', 'users.name', 'users.email'])
->get();
return $users;
}
/**
* Update the specified resource in storage.
*
* @param App\Http\Requests\Folder\UpdateRequest $request
*
* @return \Illuminate\Http\Response
*/
public function update(UpdateRequest $request, Folder $folder)
{
$validated = $request->validated();
$user = $request->user();
if ($request->has('is_expanded')) {
$user->setFolderExpandedState($validated['is_expanded'], $folder);
}
$folder->title = $validated['title'];
$folder->parent_id = $validated['parent_id'];
if ($folder->isDirty()) {
$folder->save();
}
if (!empty($folder->parent_id)) {
$user->setFolderExpandedState(true, $folder->parent);
}
return $folder;
}
/**
* Remove the specified resource from storage.
*
* @return \Illuminate\Http\Response
*/
public function destroy(Request $request, Folder $folder)
{
$user = $request->user();
$user->setSelectedFolder(null, $folder->group);
$folder->delete();
return $user->getFlatTree();
}
/**
* Toggle expanded/collapsed a whole folder's branch.
*
* @return \Illuminate\Http\Response
*/
public function toggleBranch(Request $request, Folder $folder)
{
$user = $request->user();
$user->setFolderExpandedState(!$folder->is_expanded, $folder, $folder->group, true);
return $user->getFlatTree();
}
/**
* Set permissions for specified folder, optionally for specified user.
*
* @param App\Http\Requests\Folder\SetPermissionsRequest $request
*
* @return \Illuminate\Http\Response
*/
public function setPermission(SetPermissionsRequest $request, Folder $folder)
{
if (!$request->user()->can('setPermission', $folder)) {
abort(404);
}
$validated = $request->validated();
$ability = !empty($validated['ability']) ? $validated['ability'] : null;
$granted = !empty($validated['granted']) ? $validated['granted'] : false;
if (empty($validated['user_id'])) {
$folder->setDefaultPermission($ability, $granted);
return $this->details($request, $folder);
}
$user = $folder->group->activeUsers()->findOrFail($validated['user_id']);
$user->setFolderPermissions($folder, $ability, $granted);
return $this->perUserPermissions($request, $folder);
}
/**
* Remove permissions for specified user in specified folder.
*
* @param App\Http\Requests\Folder\SetPermissionsRequest $request
*
* @return \Illuminate\Http\Response
*/
public function removePermissions(Request $request, Folder $folder, User $user)
{
if (!$request->user()->can('setPermission', $folder)) {
abort(404);
}
$user->permissions()->where('folder_id', $folder->id)->delete();
return $this->perUserPermissions($request, $folder);
}
}

View File

@@ -0,0 +1,254 @@
<?php
namespace App\Http\Controllers;
use App\Http\Requests\Groups\InviteUserRequest;
use App\Http\Requests\Groups\StoreRequest;
use App\Http\Requests\Groups\UpdateRequest;
use App\Models\Group;
use App\Models\User;
use App\Notifications\AsksToJoinGroup;
use App\Notifications\InvitedToJoinGroup;
use Illuminate\Http\Request;
use Notification;
class GroupController extends Controller
{
public function __construct()
{
$this->authorizeResource(Group::class, 'group');
}
/**
* Display a listing of the resource.
*
* @return \Illuminate\Http\Response
*/
public function index(Request $request)
{
$user = $request->user();
$search = $request->input('search');
$query = Group::visible()
->whereNotIn('id', $user->groups->pluck('id'))
->with('creator:id,name')
->withCount('activeUsers');
if (!empty($search)) {
$query = $query->where('groups.name', 'like', '%'.$search.'%');
}
return $query
->orderBy('name')
->simplePaginate(25);
}
/**
* Display a listing of the resource (active groups).
*
* @return \Illuminate\Http\Response
*/
public function indexActive(Request $request)
{
$user = $request->user();
return $user->listActiveGroups();
}
/**
* Display a listing of the resource (my groups).
*
* @return \Illuminate\Http\Response
*/
public function indexMyGroups(Request $request)
{
$user = $request->user();
return $user->groups()->withCount('activeUsers', 'pendingUsers')
->whereNotIn('status', [
Group::$STATUS_REJECTED,
Group::$STATUS_LEFT,
])->orderBy('position')->orderBy('id')->get();
}
/**
* Store a newly created resource in storage.
*
* @param \App\Http\Requests\StoreRequest $request
*
* @return \Illuminate\Http\Response
*/
public function store(StoreRequest $request)
{
$validated = $request->validated();
$user = $request->user();
$validated['user_id'] = $user->id;
$group = Group::create($validated);
$user->groups()->save($group, [
'status' => 'created',
]);
return $user->groups()->withCount('activeUsers')->orderBy('position')->get();
}
/**
* Display the specified resource.
*
* @return \Illuminate\Http\Response
*/
public function show(Request $request, Group $group)
{
$user = $request->user();
$user->setSelectedGroup($group);
return $user->getFlatTree($group);
}
/**
* Update the specified resource in storage.
*
* @return \Illuminate\Http\Response
*/
public function update(UpdateRequest $request, Group $group)
{
$validated = $request->validated();
$group->name = $validated['name'];
$group->description = $validated['description'];
$group->invite_only = $validated['invite_only'];
$group->auto_accept_users = $validated['auto_accept_users'];
$group->save();
return $request->user()->groups()->withCount('activeUsers', 'pendingUsers')->find($group->id);
}
/**
* Remove the specified resource from storage.
*
* @return \Illuminate\Http\Response
*/
public function destroy(Request $request, Group $group)
{
$user = $request->user();
$group->delete();
return $user->groups()->withCount('activeUsers')->get();
}
/**
* Update my groups positions.
*
* @return \Illuminate\Http\Response
*/
public function updatePositions(Request $request)
{
if (!$request->has('positions')) {
abort(422);
}
$positions = $request->input('positions');
if (!is_array($positions)) {
abort(422);
}
$user = $request->user();
foreach ($positions as $groupId => $position) {
if (!is_numeric($groupId) || !is_numeric($position)) {
abort(422);
}
$group = $user->groups()->findOrFail($groupId);
$user->groups()->updateExistingPivot($group, ['position' => $position]);
}
return $user->groups()->withCount('activeUsers')->orderBy('position')->get();
}
/**
* Invite user to join specified group.
*
* @param \App\Requests\Groups\InviteUserRequest $request
*
* @return \Illuminate\Http\Response
*/
public function inviteUser(InviteUserRequest $request, Group $group)
{
$user = $request->user();
if (!$user->can('invite', $group)) {
abort(403);
}
$validated = $request->validated();
$invitedUser = User::where('email', $validated['email'])->first();
if ($invitedUser) {
$invitedUser->updateGroupStatus($group, Group::$STATUS_INVITED);
}
Notification::route('mail', $validated['email'])
->notify(new InvitedToJoinGroup($request->user(), $group));
return $request->user()->groups()->withCount('activeUsers', 'pendingUsers')->find($group->id);
}
public function acceptInvitation(Request $request, Group $group)
{
$user = $request->user();
$user->updateGroupStatus($group, Group::$STATUS_ACCEPTED);
if ($request->ajax()) {
return $user->groups()->withCount('activeUsers', 'pendingUsers')->find($group->id);
}
return redirect()->route('account.groups');
}
public function approveUser(Request $request, Group $group, User $user)
{
$creator = $request->user();
if (!$creator->can('approve', $group)) {
abort(403);
}
$user->updateGroupStatus($group, Group::$STATUS_ACCEPTED);
return redirect()->route('account.groups');
}
public function rejectInvitation(Request $request, Group $group)
{
$user = $request->user();
$user->updateGroupStatus($group, Group::$STATUS_REJECTED);
return $user->groups()->withCount('activeUsers', 'pendingUsers')->find($group->id);
}
public function leave(Request $request, Group $group)
{
$user = $request->user();
$user->groups()->detach($group);
}
public function join(Request $request, Group $group)
{
$user = $request->user();
if ($group->auto_accept_users) {
$user->updateGroupStatus($group, Group::$STATUS_ACCEPTED);
} else {
$user->updateGroupStatus($group, Group::$STATUS_JOINING);
Notification::route('mail', $group->creator->email)
->notify(new AsksToJoinGroup($request->user(), $group));
}
}
}

View File

@@ -0,0 +1,103 @@
<?php
namespace App\Http\Controllers;
use App\Http\Requests\StoreHighlightRequest;
use App\Models\Highlight;
use Illuminate\Http\Request;
class HighlightController extends Controller
{
/**
* Store a newly created resource in storage.
*
* @return \Illuminate\Http\Response
*/
public function store(StoreHighlightRequest $request)
{
$data = $request->validated();
$highlight = new Highlight();
$highlight->user_id = $request->user()->id;
$highlight->expression = $data['expression'];
$highlight->color = $data['color'];
$highlight->save();
return $request->user()->highlights()->get();
}
/**
* Update the specified resource in storage.
*
* @param \App\Models\Models\Highlight $highlight
*
* @return \Illuminate\Http\Response
*/
public function update(StoreHighlightRequest $request, Highlight $highlight)
{
if ($highlight->user_id !== $request->user()->id) {
abort(404);
}
$data = $request->validated();
$highlight->expression = $data['expression'];
$highlight->color = $data['color'];
$highlight->save();
return $request->user()->highlights()->get();
}
/**
* Remove the specified resource from storage.
*
* @param \App\Models\Models\Hightlight $hightlight
*
* @return \Illuminate\Http\Response
*/
public function destroy(Request $request, Highlight $highlight)
{
if ($highlight->user_id !== $request->user()->id) {
abort(404);
}
$highlight->delete();
return $request->user()->highlights()->get();
}
/**
* Update my groups positions.
*
* @return \Illuminate\Http\Response
*/
public function updatePositions(Request $request)
{
if (!$request->has('positions')) {
abort(422);
}
$positions = $request->input('positions');
if (!is_array($positions)) {
abort(422);
}
$user = $request->user();
foreach ($positions as $highlightId => $position) {
if (!is_numeric($highlightId) || !is_numeric($position)) {
abort(422);
}
$highlight = $user->highlights()->findOrFail($highlightId);
$highlight->position = $positions[$highlightId];
$highlight->save();
}
}
}

View File

@@ -0,0 +1,102 @@
<?php
namespace App\Http\Controllers;
use App\Services\Exporter;
use App\Services\Importer;
use Illuminate\Http\Request;
class HomeController extends Controller
{
/**
* Create a new controller instance.
*/
public function __construct()
{
$this->middleware('auth');
}
/**
* Show the application dashboard.
*
* @return \Illuminate\Http\Response
*/
public function index()
{
return view('home');
}
/**
* Show application's about page'.
*
* @return \Illuminate\Http\Response
*/
public function about()
{
return view('account.about');
}
/**
* Show user's account page.
*/
public function account()
{
return view('account.my_account');
}
/**
* Show user's password update page.
*/
public function password()
{
return view('account.password');
}
/**
* Manage user's highlights.
*/
public function highlights()
{
return view('account.highlights');
}
/**
* Show the import form.
*/
public function showImportForm()
{
return view('account.import');
}
/**
* Import a file.
*/
public function import(Request $request)
{
(new Importer())->fromRequest($request)->import();
return ['ok' => true];
}
/**
* Export user's data.
*/
public function export(Request $request)
{
$data = (new Exporter())->forUser($request->user())->export();
return response()->streamDownload(function () use ($data) {
echo json_encode($data);
}, sprintf('%s - Export.json', $request->user()->name), [
'Content-Type' => 'application/x-json',
]);
}
/**
* Manage groups.
*/
public function groups()
{
return view('account.groups');
}
}

68
app/Http/Kernel.php Executable file
View File

@@ -0,0 +1,68 @@
<?php
namespace App\Http;
use Illuminate\Foundation\Http\Kernel as HttpKernel;
class Kernel extends HttpKernel
{
/**
* The application's global HTTP middleware stack.
*
* These middleware are run during every request to your application.
*
* @var array
*/
protected $middleware = [
// \App\Http\Middleware\TrustHosts::class,
\App\Http\Middleware\TrustProxies::class,
\Fruitcake\Cors\HandleCors::class,
\App\Http\Middleware\CheckForMaintenanceMode::class,
\Illuminate\Foundation\Http\Middleware\ValidatePostSize::class,
\App\Http\Middleware\TrimStrings::class,
\Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class,
];
/**
* The application's route middleware groups.
*
* @var array
*/
protected $middlewareGroups = [
'web' => [
\App\Http\Middleware\EncryptCookies::class,
\Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
\Illuminate\Session\Middleware\StartSession::class,
// \Illuminate\Session\Middleware\AuthenticateSession::class,
\Illuminate\View\Middleware\ShareErrorsFromSession::class,
\App\Http\Middleware\VerifyCsrfToken::class,
\Illuminate\Routing\Middleware\SubstituteBindings::class,
\App\Http\Middleware\SetLang::class,
],
'api' => [
'throttle:60,1',
\Illuminate\Routing\Middleware\SubstituteBindings::class,
],
];
/**
* The application's route middleware.
*
* These middleware may be assigned to groups or used individually.
*
* @var array
*/
protected $routeMiddleware = [
'auth' => \App\Http\Middleware\Authenticate::class,
'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
'bindings' => \Illuminate\Routing\Middleware\SubstituteBindings::class,
'cache.headers' => \Illuminate\Http\Middleware\SetCacheHeaders::class,
'can' => \Illuminate\Auth\Middleware\Authorize::class,
'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
'password.confirm' => \Illuminate\Auth\Middleware\RequirePassword::class,
'signed' => \Illuminate\Routing\Middleware\ValidateSignature::class,
'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class,
];
}

View File

@@ -0,0 +1,22 @@
<?php
namespace App\Http\Middleware;
use Illuminate\Auth\Middleware\Authenticate as Middleware;
class Authenticate extends Middleware
{
/**
* Get the path the user should be redirected to when they are not authenticated.
*
* @param \Illuminate\Http\Request $request
*
* @return null|string
*/
protected function redirectTo($request)
{
if (!$request->expectsJson()) {
return route('login');
}
}
}

View File

@@ -0,0 +1,16 @@
<?php
namespace App\Http\Middleware;
use Illuminate\Foundation\Http\Middleware\CheckForMaintenanceMode as Middleware;
class CheckForMaintenanceMode extends Middleware
{
/**
* The URIs that should be reachable while maintenance mode is enabled.
*
* @var array
*/
protected $except = [
];
}

View File

@@ -0,0 +1,16 @@
<?php
namespace App\Http\Middleware;
use Illuminate\Cookie\Middleware\EncryptCookies as Middleware;
class EncryptCookies extends Middleware
{
/**
* The names of the cookies that should not be encrypted.
*
* @var array
*/
protected $except = [
];
}

View File

@@ -0,0 +1,17 @@
<?php
namespace App\Http\Middleware;
use Illuminate\Foundation\Http\Middleware\PreventRequestsDuringMaintenance as Middleware;
class PreventRequestsDuringMaintenance extends Middleware
{
/**
* The URIs that should be reachable while maintenance mode is enabled.
*
* @var array
*/
protected $except = [
//
];
}

View File

@@ -0,0 +1,26 @@
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Support\Facades\Auth;
class RedirectIfAuthenticated
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param null|string $guard
*
* @return mixed
*/
public function handle($request, Closure $next, $guard = null)
{
if (Auth::guard($guard)->check()) {
return redirect(route('home'));
}
return $next($request);
}
}

27
app/Http/Middleware/SetLang.php Executable file
View File

@@ -0,0 +1,27 @@
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
class SetLang
{
/**
* Handle an incoming request.
*
* @return mixed
*/
public function handle(Request $request, Closure $next)
{
$lang = config('app.locale');
if ($request->user()) {
$lang = $request->user()->lang;
}
app()->setLocale(trim($lang));
return $next($request);
}
}

View File

@@ -0,0 +1,18 @@
<?php
namespace App\Http\Middleware;
use Illuminate\Foundation\Http\Middleware\TrimStrings as Middleware;
class TrimStrings extends Middleware
{
/**
* The names of the attributes that should not be trimmed.
*
* @var array
*/
protected $except = [
'password',
'password_confirmation',
];
}

View File

@@ -0,0 +1,20 @@
<?php
namespace App\Http\Middleware;
use Illuminate\Http\Middleware\TrustHosts as Middleware;
class TrustHosts extends Middleware
{
/**
* Get the host patterns that should be trusted.
*
* @return array
*/
public function hosts()
{
return [
$this->allSubdomainsOfApplicationUrl(),
];
}
}

View File

@@ -0,0 +1,23 @@
<?php
namespace App\Http\Middleware;
use Fideloper\Proxy\TrustProxies as Middleware;
use Illuminate\Http\Request;
class TrustProxies extends Middleware
{
/**
* The trusted proxies for this application.
*
* @var null|array|string
*/
protected $proxies = '*';
/**
* The headers that should be used to detect proxies.
*
* @var int
*/
protected $headers = Request::HEADER_X_FORWARDED_ALL;
}

View File

@@ -0,0 +1,16 @@
<?php
namespace App\Http\Middleware;
use Illuminate\Foundation\Http\Middleware\VerifyCsrfToken as Middleware;
class VerifyCsrfToken extends Middleware
{
/**
* The URIs that should be excluded from CSRF verification.
*
* @var array
*/
protected $except = [
];
}

View File

@@ -0,0 +1,56 @@
<?php
namespace App\Http\Requests\Documents;
use App\Models\Folder;
use App\Models\Group;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Validation\Rule;
class StoreRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* @return bool
*/
public function authorize()
{
$folder = Folder::find($this->folder_id);
return $this->user()->can('createBookmarkIn', $folder);
}
/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function rules()
{
return [
'url' => [
'required',
'url',
],
'group_id' => [
'required',
Rule::exists(Group::class, 'id'),
],
'folder_id' => [
'required',
Rule::exists(Folder::class, 'id'),
],
];
}
/**
* Prepare the data for validation.
*/
protected function prepareForValidation()
{
$this->merge([
'url' => urldecode($this->url),
]);
}
}

View File

@@ -0,0 +1,48 @@
<?php
namespace App\Http\Requests\Folders;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Validation\Rule;
class SetPermissionsRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* @return bool
*/
public function authorize()
{
return $this->user()->can('setPermission', $this->folder);
}
/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function rules()
{
return [
'ability' => [
'nullable',
Rule::in([
'can_create_folder',
'can_update_folder',
'can_delete_folder',
'can_create_document',
'can_delete_document',
]),
],
'granted' => [
'nullable',
'boolean',
],
'user_id' => [
'nullable',
Rule::exists('users', 'id'),
],
];
}
}

View File

@@ -0,0 +1,51 @@
<?php
namespace App\Http\Requests\Folders;
use App\Models\Folder;
use App\Models\Group;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Validation\Rule;
class StoreRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* @return bool
*/
public function authorize()
{
$parentFolder = Folder::find($this->parent_id);
return $this->user()->can('createIn', $parentFolder);
}
/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function rules()
{
$groupId = $this->group_id;
return [
'title' => [
'required',
'max:255',
],
// Parent folder ID must exist and in the same group as requested
'parent_id' => [
'required',
Rule::exists(Folder::class, 'id')->where(function ($query) use ($groupId) {
$query->where('group_id', '=', $groupId);
}),
],
'group_id' => [
'required',
Rule::exists(Group::class, 'id'),
],
];
}
}

View File

@@ -0,0 +1,107 @@
<?php
namespace App\Http\Requests\Folders;
use App\Models\Folder;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Validation\Rule;
class UpdateRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* @return bool
*/
public function authorize()
{
if (empty($this->parent_id)) {
return 'root' === $this->folder->type;
}
$parent = Folder::find($this->parent_id);
return $this->user()->can('createIn', $parent) && $this->user()->can('update', $this->folder);
}
/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function rules()
{
$groupId = $this->group_id;
return [
'title' => [
'required',
'max:255',
],
'parent_id' => [
'nullable',
Rule::exists('App\Models\Folder', 'id')->where(function ($query) use ($groupId) {
$query->where('group_id', '=', $groupId);
}),
],
'group_id' => [
'required',
Rule::exists('App\Models\Group', 'id'),
],
'is_expanded' => [
'sometimes',
'boolean',
],
];
}
/**
* Configure the validator instance.
*
* @param \Illuminate\Validation\Validator $validator
*/
public function withValidator($validator)
{
$validator->after(function ($validator) {
if ($this->isMoving()) {
if ('folder' !== $this->folder->type) {
// Trying to move a "special" folder like root
$validator->errors()->add('parent_id', __('You cannot move this folder'));
} elseif ($this->targetParentIsDescendant()) {
$validator->errors()->add('parent_id', __('You cannot move this folder to a descendant'));
}
}
});
}
/**
* Return a boolean value indicating if we're moving a folder.
*
* @return bool
*/
private function isMoving()
{
return $this->parent_id !== $this->folder->parent_id;
}
/**
* Return a boolean value indicating if we're trying to move a folder into
* one of its descendants.
*
* @return bool
*/
private function targetParentIsDescendant()
{
$parent = Folder::find($this->parent_id);
while ($parent) {
if ($parent->id === $this->folder->id) {
return true;
}
$parent = $parent->parent;
}
return false;
}
}

View File

@@ -0,0 +1,33 @@
<?php
namespace App\Http\Requests\Groups;
use Illuminate\Foundation\Http\FormRequest;
class InviteUserRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* @return bool
*/
public function authorize()
{
return $this->user()->can('invite', $this->group);
}
/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function rules()
{
return [
'email' => [
'required',
'email',
],
];
}
}

View File

@@ -0,0 +1,41 @@
<?php
namespace App\Http\Requests\Groups;
use Illuminate\Foundation\Http\FormRequest;
class StoreRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* @return bool
*/
public function authorize()
{
return true;
}
/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function rules()
{
return [
'name' => [
'required',
],
'description' => [
'nullable',
],
'invite_only' => [
'boolean',
],
'auto_accept_users' => [
'boolean',
],
];
}
}

View File

@@ -0,0 +1,41 @@
<?php
namespace App\Http\Requests\Groups;
use Illuminate\Foundation\Http\FormRequest;
class UpdateRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* @return bool
*/
public function authorize()
{
return $this->user()->can('update', $this->group);
}
/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function rules()
{
return [
'name' => [
'required',
],
'description' => [
'nullable',
],
'invite_only' => [
'boolean',
],
'auto_accept_users' => [
'boolean',
],
];
}
}

View File

@@ -0,0 +1,36 @@
<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class StoreHighlightRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* @return bool
*/
public function authorize()
{
return true;
}
/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function rules()
{
return [
'expression' => [
'required',
],
'color' => [
'required',
'regex:/^#[0-9a-f]{3,6}$/i',
],
];
}
}