초기 셋팅

master
barunsoft 2 years ago
commit b6c73dfd40

@ -0,0 +1,18 @@
root = true
[*]
charset = utf-8
end_of_line = lf
insert_final_newline = true
indent_style = space
indent_size = 4
trim_trailing_whitespace = true
[*.md]
trim_trailing_whitespace = false
[*.{yml,yaml}]
indent_size = 2
[docker-compose.yml]
indent_size = 4

@ -0,0 +1,52 @@
APP_NAME=Laravel
APP_ENV=local
APP_KEY=
APP_DEBUG=true
APP_URL=http://localhost
LOG_CHANNEL=stack
LOG_DEPRECATIONS_CHANNEL=null
LOG_LEVEL=debug
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=laravel
DB_USERNAME=root
DB_PASSWORD=
BROADCAST_DRIVER=log
CACHE_DRIVER=file
FILESYSTEM_DRIVER=local
QUEUE_CONNECTION=sync
SESSION_DRIVER=file
SESSION_LIFETIME=120
MEMCACHED_HOST=127.0.0.1
REDIS_HOST=127.0.0.1
REDIS_PASSWORD=null
REDIS_PORT=6379
MAIL_MAILER=smtp
MAIL_HOST=mailhog
MAIL_PORT=1025
MAIL_USERNAME=null
MAIL_PASSWORD=null
MAIL_ENCRYPTION=null
MAIL_FROM_ADDRESS=null
MAIL_FROM_NAME="${APP_NAME}"
AWS_ACCESS_KEY_ID=
AWS_SECRET_ACCESS_KEY=
AWS_DEFAULT_REGION=us-east-1
AWS_BUCKET=
AWS_USE_PATH_STYLE_ENDPOINT=false
PUSHER_APP_ID=
PUSHER_APP_KEY=
PUSHER_APP_SECRET=
PUSHER_APP_CLUSTER=mt1
MIX_PUSHER_APP_KEY="${PUSHER_APP_KEY}"
MIX_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}"

10
.gitattributes vendored

@ -0,0 +1,10 @@
* text=auto
*.blade.php diff=html
*.css diff=css
*.html diff=html
*.md diff=markdown
*.php diff=php
/.github export-ignore
CHANGELOG.md export-ignore

25
.gitignore vendored

@ -0,0 +1,25 @@
/node_modules
/public/hot
/public/storage
/storage/*.key
/storage
/vendor
/bootstrap
.env
.env.backup
.idea
.phpunit.result.cache
docker-compose.override.yml
Homestead.json
Homestead.yaml
npm-debug.log
yarn-error.log
/.idea
/.vscode
composer.lock
yarn.lock
.env.loc
.env.dev
laravel-echo-server.lo*
composer.lock
public/mix-manifest.json

@ -0,0 +1,14 @@
php:
preset: laravel
version: 8
disabled:
- no_unused_imports
finder:
not-name:
- index.php
- server.php
js:
finder:
not-name:
- webpack.mix.js
css: true

@ -0,0 +1,64 @@
<p align="center"><a href="https://laravel.com" target="_blank"><img src="https://raw.githubusercontent.com/laravel/art/master/logo-lockup/5%20SVG/2%20CMYK/1%20Full%20Color/laravel-logolockup-cmyk-red.svg" width="400"></a></p>
<p align="center">
<a href="https://travis-ci.org/laravel/framework"><img src="https://travis-ci.org/laravel/framework.svg" alt="Build Status"></a>
<a href="https://packagist.org/packages/laravel/framework"><img src="https://img.shields.io/packagist/dt/laravel/framework" alt="Total Downloads"></a>
<a href="https://packagist.org/packages/laravel/framework"><img src="https://img.shields.io/packagist/v/laravel/framework" alt="Latest Stable Version"></a>
<a href="https://packagist.org/packages/laravel/framework"><img src="https://img.shields.io/packagist/l/laravel/framework" alt="License"></a>
</p>
## About Laravel
Laravel is a web application framework with expressive, elegant syntax. We believe development must be an enjoyable and creative experience to be truly fulfilling. Laravel takes the pain out of development by easing common tasks used in many web projects, such as:
- [Simple, fast routing engine](https://laravel.com/docs/routing).
- [Powerful dependency injection container](https://laravel.com/docs/container).
- Multiple back-ends for [session](https://laravel.com/docs/session) and [cache](https://laravel.com/docs/cache) storage.
- Expressive, intuitive [database ORM](https://laravel.com/docs/eloquent).
- Database agnostic [schema migrations](https://laravel.com/docs/migrations).
- [Robust background job processing](https://laravel.com/docs/queues).
- [Real-time event broadcasting](https://laravel.com/docs/broadcasting).
Laravel is accessible, powerful, and provides tools required for large, robust applications.
## Learning Laravel
Laravel has the most extensive and thorough [documentation](https://laravel.com/docs) and video tutorial library of all modern web application frameworks, making it a breeze to get started with the framework.
If you don't feel like reading, [Laracasts](https://laracasts.com) can help. Laracasts contains over 1500 video tutorials on a range of topics including Laravel, modern PHP, unit testing, and JavaScript. Boost your skills by digging into our comprehensive video library.
## Laravel Sponsors
We would like to extend our thanks to the following sponsors for funding Laravel development. If you are interested in becoming a sponsor, please visit the Laravel [Patreon page](https://patreon.com/taylorotwell).
### Premium Partners
- **[Vehikl](https://vehikl.com/)**
- **[Tighten Co.](https://tighten.co)**
- **[Kirschbaum Development Group](https://kirschbaumdevelopment.com)**
- **[64 Robots](https://64robots.com)**
- **[Cubet Techno Labs](https://cubettech.com)**
- **[Cyber-Duck](https://cyber-duck.co.uk)**
- **[Many](https://www.many.co.uk)**
- **[Webdock, Fast VPS Hosting](https://www.webdock.io/en)**
- **[DevSquad](https://devsquad.com)**
- **[Curotec](https://www.curotec.com/services/technologies/laravel/)**
- **[OP.GG](https://op.gg)**
- **[WebReinvent](https://webreinvent.com/?utm_source=laravel&utm_medium=github&utm_campaign=patreon-sponsors)**
- **[Lendio](https://lendio.com)**
## Contributing
Thank you for considering contributing to the Laravel framework! The contribution guide can be found in the [Laravel documentation](https://laravel.com/docs/contributions).
## Code of Conduct
In order to ensure that the Laravel community is welcoming to all, please review and abide by the [Code of Conduct](https://laravel.com/docs/contributions#code-of-conduct).
## Security Vulnerabilities
If you discover a security vulnerability within Laravel, please send an e-mail to Taylor Otwell via [taylor@laravel.com](mailto:taylor@laravel.com). All security vulnerabilities will be promptly addressed.
## License
The Laravel framework is open-sourced software licensed under the [MIT license](https://opensource.org/licenses/MIT).

@ -0,0 +1,55 @@
<?php
namespace App\Casts;
use Illuminate\Contracts\Database\Eloquent\CastsAttributes;
use Illuminate\Support\Facades\Crypt;
class EncryptArray implements CastsAttributes
{
/**
* Cast the given value.
*
* @param \Illuminate\Database\Eloquent\Model $model
* @param string $key
* @param mixed $value
* @param array $attributes
* @return mixed
*/
public function get($model, string $key, $value, array $attributes)
{
if ($value !== '' && !is_null($value)) {
try {
$decryptValue = Crypt::decryptString($value);
$value = json_decode($decryptValue, true);
} catch (\Exception $e) {
$value = null;
}
}
return $value;
}
/**
* Prepare the given value for storage.
*
* @param \Illuminate\Database\Eloquent\Model $model
* @param string $key
* @param mixed $value
* @param array $attributes
* @return mixed
*/
public function set($model, string $key, $value, array $attributes)
{
if ($value !== '' && !is_null($value)) {
$jsonValue = json_encode($value);
try {
$value = Crypt::encryptString($jsonValue);
} catch (\Exception $e) {
logger($e->getTraceAsString());
}
}
return $value;
}
}

@ -0,0 +1,65 @@
<?php
namespace App\Casts;
use Illuminate\Contracts\Database\Eloquent\CastsAttributes;
class EncryptFixed implements CastsAttributes
{
// 암호값을 고정하기 위함
private $iv = 'FIXED_ENCRYPT_ST';
/**
* Cast the given value.
*
* @param \Illuminate\Database\Eloquent\Model $model
* @param string $key
* @param mixed $value
* @param array $attributes
* @return mixed
*/
public function get($model, string $key, $value, array $attributes)
{
if ($value !== '' && !is_null($value)) {
try {
$value = $this->decrypt($value);
} catch (\Exception $e) {
$value = null;
}
}
return $value;
}
/**
* Prepare the given value for storage.
*
* @param \Illuminate\Database\Eloquent\Model $model
* @param string $key
* @param mixed $value
* @param array $attributes
* @return mixed
*/
public function set($model, string $key, $value, array $attributes)
{
if ($value !== '' && !is_null($value)) {
try {
$value = $this->encrypt($value);
} catch (\Exception $e) {
logger($e->getTraceAsString());
}
}
return $value;
}
public function encrypt($value)
{
return base64_encode(openssl_encrypt($value, "AES-256-CBC", config('app.key'), 0, $this->iv));
}
public function decrypt($value)
{
return openssl_decrypt(base64_decode($value), "AES-256-CBC", config('app.key'), 0, $this->iv);
}
}

@ -0,0 +1,53 @@
<?php
namespace App\Casts;
use Illuminate\Contracts\Database\Eloquent\CastsAttributes;
use Illuminate\Support\Facades\Crypt;
class EncryptString implements CastsAttributes
{
/**
* Cast the given value.
*
* @param \Illuminate\Database\Eloquent\Model $model
* @param string $key
* @param mixed $value
* @param array $attributes
* @return mixed
*/
public function get($model, string $key, $value, array $attributes)
{
if ($value !== '' && !is_null($value)) {
try {
$value = Crypt::decryptString($value);
} catch (\Exception $e) {
$value = null;
}
}
return $value;
}
/**
* Prepare the given value for storage.
*
* @param \Illuminate\Database\Eloquent\Model $model
* @param string $key
* @param mixed $value
* @param array $attributes
* @return mixed
*/
public function set($model, string $key, $value, array $attributes)
{
if ($value !== '' && !is_null($value)) {
try {
$value = Crypt::encryptString($value);
} catch (\Exception $e) {
logger($e->getTraceAsString());
}
}
return $value;
}
}

@ -0,0 +1,32 @@
<?php
namespace App\Console;
use Illuminate\Console\Scheduling\Schedule;
use Illuminate\Foundation\Console\Kernel as ConsoleKernel;
class Kernel extends ConsoleKernel
{
/**
* Define the application's command schedule.
*
* @param \Illuminate\Console\Scheduling\Schedule $schedule
* @return void
*/
protected function schedule(Schedule $schedule)
{
// $schedule->command('inspire')->hourly();
}
/**
* Register the commands for the application.
*
* @return void
*/
protected function commands()
{
$this->load(__DIR__.'/Commands');
require base_path('routes/console.php');
}
}

@ -0,0 +1,217 @@
<?php
namespace App\Exceptions;
use Exception;
use Illuminate\Auth\Access\AuthorizationException;
use Illuminate\Auth\AuthenticationException;
use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
use Illuminate\Session\TokenMismatchException;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Str;
use Illuminate\Validation\ValidationException;
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
use Symfony\Component\HttpKernel\Exception\UnauthorizedHttpException;
use Throwable;
class Handler extends ExceptionHandler
{
/**
* A list of the exception types that are not reported.
*
* @var array<int, class-string<Throwable>>
*/
protected $dontReport = [
//
];
/**
* A list of the inputs that are never flashed for validation exceptions.
*
* @var array<int, string>
*/
protected $dontFlash = [
'current_password',
'password',
'password_confirmation',
];
/**
* Register the exception handling callbacks for the application.
*
* @return void
*/
public function register()
{
$this->reportable(function (Throwable $e) {
//
});
}
/**
* Report or log an exception.
*
* @param Throwable $e
* @return void
* @throws Throwable
*/
/*
public function report(Throwable $e)
{
if (app()->bound('sentry') && $this->shouldReport($e)) {
app('sentry')->captureException($e);
}
parent::report($e);
}
*/
/**
* Render an exception into an HTTP response.
*
* @param Request $request
* @param Throwable $exception
* @return JsonResponse|Response
* @throws Throwable
*/
/*
public function render($request, Throwable $exception)
{
DB::rollBack();
logger($exception);
if ($request->ajax() || $request->wantsJson() || $request->expectsJson()) {
$response = $this->errorJson($exception);
if ($response !== false) {
return $response;
}
}
$errorCode = 500;
if (method_exists($exception, 'getStatusCode')) {
$errorCode = $exception->getStatusCode();
}
$data = [
'breadcrumbs'=>[],
'pageheader'=>[
'code' => 'exception',
'title' => 'Exception',
'icon' => 'fa-exclamation-triangle',
'description' => '',
'link' => ''
],
'errorCode' => $errorCode,
'exception' => $exception
];
return response()->view('errors', $data, $errorCode);
}
*/
/**
* Render an exception into an HTTP response.
*
* @param Throwable $exception
* @return bool|JsonResponse
* @throws Throwable
*/
private function errorJson(Eexception $exception) {
$errorCode = 500;
if (method_exists($exception, 'getStatusCode')) {
$errorCode = $exception->getStatusCode();
}
if ($errorCode == 503) {
$messageText = "서버 점검중입니다.";
$result = [
"status" => $errorCode,
"message" => $messageText,
"success" => false,
"data" => null,
"errors" => [ "message" => [ $messageText ] ]
];
$headers = [];
return response()->json($result, $errorCode, $headers, JSON_UNESCAPED_UNICODE);
}
if ($exception instanceof UnauthorizedHttpException || $exception instanceof AuthenticationException || $exception instanceof AuthorizationException) {
$errorCode = 401;
$result = [
"status" => $errorCode,
"message" => "인증정보가 없습니다.",
"success" => false,
"data" => null,
"errors" => [ "message" => [ $exception->getMessage() ] ]
];
logger($result);
$headers = [];
return response()->json($result, $errorCode, $headers, JSON_UNESCAPED_UNICODE);
} else if ($exception instanceof ValidationException ) {
$result = [
"status" => $errorCode,
"message" => "유효성 검사가 실패했습니다.",
"success" => false,
"data" => null,
"errors" => $exception->validator->messages()->messages()
];
logger($result);
$headers = [];
return response()->json($result, $errorCode, $headers, JSON_UNESCAPED_UNICODE);
} else if ($exception instanceof AccessDeniedHttpException) {
$result = [
"status" => $errorCode,
"message" => "접근권한이 없습니다.",
"success" => false,
"data" => null,
"errors" => [ "message" => [ 'AccessDenied' ] ]
];
logger($result);
$headers = [];
return response()->json($result, $errorCode, $headers, JSON_UNESCAPED_UNICODE);
} else if ($exception instanceof TokenMismatchException) {
$errorCode = 419;
$result = [
"status" => $errorCode,
"message" => "인증토근이 일치하지 않습니다.",
"success" => false,
"data" => null,
"errors" => [ "message" => [ 'CSRF Token Mismatch' ] ]
];
logger($result);
$headers = [];
return response()->json($result, $errorCode, $headers, JSON_UNESCAPED_UNICODE);
} else if ($exception instanceof Exception) {
$message = $exception->getMessage();
if (!$message) {
$message = sprintf("[%d] 서버 에러", $errorCode);
}
$result = [
"status" => $errorCode,
"message" => "서버 에러",
"success" => false,
"data" => null,
"errors" => ["message" => [$message]]
];
logger($result);
if(!$exception->getMessage() || $errorCode != 404) {
logger($exception->getFile(). " : " . $exception->getLine());
logger($exception->getTraceAsString());
}
$headers = [];
return response()->json($result, $errorCode, $headers, JSON_UNESCAPED_UNICODE);
}
return false;
}
}

@ -0,0 +1,19 @@
<?php
namespace App\Exports;
use Maatwebsite\Excel\Concerns\FromArray;
class ArrayExport implements FromArray
{
protected $data;
public function __construct(array $data)
{
$this->data = $data;
}
public function array(): array
{
return $this->data;
}
}

