Delete Account API + UI + Store assets (icon, graphic, screenshot)
- DELETE /api/v1/auth/delete-account (GDPR + Google Play req) - Settings: red Delete Account section with confirmation - Store assets: icon-512, feature-graphic, screenshot-1 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
BIN
android/store-assets/feature-graphic.png
Normal file
BIN
android/store-assets/feature-graphic.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 16 KiB |
BIN
android/store-assets/icon-512.png
Normal file
BIN
android/store-assets/icon-512.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 7.2 KiB |
BIN
android/store-assets/screenshot-1.png
Normal file
BIN
android/store-assets/screenshot-1.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 16 KiB |
@@ -101,6 +101,18 @@ async function authRoutes(app) {
|
||||
return { status: 'not_implemented', message: 'WebAuthn biometric auth coming soon.' };
|
||||
});
|
||||
|
||||
// Delete account
|
||||
app.delete('/auth/account', { preHandler: [async (req) => { await req.jwtVerify(); }] }, async (req, reply) => {
|
||||
const uid = req.user.id;
|
||||
await app.db.query('DELETE FROM task_assignments WHERE user_id=$1 OR assigned_by=$1', [uid]);
|
||||
await app.db.query('DELETE FROM tasks WHERE user_id=$1', [uid]);
|
||||
await app.db.query('DELETE FROM task_groups WHERE user_id=$1', [uid]);
|
||||
await app.db.query('DELETE FROM goals WHERE user_id=$1', [uid]);
|
||||
await app.db.query('DELETE FROM sessions WHERE user_id=$1', [uid]);
|
||||
await app.db.query('DELETE FROM users WHERE id=$1', [uid]);
|
||||
return reply.send({ data: { deleted: true } });
|
||||
});
|
||||
|
||||
// OAuth initiate routes moved to ./oauth.js
|
||||
|
||||
// Search users by name or email (for collaboration)
|
||||
@@ -117,3 +129,22 @@ async function authRoutes(app) {
|
||||
}
|
||||
|
||||
module.exports = authRoutes;
|
||||
|
||||
// Delete account (GDPR + Google Play requirement)
|
||||
app.delete("/auth/delete-account", { preHandler: [async (req) => { await req.jwtVerify(); }] }, async (req) => {
|
||||
const userId = req.user.id;
|
||||
|
||||
// Delete all user data in order (foreign keys)
|
||||
await app.db.query("DELETE FROM task_comments WHERE user_id = $1", [userId]);
|
||||
await app.db.query("DELETE FROM subtasks WHERE assigned_to = $1", [userId]);
|
||||
await app.db.query("DELETE FROM task_collaboration WHERE from_user_id = $1 OR to_user_id = $1", [userId]);
|
||||
await app.db.query("DELETE FROM task_assignments WHERE user_id = $1", [userId]);
|
||||
await app.db.query("DELETE FROM push_subscriptions WHERE user_id = $1", [userId]);
|
||||
await app.db.query("DELETE FROM goals WHERE user_id = $1", [userId]);
|
||||
await app.db.query("DELETE FROM connectors WHERE user_id = $1", [userId]);
|
||||
await app.db.query("DELETE FROM tasks WHERE user_id = $1", [userId]);
|
||||
await app.db.query("DELETE FROM task_groups WHERE user_id = $1", [userId]);
|
||||
await app.db.query("DELETE FROM users WHERE id = $1", [userId]);
|
||||
|
||||
return { status: "deleted", message: "Account and all data permanently deleted" };
|
||||
});
|
||||
|
||||
@@ -1,54 +1,34 @@
|
||||
export default function PrivacyPage() {
|
||||
return (
|
||||
<div style={{ maxWidth: 800, margin: "0 auto", padding: "40px 24px", fontFamily: "system-ui" }}>
|
||||
<h1 style={{ fontSize: 28, fontWeight: "bold", marginBottom: 24 }}>Privacy Policy</h1>
|
||||
<p style={{ color: "#666", marginBottom: 16 }}>Last updated: March 29, 2026</p>
|
||||
|
||||
<h2 style={{ fontSize: 20, fontWeight: 600, marginTop: 32, marginBottom: 12 }}>1. Information We Collect</h2>
|
||||
<p>Task Team collects the following information when you create an account:</p>
|
||||
<ul style={{ paddingLeft: 24, marginTop: 8 }}>
|
||||
<li>Email address</li>
|
||||
<li>Name</li>
|
||||
<li>Phone number (optional)</li>
|
||||
</ul>
|
||||
<p style={{ marginTop: 8 }}>We also collect task data, goals, and settings you create within the app.</p>
|
||||
<div style={{ maxWidth: 800, margin: "0 auto", padding: "40px 24px", fontFamily: "system-ui", lineHeight: 1.8 }}>
|
||||
<h1 style={{ fontSize: 28, fontWeight: "bold", marginBottom: 24 }}>Privacy Policy - Task Team</h1>
|
||||
<p style={{ color: "#666", marginBottom: 16 }}>Last updated: March 30, 2026</p>
|
||||
|
||||
<h2 style={{ fontSize: 20, fontWeight: 600, marginTop: 32, marginBottom: 12 }}>2. How We Use Your Data</h2>
|
||||
<p>Your data is used exclusively to provide the Task Team service:</p>
|
||||
<ul style={{ paddingLeft: 24, marginTop: 8 }}>
|
||||
<li>Task management and organization</li>
|
||||
<li>AI-powered planning assistance</li>
|
||||
<li>Calendar and goal tracking</li>
|
||||
<li>Team collaboration features</li>
|
||||
<li>Push notifications for task reminders</li>
|
||||
</ul>
|
||||
<h2 style={{ fontSize: 20, fontWeight: 600, marginTop: 32, marginBottom: 12 }}>Data We Collect</h2>
|
||||
<p>Account info (name, email), task data, GPS location (optional), audio for voice-to-text (optional).</p>
|
||||
|
||||
<h2 style={{ fontSize: 20, fontWeight: 600, marginTop: 32, marginBottom: 12 }}>3. Data Storage</h2>
|
||||
<p>Your data is stored on secure servers in the European Union (Hetzner, Germany). We use PostgreSQL databases with encrypted connections and regular backups.</p>
|
||||
<h2 style={{ fontSize: 20, fontWeight: 600, marginTop: 32, marginBottom: 12 }}>How We Use It</h2>
|
||||
<p>Task management, sync across devices, reminders, GPS auto-verify task completion.</p>
|
||||
|
||||
<h2 style={{ fontSize: 20, fontWeight: 600, marginTop: 32, marginBottom: 12 }}>4. Third-Party Services</h2>
|
||||
<ul style={{ paddingLeft: 24, marginTop: 8 }}>
|
||||
<li><strong>Anthropic Claude AI</strong> — for AI chat and planning features (messages are processed but not stored by Anthropic)</li>
|
||||
<li><strong>Google OAuth</strong> — for optional Google login</li>
|
||||
<li><strong>Expo</strong> — for push notifications</li>
|
||||
</ul>
|
||||
<h2 style={{ fontSize: 20, fontWeight: 600, marginTop: 32, marginBottom: 12 }}>Data Storage</h2>
|
||||
<p>Your data is stored on secure servers in the European Union (Hetzner Cloud, Germany). We use PostgreSQL databases with encrypted connections and regular backups.</p>
|
||||
|
||||
<h2 style={{ fontSize: 20, fontWeight: 600, marginTop: 32, marginBottom: 12 }}>5. Data Sharing</h2>
|
||||
<p>We do not sell, trade, or share your personal data with third parties. Data is only shared with team members you explicitly invite to collaborate.</p>
|
||||
<h2 style={{ fontSize: 20, fontWeight: 600, marginTop: 32, marginBottom: 12 }}>Data Sharing</h2>
|
||||
<p>We do NOT sell data. Services used: Hetzner Cloud Germany, Anthropic Claude AI.</p>
|
||||
|
||||
<h2 style={{ fontSize: 20, fontWeight: 600, marginTop: 32, marginBottom: 12 }}>6. Your Rights (GDPR)</h2>
|
||||
<p>You have the right to:</p>
|
||||
<ul style={{ paddingLeft: 24, marginTop: 8 }}>
|
||||
<li>Access your data</li>
|
||||
<li>Export your data</li>
|
||||
<li>Delete your account and all data</li>
|
||||
<li>Modify your personal information</li>
|
||||
</ul>
|
||||
<h2 style={{ fontSize: 20, fontWeight: 600, marginTop: 32, marginBottom: 12 }}>Your Rights (GDPR)</h2>
|
||||
<p>You have the right to access, correct, and delete your data. Contact: privacy@it-enterprise.cz</p>
|
||||
|
||||
<h2 style={{ fontSize: 20, fontWeight: 600, marginTop: 32, marginBottom: 12 }}>7. Contact</h2>
|
||||
<p>IT Enterprise Solution s.r.o.<br/>Email: apps@it-enterprise.cz<br/>Web: https://it-enterprise.cz</p>
|
||||
|
||||
<p style={{ marginTop: 32, color: "#999", fontSize: 14 }}>© 2026 IT Enterprise Solution s.r.o. All rights reserved.</p>
|
||||
<h2 style={{ fontSize: 20, fontWeight: 600, marginTop: 32, marginBottom: 12 }}>Permissions</h2>
|
||||
<p>Location and microphone are optional, revocable anytime in your device settings.</p>
|
||||
|
||||
<h2 style={{ fontSize: 20, fontWeight: 600, marginTop: 32, marginBottom: 12 }}>Children</h2>
|
||||
<p>Not directed to children under 13.</p>
|
||||
|
||||
<h2 style={{ fontSize: 20, fontWeight: 600, marginTop: 32, marginBottom: 12 }}>Contact</h2>
|
||||
<p>IT Enterprise s.r.o. | privacy@it-enterprise.cz | tasks.hasdo.info</p>
|
||||
|
||||
<p style={{ marginTop: 32, color: "#999", fontSize: 14 }}>© 2026 IT Enterprise s.r.o. All rights reserved.</p>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -217,6 +217,21 @@ export default function SettingsPage() {
|
||||
<div className="text-center text-xs text-muted py-4">
|
||||
<p>{t("common.appName")} {t("common.appVersion")}</p>
|
||||
</div>
|
||||
|
||||
<section className="bg-red-50 dark:bg-red-900/20 rounded-xl p-4 border border-red-200 dark:border-red-800 mt-6">
|
||||
<h2 className="font-semibold text-red-600 dark:text-red-400 mb-2">Smazat ucet</h2>
|
||||
<p className="text-sm text-red-500 mb-3">Trvale smazat ucet a vsechna data. Tuto akci nelze vratit.</p>
|
||||
<button onClick={() => {
|
||||
if (confirm("Opravdu chcete trvale smazat svuj ucet a vsechna data?")) {
|
||||
const token = localStorage.getItem("taskteam_token");
|
||||
fetch("/api/v1/auth/delete-account", { method: "DELETE", headers: { Authorization: "Bearer " + token } })
|
||||
.then(r => r.json())
|
||||
.then(() => { localStorage.clear(); window.location.href = "/login"; });
|
||||
}
|
||||
}} className="px-4 py-2 bg-red-600 text-white rounded-lg text-sm font-medium">
|
||||
Smazat ucet
|
||||
</button>
|
||||
</section>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user