diff --git a/app/Exceptions/Handler.php b/app/Exceptions/Handler.php
index cdc851e..1ec2920 100644
--- a/app/Exceptions/Handler.php
+++ b/app/Exceptions/Handler.php
@@ -17,11 +17,15 @@ class Handler extends ExceptionHandler
{
public function report(Throwable $e): void
{
- if (
- app()->environment('local') || app()->environment('production')
- || app()->environment('LOCAL') || app()->environment('DEV')
- ) {
- $this->sendSlackException($e);
+ try {
+ if (
+ app()->environment('local') || app()->environment('production')
+ || app()->environment('LOCAL') || app()->environment('DEV')
+ ) {
+ $this->sendSlackException($e);
+ }
+ } catch (\Throwable $ex) {
+ // app()이 아직 사용 불가하거나 env 문제가 있을 때는 무시
}
parent::report($e); // 로그는 그대로
diff --git a/app/Models/Boards/BoardSetting.php b/app/Models/Boards/BoardSetting.php
index b8eb532..1a74130 100644
--- a/app/Models/Boards/BoardSetting.php
+++ b/app/Models/Boards/BoardSetting.php
@@ -1,5 +1,7 @@
app->singleton(LoginResponse::class, CustomLoginResponse::class);
- }
-
- /**
- * Bootstrap any application services.
- */
- public function boot(): void
- {
-
- Fortify::createUsersUsing(CreateNewUser::class);
- Fortify::updateUserProfileInformationUsing(UpdateUserProfileInformation::class);
- Fortify::updateUserPasswordsUsing(UpdateUserPassword::class);
- Fortify::resetUserPasswordsUsing(ResetUserPassword::class);
-
- // ✅ 로그인 시 `USER_ID`를 사용하도록 변경
- Fortify::authenticateUsing(function (Request $request) {
-
- $user = Member::where('mb_id', $request->USER_ID)->first();
- if(!$user) return null;
-
- if (Str::startsWith($user->mb_pass, '$2y$')) {
- // bcrypt로 해싱된 경우
- if(Hash::check($request->password, $user->mb_pass)) return $user;
- } else {
- // sha256으로 해싱된 경우
- if(strtoupper(hash('sha256', $request->password))) return $user;;
- }
-
- return null;
- });
-
- Fortify::loginView(fn() => view('auth.login')); // 로그인 페이지 지정
-
- RateLimiter::for('login', function (Request $request) {
- $throttleKey = Str::transliterate(Str::lower($request->input('USER_ID')).'|'.$request->ip());
-
- return Limit::perMinute(5)->by($throttleKey);
- });
-
- RateLimiter::for('two-factor', function (Request $request) {
- return Limit::perMinute(5)->by($request->session()->get('login.id'));
- });
- }
-}
diff --git a/app/Providers/JetstreamServiceProvider.php b/app/Providers/JetstreamServiceProvider.php
deleted file mode 100644
index 9139849..0000000
--- a/app/Providers/JetstreamServiceProvider.php
+++ /dev/null
@@ -1,43 +0,0 @@
-configurePermissions();
-
- Jetstream::deleteUsersUsing(DeleteUser::class);
- }
-
- /**
- * Configure the permissions that are available within the application.
- */
- protected function configurePermissions(): void
- {
- Jetstream::defaultApiTokenPermissions(['read']);
-
- Jetstream::permissions([
- 'create',
- 'read',
- 'update',
- 'delete',
- ]);
- }
-}
diff --git a/bootstrap/providers.php b/bootstrap/providers.php
index 55e8e15..38b258d 100644
--- a/bootstrap/providers.php
+++ b/bootstrap/providers.php
@@ -2,6 +2,4 @@
return [
App\Providers\AppServiceProvider::class,
- App\Providers\FortifyServiceProvider::class,
- App\Providers\JetstreamServiceProvider::class,
];
diff --git a/composer.json b/composer.json
index 1a6df4d..3ea3228 100644
--- a/composer.json
+++ b/composer.json
@@ -10,7 +10,6 @@
"darkaonline/l5-swagger": "^9.0",
"doctrine/dbal": "^4.3",
"laravel/framework": "^12.0",
- "laravel/jetstream": "^5.3",
"laravel/sanctum": "^4.0",
"laravel/tinker": "^2.10.1",
"livewire/livewire": "^3.0"
diff --git a/composer.lock b/composer.lock
index 4b0f0aa..bcbf17c 100644
--- a/composer.lock
+++ b/composer.lock
@@ -4,62 +4,8 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
- "content-hash": "592e08448fda5a7d5260d0ed24f8e7ce",
+ "content-hash": "9827ba355b77e4e0b827c6f2a101003d",
"packages": [
- {
- "name": "bacon/bacon-qr-code",
- "version": "v3.0.1",
- "source": {
- "type": "git",
- "url": "https://github.com/Bacon/BaconQrCode.git",
- "reference": "f9cc1f52b5a463062251d666761178dbdb6b544f"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/Bacon/BaconQrCode/zipball/f9cc1f52b5a463062251d666761178dbdb6b544f",
- "reference": "f9cc1f52b5a463062251d666761178dbdb6b544f",
- "shasum": ""
- },
- "require": {
- "dasprid/enum": "^1.0.3",
- "ext-iconv": "*",
- "php": "^8.1"
- },
- "require-dev": {
- "phly/keep-a-changelog": "^2.12",
- "phpunit/phpunit": "^10.5.11 || 11.0.4",
- "spatie/phpunit-snapshot-assertions": "^5.1.5",
- "squizlabs/php_codesniffer": "^3.9"
- },
- "suggest": {
- "ext-imagick": "to generate QR code images"
- },
- "type": "library",
- "autoload": {
- "psr-4": {
- "BaconQrCode\\": "src/"
- }
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "BSD-2-Clause"
- ],
- "authors": [
- {
- "name": "Ben Scholzen 'DASPRiD'",
- "email": "mail@dasprids.de",
- "homepage": "https://dasprids.de/",
- "role": "Developer"
- }
- ],
- "description": "BaconQrCode is a QR code generator for PHP.",
- "homepage": "https://github.com/Bacon/BaconQrCode",
- "support": {
- "issues": "https://github.com/Bacon/BaconQrCode/issues",
- "source": "https://github.com/Bacon/BaconQrCode/tree/v3.0.1"
- },
- "time": "2024-10-01T13:55:55+00:00"
- },
{
"name": "brick/math",
"version": "0.13.1",
@@ -270,56 +216,6 @@
],
"time": "2025-02-28T06:25:02+00:00"
},
- {
- "name": "dasprid/enum",
- "version": "1.0.6",
- "source": {
- "type": "git",
- "url": "https://github.com/DASPRiD/Enum.git",
- "reference": "8dfd07c6d2cf31c8da90c53b83c026c7696dda90"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/DASPRiD/Enum/zipball/8dfd07c6d2cf31c8da90c53b83c026c7696dda90",
- "reference": "8dfd07c6d2cf31c8da90c53b83c026c7696dda90",
- "shasum": ""
- },
- "require": {
- "php": ">=7.1 <9.0"
- },
- "require-dev": {
- "phpunit/phpunit": "^7 || ^8 || ^9 || ^10 || ^11",
- "squizlabs/php_codesniffer": "*"
- },
- "type": "library",
- "autoload": {
- "psr-4": {
- "DASPRiD\\Enum\\": "src/"
- }
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "BSD-2-Clause"
- ],
- "authors": [
- {
- "name": "Ben Scholzen 'DASPRiD'",
- "email": "mail@dasprids.de",
- "homepage": "https://dasprids.de/",
- "role": "Developer"
- }
- ],
- "description": "PHP 7.1 enum implementation",
- "keywords": [
- "enum",
- "map"
- ],
- "support": {
- "issues": "https://github.com/DASPRiD/Enum/issues",
- "source": "https://github.com/DASPRiD/Enum/tree/1.0.6"
- },
- "time": "2024-08-09T14:30:48+00:00"
- },
{
"name": "dflydev/dot-access-data",
"version": "v3.0.3",
@@ -1469,71 +1365,6 @@
],
"time": "2025-02-03T10:55:03+00:00"
},
- {
- "name": "laravel/fortify",
- "version": "v1.27.0",
- "source": {
- "type": "git",
- "url": "https://github.com/laravel/fortify.git",
- "reference": "0fb2ec99dfee77ed66884668fc06683acca91ebd"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/laravel/fortify/zipball/0fb2ec99dfee77ed66884668fc06683acca91ebd",
- "reference": "0fb2ec99dfee77ed66884668fc06683acca91ebd",
- "shasum": ""
- },
- "require": {
- "bacon/bacon-qr-code": "^3.0",
- "ext-json": "*",
- "illuminate/support": "^10.0|^11.0|^12.0",
- "php": "^8.1",
- "pragmarx/google2fa": "^8.0",
- "symfony/console": "^6.0|^7.0"
- },
- "require-dev": {
- "mockery/mockery": "^1.0",
- "orchestra/testbench": "^8.16|^9.0|^10.0",
- "phpstan/phpstan": "^1.10",
- "phpunit/phpunit": "^10.4|^11.3"
- },
- "type": "library",
- "extra": {
- "laravel": {
- "providers": [
- "Laravel\\Fortify\\FortifyServiceProvider"
- ]
- },
- "branch-alias": {
- "dev-master": "1.x-dev"
- }
- },
- "autoload": {
- "psr-4": {
- "Laravel\\Fortify\\": "src/"
- }
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "MIT"
- ],
- "authors": [
- {
- "name": "Taylor Otwell",
- "email": "taylor@laravel.com"
- }
- ],
- "description": "Backend controllers and scaffolding for Laravel authentication.",
- "keywords": [
- "auth",
- "laravel"
- ],
- "support": {
- "issues": "https://github.com/laravel/fortify/issues",
- "source": "https://github.com/laravel/fortify"
- },
- "time": "2025-06-11T14:30:52+00:00"
- },
{
"name": "laravel/framework",
"version": "v12.20.0",
@@ -1749,73 +1580,6 @@
},
"time": "2025-07-08T15:02:21+00:00"
},
- {
- "name": "laravel/jetstream",
- "version": "v5.3.7",
- "source": {
- "type": "git",
- "url": "https://github.com/laravel/jetstream.git",
- "reference": "b606c21daeaa38547f853789212e3802b0f6ff08"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/laravel/jetstream/zipball/b606c21daeaa38547f853789212e3802b0f6ff08",
- "reference": "b606c21daeaa38547f853789212e3802b0f6ff08",
- "shasum": ""
- },
- "require": {
- "ext-json": "*",
- "illuminate/console": "^11.0|^12.0",
- "illuminate/support": "^11.0|^12.0",
- "laravel/fortify": "^1.20",
- "mobiledetect/mobiledetectlib": "^4.8.08",
- "php": "^8.2.0",
- "symfony/console": "^7.0"
- },
- "require-dev": {
- "inertiajs/inertia-laravel": "^2.0",
- "laravel/sanctum": "^4.0",
- "livewire/livewire": "^3.3",
- "mockery/mockery": "^1.0",
- "orchestra/testbench": "^9.0|^10.0",
- "phpstan/phpstan": "^1.10",
- "phpunit/phpunit": "^11.0"
- },
- "type": "library",
- "extra": {
- "laravel": {
- "providers": [
- "Laravel\\Jetstream\\JetstreamServiceProvider"
- ]
- }
- },
- "autoload": {
- "psr-4": {
- "Laravel\\Jetstream\\": "src/"
- }
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "MIT"
- ],
- "authors": [
- {
- "name": "Taylor Otwell",
- "email": "taylor@laravel.com"
- }
- ],
- "description": "Tailwind scaffolding for the Laravel framework.",
- "keywords": [
- "auth",
- "laravel",
- "tailwind"
- ],
- "support": {
- "issues": "https://github.com/laravel/jetstream/issues",
- "source": "https://github.com/laravel/jetstream"
- },
- "time": "2025-06-16T13:27:00+00:00"
- },
{
"name": "laravel/prompts",
"version": "v0.3.6",
@@ -2693,71 +2457,6 @@
],
"time": "2025-04-12T22:26:52+00:00"
},
- {
- "name": "mobiledetect/mobiledetectlib",
- "version": "4.8.09",
- "source": {
- "type": "git",
- "url": "https://github.com/serbanghita/Mobile-Detect.git",
- "reference": "a06fe2e546a06bb8c2639d6823d5250b2efb3209"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/serbanghita/Mobile-Detect/zipball/a06fe2e546a06bb8c2639d6823d5250b2efb3209",
- "reference": "a06fe2e546a06bb8c2639d6823d5250b2efb3209",
- "shasum": ""
- },
- "require": {
- "php": ">=8.0",
- "psr/cache": "^3.0",
- "psr/simple-cache": "^3"
- },
- "require-dev": {
- "friendsofphp/php-cs-fixer": "^v3.65.0",
- "phpbench/phpbench": "^1.2",
- "phpstan/phpstan": "^1.12.x-dev",
- "phpunit/phpunit": "^9.6.18",
- "squizlabs/php_codesniffer": "^3.11.1"
- },
- "type": "library",
- "autoload": {
- "psr-4": {
- "Detection\\": "src/"
- }
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "MIT"
- ],
- "authors": [
- {
- "name": "Serban Ghita",
- "email": "serbanghita@gmail.com",
- "homepage": "http://mobiledetect.net",
- "role": "Developer"
- }
- ],
- "description": "Mobile_Detect is a lightweight PHP class for detecting mobile devices. It uses the User-Agent string combined with specific HTTP headers to detect the mobile environment.",
- "homepage": "https://github.com/serbanghita/Mobile-Detect",
- "keywords": [
- "detect mobile devices",
- "mobile",
- "mobile detect",
- "mobile detector",
- "php mobile detect"
- ],
- "support": {
- "issues": "https://github.com/serbanghita/Mobile-Detect/issues",
- "source": "https://github.com/serbanghita/Mobile-Detect/tree/4.8.09"
- },
- "funding": [
- {
- "url": "https://github.com/serbanghita",
- "type": "github"
- }
- ],
- "time": "2024-12-10T15:32:06+00:00"
- },
{
"name": "monolog/monolog",
"version": "3.9.0",
@@ -3259,73 +2958,6 @@
],
"time": "2025-05-08T08:14:37+00:00"
},
- {
- "name": "paragonie/constant_time_encoding",
- "version": "v3.0.0",
- "source": {
- "type": "git",
- "url": "https://github.com/paragonie/constant_time_encoding.git",
- "reference": "df1e7fde177501eee2037dd159cf04f5f301a512"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/paragonie/constant_time_encoding/zipball/df1e7fde177501eee2037dd159cf04f5f301a512",
- "reference": "df1e7fde177501eee2037dd159cf04f5f301a512",
- "shasum": ""
- },
- "require": {
- "php": "^8"
- },
- "require-dev": {
- "phpunit/phpunit": "^9",
- "vimeo/psalm": "^4|^5"
- },
- "type": "library",
- "autoload": {
- "psr-4": {
- "ParagonIE\\ConstantTime\\": "src/"
- }
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "MIT"
- ],
- "authors": [
- {
- "name": "Paragon Initiative Enterprises",
- "email": "security@paragonie.com",
- "homepage": "https://paragonie.com",
- "role": "Maintainer"
- },
- {
- "name": "Steve 'Sc00bz' Thomas",
- "email": "steve@tobtu.com",
- "homepage": "https://www.tobtu.com",
- "role": "Original Developer"
- }
- ],
- "description": "Constant-time Implementations of RFC 4648 Encoding (Base-64, Base-32, Base-16)",
- "keywords": [
- "base16",
- "base32",
- "base32_decode",
- "base32_encode",
- "base64",
- "base64_decode",
- "base64_encode",
- "bin2hex",
- "encoding",
- "hex",
- "hex2bin",
- "rfc4648"
- ],
- "support": {
- "email": "info@paragonie.com",
- "issues": "https://github.com/paragonie/constant_time_encoding/issues",
- "source": "https://github.com/paragonie/constant_time_encoding"
- },
- "time": "2024-05-08T12:36:18+00:00"
- },
{
"name": "phpoption/phpoption",
"version": "1.9.3",
@@ -3401,58 +3033,6 @@
],
"time": "2024-07-20T21:41:07+00:00"
},
- {
- "name": "pragmarx/google2fa",
- "version": "v8.0.3",
- "source": {
- "type": "git",
- "url": "https://github.com/antonioribeiro/google2fa.git",
- "reference": "6f8d87ebd5afbf7790bde1ffc7579c7c705e0fad"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/antonioribeiro/google2fa/zipball/6f8d87ebd5afbf7790bde1ffc7579c7c705e0fad",
- "reference": "6f8d87ebd5afbf7790bde1ffc7579c7c705e0fad",
- "shasum": ""
- },
- "require": {
- "paragonie/constant_time_encoding": "^1.0|^2.0|^3.0",
- "php": "^7.1|^8.0"
- },
- "require-dev": {
- "phpstan/phpstan": "^1.9",
- "phpunit/phpunit": "^7.5.15|^8.5|^9.0"
- },
- "type": "library",
- "autoload": {
- "psr-4": {
- "PragmaRX\\Google2FA\\": "src/"
- }
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "MIT"
- ],
- "authors": [
- {
- "name": "Antonio Carlos Ribeiro",
- "email": "acr@antoniocarlosribeiro.com",
- "role": "Creator & Designer"
- }
- ],
- "description": "A One Time Password Authentication package, compatible with Google Authenticator.",
- "keywords": [
- "2fa",
- "Authentication",
- "Two Factor Authentication",
- "google2fa"
- ],
- "support": {
- "issues": "https://github.com/antonioribeiro/google2fa/issues",
- "source": "https://github.com/antonioribeiro/google2fa/tree/v8.0.3"
- },
- "time": "2024-09-05T11:56:40+00:00"
- },
{
"name": "psr/cache",
"version": "3.0.0",
diff --git a/config/fortify.php b/config/fortify.php
deleted file mode 100644
index b36d04c..0000000
--- a/config/fortify.php
+++ /dev/null
@@ -1,160 +0,0 @@
- 'web',
-
- /*
- |--------------------------------------------------------------------------
- | Fortify Password Broker
- |--------------------------------------------------------------------------
- |
- | Here you may specify which password broker Fortify can use when a user
- | is resetting their password. This configured value should match one
- | of your password brokers setup in your "auth" configuration file.
- |
- */
-
- 'passwords' => 'users',
-
- /*
- |--------------------------------------------------------------------------
- | Username / Email
- |--------------------------------------------------------------------------
- |
- | This value defines which model attribute should be considered as your
- | application's "username" field. Typically, this might be the email
- | address of the users but you are free to change this value here.
- |
- | Out of the box, Fortify expects forgot password and reset password
- | requests to have a field named 'email'. If the application uses
- | another name for the field you may define it below as needed.
- |
- */
-
- 'username' => 'USER_ID', // 기본 로그인 필드 변경
- 'password' => 'USER_PWD', // 기본 비밀번호 필드 변경
-
- 'email' => 'email',
-
- /*
- |--------------------------------------------------------------------------
- | Lowercase Usernames
- |--------------------------------------------------------------------------
- |
- | This value defines whether usernames should be lowercased before saving
- | them in the database, as some database system string fields are case
- | sensitive. You may disable this for your application if necessary.
- |
- */
-
- 'lowercase_usernames' => true,
-
- /*
- |--------------------------------------------------------------------------
- | Home Path
- |--------------------------------------------------------------------------
- |
- | Here you may configure the path where users will get redirected during
- | authentication or password reset when the operations are successful
- | and the user is authenticated. You are free to change this value.
- |
- */
-
- 'home' => '/dashboard',
-
- /*
- |--------------------------------------------------------------------------
- | Fortify Routes Prefix / Subdomain
- |--------------------------------------------------------------------------
- |
- | Here you may specify which prefix Fortify will assign to all the routes
- | that it registers with the application. If necessary, you may change
- | subdomain under which all of the Fortify routes will be available.
- |
- */
-
- 'prefix' => '',
-
- 'domain' => null,
-
- /*
- |--------------------------------------------------------------------------
- | Fortify Routes Middleware
- |--------------------------------------------------------------------------
- |
- | Here you may specify which middleware Fortify will assign to the routes
- | that it registers with the application. If necessary, you may change
- | these middleware but typically this provided default is preferred.
- |
- */
-
- 'middleware' => ['web'],
-
- /*
- |--------------------------------------------------------------------------
- | Rate Limiting
- |--------------------------------------------------------------------------
- |
- | By default, Fortify will throttle logins to five requests per minute for
- | every email and IP address combination. However, if you would like to
- | specify a custom rate limiter to call then you may specify it here.
- |
- */
-
- 'limiters' => [
- 'login' => 'login',
- 'two-factor' => 'two-factor',
- ],
-
- /*
- |--------------------------------------------------------------------------
- | Register View Routes
- |--------------------------------------------------------------------------
- |
- | Here you may specify if the routes returning views should be disabled as
- | you may not need them when building your own application. This may be
- | especially true if you're writing a custom single-page application.
- |
- */
-
- 'views' => true,
-
- /*
- |--------------------------------------------------------------------------
- | Features
- |--------------------------------------------------------------------------
- |
- | Some of the Fortify features are optional. You may disable the features
- | by removing them from this array. You're free to only remove some of
- | these features or you can even remove all of these if you need to.
- |
- */
-
- 'features' => [
- Features::registration(),
- Features::resetPasswords(),
- // Features::emailVerification(),
- Features::updateProfileInformation(),
- Features::updatePasswords(),
- Features::twoFactorAuthentication([
- 'confirm' => true,
- 'confirmPassword' => true,
- // 'window' => 0,
- ]),
- ],
-
-];
diff --git a/config/jetstream.php b/config/jetstream.php
deleted file mode 100644
index 9800fbf..0000000
--- a/config/jetstream.php
+++ /dev/null
@@ -1,81 +0,0 @@
- 'livewire',
-
- /*
- |--------------------------------------------------------------------------
- | Jetstream Route Middleware
- |--------------------------------------------------------------------------
- |
- | Here you may specify which middleware Jetstream will assign to the routes
- | that it registers with the application. When necessary, you may modify
- | these middleware; however, this default value is usually sufficient.
- |
- */
-
- 'middleware' => ['web'],
-
- 'auth_session' => AuthenticateSession::class,
-
- /*
- |--------------------------------------------------------------------------
- | Jetstream Guard
- |--------------------------------------------------------------------------
- |
- | Here you may specify the authentication guard Jetstream will use while
- | authenticating users. This value should correspond with one of your
- | guards that is already present in your "auth" configuration file.
- |
- */
-
- 'guard' => 'sanctum',
-
- /*
- |--------------------------------------------------------------------------
- | Features
- |--------------------------------------------------------------------------
- |
- | Some of Jetstream's features are optional. You may disable the features
- | by removing them from this array. You're free to only remove some of
- | these features or you can even remove all of these if you need to.
- |
- */
-
- 'features' => [
- // Features::termsAndPrivacyPolicy(),
- // Features::profilePhotos(),
- // Features::api(),
- // Features::teams(['invitations' => true]),
- Features::accountDeletion(),
- ],
-
- /*
- |--------------------------------------------------------------------------
- | Profile Photo Disk
- |--------------------------------------------------------------------------
- |
- | This configuration value determines the default disk that will be used
- | when storing profile photos for your application's users. Typically
- | this will be the "public" disk but you may adjust this if needed.
- |
- */
-
- 'profile_photo_disk' => 'public',
-
-];
diff --git a/storage/api-docs/api-docs-v1.json b/storage/api-docs/api-docs-v1.json
new file mode 100755
index 0000000..6d81faf
--- /dev/null
+++ b/storage/api-docs/api-docs-v1.json
@@ -0,0 +1,777 @@
+{
+ "openapi": "3.0.0",
+ "info": {
+ "title": "SAM API Documentation",
+ "description": "===============================
[공통 에러 응답 포맷]
400: 필수 파라미터 누락
401: 인증 실패
403: 권한 없음
404: 존재하지 않는 URI 또는 데이터
405: 허용되지 않는 메서드
500: 서버 에러
모든 에러 응답 예시:
{
"success": false,
"message": "에러 메시지",
"data": null
}
===============================",
+ "contact": {
+ "email": "shine1324@gmail.com"
+ },
+ "version": "1.0.0"
+ },
+ "servers": [
+ {
+ "url": "https://api.5130.co.kr",
+ "description": "SAM관리시스템 API 서버"
+ }
+ ],
+ "paths": {
+ "/api/v1/debug-apikey": {
+ "get": {
+ "tags": [
+ "API Key 인증"
+ ],
+ "summary": "API Key 인증 확인",
+ "operationId": "8d05f26a859e82207ba533ab88682ddf",
+ "responses": {
+ "200": {
+ "description": "API Key 인증 성공"
+ },
+ "401": {
+ "description": "인증 실패"
+ }
+ },
+ "security": [
+ {
+ "ApiKeyAuth": []
+ },
+ {
+ "BearerAuth": []
+ }
+ ]
+ }
+ },
+ "/api/v1/login": {
+ "post": {
+ "tags": [
+ "Auth"
+ ],
+ "summary": "회원 토큰 정보확인",
+ "operationId": "3878a009ac5aef1ebe0e72b7716e24ac",
+ "requestBody": {
+ "required": true,
+ "content": {
+ "application/json": {
+ "schema": {
+ "required": [
+ "user_id",
+ "user_pwd"
+ ],
+ "properties": {
+ "user_id": {
+ "type": "string",
+ "example": "test"
+ },
+ "user_pwd": {
+ "type": "string",
+ "example": "testpass"
+ }
+ },
+ "type": "object"
+ }
+ }
+ }
+ },
+ "responses": {
+ "200": {
+ "description": "로그인 성공",
+ "content": {
+ "application/json": {
+ "schema": {
+ "properties": {
+ "message": {
+ "type": "string"
+ },
+ "user_token": {
+ "type": "string"
+ }
+ },
+ "type": "object"
+ }
+ }
+ }
+ },
+ "401": {
+ "description": "로그인 실패"
+ }
+ },
+ "security": [
+ {
+ "ApiKeyAuth": []
+ }
+ ]
+ }
+ },
+ "/api/v1/logout": {
+ "post": {
+ "tags": [
+ "Auth"
+ ],
+ "summary": "로그아웃 (Access 및 Token 무효화)",
+ "operationId": "39200ed8c17c34aa7af9a24f064e13a4",
+ "responses": {
+ "200": {
+ "description": "로그아웃 성공"
+ },
+ "401": {
+ "description": "인증 실패"
+ }
+ },
+ "security": [
+ {
+ "ApiKeyAuth": []
+ },
+ {
+ "BearerAuth": []
+ }
+ ]
+ }
+ },
+ "/api/v1/member/index": {
+ "get": {
+ "tags": [
+ "Member"
+ ],
+ "summary": "회원 목록 조회",
+ "description": "회원 목록을 페이징 형태로 반환합니다.",
+ "operationId": "9243d8df1b20c9552b21389ce84415ea",
+ "parameters": [
+ {
+ "name": "page",
+ "in": "query",
+ "description": "페이지 번호 (기본값: 1)",
+ "required": false,
+ "schema": {
+ "type": "integer",
+ "example": 1
+ }
+ },
+ {
+ "name": "size",
+ "in": "query",
+ "description": "페이지당 항목 수 (기본값: 20)",
+ "required": false,
+ "schema": {
+ "type": "integer",
+ "example": 20
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "회원 목록 조회 성공",
+ "content": {
+ "application/json": {
+ "schema": {
+ "properties": {
+ "success": {
+ "type": "boolean",
+ "example": true
+ },
+ "message": {
+ "type": "string",
+ "example": "회원목록 조회 성공"
+ },
+ "data": {
+ "properties": {
+ "current_page": {
+ "type": "integer",
+ "example": 1
+ },
+ "data": {
+ "type": "array",
+ "items": {
+ "properties": {
+ "id": {
+ "type": "integer",
+ "example": 1
+ },
+ "user_id": {
+ "type": "string",
+ "example": "hamss"
+ },
+ "phone": {
+ "type": "string",
+ "example": "010-4820-9104"
+ },
+ "options": {
+ "type": "string",
+ "example": null,
+ "nullable": true
+ },
+ "name": {
+ "type": "string",
+ "example": "권혁성"
+ },
+ "email": {
+ "type": "string",
+ "example": "shine1324@gmail.com"
+ },
+ "email_verified_at": {
+ "type": "string",
+ "format": "date-time",
+ "example": null,
+ "nullable": true
+ },
+ "last_login_at": {
+ "type": "string",
+ "format": "date-time",
+ "example": null,
+ "nullable": true
+ },
+ "current_team_id": {
+ "type": "integer",
+ "example": null,
+ "nullable": true
+ },
+ "profile_photo_path": {
+ "type": "string",
+ "example": null,
+ "nullable": true
+ },
+ "created_at": {
+ "type": "string",
+ "format": "date-time",
+ "example": "2025-07-16 18:28:41"
+ },
+ "updated_at": {
+ "type": "string",
+ "format": "date-time",
+ "example": "2025-07-25 23:13:06"
+ },
+ "deleted_at": {
+ "type": "string",
+ "format": "date-time",
+ "example": null,
+ "nullable": true
+ }
+ },
+ "type": "object"
+ }
+ },
+ "first_page_url": {
+ "type": "string",
+ "example": "http://api.sam.kr/api/v1/member/index?page=1"
+ },
+ "from": {
+ "type": "integer",
+ "example": 1
+ },
+ "last_page": {
+ "type": "integer",
+ "example": 1
+ },
+ "last_page_url": {
+ "type": "string",
+ "example": "http://api.sam.kr/api/v1/member/index?page=1"
+ },
+ "links": {
+ "type": "array",
+ "items": {
+ "properties": {
+ "url": {
+ "type": "string",
+ "example": null,
+ "nullable": true
+ },
+ "label": {
+ "type": "string",
+ "example": "« Previous"
+ },
+ "active": {
+ "type": "boolean",
+ "example": false
+ }
+ },
+ "type": "object"
+ }
+ },
+ "next_page_url": {
+ "type": "string",
+ "example": null,
+ "nullable": true
+ },
+ "path": {
+ "type": "string",
+ "example": "http://api.sam.kr/api/v1/member/index"
+ },
+ "per_page": {
+ "type": "integer",
+ "example": 20
+ },
+ "prev_page_url": {
+ "type": "string",
+ "example": null,
+ "nullable": true
+ },
+ "to": {
+ "type": "integer",
+ "example": 3
+ },
+ "total": {
+ "type": "integer",
+ "example": 3
+ }
+ },
+ "type": "object"
+ }
+ },
+ "type": "object"
+ }
+ }
+ }
+ }
+ },
+ "security": [
+ {
+ "ApiKeyAuth": []
+ },
+ {
+ "BearerAuth": []
+ }
+ ]
+ }
+ },
+ "/api/v1/member/show/{user_no}": {
+ "get": {
+ "tags": [
+ "Member"
+ ],
+ "summary": "회원 상세조회",
+ "description": "user_no 기준으로 회원 상세 정보를 조회합니다.",
+ "operationId": "b4c822915531828ea5f3a50d5112ef26",
+ "parameters": [
+ {
+ "name": "user_no",
+ "in": "path",
+ "description": "회원 번호 (USER_NO)",
+ "required": true,
+ "schema": {
+ "type": "integer",
+ "example": 1
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "회원 상세조회 성공",
+ "content": {
+ "application/json": {
+ "schema": {
+ "properties": {
+ "success": {
+ "type": "boolean",
+ "example": true
+ },
+ "message": {
+ "type": "string",
+ "example": "회원 상세조회 성공"
+ },
+ "data": {
+ "properties": {
+ "id": {
+ "type": "integer",
+ "example": 1
+ },
+ "user_id": {
+ "type": "string",
+ "example": "hamss"
+ },
+ "phone": {
+ "type": "string",
+ "example": "010-4820-9104"
+ },
+ "options": {
+ "type": "string",
+ "example": null,
+ "nullable": true
+ },
+ "name": {
+ "type": "string",
+ "example": "권혁성"
+ },
+ "email": {
+ "type": "string",
+ "example": "shine1324@gmail.com"
+ },
+ "email_verified_at": {
+ "type": "string",
+ "format": "date-time",
+ "example": null,
+ "nullable": true
+ },
+ "last_login_at": {
+ "type": "string",
+ "format": "date-time",
+ "example": null,
+ "nullable": true
+ },
+ "current_team_id": {
+ "type": "integer",
+ "example": null,
+ "nullable": true
+ },
+ "profile_photo_path": {
+ "type": "string",
+ "example": null,
+ "nullable": true
+ },
+ "created_at": {
+ "type": "string",
+ "format": "date-time",
+ "example": "2025-07-16 18:28:41"
+ },
+ "updated_at": {
+ "type": "string",
+ "format": "date-time",
+ "example": "2025-07-25 23:13:06"
+ },
+ "deleted_at": {
+ "type": "string",
+ "format": "date-time",
+ "example": null,
+ "nullable": true
+ }
+ },
+ "type": "object"
+ }
+ },
+ "type": "object"
+ }
+ }
+ }
+ },
+ "401": {
+ "description": "인증 실패"
+ },
+ "404": {
+ "description": "회원 정보 없음"
+ }
+ },
+ "security": [
+ {
+ "ApiKeyAuth": []
+ },
+ {
+ "BearerAuth": []
+ }
+ ]
+ }
+ },
+ "/api/v1/member/me": {
+ "get": {
+ "tags": [
+ "Member"
+ ],
+ "summary": "내 정보 조회",
+ "description": "내정보와 테넌트 정보를 전달 합니다.",
+ "operationId": "0c641be8a4e4ab5e1c2db29989b219ce",
+ "responses": {
+ "200": {
+ "description": "나의 정보 조회 성공",
+ "content": {
+ "application/json": {
+ "schema": {
+ "properties": {
+ "success": {
+ "type": "boolean",
+ "example": true
+ },
+ "message": {
+ "type": "string",
+ "example": "나의 정보 조회 성공"
+ },
+ "data": {
+ "properties": {
+ "user": {
+ "properties": {
+ "id": {
+ "type": "integer",
+ "example": 3
+ },
+ "user_id": {
+ "type": "string",
+ "example": "test"
+ },
+ "phone": {
+ "type": "string",
+ "example": "010-1234-5678"
+ },
+ "options": {
+ "type": "string",
+ "example": null,
+ "nullable": true
+ },
+ "name": {
+ "type": "string",
+ "example": "테스트"
+ },
+ "email": {
+ "type": "string",
+ "example": "test@5130.co.kr"
+ },
+ "email_verified_at": {
+ "type": "string",
+ "format": "date-time",
+ "example": null,
+ "nullable": true
+ },
+ "last_login_at": {
+ "type": "string",
+ "format": "date-time",
+ "example": null,
+ "nullable": true
+ },
+ "current_team_id": {
+ "type": "integer",
+ "example": null,
+ "nullable": true
+ },
+ "profile_photo_path": {
+ "type": "string",
+ "example": null,
+ "nullable": true
+ },
+ "created_at": {
+ "type": "string",
+ "format": "date-time",
+ "example": "2025-07-17 13:19:37"
+ },
+ "updated_at": {
+ "type": "string",
+ "format": "date-time",
+ "example": "2025-07-26 15:51:14"
+ },
+ "deleted_at": {
+ "type": "string",
+ "format": "date-time",
+ "example": null,
+ "nullable": true
+ }
+ },
+ "type": "object"
+ },
+ "tenant": {
+ "properties": {
+ "id": {
+ "type": "integer",
+ "example": 1
+ },
+ "company_name": {
+ "type": "string",
+ "example": "(주)경동기업"
+ },
+ "code": {
+ "type": "string",
+ "example": "KDCOM"
+ },
+ "email": {
+ "type": "string",
+ "example": "kd5130@naver.com"
+ },
+ "phone": {
+ "type": "string",
+ "example": "01083935130"
+ },
+ "address": {
+ "type": "string",
+ "example": "경기도 김포시 통진읍 옹정로 45-22"
+ },
+ "business_num": {
+ "type": "string",
+ "example": "1398700333"
+ },
+ "corp_reg_no": {
+ "type": "string",
+ "example": null,
+ "nullable": true
+ },
+ "ceo_name": {
+ "type": "string",
+ "example": "이경호"
+ },
+ "homepage": {
+ "type": "string",
+ "example": null,
+ "nullable": true
+ },
+ "fax": {
+ "type": "string",
+ "example": null,
+ "nullable": true
+ },
+ "logo": {
+ "type": "string",
+ "example": null,
+ "nullable": true
+ },
+ "admin_memo": {
+ "type": "string",
+ "example": null,
+ "nullable": true
+ },
+ "options": {
+ "type": "string",
+ "example": null,
+ "nullable": true
+ }
+ },
+ "type": "object"
+ }
+ },
+ "type": "object"
+ }
+ },
+ "type": "object"
+ }
+ }
+ }
+ },
+ "401": {
+ "description": "인증 실패 (헤더 누락, 유효하지 않은 토큰/키 등)"
+ }
+ },
+ "security": [
+ {
+ "ApiKeyAuth": []
+ },
+ {
+ "BearerAuth": []
+ }
+ ]
+ }
+ },
+ "/api/v1/product/category": {
+ "get": {
+ "tags": [
+ "Product"
+ ],
+ "summary": "제품 카테고리 목록 조회",
+ "description": "제품 카테고리(최상위, parent_id=null) 리스트를 반환합니다.",
+ "operationId": "ae018aa8eec41762f28513ae1aecebfc",
+ "responses": {
+ "200": {
+ "description": "카테고리 목록 조회 성공",
+ "content": {
+ "application/json": {
+ "schema": {
+ "properties": {
+ "status": {
+ "type": "string",
+ "example": "success"
+ },
+ "message": {
+ "type": "string",
+ "example": "get 성공"
+ },
+ "data": {
+ "type": "array",
+ "items": {
+ "properties": {
+ "id": {
+ "type": "integer",
+ "example": 4
+ },
+ "code_group": {
+ "type": "string",
+ "example": "category"
+ },
+ "code": {
+ "type": "string",
+ "example": "BP"
+ },
+ "name": {
+ "type": "string",
+ "example": "절곡판"
+ },
+ "parent_id": {
+ "type": "integer",
+ "example": null
+ },
+ "attributes": {
+ "type": "string",
+ "example": "[{...}]"
+ },
+ "description": {
+ "type": "string",
+ "example": "절곡판"
+ },
+ "is_active": {
+ "type": "integer",
+ "example": 1
+ },
+ "sort_order": {
+ "type": "integer",
+ "example": 10
+ },
+ "created_at": {
+ "type": "string",
+ "format": "date-time",
+ "example": "2025-07-23T09:00:00Z"
+ },
+ "updated_at": {
+ "type": "string",
+ "format": "date-time",
+ "example": "2025-07-23T09:00:00Z"
+ }
+ },
+ "type": "object"
+ }
+ }
+ },
+ "type": "object"
+ }
+ }
+ }
+ },
+ "401": {
+ "description": "인증 실패"
+ },
+ "500": {
+ "description": "서버 에러"
+ }
+ },
+ "security": [
+ {
+ "ApiKeyAuth": []
+ },
+ {
+ "BearerAuth": []
+ }
+ ]
+ }
+ }
+ },
+ "components": {
+ "securitySchemes": {
+ "ApiKeyAuth": {
+ "type": "apiKey",
+ "in": "header",
+ "name": "X-API-KEY",
+ "description": "API Key 인증: X-API-KEY: {API_KEY}"
+ },
+ "BearerAuth": {
+ "type": "http",
+ "bearerFormat": "JWT",
+ "scheme": "bearer"
+ }
+ }
+ },
+ "tags": [
+ {
+ "name": "API Key 인증",
+ "description": "API Key 인증"
+ },
+ {
+ "name": "Auth",
+ "description": "Auth"
+ },
+ {
+ "name": "Member",
+ "description": "Member"
+ },
+ {
+ "name": "Product",
+ "description": "Product"
+ }
+ ]
+}
\ No newline at end of file