indexValidation($request); $per_page = $request->limit > 100 ? 10 : $request->limit; return $this->indexFiltering($business)->paginate($per_page); } public function indexValidation($request) { $bound = 10; $this->validate($request, [ 'filter.project_id' => [new MaxBound($bound)] , 'filter.user_id' => [new MaxBound($bound)] , ]); } public function indexFiltering($business) { $query = File::where('business_id', $business); $fileQ = QueryBuilder::for($query) ->allowedFilters([ AllowedFilter::exact('user_id'), AllowedFilter::exact('project_id'), AllowedFilter::exact('extension'), ]); if (\request('_business_info')['info']['users'][\auth()->id()]['level'] != enum('levels.owner.id')) { $requested_projects = isset(\request('filter')['project_id']) ? array_unique(explode(',',\request('filter')['project_id'] ?? null )) : null; $requested_projects = collect($requested_projects)->keyBy(null)->toArray(); $project_ids = $this->myStateProjects($requested_projects); $fileQ->where(function ($q) use ($project_ids) { $q->whereIn('project_id', $project_ids['non_guest_ids']) ->orWhere(function ($q) use ($project_ids) { $q->whereIn('project_id', $project_ids['guest_ids']) ->where('user_id', auth()->id()); }); }); } if (request()->filled('group')) { $fileQ->selectRaw("files.group, count(files.id) as file_count, sum(files.size) as file_size")->groupBy('group'); } return $fileQ; } public function myStateProjects($requested_projects) { $non_guest_ids = []; $guest_ids = []; $is_empty = empty($requested_projects); foreach (\request('_business_info')['info']['projects'] as $p_id => $p) { $level = \request('_business_info')['info']['projects'][$p_id]['members'][\auth()->id()]['level']; if (( $is_empty || isset($requested_projects[$p_id])) && $level > enum('levels.guest.id')) { array_push($non_guest_ids, $p_id); } if (( $is_empty || isset($requested_projects[$p_id])) && $level == enum('levels.guest.id')) { array_push($guest_ids, $p_id); } } return ['non_guest_ids' => $non_guest_ids, 'guest_ids' => $guest_ids]; } public function store(Request $request, int $business, int $project) { // different size and different validation // validate // validate the wallet is not so much in debt // create record in the db // put file in s3 // return file resource $business = Business::findOrFail($business); $project = Project::findOrFail($project); $this->validate($request, ['file' => 'required|file',]); $file = $request->file('file'); $file_extension = $file->getClientOriginalExtension(); $file_name = Str::random(40).'.'.$file_extension; $file->storeAs( $business->id.\DIRECTORY_SEPARATOR.$project->id, $file_name, 's3' ); $file_record = File::create([ 'user_id' => Auth::id(), 'business_id' => $business->id, 'project_id' => $project->id, 'disk' => 's3', // default disk 'original_name' => $file->getClientOriginalName(), 'extension' => $file_extension, 'name' => $file_name, 'mime' => $file->getClientMimeType(), 'group' => $this->groupDetection($file), 'size' => $file->getSize(), 'description' => $request->description ]); return new FileResource($file_record); } public function groupDetection(UploadedFile $file) { // Media files like mp4, mp3, wma and png or jpeg [$type, $subtype] = Str::of($file->getMimeType())->explode("/",2)->pad(2, null); if (in_array($type, ['audio', 'video', 'image'])) { return $type; } // Covert string to \Illuminate\Support\Stringable object $subtype = Str::of($subtype); // PDF files if ($subtype->contains(["pdf"])) { return "pdf"; } // Compressed files like zip, cab, rar, etc. if ($subtype->contains(['compressed']) || in_array($file->getClientOriginalExtension(), ['zip', 'rar','7z','cab'])) { return "compressed"; } // Office files like xls, xlsx, doc, docx, etc. if ($subtype->contains(['vnd.ms', 'vnd.sealed', 'officedocument', 'opendocument'])) { return "office"; } // Non of the above files return "other"; } public function download(int $business, int $project, int $file) { // requested file belongs to this project and this business // check permisson // create perma link or temp link // return the file resource or stream it return File::findOrFail($file)->getTemporaryLink(); } public function rename(Request $request, int $business, int $project, int $file) { // requested file belongs to this project and this business // check permisson // update original name // return the file resource // sanitize the name for slashs and back slashes $this->validate($request, [ 'name' => 'required|string' ]); $file = File::findOrFail($file); $file->update(['original_name' => $request->name.".".$file->extension]); return new FileResource($file); } public function delete(Request $request, int $business, int $project, int $file) { // requested file belongs to this project and this business // check permisson // check it's relations // delete the file form File table // delete file from s3 $file = File::findOrFail($file); Storage::disk('s3')->delete($file->getPath()); return $file->delete(); } }