Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions .github/workflows/go.yml
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ jobs:
- name: Set up Go (API)
uses: actions/setup-go@7b8cf10d4e4a01d4992d18a89f4d7dc5a3e6d6f4 # v4
with:
go-version: "1.25.7"
go-version: "1.25.8"
- name: Build API
run: cd api/; go mod vendor; make build
- name: Test API
Expand All @@ -129,7 +129,7 @@ jobs:
- name: Set up Go (Libs)
uses: actions/setup-go@7b8cf10d4e4a01d4992d18a89f4d7dc5a3e6d6f4 # v4
with:
go-version: "1.25.7"
go-version: "1.25.8"
- name: Test Libs
run: cd libs/; go mod vendor; make test
- name: golangci-lint - Libs (non-blocking)
Expand All @@ -152,7 +152,7 @@ jobs:
- name: Set up Go (Proxy)
uses: actions/setup-go@7b8cf10d4e4a01d4992d18a89f4d7dc5a3e6d6f4 # v4
with:
go-version: "1.25.7"
go-version: "1.25.8"
- name: Build Proxy
run: cd proxy/; go mod vendor; make build
- name: Test Proxy
Expand All @@ -177,7 +177,7 @@ jobs:
- name: Set up Go (Blocklists)
uses: actions/setup-go@7b8cf10d4e4a01d4992d18a89f4d7dc5a3e6d6f4 # v4
with:
go-version: "1.25.7"
go-version: "1.25.8"
- name: Build Blocklists
run: cd blocklists/; go mod vendor; make build
- name: Test Blocklists
Expand All @@ -202,7 +202,7 @@ jobs:
- name: Set up Go (DNSCheck)
uses: actions/setup-go@7b8cf10d4e4a01d4992d18a89f4d7dc5a3e6d6f4 # v4
with:
go-version: "1.25.7"
go-version: "1.25.8"
- name: Build DNSCheck
run: cd dnscheck/; go mod vendor; make build
- name: golangci-lint - DNSCheck (non-blocking)
Expand Down
2 changes: 1 addition & 1 deletion api/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# NOTE: The image should be built from the root of the project (see Makefile)
FROM golang:1.25.7 AS build
FROM golang:1.25.8 AS build

WORKDIR /app

Expand Down
2 changes: 1 addition & 1 deletion api/Dockerfile.dev
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM golang:1.25.7
FROM golang:1.25.8

RUN apt update; apt install -y make

Expand Down
2 changes: 1 addition & 1 deletion api/go.mod
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
module github.com/ivpn/dns/api

go 1.25.7
go 1.25.8

