forked from github-starred/komodo
onboarding key expiry view
This commit is contained in:
@@ -1,3 +1,5 @@
|
||||
use std::cmp::Ordering;
|
||||
|
||||
use anyhow::{Context, anyhow};
|
||||
use database::mungos::find::find_collect;
|
||||
use komodo_client::api::read::{
|
||||
@@ -22,9 +24,28 @@ impl Resolve<ReadArgs> for ListOnboardingKeys {
|
||||
.status_code(StatusCode::FORBIDDEN),
|
||||
);
|
||||
}
|
||||
find_collect(&db_client().onboarding_keys, None, None)
|
||||
.await
|
||||
.context("Failed to query database for Server onboarding keys")
|
||||
.map_err(Into::into)
|
||||
|
||||
let mut keys =
|
||||
find_collect(&db_client().onboarding_keys, None, None)
|
||||
.await
|
||||
.context(
|
||||
"Failed to query database for Server onboarding keys",
|
||||
)?;
|
||||
|
||||
// No expiry keys first, followed
|
||||
keys.sort_by(|a, b| {
|
||||
if a.expires == b.expires {
|
||||
Ordering::Equal
|
||||
} else if a.expires == 0 {
|
||||
Ordering::Less
|
||||
} else if b.expires == 0 {
|
||||
Ordering::Greater
|
||||
} else {
|
||||
// Descending
|
||||
b.expires.cmp(&a.expires)
|
||||
}
|
||||
});
|
||||
|
||||
Ok(keys)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ use komodo_client::{
|
||||
api::write::{CreateBuilder, CreateServer, UpdateResourceMeta},
|
||||
entities::{
|
||||
builder::{PartialBuilderConfig, PartialServerBuilderConfig},
|
||||
komodo_timestamp,
|
||||
onboarding_key::OnboardingKey,
|
||||
server::{PartialServerConfig, Server},
|
||||
user::system_user,
|
||||
@@ -344,10 +345,14 @@ impl PublicKeyValidator for CreationKeyValidator {
|
||||
.await
|
||||
.context("Failed to query database for Server onboarding keys")?
|
||||
.context("Matching Server onboarding key not found")?;
|
||||
if onboarding_key.enabled {
|
||||
// Check enabled and not expired.
|
||||
if onboarding_key.enabled
|
||||
&& (onboarding_key.expires == 0
|
||||
|| onboarding_key.expires > komodo_timestamp())
|
||||
{
|
||||
Ok(onboarding_key)
|
||||
} else {
|
||||
Err(anyhow!("Onboarding key is disabled"))
|
||||
Err(anyhow!("Onboarding key is invalid"))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,6 +25,11 @@ pub struct OnboardingKey {
|
||||
#[serde(default)]
|
||||
pub enabled: bool,
|
||||
|
||||
/// Expiry of key, or 0 if never expires
|
||||
#[serde(default)]
|
||||
#[cfg_attr(feature = "mongo", index)]
|
||||
pub expires: I64,
|
||||
|
||||
/// Name associated with the api key for management
|
||||
#[serde(default)]
|
||||
pub name: String,
|
||||
@@ -37,10 +42,6 @@ pub struct OnboardingKey {
|
||||
#[serde(default)]
|
||||
pub created_at: I64,
|
||||
|
||||
/// Expiry of key, or 0 if never expires
|
||||
#[serde(default)]
|
||||
pub expires: I64,
|
||||
|
||||
/// Default tags to give to Servers created with this key.
|
||||
#[serde(default)]
|
||||
pub tags: Vec<String>,
|
||||
|
||||
@@ -1159,14 +1159,14 @@ export interface OnboardingKey {
|
||||
public_key: string;
|
||||
/** Disable the onboarding key when not in use. */
|
||||
enabled?: boolean;
|
||||
/** Expiry of key, or 0 if never expires */
|
||||
expires?: I64;
|
||||
/** Name associated with the api key for management */
|
||||
name?: string;
|
||||
/** The [Server](crate::entities::server::Server) ids onboarded by this Creation Key */
|
||||
onboarded?: string[];
|
||||
/** Timestamp of key creation */
|
||||
created_at?: I64;
|
||||
/** Expiry of key, or 0 if never expires */
|
||||
expires?: I64;
|
||||
/** Default tags to give to Servers created with this key. */
|
||||
tags?: string[];
|
||||
/**
|
||||
|
||||
4
frontend/public/client/types.d.ts
vendored
4
frontend/public/client/types.d.ts
vendored
@@ -1283,14 +1283,14 @@ export interface OnboardingKey {
|
||||
public_key: string;
|
||||
/** Disable the onboarding key when not in use. */
|
||||
enabled?: boolean;
|
||||
/** Expiry of key, or 0 if never expires */
|
||||
expires?: I64;
|
||||
/** Name associated with the api key for management */
|
||||
name?: string;
|
||||
/** The [Server](crate::entities::server::Server) ids onboarded by this Creation Key */
|
||||
onboarded?: string[];
|
||||
/** Timestamp of key creation */
|
||||
created_at?: I64;
|
||||
/** Expiry of key, or 0 if never expires */
|
||||
expires?: I64;
|
||||
/** Default tags to give to Servers created with this key. */
|
||||
tags?: string[];
|
||||
/**
|
||||
|
||||
@@ -27,6 +27,8 @@ import { fmt_date_with_minutes } from "@lib/formatting";
|
||||
import { Switch } from "@ui/switch";
|
||||
import { ResourceSelector, TagSelector } from "@components/resources/common";
|
||||
import { Types } from "komodo_client";
|
||||
import { ColumnDef } from "@tanstack/react-table";
|
||||
import { Badge } from "@ui/badge";
|
||||
|
||||
export const Onboarding = () => {
|
||||
useSetTitle("Onboarding");
|
||||
@@ -40,7 +42,11 @@ export const Onboarding = () => {
|
||||
toast({ title: "Updated onboarding key" });
|
||||
},
|
||||
});
|
||||
const columns = useMemo(
|
||||
const columns: (
|
||||
| ColumnDef<Types.OnboardingKey, unknown>
|
||||
| false
|
||||
| undefined
|
||||
)[] = useMemo(
|
||||
() => [
|
||||
{
|
||||
size: 150,
|
||||
@@ -81,7 +87,7 @@ export const Onboarding = () => {
|
||||
header: "Tags",
|
||||
cell: ({ row }) => (
|
||||
<TagSelector
|
||||
tags={row.original.tags}
|
||||
tags={row.original.tags!}
|
||||
set={(tags) =>
|
||||
mutate({ public_key: row.original.public_key, tags })
|
||||
}
|
||||
@@ -112,10 +118,19 @@ export const Onboarding = () => {
|
||||
header: ({ column }) => (
|
||||
<SortableHeader column={column} title="Expires" />
|
||||
),
|
||||
cell: ({ row }) =>
|
||||
row.original.expires
|
||||
? fmt_date_with_minutes(new Date(row.original.expires))
|
||||
: "Never",
|
||||
cell: ({
|
||||
row: {
|
||||
original: { expires },
|
||||
},
|
||||
}) => (
|
||||
<Badge
|
||||
variant={
|
||||
expires && expires <= Date.now() ? "destructive" : "secondary"
|
||||
}
|
||||
>
|
||||
{expires ? fmt_date_with_minutes(new Date(expires)) : "Never"}
|
||||
</Badge>
|
||||
),
|
||||
},
|
||||
{
|
||||
size: 100,
|
||||
@@ -123,12 +138,15 @@ export const Onboarding = () => {
|
||||
header: ({ column }) => (
|
||||
<SortableHeader column={column} title="Enabled" />
|
||||
),
|
||||
cell: ({ row }) => (
|
||||
cell: ({
|
||||
row: {
|
||||
original: { public_key, expires, enabled },
|
||||
},
|
||||
}) => (
|
||||
<Switch
|
||||
checked={row.original.enabled}
|
||||
onCheckedChange={(enabled) =>
|
||||
mutate({ public_key: row.original.public_key, enabled })
|
||||
}
|
||||
checked={expires && expires <= Date.now() ? false : enabled}
|
||||
onCheckedChange={(enabled) => mutate({ public_key, enabled })}
|
||||
disabled={!!expires && expires <= Date.now()}
|
||||
/>
|
||||
),
|
||||
},
|
||||
@@ -159,14 +177,14 @@ export const Onboarding = () => {
|
||||
|
||||
const ONE_DAY_MS = 1000 * 60 * 60 * 24;
|
||||
|
||||
type ExpiresOptions = "90 days" | "180 days" | "1 year" | "never";
|
||||
type ExpiresOptions = "1 day" | "7 days" | "30 days" | "never";
|
||||
|
||||
const CreateKey = () => {
|
||||
const { toast } = useToast();
|
||||
const [open, setOpen] = useState(false);
|
||||
const [name, setName] = useState("");
|
||||
const [privateKey, setPrivateKey] = useState("");
|
||||
const [expires, setExpires] = useState<ExpiresOptions>("never");
|
||||
const [expires, setExpires] = useState<ExpiresOptions>("1 day");
|
||||
const [submitted, setSubmitted] = useState<{ private_key: string }>();
|
||||
const invalidate = useInvalidate();
|
||||
const { mutate, isPending } = useWrite("CreateOnboardingKey", {
|
||||
@@ -178,9 +196,9 @@ const CreateKey = () => {
|
||||
});
|
||||
const now = Date.now();
|
||||
const expiresOptions: Record<ExpiresOptions, number> = {
|
||||
"90 days": now + ONE_DAY_MS * 90,
|
||||
"180 days": now + ONE_DAY_MS * 180,
|
||||
"1 year": now + ONE_DAY_MS * 365,
|
||||
"1 day": now + ONE_DAY_MS,
|
||||
"7 days": now + ONE_DAY_MS * 7,
|
||||
"30 days": now + ONE_DAY_MS * 90,
|
||||
never: 0,
|
||||
};
|
||||
const submit = () =>
|
||||
|
||||
Reference in New Issue
Block a user