Skip to content

Latest commit

ย 

History

History
80 lines (66 loc) ยท 8.24 KB

API_PERMISSION_MATRIX.md

File metadata and controls

80 lines (66 loc) ยท 8.24 KB

API ๊ถŒํ•œ ๋งคํŠธ๋ฆญ์Šค (2๋‹จ๊ณ„ ์™„๋ฃŒ ์‹œ์  ๊ธฐ์ค€)

์ž‘์„ฑ์ผ: 2026-08-11 ๋ฒ”์œ„: honeyRest_user(์‚ฌ์šฉ์ž ๋ฐฑ์—”๋“œ), honeyRest_host(ํ˜ธ์ŠคํŠธ ๋ฐฑ์—”๋“œ) ๊ธฐ์ค€ ์ปค๋ฐ‹: ๊ฐ ์ €์žฅ์†Œ main ์ตœ์‹  (1๋‹จ๊ณ„ + 2๋‹จ๊ณ„ ๋ณ‘ํ•ฉ ํ›„)

์ด ๋ฌธ์„œ๋Š” ROADMAP.md 2๋‹จ๊ณ„ ํ•ญ๋ชฉ 1ยท์™„๋ฃŒ ๊ฒŒ์ดํŠธ G2์˜ ์‚ฐ์ถœ๋ฌผ์ด๋‹ค. "์ธ๊ฐ€ ๊ทผ๊ฑฐ"๋Š” ๊ฐ ์—”๋“œํฌ์ธํŠธ๊ฐ€ ์‹ค์ œ๋กœ ๋ฌด์—‡์„ ๊ธฐ์ค€์œผ๋กœ ์ ‘๊ทผ์„ ํ—ˆ์šฉ/๊ฑฐ๋ถ€ํ•˜๋Š”์ง€๋ฅผ ๊ฐ€๋ฆฌํ‚ค๋ฉฐ, ์š”์ฒญ ๋ณธ๋ฌธยท์ฟผ๋ฆฌ์˜ id๋ฅผ ์‹ ๋ขฐํ•˜์ง€ ์•Š๋Š”๋‹ค๋Š” ์›์น™์ด ์ง€์ผœ์ง€๋Š”์ง€๊ฐ€ ํ•ต์‹ฌ ์ ๊ฒ€ ๋Œ€์ƒ์ด๋‹ค.

1. ์—ญํ•  ์ •์˜