@ -0,0 +1,410 @@
<?php
use Illuminate\Http\UploadedFile;
use Illuminate\Support\Facades\File;
use Illuminate\Support\Str;
use Jenssegers\Agent\Agent;
function human_distance($distance)
{
$distanceText = number_format($distance, 2) . 'm';
if($distance > 1000) $distanceText = number_format(round($distance / 1000, 2), 2) . 'Km';
return $distanceText;
}
function human_filesize($bytes, $decimals = 2)
{
if ($bytes == 0) return $bytes;
$s = ['B', 'KB', 'MB', 'GB', 'TB', 'PB'];
if ($bytes) {
$e = floor(log($bytes) / log(1024));
return sprintf("%.{$decimals}f ".$s[$e], ($bytes/pow(1024, floor($e))));
} else {
return 0;
}
}
function filesize_mb($bytes)
{
return $bytes / pow(1024, 2);
}
function removeHyphen($phone) {
return trim(str_replace("-", "", $phone));
}
function filterPhone($phone) {
$search = ["-", "#", "+", ".", ",", " ", "(", ")"];
$phone = str_replace($search, "", $phone);
return trim($phone);
}
function trimSignoutText($text) {
$trext = preg_replace("/#[0-9]+/", "", $text);
return trim($trext);
}
function formatPhone($phone) {
$phone = preg_replace("/[^0-9]/", "", $phone);
$length = strlen($phone);
switch($length){
case 11 :
return preg_replace("/([0-9]{3})([0-9]{4})([0-9]{4})/", "$1-$2-$3", $phone);
break;
case 10:
return preg_replace("/([0-9]{3})([0-9]{3})([0-9]{4})/", "$1-$2-$3", $phone);
break;
case 9:
return preg_replace("/([0-9]{2})([0-9]{3})([0-9]{4})/", "$1-$2-$3", $phone);
break;
default :
return $phone;
break;
}
}
/**
* Create a Random String
*
* Useful for generating passwords or hashes.
*
* @param integer number of characters
* @param string type of random string. basic/alpha/alunum/numeric/nozero/unique/md5/encrypt/sha1
* @return string
*/
function randomString($len = 10, $type = 'alnum') {
$str = '';
switch ($type) {
case 'basic' :
$str = mt_rand();
break;
case 'alnum' :
case 'numeric' :
case 'nozero' :
case 'alpha' :
case 'allowernum' :
case 'aluppernum' :
switch ($type) {
case 'alpha' :
$pool = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
break;
case 'alnum' :
$pool = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
break;
case 'allowernum' :
$pool = '0123456789abcdefghijklmnopqrstuvwxyz';
break;
case 'aluppernum' :
$pool = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ';
break;
case 'numeric' :
$pool = '0123456789';
break;
case 'nozero' :
$pool = '123456789';
break;
}
for ($i = 0; $i < $len; $i++) {
$str .= substr($pool, mt_rand(0, strlen($pool) -1), 1);
}
break;
case 'unique' :
case 'md5' :
$str = md5(uniqid(mt_rand()));
break;
case 'encrypt' :
case 'sha1' :
$str = sha1(uniqid(mt_rand(), true));
break;
default :
$str = mt_rand();
}
return $str;
}
/**
* Calculates the great-circle distance between two points, with
* the Haversine formula.
* @param float $latitudeFrom Latitude of start point in [deg decimal]
* @param float $longitudeFrom Longitude of start point in [deg decimal]
* @param float $latitudeTo Latitude of target point in [deg decimal]
* @param float $longitudeTo Longitude of target point in [deg decimal]
* @param float $earthRadius Mean earth radius in [m]
* @return float Distance between points in [m] (same as earthRadius)
*/
function distance($latitudeFrom, $longitudeFrom, $latitudeTo, $longitudeTo, $earthRadius = 6371000)
{
// convert from degrees to radians
$latFrom = deg2rad($latitudeFrom);
$lonFrom = deg2rad($longitudeFrom);
$latTo = deg2rad($latitudeTo);
$lonTo = deg2rad($longitudeTo);
$latDelta = $latTo - $latFrom;
$lonDelta = $lonTo - $lonFrom;
$angle = 2 * asin(sqrt(pow(sin($latDelta / 2), 2) +
cos($latFrom) * cos($latTo) * pow(sin($lonDelta / 2), 2)));
return $angle * $earthRadius;
}
function dateAgo($time) {
if (!$time) {
return '방금';
}
$stat = ' 전';
if ($time < 0) {
$time *= -1;
$stat = ' 후';
} // $time=abs($time);
$ago = array();
$ct = array(31536000,2592000,604800,86400,3600,60,1); // 대략(년:365일,월:30일 기준)
$tt = array('년','달','주','일','시간','분','초');
foreach ($ct as $k => $v) {
if ($n=floor($time/$v)) {
$ago[] = $n.$tt[$k];
$time-=$n*$v;
}
}
return implode(' ', array_slice($ago,0,2)) . $stat;
}
function getNamespace($model) {
if (!$model) {
return null;
}
$class_name = get_class($model);
$reflection_class = new \ReflectionClass($class_name);
return $reflection_class->getName();
}
/**
* Prepare URL
*
* Simply adds the http:// part if no scheme is included
*
* @param string $url
* @return string
*/
function prepareURL($url = '') {
if (empty($url) || $url == 'http://' || $url == 'https://') {
return '';
}
$urls = parse_url($url);
if (!$urls || !isset($urls['scheme'])) {
$url = 'http://'. $url;
}
return $url;
}
/**
* 한글요일 변환
*
* @param datetime
* @param integer
* @return string
*/
function getWeekName($date, $full = 0) {
$weeks = array('일','월','화','수','목','금','토');
$week = date('w', strtotime($date));
if ($full) {
return $weeks[$week] . '요일';
} else {
return $weeks[$week];
}
}
// 휴대폰번호 마스킹
function maskingPhone($str) {
$str = str_replace('-','',$str);
$len = mb_strlen($str, 'utf-8');
$mValue = "";
switch($len){
case 10:
$mValue = mb_substr($str,0,3)."-".mb_substr($str,3,1)."**"."-*".mb_substr($str,7,3);;
break;
case 11:
$mValue = mb_substr($str,0,3)."-".mb_substr($str,3,2)."**"."-*".mb_substr($str,8,3);
break;
case 0:
break;
}
return $mValue;
}
// ID 마스킹
function maskingID($str) {
$mValue = preg_replace('/.{3}$/', '***', $str);
return $mValue;
}
// 이메일 마스킹
function maskingEmail($str) {
//$str = preg_replace('/(?:^|@).\K|\.[^@]*$(*SKIP)(*F)|.(?=.*?\.)/', '*', $str);
$pattern = '/(\w+)(\w{3})(@.{1})(?=.*?\.)(.+)/i';
$replace = '\1***\3*\5';
//$str = preg_replace('/(\w+)(\w{3})@(\w+)/i','\1***@\3',$str);
$str = preg_replace('/(\w+)(\w{3})(@.{1})([\w*?]+)(.+)/i','\1***\3*\5',$str);
return $str;
}
// IP Address 마스킹
function maskingIP($ip, $pos = 2, $mask = "♡", $admin = false) {
if ($admin !== false) {
return $ip;
}
$arr = explode('.', $ip);
$arr[4 - $pos] = $mask;
return implode('.',array_reverse($arr));
}
// 문자열 마스킹
function strMasking($str) {
$str = str_replace('-','',$str);
$len = mb_strlen($str, 'utf-8');
$mValue = "";
switch($len){
case 2:
$mValue = mb_strcut($str, 0, 3, "UTF-8").'*';
break;
case 3:
$mValue = mb_strcut($str, 0, 3, "UTF-8").'*'.mb_strcut($str, 8, 11, "UTF-8");
break;
default:
$mValue = mb_strcut($str, 0, 3, "UTF-8").'**'.mb_strcut($str, 12, 15, "UTF-8");
break;
}
return $mValue;
}
/**
* 자동 링크 변환 함수
*
* @param string
* @return string
*/
function setAutoLink($str) {
$regex['file'] = "gz|tgz|tar|gzip|zip|rar|mpeg|mpg|exe|rpm|dep|rm|ram|asf|ace|viv|avi|mid|gif|jpg|png|bmp|eps|mov|mp4";
$regex['file'] = "(\.(". $regex['file'] .")\") target=\"_blank\"";
$regex['http'] = "(http|https|ftp|telnet|news|mms):\/\/(([\xA1-\xFEa-z0-9:_\-]+\.[\xA1-\xFEa-z0-9,:;&#=_~%\[\]?\/.,+\-]+)([.]*[\/a-z0-9\[\]]|=[\xA1-\xFE]+))";
$regex['mail'] = "([\xA1-\xFEa-z0-9_.-]+)@([\xA1-\xFEa-z0-9_-]+\.[\xA1-\xFEa-z0-9._-]*[a-z]{2,3}(\?[\xA1-\xFEa-z0-9=&\?]+)*)";
// &lt; 로 시작해서 3줄뒤에 &gt; 가 나올 경우와
// IMG tag 와 A tag 의 경우 링크가 여러줄에 걸쳐 이루어져 있을 경우
// 이를 한줄로 합침 (합치면서 부가 옵션들은 모두 삭제함)
$src[] = "/<([^<>\n]*)\n([^<>\n]+)\n([^<>\n]*)>/i";
$tar[] = "<\\1\\2\\3>";
$src[] = "/<([^<>\n]*)\n([^\n<>]*)>/i";
$tar[] = "<\\1\\2>";
$src[] = "/<(A|IMG)[^>]*(HREF|SRC)[^=]*=[ '\"\n]*(". $regex['http'] ."|mailto:". $regex['mail'] .")[^>]*>/i";
$tar[] = "<\\1 \\2=\"\\3\">";
// email 형식이나 URL 에 포함될 경우 URL 보호를 위해 @ 을 치환
$src[] = "/(http|https|ftp|telnet|news|mms):\/\/([^ \n@]+)@/i";
$tar[] = "\\1://\\2_HTTPAT_\\3";
// 특수 문자를 치환 및 html사용시 link 보호
$src[]= "/&(quot|gt|lt)/i";
$tar[] = "!\\1";
// 3.0.11 에서 추가
$src[] = "/&#034;/i";
$tar[] = "\"";
$src[] = "/&#039;/i";
$tar[] = "'";
$src[] = "/&#125;/";
$tar[] = "}";
$src[] = "/<a([^>]*)href=[\"' ]*(". $regex['http'] .")[\"']*[^>]*>/i";
$tar[] = "<A\\1HREF=\"\\3_orig://\\4\" target=\"_blank\">";
$src[] = "/href=[\"' ]*mailto:(". $regex['mail'] .")[\"']*>/i";
$tar[] = "HREF=\"mailto:\\2#-#\\3\">";
$src[] = "/<([^>]*)(background|codebase|src)[ \n]*=[\n\"' ]*(". $regex['http'] .")[\"']*/i";
$tar[] = "<\\1\\2=\"\\4_orig://\\5\"";
// 링크가 안된 url및 email address 자동링크
$src[] = "/((SRC|HREF|BASE|GROUND)[ ]*=[ ]*|[^=]|^)(". $regex['http'] .")/i";
$tar[] = "\\1<A HREF=\"\\3\" target=\"_blank\">\\3</a>";
$src[] = "/(". $regex['mail'] .")/i";
$tar[] = "<A HREF=\"mailto:\\1\">\\1</a>";
$src[] = "/<A HREF=[^>]+>(<A HREF=[^>]+>)/i";
$tar[] = "\\1";
$src[] = "/<\/A><\/A>/i";
$tar[] = "</A>";
// 보호를 위해 치환한 것들을 복구
$src[] = "/!(quot|gt|lt)/i";
$tar[] = "&\\1";
$src[] = "/(http|https|ftp|telnet|news|mms)_orig/i";
$tar[] = "\\1";
$src[] = "'#-#'";
$tar[] = "@";
$src[] = "/". $regex['file'] ."/i";
$tar[] = "\\1";
// email 주소를 변형한 뒤 URL 속의 @ 을 복구
$src[] = "/_HTTPAT_/";
$tar[] = "@";
// 이미지에 보더값 0 을 삽입
$src[] = "/<(IMG SRC=\"[^\"]+\")>/i";
$tar[] = "<\\1 BORDER=0>";
$str = preg_replace($src,$tar,$str);
return $str;
}
/**
* 검색어 스타일 변환
*
* @param string 검색어
* @param string 원본문자열
* @return string
*/
function setSearchStyle($word = '', $str) {
if (!trim($word)) {
return $str;
}
// 검색어 전체를 공백으로 나눈다
$words = explode(' ', $word);
$pattern = '';
$bar = '';
// "/(검색1|검색2)/i" 와 같은 패턴을 만듬
foreach ($words as $val) {
if (trim($val) == '') continue;
$tmp_str = quotemeta($val);
$tmp_str = str_replace(array("/", "|"), array("\/", "\|"), $tmp_str);
$pattern .= $bar . $tmp_str . "(?![^<]*>)";
$bar = "|";
}
$replace = "<em>\\1</em>";
return preg_replace("/(". $pattern .")/i", $replace, $str);
}
function setDefault($val) {
if ($val === null) {
return '';
}
return $val;
}

@ -0,0 +1,199 @@
<?php
namespace App\Http\Controllers\Admin;
use App\Http\Controllers\Controller;
use App\Services\CrossFileService;
use App\Libs\TraitBoard;
use Illuminate\Http\Request;
use Illuminate\Http\JsonResponse;
use Illuminate\Contracts\View\View;
class BoardController extends Controller
{
use TraitBoard;
protected $breadcrumbs = [
['title' => '공지사항', 'link' => '/cms/board/notice']
];
// Page Header
protected $page = [
'code' => 'cms.board',
'title' => '공지사항',
'icon' => 'fa-book',
'description' => '',
'link' => '/cms/board/notice'
];
/**
* 게시글 목록
*
* @Verb : GET
* @Path : /cms/board/{code}
* @param Request $request
* @param string $code
* @return View
*/
public function index(Request $request, string $code = '')
{
$perPage = 10;
$data = $this->getPostList($request, $code, $perPage);
$this->page['code'] .= '.' . $code;
$this->page['title'] = $data['board']->name;
$this->page['subTitle'] = $data['board']->name;
$view = 'admin.board.index';
if ($code == 'inquiry') {
$view = 'admin.board.inquiry.index';
}
return $this->setView($view, $data);
}
/**
* 게시글 상세
*
* @Verb : GET
* @Path : /cms/board/{code}/view/{uid}
* @param Request $request
* @param string $code
* @param string $uid
* @return View
*/
public function view(Request $request, string $code = '', string $uid = '')
{
$data = $this->showPost($request, $code, $uid);
$this->page['code'] .= '.' . $code;
$this->page['title'] = $data['board']->name;
$this->page['subTitle'] = $data['board']->name . ' 상세';
$view = 'admin.board.view';
if ($code == 'inquiry') {
$view = 'admin.board.inquiry.view';
}
return $this->setView($view, compact('data'));
}
/**
* 게시글 등록/수정
*
* @Verb : GET
* @Path : /cms/board/{code}/create
* @Path : /cms/board/{code}/modify/{uid}
* @param Request $request
* @param string $code
* @param string $uid
* @return View
*/
public function create(Request $request, string $code = '', string $uid = '')
{
$data = $this->createPost($request, $code, $uid);
$this->page['code'] .= '.' . $code;
$this->page['title'] = $data->board->name;
$this->page['subTitle'] = $data->board->name . ($data->mode == 'modify' ? ' 수정' : ' 등록');
return $this->setView('admin.board.create', compact('data'));
}
/**
* 게시글 저장
*
* @Verb : POST
* @Path : /cms/board/store
* @param Request $request
* @param CrossFileService $fileService
* @return JsonResponse
*/
public function store(Request $request, CrossFileService $fileService)
{
$result = $this->storePost($request, $fileService);
return $this->sendJson($result['message'], $result['code']);
}
/**
* 에디터 이미지 업로드 저장
*
* @Verb : POST
* @Path : /cms/board/image/upload
* @param Request $request
* @param CrossFileService $fileService
* @return JsonResponse
*/
public function imageUpload(Request $request, CrossFileService $fileService)
{
$result = $this->editorImageUpload($request, $fileService);
return $this->sendJson($result['message'], $result['code'], $result['data']);
}
/**
* 첨부파일 삭제
*
* @Verb : POST
* @Path : /cms/board/asset/delete
* @param Request $request
* @param CrossFileService $fileService
* @return JsonResponse
*/
public function assetDelete(Request $request, CrossFileService $fileService)
{
$result = $this->assetDelete($request, $fileService);
return $this->sendJson($result['message'], $result['code']);
}
/**
* 댓글 저장
*
* @Verb : POST
* @Path : /cms/board/comment/store
* @param Request $request
* @return JsonResponse
*/
public function commentStore(Request $request)
{
$result = $this->storeComment($request);
return $this->sendJson($result['message'], $result['code']);
}
/**
* 댓글 삭제
*
* @Verb : POST
* @Path : /cms/board/comment/delete
* @param Request $request
* @return JsonResponse
*/
public function commentDelete(Request $request)
{
$result = $this->deleteComment($request);
return $this->sendJson($result['message'], $result['code']);
}
/**
* 게시글 삭제
*
* @Verb : POST
* @Path : /cms/board/delete
* @param Request $request
* @param CrossFileService $fileService
* @return JsonResponse
*/
public function delete(Request $request, CrossFileService $fileService)
{
$result = $this->deletePost($request, $fileService);
return $this->sendJson($result['message'], $result['code']);
}
}

@ -0,0 +1,44 @@
<?php
namespace App\Http\Controllers\Admin;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
class IndexController extends Controller
{
protected $breadcrumbs = [
['title' => '홈', 'link' => '/cms']
];
// Page Header
protected $page = [
'code' => 'cms.home',
'title' => '청담K',
'icon' => 'fa-home',
'description' => '',
'link' => '/cms'
];
/**
* Create a new controller instance.
*
* @return void
*/
public function __construct()
{
// $this->middleware('auth');
}
/**
* Show the application dashboard.
*
* @return \Illuminate\Contracts\Support\Renderable
*/
public function index()
{
$data = [];
return $this->setView('admin.index', $data);
}
}

@ -0,0 +1,97 @@
<?php
namespace App\Http\Controllers\Admin;
use App\Http\Controllers\Controller;
use App\Services\CrossFileService;
use App\Libs\TraitPartner;
use Illuminate\Http\Request;
use Illuminate\Http\JsonResponse;
use Illuminate\Contracts\View\View;
class PartnerController extends Controller
{
use TraitPartner;
protected $breadcrumbs = [
['title' => '제휴업체', 'link' => '/cms/partner']
];
// Page Header
protected $page = [
'code' => 'cms.partner',
'title' => '제휴업체',
'icon' => 'fa-flag',
'description' => '',
'link' => '/cms/partner'
];
/**
* 제휴업체 목록
*
* @Verb : GET
* @Path : /cms/partner
* @param Request $request
* @return View
*/
public function index(Request $request)
{
$this->page['subTitle'] = '제휴업체 목록';
$perPage = 10;
$data = $this->getPartnerList($request, $perPage, false);
return $this->setView('admin.partner.index', $data);
}
/**
* 제휴업체 등록
*
* @Verb : GET
* @Path : /cms/partner/create
* @Path : /cms/partner/modify/{uid}
* @param string $uid
* @return View
*/
public function create($uid = '')
{
$data = $this->createPartner($uid);
$this->page['subTitle'] = ($data->mode == 'modify') ? '제휴업체 변경' : '제휴업체 등록';
return $this->setView('admin.partner.create', compact('data'));
}
/**
* 제휴업체 저장
*
* @Verb : POST
* @Path : /cms/partner/store
* @param Request $request
* @param CrossFileService $fileService
* @return JsonResponse
*/
public function store(Request $request, CrossFileService $fileService)
{
$result = $this->storePartner($request, $fileService);
return $this->sendJson($result['message'], $result['code']);
}
/**
* 제휴업체 삭제
*
* Verb : POST
* Path : /cms/partner/delete
* @param Request $request
* @return JsonResponse
*/
public function delete(Request $request)
{
$result = $this->deletePartner($request);
return $this->sendJson($result['message'], $result['code']);
}
}

@ -0,0 +1,95 @@
<?php
namespace App\Http\Controllers\Admin;
use App\Http\Controllers\Controller;
use App\Libs\TraitSetting;
use Illuminate\Http\Request;
use Illuminate\Http\JsonResponse;
use Illuminate\Contracts\View\View;
class SettingController extends Controller
{
use TraitSetting;
protected $breadcrumbs = [
['title' => '사이트 설정', 'link' => '/cms/setting']
];
// Page Header
protected $page = [
'code' => 'cms.setting',
'title' => '사이트 설정',
'icon' => 'fa-cog',
'description' => '사이트에서 사용되는 설정값들을 관리합니다.',
'link' => '/cms/setting'
];
/**
* 설정변수 목록
*
* @Verb : GET
* @Path : /cms/setting
* @param Request $request
* @return View
*/
public function index(Request $request)
{
$this->page['subTitle'] = $this->page['title'];
$data = $this->getSettingList($request);
return $this->setView('admin.setting.index', $data);
}
/**
* 설정변수 등록
*
* @Verb : GET
* @Path : /cms/setting/create
* @param Request $request
* @return JsonResponse
*/
public function create(Request $request)
{
$data = $this->createSetting($request);
$result = [
'mode' => $data->mode,
'data' => $data
];
return $this->sendJson('', 'success', $result);
}
/**
* 설정변수 저장
*
* @Verb : POST
* @Path : /cms/setting/store
* @param Request $request
* @return JsonResponse
*/
public function store(Request $request)
{
$result = $this->storeSetting($request);
return $this->sendJson($result['message'], $result['code']);
}
/**
* 설정변수 삭제
*
* Verb : POST
* Path : /cms/setting/delete
* @param Request $request
* @return JsonResponse
*/
public function delete(Request $request)
{
$result = $this->deleteSetting($request);
return $this->sendJson($result['message'], $result['code']);
}
}

@ -0,0 +1,294 @@
<?php
namespace App\Http\Controllers\Admin;
use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\DB;
use Illuminate\Contracts\Support\Renderable;
use Illuminate\Http\Request;
use Carbon\Carbon;
use App\Models\User;
class UserController extends Controller
{
protected $breadcrumbs = [
[
'title' => '회원',
'link' => '/cms/user'
]
];
protected $page = [
'code' => 'cms.user',
'title' => '회원',
'icon' => 'fa-users',
'description' => '',
'link' => '/cms/user'
];
/**
* 회원 목록
*
* @Verb : GET
* @Path : /admin/missing
* @return Renderable
*/
public function index()
{
}
/**
* 회원 등록/수정
*
* @Verb : GET
* @Path : /cms/user/create
* @Path : /cms/user/modify/{uid}
* @param null $uid
* @return Renderable
*/
public function create($uid = null)
{
$data = null;
// 등록양식
$this->addModal(MissingUpdateModal::class);
if ($uid) {
$data = Missing::query()
->withTrashed()
->with(['profile', 'assets', 'modified', 'user' => function($query) {
$query->withTrashed();
}])
->withCount('reports', 'modified')
->where('uid', $uid)
->first();
//logger(json_decode(json_encode($data->user), true));
}
if (!$data) {
$fields = [
'uid' => '',
'inflow' => 'admin',
'type' => 1,
'name' => '',
'gender' => 'M',
'birthday' => '',
'missing_at' => '',
'address' => '',
'latitude' => '',
'longitude' => '',
'content' => '',
'register_name' => '',
'register_phone' => '',
'reports' => null,
'status' => 0,
'created_id' => '',
'created_at' => '',
'approved_at' => '',
'completed_at' => '',
'profile' => null,
'assets' => null,
'modified' => null,
'reports_count' => 0,
'modified_count' => 0,
'user' => null
];
$data = (object)$fields;
}
$config = config('missing');
return $this->setView('admin.missing.detail', compact('data', 'config'));
}
/**
* 회원 저장
*
* Verb : Post
* Path : /cms/user/store
* @param Request $request
* @return \Illuminate\Http\JsonResponse
*/
public function store(Request $request)
{
$validate = [
'type' => 'required|integer',
'name' => 'required|string|max:50',
'gender' => 'required|in:M,F',
'birthday' => 'required|string|size:10',
'missing_at' => 'required|string|size:10',
'address' => 'required|string',
'content' => 'required|string',
'register_name' => 'required|string|max:50',
'register_phone' => 'required|string|max:20'
];
$validator = $this->validatorApi($request, $validate);
if ($validator !== true) {
return $validator;
}
$config = config('missing');
$fields = $request->only([
'type', 'name', 'gender', 'birthday', 'missing_at',
'address', 'latitude', 'longitude', 'content',
'register_name', 'register_phone',
'status'
]);
if (!array_key_exists($fields['type'], $config['types'])) {
$fields['type'] = 1;
}
if (!array_key_exists($fields['status'], $config['status'])) {
$fields['status'] = 0;
}
$fields['birthday'] = str_replace('.', '-', trim($fields['birthday']));
$fields['missing_at'] = str_replace('.', '-', trim($fields['missing_at']));
$isNew = true;
$oldStatus = 0;
$newStatus = $fields['status'];
// 수정
if ($request->filled('uid')) {
$isNew = false;
$data = Missing::data($request->uid, false, 'user');
if ($data->error) {
return $this->sendResultMessage($data->error, false);
}
$oldStatus = $data->status;
$data->fill($fields);
$data->save();
// 등록
} else {
$fields['inflow'] = 'admin';
$data = Missing::add($fields);
}
if ($isNew && !$data->id) {
return $this->sendResultMessage('실종자 등록이 실패했습니다.', false);
}
if ($isNew) {
$message = '실종자 정보가 등록되었습니다.';
} else {
$message = '실종자 정보가 수정되었습니다.';
}
return $this->sendResult($message, $data);
}
/**
* 회원 비밀번호 변경
*
* Verb : POST
* Path : /cms/user/change/password
* @param Request $request
* @return \Illuminate\Http\JsonResponse
*/
public function passwordChange(Request $request)
{
$uid = $request->post('uid', '');
$data = MissingUpdate::data($uid, false, 'profile');
if ($data->error) {
return $this->sendResultMessage($data->error, false);
}
$missing_uid = $data->missing_uid;
$missing = Missing::data($missing_uid, false, ['profile','user']);
if ($missing->error) {
return $this->sendResultMessage($missing->error, false);
}
$now = (string)Carbon::now();
// 실종자 정보변경
$fields = $data->only([
'type', 'name', 'gender', 'birthday', 'missing_at',
'address', 'latitude', 'longitude', 'content',
'register_name', 'register_phone'
]);
$additions = [
'updated_id' => auth()->user()->id,
'updated_at' => $now
];
$missing->fill(array_merge($fields, $additions));
if (!$missing->save()) {
return $this->sendResultMessage('실종자 정보수정이 실패했습니다.', false);
}
// 수정요청 상태 변경
$data->fill(['status' => 1]);
$data->save();
return $this->sendResult('수정요청이 승인되었습니다.', $data);
}
/**
* 회원 탈퇴 처리
*
* Verb : POST
* Path : /cms/user/signout
* @param Request $request
* @return bool|\Illuminate\Http\JsonResponse
*/
public function signout(Request $request)
{
$data = Missing::data($request->uid);
if ($data->error) {
return $this->sendResultMessage($data->error, false);
}
// 사진파일 삭제
if ($data->assets) {
foreach ($data->assets as $asset) {
$fileService->deleteFile($asset->uid);
$asset->delete();
}
}
$data->delete();
return $this->sendResult('실종자 정보가 삭제되었습니다.', $data);
}
/**
* 회원 복구
*
* Verb : POST
* Path : /cms/user/restore
* @param Request $request
* @return bool|\Illuminate\Http\JsonResponse
*/
public function restore(Request $request)
{
$data = Missing::data($request->uid);
if ($data->error) {
return $this->sendResultMessage($data->error, false);
}
// 사진파일 삭제
if ($data->assets) {
foreach ($data->assets as $asset) {
$fileService->deleteFile($asset->uid);
$asset->delete();
}
}
$data->delete();
return $this->sendResult('실종자 정보가 삭제되었습니다.', $data);
}
}

@ -0,0 +1,51 @@
<?php
namespace App\Http\Controllers;
use App\Services\CrossFileService;
use Illuminate\Http\Request;
class AssetController extends Controller
{
public function upload(Request $request, CrossFileService $fileService)
{
$asset = $fileService->saveFile(auth()->user(), $request, "file");
$data = [
'uid' => $asset->uid,
'url' => '/image/rate/w800/'. $asset->uid,
];
return $this->sendJson('업로드 완료', 'success', $data, [], true);
}
public function download($uid, CrossFileService $fileService)
{
return $fileService->download($uid);
}
public function downloadImageRate($rate, $uid, CrossFileService $fileService)
{
if (!empty($rate)) {
$type = substr($rate, 0, 1);
$size = substr($rate, 1);
if ($type == 'w' || $type == 'h') {
return $fileService->downloadImageRate($uid, $type, $size);
}
}
abort(404);
}
public function downloadImage($size, $uid, CrossFileService $fileService)
{
if (!empty($size)) {
$size = explode("x", $size);
$width = (int)$size[0];
$height = (int)$size[1];
return $fileService->downloadImage($uid, $width, $height);
}
abort(404);
}
}

