Restrict Google OAuth to youtube.force-ssl and document zero Google data sharing.
Addresses Google OAuth verification feedback on scopes and privacy disclosure.
This commit is contained in:
@@ -0,0 +1,190 @@
|
|||||||
|
import type { Metadata } from "next";
|
||||||
|
import { LegalPageLayout } from "@/components/LegalPageLayout";
|
||||||
|
import { LEGAL_OPERATOR } from "@/lib/legal/constants";
|
||||||
|
|
||||||
|
export const metadata: Metadata = {
|
||||||
|
title: "Privacy Policy | Songs2VID",
|
||||||
|
description: "How Songs2VID collects, uses, and protects your personal data.",
|
||||||
|
};
|
||||||
|
|
||||||
|
export default function PrivacyPage() {
|
||||||
|
return (
|
||||||
|
<LegalPageLayout
|
||||||
|
title="Privacy Policy"
|
||||||
|
description="How we handle your personal data when you use Songs2VID."
|
||||||
|
>
|
||||||
|
<h2>1. Overview</h2>
|
||||||
|
<p>
|
||||||
|
This Privacy Policy explains how {LEGAL_OPERATOR.name} ("we", "us")
|
||||||
|
processes personal data when you use our website, hosted cloud service, and related features
|
||||||
|
that convert audio and images into videos for upload to YouTube.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
We process personal data in accordance with applicable data protection laws, including the
|
||||||
|
General Data Protection Regulation (GDPR) where it applies.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h2>2. Data controller</h2>
|
||||||
|
<p>
|
||||||
|
{LEGAL_OPERATOR.legalName}
|
||||||
|
<br />
|
||||||
|
{LEGAL_OPERATOR.address}
|
||||||
|
<br />
|
||||||
|
{LEGAL_OPERATOR.city}
|
||||||
|
<br />
|
||||||
|
Email: <a href={`mailto:${LEGAL_OPERATOR.email}`}>{LEGAL_OPERATOR.email}</a>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h2>3. What data we collect</h2>
|
||||||
|
<h3>3.1 Account and authentication data</h3>
|
||||||
|
<p>When you sign in with Google, we receive and store:</p>
|
||||||
|
<ul>
|
||||||
|
<li>Your name, email address, and profile image (from Google)</li>
|
||||||
|
<li>OAuth tokens required to authenticate your session</li>
|
||||||
|
<li>YouTube connection data, including channel ID and title</li>
|
||||||
|
<li>Encrypted YouTube API access and refresh tokens needed to upload videos on your behalf</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<h3>3.2 Uploaded content</h3>
|
||||||
|
<p>When you use the service, we temporarily process:</p>
|
||||||
|
<ul>
|
||||||
|
<li>Image and audio files you upload</li>
|
||||||
|
<li>Generated video files</li>
|
||||||
|
<li>Per-video metadata you provide (title, description, tags, privacy settings, etc.)</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<h3>3.3 Usage and technical data</h3>
|
||||||
|
<ul>
|
||||||
|
<li>Plan type, quota usage, and job processing status</li>
|
||||||
|
<li>IP address, browser type, device information, and request logs</li>
|
||||||
|
<li>Error reports and operational diagnostics</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<h3>3.4 Payment data</h3>
|
||||||
|
<p>
|
||||||
|
If you purchase a paid plan, payment processing is handled by our payment provider. We do
|
||||||
|
not store full payment card details on our servers. We may receive billing status,
|
||||||
|
subscription identifiers, and transaction references.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h2>4. Why we process your data</h2>
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
<strong>Contract performance:</strong> to provide video encoding, metadata handling, and
|
||||||
|
YouTube upload features you request
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<strong>Legitimate interests:</strong> to secure our service, prevent abuse, improve
|
||||||
|
reliability, and enforce our terms
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<strong>Legal obligations:</strong> where required by tax, accounting, or regulatory law
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<strong>Consent:</strong> where you have given explicit consent, such as optional
|
||||||
|
marketing communications if offered
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<h2>5. Third-party services</h2>
|
||||||
|
<p>We use trusted third parties to operate Songs2VID, including:</p>
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
<strong>Google / YouTube:</strong> authentication and video uploads via Google OAuth and
|
||||||
|
the YouTube Data API
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<strong>Hosting and infrastructure providers:</strong> servers, databases, queues, and
|
||||||
|
storage
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<strong>Payment processors:</strong> for Pro and Enterprise billing when available
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<p>
|
||||||
|
These providers process data only as necessary to deliver their services and under
|
||||||
|
appropriate contractual safeguards where required.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h2>Google User Data Sharing and Disclosure</h2>
|
||||||
|
<p>
|
||||||
|
We do not sell, share, transfer, or disclose any Google user data to any third parties.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
All user data retrieved via Google OAuth APIs is used solely and strictly for the core
|
||||||
|
functionality of the application (uploading user-generated media) and is never distributed,
|
||||||
|
transferred, or disclosed to external services, partners, or third parties.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h2>6. Data retention</h2>
|
||||||
|
<ul>
|
||||||
|
<li>Uploaded source files and generated outputs are retained only as long as needed to complete your jobs</li>
|
||||||
|
<li>Account data is kept while your account remains active</li>
|
||||||
|
<li>Billing records may be retained as required by law</li>
|
||||||
|
<li>Logs are retained for a limited period for security and troubleshooting</li>
|
||||||
|
</ul>
|
||||||
|
<p>You may request deletion of your account data subject to legal retention obligations.</p>
|
||||||
|
|
||||||
|
<h2>7. Self-hosted deployments</h2>
|
||||||
|
<p>
|
||||||
|
If you deploy Songs2VID on your own infrastructure, you are the data controller for data
|
||||||
|
processed on your instance. This Privacy Policy applies to the hosted cloud service
|
||||||
|
operated by us, not to independent self-hosted installations unless we provide managed
|
||||||
|
hosting for you under contract.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h2>8. Your rights</h2>
|
||||||
|
<p>Depending on your location, you may have the right to:</p>
|
||||||
|
<ul>
|
||||||
|
<li>Access the personal data we hold about you</li>
|
||||||
|
<li>Request correction or deletion</li>
|
||||||
|
<li>Restrict or object to certain processing</li>
|
||||||
|
<li>Data portability</li>
|
||||||
|
<li>Withdraw consent where processing is consent-based</li>
|
||||||
|
<li>Lodge a complaint with a supervisory authority</li>
|
||||||
|
</ul>
|
||||||
|
<p>
|
||||||
|
To exercise these rights, contact{" "}
|
||||||
|
<a href={`mailto:${LEGAL_OPERATOR.email}`}>{LEGAL_OPERATOR.email}</a>.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h2>9. Cookies and local storage</h2>
|
||||||
|
<p>
|
||||||
|
We use essential cookies and similar technologies for authentication, session management,
|
||||||
|
and security. We do not use non-essential tracking cookies unless disclosed separately and
|
||||||
|
enabled with your consent where required.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h2>10. Security</h2>
|
||||||
|
<p>
|
||||||
|
We implement appropriate technical and organizational measures to protect your data,
|
||||||
|
including encryption in transit, access controls, and isolated processing environments.
|
||||||
|
No method of transmission or storage is 100% secure.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h2>11. International transfers</h2>
|
||||||
|
<p>
|
||||||
|
If data is transferred outside your country, we ensure appropriate safeguards such as
|
||||||
|
standard contractual clauses or equivalent mechanisms where required by law.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h2>12. Children</h2>
|
||||||
|
<p>
|
||||||
|
Songs2VID is not directed at children under 16. We do not knowingly collect personal data
|
||||||
|
from children. If you believe a child has provided us data, please contact us.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h2>13. Changes to this policy</h2>
|
||||||
|
<p>
|
||||||
|
We may update this Privacy Policy from time to time. Material changes will be posted on
|
||||||
|
this page with an updated effective date.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h2>14. Contact</h2>
|
||||||
|
<p>
|
||||||
|
Questions about this Privacy Policy:{" "}
|
||||||
|
<a href={`mailto:${LEGAL_OPERATOR.email}`}>{LEGAL_OPERATOR.email}</a>
|
||||||
|
</p>
|
||||||
|
</LegalPageLayout>
|
||||||
|
);
|
||||||
|
}
|
||||||
+10
-6
@@ -1,5 +1,6 @@
|
|||||||
import { NextAuthOptions } from "next-auth";
|
import { NextAuthOptions } from "next-auth";
|
||||||
import GoogleProvider from "next-auth/providers/google";
|
import GoogleProvider from "next-auth/providers/google";
|
||||||
|
import { encryptSecret } from "./crypto/secrets";
|
||||||
import { prisma } from "./db";
|
import { prisma } from "./db";
|
||||||
import { getInitialQuotaResetAt } from "./quota";
|
import { getInitialQuotaResetAt } from "./quota";
|
||||||
import { fetchYouTubeChannel } from "./youtube/upload";
|
import { fetchYouTubeChannel } from "./youtube/upload";
|
||||||
@@ -18,8 +19,8 @@ export const authOptions: NextAuthOptions = {
|
|||||||
"openid",
|
"openid",
|
||||||
"email",
|
"email",
|
||||||
"profile",
|
"profile",
|
||||||
"https://www.googleapis.com/auth/youtube.upload",
|
// Single YouTube Data API scope (covers upload, channel, and playlist APIs)
|
||||||
"https://www.googleapis.com/auth/youtube.readonly",
|
"https://www.googleapis.com/auth/youtube.force-ssl",
|
||||||
].join(" "),
|
].join(" "),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -49,12 +50,15 @@ export const authOptions: NextAuthOptions = {
|
|||||||
account.refresh_token,
|
account.refresh_token,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const accessToken = encryptSecret(account.access_token);
|
||||||
|
const refreshToken = encryptSecret(account.refresh_token);
|
||||||
|
|
||||||
await prisma.youTubeConnection.upsert({
|
await prisma.youTubeConnection.upsert({
|
||||||
where: { userId: dbUser.id },
|
where: { userId: dbUser.id },
|
||||||
create: {
|
create: {
|
||||||
userId: dbUser.id,
|
userId: dbUser.id,
|
||||||
accessToken: account.access_token,
|
accessToken,
|
||||||
refreshToken: account.refresh_token,
|
refreshToken,
|
||||||
expiresAt: account.expires_at
|
expiresAt: account.expires_at
|
||||||
? new Date(account.expires_at * 1000)
|
? new Date(account.expires_at * 1000)
|
||||||
: new Date(Date.now() + 3600 * 1000),
|
: new Date(Date.now() + 3600 * 1000),
|
||||||
@@ -62,8 +66,8 @@ export const authOptions: NextAuthOptions = {
|
|||||||
channelTitle: channel.channelTitle,
|
channelTitle: channel.channelTitle,
|
||||||
},
|
},
|
||||||
update: {
|
update: {
|
||||||
accessToken: account.access_token,
|
accessToken,
|
||||||
refreshToken: account.refresh_token,
|
refreshToken,
|
||||||
expiresAt: account.expires_at
|
expiresAt: account.expires_at
|
||||||
? new Date(account.expires_at * 1000)
|
? new Date(account.expires_at * 1000)
|
||||||
: new Date(Date.now() + 3600 * 1000),
|
: new Date(Date.now() + 3600 * 1000),
|
||||||
|
|||||||
Reference in New Issue
Block a user