feat(auth): password change (self + admin reset) with rate limiting; dedupe watchlist to user menu
Build & Push Docker Image / build (push) Successful in 2m19s

This commit is contained in:
opencode
2026-08-03 07:43:24 +02:00
parent 63f0bdbab6
commit 68a81ec775
20 changed files with 825 additions and 16 deletions
+44
View File
@@ -480,6 +480,28 @@ export const GetMeResponse = zod.object({
})
/**
* @summary Change own password (local users only)
*/
export const changeMyPasswordBodyNewPasswordMin = 8;
export const ChangeMyPasswordBody = zod.object({
"currentPassword": zod.string().min(1),
"newPassword": zod.string().min(changeMyPasswordBodyNewPasswordMin)
})
/**
* @summary Get redirect URL for managing credentials in the identity provider
*/
export const GetPasswordRedirectResponse = zod.object({
"url": zod.string().nullable()
})
/**
* @summary Get current user's browse preferences
*/
@@ -532,12 +554,15 @@ export const GetMeWatchlistResponse = zod.array(GetMeWatchlistResponseItem)
/**
* @summary List all local users (admin only)
*/
export const listUsersResponseAuthProviderDefault = `local`;
export const ListUsersResponseItem = zod.object({
"id": zod.number(),
"username": zod.string(),
"email": zod.string().nullish(),
"role": zod.enum(['admin', 'user']),
"tier": zod.enum(['free', 'premium', 'enterprise']).optional(),
"authProvider": zod.enum(['local', 'oidc']).default(listUsersResponseAuthProviderDefault),
"createdAt": zod.coerce.date()
})
export const ListUsersResponse = zod.array(ListUsersResponseItem)
@@ -573,12 +598,15 @@ export const UpdateUserBody = zod.object({
"tier": zod.enum(['free', 'premium', 'enterprise']).optional()
})
export const updateUserResponseAuthProviderDefault = `local`;
export const UpdateUserResponse = zod.object({
"id": zod.number(),
"username": zod.string(),
"email": zod.string().nullish(),
"role": zod.enum(['admin', 'user']),
"tier": zod.enum(['free', 'premium', 'enterprise']).optional(),
"authProvider": zod.enum(['local', 'oidc']).default(updateUserResponseAuthProviderDefault),
"createdAt": zod.coerce.date()
})
@@ -591,6 +619,22 @@ export const DeleteUserParams = zod.object({
})
/**
* @summary Set/reset a user's password (admin only, local users only)
*/
export const SetUserPasswordParams = zod.object({
"id": zod.coerce.number()
})
export const setUserPasswordBodyPasswordMin = 8;
export const SetUserPasswordBody = zod.object({
"password": zod.string().min(setUserPasswordBodyPasswordMin)
})
/**
* @summary List audit log entries (admin only)
*/
@@ -0,0 +1,14 @@
/**
* 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 ChangePasswordInput {
/** @minLength 1 */
currentPassword: string;
/** @minLength 8 */
newPassword: string;
}
+4
View File
@@ -14,6 +14,7 @@ export * from './authUser';
export * from './authUserRole';
export * from './authUserTier';
export * from './categoryStats';
export * from './changePasswordInput';
export * from './emptyTrash200';
export * from './errorResponse';
export * from './getRatingDistributionParams';
@@ -26,12 +27,14 @@ export * from './listToolsParams';
export * from './listToolsSort';
export * from './listTrashedToolsParams';
export * from './localLoginInput';
export * from './passwordRedirect';
export * from './rating';
export * from './ratingDistribution';
export * from './ratingHistoryItem';
export * from './ratingInput';
export * from './restoreTools200';
export * from './scoreBucket';
export * from './setPasswordInput';
export * from './tool';
export * from './toolInput';
export * from './toolUpdate';
@@ -40,6 +43,7 @@ export * from './topToolEntry';
export * from './trashTools200';
export * from './trashToolsInput';
export * from './user';
export * from './userAuthProvider';
export * from './userCreateInput';
export * from './userCreateInputRole';
export * from './userCreateInputTier';
@@ -0,0 +1,12 @@
/**
* 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 PasswordRedirect {
/** @nullable */
url: string | null;
}
@@ -0,0 +1,12 @@
/**
* 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 SetPasswordInput {
/** @minLength 8 */
password: string;
}
+2
View File
@@ -5,6 +5,7 @@
* ToolRate API — Tool listing and rating platform
* OpenAPI spec version: 0.1.0
*/
import type { UserAuthProvider } from './userAuthProvider';
import type { UserRole } from './userRole';
import type { UserTier } from './userTier';
@@ -15,5 +16,6 @@ export interface User {
email?: string | null;
role: UserRole;
tier?: UserTier;
authProvider?: UserAuthProvider;
createdAt: Date;
}
@@ -0,0 +1,15 @@
/**
* 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 type UserAuthProvider = typeof UserAuthProvider[keyof typeof UserAuthProvider];
export const UserAuthProvider = {
local: 'local',
oidc: 'oidc',
} as const;