fix: update the logic for change password

This commit is contained in:
2026-07-15 10:50:35 +07:00
parent ece079e71f
commit 3b832fe605
7 changed files with 10 additions and 65 deletions
+2 -22
View File
@@ -31,7 +31,7 @@ export default function ProfilePage() {
const [langOpen, setLangOpen] = useState(false);
const [settings, setSettings] = useState({ fallbackStrategy: "fill-first" });
const [loading, setLoading] = useState(true);
const [passwords, setPasswords] = useState({ current: "", new: "", confirm: "" });
const [passwords, setPasswords] = useState({ new: "", confirm: "" });
const [passStatus, setPassStatus] = useState({ type: "", message: "" });
const [passLoading, setPassLoading] = useState(false);
const [dbLoading, setDbLoading] = useState(false);
@@ -138,7 +138,6 @@ export default function ProfilePage() {
method: "PATCH",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
currentPassword: passwords.current,
newPassword: passwords.new,
}),
});
@@ -147,7 +146,7 @@ export default function ProfilePage() {
if (res.ok) {
setPassStatus({ type: "success", message: "Password updated successfully" });
setPasswords({ current: "", new: "", confirm: "" });
setPasswords({ new: "", confirm: "" });
} else {
setPassStatus({ type: "error", message: data.error || "Failed to update password" });
}
@@ -421,25 +420,6 @@ export default function ProfilePage() {
<h3 className="text-base sm:text-lg font-semibold">Password</h3>
</div>
<form onSubmit={handlePasswordChange} className="flex flex-col gap-4">
{settings.hasPassword && (
<div className="flex flex-col gap-2">
<label className="text-xs sm:text-sm font-medium">Current Password</label>
<Input
type="password"
placeholder="Enter current password"
value={passwords.current}
onChange={(e) => setPasswords({ ...passwords, current: e.target.value })}
required
/>
</div>
)}
{/* {!settings.hasPassword && (
<div className="p-3 rounded-lg bg-blue-500/10 border border-blue-500/20">
<p className="text-sm text-blue-600 dark:text-blue-400">
Setting password for the first time. Leave current password empty or use default: <code className="bg-blue-500/20 px-1 rounded">123456</code>
</p>
</div>
)} */}
<div className="grid grid-cols-1 sm:grid-cols-2 gap-4">
<div className="flex flex-col gap-2">
<label className="text-xs sm:text-sm font-medium">New Password</label>
@@ -131,7 +131,6 @@ export default function ProviderLimits() {
const [lastUpdated, setLastUpdated] = useState(null);
const [hasHydratedAutoRefresh, setHasHydratedAutoRefresh] = useState(false);
const [refreshingAll, setRefreshingAll] = useState(false);
const [countdown, setCountdown] = useState(60);
const [connectionsLoading, setConnectionsLoading] = useState(true);
const [deletingId, setDeletingId] = useState(null);
const [togglingId, setTogglingId] = useState(null);
@@ -165,7 +164,6 @@ export default function ProviderLimits() {
});
const intervalRef = useRef(null);
const countdownRef = useRef(null);
const tickCountRef = useRef(0);
const fetchConnections = useCallback(
@@ -461,7 +459,6 @@ export default function ProviderLimits() {
if (refreshingAll) return;
setRefreshingAll(true);
setCountdown(60);
// Throttle Claude: poll its quota every Nth auto-tick (manual force bypasses)
const tick = (tickCountRef.current += 1);
@@ -571,10 +568,6 @@ export default function ProviderLimits() {
clearInterval(intervalRef.current);
intervalRef.current = null;
}
if (countdownRef.current) {
clearInterval(countdownRef.current);
countdownRef.current = null;
}
return;
}
@@ -583,17 +576,8 @@ export default function ProviderLimits() {
refreshAll();
}, REFRESH_INTERVAL_MS);
// Countdown interval
countdownRef.current = setInterval(() => {
setCountdown((prev) => {
if (prev <= 1) return 60;
return prev - 1;
});
}, 1000);
return () => {
if (intervalRef.current) clearInterval(intervalRef.current);
if (countdownRef.current) clearInterval(countdownRef.current);
};
}, [autoRefresh, refreshAll, hasHydratedAutoRefresh]);
@@ -605,16 +589,9 @@ export default function ProviderLimits() {
clearInterval(intervalRef.current);
intervalRef.current = null;
}
if (countdownRef.current) {
clearInterval(countdownRef.current);
countdownRef.current = null;
}
} else if (autoRefresh && hasHydratedAutoRefresh) {
// Resume auto-refresh when tab becomes visible
intervalRef.current = setInterval(() => refreshAll(), REFRESH_INTERVAL_MS);
countdownRef.current = setInterval(() => {
setCountdown((prev) => (prev <= 1 ? 60 : prev - 1));
}, 1000);
}
};
@@ -927,11 +904,6 @@ export default function ProviderLimits() {
<span className="hidden text-text-primary sm:inline">
Auto-refresh
</span>
{autoRefresh && (
<span className="text-[10px] text-text-muted tabular-nums">
({countdown}s)
</span>
)}
</button>
@@ -287,7 +287,7 @@ export default function RequestDetailsTab() {
className="border-b border-black/5 dark:border-white/5 last:border-b-0 hover:bg-black/[0.02] dark:hover:bg-white/[0.02] transition-colors"
>
<td className="whitespace-nowrap p-4 text-sm text-text-main">
{formatVietnamDateTime(detail.timestamp, { dateStyle: "medium", timeStyle: "medium" }) || "—"}
{formatVietnamDateTime(detail.timestamp, { dateStyle: "medium", timeStyle: "short" }) || "—"}
</td>
<td className="max-w-[260px] truncate p-4 font-mono text-sm text-text-main">
{detail.model}
@@ -359,7 +359,7 @@ export default function RequestDetailsTab() {
</div>
<div>
<span className="text-text-muted">Timestamp:</span>{" "}
<span className="text-text-main">{formatVietnamDateTime(selectedDetail.timestamp, { dateStyle: "medium", timeStyle: "medium" }) || "—"}</span>
<span className="text-text-main">{formatVietnamDateTime(selectedDetail.timestamp, { dateStyle: "medium", timeStyle: "short" }) || "—"}</span>
</div>
<div>
<span className="text-text-muted">Provider:</span>{" "}
+2 -8
View File
@@ -4,7 +4,7 @@ import { applyOutboundProxyEnv } from "@/lib/network/outboundProxy";
import { resetComboRotation } from "open-sse/services/combo.js";
import { runQuotaAutoPingTick } from "@/shared/services/quotaAutoPing";
import { requireCurrentDashboardUser, requireUsageDashboardUser } from "@/lib/auth/currentUser";
import { updateUser, verifyUserPassword } from "@/lib/db";
import { updateUser } from "@/lib/db";
export const dynamic = "force-dynamic";
export const revalidate = 0;
@@ -115,7 +115,7 @@ export async function PATCH(request) {
// Strip protected secrets before any internal handling sets them
for (const key of PROTECTED_SETTING_KEYS) delete body[key];
// If updating password, hash it
// An authenticated dashboard session is sufficient to change its own password.
if (body.newPassword) {
let user;
try {
@@ -124,12 +124,6 @@ export async function PATCH(request) {
return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
}
if (!body.currentPassword) {
return NextResponse.json({ error: "Current password required" }, { status: 400 });
}
if (!(await verifyUserPassword(user.id, body.currentPassword))) {
return NextResponse.json({ error: "Invalid current password" }, { status: 401 });
}
await updateUser(user.id, { password: body.newPassword });
delete body.newPassword;
delete body.currentPassword;
-1
View File
@@ -1002,7 +1002,6 @@ function formatLogDate(date = new Date()) {
year: "numeric",
hour: "2-digit",
minute: "2-digit",
second: "2-digit",
hourCycle: "h23",
});
}
+1 -1
View File
@@ -43,7 +43,7 @@ export default function RequestLogger() {
<h2 className="text-xl font-semibold">Request Logs</h2>
<div className="flex items-center gap-2">
<label className="text-sm font-medium text-text-muted flex items-center gap-2 cursor-pointer">
<span>Auto Refresh (3s)</span>
<span>Auto Refresh</span>
<div
onClick={() => setAutoRefresh(!autoRefresh)}
className={`relative inline-flex h-5 w-9 items-center rounded-full transition-colors focus:outline-none ${autoRefresh ? "bg-primary" : "bg-bg-subtle border border-border"
+3 -3
View File
@@ -13,18 +13,18 @@ import UsageChart from "@/app/(dashboard)/dashboard/usage/components/UsageChart"
function timeAgo(timestamp) {
const diff = Math.floor((Date.now() - new Date(timestamp)) / 1000);
if (diff < 60) return `${diff}s ago`;
if (diff < 60) return "Just now";
if (diff < 3600) return `${Math.floor(diff / 60)}m ago`;
if (diff < 86400) return `${Math.floor(diff / 3600)}h ago`;
return `${Math.floor(diff / 86400)}d ago`;
}
// Auto-update time display every second without re-rendering parent
// Keep relative time current without exposing second-level precision.
function TimeAgo({ timestamp }) {
const [, setTick] = useState(0);
useEffect(() => {
const timer = setInterval(() => setTick(t => t + 1), 1000);
const timer = setInterval(() => setTick(t => t + 1), 60000);
return () => clearInterval(timer);
}, []);