@ -0,0 +1,40 @@
<?php
namespace App\Http\Controllers\Auth;
use App\Http\Controllers\Controller;
use App\Providers\RouteServiceProvider;
use Illuminate\Foundation\Auth\ConfirmsPasswords;
class ConfirmPasswordController extends Controller
{
/*
|--------------------------------------------------------------------------
| Confirm Password Controller
|--------------------------------------------------------------------------
|
| This controller is responsible for handling password confirmations and
| uses a simple trait to include the behavior. You're free to explore
| this trait and override any functions that require customization.
|
*/
use ConfirmsPasswords;
/**
* Where to redirect users when the intended url fails.
*
* @var string
*/
protected $redirectTo = RouteServiceProvider::HOME;
/**
* Create a new controller instance.
*
* @return void
*/
public function __construct()
{
$this->middleware('auth');
}
}

@ -0,0 +1,22 @@
<?php
namespace App\Http\Controllers\Auth;
use App\Http\Controllers\Controller;
use Illuminate\Foundation\Auth\SendsPasswordResetEmails;
class ForgotPasswordController extends Controller
{
/*
|--------------------------------------------------------------------------
| Password Reset Controller
|--------------------------------------------------------------------------
|
| This controller is responsible for handling password reset emails and
| includes a trait which assists in sending these notifications from
| your application to your users. Feel free to explore this trait.
|
*/
use SendsPasswordResetEmails;
}

@ -0,0 +1,59 @@
<?php
namespace App\Http\Controllers\Auth;
use App\Http\Controllers\Controller;
use App\Providers\RouteServiceProvider;
use App\Libs\EncryptQuery;
use Illuminate\Foundation\Auth\AuthenticatesUsers;
use Illuminate\Http\Request;
class LoginController extends Controller
{
/*
|--------------------------------------------------------------------------
| Login Controller
|--------------------------------------------------------------------------
|
| This controller handles authenticating users for the application and
| redirecting them to your home screen. The controller uses a trait
| to conveniently provide its functionality to your applications.
|
*/
use AuthenticatesUsers;
use EncryptQuery;
/**
* Where to redirect users after login.
*
* @var string
*/
protected $redirectTo = '/cms';
/**
* Create a new controller instance.
*
* @return void
*/
public function __construct()
{
$this->middleware('guest')->except('logout');
parent::__construct();
}
protected function authenticated(Request $request, $user)
{
$isDebug = config('app.debug', 'false');
if($isDebug && $user->type == 'Admin') {
// 자동인증
$request->session()->put('super_verified', true);
}
}
protected function loggedOut(Request $request)
{
return redirect(route('cms.login'));
}
}

@ -0,0 +1,78 @@
<?php
namespace App\Http\Controllers\Auth;
use Illuminate\Foundation\Auth\RegistersUsers;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Validator;
use Illuminate\Support\Str;
use App\Http\Controllers\Controller;
use App\Providers\RouteServiceProvider;
use App\Models\User;
class RegisterController extends Controller
{
/*
|--------------------------------------------------------------------------
| Register Controller
|--------------------------------------------------------------------------
|
| This controller handles the registration of new users as well as their
| validation and creation. By default this controller uses a trait to
| provide this functionality without requiring any additional code.
|
*/
use RegistersUsers;
/**
* Where to redirect users after registration.
*
* @var string
*/
protected $redirectTo = RouteServiceProvider::HOME;
/**
* Create a new controller instance.
*
* @return void
*/
public function __construct()
{
$this->middleware('guest');
}
/**
* Get a validator for an incoming registration request.
*
* @param array $data
* @return \Illuminate\Contracts\Validation\Validator
*/
protected function validator(array $data)
{
return Validator::make($data, [
'name' => ['required', 'string', 'max:255'],
'email' => ['required', 'string', 'email', 'max:255'],
'password' => ['required', 'string', 'min:6', 'confirmed'],
]);
}
/**
* Create a new user instance after a valid registration.
*
* @param array $data
* @return \App\Models\User
*/
protected function create(array $data)
{
return User::create([
'uid' => Str::uuid()->toString(),
'type' => config('env.user.type.default'),
'email' => $data['email'],
'password' => Hash::make($data['password']),
'name' => $data['name'],
'status' => config('env.user.status.default')
]);
}
}

@ -0,0 +1,30 @@
<?php
namespace App\Http\Controllers\Auth;
use App\Http\Controllers\Controller;
use App\Providers\RouteServiceProvider;
use Illuminate\Foundation\Auth\ResetsPasswords;
class ResetPasswordController extends Controller
{
/*
|--------------------------------------------------------------------------
| Password Reset Controller
|--------------------------------------------------------------------------
|
| This controller is responsible for handling password reset requests
| and uses a simple trait to include this behavior. You're free to
| explore this trait and override any methods you wish to tweak.
|
*/
use ResetsPasswords;
/**
* Where to redirect users after resetting their password.
*
* @var string
*/
protected $redirectTo = RouteServiceProvider::HOME;
}

@ -0,0 +1,42 @@
<?php
namespace App\Http\Controllers\Auth;
use App\Http\Controllers\Controller;
use App\Providers\RouteServiceProvider;
use Illuminate\Foundation\Auth\VerifiesEmails;
class VerificationController extends Controller
{
/*
|--------------------------------------------------------------------------
| Email Verification Controller
|--------------------------------------------------------------------------
|
| This controller is responsible for handling email verification for any
| user that recently registered with the application. Emails may also
| be re-sent if the user didn't receive the original email message.
|
*/
use VerifiesEmails;
/**
* Where to redirect users after verification.
*
* @var string
*/
protected $redirectTo = RouteServiceProvider::HOME;
/**
* Create a new controller instance.
*
* @return void
*/
public function __construct()
{
$this->middleware('auth');
$this->middleware('signed')->only('verify');
$this->middleware('throttle:6,1')->only('verify', 'resend');
}
}

@ -0,0 +1,193 @@
<?php
namespace App\Http\Controllers;
use Carbon\Carbon;
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
use Illuminate\Foundation\Bus\DispatchesJobs;
use Illuminate\Foundation\Validation\ValidatesRequests;
use Illuminate\Http\JsonResponse as JsonResponseAlias;
use Illuminate\Http\Request;
use Illuminate\Routing\Controller as BaseController;
use Illuminate\Support\Facades\Validator;
use Illuminate\Support\Facades\View;
use App\Models\Setting;
class Controller extends BaseController
{
use AuthorizesRequests, DispatchesJobs, ValidatesRequests;
protected $breadcrumbs = [];
protected $page = [];
protected $title = '';
public function __construct()
{
$now = Carbon::now()->timestamp;
View::share('now', $now);
// 전역변수 설정
$_settings = Setting::all();
$settings = [];
if ($_settings) {
foreach ($_settings as $row) {
$settings[$row['key']] = $row['value'];
}
}
//logger($settings);
View::share('settings', (object)$settings);
}
protected function baseData() {
// breadcrumb 추가
return [
'breadcrumbs' => $this->breadcrumbs,
'page' => $this->page,
'title' => $this->title,
'pages' => config('pages')
];
}
protected function setView($name, $data = []) {
return view($name, $data, $this->baseData());
}
/**
* 유효성 검사
*
* @param Request $request
* @param array $rules
* @param array $message
* @return bool|string
*/
protected function validation(Request $request, array $rules = [], array $message = [])
{
$validator = Validator::make($request->all(), $rules, $message);
if ($validator->fails()) {
return $validator->errors()->first();
}
return true;
}
/**
* 처리결과
*
* @param string $message
* @param string $code
* @param array $appends
* @return array
*/
protected function sendResult(string $message = '', string $code = 'error', array $appends = [])
{
$result = [
'code' => $code,
'message' => $message
];
if (!empty($appends)) {
$result = array_merge($result, $appends);
}
return $result;
}
/**
* JSON Return
*
* @param string $message
* @param string $code
* @param mixed $data
* @param array $errors
* @param bool $success
* @return JsonResponseAlias
*/
protected function sendJson(string $message = '', string $code = 'success', $data = null, array $errors = [], bool $success = true)
{
$errorCode = $success ? 200 : 422;
$result = [
'code' => $code,
'message' => $message,
'success' => $success,
'data' => $data,
'errors' => $errors
];
try {
logger(json_decode(json_encode($result), true));
} catch (\JsonException $e) {
logger($e);
}
return response()->json($result, $errorCode, [], JSON_UNESCAPED_UNICODE);
}
/**
* JSON Return Aliasing
*
* @param string $message
* @param string $code
* @param bool $status
* @return JsonResponseAlias
*/
protected function sendJsonMessage(string $message = '', string $code = 'success', bool $status = true)
{
return $this->sendJson($message, $code, null, [], $status);
}
/**
* 유효성 검사
*
* @param Request $request
* @param array $rules
* @param array $message
* @return bool|JsonResponseAlias
*/
protected function validationJson(Request $request, array $rules = [], array $message = [])
{
$validator = Validator::make($request->all(), $rules, $message);
if ($validator->fails()) {
return $this->sendJson(
'입력하신 데이터가 유효하지 않습니다.',
'error',
null,
$validator->getMessageBag()->getMessages(),
false
);
}
return true;
}
/**
* 목록에서 순번 뽑아오기
*
* @param $list
* @return mixed
*/
protected function getListNumber($list) {
// 전체 갯수
$total = $list->total();
// 페이지당 갯수
$perPage = $list->perPage();
// 현재 페이지번호
$currentPage = $list->currentPage();
$count = 0;
$list->getCollection()->transform(function($list) use($total, $perPage, $currentPage, &$count) {
$list->number = ($total - ($perPage * ($currentPage - 1))) - $count;
$count++;
return $list;
});
return $list;
}
}

@ -0,0 +1,122 @@
<?php
namespace App\Http\Controllers\Front;
use App\Http\Controllers\Controller;
use App\Libs\TraitBoard;
use App\Services\CrossFileService;
use Illuminate\Http\Request;
use Illuminate\Http\JsonResponse;
use Illuminate\Contracts\View\View;
class BoardController extends Controller
{
use TraitBoard;
protected $page = [
'code' => 'board',
'title' => '게시판',
'subTitle' => '',
'description' => '',
'link' => '/board/notice'
];
/**
* 게시글 목록
*
* @Verb : GET
* @Path : /board/{code}
* @param Request $request
* @param string $code
* @return View
*/
public function index(Request $request, string $code = '')
{
if ($code == 'inquiry') {
return redirect(route('board.create', [$code]));
}
if ($code == 'news') {
$perPage = 0;
} else {
$perPage = 10;
}
$data = $this->getPostList($request, $code, $perPage);
$this->page['code'] .= '.' . $code;
$this->page['subTitle'] = $data['board']->name;
$skin = $data['board']->skin ?? 'default';
$view = 'board.'. $skin .'.index';
return $this->setView($view, $data);
}
/**
* 게시글 상세
*
* @Verb : GET
* @Path : /board/{code}/{uid}
* @param Request $request
* @param string $code
* @param string $uid
* @return View
*/
public function view(Request $request, string $code = '', string $uid = '')
{
$data = $this->showPost($request, $code, $uid);
$this->page['code'] .= '.' . $code;
$this->page['subTitle'] = $data->board->name;
$skin = $data->board->skin ?? 'default';
$view = 'board.'. $skin .'.view';
return $this->setView($view, compact('data'));
}
/**
* 문의하기 등록
*
* @Verb : GET
* @Path : /board/{code}/create
* @param Request $request
* @param string $code
* @param string $uid
* @return View
*/
public function create(Request $request, string $code = '', string $uid = '')
{
$data = $this->createPost($request, $code, $uid);
$this->page['code'] .= '.' . $code;
$this->page['subTitle'] = $data->board->name;
$skin = $data->board->skin ?? 'default';
$view = 'board.'. $skin .'.create';
return $this->setView($view, compact('data'));
}
/**
* 문의하기 저장
*
* @Verb : POST
* @Path : /board/store
* @param Request $request
* @param CrossFileService $fileService
* @return JsonResponse
*/
public function store(Request $request, CrossFileService $fileService)
{
$result = $this->storePost($request, $fileService);
return $this->sendJson($result['message'], $result['code']);
}
}

@ -0,0 +1,38 @@
<?php
namespace App\Http\Controllers\Front;
use App\Http\Controllers\Controller;
use Illuminate\Contracts\View\View;
use App\Libs\TraitBoard;
class IndexController extends Controller
{
use TraitBoard;
protected $page = [
'code' => 'index',
'title' => '',
'subTitle' => '',
'description' => '',
'link' => '/',
'is_main' => true
];
/**
* 홈페이지 메인
*
* @Verb : GET
* @Path : /
* @return View
*/
public function index()
{
$data = [
'notice' => $this->getLatest('notice'),
'news' => $this->getLatest('news'),
];
return $this->setView('index', $data);
}
}

@ -0,0 +1,45 @@
<?php
namespace App\Http\Controllers\Front;
use App\Http\Controllers\Controller;
use Illuminate\Contracts\View\View;
use Illuminate\Http\Request;
class PagesController extends Controller
{
protected $page = [
'code' => 'pages',
'title' => '갤러리소개',
'subTitle' => '',
'description' => '',
'link' => '/'
];
/**
* 일반페이지
*
* @Verb : GET
* @Path : /pages/{code}
* @param Request $request
* @param string $code
* @return View
*/
public function index(Request $request, string $code = '')
{
$data = [];
$this->page['code'] .= '.' . $code;
$pages = config('pages');
if (array_key_exists($code, $pages)) {
$this->page['subTitle'] = $pages[$code];
$view = 'pages.'. $code;
} else {
return redirect('/');
}
return $this->setView($view, $data);
}
}

@ -0,0 +1,41 @@
<?php
namespace App\Http\Controllers\Front;
use App\Http\Controllers\Controller;
use App\Libs\TraitPartner;
use Illuminate\Http\Request;
use Illuminate\Contracts\View\View;
class PartnerController extends Controller
{
use TraitPartner;
protected $page = [
'code' => 'partner',
'title' => '제휴업체',
'subTitle' => '',
'description' => '',
'link' => '/partner'
];
/**
* 제휴업체 목록
*
* @Verb : GET
* @Path : /cms/partner
* @param Request $request
* @return View
*/
public function index(Request $request)
{
$perPage = 0;
$data = $this->getPartnerList($request, $perPage);
$this->page['subTitle'] = $this->page['title'];
return $this->setView('partner.index', $data);
}
}

@ -0,0 +1,92 @@
<?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<int, class-string|string>
*/
protected $middleware = [
// \App\Http\Middleware\TrustHosts::class,
\Fruitcake\Cors\HandleCors::class,
\Illuminate\Foundation\Http\Middleware\ValidatePostSize::class,
\Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class,
\App\Http\Middleware\PreventRequestsDuringMaintenance::class,
\App\Http\Middleware\CheckForMaintenanceMode::class,
\App\Http\Middleware\TrustProxies::class,
\App\Http\Middleware\TrimStrings::class,
\App\Http\Middleware\Transactional::class,
\App\Http\Middleware\ConvertStringBooleans::class,
// \App\Http\Middleware\PhoneFilter::class,
];
/**
* The application's route middleware groups.
*
* @var array<string, array<int, class-string|string>>
*/
protected $middlewareGroups = [
'web' => [
\App\Http\Middleware\EncryptCookies::class,
\Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
\Illuminate\Session\Middleware\StartSession::class,
// \Illuminate\Session\Middleware\AuthenticateSession::class,
\App\Http\Middleware\AuthenticateSession::class,
\Illuminate\View\Middleware\ShareErrorsFromSession::class,
\App\Http\Middleware\VerifyCsrfToken::class,
\Illuminate\Routing\Middleware\SubstituteBindings::class,
],
'api' => [
// \Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class,
'throttle:api',
'bindings',
],
];
/**
* The application's route middleware.
*
* These middleware may be assigned to groups or used individually.
*
* @var array<string, class-string|string>
*/
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,
'auth.admin' => \App\Http\Middleware\AuthenticateAdmin::class,
'admin' => \App\Http\Middleware\AuthAdmin::class,
];
/**
* The priority-sorted list of middleware.
*
* This forces non-global middleware to always be in the given order.
*
* @var array
*/
protected $middlewarePriority = [
\Illuminate\Session\Middleware\StartSession::class,
\Illuminate\View\Middleware\ShareErrorsFromSession::class,
\App\Http\Middleware\Authenticate::class,
\App\Http\Middleware\AuthenticateSession::class,
\Illuminate\Routing\Middleware\SubstituteBindings::class,
\Illuminate\Auth\Middleware\Authorize::class,
];
}

@ -0,0 +1,43 @@
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Auth\Middleware\Authenticate as Middleware;
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
class AuthAdmin extends Middleware
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return mixed
*/
public function handle($request, Closure $next, ...$guards)
{
if (auth()->check() && auth()->user()->type === 'Admin') {
return $next($request);
}
if ($request->ajax()) {
$errorCode = 403;
$result = [
"message" => '권한이 없습니다.',
"success" => false,
"data" => [],
"errors" => []
];
// logger(json_decode(json_encode($result), true));
$headers = [];
return response()->json($result, $errorCode, $headers, JSON_UNESCAPED_UNICODE);
} else {
$data = [
'exception' => new AccessDeniedHttpException()
];
return response()->view('errors', $data);
}
}
}

@ -0,0 +1,21 @@
<?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 string|null
*/
protected function redirectTo($request)
{
if (! $request->expectsJson()) {
return route('login');
}
}
}

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

@ -0,0 +1,37 @@
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Session\Middleware\AuthenticateSession as Middleware;
class AuthenticateSession extends Middleware
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return mixed
*/
public function handle($request, Closure $next)
{
if (! $request->user() || ! $request->session()) {
return $next($request);
}
if ($this->auth->viaRemember()) {
$passwordHash = explode('|', $request->cookies->get($this->auth->getRecallerName()))[2];
if ($passwordHash != $request->user()->getAuthPassword()) {
$this->logout($request);
}
}
return tap($next($request), function () use ($request) {
$this->storePasswordHashInSession($request);
});
}
}

@ -0,0 +1,17 @@
<?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 = [
//
];
}

@ -0,0 +1,14 @@
<?php
namespace App\Http\Middleware;
use Illuminate\Foundation\Http\Middleware\TransformsRequest;
class ConvertStringBooleans extends TransformsRequest
{
protected function transform($key, $value)
{
if($value === 'true' || $value === 'TRUE') return true;
if($value === 'false' || $value === 'FALSE') return false;
return $value;
}
}

@ -0,0 +1,17 @@
<?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<int, string>
*/
protected $except = [
//
];
}

@ -0,0 +1,35 @@
<?php
/**
* Disable HTTP Cache
*
* @author Been Kyung-yoon <master@best79.com>
* @license http://www.opensource.org/licenses/mit-license.php MIT
*/
namespace App\Http\Middleware;
use Closure;
class NoCacheMiddleware
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
*
* @return mixed
*/
public function handle($request, Closure $next)
{
$response = $next($request);
// 웹페이지 캐시 비활성화 - 로그아웃 후 뒤로가기시 로그인된 화면이 보이는 것 방지.
if (method_exists($response, 'header')) {
$response->header('Cache-Control', 'private, no-cache, no-store, must-revalidate');
$response->header('Pragma', 'no-cache');
$response->header('Expires', 'Thu, 19 Nov 1981 08:52:00 GMT');
}
return $response;
}
}

@ -0,0 +1,24 @@
<?php
namespace App\Http\Middleware;
use Illuminate\Foundation\Http\Middleware\TransformsRequest;
class PhoneFilter extends TransformsRequest
{
/**
* Transform the given value.
*
* @param string $key
* @param mixed $value
* @return mixed
*/
protected function transform($key, $value)
{
if ($key == 'phone') {
return removeHyphen( filterPhone($value) );
}
return $value;
}
}

@ -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<int, string>
*/
protected $except = [
//
];
}

@ -0,0 +1,32 @@
<?php
namespace App\Http\Middleware;
use App\Providers\RouteServiceProvider;
use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
class RedirectIfAuthenticated
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure(\Illuminate\Http\Request): (\Illuminate\Http\Response|\Illuminate\Http\RedirectResponse) $next
* @param string|null ...$guards
* @return \Illuminate\Http\Response|\Illuminate\Http\RedirectResponse
*/
public function handle(Request $request, Closure $next, ...$guards)
{
$guards = empty($guards) ? [null] : $guards;
foreach ($guards as $guard) {
if (Auth::guard($guard)->check()) {
return redirect(RouteServiceProvider::HOME);
}
}
return $next($request);
}
}

@ -0,0 +1,37 @@
<?php
namespace App\Http\Middleware;
use Closure;
use Exception;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
use Symfony\Component\HttpFoundation\BinaryFileResponse;
class Transactional
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @param string|null $guard
* @return mixed
* @throws Exception
*/
public function handle($request, Closure $next, $guard = null)
{
DB::beginTransaction();
$response = $next($request);
if($response instanceof BinaryFileResponse) {
return $next($request);
}
if($response instanceof Exception) {
DB::rollBack();
} else {
DB::commit();
}
return $response;
}
}

@ -0,0 +1,19 @@
<?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<int, string>
*/
protected $except = [
'current_password',
'password',
'password_confirmation',
];
}

@ -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<int, string|null>
*/
public function hosts()
{
return [
$this->allSubdomainsOfApplicationUrl(),
];
}
}

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

@ -0,0 +1,17 @@
<?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<int, string>
*/
protected $except = [
//
];
}

@ -0,0 +1,43 @@
<?php
namespace App\Libs;
trait EncryptQuery
{
// 암호값을 고정하기 위함
private $iv = 'FIXED_ENCRYPT_ST';
public function scopeWhereCompareCrypt($query, $field, $compare, $value)
{
return $query->where($field, $compare, $this->encrypt($value));
}
public function scopeWhereCrypt($query, $field, $value)
{
return $query->where($field, $this->encrypt($value));
}
public function scopeOrWhereCrypt($query, $field, $value)
{
return $query->orWhere($field, $this->encrypt($value));
}
public function scopeWhereInCrypt($query, $field, $values)
{
$ins = [];
foreach ($values as $value) {
$ins[] = $this->encrypt($value);
}
return $query->whereIn($field, $ins);
}
public function encrypt($value)
{
return base64_encode(openssl_encrypt($value, "AES-256-CBC", config('app.key'), 0, $this->iv));
}
public function decrypt($value)
{
return openssl_decrypt(base64_decode($value), "AES-256-CBC", config('app.key'), 0, $this->iv);
}
}

