Improve GDPR implementation
This commit is contained in:
88
frontend/src/api/services/consent.ts
Normal file
88
frontend/src/api/services/consent.ts
Normal file
@@ -0,0 +1,88 @@
|
||||
// ================================================================
|
||||
// frontend/src/api/services/consent.ts
|
||||
// ================================================================
|
||||
/**
|
||||
* Consent Service - GDPR Compliance
|
||||
*
|
||||
* Backend API: services/auth/app/api/consent.py
|
||||
*
|
||||
* Last Updated: 2025-10-16
|
||||
*/
|
||||
import { apiClient } from '../client';
|
||||
|
||||
export interface ConsentRequest {
|
||||
terms_accepted: boolean;
|
||||
privacy_accepted: boolean;
|
||||
marketing_consent?: boolean;
|
||||
analytics_consent?: boolean;
|
||||
consent_method: 'registration' | 'settings' | 'cookie_banner';
|
||||
consent_version?: string;
|
||||
}
|
||||
|
||||
export interface ConsentResponse {
|
||||
id: string;
|
||||
user_id: string;
|
||||
terms_accepted: boolean;
|
||||
privacy_accepted: boolean;
|
||||
marketing_consent: boolean;
|
||||
analytics_consent: boolean;
|
||||
consent_version: string;
|
||||
consent_method: string;
|
||||
consented_at: string;
|
||||
withdrawn_at: string | null;
|
||||
}
|
||||
|
||||
export interface ConsentHistoryResponse {
|
||||
id: string;
|
||||
user_id: string;
|
||||
action: string;
|
||||
consent_snapshot: Record<string, any>;
|
||||
created_at: string;
|
||||
}
|
||||
|
||||
export class ConsentService {
|
||||
private readonly baseUrl = '/auth';
|
||||
|
||||
/**
|
||||
* Record user consent for data processing
|
||||
* GDPR Article 7 - Conditions for consent
|
||||
*/
|
||||
async recordConsent(consentData: ConsentRequest): Promise<ConsentResponse> {
|
||||
return apiClient.post<ConsentResponse>(`${this.baseUrl}/consent`, consentData);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get current active consent for user
|
||||
*/
|
||||
async getCurrentConsent(): Promise<ConsentResponse | null> {
|
||||
return apiClient.get<ConsentResponse | null>(`${this.baseUrl}/consent/current`);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get complete consent history for user
|
||||
* GDPR Article 7(1) - Demonstrating consent
|
||||
*/
|
||||
async getConsentHistory(): Promise<ConsentHistoryResponse[]> {
|
||||
return apiClient.get<ConsentHistoryResponse[]>(`${this.baseUrl}/consent/history`);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update user consent preferences
|
||||
* GDPR Article 7(3) - Withdrawal of consent
|
||||
*/
|
||||
async updateConsent(consentData: ConsentRequest): Promise<ConsentResponse> {
|
||||
return apiClient.put<ConsentResponse>(`${this.baseUrl}/consent`, consentData);
|
||||
}
|
||||
|
||||
/**
|
||||
* Withdraw all consent
|
||||
* GDPR Article 7(3) - Right to withdraw consent
|
||||
*/
|
||||
async withdrawConsent(): Promise<{ message: string; withdrawn_count: number }> {
|
||||
return apiClient.post<{ message: string; withdrawn_count: number }>(
|
||||
`${this.baseUrl}/consent/withdraw`
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export const consentService = new ConsentService();
|
||||
@@ -299,6 +299,53 @@ export class SubscriptionService {
|
||||
doesAnalyticsLevelMeetMinimum(level: AnalyticsLevel, minimumRequired: AnalyticsLevel): boolean {
|
||||
return ANALYTICS_HIERARCHY[level] >= ANALYTICS_HIERARCHY[minimumRequired];
|
||||
}
|
||||
|
||||
/**
|
||||
* Cancel subscription - Downgrade to read-only mode
|
||||
*/
|
||||
async cancelSubscription(tenantId: string, reason?: string): Promise<{
|
||||
success: boolean;
|
||||
message: string;
|
||||
status: string;
|
||||
cancellation_effective_date: string;
|
||||
days_remaining: number;
|
||||
read_only_mode_starts: string;
|
||||
}> {
|
||||
return apiClient.post('/subscriptions/cancel', {
|
||||
tenant_id: tenantId,
|
||||
reason: reason || ''
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reactivate a cancelled or inactive subscription
|
||||
*/
|
||||
async reactivateSubscription(tenantId: string, plan: string = 'starter'): Promise<{
|
||||
success: boolean;
|
||||
message: string;
|
||||
status: string;
|
||||
plan: string;
|
||||
next_billing_date: string | null;
|
||||
}> {
|
||||
return apiClient.post('/subscriptions/reactivate', {
|
||||
tenant_id: tenantId,
|
||||
plan
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Get subscription status including read-only mode info
|
||||
*/
|
||||
async getSubscriptionStatus(tenantId: string): Promise<{
|
||||
tenant_id: string;
|
||||
status: string;
|
||||
plan: string;
|
||||
is_read_only: boolean;
|
||||
cancellation_effective_date: string | null;
|
||||
days_until_inactive: number | null;
|
||||
}> {
|
||||
return apiClient.get(`/subscriptions/${tenantId}/status`);
|
||||
}
|
||||
}
|
||||
|
||||
export const subscriptionService = new SubscriptionService();
|
||||
@@ -18,7 +18,7 @@
|
||||
|
||||
/**
|
||||
* User registration request
|
||||
* Backend: services/auth/app/schemas/auth.py:15-24 (UserRegistration)
|
||||
* Backend: services/auth/app/schemas/auth.py:15-29 (UserRegistration)
|
||||
*/
|
||||
export interface UserRegistration {
|
||||
email: string; // EmailStr - validated email format
|
||||
@@ -29,6 +29,11 @@ export interface UserRegistration {
|
||||
subscription_plan?: string | null; // Default: "starter", options: starter, professional, enterprise
|
||||
use_trial?: boolean | null; // Default: false - Whether to use trial period
|
||||
payment_method_id?: string | null; // Stripe payment method ID
|
||||
// GDPR Consent fields
|
||||
terms_accepted?: boolean; // Default: true - Accept terms of service
|
||||
privacy_accepted?: boolean; // Default: true - Accept privacy policy
|
||||
marketing_consent?: boolean; // Default: false - Consent to marketing communications
|
||||
analytics_consent?: boolean; // Default: false - Consent to analytics cookies
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user