Skip to content

Commit 4d3384f

Browse files
kahoona77cesmarvin
authored andcommitted
Merge branch 'release/v1.17.0-1'
2 parents db84902 + a1a266b commit 4d3384f

File tree

12 files changed

+110
-64
lines changed

12 files changed

+110
-64
lines changed

CHANGELOG.md

+6
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
66

77
## [Unreleased]
88

9+
## [v1.17.0-1] - 2024-10-29
10+
### Changed
11+
- Mark external users [#173]
12+
- When editing external users, the password field is hidden and all other fields cannot be edited
13+
- Groups can still be added or removed to the users
14+
915
## [v1.16.4-1] - 2024-10-18
1016
### Changed
1117
- Set the page size of user import preview to 25 from 8 [#170]

Dockerfile

+1-1
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ FROM registry.cloudogu.com/official/java:8u402-6
7575
ARG TOMCAT_VERSION
7676

7777
LABEL NAME="official/usermgt" \
78-
VERSION="1.16.4-1" \
78+
VERSION="1.17.0-1" \
7979
maintainer="[email protected]"
8080

8181
# mark as webapp for nginx

Makefile

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Set these to the desired values
22
ARTIFACT_ID=usermgt
3-
VERSION=1.16.4-1
3+
VERSION=1.17.0-1
44
# overwrite ADDITIONAL_LDFLAGS to disable static compilation
55
# this should fix https://github.com/golang/go/issues/13470
66
ADDITIONAL_LDFLAGS=""

app/env/data/ldap.xml

+2-2
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,10 @@
77
<bind-password>bJ3VoW2iMEgsj+misqcY7z4rdVJwSuSxDwlIcaPYYAx+nBScxbFvI1ISihDRio/F</bind-password>
88
-->
99
<bind-dn>cn=usermgt_x53eMC,ou=Special Users,o=ces.local,dc=cloudogu,dc=com</bind-dn>
10-
10+
1111
<!--<bind-dn>cn=Directory Manager,dc=cloudogu,dc=com</bind-dn>-->
1212
<bind-password>uXMC36Mdei48rhVBQ+p6+nCTz0AvlDRg9Qc1I31Xht2GidUo3BFds+S/0NooTcRC</bind-password>
13-
13+
1414
<user-base-dn>ou=People,o=ces.local,dc=cloudogu,dc=com</user-base-dn>
1515
<group-base-dn>ou=Groups,o=ces.local,dc=cloudogu,dc=com</group-base-dn>
1616

app/src/main/ui/src/components/users/UserForm.tsx

+69-58
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,18 @@
1-
import { deprecated_Form as Form, Details } from "@cloudogu/ces-theme-tailwind";
2-
import { Button, H2, ListWithSearchbar } from "@cloudogu/deprecated-ces-theme-tailwind";
3-
import { TrashIcon } from "@heroicons/react/24/outline";
4-
import { twMerge } from "tailwind-merge";
5-
import { t } from "../../helpers/i18nHelpers";
6-
import { useConfirmation } from "../../hooks/useConfirmation";
7-
import { Prompt } from "../../hooks/usePrompt";
1+
import {deprecated_Form as Form, Details} from "@cloudogu/ces-theme-tailwind";
2+
import {Button, H2, ListWithSearchbar} from "@cloudogu/deprecated-ces-theme-tailwind";
3+
import {TrashIcon} from "@heroicons/react/24/outline";
4+
import {twMerge} from "tailwind-merge";
5+
import {t} from "../../helpers/i18nHelpers";
6+
import {useConfirmation} from "../../hooks/useConfirmation";
7+
import {Prompt} from "../../hooks/usePrompt";
88
import useUserFormHandler from "../../hooks/useUserFormHandler";
9-
import { GroupsService } from "../../services/Groups";
10-
import { ConfirmationDialog } from "../ConfirmationDialog";
11-
import { useApplicationContext } from "../contexts/ApplicationContext";
9+
import {GroupsService} from "../../services/Groups";
10+
import {ConfirmationDialog} from "../ConfirmationDialog";
11+
import {useApplicationContext} from "../contexts/ApplicationContext";
1212
import HelpLink from "../helpLink";
13-
import type { Group } from "../../services/Groups";
14-
import type { User } from "../../services/Users";
15-
import type { NotifyFunction, UseFormHandlerFunctions } from "@cloudogu/deprecated-ces-theme-tailwind";
13+
import type {Group} from "../../services/Groups";
14+
import type {User} from "../../services/Users";
15+
import type {NotifyFunction, UseFormHandlerFunctions} from "@cloudogu/deprecated-ces-theme-tailwind";
1616

1717
const MAX_SEARCH_RESULTS = 10;
1818

@@ -29,15 +29,15 @@ export interface UserFormProps<T extends User> {
2929
}
3030

3131
export default function UserForm<T extends User>(props: UserFormProps<T>) {
32-
const { handler, notification, notify } = useUserFormHandler<T>(props.initialUser, (values: T) => props.onSubmit(values, notify, handler));
33-
const { open, setOpen: toggleModal, targetName: groupName, setTargetName: setGroupName } = useConfirmation();
32+
const {handler, notification, notify} = useUserFormHandler<T>(props.initialUser, (values: T) => props.onSubmit(values, notify, handler));
33+
const {open, setOpen: toggleModal, targetName: groupName, setTargetName: setGroupName} = useConfirmation();
3434

35-
const { admin } = useApplicationContext().casUser;
35+
const {admin} = useApplicationContext().casUser;
3636

3737
const addGroup = (groupName: string): void => {
3838
if (handler.values.memberOf.indexOf(groupName) < 0) {
3939
const newGroups = [...handler.values.memberOf, groupName];
40-
handler.setValues({ ...handler.values, memberOf: newGroups });
40+
handler.setValues({...handler.values, memberOf: newGroups});
4141
}
4242
};
4343

@@ -78,7 +78,7 @@ export default function UserForm<T extends User>(props: UserFormProps<T>) {
7878
addLable={t("users.labels.addGroup") + " (" + t("general.optional") + ")"}
7979
removeLable={t("users.labels.removeGroup")}
8080
emptyItemsLable={t("users.labels.emptyGroups")}
81-
removeIcon={<TrashIcon className={"w-6 h-6"} />}
81+
removeIcon={<TrashIcon className={"w-6 h-6"}/>}
8282
pageSize={pageSize}
8383
/>
8484
);
@@ -93,35 +93,42 @@ export default function UserForm<T extends User>(props: UserFormProps<T>) {
9393
await removeGroup(groupName ?? "");
9494
}}
9595
title={t("users.labels.removeGroup")}
96-
message={t("users.labels.removeGroupConfirmationMessage", { groupName: groupName })}
96+
message={t("users.labels.removeGroupConfirmationMessage", {groupName: groupName})}
9797
/>
98-
<Prompt when={handler.dirty && !handler.isSubmitting} message={t("generic.notification.form.prompt")} />
98+
<Prompt when={handler.dirty && !handler.isSubmitting} message={t("generic.notification.form.prompt")}/>
9999
<Form handler={handler}>
100100
{notification}
101+
<span className={"font-bold"}>
102+
{t("users.externalUserWarning")}
103+
</span>
101104
<Form.ValidatedTextInput type={"text"} name={"username"} disabled={props.disableUsernameField ?? true} data-testid="username" placeholder={t("users.placeholder.username")} hint={t("users.hint.username")}>
102105
{t("editUser.labels.username")}
103106
</Form.ValidatedTextInput>
104-
<Form.ValidatedTextInput type={"text"} name={"givenname"} data-testid="givenname" placeholder={t("users.placeholder.givenname")}>
107+
<Form.ValidatedTextInput disabled={props.initialUser.external} type={"text"} name={"givenname"} data-testid="givenname" placeholder={t("users.placeholder.givenname")}>
105108
{t("editUser.labels.givenName")}
106109
</Form.ValidatedTextInput>
107-
<Form.ValidatedTextInput type={"text"} name={"surname"} data-testid="surname" placeholder={t("users.placeholder.surname")}>
110+
<Form.ValidatedTextInput disabled={props.initialUser.external} type={"text"} name={"surname"} data-testid="surname" placeholder={t("users.placeholder.surname")}>
108111
{t("editUser.labels.surname")}
109112
</Form.ValidatedTextInput>
110-
<Form.ValidatedTextInput type={"text"} name={"displayName"} data-testid="displayName" placeholder={t("users.placeholder.displayName")} hint={t("users.hint.displayName")}>
113+
<Form.ValidatedTextInput disabled={props.initialUser.external} type={"text"} name={"displayName"} data-testid="displayName" placeholder={t("users.placeholder.displayName")} hint={t("users.hint.displayName")}>
111114
{t("editUser.labels.displayName")}
112115
</Form.ValidatedTextInput>
113-
<Form.ValidatedTextInput type={"text"} name={"mail"} data-testid="mail" placeholder={t("users.placeholder.mail")}>
116+
<Form.ValidatedTextInput disabled={props.initialUser.external} type={"text"} name={"mail"} data-testid="mail" placeholder={t("users.placeholder.mail")}>
114117
{t("editUser.labels.email")}
115118
</Form.ValidatedTextInput>
116-
<Form.ValidatedTextInput type={"password"} name={"password"} data-testid="password" placeholder={t("users.placeholder.password")}>
117-
{t("editUser.labels.password")}
118-
</Form.ValidatedTextInput>
119-
<Form.ValidatedTextInput type={"password"} name={"confirmPassword"} data-testid="confirmPassword" placeholder={t("users.placeholder.confirmPassword")}>
120-
{t("editUser.labels.confirmPassword")}
121-
</Form.ValidatedTextInput>
119+
{!props.initialUser.external &&
120+
<>
121+
<Form.ValidatedTextInput disabled={props.initialUser.external} type={"password"} name={"password"} data-testid="password" placeholder={t("users.placeholder.password")}>
122+
{t("editUser.labels.password")}
123+
</Form.ValidatedTextInput>
124+
<Form.ValidatedTextInput disabled={props.initialUser.external} type={"password"} name={"confirmPassword"} data-testid="confirmPassword" placeholder={t("users.placeholder.confirmPassword")}>
125+
{t("editUser.labels.confirmPassword")}
126+
</Form.ValidatedTextInput>
127+
</>
128+
}
122129

123130
<>
124-
{props.passwordReset && (
131+
{(props.passwordReset && !props.initialUser.external) && (
125132
<>
126133
<Form.ValidatedCheckboxLabelRight name={"pwdReset"} data-testid="pwdReset">
127134
{t("editUser.labels.mustChangePassword")}
@@ -154,33 +161,37 @@ export default function UserForm<T extends User>(props: UserFormProps<T>) {
154161
</div>
155162
</Form>
156163

157-
{props.groupsReadonly ? (
158-
<>
159-
<H2>
160-
{t("users.labels.myGroups")} ({handler.values.memberOf.length})
161-
</H2>
162-
{renderGroupsList(true, 10)}
163-
</>
164-
) : (
165-
<></>
166-
)}
167-
{admin ? (
168-
<>
169-
<hr />
170-
<Details className={twMerge("py-2")}>
171-
<Details.Summary>
172-
<Details.Summary.Arrow />
173-
{t("users.steps.title")}
174-
</Details.Summary>
175-
<Details.Content>
176-
{t("users.steps.text")}
177-
<HelpLink />
178-
</Details.Content>
179-
</Details>
180-
</>
181-
) : (
182-
<></>
183-
)}
164+
{
165+
props.groupsReadonly ? (
166+
<>
167+
<H2>
168+
{t("users.labels.myGroups")} ({handler.values.memberOf.length})
169+
</H2>
170+
{renderGroupsList(true, 10)}
171+
</>
172+
) : (
173+
<></>
174+
)
175+
}
176+
{
177+
admin ? (
178+
<>
179+
<hr/>
180+
<Details className={twMerge("py-2")}>
181+
<Details.Summary>
182+
<Details.Summary.Arrow/>
183+
{t("users.steps.title")}
184+
</Details.Summary>
185+
<Details.Content>
186+
{t("users.steps.text")}
187+
<HelpLink/>
188+
</Details.Content>
189+
</Details>
190+
</>
191+
) : (
192+
<></>
193+
)
194+
}
184195
</>
185196
);
186197
}

app/src/main/ui/src/i18n/de.json

+4
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,10 @@
135135
"users.table.email": "E-Mail",
136136
"users.table.username": "Nutzername",
137137
"users.table.actions": "Aktionen",
138+
"users.table.external": "Extern",
139+
"users.table.external.true": "Ja",
140+
"users.table.external.false": "Nein",
141+
"users.externalUserWarning": "Externer Nutzer. Für diesen Nutzer können Sie nur die Gruppenzuordnung bearbeiten.",
138142
"usersImport.buttons.reset": "Abbrechen",
139143
"usersImport.buttons.upload": "Importieren",
140144
"usersImport.headlines.importErrors": "Fehler",

app/src/main/ui/src/i18n/en.json

+4
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,10 @@
135135
"users.table.email": "E-Mail",
136136
"users.table.username": "Username",
137137
"users.table.actions": "Actions",
138+
"users.table.external": "External",
139+
"users.table.external.true": "Yes",
140+
"users.table.external.false": "No",
141+
"users.externalUserWarning": "External user. You can only edit the group assignment for this user.",
138142
"usersImport.buttons.reset": "Reset",
139143
"usersImport.buttons.upload": "Upload",
140144
"usersImport.headlines.importErrors": "Fehler",

app/src/main/ui/src/pages/Users.tsx

+7
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,11 @@ export default function Users() {
2525

2626
const {items, isLoading, paginationControl, updateSearchQuery, searchQuery, onDelete} = usePaginationTableState<User>(UsersService);
2727

28+
const hasExternal = useMemo(() => {
29+
console.log(items);
30+
return items.reduce((a,b) => a || b.external, false);
31+
}, [items]);
32+
2833
return <>
2934
<div className="flex flex-wrap justify-between">
3035
<H1 className="uppercase">{t("pages.users")}</H1>
@@ -54,6 +59,7 @@ export default function Users() {
5459
<ActionTable.HeadWithOneRow.Column>{t("users.table.username")}</ActionTable.HeadWithOneRow.Column>
5560
<ActionTable.HeadWithOneRow.Column>{t("users.table.displayName")}</ActionTable.HeadWithOneRow.Column>
5661
<ActionTable.HeadWithOneRow.Column>{t("users.table.email")}</ActionTable.HeadWithOneRow.Column>
62+
{hasExternal && <ActionTable.HeadWithOneRow.Column>{t("users.table.external")}</ActionTable.HeadWithOneRow.Column>}
5763
<ActionTable.HeadWithOneRow.Column
5864
align={"center"}>{t("users.table.actions")}</ActionTable.HeadWithOneRow.Column>
5965
</ActionTable.HeadWithOneRow>
@@ -73,6 +79,7 @@ export default function Users() {
7379
<ActionTable.Body.Row.Column>
7480
<a href={`mailto:${user.mail}`}>{user.mail}</a>
7581
</ActionTable.Body.Row.Column>
82+
{hasExternal && <ActionTable.Body.Row.Column>{t(`users.table.external.${user.external}`)}</ActionTable.Body.Row.Column>}
7683
<ActionTable.Body.Row.Column className="flex justify-center">
7784
<EditLink
7885
className={"flex items-center"}

docs/development/Developers_Guide_de.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ Das Backend ist unter der URL `http://localhost:8084/usermgt/api` erreichbar
105105
106106
## Das Frontend lokal entwickeln
107107

108-
Das Frontend des Usermgt kann lokal entweder mit einem Mock-Backend oder mit dem lokalen Backen des Usermgt entwickelt
108+
Das Frontend des Usermgt kann lokal entweder mit einem Mock-Backend oder mit dem lokalen Backend des Usermgt entwickelt
109109
werden.
110110

111111
### Mock-Backend starten

docs/gui/release_notes_de.md

+7
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,13 @@ Im Folgenden finden Sie die Release Notes für das User Management.
44

55
Technische Details zu einem Release finden Sie im zugehörigen [Changelog](https://docs.cloudogu.com/de/docs/dogus/usermgt/CHANGELOG/).
66

7+
## Release 1.17.0-1
8+
* Externe Nutzer werden als solche in der Übersicht markiert
9+
* In der Übersichtstabelle der Nutzer wird eine weitere Spalte angezeigt, die angibt ob ein Nutzer extern oder intern ist
10+
* Diese Spalte wird nur angezeigt, wenn mindestens ein externer Benutzer vorhanden ist
11+
* Externe Nutzer können nicht editiert werden. Alle Felder werden entweder ausgeblendet oder deaktiviert
12+
* Gruppen können weiterhin zu externen Nutzern hinzugefügt und entfernt werden
13+
714
## Release 1.16.4-1
815
* Auf der Nutzerimport-Vorschauseite sind nun 25 Einträge pro Seite statt der vorherigen 8 Einträge
916
* Mails mit mehr als einem '@' sind nun nicht mehr zulässig

docs/gui/release_notes_en.md

+7
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,13 @@ Below you will find the release notes for User Management.
44

55
Technical details on a release can be found in the corresponding [Changelog](https://docs.cloudogu.com/en/docs/dogus/usermgt/CHANGELOG/).
66

7+
## Release 1.17.0-1
8+
* External users are marked as such in the overview
9+
* There is an additional column in the user overview table that shows whether a user is external or internal
10+
* This column is only displayed if there is at least one external user
11+
* External users cannot be edited. All fields are either hidden or deactivated
12+
* Groups can still be added to and removed from external users
13+
714
## Release 1.16.4-1
815
* On the user import preview page there are now 25 entries per page instead of the previously 8 entries
916
* Mails with more than one ‘@’ are no longer allowed

dogu.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"Name": "official/usermgt",
3-
"Version": "1.16.4-1",
3+
"Version": "1.17.0-1",
44
"DisplayName": "User Management",
55
"Description": "User and Group Management.",
66
"Category": "Administration Apps",

0 commit comments

Comments
 (0)