@ -0,0 +1,63 @@
<?php
namespace App\Libs;
use Carbon\Carbon;
use Illuminate\Support\Facades\Crypt;
trait EncryptUser
{
use Encryptable;
protected $_crypt_data = null;
protected $_cryptable = 'cryptable';
protected $encryptable = [
'birthday',
'gender',
'age',
];
public function setBirthdayAttribute($value)
{
$this->setAttribute('birth_day', $value);
}
public function setGenderAttribute($value)
{
$this->setAttribute('gender', $value);
}
public function setAgeAttribute($value)
{
$this->setAttribute('age', $value);
}
public function getBirthdayAttribute()
{
$value = $this->getAttribute('birthday');
if (empty($value)) {
return null;
}
return Carbon::parse($value)->format('Y-m-d');
}
public function getGenderAttribute()
{
$value = $this->getAttribute('gender');
if (empty($value)) {
return null;
}
return $value;
}
public function getAgeAttribute()
{
$value = $this->getAttribute('age');
if (empty($value)) {
return null;
}
return (int) $value;
}
}

@ -0,0 +1,81 @@
<?php
namespace App\Libs;
use Illuminate\Support\Facades\Crypt;
trait Encryptable
{
public function getCryptData()
{
if($this->_crypt_data == null && $this->_cryptable) {
$cryptValue = $this->{$this->_cryptable};
// logger($cryptValue);
// print_r($cryptValue);
if($cryptValue) {
try {
$decryptValue = Crypt::decryptString($cryptValue);
$this->_crypt_data = json_decode($decryptValue, true);
} catch (\Exception $e) {
logger($e->getTraceAsString());
$this->_crypt_data = [];
}
// print_r($this->_crypt_data);
}
else $this->_crypt_data = [];
// logger($this->_crypt_data);
// print_r($this->_crypt_data);
}
return $this->_crypt_data;
}
public function cryptData($data)
{
if($data == null || count($data) == 0) {
$this->{$this->_cryptable} = null;
$this->_crypt_data = null;
return;
}
// print_r($data);
$jsonText = json_encode($data);
// AES-256-CBC
try {
$encryptValue = Crypt::encryptString($jsonText);
$this->{$this->_cryptable} = $encryptValue;
$this->_crypt_data = null;
} catch (\Exception $e) {
logger($e->getTraceAsString());
$this->{$this->_cryptable} = null;
$this->_crypt_data = null;
}
}
public function getAttribute($key)
{
if (in_array($key, $this->encryptable)) {
return $this->getEncryptValue($key);
}
return parent::getAttribute($key);
}
private function getEncryptValue($key)
{
if (in_array($key, $this->encryptable)) {
$data = $this->getCryptData();
if(isset($data[$key])) return $data[$key];
return null;
}
return null;
}
public function setAttribute($key, $value)
{
// logger('--------EncrypUser------');
if (in_array($key, $this->encryptable)) {
$data = $this->getCryptData();
if($value) $data[$key] = $value;
$this->cryptData($data);
}
else parent::setAttribute($key, $value);
}
}

@ -0,0 +1,570 @@
<?php
namespace App\Libs;
use App\Models\Board;
use App\Models\BoardArticle;
use App\Models\BoardAsset;
use App\Models\BoardComment;
use App\Services\CrossFileService;
use Carbon\Carbon;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Validator;
use Illuminate\Support\Str;
trait TraitBoard
{
protected $cookie;
/**
* 게시판 정보
*
* @param string $code
* @return mixed
*/
protected function getBoardInfo(string $code = '')
{
return Board::query()->where('code', $code)->first();
}
/**
* 게시물 목록
*
* @param Request $request
* @param string $code
* @param int $perPage
* @return array
*/
protected function getPostList(Request $request, string $code = '', int $perPage = 15)
{
$board = $this->getBoardInfo($code);
$list = BoardArticle::query()
->with(['user', 'asset', 'assets', 'comments'])
->withCount(['assets', 'comments'])
->where('board_id', $board->id)
->where(function ($query) use ($request) {
if ($request->filled('word')) {
if ($request->filled('field') && $request->field != 'all') {
$query->where($request->field, 'like', '%' . $request->word . '%');
} else {
$query->orWhere('name', 'like', '%'. $request->word .'%')
->orWhere('email', 'like', '%'. $request->word .'%')
->orWhere('phone', 'like', '%'. $request->word .'%')
->orWhere('subject', 'like', '%'. $request->word .'%')
->orWhere('content', 'like', '%'. $request->word .'%');
}
}
})
->orderByDesc('notice')
->latest()
->paginate($perPage);
$list = $this->getListNumber($list);
$search = $request->all();
$list->appends($search);
$searchs = [
'all' => '통합검색',
'subject' => '제목',
'content' => '내용'
];
if ($code == 'inquiry') {
$searchs = [
'all' => '통합검색',
'name' => '이름',
'email' => '이메일',
'phone' => '연락처',
'content' => '내용'
];
}
$data = [
'mode' => 'list',
'code' => $code,
'board' => $board,
'data' => $list,
'search' => $search,
'searchs' => $searchs
];
return $data;
}
/**
* 최근게시물
*
* @param Request $request
* @param string $code
* @param int $perPage
* @return array
*/
protected function getLatest(string $code = '', int $count = 5)
{
$board = $this->getBoardInfo($code);
$data = BoardArticle::query()->where('board_id', $board->id)->latest()->limit($count)->get();
return $data;
}
/**
* 게시글 정보
*
* @param string $uid
* @return mixed
*/
protected function getPostInfo(string $uid = '')
{
$data = BoardArticle::query()
->with(['board', 'user', 'asset', 'assets', 'comments'])
->withCount(['assets', 'comments'])
->where('uid', $uid)
->first();
logger(json_decode(json_encode($data), true));
return $data;
}
/**
* 게시글 보기 화면
*
* @param Request $request
* @param string $code
* @param string $uid
* @return mixed
*/
protected function showPost(Request $request, string $code = '', string $uid = '')
{
$next = null;
$prev = null;
$board = $this->getBoardInfo($code);
$data = $this->getPostInfo($uid);
if ($data) {
$prev = BoardArticle::query()
->where('id', '>', $data->id)
->where('board_id', $data->board->id)
->first();
$next = BoardArticle::query()
->where('id', '<', $data->id)
->where('board_id', $data->board->id)
->orderBy('created_at', "desc")
->first();
} else {
$data = new BoardArticle;
}
$data->mode = 'view';
$data->code = $code;
$data->board = $board;
$data->board_id = $board->id;
$data->next = $next;
$data->prev = $prev;
$data->search = $request->all();
$images = [];
$files = [];
if ($data->assets) {
foreach ($data->assets as $asset) {
if ($asset->asset->width && $asset->asset->height) {
$images[] = $asset->asset;
} else {
$files[] = $asset->asset;
}
}
}
$data->images = $images;
$data->files = $files;
return $data;
}
/**
* 게시글 등록/수정
*
* @param Request $request
* @param string $code
* @param string $uid
* @return array
*/
protected function createPost(Request $request, string $code = '', string $uid = '')
{
$board = $this->getBoardInfo($code);
if ($uid) {
$data = $this->getPostInfo($uid);
$data->mode = 'modify';
} else {
$data = new BoardArticle;
$data->mode = 'add';
$data->board_id = $board->id;
$data->uid = '';
}
$data->code = $code;
$data->board = $board;
$data->search = $request->all();
return $data;
}
/**
* 게시글 저장
*
* @param Request $request
* @param CrossFileService $fileService
* @return mixed
*/
protected function storePost(Request $request, CrossFileService $fileService)
{
return DB::transaction(function() use ($request, $fileService) {
$rules = [
'mode' => 'required|string',
'code' => 'required|string|max:20',
'board_id' => 'required|integer',
'subject' => 'required|string|max:255',
'content' => 'required|string'
];
$boardCode = $request->code;
if ($boardCode == 'inquiry') {
unset($rules['subject']);
$rules['name'] = 'required|string';
$rules['email'] = 'required|string';
$rules['phone'] = 'required|string';
}
$validator = $this->validation($request, $rules);
if ($validator !== true) {
return $this->sendResult($validator);
}
$board = $this->getBoardInfo($boardCode);
if (!$board) {
return $this->sendResult('존재하지 않는 게시판입니다.');
}
$mode = $request->get('mode', 'add');
$uid = (string)$request->get('uid', '');
$data = $this->getPostInfo($uid);
$postData = $request->only([
'board_id', 'category', 'notice',
'name', 'email', 'phone',
'subject', 'content', 'related_link'
]);
$postData = array_map('setDefault', $postData);
if (!isset($postData['subject'])) {
$postData['subject'] = 0;
}
if (!isset($postData['notice'])) {
$postData['notice'] = 0;
}
if (!isset($postData['name'])) {
$postData['name'] = auth()->user()->name;
}
if (!isset($postData['email'])) {
$postData['email'] = auth()->user()->email;
}
if (!isset($postData['phone'])) {
$postData['phone'] = auth()->user()->phone;
}
// 목록이미지 삭제
if ($request->get('delImage', 0)) {
// 기존파일 삭제
if ($data && $data->image) {
$fileService->deleteFile($data->image);
}
$postData['image'] = '';
}
// 갤러리형 목록이미지
if ($request->hasFile('image')) {
// 기존파일 삭제
if ($data && $data->image) {
$fileService->deleteFile($data->image);
}
$asset = $fileService->saveFile(auth()->user(), $request, 'image');
if ($asset) {
$postData['image'] = $asset->uid;
}
}
// 수정
if ($mode == 'modify') {
if (!$data) {
return $this->sendResult('게시글이 존재하지 않습니다.');
}
// 기존파일 삭제
$delFiles = $request->get('delFiles');
if (!empty($delFiles) && $data->assets) {
foreach ($data->assets as $asset) {
if (in_array($asset->uid, $delFiles)) {
$fileService->deleteFile($asset->uid);
$asset->delete();
}
}
}
$appends = [
'updated_id' => auth()->user()->id,
'updated_at' => (string)Carbon::now()
];
$postData = array_merge($postData, $appends);
$data->fill($postData);
$data->save();
} else {
$appends = [
'uid' => Str::uuid()->toString(),
'created_id' => auth()->user()->id,
'created_at' => (string)Carbon::now()
];
$postData = array_merge($postData, $appends);
$data = BoardArticle::query()->create($postData);
if (!$data) {
return $this->sendResult('게시물 등록에 실패했습니다.');
}
}
// 첨부사진
if ($request->file('files')) {
$assets = $fileService->saveFile(auth()->user(), $request, 'files');
if (is_array($assets)) {
foreach ($assets as $asset) {
if ($asset) {
$assetFields = array(
'article_id' => $data->id,
'uid' => $asset->uid
);
BoardAsset::query()->create($assetFields);
}
}
}
}
if ($mode == 'add') {
$message = '게시물이 등록되었습니다.';
} else {
$message = '게시물 정보가 수정되었습니다.';
}
return $this->sendResult($message, 'success');
});
}
/**
* 에디터 이미지 첨부파일 저장하기
*
* @param Request $request
* @param CrossFileService $fileService
* @return array
*/
protected function editorImageUpload(Request $request, CrossFileService $fileService)
{
$message = '';
$statusCode = '';
$data = [];
$validatorRules = [
'image' => 'bail|required|file|image',
];
$validatorMessages = [
'image' => '이미지 파일만 업로드 가능합니다',
];
$validator = Validator::make($request->all(), $validatorRules, $validatorMessages);
if ($validator->fails()) {
$message = $validator->errors()->first('image');
$statusCode = 'error';
} else {
try {
$asset = $fileService->saveFile(auth()->user(), $request, 'image');
if ($asset) {
$data = [
'name' => $asset->name,
'origin' => $asset->orgin_name,
'size' => $asset->size,
'width' => $asset->width,
'height' => $asset->height,
'url' => '/image/' . $asset->uid
];
$statusCode = 'success';
}
} catch (\Exception $exception) {
$message = '업로드 중 에러가 발생했습니다.';
$statusCode = 'error';
}
}
return $this->sendResult($message, $statusCode, ['data' => $data]);
}
/**
* 첨부 파일 삭제하기
*
* @param Request $request
* @param CrossFileService $fileService
* @return array
*/
public function assetDelete(Request $request, CrossFileService $fileService)
{
$data = BoardAsset::query()->where('uid', $request->uid)->first();
$statusCode = 'error';
if ($data) {
$fileService->deleteFile($data->uid);
$data->delete();
$message = '파일이 삭제되었습니다.';
$statusCode = 'success';
} else {
$message = '파일을 삭제하지 못했습니다.';
}
return $this->sendResult($message, $statusCode);
}
/**
* 댓글 저장하기
*
* @param Request $request
* @return array
*/
protected function storeComment(Request $request)
{
return DB::transaction(function () use ($request) {
$rules = [
'artist_id' => 'required|string',
'content' => 'required|string'
];
$validator = $this->validation($request, $rules);
if ($validator !== true) {
return $this->sendResult($validator);
}
$article_id = $request->get('article_id', 0);
$uid = $request->get('uid', '');
$article = $this->getPostInfo($article_id);
if (!$article_id || !$article) {
return $this->sendResult('게시글이 존재하지 않습니다.');
}
$data = BoardComment::query()->where('uid', $uid)->first();
$postData = $request->only([
'content'
]);
$postData = array_map('setDefault', $postData);
// 수정
if ($uid) {
if (!$data) {
return $this->sendResult('댓글이 존재하지 않습니다.');
}
$appends = [
'updated_id' => auth()->user()->id,
'updated_at' => (string)Carbon::now()
];
$postData = array_merge($postData, $appends);
$data->fill($postData);
$data->save();
return $this->sendResult('댓글이 등록되었습니다.', 'success');
} else {
$uid = Str::uuid()->toString();
$appends = [
'article_id' => $article->id,
'uid' => $uid,
'parent_id' => $uid,
'name' => auth()->user()->name,
'created_id' => auth()->user()->id,
'created_at' => (string)Carbon::now()
];
$postData = array_merge($postData, $appends);
$data = BoardComment::query()->create($postData);
if (!$data) {
return $this->sendResult('댓글 등록에 실패했습니다.');
}
return $this->sendResult('댓글이 수정되었습니다.', 'success');
}
});
}
/**
* 댓글 삭제하기
*
* @param Request $request
* @return array
*/
protected function deleteComment(Request $request)
{
return DB::transaction(function () use ($request) {
$uid = $request->get('uid', '');
$data = BoardComment::query()->where('uid', $uid)->first();
if (!$uid || !$data) {
return $this->sendResult('댓글이 존재하지 않습니다.');
}
$data->delete();
return $this->sendResult('댓글이 삭제되었습니다.', 'success');
});
}
/**
* 게시글 삭제
*
* @param Request $request
* @param CrossFileService $fileService
* @return array
*/
public function deletePost(Request $request, CrossFileService $fileService)
{
$uid = $request->get('uid', '');
$data = $this->getPostInfo($uid);
if (!$uid || !$data) {
return $this->sendResult('해당 게시글이 존재하지 않습니다.');
}
// 댓글 삭제
if ($data->comments_count) {
$data->comments->delete();
}
// 첨부파일 삭제
if ($data->assets) {
foreach ($data->assets as $asset) {
$fileService->deleteFile($asset->uid);
$asset->delete();
}
}
$data->delete();
return $this->sendResult('게시글이 삭제되었습니다.', 'success');
}
}

@ -0,0 +1,204 @@
<?php
namespace App\Libs;
use App\Models\Partner;
use App\Services\CrossFileService;
use Carbon\Carbon;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Str;
trait TraitPartner
{
/**
* 업체목록 가져오기
*
* @param Request $request
* @param int $perPage
* @param bool $status
* @return array
*/
protected function getPartnerList(Request $request, $perPage = 15, $status = true)
{
$list = Partner::query()
->with('user')
->where(function ($query) use ($request, $status) {
if ($request->filled('status')) {
$query->where('status', $request->status);
} else if ($status) {
$query->where('status', 1);
}
if ($request->filled('word')) {
if ($request->filled('field') && $request->field != 'all') {
$query->where($request->field, 'like', '%' . $request->word . '%');
} else {
$query->orWhere('title', 'like', '%'. $request->word .'%');
}
}
})
->latest()
->paginate($perPage);
$list = $this->getListNumber($list);
$search = $request->all();
$list->appends($search);
$searchs = [
'name' => '업체명'
];
$data = [
'mode' => 'list',
'data' => $list,
'search' => $search,
'searchs' => $searchs
];
return $data;
}
/**
* 업체정보 가져오기
*
* @param string $uid
* @return mixed
*/
protected function getPartnerInfo($uid = '')
{
$data = Partner::query()
->with('user')
->where('uid', $uid)
->first();
return $data;
}
/**
* 업체 등록
*
* @param string $uid
* @return array
*/
protected function createPartner($uid = '')
{
if ($uid) {
$data = $this->getPartnerInfo($uid);
$data->mode = 'modify';
} else {
$data = new Partner;
$data->mode = 'add';
$data->uid = '';
$data->category = 1;
$data->status = 1;
}
// logger($data);
return $data;
}
/**
* 업체정보 저장
*
* @param Request $request
* @param CrossFileService $fileService
* @return mixed
*/
protected function storePartner(Request $request, CrossFileService $fileService)
{
return DB::transaction(function() use ($request, $fileService) {
$rules = [
'mode' => 'required|string',
'title' => 'required|string'
];
$validator = $this->validation($request, $rules);
if ($validator !== true) {
return $this->sendResult($validator);
}
$mode = $request->get('mode', 'add');
$uid = $request->get('uid', '');
$data = $this->getPartnerInfo($uid);
$postData = $request->only([
'category', 'title', 'link', 'status'
]);
$postData = array_map('setDefault', $postData);
// 업체이미지
if ($request->hasFile('image')) {
// 기존파일 삭제
if ($data && $data->image) {
$fileService->deleteFile($data->image);
}
$asset = $fileService->saveFile(auth()->user(), $request, 'image');
$postData['image'] = $asset->uid;
$postData['width'] = $asset->width;
$postData['height'] = $asset->height;
}
// 수정
if ($mode == 'modify') {
if (!$data) {
return $this->sendResult('업체정보가 존재하지 않습니다.');
}
$data->fill($postData);
$data->save();
} else {
$appends = [
'uid' => Str::uuid()->toString(),
'created_id' => auth()->user()->id,
'created_at' => (string)Carbon::now()
];
$postData = array_merge($postData, $appends);
$data = Partner::query()->create($postData);
if (!$data) {
return $this->sendResult('업체정보 등록에 실패했습니다.');
}
}
if ($mode == 'add') {
$message = '업체정보가 등록되었습니다.';
} else {
$message = '업체정보가 수정되었습니다.';
}
return $this->sendResult($message, 'success');
});
}
/**
* 업체정보 삭제
*
* @param Request $request
* @param CrossFileService $fileService
* @return mixed
*/
public function deletePartner(Request $request, CrossFileService $fileService)
{
return DB::transaction(function() use ($request, $fileService) {
$uid = $request->get('uid', '');
$data = $this->getPartnerInfo($uid);
if (!$data) {
return $this->sendResult('업체정보가 존재하지 않습니다.');
}
// 기존파일 삭제
if ($data->image) {
$fileService->deleteFile($data->image);
}
$data->delete();
return $this->sendResult('업체정보가 삭제되었습니다.', 'success');
});
}
}

@ -0,0 +1,205 @@
<?php
namespace App\Libs;
use App\Models\Setting;
use Carbon\Carbon;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
trait TraitSetting
{
/**
* 설정목록 가져오기
*
* @param Request $request
* @return array
*/
protected function getSettingList(Request $request)
{
$list = Setting::query()
->with('user')
->where(function ($query) use ($request) {
if ($request->filled('word')) {
if ($request->filled('field') && $request->field != 'all') {
$query->where($request->field, 'like', '%' . $request->word . '%');
} else {
$query->orWhere('name', 'like', '%'. $request->word .'%')
->orWhere('key', 'like', '%'. $request->word .'%')
->orWhere('value', 'like', '%'. $request->word .'%');
}
}
})
->orderBy('key')
->latest()
->get();
$search = $request->all();
$searchs = [
'all' => '통합검색',
'name' => '변수명',
'key' => '변수키',
'value' => '변수값'
];
$data = [
'mode' => 'list',
'data' => $list,
'search' => $search,
'searchs' => $searchs
];
return $data;
}
/**
* 설정변수 가져오기
*
* @param int $id
* @return mixed
*/
protected function getSettingInfo($id = 0)
{
$data = Setting::query()
->with('user')
->where('id', $id)
->first();
return $data;
}
/**
* 설정변수 등록
*
* @param Request $request
* @return array
*/
protected function createSetting(Request $request)
{
$id = $request->get('id', 0);
if ($id) {
$data = $this->getSettingInfo($id);
$data->mode = 'modify';
} else {
$data = new Setting;
$data->mode = 'add';
$data->system = 1;
}
return $data;
}
/**
* 설정변수 저장
*
* @param Request $request
* @return mixed
*/
protected function storeSetting(Request $request)
{
return DB::transaction(function() use ($request) {
$rules = [
'name' => 'required|string|max:100',
'key' => 'required|string|max:30',
'value' => 'string',
'system' => 'integer'
];
$validator = $this->validation($request, $rules);
if ($validator !== true) {
return $this->sendResult($validator);
}
$mode = $request->get('mode', 'add');
$id = $request->get('id', 0);
$data = $this->getSettingInfo($id);
$postData = $request->only([
'name', 'key', 'value'
]);
$postData = array_map('setDefault', $postData);
$postData['system'] = $request->get('system', 0);
// 수정
if ($mode == 'modify') {
if (!$data) {
return $this->sendResult('해당 변수가 존재하지 않습니다.');
}
// 시스템 변수는 key값 수정 불가
if ($data->system && $data->key != $postData['key']) {
return $this->sendResult('시스템 변수는 변수키를 수정할 수 없습니다.');
}
$exist = Setting::query()->whereNotIn('id', [$id])->where('key', $postData['key'])->first();
if ($exist) {
return $this->sendResult('이미 등록된 변수키입니다.');
}
$appends = [
'updated_id' => auth()->user()->id,
'updated_at' => (string)Carbon::now()
];
$postData = array_merge($postData, $appends);
$data->fill($postData);
$data->save();
} else {
$exist = Setting::query()->where('key', $postData['key'])->first();
if ($exist) {
return $this->sendResult('이미 등록된 변수키입니다.');
}
$appends = [
'created_id' => auth()->user()->id,
'created_at' => (string)Carbon::now()
];
$postData = array_merge($postData, $appends);
$data = Setting::query()->create($postData);
if (!$data) {
return $this->sendResult('변수 등록에 실패했습니다.');
}
}
if ($mode == 'add') {
$message = '변수가 등록되었습니다.';
} else {
$message = '변수정보가 수정되었습니다.';
}
return $this->sendResult($message, 'success');
});
}
/**
* 변수 삭제
*
* @param Request $request
* @return mixed
*/
public function deleteSetting(Request $request)
{
return DB::transaction(function() use ($request) {
$id = $request->get('id', 0);
$data = $this->getSettingInfo($id);
// 시스템 변수 삭제 불가
if ($data->system) {
return $this->sendResult('시스템 변수는 삭제할 수 없습니다.');
}
if (!$data) {
return $this->sendResult('해당 변수가 존재하지 않습니다.');
}
$data->delete();
return $this->sendResult('변수가 삭제되었습니다.', 'success');
});
}
}

