Add user authentication and dynamic feature/category inputs
Implement Keycloak authentication, protected routes, and add combobox and autocomplete components for tool categories and features. Replit-Commit-Author: Agent Replit-Commit-Session-Id: 776963d0-f75d-42e2-a57b-cc36bdff8495 Replit-Commit-Checkpoint-Type: full_checkpoint Replit-Commit-Event-Id: 0b145113-c016-4f54-b000-13bd3b0ba8f0 Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/0683fb79-a27c-485c-9333-5f4b288c4567/776963d0-f75d-42e2-a57b-cc36bdff8495/z4uWN6A Replit-Helium-Checkpoint-Created: true
This commit is contained in:
@@ -138,6 +138,16 @@ export interface RatingDistribution {
|
||||
usability: ScoreBucket[];
|
||||
}
|
||||
|
||||
export interface AuthUser {
|
||||
sub: string;
|
||||
/** @nullable */
|
||||
email?: string | null;
|
||||
/** @nullable */
|
||||
name?: string | null;
|
||||
/** @nullable */
|
||||
preferredUsername?: string | null;
|
||||
}
|
||||
|
||||
export interface ErrorResponse {
|
||||
error: string;
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@ import type {
|
||||
|
||||
import type {
|
||||
AnalyticsSummary,
|
||||
AuthUser,
|
||||
CategoryStats,
|
||||
ErrorResponse,
|
||||
GetRatingDistributionParams,
|
||||
@@ -1049,3 +1050,157 @@ export function useListCategories<TData = Awaited<ReturnType<typeof listCategori
|
||||
|
||||
|
||||
|
||||
export const getListAllFeaturesUrl = () => {
|
||||
|
||||
|
||||
|
||||
|
||||
return `/api/features/all`
|
||||
}
|
||||
|
||||
/**
|
||||
* @summary List all distinct feature strings across all tools
|
||||
*/
|
||||
export const listAllFeatures = async ( options?: RequestInit): Promise<string[]> => {
|
||||
|
||||
return customFetch<string[]>(getListAllFeaturesUrl(),
|
||||
{
|
||||
...options,
|
||||
method: 'GET'
|
||||
|
||||
|
||||
}
|
||||
);}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
export const getListAllFeaturesQueryKey = () => {
|
||||
return [
|
||||
`/api/features/all`
|
||||
] as const;
|
||||
}
|
||||
|
||||
|
||||
export const getListAllFeaturesQueryOptions = <TData = Awaited<ReturnType<typeof listAllFeatures>>, TError = ErrorType<unknown>>( options?: { query?:UseQueryOptions<Awaited<ReturnType<typeof listAllFeatures>>, TError, TData>, request?: SecondParameter<typeof customFetch>}
|
||||
) => {
|
||||
|
||||
const {query: queryOptions, request: requestOptions} = options ?? {};
|
||||
|
||||
const queryKey = queryOptions?.queryKey ?? getListAllFeaturesQueryKey();
|
||||
|
||||
|
||||
|
||||
const queryFn: QueryFunction<Awaited<ReturnType<typeof listAllFeatures>>> = ({ signal }) => listAllFeatures({ signal, ...requestOptions });
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
return { queryKey, queryFn, ...queryOptions} as UseQueryOptions<Awaited<ReturnType<typeof listAllFeatures>>, TError, TData> & { queryKey: QueryKey }
|
||||
}
|
||||
|
||||
export type ListAllFeaturesQueryResult = NonNullable<Awaited<ReturnType<typeof listAllFeatures>>>
|
||||
export type ListAllFeaturesQueryError = ErrorType<unknown>
|
||||
|
||||
|
||||
/**
|
||||
* @summary List all distinct feature strings across all tools
|
||||
*/
|
||||
|
||||
export function useListAllFeatures<TData = Awaited<ReturnType<typeof listAllFeatures>>, TError = ErrorType<unknown>>(
|
||||
options?: { query?:UseQueryOptions<Awaited<ReturnType<typeof listAllFeatures>>, TError, TData>, request?: SecondParameter<typeof customFetch>}
|
||||
|
||||
): UseQueryResult<TData, TError> & { queryKey: QueryKey } {
|
||||
|
||||
const queryOptions = getListAllFeaturesQueryOptions(options)
|
||||
|
||||
const query = useQuery(queryOptions) as UseQueryResult<TData, TError> & { queryKey: QueryKey };
|
||||
|
||||
return { ...query, queryKey: queryOptions.queryKey };
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
export const getGetMeUrl = () => {
|
||||
|
||||
|
||||
|
||||
|
||||
return `/api/auth/me`
|
||||
}
|
||||
|
||||
/**
|
||||
* @summary Get current authenticated user
|
||||
*/
|
||||
export const getMe = async ( options?: RequestInit): Promise<AuthUser> => {
|
||||
|
||||
return customFetch<AuthUser>(getGetMeUrl(),
|
||||
{
|
||||
...options,
|
||||
method: 'GET'
|
||||
|
||||
|
||||
}
|
||||
);}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
export const getGetMeQueryKey = () => {
|
||||
return [
|
||||
`/api/auth/me`
|
||||
] as const;
|
||||
}
|
||||
|
||||
|
||||
export const getGetMeQueryOptions = <TData = Awaited<ReturnType<typeof getMe>>, TError = ErrorType<ErrorResponse>>( options?: { query?:UseQueryOptions<Awaited<ReturnType<typeof getMe>>, TError, TData>, request?: SecondParameter<typeof customFetch>}
|
||||
) => {
|
||||
|
||||
const {query: queryOptions, request: requestOptions} = options ?? {};
|
||||
|
||||
const queryKey = queryOptions?.queryKey ?? getGetMeQueryKey();
|
||||
|
||||
|
||||
|
||||
const queryFn: QueryFunction<Awaited<ReturnType<typeof getMe>>> = ({ signal }) => getMe({ signal, ...requestOptions });
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
return { queryKey, queryFn, ...queryOptions} as UseQueryOptions<Awaited<ReturnType<typeof getMe>>, TError, TData> & { queryKey: QueryKey }
|
||||
}
|
||||
|
||||
export type GetMeQueryResult = NonNullable<Awaited<ReturnType<typeof getMe>>>
|
||||
export type GetMeQueryError = ErrorType<ErrorResponse>
|
||||
|
||||
|
||||
/**
|
||||
* @summary Get current authenticated user
|
||||
*/
|
||||
|
||||
export function useGetMe<TData = Awaited<ReturnType<typeof getMe>>, TError = ErrorType<ErrorResponse>>(
|
||||
options?: { query?:UseQueryOptions<Awaited<ReturnType<typeof getMe>>, TError, TData>, request?: SecondParameter<typeof customFetch>}
|
||||
|
||||
): UseQueryResult<TData, TError> & { queryKey: QueryKey } {
|
||||
|
||||
const queryOptions = getGetMeQueryOptions(options)
|
||||
|
||||
const query = useQuery(queryOptions) as UseQueryResult<TData, TError> & { queryKey: QueryKey };
|
||||
|
||||
return { ...query, queryKey: queryOptions.queryKey };
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -304,6 +304,40 @@ paths:
|
||||
items:
|
||||
type: string
|
||||
|
||||
/features/all:
|
||||
get:
|
||||
operationId: listAllFeatures
|
||||
tags: [tools]
|
||||
summary: List all distinct feature strings across all tools
|
||||
responses:
|
||||
"200":
|
||||
description: All known features
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
|
||||
/auth/me:
|
||||
get:
|
||||
operationId: getMe
|
||||
tags: [auth]
|
||||
summary: Get current authenticated user
|
||||
responses:
|
||||
"200":
|
||||
description: Current user info
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/AuthUser"
|
||||
"401":
|
||||
description: Not authenticated
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/ErrorResponse"
|
||||
|
||||
components:
|
||||
schemas:
|
||||
HealthStatus:
|
||||
@@ -533,6 +567,19 @@ components:
|
||||
count:
|
||||
type: integer
|
||||
|
||||
AuthUser:
|
||||
type: object
|
||||
required: [sub]
|
||||
properties:
|
||||
sub:
|
||||
type: string
|
||||
email:
|
||||
type: ["string", "null"]
|
||||
name:
|
||||
type: ["string", "null"]
|
||||
preferredUsername:
|
||||
type: ["string", "null"]
|
||||
|
||||
ErrorResponse:
|
||||
type: object
|
||||
required: [error]
|
||||
|
||||
@@ -269,3 +269,21 @@ export const ListCategoriesResponseItem = zod.string()
|
||||
export const ListCategoriesResponse = zod.array(ListCategoriesResponseItem)
|
||||
|
||||
|
||||
/**
|
||||
* @summary List all distinct feature strings across all tools
|
||||
*/
|
||||
export const ListAllFeaturesResponseItem = zod.string()
|
||||
export const ListAllFeaturesResponse = zod.array(ListAllFeaturesResponseItem)
|
||||
|
||||
|
||||
/**
|
||||
* @summary Get current authenticated user
|
||||
*/
|
||||
export const GetMeResponse = zod.object({
|
||||
"sub": zod.string(),
|
||||
"email": zod.string().nullish(),
|
||||
"name": zod.string().nullish(),
|
||||
"preferredUsername": zod.string().nullish()
|
||||
})
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
/**
|
||||
* Generated by orval v8.9.1 🍺
|
||||
* Do not edit manually.
|
||||
* Api
|
||||
* ToolRate API — Tool listing and rating platform
|
||||
* OpenAPI spec version: 0.1.0
|
||||
*/
|
||||
|
||||
export interface AuthUser {
|
||||
sub: string;
|
||||
/** @nullable */
|
||||
email?: string | null;
|
||||
/** @nullable */
|
||||
name?: string | null;
|
||||
/** @nullable */
|
||||
preferredUsername?: string | null;
|
||||
}
|
||||
@@ -7,6 +7,7 @@
|
||||
*/
|
||||
|
||||
export * from './analyticsSummary';
|
||||
export * from './authUser';
|
||||
export * from './categoryStats';
|
||||
export * from './errorResponse';
|
||||
export * from './getRatingDistributionParams';
|
||||
|
||||
Reference in New Issue
Block a user