Files
Gnuboard7/plugins/_bundled/sirsoft-gdpr/src/Repositories/GdprUserConsentRepository.php
T
chym1217 ef13a1ddff feat(gdpr): 쿠키 거부 기능 + 마이페이지 동의 관리 토글 재설계
STEP 1~7 (거부 기능):
- 쿠키 배너에 「동의하지 않고 계속하기」 거부 버튼 추가 (intent=reject)
- is_rejected/rejected_at 컬럼 + ConsentAction Enum 3분기 (동의/철회/거부)
- 관리자 동의 이력에 [거부] 필터 + amber 배지

STEP A~F (토글 재설계):
- 필수 카테고리를 동의 축에서 완전 제외 (status/history 미저장) — ePrivacy Art.5(3) 면제
- 마이페이지 표→토글 전환: 필수=「항상 켜짐」 잠금, 선택=on/off 스위치, 동의일 제거, 「모두 켜기」 바
- 거부 토스트 문구 정정: consent.granted → rejected_saved (배너 + 컨트롤러 응답)

테스트: 백엔드 201/201, 프론트 288/288, 시나리오 커버리지 audit 통과
Chrome MCP 실측: 토글 grant/revoke/모두켜기 + 배너 거부 토스트 + 거부 직후 마이페이지 표기 확인
2026-07-27 15:58:28 +09:00

140 lines
4.3 KiB
PHP

<?php
namespace Plugins\Sirsoft\Gdpr\Repositories;
use Illuminate\Support\Collection;
use Plugins\Sirsoft\Gdpr\Models\GdprUserConsent;
use Plugins\Sirsoft\Gdpr\Repositories\Contracts\GdprUserConsentRepositoryInterface;
/**
* GDPR 사용자 현재 동의 상태 Repository 구현체
*/
class GdprUserConsentRepository implements GdprUserConsentRepositoryInterface
{
/**
* 사용자 ID와 동의 키로 동의 상태를 조회합니다.
*
* @param int $userId 사용자 ID
* @param string $consentKey 동의 항목 키
* @return GdprUserConsent|null
*/
public function findByUserAndKey(int $userId, string $consentKey): ?GdprUserConsent
{
return GdprUserConsent::where('user_id', $userId)
->where('consent_key', $consentKey)
->first();
}
/**
* 사용자 ID로 모든 동의 상태를 조회합니다.
*
* @param int $userId 사용자 ID
* @return Collection<int, GdprUserConsent>
*/
public function getAllByUserId(int $userId): Collection
{
return GdprUserConsent::where('user_id', $userId)->get();
}
/**
* 사용자 ID로 활성 동의(is_consented=true)만 조회합니다.
*
* @param int $userId 사용자 ID
* @return Collection<int, GdprUserConsent>
*/
public function getActiveByUserId(int $userId): Collection
{
return GdprUserConsent::where('user_id', $userId)
->where('is_consented', true)
->get();
}
/**
* 가상의 비활성 동의 상태 모델을 합성합니다 (DB 미저장).
*
* @param int $userId 사용자 ID
* @param string $consentKey 동의 항목 키 (cookie_ 접두사 포함)
* @param string|null $consentCategory 카테고리
* @return GdprUserConsent 합성된 비활성 모델 (DB 미저장)
*/
public function buildVirtualStatus(int $userId, string $consentKey, ?string $consentCategory = null): GdprUserConsent
{
$row = new GdprUserConsent();
$row->user_id = $userId;
$row->consent_key = $consentKey;
$row->consent_category = $consentCategory;
$row->is_consented = false;
$row->is_rejected = false;
$row->consent_count = 0;
$row->consented_at = null;
$row->revoked_at = null;
$row->rejected_at = null;
$row->policy_version = null;
$row->last_source = null;
// exists=false 로 두어 호출 측이 이 모델이 영구화되지 않았음을 인식 가능 (Eloquent 기본값)
return $row;
}
/**
* 동의 상태 레코드를 생성하거나 업데이트합니다.
*
* @param int $userId 사용자 ID
* @param string $consentKey 동의 항목 키
* @param array $data 업데이트 데이터
* @return GdprUserConsent
*/
public function upsert(int $userId, string $consentKey, array $data): GdprUserConsent
{
$consent = GdprUserConsent::firstOrNew([
'user_id' => $userId,
'consent_key' => $consentKey,
]);
$consent->fill($data)->save();
return $consent->fresh();
}
/**
* 사용자의 모든 활성 동의를 일괄 철회 처리합니다 (탈퇴 시 사용).
*
* @param int $userId 사용자 ID
* @return int 영향받은 행 수
*/
public function revokeAllForUser(int $userId): int
{
return GdprUserConsent::where('user_id', $userId)
->where('is_consented', true)
->update([
'is_consented' => false,
'revoked_at' => now(),
'last_source' => 'withdraw',
]);
}
/**
* 특정 동의 키에 동의한 사용자 수를 반환합니다.
*
* @param string $consentKey 동의 항목 키
* @return int
*/
public function countConsentedByKey(string $consentKey): int
{
return GdprUserConsent::where('consent_key', $consentKey)
->where('is_consented', true)
->count();
}
/**
* 사용자 ID로 모든 동의 상태 레코드를 삭제합니다.
*
* @param int $userId 사용자 ID
* @return void
*/
public function deleteByUserId(int $userId): void
{
GdprUserConsent::where('user_id', $userId)->delete();
}
}