@ -0,0 +1,206 @@
<?php
namespace App\Libs;
use Illuminate\Auth\Events\PasswordReset;
use Illuminate\Foundation\Auth\RedirectsUsers;
use Illuminate\Foundation\Auth\ResetsPasswords;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Password;
use Illuminate\Support\Str;
use Illuminate\Support\Facades\DB;
use Carbon\Carbon;
trait UserResetsPasswords
{
use RedirectsUsers;
/**
* Where to redirect users after resetting their password.
*
* @var string
*/
protected $redirectTo = '/password/reset-completed';
/**
* Display the password reset view for the given token.
*
* If no token is present, display the link request form.`
*
* @param \Illuminate\Http\Request $request
* @param string|null $token
* @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
*/
public function showResetForm(Request $request, $token = null)
{
$expire = config('auth.passwords.users.expire');
$row = DB::table('password_resets')
->where('email', $request->email)
->where('created_at','>', Carbon::now()->subMinutes($expire))
->first();
return view('auth.passwords.reset')->with(
[
'token' => $token,
'email' => $request->email,
'expire' => $expire,
'row' => $row
]
);
}
/**
* Reset the given user's password.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\RedirectResponse|\Illuminate\Http\JsonResponse
*/
public function reset(Request $request)
{
$request->validate($this->rules($request), $this->validationErrorMessages());
// validate custom 수정
$this->broker()->validator(function (array $credentials)
{
[$password, $confirm] = [
$credentials['password'],
$credentials['password_confirmation'],
];
return $password === $confirm && mb_strlen($password) >= 6 && mb_strlen($password) <= 20;
});
$response = $this->broker()->reset(
$this->credentials($request), function ($user, $password) {
$this->resetPassword($user, $password);
}
);
// If the password was successfully reset, we will redirect the user back to
// the application's home authenticated view. If there is an error we can
// redirect them back to where they came from with their error message.
return $response == Password::PASSWORD_RESET
? $this->sendResetResponse($request, $response)
: $this->sendResetFailedResponse($request, $response);
}
/**
* Get the password reset validation rules.
*
* @return array
*/
protected function rules(Request $request)
{
$rules = [
'token' => 'required',
'email' => 'required|email',
'password' => 'required|confirmed|min:6|max:20',
];
return $rules;
}
/**
* Get the password reset validation error messages.
*
* @return array
*/
protected function validationErrorMessages()
{
return [];
}
/**
* Get the password reset credentials from the request.
*
* @param \Illuminate\Http\Request $request
* @return array
*/
protected function credentials(Request $request)
{
$credentials = $request->only('email', 'password', 'password_confirmation', 'token');
return $credentials;
}
/**
* Reset the given user's password.
*
* @param \Illuminate\Contracts\Auth\CanResetPassword $user
* @param string $password
* @return void
*/
protected function resetPassword($user, $password)
{
$user->password = Hash::make($password);
$user->setRememberToken(Str::random(60));
$user->save();
event(new PasswordReset($user));
$this->guard()->login($user);
}
/**
* Get the response for a successful password reset.
*
* @param \Illuminate\Http\Request $request
* @param string $response
* @return \Illuminate\Http\RedirectResponse|\Illuminate\Http\JsonResponse
*/
protected function sendResetResponse(Request $request, $response)
{
return redirect($this->redirectPath())
->with('status', trans($response));
}
/**
* Get the response for a failed password reset.
*
* @param \Illuminate\Http\Request $request
* @param string $response
* @return \Illuminate\Http\RedirectResponse|\Illuminate\Http\JsonResponse
*/
protected function sendResetFailedResponse(Request $request, $response)
{
$input = $request->only('email');
$errors = ['email' => trans($response)];
if ($response == 'passwords.token') {
$errors['token'] = trans($response);
}
logger($errors);
return redirect()->back()
->withInput($input)
->withErrors($errors);
}
/**
* Get the broker to be used during password reset.
*
* @return \Illuminate\Contracts\Auth\PasswordBroker
*/
public function broker()
{
return Password::broker();
}
/**
* Get the guard to be used during password reset.
*
* @return \Illuminate\Contracts\Auth\StatefulGuard
*/
protected function guard()
{
return Auth::guard();
}
}

@ -0,0 +1,34 @@
<?php
namespace App\Mail;
use Illuminate\Bus\Queueable;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
class InqueryAnswerMailable extends Mailable
{
use Queueable, SerializesModels;
public $data;
/**
* Create a new message instance.
*
* @return void
*/
public function __construct($data)
{
$this->data = $data;
}
/**
* Build the message.
*
* @return $this
*/
public function build()
{
return $this->from('mailer-daemon@dowajwo.com', '도와줘')
->subject("도와줘 홈페이지에 남겨주신 문의 답변입니다.")
->view('emails.inqeury-page-answer');
}
}

@ -0,0 +1,36 @@
<?php
namespace App\Mail;
use Illuminate\Bus\Queueable;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
class ResetPasswordMailable extends Mailable
{
use Queueable, SerializesModels;
public $user;
public $password;
/**
* Create a new message instance.
*
* @return void
*/
public function __construct($user, $password)
{
$this->user = $user;
$this->password = $password;
}
/**
* Build the message.
*
* @return $this
*/
public function build()
{
return $this->from('mailer-daemon@dowajwo.com', '도와줘')
->subject("임시 비밀번호가 발급되었습니다.")
->view('emails.reset-password');
}
}

@ -0,0 +1,25 @@
<?php namespace App\Models;
class Asset extends BaseSoftDeleteModel
{
protected $table = 'asset';
/**
* The attributes that are mass assignable.
*
* @var array
*/
protected $fillable = [
'uid', 'orgin_name', 'name', 'path', 'type', 'size', 'width', 'height', 'count', 'ext'
];
/**
* The attributes that should be hidden for arrays.
*
* @var array
*/
protected $hidden = [
];
}

@ -0,0 +1,30 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\Auth;
abstract class BaseModel extends Model {
protected $casts = [
'created_at' => 'datetime:Y-m-d H:i:s',
'updated_at' => 'datetime:Y-m-d H:i:s',
'deleted_at' => 'datetime:Y-m-d H:i:s',
];
protected $dateFormat = 'Y-m-d H:i:s';
/**
* 자신의 데이터만 구하기 위함
* @param string $column
* @return bool
*/
public function checkOwner($column = "user_id") {
$user = auth()->user();
if (!$user) $user = Auth::user();
if (!$user) $user = new User;
return $this->{$column} == $user->id;
}
}

@ -0,0 +1,10 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\SoftDeletes;
abstract class BaseSoftDeleteModel extends BaseModel {
// 소프트 삭제 사용여부
use SoftDeletes;
}

@ -0,0 +1,33 @@
<?php
namespace App\Models;
class Board extends BaseSoftDeleteModel
{
protected $table = 'board';
/**
* The attributes that are mass assignable.
*
* @var array
*/
protected $fillable = [
'code', 'name', 'skin', 'template', 'status'
];
/**
* The attributes that should be hidden for arrays.
*
* @var array
*/
protected $hidden = [
];
protected $visible = [
'id', 'code', 'name', 'skin', 'template', 'status'
];
public function articles()
{
return $this->hasMany('App\Models\BoardArticle', 'board_id');
}
}

@ -0,0 +1,90 @@
<?php
namespace App\Models;
use App\Casts\EncryptFixed;
use Carbon\Carbon;
class BoardArticle extends BaseSoftDeleteModel
{
protected $table = 'board_article';
/**
* The attributes that are mass assignable.
*
* @var array
*/
protected $fillable = [
'board_id', 'uid',
'notice', 'image', 'category',
'name', 'email', 'phone',
'subject', 'content', 'related_link',
'view_count',
'created_id', 'created_at'
];
/**
* The attributes that should be hidden for arrays.
*
* @var array
*/
protected $hidden = [
];
protected $visible = [
'id', 'board_id', 'uid',
'notice', 'image', 'category',
'name', 'email', 'phone',
'subject', 'content', 'related_link',
'view_count',
'created_id', 'created_at',
'is_new',
'assets', 'assets_count',
'comments', 'comments_count'
];
protected $appends = [
'is_new'
];
/**
* The attributes that should be cast.
*
* @var array<string, string>
*/
protected $casts = [
];
public function getIsNewAttribute()
{
if ($this->created_at) {
return $this->created_at->diffInHours(Carbon::now()) <= 24;
}
return false;
}
public function board()
{
return $this->belongsTo('App\Models\Board', 'board_id');
}
public function asset()
{
return $this->belongsTo('App\Models\Asset', 'image', 'uid');
}
public function assets()
{
return $this->hasMany('App\Models\BoardAsset', 'article_id');
}
public function comments()
{
return $this->hasMany('App\Models\BoardComment', 'article_id');
}
public function user()
{
return $this->belongsTo('App\Models\User', 'created_id');
}
}

@ -0,0 +1,40 @@
<?php
namespace App\Models;
class BoardAsset extends BaseModel
{
protected $table = 'board_assets';
public $timestamps = false;
/**
* The attributes that are mass assignable.
*
* @var array
*/
protected $fillable = [
'article_id',
'uid',
];
/**
* The attributes that should be hidden for arrays.
*
* @var array
*/
protected $hidden = [
];
protected $visible = [
'uid'
];
public function article()
{
return $this->belongsTo('App\Models\BoardArticle', 'article_id');
}
public function asset()
{
return $this->belongsTo('App\Models\Asset', 'uid', 'uid');
}
}

@ -0,0 +1,45 @@
<?php
namespace App\Models;
class BoardComment extends BaseSoftDeleteModel
{
protected $table = 'board_comment';
/**
* The attributes that are mass assignable.
*
* @var array
*/
protected $fillable = [
'article_id',
'uid',
'parent_id',
'content',
'path',
'created_id',
'created_at'
];
/**
* The attributes that should be hidden for arrays.
*
* @var array
*/
protected $hidden = [
];
protected $visible = [
'article_id',
'uid',
'parent_id',
'content',
'path',
'created_id',
'created_at'
];
public function article()
{
return $this->belongsTo('App\Models\BoardArticle', 'article_id');
}
}

@ -0,0 +1,35 @@
<?php
namespace App\Models;
class Counter extends BaseModel
{
protected $table = 'counter';
/**
* The attributes that are mass assignable.
*
* @var array<int, string>
*/
protected $fillable = [
'lo_date', 'lo_count'
];
protected $visible = [
'lo_date', 'lo_count'
];
/**
* 카운터 저장
* param : Array $data
* return : Void
*/
public static function add($data)
{
return self::query()->create([
'lo_date' => $data['lo_date'],
'lo_count' => $data['lo_count']
]);
}
}

@ -0,0 +1,54 @@
<?php
namespace App\Models;
class Partner extends BaseSoftDeleteModel
{
protected $table = 'partner';
/**
* The attributes that are mass assignable.
*
* @var array<int, string>
*/
protected $fillable = [
'uid',
'category', 'title', 'link', 'image', 'width', 'height',
'status',
'created_id',
'created_at', 'updated_at', 'deleted_at'
];
/**
* The attributes that should be hidden for serialization.
*
* @var array<int, string>
*/
protected $hidden = [
];
protected $visible = [
'uid',
'category', 'title', 'link', 'image', 'width', 'height',
'status',
'created_at'
];
/**
* The attributes that should be cast.
*
* @var array<string, string>
*/
protected $casts = [
'category' => 'integer',
'width' => 'integer',
'height' => 'integer',
'status' => 'integer'
];
public function user()
{
return $this->belongsTo('App\Models\User', 'created_id');
}
}

@ -0,0 +1,49 @@
<?php
namespace App\Models;
use Illuminate\Support\Str;
use Carbon\Carbon;
class Seo extends BaseModel
{
protected $table = 'seo';
/**
* The attributes that are mass assignable.
*
* @var array<int, string>
*/
protected $fillable = [
'uid', 'page', 'title', 'description', 'keywords',
'created_id', 'updated_id', 'deleted_id',
'created_at', 'updated_at', 'deleted_at'
];
/**
* The attributes that should be hidden for serialization.
*
* @var array<int, string>
*/
protected $hidden = [
];
protected $visible = [
'uid', 'page', 'title', 'description', 'keywords',
'created_id',
'created_at', 'updated_at'
];
/**
* The attributes that should be cast.
*
* @var array<string, string>
*/
protected $casts = [
];
public function user()
{
return $this->belongsTo('App\Models\User', 'created_id');
}
}

@ -0,0 +1,49 @@
<?php
namespace App\Models;
use Carbon\Carbon;
class Setting extends BaseModel
{
protected $table = 'setting';
/**
* The attributes that are mass assignable.
*
* @var array<int, string>
*/
protected $fillable = [
'name', 'key', 'value', 'system',
'created_id', 'updated_id',
'created_at', 'updated_at'
];
/**
* The attributes that should be hidden for serialization.
*
* @var array<int, string>
*/
protected $hidden = [
];
protected $visible = [
'id', 'name', 'key', 'value', 'system',
'created_id',
'created_at'
];
/**
* The attributes that should be cast.
*
* @var array<string, string>
*/
protected $casts = [
'system' => 'integer'
];
public function user()
{
return $this->belongsTo('App\Models\User', 'created_id');
}
}

@ -0,0 +1,222 @@
<?php
namespace App\Models;
use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Laravel\Sanctum\HasApiTokens;
use Illuminate\Support\Facades\Mail;
use Yadahan\AuthenticationLog\AuthenticationLogable;
use Carbon\Carbon;
use App\Libs\EncryptUser;
use App\Libs\EncryptQuery;
use App\Casts\EncryptFixed;
class User extends Authenticatable
{
use HasApiTokens, HasFactory, Notifiable;
use SoftDeletes;
use AuthenticationLogable;
use EncryptUser, EncryptQuery {
EncryptUser::setAttribute as setEncryptAttribute;
EncryptUser::getAttribute as getEncryptAttribute;
}
protected $table = 'user';
/**
* The attributes that are mass assignable.
*
* @var array<int, string>
*/
protected $fillable = [
'uid',
'type',
'email',
'email_verify',
'phone',
'phone_verify',
'name',
'memo',
'password',
'agree_service',
'agree_private',
'agree_marketing',
'status',
];
/**
* The attributes that should be hidden for serialization.
*
* @var array<int, string>
*/
protected $hidden = [
'password',
'remember_token',
];
protected $visible = [
'uid',
'type',
'email',
'email_verify',
'phone',
'phone_verify',
'name',
'memo',
'status',
];
/**
* The attributes that should be cast.
*
* @var array<string, string>
*/
protected $casts = [
'email' => EncryptFixed::class,
'name' => EncryptFixed::class,
'phone' => EncryptFixed::class
];
public function getAttribute($key)
{
if (in_array($key, $this->encryptable)) {
$value = $this->getEncryptAttribute($key);
} else {
$value = parent::getAttribute($key);
}
return $value;
}
public function setAttribute($key, $value)
{
if (in_array($key, $this->encryptable)) {
$this->setEncryptAttribute($key, $value);
} else {
parent::setAttribute($key, $value);
}
}
/**
* Get the entity's last logout at.
*/
public function lastLogoutAt()
{
return optional($this->authentications()->first())->logout_at;
}
/**
* Get age from birthday.
*/
public function getBirthDayAgeAttribute()
{
$birthday = $this->getAttribute('birthday');
if (empty($birthday)) {
return '';
}
$birthday = Carbon::parse($birthday);
if ($birthday) {
return $birthday->age;
}
return '';
}
/**
* 회원 탈퇴 처리
* @param string $id
* @return array
*/
public static function userSignout($id) {
$time = Carbon::now()->format("YmdHis");
$data = self::query()->find($id);
// 탈퇴시 중복체크 피하기 위함
$data->email = $data->email .'#'. $time;
$data->phone = $data->phone .'#'. $time;
$data->status = 'SignOut';
$data->save();
// 삭제 처리
$data->delete();
return [
'success' => true,
'message' => '회원 탈퇴 완료',
'data' => $data->toArray()
];
}
/**
* 회원 복구 처리
* @param string $id
* @return array
*/
public static function userRestore($id) {
$data = self::query()->withTrashed()->find($id);
// 복구
$data->email = trimSignoutText($data->email);
$data->phone = trimSignoutText($data->phone);
$data->status = 'Registered';
// 중복검사
$count = self::query()->whereCrypt('email', $data->email)->count();
if ($count) {
return ['success' => false, 'message' => '이미 존재하는 이메일입니다.\n복구할 수 없습니다.'];
}
$count = self::query()->whereCrypt('phone', $data->phone)->count();
if ($count) {
return ['success' => false, 'message' => '이미 가입된 전화번호입니다.\n복구할 수 없습니다.'];
}
$data->save();
// 복구 처리
$data = self::query()->withTrashed()->find($id);
$data->restore();
return ['success' => true, 'message' => '복구되었습니다.'];
}
/**
* 비밀번호 재설정 이메일 전송 오버라이드
* @param $token
* @return void
*/
public function sendPasswordResetNotification($token) {
$data = [
$this->email
];
Mail::send('emails.reset-password-email', [
'expire' => config('auth.passwords.users.expire'),
'reset_url' => route('password.reset', ['token' => $token, 'email' => $this->email]),
], function($message) use($data){
$message->subject('요청하신 비밀번호 재설정 안내 메일입니다');
$message->to($data[0]);
});
}
public function getAppends()
{
if (!count($this->appends)) {
return [];
}
return $this->getArrayableItems(
array_combine($this->appends, $this->appends)
);
}
}

@ -0,0 +1,58 @@
<?php
namespace App\Models;
class Visitor extends BaseModel
{
protected $table = 'visitor';
/**
* The attributes that are mass assignable.
*
* @var array<int, string>
*/
protected $fillable = [
'lo_ip', 'lo_date', 'lo_timealue', 'lo_week',
'lo_agent', 'lo_referer', 'lo_device'
];
/**
* The attributes that should be hidden for serialization.
*
* @var array<int, string>
*/
protected $hidden = [
];
protected $visible = [
'lo_ip', 'lo_date', 'lo_time', 'lo_week',
'lo_agent', 'lo_referer', 'lo_device'
];
/**
* The attributes that should be cast.
*
* @var array<string, string>
*/
protected $casts = [
];
/**
* 방문로그 저장
* param : Array $data
* return : Void
*/
public static function add($data)
{
return self::query()->create([
'lo_ip' => $data['lo_ip'],
'lo_date' => $data['lo_date'],
'lo_time' => $data['lo_time'],
'lo_week' => $data['lo_week'],
'lo_agent' => $data['lo_agent'],
'lo_referer' => $data['lo_referer'],
'lo_device' => $data['lo_device']
]);
}
}

@ -0,0 +1,36 @@
<?php
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
use Illuminate\Pagination\Paginator;
use Illuminate\Support\Facades\Validator;
class AppServiceProvider extends ServiceProvider
{
/**
* Register any application services.
*
* @return void
*/
public function register()
{
//
}
/**
* Bootstrap any application services.
*
* @return void
*/
public function boot()
{
$schemaType = config('app.schema_type', 'https');
if ($schemaType == 'https') {
// URL::forceScheme('https');
$this->app['request']->server->set('HTTPS', true);
}
Paginator::defaultView('layouts.paginator');
}
}

@ -0,0 +1,32 @@
<?php
namespace App\Providers;
use Illuminate\Support\Facades\Auth;
use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider;
class AuthServiceProvider extends ServiceProvider
{
/**
* The policy mappings for the application.
*
* @var array<class-string, class-string>
*/
protected $policies = [
// 'App\Models\Model' => 'App\Policies\ModelPolicy',
];
/**
* Register any authentication / authorization services.
*
* @return void
*/
public function boot()
{
$this->registerPolicies();
Auth::provider('cryptUsers', function($app, array $config) {
return new CryptUserProvider($app['hash'], $config['model']);
});
}
}

@ -0,0 +1,21 @@
<?php
namespace App\Providers;
use Illuminate\Support\Facades\Broadcast;
use Illuminate\Support\ServiceProvider;
class BroadcastServiceProvider extends ServiceProvider
{
/**
* Bootstrap any application services.
*
* @return void
*/
public function boot()
{
Broadcast::routes();
require base_path('routes/channels.php');
}
}

@ -0,0 +1,50 @@
<?php
namespace App\Providers;
use Illuminate\Auth\EloquentUserProvider;
use Illuminate\Contracts\Support\Arrayable;
use Illuminate\Support\Str;
use App\Casts\EncryptFixed;
class CryptUserProvider extends EloquentUserProvider
{
/**
* Retrieve a user by the given credentials.
*
* @param array $credentials
* @return \Illuminate\Contracts\Auth\Authenticatable|null
*/
public function retrieveByCredentials(array $credentials)
{
if (empty($credentials) || (count($credentials) === 1 && Str::contains($this->firstCredentialKey($credentials), 'password'))) {
return;
}
// First we will add each credential element to the query as a where clause.
// Then we can execute the query and, if we found a user, return it in a
// Eloquent Front "model" that will be utilized by the Guard instances.
$query = $this->newModelQuery();
$userModel = $this->createModel();
foreach ($credentials as $key => $value) {
if (Str::contains($key, 'password')) {
continue;
}
logger($key . " : " . $value);
if (Str::contains($key, ['email','phone','name'])) {
$query->whereCrypt($key, $value);
} else if ($value instanceof EncryptFixed) {
$query->whereCrypt($key, $value);
} else if (is_array($value) || $value instanceof Arrayable) {
$query->whereIn($key, $value);
} else {
$query->where($key, $value);
}
}
return $query->first();
}
}

@ -0,0 +1,32 @@
<?php
namespace App\Providers;
use Illuminate\Auth\Events\Registered;
use Illuminate\Auth\Listeners\SendEmailVerificationNotification;
use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider;
use Illuminate\Support\Facades\Event;
class EventServiceProvider extends ServiceProvider
{
/**
* The event listener mappings for the application.
*
* @var array<class-string, array<int, class-string>>
*/
protected $listen = [
Registered::class => [
SendEmailVerificationNotification::class,
],
];
/**
* Register any events for your application.
*
* @return void
*/
public function boot()
{
//
}
}