์ €์žฅ์†Œ ์—ญํ•  ์˜๋ฏธ
์‚ฌ์šฉ์ž ๋ฐฑ์—”๋“œ (์ต๋ช…) ๋กœ๊ทธ์ธํ•˜์ง€ ์•Š์€ ๋ฐฉ๋ฌธ์ž
์‚ฌ์šฉ์ž ๋ฐฑ์—”๋“œ USER ๋กœ๊ทธ์ธํ•œ ์ผ๋ฐ˜ ํšŒ์› (JWT์˜ role ํด๋ ˆ์ž„์ด ์•„๋‹ˆ๋ผ ๋งค ์š”์ฒญ๋งˆ๋‹ค DB์—์„œ ์žฌ์กฐํšŒํ•œ user.role)
์‚ฌ์šฉ์ž ๋ฐฑ์—”๋“œ ADMIN ๋ฐฐ๋„ˆ/์ด๋ฒคํŠธ/์ˆ™์†Œ ํƒœ๊ทธ ์“ฐ๊ธฐ ์ „์šฉ ์—ญํ• . ์ด ๋ฐฑ์—”๋“œ์—๋Š” ADMIN์„ ์‹ค์ œ๋กœ ๋ถ€์—ฌํ•˜๋Š” ๊ฐ€์ž… ๊ฒฝ๋กœ๊ฐ€ ์—†๋‹ค โ€” ์ฆ‰ ํ˜„์žฌ๋Š” ์‚ฌ์‹ค์ƒ ์ „๋ฉด ์ฐจ๋‹จ(fail-closed) ์ƒํƒœ์ด๋ฉฐ, ํ˜ธ์ŠคํŠธ ๋ฐฑ์—”๋“œ๋กœ์˜ ์ด๊ด€ ๋˜๋Š” ๋ณ„๋„ ๋ฐœ๊ธ‰ ์ ˆ์ฐจ๊ฐ€ 3๋‹จ๊ณ„ ์ดํ›„ ๊ณผ์ œ๋‹ค
ํ˜ธ์ŠคํŠธ ๋ฐฑ์—”๋“œ (์ต๋ช…) ๋กœ๊ทธ์ธํ•˜์ง€ ์•Š์€ ๋ฐฉ๋ฌธ์ž
ํ˜ธ์ŠคํŠธ ๋ฐฑ์—”๋“œ COMPANY_ADMIN ์ž…์  ์—…์ฒด ๊ด€๋ฆฌ์ž. ์ž๊ธฐ ํšŒ์‚ฌ ์†Œ์œ  ๋ฆฌ์†Œ์Šค๋งŒ ์ ‘๊ทผ ๊ฐ€๋Šฅ
ํ˜ธ์ŠคํŠธ ๋ฐฑ์—”๋“œ SUPER_ADMIN ์ด๊ด€๋ฆฌ์ž. ์ „ ์—…์ฒด ๋ฐ์ดํ„ฐ ์ ‘๊ทผ ๋ฐ ์Šน์ธ ๊ถŒํ•œ

2. ์‹ ์› ํ•ด์„ ๋ฐฉ์‹

์ €์žฅ์†Œ ์‹ ์› ํŒ๋ณ„ ์†Œ์Šค ๋น„๊ณ 
์‚ฌ์šฉ์ž ๋ฐฑ์—”๋“œ @AuthenticationPrincipal CustomUserPrincipal โ†’ principal.getUserId() JwtTokenProvider.getAuthentication()๊ฐ€ ๋งค ์š”์ฒญ๋งˆ๋‹ค userRepository.findById()๋กœ DB ์žฌ์กฐํšŒํ•˜๋ฉฐ, tokenValidAfter(๋กœ๊ทธ์•„์›ƒ/๋น„๋ฒˆ๋ณ€๊ฒฝ ์ดํ›„ ๋ฐœ๊ธ‰ ์—ฌ๋ถ€)์™€ status != DELETED๋ฅผ ํ•จ๊ป˜ ๊ฒ€์‚ฌํ•œ๋‹ค
ํ˜ธ์ŠคํŠธ ๋ฐฑ์—”๋“œ Authentication.getName() (JWT์˜ email ํด๋ ˆ์ž„) โ†’ CompanyResourceAccessService.currentCompanyId(authentication) ์ปจํŠธ๋กค๋Ÿฌ๋งˆ๋‹ค ํฉ์–ด์ ธ ์žˆ๋˜ ์‹ ์› ํ•ด์„์„ 1๋‹จ๊ณ„ยท2๋‹จ๊ณ„์—์„œ ์ด ์„œ๋น„์Šค๋กœ ์ ์ง„์ ์œผ๋กœ ํ†ตํ•ฉํ•จ. @AuthenticationPrincipal User๋Š” ์ด ์•ฑ์˜ principal ํƒ€์ž…์ด String์ด๋ผ ํ•ญ์ƒ null์ด ๋˜๋Š” ๋ฒ„๊ทธ๊ฐ€ ์žˆ์—ˆ๊ณ (P0-3), ๋ฐœ๊ฒฌ๋œ ์ง€์ ์€ ๋ชจ๋‘ ์ˆ˜์ •ํ•จ

3. ์‚ฌ์šฉ์ž ๋ฐฑ์—”๋“œ โ€” ์—”๋“œํฌ์ธํŠธ๋ณ„ ์ธ๊ฐ€ ๊ทผ๊ฑฐ

