Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add new input cookie_domain, fix styles for Custom component #15

Merged
merged 14 commits into from
Feb 1, 2023
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@

- Refactorization of CustomDataContainer to prevent passing invalid format of `uri` prop. Added documentation. (INDIGO Sprint 221209, [!11](https://github.com/TeskaLabs/seacat-admin-webui/pull/11))

- Add new input `cookie_domain` to Clients. Fix min-max height styles for CustomComponent (INDIGO Sprint 230120, [!15](https://github.com/TeskaLabs/seacat-admin-webui/pull/15))

## v22.48

### Compatibility
Expand Down
10 changes: 8 additions & 2 deletions public/locales/cs/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@
"Grant types": "Typy grantů",
"Application type": "Typ aplikace",
"Token endpoint authentication method": "Způsob autentikace pro získání tokenu",
"Cookie domain": "Cookie doména",
"Redirect URIs": "URIs k přesměrování",
"Create client": "Vytvořit klienta",
"Unknown item": "Neznámá položka"
Expand All @@ -127,18 +128,23 @@
"Response types": "Typy odpovědí",
"Grant types": "Typy grantů",
"Token endpoint auth. method": "Způsob autentikace pro získání tokenu",
"Cookie domain": "Cookie doména",
"Redirect URIs": "URIs k přesměrování",
"Redirect URI must be in absolute format without a fragment component.": "URI k přesměrování musí být v absolutním formátu a bez fragment komponenty.",
"Remove client": "Odstranit klienta"
"Remove client": "Odstranit klienta",
"Save changes": "Uložit změny",
"No changes were made": "Nebyly provedeny žádné změny"
},
"ClientFormField": {
"Add new input": "Přidat pole",
"Remove input": "Odstranit pole",
"Invalid format, input should have minimum of 8 characters": "Nesprávný formát, pole musí mít minimálně 8 znaků",
"Invalid format for cookie_domain": "Nesprávný formát pro cookie_domain",
"URI can't be empty": "URI nemůže být prázdný",
"URI have to start with https": "URI musí začínat https",
"URL hash have to be empty": "URL hash musí být prázdný",
"Choose an option": "Zvolte možnost"
"Choose an option": "Zvolte možnost",
"Required field": "Povinný údaj"
},
"CredentialsCreateContainer": {
"Create new credentials": "Vytvořit nové údaje",
Expand Down
10 changes: 8 additions & 2 deletions public/locales/en/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@
"Grant types": "Grant types",
"Application type": "Application type",
"Token endpoint authentication method": "Token endpoint authentication method",
"Cookie domain": "Cookie domain",
"Redirect URIs": "Redirect URIs",
"Create client": "Create client",
"Unknown item": "Unknown item"
Expand All @@ -127,18 +128,23 @@
"Response types": "Response types",
"Grant types": "Grant types",
"Token endpoint auth. method": "Token endpoint auth. method",
"Cookie domain": "Cookie domain",
"Redirect URIs": "Redirect URIs",
"Redirect URI must be in absolute format without a fragment component.": "Redirect URI must be in absolute format without a fragment component.",
"Remove client": "Remove client"
"Remove client": "Remove client",
"Save changes": "Save changes",
"No changes were made": "No changes were made"
},
"ClientFormField": {
"Add new input": "Add new input",
"Remove input": "Remove input",
"Invalid format, input should have minimum of 8 characters": "Invalid format, input should have minimum of 8 characters",
"Invalid format for cookie_domain": "Invalid format for cookie_domain",
"URI can't be empty": "URI can't be empty",
"URI have to start with https": "URI have to start with https",
"URL hash have to be empty": "URL hash have to be empty",
"Choose an option": "Choose an option"
"Choose an option": "Choose an option",
"Required field": "Required field"
},
"CredentialsCreateContainer": {
"Create new credentials": "Create new credentials",
Expand Down
13 changes: 11 additions & 2 deletions src/modules/auth/clients/ClientCreateContainer.js
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,14 @@ const ClientCreateContainer = (props) => {
delete body.preferred_client_id;
}

if (body.client_uri == "") {
delete body.client_uri;
}

if (body.cookie_domain == "") {
delete body.cookie_domain;
}

try {
let response = await SeaCatAuthAPI.post(`/client`, body);
if (response.statusText != 'OK') {
Expand Down Expand Up @@ -187,9 +195,10 @@ const ClientCreateContainer = (props) => {
</FormGroup>
{metaData["properties"] && Object.entries(metaData["properties"]).map(([key, value]) => {
switch(key) {
case 'redirect_uris': return(<URiInput key={key} name={key} control={control} errors={errors} append={append} remove={remove} fields={fields} labelName={t("ClientCreateContainer|Redirect URIs")}/>)
case 'client_name': return(<TextInput key={key} name={key} register={register} labelName={t('ClientCreateContainer|Client name')}/>)
case 'redirect_uris': return(<URiInput key={key} name={key} control={control} errors={errors} append={append} remove={remove} fields={fields} labelName={`${t("ClientCreateContainer|Redirect URIs")}*`}/>)
case 'client_name': return(<TextInput key={key} name={key} register={register} labelName={`${t("ClientCreateContainer|Client name")}*`}/>)
case 'client_uri': return(<TextInput key={key} name={key} register={register} labelName={t('ClientCreateContainer|Client URI')}/>)
case 'cookie_domain': return(<TextInput key={key} name={key} register={register} errors={errors} labelName={t('ClientCreateContainer|Cookie domain')}/>)
case 'preferred_client_id': return(<TextInput key={key} name={key} register={register} errors={errors} labelName={t('ClientCreateContainer|Preferred client ID')}/>)
case 'response_types': return(selectedTemplate === "Custom" && <MultiCheckbox key={key} name={key} value={value["items"]["enum"]} setValue={setValue} labelName={t('ClientCreateContainer|Response types')}/>)
case 'grant_types': return(selectedTemplate === "Custom" && <MultiCheckbox key={key} name={key} value={value["items"]["enum"]} setValue={setValue} labelName={t('ClientCreateContainer|Grant types')}/>)
Expand Down
87 changes: 49 additions & 38 deletions src/modules/auth/clients/ClientDetailContainer.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ const ClientDetailContainer = (props) => {
const advmode = useSelector(state => state.advmode.enabled);


const { handleSubmit, formState: { errors }, control, setValue, reset, register } = useForm({
const { handleSubmit, formState: { errors, isSubmitting, isDirty }, control, setValue, reset, register } = useForm({
defaultValues: {
redirect_uris: [{ text: ""}],
}
Expand Down Expand Up @@ -100,7 +100,9 @@ const ClientDetailContainer = (props) => {
await Promise.all(Object.values(values[key]).map((item, index) => {
uri.push(item.text)
}))
} else {
} else if (key == "client_name") {
body[key] = values[key];
} else if (key == "cookie_domain") {
body[key] = values[key];
}
}))
Expand All @@ -111,10 +113,7 @@ const ClientDetailContainer = (props) => {
}

try {
let response = await SeaCatAuthAPI.put(`/client/${client_id}`, {
redirect_uris: body?.redirect_uris,
client_name: body?.client_name
});
let response = await SeaCatAuthAPI.put(`/client/${client_id}`, body);
if (response.statusText != 'OK') {
throw new Error("Unable to change client details");
}
Expand All @@ -123,7 +122,6 @@ const ClientDetailContainer = (props) => {
setDisabled(false);
getClientDetail();
props.app.addAlert("success", t("ClientDetailContainer|Client updated successfully"));

} catch (e) {
setDisabled(false);
setEditMode(true);
Expand Down Expand Up @@ -169,38 +167,27 @@ const ClientDetailContainer = (props) => {
</div>
</CardHeader>
<CardBody className="card-body-client">
{client?.client_name ?
<Row className="card-body-row">
<Col md={4}>{t("ClientDetailContainer|Client name")}</Col>
{editMode ?
<Col className="client-name">
<TextInput name="client_name" register={register} disabled={disabled}/>
</Col>

<Row className="card-body-row">
<Col md={4} title="client_name">{t("ClientDetailContainer|Client name")}</Col>
{editMode ?
<Col className="client-edit">
<TextInput name="client_name" register={register} disabled={disabled}/>
</Col>
:
<Col className="client-name">{client?.client_name}</Col>
}
</Row>
:
editMode &&
<Row className="card-body-row">
<Col md={4}>{t("ClientDetailContainer|Client name")}</Col>
<TextInput name="client_name" register={register}/>
</Row>
}
<Col className="client-edit" title="client_name">{client?.client_name ? client.client_name : "N/A"}</Col>
}
</Row>
<Row className="card-body-row">
<Col md={4}>{t("ClientDetailContainer|Client ID")}</Col>
<Col md={4} title="client_id">{t("ClientDetailContainer|Client ID")}</Col>
<Col><code>{client?.client_id}</code></Col>
</Row>
{client?.client_uri &&
<Row className="card-body-row">
<Col md={4}>{t("ClientDetailContainer|Client URI")}</Col>
<Col>{client?.client_uri}</Col>
</Row>
}
<Row className="card-body-row">
<Col md={4} title="client_uri">{t("ClientDetailContainer|Client URI")}</Col>
<Col>{client?.client_uri ? client.client_uri : "N/A"}</Col>
</Row>
{client?.client_secret &&
<Row className="card-body-row">
<Col md={4}>{t("ClientDetailContainer|Client secret")}</Col>
<Col md={4} title="client_secret">{t("ClientDetailContainer|Client secret")}</Col>
<Col>
<code>{client?.client_secret}</code>
<Button
Expand All @@ -214,11 +201,11 @@ const ClientDetailContainer = (props) => {
</Row>
}
<Row className="mt-2 card-body-row">
<Col md={4}>{t("Created at")}</Col>
<Col md={4} title="created_at">{t("Created at")}</Col>
<Col><DateTime value={client?._c} /></Col>
</Row>
<Row className="card-body-row">
<Col md={4}>{t("Modified at")}</Col>
<Col md={4} title="modified_at">{t("Modified at")}</Col>
<Col><DateTime value={client?._m} /></Col>
</Row>
<Row className="card-body-row">
Expand Down Expand Up @@ -249,6 +236,16 @@ const ClientDetailContainer = (props) => {
<Col md={4} title="token_endpoint_auth_method">{t("ClientDetailContainer|Token endpoint auth. method")}</Col>
<Col title="token_endpoint_auth_method">{client?.token_endpoint_auth_method}</Col>
</Row>
<Row className="card-body-row">
<Col md={4} title="cookie_domain">{t("ClientDetailContainer|Cookie domain")}</Col>
{editMode ?
<Col className="client-edit">
<TextInput name="cookie_domain" register={register} errors={errors} disabled={disabled}/>
</Col>
:
<Col className="client-edit" title="cookie_domain">{client?.cookie_domain ? client.cookie_domain : "N/A"}</Col>
}
</Row>
<Row className="mt-3 card-body-row">
<Col md={4} title="redirect_uris">{t("ClientDetailContainer|Redirect URIs")}</Col>
<Col title="redirect_uris" className={"redirect_uris" + (editMode ? "" : " edit")}>
Expand All @@ -269,10 +266,24 @@ const ClientDetailContainer = (props) => {
<ButtonGroup>
{editMode ?
<>
<Button color="primary" type="submit" >{t("Save")}</Button>
<Button color="outline-primary" type="button" onClick={(e) => (setEditMode(false))}>{t("Cancel")}</Button>
<Button
color="primary"
type="submit"
title={isDirty ? t("ClientDetailContainer|Save changes") : t("ClientDetailContainer|No changes were made")}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Aringoaway Out of curiosity, why do you need isDirty here?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I need it, that to see if there have been any changes in the inputs. If no changes have been made, the Save button will be disabled

disabled={!isDirty || isSubmitting}
>
{t("Save")}
</Button>
<Button
color="outline-primary"
type="button"
disabled={isSubmitting}
onClick={(e) => (setEditMode(false))}
>
{t("Cancel")}
</Button>
</>
:
:
<>
<ButtonWithAuthz
title={t("Edit")}
Expand Down
26 changes: 20 additions & 6 deletions src/modules/auth/clients/FormFields.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,27 +11,41 @@ export function TextInput ({ name, register, errors, labelName, disabled }) {
const { t } = useTranslation();
const reg = register(
name,
(name == "preferred_client_id") && {
(name === "preferred_client_id") ? {
validate: {
validation: value => (/^[-_a-zA-Z0-9]{8,64}$|^$/).test(value) || t("ClientFormField|Invalid format, input should have minimum of 8 characters"),
}
}
:
(name === "cookie_domain") && {
validate: {
validation: value => (/^[a-z0-9\.-]{1,61}\.[a-z]{2,}$|^$/).test(value) || t("ClientFormField|Invalid format for cookie_domain"),
}
}
);

const isInvalid = (name) => {
if (((name === "preferred_client_id") || (name === "cookie_domain")) && (errors[name] != undefined)) {
return true;
}
return false;
}
return (
<FormGroup key={name}>
{labelName && <Label for={name}>{labelName}</Label>}
{labelName && <Label for={name} title={(name === "client_name") && t("ClientFormField|Required field")}>{labelName}</Label>}
<Input
id={name}
name={name}
type="text"
disabled={disabled}
required={name == "client_name" ? true : false}
required={(name === "client_name") ? true : false}
onChange={reg.onChange}
onBlur={reg.onBlur}
innerRef={reg.ref}
invalid={errors?.preferred_client_id && errors.preferred_client_id}
invalid={isInvalid(name)}
/>
{errors?.preferred_client_id && <FormFeedback>{errors.preferred_client_id.message}</FormFeedback>}
{name === "preferred_client_id" && (errors.preferred_client_id != undefined && <FormFeedback>{errors.preferred_client_id?.message}</FormFeedback>)}
{name === "cookie_domain" && (errors?.cookie_domain && <FormFeedback>{errors.cookie_domain?.message}</FormFeedback>)}
</FormGroup>
)
}
Expand Down Expand Up @@ -69,7 +83,7 @@ export function URiInput ({ name, control, errors, append, remove, fields, label
return (
<FormGroup title={name}>
{(labelName && name) &&
<Label for={name} title={name}>{labelName}</Label>}
<Label for={name} title={t("ClientFormField|Required field")}>{labelName}</Label>}
{fields && fields.map((item, idx) => {
return (
<InputGroup key={item.id} className="mb-1">
Expand Down
2 changes: 1 addition & 1 deletion src/modules/auth/clients/clients.scss
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ $svg-arrow: var(--svg-arrow);
.form-group {
margin-bottom: 0;
}
.client-name {
.client-edit {
height: 40px;
}
.redirect_uris {
Expand Down
2 changes: 1 addition & 1 deletion src/modules/auth/components/CustomDataContainer.js
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ export function CustomDataContainer({app, resources, customData, setCustomData,
</div>
</CardHeader>

<Form onSubmit={handleSubmit((values) => {onSave(values)})}>
<Form className="d-flex flex-column justify-content-between h-100" onSubmit={handleSubmit((values) => {onSave(values)})}>
<CardBody className="card-body-scroll-sm " >
{loading ?
<CellContentLoader cols={2} rows={5} />
Expand Down
6 changes: 5 additions & 1 deletion src/modules/auth/components/customdata.scss
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
.input-group .input-group-append{
margin-left: "0";
margin-left: 0;
}

.custom-data {
Expand All @@ -18,6 +18,10 @@

.custom-data-card {
grid-area: q;
.card-body-scroll-sm {
height: 200px !important;
overflow-y: auto;
}
}

@media (max-width: 576px) {
Expand Down
11 changes: 2 additions & 9 deletions src/modules/auth/credentials/credentials.scss
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,6 @@
min-height: 20vh !important;
}

//CredentialCustomDataContainer
.card-body-scroll-sm {
max-height: 15vh;
min-height: 15vh !important;
overflow-y: auto;
}

//CredentialsDetailContainer/Credentials Status
.credential-status {
display: inline-block;
Expand Down Expand Up @@ -78,7 +71,7 @@
grid-template-areas:
"top"
"bottom";
grid-template-columns: "1fr";
grid-template-rows: 2fr 1fr;
}

.info-detail-area {
Expand All @@ -88,7 +81,7 @@
grid-template-areas:
"i"
"q";
grid-template-columns: "1fr";
grid-template-rows: 1fr 1fr;
}
}

Expand Down