@ -0,0 +1,144 @@
<?php namespace App\Providers;
use Collective\Html\FormFacade;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\HtmlString;
use Illuminate\Support\ServiceProvider;
use Illuminate\Support\Str;
class FormMacroServiceProvider extends ServiceProvider
{
/**
* Bootstrap the application services.
*
* @return void
*/
public function boot()
{
FormFacade::macro('quickForm', function (Model $model, $params = []) {
$funcGeneaterRoute = function ($model, $data) use($params) {
if(is_array($data)) {
$args = [];
if(isset($data[1]) && count($data[1]) > 0) {
foreach($data[1] as $key=>$attr) {
// $params 에서 찾기
if(isset($params[$attr])) {
$args[$key] = $params[$attr];
}
// 모델에서 찾기
if(property_exists($model, $attr)) {
$args[$key] = $model->{$attr};
}
// request 에서 찾기
if(request()->has($attr)) {
$args[$key] = request()->get($attr, '');
}
}
}
return route($data[0], $args);
}
return route($data);
};
$htmls = [];
if(property_exists($model, 'form')) {
$form = $model->form;
$htmls[] = FormFacade::model($model, ['id'=>'form', 'route'=>$form['action'], 'files' => true]);
$inputs = $model->inputs;
$rows = [];
foreach($inputs as $name => $element) {
$rowHtml = [];
$rowHtml['label'] = '';
$rowHtml['html'] = '';
// hidden
if($name == '#') {
$rowHtml['hidden'] = $element;
$rows[] = $rowHtml;
continue;
}
// custom view
else if(Str::startsWith($name, '@')) {
$rowHtml['view'] = $element;
$rows[] = $rowHtml;
continue;
}
$type = 'text';
if(isset($element['type'])) $type = $element['type'];
$rowHtml['label'] = FormFacade::label($name, $element['label']);
if($type == 'text') $rowHtml['html'] = FormFacade::text($name, null, array_merge(['class'=>'form-control'], isset($element['attrs'])?$element['attrs']:[]));
else if($type == 'textarea') $rowHtml['html'] = FormFacade::textarea($name, null, array_merge(['class'=>'form-control'], isset($element['attrs'])?$element['attrs']:[]));
else if($type == 'select') $rowHtml['html'] = FormFacade::select($name, $element['data'], null, array_merge(['class'=>'form-control'], isset($element['attrs'])?$element['attrs']:[]));
else if($type == 'radio') {
$radioLables = [];
$radioHtmls = [];
if(isset($element['data'])) {
$no = 0;
foreach($element['data'] as $value => $text) {
$id = $name.'-'.($no++);
$radioLables[] = FormFacade::label($id, $text, ['class'=>'custom-control-label']);
$radioHtmls[] = FormFacade::radio($name, $value, null, array_merge(['id'=>$id, 'class'=>'custom-control-input'], isset($element['attrs'])?$element['attrs']:[]));
}
}
$radioHtml = [];
foreach($radioLables as $index=>$label) {
$radioHtml[] = sprintf('<div class="custom-control custom-radio custom-control-inline">%s%s</div>', $radioHtmls[$index], $label);
}
$rowHtml['html'] = sprintf('<div class="frame-wrap">%s</div>', implode("", $radioHtml));
}
else if($type == 'file') $rowHtml['html'] = sprintf('<div class="custom-file">%s<label class="custom-file-label" for="customFile">파일선택</label></div>', FormFacade::file($name, ['class'=>'custom-file-input']));
$rows[] = $rowHtml;
}
$inputHtml = [];
foreach($rows as $row) {
if(isset($row['hidden'])) {
foreach($row['hidden'] as $hidden) {
$inputHtml[] = FormFacade::hidden($hidden);
}
}
else if(isset($row['view'])) $inputHtml[] = view($row['view'], array_merge(['data' => $model], $params))->render();
else $inputHtml[] = sprintf('<div class="form-group">%s%s</div>', $row['label'], $row['html']);
}
$htmls[] = implode("\n", $inputHtml);
$buttonText = '저장';
if($model->id > 0) $buttonText = '수정';
$buttons = [];
if(isset($form['list'])) $buttons[] = sprintf('<div class="col-sm"><a href="%s" class="btn btn-info btn-list">목록</a></div>', $funcGeneaterRoute($model, $form['list']));
else $buttons[] = '<div class="col-sm"></div>';
$buttons[] = sprintf('<div class="col-sm text-center">%s</div>', FormFacade::button($buttonText, ['type'=>'submit', 'class'=>'btn btn-primary waves-effect waves-themed']));
if(isset($form['delete'])) $buttons[] = sprintf('<div class="col-sm text-right"><a href="%s" class="btn btn-danger btn-delete">삭제</a></div>', $funcGeneaterRoute($model, $form['delete']));
else $buttons[] = '<div class="col-sm text-right"></div>';
$htmls[] = sprintf('<div class="row">%s</div>', implode("\n", $buttons) );
$htmls[] = FormFacade::close();
}
return new HtmlString( implode("\n", $htmls) );
});
}
/**
* Register any application services.
*
* @return void
*/
public function register()
{
//
}
}

@ -0,0 +1,68 @@
<?php
namespace App\Providers;
use Illuminate\Cache\RateLimiting\Limit;
use Illuminate\Foundation\Support\Providers\RouteServiceProvider as ServiceProvider;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\RateLimiter;
use Illuminate\Support\Facades\Route;
class RouteServiceProvider extends ServiceProvider
{
/**
* The path to the "home" route for your application.
*
* This is used by Laravel authentication to redirect users after login.
*
* @var string
*/
public const HOME = '/';
/**
* The controller namespace for the application.
*
* When present, controller route declarations will automatically be prefixed with this namespace.
*
* @var string|null
*/
protected $namespace = 'App\\Http\\Controllers';
/**
* Define your route model bindings, pattern filters, etc.
*
* @return void
*/
public function boot()
{
$this->configureRateLimiting();
$this->routes(function () {
Route::prefix('api')
->middleware('api')
->namespace($this->namespace)
->group(base_path('routes/api.php'));
Route::middleware('web')
->namespace($this->namespace)
->group(base_path('routes/web.php'));
Route::middleware('web')
->prefix(config('admin.prefix'))
->namespace($this->namespace)
->group(base_path('routes/admin.php'));
});
}
/**
* Configure the rate limiters for the application.
*
* @return void
*/
protected function configureRateLimiting()
{
RateLimiter::for('api', function (Request $request) {
return Limit::perMinute(60)->by(optional($request->user())->id ?: $request->ip());
});
}
}

@ -0,0 +1,43 @@
<?php
namespace App\Services;
use Illuminate\Http\Request;
class CrossFileService
{
/**
* @var FileInterface
*/
private $fileService;
public function __construct()
{
$this->fileService = new DiskFileService();
}
public function deleteFile($uid, $callback = null)
{
$this->fileService->deleteFile($uid, $callback);
}
public function saveFile($user, Request $request, $name = 'file')
{
return $this->fileService->saveFile($user, $request, $name);
}
public function download($uid)
{
return $this->fileService->download($uid);
}
public function downloadImageRate($uid, $type, $size)
{
return $this->fileService->downloadImageRate($uid, $type, $size);
}
public function downloadImage($uid, $width, $height)
{
return $this->fileService->downloadImage($uid, $width, $height);
}
}

@ -0,0 +1,249 @@
<?php
namespace App\Services;
use App\Models\Asset;
use Illuminate\Http\Request;
use Illuminate\Http\UploadedFile;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Str;
use Intervention\Image\Facades\Image;
use Symfony\Component\HttpFoundation\BinaryFileResponse;
class DiskFileService implements FileInterface
{
private $dirver = 'local';
private $uploadPath = 'upload';
private $storage;
public function __construct()
{
$this->storage = Storage::disk($this->dirver);
}
public function deleteFile($uid, $callback = '')
{
$asset = Asset::query()->where('uid', $uid)->first();
if ($asset && !empty($asset->path) && !empty($asset->name)) {
$file = $asset->path . $asset->name;
logger('file delete : ' . $file);
if ($this->storage->exists($file)) {
$this->storage->delete($file);
logger('Deleted OK!');
}
$asset->delete();
}
if (!empty($callback)) {
$callback();
}
}
public function saveFile($user, Request $request, $name = 'file')
{
$file = $request->file($name);
if (is_array($file)) {
$files = $file;
$file = null;
$saves = [];
foreach ($files as $file) {
$saves[] = $this->save($user, $file);
}
return $saves;
} else if ($file) {
return $this->save($user, $file);
}
return false;
}
public function save($user, UploadedFile $file)
{
if ($file == null || !$file->isValid()) {
return false;
}
logger($file->getClientOriginalName() . " - " . $file->getMimeType() . " - " . $file->getSize() . " - " . $file->getClientOriginalExtension());
// 날짜 별로 누적
$save_path = $this->uploadPath . '/' . date('Y/m/d/');
$this->storage->makeDirectory($save_path);
$data = array();
$allowedImageMimeTypes = ['image/jpeg','image/gif','image/png','image/bmp','image/svg+xml'];
// 서버 파일 저장용 이름 변경
$save_name = md5(microtime() . $file->getClientOriginalName()) . '.' . $file->getClientOriginalExtension();
$destinationPath = $this->storage->path($save_path);
logger($destinationPath . $save_name);
$data['uid'] = Str::uuid()->toString();
$data['orgin_name'] = $file->getClientOriginalName();
$data['name'] = $save_name;
$data['path'] = $save_path;
$data['type'] = $file->getMimeType();
$data['size'] = $file->getSize();
$data['ext'] = strtolower($file->getClientOriginalExtension());
$data['count'] = 0;
$data['created_id'] = $user->id;
if ($file->move($destinationPath, $save_name)) {
if (in_array($data['type'], $allowedImageMimeTypes)) {
// 가로세로 자동 회전
$image = Image::make($destinationPath . '/' . $save_name);
if($data['ext'] == 'jpg' || $data['ext'] == 'jpeg') {
$image->orientate()->save($destinationPath . '/' . $save_name);
}
// 가로세로 사이즈 구하기
$image = Image::make($destinationPath . '/' . $save_name);
$data['width'] = $image->width();
$data['height'] = $image->height();
}
logger('Saved OK!');
// 데이터 DB 저장
return Asset::query()->create($data);
}
logger('Saved Fail!');
return false;
}
public function download($uid, string $name = null)
{
$headers = array();
$asset = Asset::query()->where('uid', $uid)->first();
if (!$asset || $asset->id == 0) {
abort(404, "파일이 존재하지 않습니다.");
}
$asset->increment('count');
$file = $asset->path . $asset->name;
if (!$this->storage->exists($file)) {
abort(404, '파일이 존재하지 않습니다.');
}
$fullPath = $this->storage->path($file);
//download 통합. 다운로드 파일이름 커스텀시 그것으로 사용.
$down_name = $asset->orgin_name;
if($name) {
$down_name = $name . '.' . $asset->ext;
}
return response()->download($fullPath, $down_name, $headers);
}
public function stream($uid)
{
$asset = Asset::query()->where('uid', $uid)->first();
if (!$asset || $asset->id == 0) {
abort(404, '파일이 존재하지 않습니다.');
}
$asset->increment("count");
$file = $asset->path . $asset->name;
if (!$this->storage->exists($file)) {
abort(404, '파일이 존재하지 않습니다.');
}
$fullPath = $this->storage->path($file);
logger('stream file : ' . $fullPath);
$response = new BinaryFileResponse($fullPath);
BinaryFileResponse::trustXSendfileTypeHeader();
return $response;
}
public function downloadImageRate($uid, $type, $size)
{
$headers = array();
$asset = Asset::query()->where('uid', $uid)->first();
$thumbFolder = $type . $size;
if (!$asset || $asset->id == 0) {
abort(404, '파일이 존재하지 않습니다.');
}
// $asset->increment("count");
$file = $asset->path . $asset->name;
$thumbPath = $asset->path . $thumbFolder;
$thumbFile = $thumbPath . '/' . $asset->name;
if (!$this->storage->exists($thumbFile)) {
if ($this->storage->exists($file)) {
$save_path = $asset->path . $thumbFolder;
$this->storage->makeDirectory($save_path);
$fullPath = $this->storage->path($file);
// 너비 고정
if ($type == 'w') {
Image::make($fullPath)->resize($size, null, function ($constraint) {
$constraint->aspectRatio();
$constraint->upsize();
})->save($this->storage->path($thumbFile));
// 높이 고정
} else if ($type == 'h') {
Image::make($fullPath)->resize(null, $size, function ($constraint) {
$constraint->aspectRatio();
$constraint->upsize();
})->save($this->storage->path($thumbFile));
}
}
}
if (!$this->storage->exists($thumbFile)) {
abort(404, '파일이 존재하지 않습니다.');
}
return response()->download($this->storage->path($thumbFile), $asset->orgin_name, $headers);
}
public function downloadImage($uid, $width, $height)
{
$headers = array();
$asset = Asset::query()->where('uid', $uid)->first();
$thumbFolder = $width .'x'. $height;
if (!$asset || $asset->id == 0) {
abort(404, '파일이 존재하지 않습니다.');
}
$asset->increment('count');
$file = $asset->path . $asset->name;
$thumbPath = $asset->path . $thumbFolder;
$thumbFile = $thumbPath . '/' . $asset->name;
if (!$this->storage->exists($thumbFile)) {
if ($this->storage->exists($file)) {
$save_path = $asset->path . $thumbFolder;
$this->storage->makeDirectory($save_path);
Image::make($this->storage->path($file))->fit($width, $height, function ($constraint) {
$constraint->upsize();
})->save($this->storage->path($thumbFile));
}
}
if (!$this->storage->exists($thumbFile)) {
abort(404, '파일이 존재하지 않습니다.');
}
// logger("------------- download -----------");
return response()->download($this->storage->path($thumbFile), $asset->orgin_name, $headers);
}
}

@ -0,0 +1,38 @@
<?php
namespace App\Services;
use App\Models\User;
use Illuminate\Support\Facades\Mail;
class EmailService
{
public function sendUserFromKey($id, $title, $message, $files = array())
{
$user = User::find($id);
$this->sendUsers( array( $user ), $title, $message, $files);
}
public function sendUser($user, $title, $message, $files = array())
{
$this->sendUsers( array( $user ), $title, $message, $files);
}
public function sendUsers(array $users, $title, $message, $files = array())
{
foreach($users as $user) {
$this->sendEmail($user->userid, $user->name, $title, $message, $files);
}
}
public function sendEmail($email, $name, $title, $messageText, $files = array())
{
Mail::raw( $messageText, function ($message) use ($email, $name, $title, $messageText, $files) {
$message->subject($title);
$message->setBody($messageText, 'text/html');
$message->from('mailer-daemon@dowajwo.com', '도와줘');
$message->to($email, $name);
foreach($files as $file) {
$message->attach($file['path'], ['as' => $file['name']]);
}
});
}
}
?>

@ -0,0 +1,14 @@
<?php
namespace App\Services;
use Illuminate\Http\Request;
use Illuminate\Http\UploadedFile;
interface FileInterface
{
public function deleteFile($uid, $callback = null);
public function saveFile($user, Request $request, $name = 'file');
public function download($uid);
public function downloadImageRate($uid, $type, $size);
public function downloadImage($uid, $width, $height);
}

@ -0,0 +1,19 @@
<?php
namespace App\Services;
class ParseText {
private $data;
public function __construct($text)
{
$this->data = [];
foreach(explode("\n", $text) as $line) {
$row = explode(':', $line);
if(count($row) > 1 && !empty(trim($row[0]))) $this->data[trim($row[0])] = trim($row[1]);
}
// logger($text);
}
public function value($key) {
return $this->data[$key] ?? null;
}
}

@ -0,0 +1,28 @@
<?php namespace App\Validators;
use App\Models\User;
class Validation {
public function validateIsUserDuplicatePhone($attribute, $value, $parameters, $validator)
{
$phone = removeHyphen(filterPhone($value));
$type = 'Front';
$validatorData = $validator->getData();
if(isset($validatorData['type'])) $type = $validatorData['type'];
$user = User::query()->whereCrypt('phone', $phone)->where('type', $type);
// uid 가 있다면 자신은 제외
if(isset($validatorData['uid'])) {
$uid = $validatorData['uid'];
$user->where('uid', '<>', $uid);
}
$count = $user->count();
return $count == 0;
}
}

@ -0,0 +1,53 @@
#!/usr/bin/env php
<?php
define('LARAVEL_START', microtime(true));
/*
|--------------------------------------------------------------------------
| Register The Auto Loader
|--------------------------------------------------------------------------
|
| Composer provides a convenient, automatically generated class loader
| for our application. We just need to utilize it! We'll require it
| into the script here so that we do not have to worry about the
| loading of any of our classes manually. It's great to relax.
|
*/
require __DIR__.'/vendor/autoload.php';
$app = require_once __DIR__.'/bootstrap/app.php';
/*
|--------------------------------------------------------------------------
| Run The Artisan Application
|--------------------------------------------------------------------------
|
| When we run the console application, the current CLI command will be
| executed in this console and the response sent back to a terminal
| or another output device for the developers. Here goes nothing!
|
*/
$kernel = $app->make(Illuminate\Contracts\Console\Kernel::class);
$status = $kernel->handle(
$input = new Symfony\Component\Console\Input\ArgvInput,
new Symfony\Component\Console\Output\ConsoleOutput
);
/*
|--------------------------------------------------------------------------
| Shutdown The Application
|--------------------------------------------------------------------------
|
| Once Artisan has finished running, we will fire off the shutdown events
| so that any final work may be done by the application before we shut
| down the process. This is the last thing to happen to the request.
|
*/
$kernel->terminate($input, $status);
exit($status);

@ -0,0 +1,90 @@
{
"name": "laravel/laravel",
"type": "project",
"description": "The Laravel Framework.",
"keywords": ["framework", "laravel"],
"license": "MIT",
"require": {
"php": "^7.3|^8.0",
"ext-curl": "*",
"ext-json": "*",
"ext-openssl": "*",
"ext-pdo": "*",
"ext-zlib": "*",
"fideloper/proxy": "^4.3",
"fruitcake/laravel-cors": "^2.0",
"grimzy/laravel-mysql-spatial": "4.0",
"guzzlehttp/guzzle": "^7.0.1",
"intervention/image": "^2.7",
"jenssegers/agent": "^2.6",
"jeroennoten/laravel-adminlte": "^3.8",
"laravel/framework": "^8.75",
"laravel/sanctum": "^2.11",
"laravel/socialite": "^5.5",
"laravel/tinker": "^2.5",
"laravel/ui": "^3.4",
"laravelcollective/html": "^6.3",
"league/flysystem-aws-s3-v3": "~1",
"mlntn/laravel-unique-queue": "^1.3",
"overtrue/laravel-query-logger": "^2.1",
"predis/predis": "^2.0",
"riverskies/laravel-mobile-detect": "^1.3",
"sentry/sentry-laravel": "^2.13",
"yadahan/laravel-authentication-log": "^1.5",
"yajra/laravel-datatables": "^1.5"
},
"require-dev": {
"roave/security-advisories": "dev-latest",
"beyondcode/laravel-dump-server": "^1.8",
"facade/ignition": "^2.5",
"fakerphp/faker": "^1.9.1",
"filp/whoops": "^2.14",
"laravel/sail": "^1.0.1",
"mockery/mockery": "^1.5",
"nunomaduro/collision": "^5.11",
"phpunit/phpunit": "^9.5.10"
},
"autoload": {
"psr-4": {
"App\\": "app/",
"Database\\Factories\\": "database/factories/",
"Database\\Seeders\\": "database/seeders/"
},
"files": [
"app/Helpers.php"
]
},
"autoload-dev": {
"psr-4": {
"Tests\\": "tests/"
}
},
"scripts": {
"post-autoload-dump": [
"Illuminate\\Foundation\\ComposerScripts::postAutoloadDump",
"@php artisan package:discover --ansi"
],
"post-update-cmd": [
"@php artisan vendor:publish --tag=laravel-assets --ansi --force"
],
"post-root-package-install": [
"@php -r \"file_exists('.env') || copy('.env.example', '.env');\""
],
"post-create-project-cmd": [
"@php artisan key:generate --ansi"
]
},
"extra": {
"laravel": {
"dont-discover": []
}
},
"config": {
"optimize-autoloader": true,
"preferred-install": "dist",
"sort-packages": true,
"platform-check": false
},
"minimum-stability": "dev",
"prefer-stable": true
}

@ -0,0 +1,4 @@
<?php
return [
'prefix' => env('APP_ADMIN_PREFIX', 'admin'),
];

