Skip to content

Commit

Permalink
Merge branch 'daniel-schwartz-k:main' into main
Browse files Browse the repository at this point in the history
  • Loading branch information
danielschwartz85 authored Jul 24, 2023
2 parents dfc0627 + 11a570f commit ccd725d
Show file tree
Hide file tree
Showing 4 changed files with 81 additions and 19 deletions.
28 changes: 20 additions & 8 deletions src/components/secret.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,18 @@ import TextField from '@mui/material/TextField'
import Box from '@mui/material/Box'
import Tooltip from '@mui/material/Tooltip'
import Typography from '@mui/material/Typography'
import SecretDialog from './secretDialog'
import SecretDialog, { ISecretDialogProps } from './secretDialog'
import { useState } from 'react'
import { SecretManager } from '../src/util'

type INewSecretProps = AutocompleteRenderInputParams & { value?: string }

function TextWithSave(props: INewSecretProps) {
const { value, InputProps } = props
const [isOpen, setIsOpen] = useState(false)
const [isDialogOpen, setIsDialogOpen] = useState(false)

const handleClickSave = () => {
setIsOpen(true)
const handleClickSaveIcon = () => {
setIsDialogOpen(true)
// show dialog [date, label(required), value], [save, cancel]
// save to local storage
// reset option values with new label + secret
Expand All @@ -34,13 +35,24 @@ function TextWithSave(props: INewSecretProps) {
event.preventDefault()
}

const handleClose = () => {
setIsOpen(false)
const handleCloseDialog = () => {
setIsDialogOpen(false)
}

const handleSaveDialog: ISecretDialogProps['handleSave'] = (secret) => {
console.log('🚀 XXXXXX ~ file: secret.tsx:43 ~ TextWithSave ~ secret:', secret)
SecretManager.saveSecret(secret)
setIsDialogOpen(false)
}

return (
<>
<SecretDialog isOpen={isOpen} handleClose={handleClose} handleSave={handleClose} />
<SecretDialog
initialValue={value as string}
isOpen={isDialogOpen}
handleClose={handleCloseDialog}
handleSave={handleSaveDialog}
/>
<TextField
{...props}
InputProps={{
Expand All @@ -50,7 +62,7 @@ function TextWithSave(props: INewSecretProps) {
{value && (
<IconButton
aria-label="save secret"
onClick={handleClickSave}
onClick={handleClickSaveIcon}
onMouseDown={handleMouseDownSave}
edge="end"
sx={{ mr: -1 }}
Expand Down
36 changes: 26 additions & 10 deletions src/components/secretDialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,13 @@ import FormHelperText from '@mui/material/FormHelperText'
import FormControl from '@mui/material/FormControl'
import Box from '@mui/material/Box'
import { useEffect, useState } from 'react'
import { ISavedSecret } from '../src/state'

export interface SecretDialogProps {
export interface ISecretDialogProps {
isOpen: boolean
initialValue: string
handleClose: () => void
handleSave: () => void
handleSave: (secret: ISavedSecret) => void
}

enum EExpiration {
Expand All @@ -25,20 +27,34 @@ enum EExpiration {
Month = 'Month',
Year = 'Year',
}

const DefaultFormState = {
label: '',
value: '',
expiration: EExpiration.Week,
isError: false,
}

export default function SecretDialog(props: SecretDialogProps) {
const { isOpen, handleClose, handleSave } = props
const [state, setState] = useState(DefaultFormState)
function getExpirationDate(expiration: EExpiration): Date {
const now = new Date()
const getDate = {
[EExpiration.Hour]: () => now.setHours(now.getHours() + 1),
[EExpiration.Day]: () => now.setDate(now.getDate() + 1),
[EExpiration.Week]: () => now.setDate(now.getDate() + 7),
[EExpiration.Month]: () => now.setMonth(now.getMonth() + 1),
[EExpiration.Year]: () => now.setMonth(now.getMonth() + 12),
}
getDate[expiration]()
return now
}

export default function SecretDialog(props: ISecretDialogProps) {
const { isOpen, initialValue, handleClose, handleSave } = props
const [state, setState] = useState({ ...DefaultFormState, value: initialValue })

useEffect(() => {
setState(DefaultFormState)
}, [isOpen])
setState({ ...DefaultFormState, value: initialValue })
}, [isOpen, initialValue])

const onLabelChange = (e: React.ChangeEvent<HTMLInputElement>) => {
setState((state) => ({ ...state, label: e.target.value }))
Expand All @@ -57,9 +73,9 @@ export default function SecretDialog(props: SecretDialogProps) {
setState((state) => ({ ...state, isError: true }))
return
}
// TODO: convert expiration and call handleSave with label + expiration + value
alert('not supported yet, coming soon..')
handleSave()
const expiration = getExpirationDate(state.expiration)
const { label, value } = state
handleSave({ expiration, label, value })
}

return (
Expand Down
6 changes: 6 additions & 0 deletions src/src/state.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
import { JWTPayload, ProtectedHeaderParameters } from 'jose'
import { jsonPrettyStr } from './util'

export interface ISavedSecret {
expiration: Date
label: string
value: string
}

export interface IState {
encoded: string
header: string
Expand Down
30 changes: 29 additions & 1 deletion src/src/util.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { CompactSign, compactVerify, decodeJwt, decodeProtectedHeader } from 'jose'
import { IDecoded } from './state'
import { IDecoded, ISavedSecret } from './state'
import useMediaQuery from '@mui/material/useMediaQuery/useMediaQuery'
import React, { useEffect, useState } from 'react'
import createTheme, { Theme } from '@mui/material/styles/createTheme'
Expand Down Expand Up @@ -73,3 +73,31 @@ export function useUserTheme(): [Theme, boolean, () => void] {

return [theme, isDarkMode, toggleDarkMode]
}

export const SecretManager = {
getSecret: (label: string): string | undefined => {
const secrets = SecretManager._secrets()
if (!secrets[label]) return
const exp = new Date(secrets[label].expiration)
if (exp < new Date()) {
SecretManager.deleteSecret(label)
return
}
return secrets[label].value
},
saveSecret: (secret: ISavedSecret): void => {
const secrets = SecretManager._secrets()
secrets[secret.label] = secret
localStorage.setItem('secrets', JSON.stringify(secrets))
},
deleteSecret: (label: string): void => {
const secrets = SecretManager._secrets()
if (!secrets[label]) return
delete secrets[label]
localStorage.setItem('secrets', JSON.stringify(secrets))
},
_secrets: (): Record<string, ISavedSecret> => {
const savedSecrets = localStorage.getItem('secrets')
return savedSecrets ? JSON.parse(savedSecrets) : {}
},
}

0 comments on commit ccd725d

Please sign in to comment.