Skip to content

Commit eb17e5b

Browse files
committed
chore: generateSecurePassword
1 parent 636ef3f commit eb17e5b

File tree

5 files changed

+74
-17
lines changed

5 files changed

+74
-17
lines changed

src/components/create-job/steps/deployment/ServiceDeployment.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,9 @@ function ServiceDeployment({ isEditingJob }: { isEditingJob?: boolean }) {
3939
<AppParametersSection />
4040
</SlateCard>
4141

42-
{containerOrWorkerType.inputs && <ServiceInputsSection inputs={containerOrWorkerType.inputs} />}
42+
{containerOrWorkerType.inputs && (
43+
<ServiceInputsSection inputs={containerOrWorkerType.inputs} isEditingJob={isEditingJob} />
44+
)}
4345

4446
{/* <SlateCard title="Other">
4547
<InputWithLabel name="deployment.serviceReplica" label="Service Replica" placeholder="0x_ai" isOptional />

src/components/draft/job-lists/ServiceDraftJobsList.tsx

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { ContainerOrWorkerType } from '@data/containerResources';
1+
import { Service } from '@data/containerResources';
22
import { DeploymentContextType, useDeploymentContext } from '@lib/contexts/deployment';
33
import { getContainerOrWorkerType, getContainerOrWorkerTypeDescription } from '@lib/deeploy-utils';
44
import { applyWidthClasses } from '@lib/utils';
@@ -32,10 +32,7 @@ export default function ServiceDraftJobsList({ jobs }: { jobs: ServiceDraftJob[]
3232
jobs={jobs}
3333
renderJob={(job) => {
3434
const serviceJob = job as ServiceDraftJob;
35-
const containerOrWorkerType: ContainerOrWorkerType = getContainerOrWorkerType(
36-
serviceJob.jobType,
37-
serviceJob.specifications,
38-
);
35+
const containerOrWorkerType: Service = getContainerOrWorkerType(serviceJob.jobType, serviceJob.specifications);
3936

4037
return (
4138
<>

src/components/project/job-lists/ServiceRunningJobsList.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { Service } from '@data/containerResources';
12
import { getContainerOrWorkerTypeDescription } from '@lib/deeploy-utils';
23
import { applyWidthClasses } from '@lib/utils';
34
import RunningJobsList from '@shared/jobs/projects/RunningJobsList';
@@ -34,6 +35,7 @@ function ServiceRunningJobsList({ jobs }: { jobs: RunningJobWithResources[] }) {
3435
}}
3536
renderJob={(job) => {
3637
const { containerOrWorkerType } = job.resources;
38+
const service: Service = containerOrWorkerType as Service;
3739
const targetNodes = Number(job.numberOfNodesRequested);
3840

3941
return (
@@ -46,7 +48,7 @@ function ServiceRunningJobsList({ jobs }: { jobs: RunningJobWithResources[] }) {
4648
</div>
4749

4850
<div className={widthClasses[2]}>
49-
<SmallTag variant={containerOrWorkerType.notesColor}>{containerOrWorkerType.dbSystem}</SmallTag>
51+
<SmallTag variant={service.notesColor}>{service.dbSystem}</SmallTag>
5052
</div>
5153

5254
<div className={widthClasses[3]}>

src/lib/utils.tsx

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,3 +100,35 @@ export const extractRepositoryPath = (url: string): string => {
100100
return url;
101101
}
102102
};
103+
104+
/**
105+
* Generates a random secure password with the specified length
106+
* @param length - The length of the password (default: 24)
107+
* @returns A secure password string
108+
*/
109+
function generateSecurePassword(length: number = 24): string {
110+
const lowercase = 'abcdefghijklmnopqrstuvwxyz';
111+
const uppercase = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
112+
const numbers = '0123456789';
113+
const symbols = '!@#$%^&*()_+-=[]{}|;:,.<>?';
114+
115+
const allChars = lowercase + uppercase + numbers + symbols;
116+
117+
// Ensure at least one character from each category
118+
let password = '';
119+
password += lowercase[Math.floor(Math.random() * lowercase.length)];
120+
password += uppercase[Math.floor(Math.random() * uppercase.length)];
121+
password += numbers[Math.floor(Math.random() * numbers.length)];
122+
password += symbols[Math.floor(Math.random() * symbols.length)];
123+
124+
// Fill the rest with random characters
125+
for (let i = 4; i < length; i++) {
126+
password += allChars[Math.floor(Math.random() * allChars.length)];
127+
}
128+
129+
// Shuffle the password to randomize the position of required characters
130+
return password
131+
.split('')
132+
.sort(() => Math.random() - 0.5)
133+
.join('');
134+
}

src/shared/jobs/ServiceInputsSection.tsx

Lines changed: 34 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,13 @@ import { KeyValueEntryWithId } from '@typedefs/deeploys';
44
import { useEffect } from 'react';
55
import { useFieldArray, useFormContext } from 'react-hook-form';
66

7-
export default function ServiceInputsSection({ inputs }: { inputs: { key: string; label: string }[] }) {
7+
export default function ServiceInputsSection({
8+
inputs,
9+
isEditingJob,
10+
}: {
11+
inputs: { key: string; label: string }[];
12+
isEditingJob?: boolean;
13+
}) {
814
const { control, setValue } = useFormContext();
915

1016
const { fields } = useFieldArray({
@@ -17,21 +23,39 @@ export default function ServiceInputsSection({ inputs }: { inputs: { key: string
1723
useEffect(() => {
1824
setValue(
1925
'deployment.inputs',
20-
inputs.map((input) => ({ key: input.key, value: '' })),
26+
inputs.map((input) => {
27+
// let value = '';
28+
29+
if (!isEditingJob && input.key.toLowerCase().includes('password')) {
30+
// TODO: Only generate it if no default value (editing flow) exists
31+
// value = generateSecurePassword();
32+
}
33+
34+
return { key: input.key, value: '' };
35+
}),
2136
);
2237
}, [inputs]);
2338

2439
return (
2540
<SlateCard title="Service Inputs">
26-
{typedFields.map((field, index) => (
27-
<div key={field.id}>
28-
<InputWithLabel
29-
name={`deployment.inputs.${index}.value`}
30-
label={inputs[index].label}
31-
placeholder="Required"
32-
/>
41+
<div className="col gap-4">
42+
<div className="col gap-2">
43+
{typedFields.map((field, index) => (
44+
<div key={field.id}>
45+
<InputWithLabel
46+
name={`deployment.inputs.${index}.value`}
47+
label={inputs[index].label}
48+
placeholder="Required"
49+
/>
50+
</div>
51+
))}
3352
</div>
34-
))}
53+
54+
{/* TODO: Display after the input becomes dirty */}
55+
{inputs.some((input) => input.key.toLowerCase().includes('password')) && (
56+
<div className="text-sm text-slate-500">Don't forget to save your auto-generated password.</div>
57+
)}
58+
</div>
3559
</SlateCard>
3660
);
3761
}

0 commit comments

Comments
 (0)