@ -0,0 +1,476 @@
<?php
return [
/*
|--------------------------------------------------------------------------
| Title
|--------------------------------------------------------------------------
|
| Here you can change the default title of your admin panel.
|
| For detailed instructions you can look the title section here:
| https://github.com/jeroennoten/Laravel-AdminLTE/wiki/Basic-Configuration
|
*/
'title' => 'AdminLTE 3',
'title_prefix' => '',
'title_postfix' => '',
/*
|--------------------------------------------------------------------------
| Favicon
|--------------------------------------------------------------------------
|
| Here you can activate the favicon.
|
| For detailed instructions you can look the favicon section here:
| https://github.com/jeroennoten/Laravel-AdminLTE/wiki/Basic-Configuration
|
*/
'use_ico_only' => false,
'use_full_favicon' => false,
/*
|--------------------------------------------------------------------------
| Logo
|--------------------------------------------------------------------------
|
| Here you can change the logo of your admin panel.
|
| For detailed instructions you can look the logo section here:
| https://github.com/jeroennoten/Laravel-AdminLTE/wiki/Basic-Configuration
|
*/
'logo' => '<b>Admin</b>LTE',
'logo_img' => 'vendor/adminlte/dist/img/AdminLTELogo.png',
'logo_img_class' => 'brand-image img-circle elevation-3',
'logo_img_xl' => null,
'logo_img_xl_class' => 'brand-image-xs',
'logo_img_alt' => 'AdminLTE',
/*
|--------------------------------------------------------------------------
| User Menu
|--------------------------------------------------------------------------
|
| Here you can activate and change the user menu.
|
| For detailed instructions you can look the user menu section here:
| https://github.com/jeroennoten/Laravel-AdminLTE/wiki/Basic-Configuration
|
*/
'usermenu_enabled' => true,
'usermenu_header' => false,
'usermenu_header_class' => 'bg-primary',
'usermenu_image' => false,
'usermenu_desc' => false,
'usermenu_profile_url' => false,
/*
|--------------------------------------------------------------------------
| Layout
|--------------------------------------------------------------------------
|
| Here we change the layout of your admin panel.
|
| For detailed instructions you can look the layout section here:
| https://github.com/jeroennoten/Laravel-AdminLTE/wiki/Layout-and-Styling-Configuration
|
*/
'layout_topnav' => null,
'layout_boxed' => null,
'layout_fixed_sidebar' => null,
'layout_fixed_navbar' => null,
'layout_fixed_footer' => null,
'layout_dark_mode' => null,
/*
|--------------------------------------------------------------------------
| Authentication Views Classes
|--------------------------------------------------------------------------
|
| Here you can change the look and behavior of the authentication views.
|
| For detailed instructions you can look the auth classes section here:
| https://github.com/jeroennoten/Laravel-AdminLTE/wiki/Layout-and-Styling-Configuration
|
*/
'classes_auth_card' => 'card-outline card-primary',
'classes_auth_header' => '',
'classes_auth_body' => '',
'classes_auth_footer' => '',
'classes_auth_icon' => '',
'classes_auth_btn' => 'btn-flat btn-primary',
/*
|--------------------------------------------------------------------------
| Admin Panel Classes
|--------------------------------------------------------------------------
|
| Here you can change the look and behavior of the admin panel.
|
| For detailed instructions you can look the admin panel classes here:
| https://github.com/jeroennoten/Laravel-AdminLTE/wiki/Layout-and-Styling-Configuration
|
*/
'classes_body' => '',
'classes_brand' => '',
'classes_brand_text' => '',
'classes_content_wrapper' => '',
'classes_content_header' => '',
'classes_content' => '',
'classes_sidebar' => 'sidebar-dark-primary elevation-4',
'classes_sidebar_nav' => '',
'classes_topnav' => 'navbar-white navbar-light',
'classes_topnav_nav' => 'navbar-expand',
'classes_topnav_container' => 'container',
/*
|--------------------------------------------------------------------------
| Sidebar
|--------------------------------------------------------------------------
|
| Here we can modify the sidebar of the admin panel.
|
| For detailed instructions you can look the sidebar section here:
| https://github.com/jeroennoten/Laravel-AdminLTE/wiki/Layout-and-Styling-Configuration
|
*/
'sidebar_mini' => 'lg',
'sidebar_collapse' => false,
'sidebar_collapse_auto_size' => false,
'sidebar_collapse_remember' => false,
'sidebar_collapse_remember_no_transition' => true,
'sidebar_scrollbar_theme' => 'os-theme-light',
'sidebar_scrollbar_auto_hide' => 'l',
'sidebar_nav_accordion' => true,
'sidebar_nav_animation_speed' => 300,
/*
|--------------------------------------------------------------------------
| Control Sidebar (Right Sidebar)
|--------------------------------------------------------------------------
|
| Here we can modify the right sidebar aka control sidebar of the admin panel.
|
| For detailed instructions you can look the right sidebar section here:
| https://github.com/jeroennoten/Laravel-AdminLTE/wiki/Layout-and-Styling-Configuration
|
*/
'right_sidebar' => false,
'right_sidebar_icon' => 'fas fa-cogs',
'right_sidebar_theme' => 'dark',
'right_sidebar_slide' => true,
'right_sidebar_push' => true,
'right_sidebar_scrollbar_theme' => 'os-theme-light',
'right_sidebar_scrollbar_auto_hide' => 'l',
/*
|--------------------------------------------------------------------------
| URLs
|--------------------------------------------------------------------------
|
| Here we can modify the url settings of the admin panel.
|
| For detailed instructions you can look the urls section here:
| https://github.com/jeroennoten/Laravel-AdminLTE/wiki/Basic-Configuration
|
*/
'use_route_url' => false,
'dashboard_url' => 'home',
'logout_url' => 'logout',
'login_url' => 'login',
'register_url' => 'register',
'password_reset_url' => 'password/reset',
'password_email_url' => 'password/email',
'profile_url' => false,
/*
|--------------------------------------------------------------------------
| Laravel Mix
|--------------------------------------------------------------------------
|
| Here we can enable the Laravel Mix option for the admin panel.
|
| For detailed instructions you can look the laravel mix section here:
| https://github.com/jeroennoten/Laravel-AdminLTE/wiki/Other-Configuration
|
*/
'enabled_laravel_mix' => false,
'laravel_mix_css_path' => 'css/app.css',
'laravel_mix_js_path' => 'js/app.js',
/*
|--------------------------------------------------------------------------
| Menu Items
|--------------------------------------------------------------------------
|
| Here we can modify the sidebar/top navigation of the admin panel.
|
| For detailed instructions you can look here:
| https://github.com/jeroennoten/Laravel-AdminLTE/wiki/Menu-Configuration
|
*/
'menu' => [
// Navbar items:
[
'type' => 'navbar-search',
'text' => 'search',
'topnav_right' => true,
],
[
'type' => 'fullscreen-widget',
'topnav_right' => true,
],
// Sidebar items:
[
'type' => 'sidebar-menu-search',
'text' => 'search',
],
[
'text' => 'blog',
'url' => 'admin/blog',
'can' => 'manage-blog',
],
[
'text' => 'pages',
'url' => 'admin/pages',
'icon' => 'far fa-fw fa-file',
'label' => 4,
'label_color' => 'success',
],
['header' => 'account_settings'],
[
'text' => 'profile',
'url' => 'admin/settings',
'icon' => 'fas fa-fw fa-user',
],
[
'text' => 'change_password',
'url' => 'admin/settings',
'icon' => 'fas fa-fw fa-lock',
],
[
'text' => 'multilevel',
'icon' => 'fas fa-fw fa-share',
'submenu' => [
[
'text' => 'level_one',
'url' => '#',
],
[
'text' => 'level_one',
'url' => '#',
'submenu' => [
[
'text' => 'level_two',
'url' => '#',
],
[
'text' => 'level_two',
'url' => '#',
'submenu' => [
[
'text' => 'level_three',
'url' => '#',
],
[
'text' => 'level_three',
'url' => '#',
],
],
],
],
],
[
'text' => 'level_one',
'url' => '#',
],
],
],
['header' => 'labels'],
[
'text' => 'important',
'icon_color' => 'red',
'url' => '#',
],
[
'text' => 'warning',
'icon_color' => 'yellow',
'url' => '#',
],
[
'text' => 'information',
'icon_color' => 'cyan',
'url' => '#',
],
],
/*
|--------------------------------------------------------------------------
| Menu Filters
|--------------------------------------------------------------------------
|
| Here we can modify the menu filters of the admin panel.
|
| For detailed instructions you can look the menu filters section here:
| https://github.com/jeroennoten/Laravel-AdminLTE/wiki/Menu-Configuration
|
*/
'filters' => [
JeroenNoten\LaravelAdminLte\Menu\Filters\GateFilter::class,
JeroenNoten\LaravelAdminLte\Menu\Filters\HrefFilter::class,
JeroenNoten\LaravelAdminLte\Menu\Filters\SearchFilter::class,
JeroenNoten\LaravelAdminLte\Menu\Filters\ActiveFilter::class,
JeroenNoten\LaravelAdminLte\Menu\Filters\ClassesFilter::class,
JeroenNoten\LaravelAdminLte\Menu\Filters\LangFilter::class,
JeroenNoten\LaravelAdminLte\Menu\Filters\DataFilter::class,
],
/*
|--------------------------------------------------------------------------
| Plugins Initialization
|--------------------------------------------------------------------------
|
| Here we can modify the plugins used inside the admin panel.
|
| For detailed instructions you can look the plugins section here:
| https://github.com/jeroennoten/Laravel-AdminLTE/wiki/Plugins-Configuration
|
*/
'plugins' => [
'Datatables' => [
'active' => false,
'files' => [
[
'type' => 'js',
'asset' => false,
'location' => '//cdn.datatables.net/1.10.19/js/jquery.dataTables.min.js',
],
[
'type' => 'js',
'asset' => false,
'location' => '//cdn.datatables.net/1.10.19/js/dataTables.bootstrap4.min.js',
],
[
'type' => 'css',
'asset' => false,
'location' => '//cdn.datatables.net/1.10.19/css/dataTables.bootstrap4.min.css',
],
],
],
'Select2' => [
'active' => false,
'files' => [
[
'type' => 'js',
'asset' => false,
'location' => '//cdnjs.cloudflare.com/ajax/libs/select2/4.0.3/js/select2.min.js',
],
[
'type' => 'css',
'asset' => false,
'location' => '//cdnjs.cloudflare.com/ajax/libs/select2/4.0.3/css/select2.css',
],
],
],
'Chartjs' => [
'active' => false,
'files' => [
[
'type' => 'js',
'asset' => false,
'location' => '//cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.0/Chart.bundle.min.js',
],
],
],
'Sweetalert2' => [
'active' => false,
'files' => [
[
'type' => 'js',
'asset' => false,
'location' => '//cdn.jsdelivr.net/npm/sweetalert2@8',
],
],
],
'Pace' => [
'active' => false,
'files' => [
[
'type' => 'css',
'asset' => false,
'location' => '//cdnjs.cloudflare.com/ajax/libs/pace/1.0.2/themes/blue/pace-theme-center-radar.min.css',
],
[
'type' => 'js',
'asset' => false,
'location' => '//cdnjs.cloudflare.com/ajax/libs/pace/1.0.2/pace.min.js',
],
],
],
],
/*
|--------------------------------------------------------------------------
| IFrame
|--------------------------------------------------------------------------
|
| Here we change the IFrame mode configuration. Note these changes will
| only apply to the view that extends and enable the IFrame mode.
|
| For detailed instructions you can look the iframe mode section here:
| https://github.com/jeroennoten/Laravel-AdminLTE/wiki/IFrame-Mode-Configuration
|
*/
'iframe' => [
'default_tab' => [
'url' => null,
'title' => null,
],
'buttons' => [
'close' => true,
'close_all' => true,
'close_all_other' => true,
'scroll_left' => true,
'scroll_right' => true,
'fullscreen' => true,
],
'options' => [
'loading_screen' => 1000,
'auto_show_new_tab' => true,
'use_navbar_items' => true,
],
],
/*
|--------------------------------------------------------------------------
| Livewire
|--------------------------------------------------------------------------
|
| Here we can enable the Livewire support.
|
| For detailed instructions you can look the livewire here:
| https://github.com/jeroennoten/Laravel-AdminLTE/wiki/Other-Configuration
|
*/
'livewire' => false,
];

@ -0,0 +1,253 @@
<?php
return [
/*
|--------------------------------------------------------------------------
| Application Name
|--------------------------------------------------------------------------
|
| This value is the name of your application. This value is used when the
| framework needs to place the application's name in a notification or
| any other location as required by the application or its packages.
|
*/
'name' => env('APP_NAME', 'Laravel'),
/*
|--------------------------------------------------------------------------
| Application Environment
|--------------------------------------------------------------------------
|
| This value determines the "environment" your application is currently
| running in. This may determine how you prefer to configure various
| services the application utilizes. Set this in your ".env" file.
|
*/
'env' => env('APP_ENV', 'production'),
/*
|--------------------------------------------------------------------------
| Application Debug Mode
|--------------------------------------------------------------------------
|
| When your application is in debug mode, detailed error messages with
| stack traces will be shown on every error that occurs within your
| application. If disabled, a simple generic error page is shown.
|
*/
'debug' => (bool) env('APP_DEBUG', false),
'debug_type' => env('APP_DEBUG_TYPE', 'real'),
'file_server' => env('APP_FILE_SERVER', 'local'),
'schema_type' => env('APP_SCHEMA_TYPE', 'http'),
/*
|--------------------------------------------------------------------------
| Application URL
|--------------------------------------------------------------------------
|
| This URL is used by the console to properly generate URLs when using
| the Artisan command line tool. You should set this to the root of
| your application so that it is used when running Artisan tasks.
|
*/
'url' => env('APP_URL', 'http://localhost'),
'asset_url' => env('ASSET_URL', null),
/*
|--------------------------------------------------------------------------
| Application Timezone
|--------------------------------------------------------------------------
|
| Here you may specify the default timezone for your application, which
| will be used by the PHP date and date-time functions. We have gone
| ahead and set this to a sensible default for you out of the box.
|
*/
'timezone' => 'Asia/Seoul',
/*
|--------------------------------------------------------------------------
| Application Locale Configuration
|--------------------------------------------------------------------------
|
| The application locale determines the default locale that will be used
| by the translation service provider. You are free to set this value
| to any of the locales which will be supported by the application.
|
*/
'locale' => 'ko',
/*
|--------------------------------------------------------------------------
| Application Fallback Locale
|--------------------------------------------------------------------------
|
| The fallback locale determines the locale to use when the current one
| is not available. You may change the value to correspond to any of
| the language folders that are provided through your application.
|
*/
'fallback_locale' => 'en',
/*
|--------------------------------------------------------------------------
| Faker Locale
|--------------------------------------------------------------------------
|
| This locale will be used by the Faker PHP library when generating fake
| data for your database seeds. For example, this will be used to get
| localized telephone numbers, street address information and more.
|
*/
'faker_locale' => 'en_US',
/*
|--------------------------------------------------------------------------
| Encryption Key
|--------------------------------------------------------------------------
|
| This key is used by the Illuminate encrypter service and should be set
| to a random, 32 character string, otherwise these encrypted strings
| will not be safe. Please do this before deploying an application!
|
*/
'key' => env('APP_KEY'),
'cipher' => 'AES-256-CBC',
/*
|--------------------------------------------------------------------------
| Autoloaded Service Providers
|--------------------------------------------------------------------------
|
| The service providers listed here will be automatically loaded on the
| request to your application. Feel free to add your own services to
| this array to grant expanded functionality to your applications.
|
*/
'providers' => [
/*
* Laravel Framework Service Providers...
*/
Illuminate\Auth\AuthServiceProvider::class,
Illuminate\Broadcasting\BroadcastServiceProvider::class,
Illuminate\Bus\BusServiceProvider::class,
Illuminate\Cache\CacheServiceProvider::class,
Illuminate\Foundation\Providers\ConsoleSupportServiceProvider::class,
Illuminate\Cookie\CookieServiceProvider::class,
Illuminate\Database\DatabaseServiceProvider::class,
Illuminate\Encryption\EncryptionServiceProvider::class,
Illuminate\Filesystem\FilesystemServiceProvider::class,
Illuminate\Foundation\Providers\FoundationServiceProvider::class,
Illuminate\Hashing\HashServiceProvider::class,
Illuminate\Mail\MailServiceProvider::class,
Illuminate\Notifications\NotificationServiceProvider::class,
Illuminate\Pagination\PaginationServiceProvider::class,
Illuminate\Pipeline\PipelineServiceProvider::class,
Illuminate\Queue\QueueServiceProvider::class,
Illuminate\Redis\RedisServiceProvider::class,
Illuminate\Auth\Passwords\PasswordResetServiceProvider::class,
Illuminate\Session\SessionServiceProvider::class,
Illuminate\Translation\TranslationServiceProvider::class,
Illuminate\Validation\ValidationServiceProvider::class,
Illuminate\View\ViewServiceProvider::class,
/*
* Package Service Providers...
*/
/*
* Application Service Providers...
*/
App\Providers\AppServiceProvider::class,
App\Providers\AuthServiceProvider::class,
App\Providers\BroadcastServiceProvider::class,
App\Providers\EventServiceProvider::class,
App\Providers\RouteServiceProvider::class,
Collective\Html\HtmlServiceProvider::class,
// image thumbnail
Intervention\Image\ImageServiceProvider::class,
// datatable
Yajra\DataTables\DataTablesServiceProvider::class,
Yajra\DataTables\HtmlServiceProvider::class,
Yajra\DataTables\ButtonsServiceProvider::class,
],
/*
|--------------------------------------------------------------------------
| Class Aliases
|--------------------------------------------------------------------------
|
| This array of class aliases will be registered when this application
| is started. However, feel free to register as many as you wish as
| the aliases are "lazy" loaded so they don't hinder performance.
|
*/
'aliases' => [
'App' => Illuminate\Support\Facades\App::class,
'Arr' => Illuminate\Support\Arr::class,
'Artisan' => Illuminate\Support\Facades\Artisan::class,
'Auth' => Illuminate\Support\Facades\Auth::class,
'Blade' => Illuminate\Support\Facades\Blade::class,
'Broadcast' => Illuminate\Support\Facades\Broadcast::class,
'Bus' => Illuminate\Support\Facades\Bus::class,
'Cache' => Illuminate\Support\Facades\Cache::class,
'Config' => Illuminate\Support\Facades\Config::class,
'Cookie' => Illuminate\Support\Facades\Cookie::class,
'Crypt' => Illuminate\Support\Facades\Crypt::class,
'Date' => Illuminate\Support\Facades\Date::class,
'DB' => Illuminate\Support\Facades\DB::class,
'Eloquent' => Illuminate\Database\Eloquent\Model::class,
'Event' => Illuminate\Support\Facades\Event::class,
'File' => Illuminate\Support\Facades\File::class,
'Gate' => Illuminate\Support\Facades\Gate::class,
'Hash' => Illuminate\Support\Facades\Hash::class,
'Http' => Illuminate\Support\Facades\Http::class,
'Js' => Illuminate\Support\Js::class,
'Lang' => Illuminate\Support\Facades\Lang::class,
'Log' => Illuminate\Support\Facades\Log::class,
'Mail' => Illuminate\Support\Facades\Mail::class,
'Notification' => Illuminate\Support\Facades\Notification::class,
'Password' => Illuminate\Support\Facades\Password::class,
'Queue' => Illuminate\Support\Facades\Queue::class,
'RateLimiter' => Illuminate\Support\Facades\RateLimiter::class,
'Redirect' => Illuminate\Support\Facades\Redirect::class,
'Redis' => Illuminate\Support\Facades\Redis::class,
'Request' => Illuminate\Support\Facades\Request::class,
'Response' => Illuminate\Support\Facades\Response::class,
'Route' => Illuminate\Support\Facades\Route::class,
'Schema' => Illuminate\Support\Facades\Schema::class,
'Session' => Illuminate\Support\Facades\Session::class,
'Storage' => Illuminate\Support\Facades\Storage::class,
'Str' => Illuminate\Support\Str::class,
'URL' => Illuminate\Support\Facades\URL::class,
'Validator' => Illuminate\Support\Facades\Validator::class,
'View' => Illuminate\Support\Facades\View::class,
'Form' => Collective\Html\FormFacade::class,
'Html' => Collective\Html\HtmlFacade::class,
'Image' => Intervention\Image\Facades\Image::class,
'MobileDetect' => Riverskies\Laravel\MobileDetect\Facades\MobileDetect::class,
],
];

@ -0,0 +1,116 @@
<?php
return [
/*
|--------------------------------------------------------------------------
| Authentication Defaults
|--------------------------------------------------------------------------
|
| This option controls the default authentication "guard" and password
| reset options for your application. You may change these defaults
| as required, but they're a perfect start for most applications.
|
*/
'defaults' => [
'guard' => 'web',
'passwords' => 'users',
],
/*
|--------------------------------------------------------------------------
| Authentication Guards
|--------------------------------------------------------------------------
|
| Next, you may define every authentication guard for your application.
| Of course, a great default configuration has been defined for you
| here which uses session storage and the Eloquent user provider.
|
| All authentication drivers have a user provider. This defines how the
| users are actually retrieved out of your database or other storage
| mechanisms used by this application to persist your user's data.
|
| Supported: "session"
|
*/
'guards' => [
'web' => [
'driver' => 'session',
'provider' => 'users',
]
],
/*
|--------------------------------------------------------------------------
| Front Providers
|--------------------------------------------------------------------------
|
| All authentication drivers have a user provider. This defines how the
| users are actually retrieved out of your database or other storage
| mechanisms used by this application to persist your user's data.
|
| If you have multiple user tables or models you may configure multiple
| sources which represent each model / table. These sources may then
| be assigned to any extra authentication guards you have defined.
|
| Supported: "database", "eloquent"
|
*/
'providers' => [
'users' => [
'driver' => 'cryptUsers',
'model' => App\Models\User::class,
],
//'users' => [
// 'driver' => 'eloquent',
// 'model' => App\Models\Front::class,
//],
// 'users' => [
// 'driver' => 'database',
// 'table' => 'users',
// ],
],
/*
|--------------------------------------------------------------------------
| Resetting Passwords
|--------------------------------------------------------------------------
|
| You may specify multiple password reset configurations if you have more
| than one user table or model in the application and you want to have
| separate password reset settings based on the specific user types.
|
| The expire time is the number of minutes that each reset token will be
| considered valid. This security feature keeps tokens short-lived so
| they have less time to be guessed. You may change this as needed.
|
*/
'passwords' => [
'users' => [
'provider' => 'users',
'table' => 'password_resets',
'expire' => 60,
'throttle' => 60,
],
],
/*
|--------------------------------------------------------------------------
| Password Confirmation Timeout
|--------------------------------------------------------------------------
|
| Here you may define the amount of seconds before a password confirmation
| times out and the user is prompted to re-enter their password via the
| confirmation screen. By default, the timeout lasts for three hours.
|
*/
'password_timeout' => 10800,
];

@ -0,0 +1,64 @@
<?php
return [
/*
|--------------------------------------------------------------------------
| Default Broadcaster
|--------------------------------------------------------------------------
|
| This option controls the default broadcaster that will be used by the
| framework when an event needs to be broadcast. You may set this to
| any of the connections defined in the "connections" array below.
|
| Supported: "pusher", "ably", "redis", "log", "null"
|
*/
'default' => env('BROADCAST_DRIVER', 'null'),
/*
|--------------------------------------------------------------------------
| Broadcast Connections
|--------------------------------------------------------------------------
|
| Here you may define all of the broadcast connections that will be used
| to broadcast events to other systems or over websockets. Samples of
| each available type of connection are provided inside this array.
|
*/
'connections' => [
'pusher' => [
'driver' => 'pusher',
'key' => env('PUSHER_APP_KEY'),
'secret' => env('PUSHER_APP_SECRET'),
'app_id' => env('PUSHER_APP_ID'),
'options' => [
'cluster' => env('PUSHER_APP_CLUSTER'),
'useTLS' => true,
],
],
'ably' => [
'driver' => 'ably',
'key' => env('ABLY_KEY'),
],
'redis' => [
'driver' => 'redis',
'connection' => 'default',
],
'log' => [
'driver' => 'log',
],
'null' => [
'driver' => 'null',
],
],
];