require (
github.com/AfterShip/email-verifier v1.4.0
Expand Down
3 changes: 2 additions & 1 deletion app/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
import MobileconfigPage from '@/pages/mobileconfig/MobileconfigPage';
import MobileconfigDownload from '@/pages/mobileconfig/MobileconfigDownload';
import HomeScreen from './pages/home/HomeScreen';
import { createBrowserRouter, RouterProvider, Navigate, Outlet, useLoaderData, useLocation, useNavigate, redirect } from 'react-router-dom';
import { createBrowserRouter, RouterProvider, Navigate, Outlet, useLoaderData, useLocation, useNavigate, redirect, ScrollRestoration } from 'react-router-dom';
import { ThemeProvider } from "@/components/theme-provider"
import api from "@/api/api";
import type { ModelAccount, ModelProfile } from "@/api/client/api";
Expand Down Expand Up @@ -177,13 +177,13 @@
account,
profiles,
};
} catch (error: any) {

Check failure on line 180 in app/src/App.tsx

View workflow job for this annotation

GitHub Actions / frontend

Unexpected any. Specify a different type




if (error instanceof Response) throw error;
const status = error?.response?.status ?? error?.status ?? (error instanceof Error && (error as any).status);

Check failure on line 186 in app/src/App.tsx

View workflow job for this annotation

GitHub Actions / frontend

Unexpected any. Specify a different type
if (status === 401 || status === 404) {
// Dispatch a unified session expired event; AuthProvider subscriber performs cleanup + toast
if (typeof window !== 'undefined') {
Expand Down Expand Up @@ -229,9 +229,9 @@
account: null,
profiles,
};
} catch (error: any) {

Check failure on line 232 in app/src/App.tsx

View workflow job for this annotation

GitHub Actions / frontend

Unexpected any. Specify a different type
if (error instanceof Response) throw error;
const status = error?.response?.status ?? error?.status ?? (error instanceof Error && (error as any).status);

Check failure on line 234 in app/src/App.tsx

View workflow job for this annotation

GitHub Actions / frontend

Unexpected any. Specify a different type
if (status === 401 || status === 404) {
if (typeof window !== 'undefined') {
dispatch({ type: 'auth/sessionExpired' });
Expand Down Expand Up @@ -491,6 +491,7 @@
function AppWithEventHandler() {
return (
<>
<ScrollRestoration />
<Toaster />
<AuthProvider>
<NavigationCollapseProvider>
Expand Down Expand Up @@ -568,4 +569,4 @@


export default App;
export { useAuth, AuthContext, RootIndexRedirect };

Check warning on line 572 in app/src/App.tsx

View workflow job for this annotation

GitHub Actions / frontend

Fast refresh only works when a file only exports components. Use a new file to share constants or functions between components
75 changes: 3 additions & 72 deletions app/src/pages/account_preferences/Account.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,13 @@ import {
TrashIcon,
} from "lucide-react";
import type { JSX } from "react";
import { useState, useEffect } from "react";
import { useState } from "react";
import { useLocation } from 'react-router-dom';
import { Button } from "@/components/ui/button";
import StatusBadge from "@/components/general/StatusBadge";
import { Card, CardContent } from "@/components/ui/card";
import AccountInfoCard from "@/pages/account_preferences/AccountInfoCard";
import type { ModelAccount, ModelSubscription, ModelSubscriptionType } from "@/api/client/api";
import type { ModelAccount } from "@/api/client/api";
import api from "@/api/api";
import ToggleGroup from "@/components/general/ToggleGroup";
import { toast } from "sonner"
Expand Down Expand Up @@ -120,59 +120,7 @@ const PreferencesSection = ({ account }: PreferencesSectionProps): JSX.Element =
}
};

// Subscription state
const [subscription, setSubscription] = useState<ModelSubscription | null>(null);
const [subscriptionLoading, setSubscriptionLoading] = useState(false);
const [subscriptionError, setSubscriptionError] = useState<string | null>(null);

// Fetch subscription info once on mount (requires auth cookie)
useEffect(() => {
let cancelled = false;
const fetchSubscription = async () => {
setSubscriptionLoading(true);
setSubscriptionError(null);
try {
const resp = await api.Client.subscriptionApi.apiV1SubGet();
if (!cancelled) {
setSubscription(resp.data);
}
} catch (err: unknown) {
// 404 means no subscription yet; treat silently
let notFound = false;
if (typeof err === 'object' && err !== null && 'response' in err) {
const response = (err as { response?: { status?: number } }).response;
if (response?.status === 404) {
notFound = true;
}
}
if (notFound) {
if (!cancelled) setSubscription(null);
} else if (!cancelled) {
setSubscriptionError('Failed to load subscription');
}
} finally {
if (!cancelled) setSubscriptionLoading(false);
}
};
fetchSubscription();
return () => { cancelled = true; };
}, []);

const formatDate = (iso?: string) => {
if (!iso) return '—';
try {
const d = new Date(iso);
if (isNaN(d.getTime())) return iso;
return d.toLocaleDateString();
} catch { return iso; }
};

const normalizeType = (t?: ModelSubscriptionType) => {
if (!t) return '—';
return String(t).charAt(0).toUpperCase() + String(t).slice(1);
};

// Account info data (Member since removed; Active until + Subscription type added)
// Account info data
const accountInfo = [
{ label: "modDNS ID", value: currentAccount?.email || "" },
{
Expand All @@ -193,23 +141,6 @@ const PreferencesSection = ({ account }: PreferencesSectionProps): JSX.Element =
? <ShieldCheck className="w-4 h-4 text-[var(--tailwind-colors-rdns-600)]" />
: <ShieldX className="w-4 h-4 text-[var(--tailwind-colors-red-600)]" />,
},
{
label: "Active until",
value: subscriptionLoading
? 'Loading…'
: subscriptionError
? subscriptionError
: formatDate(subscription?.active_until),
},
// TODO: Uncomment when subscription types are supported
// {
// label: "Subscription type",
// value: subscriptionLoading
// ? 'Loading…'
// : subscriptionError
// ? '—'
// : normalizeType(subscription?.type),
// },
];

// Section data
Expand Down
Loading
Loading