์—”๋“œํฌ์ธํŠธ ๊ณต๊ฐœ ๋ฒ”์œ„ ์ธ๊ฐ€ ๊ทผ๊ฑฐ ์ƒํƒœ
GET /api/accommodations/**, /api/event/**, /api/banner/** ์ต๋ช… ํฌํ•จ ์ „์ฒด ๊ณต๊ฐœ ์—†์Œ(์˜๋„๋œ ๊ณต๊ฐœ ์กฐํšŒ) ์•ˆ์ „
POST/PUT/DELETE /api/accommodations/**, /api/event/**, /api/banner/** ADMIN๋งŒ hasRole("ADMIN") (๋ฐœ๊ธ‰ ๊ฒฝ๋กœ ์—†์–ด ์‚ฌ์‹ค์ƒ ์ „๋ฉด ์ฐจ๋‹จ) ์•ˆ์ „
GET /api/reserve/form-info ์ต๋ช… ํ—ˆ์šฉ(๋น„ํšŒ์› ์˜ˆ์•ฝ ์ง€์›) userId๋ฅผ ์ฟผ๋ฆฌ์—์„œ ๋ฐ›์ง€ ์•Š๊ณ  principal์—์„œ ๋„์ถœ, ๋น„๋กœ๊ทธ์ธ ์‹œ ๊ฐœ์ธ์ •๋ณด ํ•„๋“œ๋Š” ๋น„์›€ ์•ˆ์ „ (P0-4 ์ˆ˜์ •)
POST /api/payment/toss/confirm USER reservationInfo.userId๋ฅผ ์š”์ฒญ ๋ฐ”๋””๊ฐ’์œผ๋กœ ๋‘์ง€ ์•Š๊ณ  ํ•ญ์ƒ principal.getUserId()๋กœ ๋ฎ์–ด์”€ ์•ˆ์ „ (P0-7 ์ˆ˜์ •)
POST /api/wishList/toggle USER dto.userId ๋Œ€์‹  principal.getUserId() ์•ˆ์ „ (P1-4 ์ˆ˜์ •)
POST /api/review/write USER reservation.user == principal && status == COMPLETED ๊ฒ€์ฆ ์•ˆ์ „ (P0-6 ์ˆ˜์ •)
DELETE/POST /api/user/reviews/** USER ์„œ๋น„์Šค ๊ณ„์ธต์—์„œ review.user.userId == principal.userId ์•ˆ์ „
GET/POST /api/user/reservations/** USER findByReservationIdAndUser_UserId๋กœ ์กฐํšŒ ์ž์ฒด๊ฐ€ ์Šค์ฝ”ํ”„๋จ ์•ˆ์ „
GET /api/user/coupons, /point-history USER principal.getUserId() ๊ณ ์ •, ์ฟผ๋ฆฌ ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ํƒ€์ธ id ์ง€์ • ๋ถˆ๊ฐ€ ์•ˆ์ „
POST /api/files/upload, DELETE /api/files USER folder ํ™”์ดํŠธ๋ฆฌ์ŠคํŠธ(reviews,profile) + DB ์กฐํšŒ๋กœ ์‹ค์ œ ์†Œ์œ  ๋ฆฌ์†Œ์Šค์ธ์ง€ ์žฌ๊ฒ€์ฆ ์•ˆ์ „ (P1-5 ์ˆ˜์ •)
POST /api/user/email/verify-change USER (2๋‹จ๊ณ„์—์„œ authenticated๋กœ ์ „ํ™˜) ํ† ํฐ์˜ tokenType == EMAIL_CHANGE, pendingEmail == newEmail, ํ˜ธ์ถœ์ž == token.user ๋ชจ๋‘ ๊ฒ€์ฆ ์•ˆ์ „ (P0-8 ์ˆ˜์ •)
POST /api/auth/logout USER ๋กœ๊ทธ์•„์›ƒ ์‹œ user.tokenValidAfter๋ฅผ ๊ฐฑ์‹ ํ•ด ๊ธฐ์กด access token์„ ์ „๋ถ€ ๋ฌดํšจํ™” ์•ˆ์ „ (P1-10 ์ˆ˜์ •)

4. ํ˜ธ์ŠคํŠธ ๋ฐฑ์—”๋“œ โ€” ์—”๋“œํฌ์ธํŠธ๋ณ„ ์ธ๊ฐ€ ๊ทผ๊ฑฐ

์—”๋“œํฌ์ธํŠธ ๊ณต๊ฐœ ๋ฒ”์œ„ ์ธ๊ฐ€ ๊ทผ๊ฑฐ ์ƒํƒœ
/admin/** COMPANY_ADMIN hasRole("COMPANY_ADMIN") ์•ˆ์ „
/owner/** SUPER_ADMIN hasRole("SUPER_ADMIN") ์•ˆ์ „
/api/owner/auth/signup SUPER_ADMIN /api/owner/**๋ฅผ hasRole("SUPER_ADMIN")๋กœ ๋ช…์‹œ ์ž ๊ธˆ + ์„œ๋น„์Šค๊ฐ€ ์š”์ฒญ role์„ ๊ทธ๋Œ€๋กœ ์‹ ๋ขฐํ•˜์ง€ ์•Š๊ณ  ๊ฒ€์ฆ๋œ ํ˜ธ์ถœ์ž ์ปจํ…์ŠคํŠธ์—์„œ๋งŒ role ์ง€์ • ํ—ˆ์šฉ ์•ˆ์ „ (P0-2 ์ˆ˜์ •, ๊ฐ€์žฅ ์‹ฌ๊ฐํ–ˆ๋˜ ๊ถŒํ•œ ์ƒ์Šน)
/api/admin/auth/signup, /login ์ต๋ช…(์‹ ๊ทœ ์—…์ฒด ์ž๊ฐ€ ๊ฐ€์ž… ๋ชฉ์ ) ์„œ๋น„์Šค๊ฐ€ role์„ ํ•ญ์ƒ COMPANY_ADMIN์œผ๋กœ ๊ณ ์ •, ์ด๋ฉ”์ผ ์ค‘๋ณต ์ฒดํฌ ํ™œ์„ฑํ™” ์•ˆ์ „
/admin/price/**(๊ฐ€๊ฒฉ ์บ˜๋ฆฐ๋”) COMPANY_ADMIN ํด๋ผ์ด์–ธํŠธ๊ฐ€ ๋ณด๋‚ธ companyId๋ฅผ ์‹ ๋ขฐํ•˜์ง€ ์•Š๊ณ  CompanyResourceAccessService.currentCompanyId(auth)๋กœ ์žฌ๊ณ„์‚ฐ, roomId/accommodationId๋„ ์†Œ์œ ๊ถŒ ๊ฒ€์ฆ ์•ˆ์ „ (P0-4 ์ˆ˜์ •)
/admin/reviews/**, /admin/inquiries/** ๋‹จ๊ฑด ์กฐ์ž‘ COMPANY_ADMIN ownsReview/ownsInquiry๋กœ accommodation ์†Œ์œ ๊ถŒ ์—ญ์ถ”์  ๊ฒ€์ฆ ์•ˆ์ „ (P0-5 ์ˆ˜์ •)
/admin/point/refunds(๊ฒฐ์ œ/ํ™˜๋ถˆ) COMPANY_ADMIN @AuthenticationPrincipal User(ํ•ญ์ƒ null์ด๋˜ ๋ฒ„๊ทธ) ์ œ๊ฑฐ, Authentication.getName() ์‚ฌ์šฉ. companyId ๋ชป ๊ตฌํ•˜๋ฉด fail-closed ๋นˆ ๋ชฉ๋ก ์•ˆ์ „ (P0-3 ์ˆ˜์ •)
/admin/accommodations/{id}/request COMPANY_ADMIN ํšŒ์‚ฌ ์†Œ์œ ๊ถŒ ํ™•์ธ + changeStatus๊ฐ€ PENDING ์™ธ ๊ฐ’์„ ๊ฑฐ๋ถ€(์ž๊ฐ€ ์Šน์ธ ์ฐจ๋‹จ) ์•ˆ์ „ (P1-1 ์ˆ˜์ •)
/owner/accommodation/{id}/approve, /reject SUPER_ADMIN /owner/** ์ž ๊ธˆ + updateStatusIfCurrent๋กœ PENDING โ†’ ACTIVE/REJECTED ์›์ž์  ์ „์ด๋งŒ ํ—ˆ์šฉ ์•ˆ์ „ (P1-1/P1-2 ์ˆ˜์ •, ์‹ ์„ค)
POST /admin/rooms/{roomId} COMPANY_ADMIN roomId ์†Œ์œ ๊ถŒ + ํผ์˜ accommodationId๋„ ๊ฐ™์€ ํšŒ์‚ฌ ์†Œ์†์ธ์ง€ ๊ฒ€์ฆ ์•ˆ์ „ (P1-3 ์ˆ˜์ •)
์ˆ™์†Œ ์ด๋ฏธ์ง€ ์‚ญ์ œ(deleteSubImageIds) COMPANY_ADMIN accommodationId์™€ imageId๊ฐ€ ์‹ค์ œ๋กœ ์—ฐ๊ฒฐ๋œ ๊ฒฝ์šฐ๋งŒ ์‚ญ์ œ(deleteByAccommodation_AccommodationIdAndImageIdIn) ์•ˆ์ „ (P1-4 ์ˆ˜์ •)
JWT ์ธ์ฆ ์ „๋ฐ˜ - typ ํด๋ ˆ์ž„์ด access์ธ ํ† ํฐ๋งŒ ์ธ์ฆ์— ์‚ฌ์šฉ, refresh ํ† ํฐ์œผ๋กœ๋Š” ์ธ์ฆ ๋ถˆ๊ฐ€ ์•ˆ์ „ (P1-7 ์ˆ˜์ •)
ํผ ๊ธฐ๋ฐ˜ ๊ด€๋ฆฌ์ž ์ฝ˜์†” ์ „์ฒด (/admin/**, /owner/**์˜ POST) COMPANY_ADMIN/SUPER_ADMIN CookieCsrfTokenRepository + ์กฐ๊ธฐ ๋กœ๋”ฉ ํ•„ํ„ฐ + MultipartFilter ์ˆœ์„œ ์กฐ์ •์œผ๋กœ ์žฌํ™œ์„ฑํ™” ์•ˆ์ „ (2026-08-11 ์™„๋ฃŒ)

5. ์•Œ๋ ค์ง„ ์ž”์—ฌ ์œ„ํ—˜ (3๋‹จ๊ณ„ ์ดํ›„๋กœ ์ด์—ฐ)

  • ์˜ˆ์•ฝ ์žฌ๊ณ /๋™์‹œ์„ฑ: ๋‚ ์งœ๋ณ„ ์žฌ๊ณ  ํ…Œ์ด๋ธ”์ด ์—†์–ด ๋™์ผ ๊ฐ์‹ค ์ค‘๋ณต ์˜ˆ์•ฝ(์˜ค๋ฒ„๋ถ€ํ‚น)์ด ๊ฐ€๋Šฅ. 3๋‹จ๊ณ„ ํ•ญ๋ชฉ.
  • ๊ฒฐ์ œ ๋ณด์ƒ ํŠธ๋žœ์žญ์…˜: Toss ์Šน์ธ ํ›„ DB ์‹คํŒจ ์‹œ ์ž๋™ ์ทจ์†Œยท์žฌ์ฒ˜๋ฆฌ๊ฐ€ ์—†์Œ. 4๋‹จ๊ณ„ ํ•ญ๋ชฉ.
  • CSRF ์žฌํ™œ์„ฑํ™”: ์œ„ ํ‘œ ์ฐธ๊ณ , ๋ณ„๋„ ์ž‘์—…์œผ๋กœ ๋ถ„๋ฆฌ๋จ(task_1cdef24a).
  • principal resolver ์™„์ „ ํ†ตํ•ฉ: ํ˜ธ์ŠคํŠธ ๋ฐฑ์—”๋“œ๋Š” ์ด๋ฒˆ ๋‹จ๊ณ„์—์„œ ์†๋Œ„ ์ปจํŠธ๋กค๋Ÿฌ ์œ„์ฃผ๋กœ CompanyResourceAccessService์— ์ˆ˜๋ ด์‹œ์ผฐ์œผ๋‚˜, ์ „์ฒด ์ปจํŠธ๋กค๋Ÿฌ๋ฅผ ๋Œ€์ƒ์œผ๋กœ ํ•œ ์ „์ˆ˜ ๊ฐ์‚ฌ๋Š” ์•„์ง ํ•˜์ง€ ์•Š์•˜๋‹ค.

6. Gate G2 ์ฒดํฌ๋ฆฌ์ŠคํŠธ

  • ์ด๋ฒˆ ๋‹จ๊ณ„์—์„œ ๋ณ€๊ฒฝํ•œ API๋Š” ๋ณธ๋ฌธยท์ฟผ๋ฆฌ์˜ ์‚ฌ์šฉ์ž/ํšŒ์‚ฌ ID๋ฅผ ๊ถŒํ•œ ๊ทผ๊ฑฐ๋กœ ์“ฐ์ง€ ์•Š๋Š”๋‹ค.
  • ์ด๋ฒˆ ๋‹จ๊ณ„์—์„œ ๋‹ค๋ฃฌ ์ €์žฅ์†Œ ์กฐํšŒ์— null์„ ์ „๋‹ฌํ•ด ์ „์ฒด ํ…Œ๋„ŒํŠธ๊ฐ€ ๋…ธ์ถœ๋˜๋Š” ๊ฒฝ๋กœ๋ฅผ ๋‹ซ์•˜๋‹ค(PaymentRepository ๋“ฑ).
  • ์ด๋ฒˆ ๋‹จ๊ณ„์—์„œ ์ˆ˜์ •ํ•œ ํ•ญ๋ชฉ์— ๋Œ€ํ•ด ์—ญํ• ๋ณ„ ํ—ˆ์šฉยท๊ฑฐ๋ถ€ ํšŒ๊ท€ ํ…Œ์ŠคํŠธ๋ฅผ ์ถ”๊ฐ€ํ–ˆ๋‹ค (OwnerAuthSignupSecurityTest, PaymentServiceImplTest, OAccommodationServiceImplTest, JwtAuthFilterTest, AdminWriteApiSecurityTest, FileControllerTest, ReviewServiceTest, JwtTokenProviderTest ๋“ฑ).
  • ์ „์ฒด API ํ‘œ๋ฉด์— ๋Œ€ํ•œ ์™„์ „ํ•œ ๊ถŒํ•œ ๋งคํŠธ๋ฆญ์Šค๋Š” ์•„๋‹ˆ๋‹ค โ€” ์ด๋ฒˆ์— ๋‹ค๋ฃฌ ํ•ญ๋ชฉ ์œ„์ฃผ๋‹ค. ๋‚˜๋จธ์ง€ ์ปจํŠธ๋กค๋Ÿฌ ์ „์ˆ˜ ์ ๊ฒ€์€ 3๋‹จ๊ณ„ ์ดํ›„ ๋ณ„๋„ ๊ฐ์‚ฌ๋กœ ๋‚จ๊ฒจ๋‘”๋‹ค.