@ -0,0 +1,110 @@
<?php
use Illuminate\Support\Str;
return [
/*
|--------------------------------------------------------------------------
| Default Cache Store
|--------------------------------------------------------------------------
|
| This option controls the default cache connection that gets used while
| using this caching library. This connection is used when another is
| not explicitly specified when executing a given caching function.
|
*/
'default' => env('CACHE_DRIVER', 'file'),
/*
|--------------------------------------------------------------------------
| Cache Stores
|--------------------------------------------------------------------------
|
| Here you may define all of the cache "stores" for your application as
| well as their drivers. You may even define multiple stores for the
| same cache driver to group types of items stored in your caches.
|
| Supported drivers: "apc", "array", "database", "file",
| "memcached", "redis", "dynamodb", "octane", "null"
|
*/
'stores' => [
'apc' => [
'driver' => 'apc',
],
'array' => [
'driver' => 'array',
'serialize' => false,
],
'database' => [
'driver' => 'database',
'table' => 'cache',
'connection' => null,
'lock_connection' => null,
],
'file' => [
'driver' => 'file',
'path' => storage_path('framework/cache/data'),
],
'memcached' => [
'driver' => 'memcached',
'persistent_id' => env('MEMCACHED_PERSISTENT_ID'),
'sasl' => [
env('MEMCACHED_USERNAME'),
env('MEMCACHED_PASSWORD'),
],
'options' => [
// Memcached::OPT_CONNECT_TIMEOUT => 2000,
],
'servers' => [
[
'host' => env('MEMCACHED_HOST', '127.0.0.1'),
'port' => env('MEMCACHED_PORT', 11211),
'weight' => 100,
],
],
],
'redis' => [
'driver' => 'redis',
'connection' => 'cache',
'lock_connection' => 'default',
],
'dynamodb' => [
'driver' => 'dynamodb',
'key' => env('AWS_ACCESS_KEY_ID'),
'secret' => env('AWS_SECRET_ACCESS_KEY'),
'region' => env('AWS_DEFAULT_REGION', 'us-east-1'),
'table' => env('DYNAMODB_CACHE_TABLE', 'cache'),
'endpoint' => env('DYNAMODB_ENDPOINT'),
],
'octane' => [
'driver' => 'octane',
],
],
/*
|--------------------------------------------------------------------------
| Cache Key Prefix
|--------------------------------------------------------------------------
|
| When utilizing a RAM based store such as APC or Memcached, there might
| be other applications utilizing the same cache. So, we'll specify a
| value to get prefixed to all our keys so we can avoid collisions.
|
*/
'prefix' => env('CACHE_PREFIX', Str::slug(env('APP_NAME', 'laravel'), '_').'_cache'),
];

@ -0,0 +1,34 @@
<?php
return [
/*
|--------------------------------------------------------------------------
| Cross-Origin Resource Sharing (CORS) Configuration
|--------------------------------------------------------------------------
|
| Here you may configure your settings for cross-origin resource sharing
| or "CORS". This determines what cross-origin operations may execute
| in web browsers. You are free to adjust these settings as needed.
|
| To learn more: https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS
|
*/
'paths' => ['api/*', 'sanctum/csrf-cookie'],
'allowed_methods' => ['*'],
'allowed_origins' => ['*'],
'allowed_origins_patterns' => [],
'allowed_headers' => ['*'],
'exposed_headers' => [],
'max_age' => 0,
'supports_credentials' => false,
];

@ -0,0 +1,160 @@
<?php
use Illuminate\Support\Str;
return [
/*
|--------------------------------------------------------------------------
| Default Database Connection Name
|--------------------------------------------------------------------------
|
| Here you may specify which of the database connections below you wish
| to use as your default connection for all database work. Of course
| you may use many connections at once using the Database library.
|
*/
'default' => env('DB_CONNECTION', 'mysql'),
/*
|--------------------------------------------------------------------------
| Database Connections
|--------------------------------------------------------------------------
|
| Here are each of the database connections setup for your application.
| Of course, examples of configuring each database platform that is
| supported by Laravel is shown below to make development simple.
|
|
| All database work in Laravel is done through the PHP PDO facilities
| so make sure you have the driver for your particular database of
| choice installed on your machine before you begin development.
|
*/
'connections' => [
'sqlite' => [
'driver' => 'sqlite',
'url' => env('DATABASE_URL'),
'database' => env('DB_DATABASE', database_path('database.sqlite')),
'prefix' => '',
'foreign_key_constraints' => env('DB_FOREIGN_KEYS', true),
],
'mysql' => [
'driver' => 'mysql',
'url' => env('DATABASE_URL'),
'host' => env('DB_HOST', '127.0.0.1'),
'port' => env('DB_PORT', '3306'),
'database' => env('DB_DATABASE', 'forge'),
'username' => env('DB_USERNAME', 'forge'),
'password' => env('DB_PASSWORD', ''),
'unix_socket' => env('DB_SOCKET', ''),
'charset' => 'utf8mb4',
'collation' => 'utf8mb4_0900_ai_ci',
'prefix' => env('DB_PREFIX', ''),
'prefix_indexes' => true,
'sticky' => env('DB_STICKY', true),
'engine' => null,
'options' => extension_loaded('pdo_mysql') ? array_filter([
PDO::MYSQL_ATTR_SSL_CA => env('MYSQL_ATTR_SSL_CA'),
]) : [],
],
'pgsql' => [
'driver' => 'pgsql',
'url' => env('DATABASE_URL'),
'host' => env('DB_HOST', '127.0.0.1'),
'port' => env('DB_PORT', '5432'),
'database' => env('DB_DATABASE', 'forge'),
'username' => env('DB_USERNAME', 'forge'),
'password' => env('DB_PASSWORD', ''),
'charset' => 'utf8',
'prefix' => '',
'prefix_indexes' => true,
'schema' => 'public',
'sslmode' => 'prefer',
],
'sqlsrv' => [
'driver' => 'sqlsrv',
'url' => env('DATABASE_URL'),
'host' => env('DB_HOST', 'localhost'),
'port' => env('DB_PORT', '1433'),
'database' => env('DB_DATABASE', 'forge'),
'username' => env('DB_USERNAME', 'forge'),
'password' => env('DB_PASSWORD', ''),
'charset' => 'utf8',
'prefix' => '',
'prefix_indexes' => true,
],
],
/*
|--------------------------------------------------------------------------
| Migration Repository Table
|--------------------------------------------------------------------------
|
| This table keeps track of all the migrations that have already run for
| your application. Using this information, we can determine which of
| the migrations on disk haven't actually been run in the database.
|
*/
'migrations' => 'migrations',
/*
|--------------------------------------------------------------------------
| Redis Databases
|--------------------------------------------------------------------------
|
| Redis is an open source, fast, and advanced key-value store that also
| provides a richer body of commands than a typical key-value system
| such as APC or Memcached. Laravel makes it easy to dig right in.
|
*/
'redis' => [
'client' => env('REDIS_CLIENT', 'phpredis'),
'options' => [
'cluster' => env('REDIS_CLUSTER', 'redis'),
'prefix' => env('REDIS_PREFIX', Str::slug(env('APP_NAME', 'laravel'), '_').'_database_'),
],
'default' => [
'url' => env('REDIS_URL'),
'host' => env('REDIS_HOST', '127.0.0.1'),
'password' => env('REDIS_PASSWORD', null),
'port' => env('REDIS_PORT', '6379'),
'database' => env('REDIS_DB', '0'),
],
'cache' => [
'url' => env('REDIS_URL'),
'host' => env('REDIS_HOST', '127.0.0.1'),
'password' => env('REDIS_PASSWORD', null),
'port' => env('REDIS_PORT', '6379'),
'database' => env('REDIS_CACHE_DB', '1'),
],
'queue' => [
'host' => env('REDIS_QUEUE_HOST', '127.0.0.1'),
'password' => env('REDIS_QUEUE_PASSWORD', null),
'port' => env('REDIS_QUEUE_PORT', 6379),
'database' => 0,
],
'push' => [
'host' => env('REDIS_PUSH_HOST', '127.0.0.1'),
'password' => env('REDIS_PUSH_PASSWORD', null),
'port' => env('REDIS_PUSH_PORT', 6379),
'database' => env('REDIS_PUSH_DB', 1),
],
],
];

@ -0,0 +1,90 @@
<?php
return [
/*
* Namespaces used by the generator.
*/
'namespace' => [
/*
* Base namespace/directory to create the new file.
* This is appended on default Laravel namespace.
* Usage: php artisan datatables:make Front
* Output: App\DataTables\UserDataTable
* With Model: App\Front (default model)
* Export filename: users_timestamp
*/
'base' => 'DataTables',
/*
* Base namespace/directory where your model's are located.
* This is appended on default Laravel namespace.
* Usage: php artisan datatables:make Post --model
* Output: App\DataTables\PostDataTable
* With Model: App\Post
* Export filename: posts_timestamp
*/
'model' => '',
],
/*
* Set Custom stub folder
*/
//'stub' => '/resources/custom_stub',
/*
* PDF generator to be used when converting the table to pdf.
* Available generators: excel, snappy
* Snappy package: barryvdh/laravel-snappy
* Excel package: maatwebsite/excel
*/
'pdf_generator' => 'snappy',
/*
* Snappy PDF options.
*/
'snappy' => [
'options' => [
'no-outline' => true,
'margin-left' => '0',
'margin-right' => '0',
'margin-top' => '10mm',
'margin-bottom' => '10mm',
],
'orientation' => 'landscape',
],
/*
* Default html builder parameters.
*/
'parameters' => [
'dom' => 'Bfrtip',
'order' => [[0, 'desc']],
'buttons' => [
'create',
'export',
'print',
'reset',
'reload',
],
],
/*
* Generator command default options value.
*/
'generator' => [
/*
* Default columns to generate when not set.
*/
'columns' => 'id,add your columns,created_at,updated_at',
/*
* Default buttons to generate when not set.
*/
'buttons' => 'create,export,print,reset,reload',
/*
* Default DOM to generate when not set.
*/
'dom' => 'Bfrtip',
],
];

@ -0,0 +1,122 @@
<?php
return [
/*
* DataTables search options.
*/
'search' => [
/*
* Smart search will enclose search keyword with wildcard string "%keyword%".
* SQL: column LIKE "%keyword%"
*/
'smart' => true,
/*
* Multi-term search will explode search keyword using spaces resulting into multiple term search.
*/
'multi_term' => true,
/*
* Case insensitive will search the keyword in lower case format.
* SQL: LOWER(column) LIKE LOWER(keyword)
*/
'case_insensitive' => true,
/*
* Wild card will add "%" in between every characters of the keyword.
* SQL: column LIKE "%k%e%y%w%o%r%d%"
*/
'use_wildcards' => false,
/*
* Perform a search which starts with the given keyword.
* SQL: column LIKE "keyword%"
*/
'starts_with' => false,
],
/*
* DataTables internal index id response column name.
*/
'index_column' => 'DT_RowIndex',
/*
* List of available builders for DataTables.
* This is where you can register your custom dataTables builder.
*/
'engines' => [
'eloquent' => Yajra\DataTables\EloquentDataTable::class,
'query' => Yajra\DataTables\QueryDataTable::class,
'collection' => Yajra\DataTables\CollectionDataTable::class,
'resource' => Yajra\DataTables\ApiResourceDataTable::class,
],
/*
* DataTables accepted builder to engine mapping.
* This is where you can override which engine a builder should use
* Note, only change this if you know what you are doing!
*/
'builders' => [
//Illuminate\Database\Eloquent\Relations\Relation::class => 'eloquent',
//Illuminate\Database\Eloquent\Builder::class => 'eloquent',
//Illuminate\Database\Query\Builder::class => 'query',
//Illuminate\Support\Collection::class => 'collection',
],
/*
* Nulls last sql pattern for PostgreSQL & Oracle.
* For MySQL, use 'CASE WHEN :column IS NULL THEN 1 ELSE 0 END, :column :direction'
*/
'nulls_last_sql' => ':column :direction NULLS LAST',
/*
* Front friendly message to be displayed on user if error occurs.
* Possible values:
* null - The exception message will be used on error response.
* 'throw' - Throws a \Yajra\DataTables\Exceptions\Exception. Use your custom error handler if needed.
* 'custom message' - Any friendly message to be displayed to the user. You can also use translation key.
*/
'error' => env('DATATABLES_ERROR', null),
/*
* Default columns definition of dataTable utility functions.
*/
'columns' => [
/*
* List of columns hidden/removed on json response.
*/
'excess' => ['rn', 'row_num'],
/*
* List of columns to be escaped. If set to *, all columns are escape.
* Note: You can set the value to empty array to disable XSS protection.
*/
'escape' => '*',
/*
* List of columns that are allowed to display html content.
* Note: Adding columns to list will make us available to XSS attacks.
*/
'raw' => ['action'],
/*
* List of columns are are forbidden from being searched/sorted.
*/
'blacklist' => ['password', 'remember_token'],
/*
* List of columns that are only allowed fo search/sort.
* If set to *, all columns are allowed.
*/
'whitelist' => '*',
],
/*
* JsonResponse header and options config.
*/
'json' => [
'header' => [],
'options' => 0,
],
];

@ -0,0 +1,21 @@
<?php
return [
'user' => [
'type' => [
'default' => 'User',
'roles' => [
'admin' => [
'label' => '관리자',
'type' => 'Admin',
],
'user' => [
'label' => '회원',
'type' => 'User',
]
]
],
'status' => [
'default' => 'Waiting'
]
],
];

@ -0,0 +1,73 @@
<?php
return [
/*
|--------------------------------------------------------------------------
| Default Filesystem Disk
|--------------------------------------------------------------------------
|
| Here you may specify the default filesystem disk that should be used
| by the framework. The "local" disk, as well as a variety of cloud
| based disks are available to your application. Just store away!
|
*/
'default' => env('FILESYSTEM_DRIVER', 'local'),
/*
|--------------------------------------------------------------------------
| Filesystem Disks
|--------------------------------------------------------------------------
|
| Here you may configure as many filesystem "disks" as you wish, and you
| may even configure multiple disks of the same driver. Defaults have
| been setup for each driver as an example of the required options.
|
| Supported Drivers: "local", "ftp", "sftp", "s3"
|
*/
'disks' => [
'local' => [
'driver' => 'local',
'root' => storage_path('app'),
],
'public' => [
'driver' => 'local',
'root' => storage_path('app/public'),
'url' => env('APP_URL').'/storage',
'visibility' => 'public',
],
's3' => [
'driver' => 's3',
'key' => env('AWS_ACCESS_KEY_ID'),
'secret' => env('AWS_SECRET_ACCESS_KEY'),
'region' => env('AWS_DEFAULT_REGION'),
'bucket' => env('AWS_BUCKET'),
'url' => env('AWS_URL'),
'endpoint' => env('AWS_ENDPOINT'),
'use_path_style_endpoint' => env('AWS_USE_PATH_STYLE_ENDPOINT', false),
],
],
/*
|--------------------------------------------------------------------------
| Symbolic Links
|--------------------------------------------------------------------------
|
| Here you may configure the symbolic links that will be created when the
| `storage:link` Artisan command is executed. The array keys should be
| the locations of the links and the values should be their targets.
|
*/
'links' => [
public_path('storage') => storage_path('app/public'),
],
];

@ -0,0 +1,52 @@
<?php
return [
/*
|--------------------------------------------------------------------------
| Default Hash Driver
|--------------------------------------------------------------------------
|
| This option controls the default hash driver that will be used to hash
| passwords for your application. By default, the bcrypt algorithm is
| used; however, you remain free to modify this option if you wish.
|
| Supported: "bcrypt", "argon", "argon2id"
|
*/
'driver' => 'bcrypt',
/*
|--------------------------------------------------------------------------
| Bcrypt Options
|--------------------------------------------------------------------------
|
| Here you may specify the configuration options that should be used when
| passwords are hashed using the Bcrypt algorithm. This will allow you
| to control the amount of time it takes to hash the given password.
|
*/
'bcrypt' => [
'rounds' => env('BCRYPT_ROUNDS', 10),
],
/*
|--------------------------------------------------------------------------
| Argon Options
|--------------------------------------------------------------------------
|
| Here you may specify the configuration options that should be used when
| passwords are hashed using the Argon algorithm. These will allow you
| to control the amount of time it takes to hash the given password.
|
*/
'argon' => [
'memory' => 65536,
'threads' => 1,
'time' => 4,
],
];

@ -0,0 +1,20 @@
<?php
return [
/*
|--------------------------------------------------------------------------
| Image Driver
|--------------------------------------------------------------------------
|
| Intervention Image supports "GD Library" and "Imagick" to process images
| internally. You may choose one of them according to your PHP
| configuration. By default PHP's "GD Library" implementation is used.
|
| Supported: "gd", "imagick"
|
*/
'driver' => 'gd'
];

@ -0,0 +1,129 @@
<?php
use Monolog\Handler\NullHandler;
use Monolog\Handler\StreamHandler;
use Monolog\Handler\SyslogUdpHandler;
return [
/*
|--------------------------------------------------------------------------
| Default Log Channel
|--------------------------------------------------------------------------
|
| This option defines the default log channel that gets used when writing
| messages to the logs. The name specified in this option should match
| one of the channels defined in the "channels" configuration array.
|
*/
'default' => env('LOG_CHANNEL', 'stack'),
/*
|--------------------------------------------------------------------------
| Deprecations Log Channel
|--------------------------------------------------------------------------
|
| This option controls the log channel that should be used to log warnings
| regarding deprecated PHP and library features. This allows you to get
| your application ready for upcoming major versions of dependencies.
|
*/
'deprecations' => env('LOG_DEPRECATIONS_CHANNEL', 'null'),
/*
|--------------------------------------------------------------------------
| Log Channels
|--------------------------------------------------------------------------
|
| Here you may configure the log channels for your application. Out of
| the box, Laravel uses the Monolog PHP logging library. This gives
| you a variety of powerful log handlers / formatters to utilize.
|
| Available Drivers: "single", "daily", "slack", "syslog",
| "errorlog", "monolog",
| "custom", "stack"
|
*/
'channels' => [
'stack' => [
'driver' => 'stack',
'channels' => ['single'],
'ignore_exceptions' => false,
],
'single' => [
'driver' => 'single',
'path' => storage_path('logs/laravel.log'),
'level' => env('LOG_LEVEL', 'debug'),
],
'daily' => [
'driver' => 'daily',
'path' => storage_path('logs/laravel.log'),
'level' => env('LOG_LEVEL', 'debug'),
'days' => 14,
],
'slack' => [
'driver' => 'slack',
'url' => env('LOG_SLACK_WEBHOOK_URL'),
'username' => 'Laravel Log',
'emoji' => ':boom:',
'level' => env('LOG_LEVEL', 'critical'),
],
'papertrail' => [
'driver' => 'monolog',
'level' => env('LOG_LEVEL', 'debug'),
'handler' => SyslogUdpHandler::class,
'handler_with' => [
'host' => env('PAPERTRAIL_URL'),
'port' => env('PAPERTRAIL_PORT'),
],
],
'stderr' => [
'driver' => 'monolog',
'level' => env('LOG_LEVEL', 'debug'),
'handler' => StreamHandler::class,
'formatter' => env('LOG_STDERR_FORMATTER'),
'with' => [
'stream' => 'php://stderr',
],
],
'syslog' => [
'driver' => 'syslog',
'level' => env('LOG_LEVEL', 'debug'),
],
'errorlog' => [
'driver' => 'errorlog',
'level' => env('LOG_LEVEL', 'debug'),
],
'null' => [
'driver' => 'monolog',
'handler' => NullHandler::class,
],
'emergency' => [
'path' => storage_path('logs/laravel.log'),
],
],
'query' => [
'enabled' => env('LOG_QUERY', env('APP_ENV') === 'local'),
// Only record queries that are slower than the following time
// Unit: milliseconds
'slower_than' => 0,
// Only record queries when the QUERY_LOG_TRIGGER is set in the environment,
// or when the trigger HEADER, GET, POST, or COOKIE variable is set.
'trigger' => env('QUERY_LOG_TRIGGER'),
],
];

@ -0,0 +1,118 @@
<?php
return [
/*
|--------------------------------------------------------------------------
| Default Mailer
|--------------------------------------------------------------------------
|
| This option controls the default mailer that is used to send any email
| messages sent by your application. Alternative mailers may be setup
| and used as needed; however, this mailer will be used by default.
|
*/
'default' => env('MAIL_MAILER', 'smtp'),
/*
|--------------------------------------------------------------------------
| Mailer Configurations
|--------------------------------------------------------------------------
|
| Here you may configure all of the mailers used by your application plus
| their respective settings. Several examples have been configured for
| you and you are free to add your own as your application requires.
|
| Laravel supports a variety of mail "transport" drivers to be used while
| sending an e-mail. You will specify which one you are using for your
| mailers below. You are free to add additional mailers as required.
|
| Supported: "smtp", "sendmail", "mailgun", "ses",
| "postmark", "log", "array", "failover"
|
*/
'mailers' => [
'smtp' => [
'transport' => 'smtp',
'host' => env('MAIL_HOST', 'smtp.mailgun.org'),
'port' => env('MAIL_PORT', 587),
'encryption' => env('MAIL_ENCRYPTION', 'tls'),
'username' => env('MAIL_USERNAME'),
'password' => env('MAIL_PASSWORD'),
'timeout' => null,
'auth_mode' => null,
],
'ses' => [
'transport' => 'ses',
],
'mailgun' => [
'transport' => 'mailgun',
],
'postmark' => [
'transport' => 'postmark',
],
'sendmail' => [
'transport' => 'sendmail',
'path' => env('MAIL_SENDMAIL_PATH', '/usr/sbin/sendmail -t -i'),
],
'log' => [
'transport' => 'log',
'channel' => env('MAIL_LOG_CHANNEL'),
],
'array' => [
'transport' => 'array',
],
'failover' => [
'transport' => 'failover',
'mailers' => [
'smtp',
'log',
],
],
],
/*
|--------------------------------------------------------------------------
| Global "From" Address
|--------------------------------------------------------------------------
|
| You may wish for all e-mails sent by your application to be sent from
| the same address. Here, you may specify a name and address that is
| used globally for all e-mails that are sent by your application.
|
*/
'from' => [
'address' => env('MAIL_FROM_ADDRESS', 'hello@example.com'),
'name' => env('MAIL_FROM_NAME', 'Example'),
],
/*
|--------------------------------------------------------------------------
| Markdown Mail Settings
|--------------------------------------------------------------------------
|
| If you are using Markdown based email rendering, you may configure your
| theme and component paths here, allowing you to customize the design
| of the emails. Or, you may simply stick with the Laravel defaults!
|
*/
'markdown' => [
'theme' => 'default',
'paths' => [
resource_path('views/vendor/mail'),
],
],
];

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save