mirror of
https://github.com/freedbygrace/DynamoDNS.git
synced 2026-08-08 17:23:24 +00:00
Enhance API token management by adding custom expiration date/time selection.
Replit-Commit-Author: Agent Replit-Commit-Session-Id: 9111ef36-26c8-4085-84ca-a35dc1fec1b5 Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/7083d608-d6d3-4a6a-9a27-6286c5109627/cb03c6a4-753d-4c14-9c5d-1ddb6ed4807f.jpg
This commit is contained in:
+139
-22
@@ -6,7 +6,8 @@ import { useAuth } from "@/hooks/use-auth";
|
||||
import { useOrganization } from "@/context/organization-context";
|
||||
import { apiRequest, queryClient } from "@/lib/queryClient";
|
||||
import { useToast } from "@/hooks/use-toast";
|
||||
import { useForm } from "react-hook-form";
|
||||
import { useForm, useWatch } from "react-hook-form";
|
||||
import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover";
|
||||
import { zodResolver } from "@hookform/resolvers/zod";
|
||||
import { z } from "zod";
|
||||
import {
|
||||
@@ -61,6 +62,7 @@ import { Button } from "@/components/ui/button";
|
||||
import { Input } from "@/components/ui/input";
|
||||
import { Badge } from "@/components/ui/badge";
|
||||
import { Checkbox } from "@/components/ui/checkbox";
|
||||
import { Calendar } from "@/components/ui/calendar";
|
||||
import {
|
||||
Select,
|
||||
SelectContent,
|
||||
@@ -68,7 +70,7 @@ import {
|
||||
SelectTrigger,
|
||||
SelectValue,
|
||||
} from "@/components/ui/select";
|
||||
import { Loader2, Key, MoreVertical, Calendar, Copy, Info } from "lucide-react";
|
||||
import { Loader2, Key, MoreVertical, CalendarIcon, Copy, Info, Clock } from "lucide-react";
|
||||
import { formatDistanceToNow, format } from "date-fns";
|
||||
|
||||
// Token form schema
|
||||
@@ -126,25 +128,44 @@ export default function ApiTokensPage() {
|
||||
if (data.expiresIn && data.expiresIn !== 'never') {
|
||||
const now = new Date();
|
||||
|
||||
switch (data.expiresIn) {
|
||||
case '1hour':
|
||||
tokenData.expiresAt = new Date(now.getTime() + 60 * 60 * 1000);
|
||||
break;
|
||||
case '1day':
|
||||
tokenData.expiresAt = new Date(now.getTime() + 24 * 60 * 60 * 1000);
|
||||
break;
|
||||
case '7days':
|
||||
tokenData.expiresAt = new Date(now.getTime() + 7 * 24 * 60 * 60 * 1000);
|
||||
break;
|
||||
case '30days':
|
||||
tokenData.expiresAt = new Date(now.getTime() + 30 * 24 * 60 * 60 * 1000);
|
||||
break;
|
||||
case '90days':
|
||||
tokenData.expiresAt = new Date(now.getTime() + 90 * 24 * 60 * 60 * 1000);
|
||||
break;
|
||||
case '1year':
|
||||
tokenData.expiresAt = new Date(now.getTime() + 365 * 24 * 60 * 60 * 1000);
|
||||
break;
|
||||
if (data.expiresIn === 'custom' && data.customDate) {
|
||||
// For custom date/time
|
||||
if (data.customDate) {
|
||||
const customDate = new Date(data.customDate);
|
||||
|
||||
// If time was selected, add it to the date
|
||||
if (data.customTime) {
|
||||
const [hours, minutes] = data.customTime.split(':').map(Number);
|
||||
customDate.setHours(hours, minutes, 0, 0);
|
||||
} else {
|
||||
// Default to end of day if no time selected
|
||||
customDate.setHours(23, 59, 59, 999);
|
||||
}
|
||||
|
||||
tokenData.expiresAt = customDate;
|
||||
}
|
||||
} else {
|
||||
// For preset expiration options
|
||||
switch (data.expiresIn) {
|
||||
case '1hour':
|
||||
tokenData.expiresAt = new Date(now.getTime() + 60 * 60 * 1000);
|
||||
break;
|
||||
case '1day':
|
||||
tokenData.expiresAt = new Date(now.getTime() + 24 * 60 * 60 * 1000);
|
||||
break;
|
||||
case '7days':
|
||||
tokenData.expiresAt = new Date(now.getTime() + 7 * 24 * 60 * 60 * 1000);
|
||||
break;
|
||||
case '30days':
|
||||
tokenData.expiresAt = new Date(now.getTime() + 30 * 24 * 60 * 60 * 1000);
|
||||
break;
|
||||
case '90days':
|
||||
tokenData.expiresAt = new Date(now.getTime() + 90 * 24 * 60 * 60 * 1000);
|
||||
break;
|
||||
case '1year':
|
||||
tokenData.expiresAt = new Date(now.getTime() + 365 * 24 * 60 * 60 * 1000);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -281,7 +302,7 @@ export default function ApiTokensPage() {
|
||||
<TableCell>
|
||||
{token.expiresAt ? (
|
||||
<div className="flex items-center">
|
||||
<Calendar className="mr-1 h-3 w-3 text-muted-foreground" />
|
||||
<CalendarIcon className="mr-1 h-3 w-3 text-muted-foreground" />
|
||||
<span
|
||||
className="text-sm"
|
||||
title={format(new Date(token.expiresAt), 'PPpp')}
|
||||
@@ -435,6 +456,7 @@ export default function ApiTokensPage() {
|
||||
<SelectItem value="30days">30 days</SelectItem>
|
||||
<SelectItem value="90days">90 days</SelectItem>
|
||||
<SelectItem value="1year">1 year</SelectItem>
|
||||
<SelectItem value="custom">Custom date/time</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
<FormDescription>
|
||||
@@ -445,6 +467,101 @@ export default function ApiTokensPage() {
|
||||
)}
|
||||
/>
|
||||
|
||||
{/* Custom date and time fields - show only when custom expiration is selected */}
|
||||
{form.watch("expiresIn") === "custom" && (
|
||||
<div className="space-y-4">
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="customDate"
|
||||
render={({ field }) => (
|
||||
<FormItem className="flex flex-col">
|
||||
<FormLabel>Custom Date</FormLabel>
|
||||
<Popover>
|
||||
<PopoverTrigger asChild>
|
||||
<FormControl>
|
||||
<Button
|
||||
variant={"outline"}
|
||||
className={`w-full pl-3 text-left font-normal ${!field.value && "text-muted-foreground"}`}
|
||||
>
|
||||
{field.value ? (
|
||||
format(field.value, "PPP")
|
||||
) : (
|
||||
<span>Pick a date</span>
|
||||
)}
|
||||
<CalendarIcon className="ml-auto h-4 w-4 opacity-50" />
|
||||
</Button>
|
||||
</FormControl>
|
||||
</PopoverTrigger>
|
||||
<PopoverContent className="w-auto p-0" align="start">
|
||||
<Calendar
|
||||
mode="single"
|
||||
selected={field.value}
|
||||
onSelect={field.onChange}
|
||||
disabled={(date) => date < new Date()}
|
||||
initialFocus
|
||||
/>
|
||||
</PopoverContent>
|
||||
</Popover>
|
||||
<FormDescription>
|
||||
The date when the token will expire
|
||||
</FormDescription>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="customTime"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>Custom Time</FormLabel>
|
||||
<Select
|
||||
onValueChange={field.onChange}
|
||||
defaultValue={field.value}
|
||||
>
|
||||
<FormControl>
|
||||
<SelectTrigger>
|
||||
<SelectValue placeholder="Select a time" />
|
||||
</SelectTrigger>
|
||||
</FormControl>
|
||||
<SelectContent>
|
||||
<SelectItem value="00:00">12:00 AM</SelectItem>
|
||||
<SelectItem value="01:00">1:00 AM</SelectItem>
|
||||
<SelectItem value="02:00">2:00 AM</SelectItem>
|
||||
<SelectItem value="03:00">3:00 AM</SelectItem>
|
||||
<SelectItem value="04:00">4:00 AM</SelectItem>
|
||||
<SelectItem value="05:00">5:00 AM</SelectItem>
|
||||
<SelectItem value="06:00">6:00 AM</SelectItem>
|
||||
<SelectItem value="07:00">7:00 AM</SelectItem>
|
||||
<SelectItem value="08:00">8:00 AM</SelectItem>
|
||||
<SelectItem value="09:00">9:00 AM</SelectItem>
|
||||
<SelectItem value="10:00">10:00 AM</SelectItem>
|
||||
<SelectItem value="11:00">11:00 AM</SelectItem>
|
||||
<SelectItem value="12:00">12:00 PM</SelectItem>
|
||||
<SelectItem value="13:00">1:00 PM</SelectItem>
|
||||
<SelectItem value="14:00">2:00 PM</SelectItem>
|
||||
<SelectItem value="15:00">3:00 PM</SelectItem>
|
||||
<SelectItem value="16:00">4:00 PM</SelectItem>
|
||||
<SelectItem value="17:00">5:00 PM</SelectItem>
|
||||
<SelectItem value="18:00">6:00 PM</SelectItem>
|
||||
<SelectItem value="19:00">7:00 PM</SelectItem>
|
||||
<SelectItem value="20:00">8:00 PM</SelectItem>
|
||||
<SelectItem value="21:00">9:00 PM</SelectItem>
|
||||
<SelectItem value="22:00">10:00 PM</SelectItem>
|
||||
<SelectItem value="23:00">11:00 PM</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
<FormDescription>
|
||||
The time when the token will expire
|
||||
</FormDescription>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<DialogFooter>
|
||||
<Button
|
||||
type="submit"
|
||||
|
||||
Reference in New Issue
Block a user