User Create/Edit/Invite frontend + backend
This commit is contained in:
parent
675025800b
commit
91520dd26c
@ -16,14 +16,16 @@ class ArrayType extends Parameter {
|
|||||||
* @param bool $optional true if the parameter is optional
|
* @param bool $optional true if the parameter is optional
|
||||||
* @param array|null $defaultValue the default value to use, if the parameter is not given
|
* @param array|null $defaultValue the default value to use, if the parameter is not given
|
||||||
*/
|
*/
|
||||||
public function __construct(string $name, int $elementType = Parameter::TYPE_MIXED, bool $canBeOne = false, bool $optional = FALSE, ?array $defaultValue = NULL) {
|
public function __construct(string $name, int $elementType = Parameter::TYPE_MIXED, bool $canBeOne = false,
|
||||||
|
bool $optional = FALSE, ?array $defaultValue = NULL, ?array $choices = NULL) {
|
||||||
$this->elementType = $elementType;
|
$this->elementType = $elementType;
|
||||||
$this->elementParameter = new Parameter('', $elementType);
|
$this->elementParameter = new Parameter('', $elementType);
|
||||||
$this->canBeOne = $canBeOne;
|
$this->canBeOne = $canBeOne;
|
||||||
parent::__construct($name, Parameter::TYPE_ARRAY, $optional, $defaultValue);
|
parent::__construct($name, Parameter::TYPE_ARRAY, $optional, $defaultValue, $choices);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function parseParam($value): bool {
|
public function parseParam($value): bool {
|
||||||
|
|
||||||
if (!is_array($value)) {
|
if (!is_array($value)) {
|
||||||
if (!$this->canBeOne) {
|
if (!$this->canBeOne) {
|
||||||
return false;
|
return false;
|
||||||
@ -42,6 +44,14 @@ class ArrayType extends Parameter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!is_null($this->choices)) {
|
||||||
|
foreach ($value as $element) {
|
||||||
|
if (!in_array($element, $this->choices)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
$this->value = $value;
|
$this->value = $value;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -2,8 +2,11 @@
|
|||||||
|
|
||||||
namespace Core\API {
|
namespace Core\API {
|
||||||
|
|
||||||
|
use Core\Driver\SQL\Column\Column;
|
||||||
use Core\Driver\SQL\Condition\Compare;
|
use Core\Driver\SQL\Condition\Compare;
|
||||||
|
use Core\Driver\SQL\Condition\CondIn;
|
||||||
use Core\Objects\Context;
|
use Core\Objects\Context;
|
||||||
|
use Core\Objects\DatabaseEntity\Group;
|
||||||
use Core\Objects\DatabaseEntity\Language;
|
use Core\Objects\DatabaseEntity\Language;
|
||||||
use Core\Objects\DatabaseEntity\User;
|
use Core\Objects\DatabaseEntity\User;
|
||||||
use Core\Objects\DatabaseEntity\UserToken;
|
use Core\Objects\DatabaseEntity\UserToken;
|
||||||
@ -75,6 +78,26 @@ namespace Core\API {
|
|||||||
$this->checkPasswordRequirements($password, $confirmPassword);
|
$this->checkPasswordRequirements($password, $confirmPassword);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected function checkGroups(array &$groups): bool {
|
||||||
|
$sql = $this->context->getSQL();
|
||||||
|
$currentUser = $this->context->getUser();
|
||||||
|
$requestedGroups = array_unique($this->getParam("groups"));
|
||||||
|
if (!empty($requestedGroups)) {
|
||||||
|
$availableGroups = Group::findAll($sql, new CondIn(new Column("id"), $requestedGroups));
|
||||||
|
foreach ($requestedGroups as $groupId) {
|
||||||
|
if (!isset($availableGroups[$groupId])) {
|
||||||
|
return $this->createError("Group with id=$groupId does not exist.");
|
||||||
|
} else if ($this->isExternalCall() && $groupId === Group::ADMIN && !$currentUser->hasGroup(Group::ADMIN)) {
|
||||||
|
return $this->createError("You cannot create users with administrator groups.");
|
||||||
|
} else {
|
||||||
|
$groups[] = $groupId;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
protected function insertUser(string $username, ?string $email, string $password, bool $confirmed, string $fullName = "", array $groups = []): bool|User {
|
protected function insertUser(string $username, ?string $email, string $password, bool $confirmed, string $fullName = "", array $groups = []): bool|User {
|
||||||
$sql = $this->context->getSQL();
|
$sql = $this->context->getSQL();
|
||||||
|
|
||||||
@ -153,6 +176,7 @@ namespace Core\API\User {
|
|||||||
public function __construct(Context $context, $externalCall = false) {
|
public function __construct(Context $context, $externalCall = false) {
|
||||||
parent::__construct($context, $externalCall, array(
|
parent::__construct($context, $externalCall, array(
|
||||||
'username' => new StringType('username', 32),
|
'username' => new StringType('username', 32),
|
||||||
|
'fullName' => new StringType('fullName', 64, true, ""),
|
||||||
'email' => new Parameter('email', Parameter::TYPE_EMAIL, true, NULL),
|
'email' => new Parameter('email', Parameter::TYPE_EMAIL, true, NULL),
|
||||||
'password' => new StringType('password'),
|
'password' => new StringType('password'),
|
||||||
'confirmPassword' => new StringType('confirmPassword'),
|
'confirmPassword' => new StringType('confirmPassword'),
|
||||||
@ -165,6 +189,7 @@ namespace Core\API\User {
|
|||||||
public function _execute(): bool {
|
public function _execute(): bool {
|
||||||
|
|
||||||
$username = $this->getParam('username');
|
$username = $this->getParam('username');
|
||||||
|
$fullName = $this->getParam('fullName');
|
||||||
$email = $this->getParam('email');
|
$email = $this->getParam('email');
|
||||||
$password = $this->getParam('password');
|
$password = $this->getParam('password');
|
||||||
$confirmPassword = $this->getParam('confirmPassword');
|
$confirmPassword = $this->getParam('confirmPassword');
|
||||||
@ -172,31 +197,18 @@ namespace Core\API\User {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$groups = [];
|
||||||
|
if (!$this->checkGroups($groups)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (!$this->checkUserExists($username, $email)) {
|
if (!$this->checkUserExists($username, $email)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
$groups = [];
|
|
||||||
$sql = $this->context->getSQL();
|
|
||||||
$currentUser = $this->context->getUser();
|
|
||||||
|
|
||||||
$requestedGroups = array_unique($this->getParam("groups"));
|
|
||||||
if (!empty($requestedGroups)) {
|
|
||||||
$availableGroups = Group::findAll($sql, new CondIn(new Column("id"), $requestedGroups));
|
|
||||||
foreach ($requestedGroups as $groupId) {
|
|
||||||
if (!isset($availableGroups[$groupId])) {
|
|
||||||
return $this->createError("Group with id=$groupId does not exist.");
|
|
||||||
} else if ($this->isExternalCall() && $groupId === Group::ADMIN && !$currentUser->hasGroup(Group::ADMIN)) {
|
|
||||||
return $this->createError("You cannot create users with administrator groups.");
|
|
||||||
} else {
|
|
||||||
$groups[] = $groupId;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// prevent duplicate keys
|
// prevent duplicate keys
|
||||||
$email = (!is_null($email) && empty($email)) ? null : $email;
|
$email = (!is_null($email) && empty($email)) ? null : $email;
|
||||||
$user = $this->insertUser($username, $email, $password, true, "", $groups);
|
$user = $this->insertUser($username, $email, $password, true, $fullName, $groups);
|
||||||
if ($user !== false) {
|
if ($user !== false) {
|
||||||
$this->user = $user;
|
$this->user = $user;
|
||||||
$this->result["userId"] = $user->getId();
|
$this->result["userId"] = $user->getId();
|
||||||
@ -432,7 +444,9 @@ namespace Core\API\User {
|
|||||||
public function __construct(Context $context, $externalCall = false) {
|
public function __construct(Context $context, $externalCall = false) {
|
||||||
parent::__construct($context, $externalCall, array(
|
parent::__construct($context, $externalCall, array(
|
||||||
'username' => new StringType('username', 32),
|
'username' => new StringType('username', 32),
|
||||||
|
'fullName' => new StringType('fullName', 64, true, ""),
|
||||||
'email' => new StringType('email', 64),
|
'email' => new StringType('email', 64),
|
||||||
|
'groups' => new ArrayType("groups", Parameter::TYPE_INT, true, true, [])
|
||||||
));
|
));
|
||||||
|
|
||||||
$this->loginRequired = true;
|
$this->loginRequired = true;
|
||||||
@ -440,24 +454,38 @@ namespace Core\API\User {
|
|||||||
|
|
||||||
public function _execute(): bool {
|
public function _execute(): bool {
|
||||||
|
|
||||||
|
$sql = $this->context->getSQL();
|
||||||
|
$settings = $this->context->getSettings();
|
||||||
|
$currentUser = $this->context->getUser();
|
||||||
|
if (!$settings->isMailEnabled()) {
|
||||||
|
return $this->createError("An invitation cannot be sent because mailing is not enabled.");
|
||||||
|
}
|
||||||
|
|
||||||
$username = $this->getParam('username');
|
$username = $this->getParam('username');
|
||||||
|
$fullName = $this->getParam('fullName');
|
||||||
$email = $this->getParam('email');
|
$email = $this->getParam('email');
|
||||||
|
$groups = [];
|
||||||
|
|
||||||
|
if (!$this->checkGroups($groups)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (!$this->checkUserExists($username, $email)) {
|
if (!$this->checkUserExists($username, $email)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create user
|
// Create user
|
||||||
$user = $this->insertUser($username, $email, "", false);
|
$user = $this->insertUser($username, $email, "", false, $fullName, $groups);
|
||||||
if ($user === false) {
|
if ($user === false) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$this->result["userId"] = $user->getId();
|
||||||
$this->logger->info("A new user with username='$username' and email='$email' was invited by " . $this->logUserId());
|
$this->logger->info("A new user with username='$username' and email='$email' was invited by " . $this->logUserId());
|
||||||
|
|
||||||
// Create Token
|
// Create Token
|
||||||
$token = generateRandomString(36);
|
$token = generateRandomString(36);
|
||||||
$validDays = 7;
|
$validDays = 7;
|
||||||
$sql = $this->context->getSQL();
|
|
||||||
$userToken = new UserToken($user, $token, UserToken::TYPE_INVITE, $validDays * 24);
|
$userToken = new UserToken($user, $token, UserToken::TYPE_INVITE, $validDays * 24);
|
||||||
|
|
||||||
if ($userToken->save($sql)) {
|
if ($userToken->save($sql)) {
|
||||||
|
@ -10,7 +10,6 @@ import {
|
|||||||
import { Dropdown } from '@mui/base/Dropdown';
|
import { Dropdown } from '@mui/base/Dropdown';
|
||||||
import ChevronRightIcon from '@mui/icons-material/ChevronRight';
|
import ChevronRightIcon from '@mui/icons-material/ChevronRight';
|
||||||
import ChevronLeftIcon from '@mui/icons-material/ChevronLeft';
|
import ChevronLeftIcon from '@mui/icons-material/ChevronLeft';
|
||||||
import ProfilePicture from "shared/elements/profile-picture";
|
|
||||||
import {Dns, Groups, People, QueryStats, Security, Settings, Route, ArrowBack, Translate} from "@mui/icons-material";
|
import {Dns, Groups, People, QueryStats, Security, Settings, Route, ArrowBack, Translate} from "@mui/icons-material";
|
||||||
import useCurrentPath from "shared/hooks/current-path";
|
import useCurrentPath from "shared/hooks/current-path";
|
||||||
import ProfileLink from "./profile-link";
|
import ProfileLink from "./profile-link";
|
||||||
|
@ -107,7 +107,7 @@ export default function EditProfilePicture(props) {
|
|||||||
|
|
||||||
if (croppedSize < 150) {
|
if (croppedSize < 150) {
|
||||||
setImage({ loading: false, file: null, data: null });
|
setImage({ loading: false, file: null, data: null });
|
||||||
showDialog(L("account.profile_picture_invalid_dimensions"), L("general.error"));
|
showDialog(L("account.profile_picture_invalid_dimensions"), L("general.error_occurred"));
|
||||||
} else {
|
} else {
|
||||||
setImage({ loading: false, file: file, data: imageData });
|
setImage({ loading: false, file: file, data: imageData });
|
||||||
}
|
}
|
||||||
|
@ -7,17 +7,28 @@ import {
|
|||||||
CircularProgress,
|
CircularProgress,
|
||||||
FormControl,
|
FormControl,
|
||||||
FormControlLabel,
|
FormControlLabel,
|
||||||
FormLabel,
|
FormLabel, Grid,
|
||||||
TextField
|
TextField,
|
||||||
|
FormGroup as MuiFormGroup
|
||||||
} from "@mui/material";
|
} from "@mui/material";
|
||||||
import {LocaleContext} from "shared/locale";
|
import {LocaleContext} from "shared/locale";
|
||||||
import * as React from "react";
|
import * as React from "react";
|
||||||
import ViewContent from "../../elements/view-content";
|
import ViewContent from "../../elements/view-content";
|
||||||
import FormGroup from "../../elements/form-group";
|
import FormGroup from "../../elements/form-group";
|
||||||
import ButtonBar from "../../elements/button-bar";
|
import ButtonBar from "../../elements/button-bar";
|
||||||
import {RestartAlt, Save} from "@mui/icons-material";
|
import {RestartAlt, Save, Send} from "@mui/icons-material";
|
||||||
import {parseBool} from "shared/util";
|
import PasswordStrength from "shared/elements/password-strength";
|
||||||
import SpacedFormGroup from "../../elements/form-group";
|
|
||||||
|
const initialUser = {
|
||||||
|
name: "",
|
||||||
|
fullName: "",
|
||||||
|
email: "",
|
||||||
|
password: "",
|
||||||
|
passwordConfirm: "",
|
||||||
|
groups: [],
|
||||||
|
confirmed: false,
|
||||||
|
active: true,
|
||||||
|
};
|
||||||
|
|
||||||
export default function UserEditView(props) {
|
export default function UserEditView(props) {
|
||||||
|
|
||||||
@ -30,19 +41,12 @@ export default function UserEditView(props) {
|
|||||||
const isNewUser = userId === "new";
|
const isNewUser = userId === "new";
|
||||||
const {translate: L, requestModules, currentLocale} = useContext(LocaleContext);
|
const {translate: L, requestModules, currentLocale} = useContext(LocaleContext);
|
||||||
const [fetchUser, setFetchUser] = useState(!isNewUser);
|
const [fetchUser, setFetchUser] = useState(!isNewUser);
|
||||||
const [user, setUser] = useState(isNewUser ? {
|
const [user, setUser] = useState(isNewUser ? initialUser : null);
|
||||||
name: "",
|
|
||||||
fullName: "",
|
|
||||||
email: "",
|
|
||||||
password: "",
|
|
||||||
groups: [],
|
|
||||||
confirmed: false,
|
|
||||||
active: true,
|
|
||||||
} : null);
|
|
||||||
|
|
||||||
// ui
|
// ui
|
||||||
const [hasChanged, setChanged] = useState(isNewUser);
|
const [hasChanged, setChanged] = useState(isNewUser);
|
||||||
const [isSaving, setSaving] = useState(false);
|
const [isSaving, setSaving] = useState(false);
|
||||||
|
const [sendInvite, setSetInvite] = useState(isNewUser);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
requestModules(props.api, ["general", "account"], currentLocale).then(data => {
|
requestModules(props.api, ["general", "account"], currentLocale).then(data => {
|
||||||
@ -52,14 +56,6 @@ export default function UserEditView(props) {
|
|||||||
});
|
});
|
||||||
}, [currentLocale]);
|
}, [currentLocale]);
|
||||||
|
|
||||||
const onReset = useCallback(() => {
|
|
||||||
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
const onSaveUser = useCallback(() => {
|
|
||||||
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
const onFetchUser = useCallback((force = false) => {
|
const onFetchUser = useCallback((force = false) => {
|
||||||
if (!isNewUser && (force || fetchUser)) {
|
if (!isNewUser && (force || fetchUser)) {
|
||||||
setFetchUser(false);
|
setFetchUser(false);
|
||||||
@ -76,9 +72,60 @@ export default function UserEditView(props) {
|
|||||||
}
|
}
|
||||||
}, [api, showDialog, fetchUser, isNewUser, userId, user]);
|
}, [api, showDialog, fetchUser, isNewUser, userId, user]);
|
||||||
|
|
||||||
const onChangeValue = useCallback((name, value) => {
|
const onReset = useCallback(() => {
|
||||||
|
if (isNewUser) {
|
||||||
|
setUser({...initialUser});
|
||||||
|
} else {
|
||||||
|
onFetchUser(true);
|
||||||
|
}
|
||||||
|
}, [isNewUser, onFetchUser]);
|
||||||
|
|
||||||
}, []);
|
const onSaveUser = useCallback(() => {
|
||||||
|
if (!isSaving) {
|
||||||
|
setSaving(true);
|
||||||
|
if (isNewUser) {
|
||||||
|
if (sendInvite) {
|
||||||
|
api.inviteUser(user.name, user.fullName, user.email).then(res => {
|
||||||
|
setSaving(false);
|
||||||
|
if (res.success) {
|
||||||
|
setChanged(false);
|
||||||
|
navigate("/admin/user/" + res.userId);
|
||||||
|
} else {
|
||||||
|
showDialog(res.msg, L("account.invite_user_error"));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
api.createUser(user.name, user.fullName, user.email, user.password, user.passwordConfirm).then(res => {
|
||||||
|
setSaving(false);
|
||||||
|
if (res.success) {
|
||||||
|
setChanged(false);
|
||||||
|
navigate("/admin/user/" + res.userId);
|
||||||
|
} else {
|
||||||
|
showDialog(res.msg, L("account.create_user_error"));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
api.editUser(
|
||||||
|
userId, user.name, user.email, user.password,
|
||||||
|
user.groups, user.confirmed, user.active
|
||||||
|
).then(res => {
|
||||||
|
setSaving(false);
|
||||||
|
if (res.success) {
|
||||||
|
setChanged(false);
|
||||||
|
} else {
|
||||||
|
showDialog(res.msg, L("account.save_user_error"));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}, [isSaving, sendInvite, isNewUser, userId, showDialog]);
|
||||||
|
|
||||||
|
const onChangeValue = useCallback((name, value) => {
|
||||||
|
setUser({...user, [name]: value});
|
||||||
|
setChanged(true);
|
||||||
|
}, [user]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!isNewUser) {
|
if (!isNewUser) {
|
||||||
@ -95,7 +142,8 @@ export default function UserEditView(props) {
|
|||||||
<Link key={"users"} to={"/admin/users"}>User</Link>,
|
<Link key={"users"} to={"/admin/users"}>User</Link>,
|
||||||
<span key={"action"}>{isNewUser ? "New" : "Edit"}</span>
|
<span key={"action"}>{isNewUser ? "New" : "Edit"}</span>
|
||||||
]}>
|
]}>
|
||||||
<Box>
|
<Grid container>
|
||||||
|
<Grid item xs={12} lg={6}>
|
||||||
<FormGroup>
|
<FormGroup>
|
||||||
<FormLabel>{L("account.name")}</FormLabel>
|
<FormLabel>{L("account.name")}</FormLabel>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
@ -124,12 +172,22 @@ export default function UserEditView(props) {
|
|||||||
{ !isNewUser ?
|
{ !isNewUser ?
|
||||||
<>
|
<>
|
||||||
<FormGroup>
|
<FormGroup>
|
||||||
|
<FormLabel>{L("account.password")}</FormLabel>
|
||||||
|
<FormControl>
|
||||||
|
<TextField size={"small"} variant={"outlined"}
|
||||||
|
value={user.password}
|
||||||
|
type={"password"}
|
||||||
|
placeholder={"(" + L("general.unchanged") + ")"}
|
||||||
|
onChange={e => setUser({...user, password: e.target.value})} />
|
||||||
|
</FormControl>
|
||||||
|
</FormGroup>
|
||||||
|
<MuiFormGroup>
|
||||||
<FormControlLabel
|
<FormControlLabel
|
||||||
control={<Checkbox
|
control={<Checkbox
|
||||||
checked={!!user.active}
|
checked={!!user.active}
|
||||||
onChange={(e, v) => onChangeValue("active", v)} />}
|
onChange={(e, v) => onChangeValue("active", v)} />}
|
||||||
label={L("account.active")} />
|
label={L("account.active")} />
|
||||||
</FormGroup>
|
</MuiFormGroup>
|
||||||
<FormGroup>
|
<FormGroup>
|
||||||
<FormControlLabel
|
<FormControlLabel
|
||||||
control={<Checkbox
|
control={<Checkbox
|
||||||
@ -138,18 +196,52 @@ export default function UserEditView(props) {
|
|||||||
label={L("account.confirmed")} />
|
label={L("account.confirmed")} />
|
||||||
</FormGroup>
|
</FormGroup>
|
||||||
</> : <>
|
</> : <>
|
||||||
|
<FormGroup>
|
||||||
|
<FormControlLabel
|
||||||
|
control={<Checkbox
|
||||||
|
checked={sendInvite}
|
||||||
|
onChange={(e, v) => setSetInvite(v)} />}
|
||||||
|
label={L("account.send_invite")} />
|
||||||
|
</FormGroup>
|
||||||
|
{!sendInvite && <>
|
||||||
|
<FormGroup>
|
||||||
|
<FormLabel>{L("account.password")}</FormLabel>
|
||||||
|
<FormControl>
|
||||||
|
<TextField size={"small"} variant={"outlined"}
|
||||||
|
value={user.password}
|
||||||
|
type={"password"}
|
||||||
|
onChange={e => setUser({...user, password: e.target.value})} />
|
||||||
|
</FormControl>
|
||||||
|
</FormGroup>
|
||||||
|
<FormGroup>
|
||||||
|
<FormLabel>{L("account.password_confirm")}</FormLabel>
|
||||||
|
<FormControl>
|
||||||
|
<TextField size={"small"} variant={"outlined"}
|
||||||
|
value={user.passwordConfirm}
|
||||||
|
type={"password"}
|
||||||
|
onChange={e => setUser({...user, passwordConfirm: e.target.value})} />
|
||||||
|
</FormControl>
|
||||||
|
</FormGroup>
|
||||||
|
<Box mb={2}>
|
||||||
|
<PasswordStrength password={user.password} />
|
||||||
|
</Box>
|
||||||
</>
|
</>
|
||||||
}
|
}
|
||||||
</Box>
|
</>
|
||||||
|
}
|
||||||
|
</Grid>
|
||||||
|
</Grid>
|
||||||
<ButtonBar>
|
<ButtonBar>
|
||||||
<Button color={"primary"}
|
<Button color={"primary"}
|
||||||
onClick={onSaveUser}
|
onClick={onSaveUser}
|
||||||
disabled={isSaving || !(isNewUser ? api.hasPermission("user/create") : api.hasPermission("user/edit"))}
|
disabled={isSaving || !(isNewUser ? api.hasPermission("user/create") : api.hasPermission("user/edit"))}
|
||||||
startIcon={isSaving ? <CircularProgress size={14} /> : <Save />}
|
startIcon={isSaving ?
|
||||||
|
<CircularProgress size={14} /> :
|
||||||
|
(sendInvite ? <Send /> : <Save /> )}
|
||||||
variant={"outlined"} title={L(hasChanged ? "general.unsaved_changes" : "general.save")}>
|
variant={"outlined"} title={L(hasChanged ? "general.unsaved_changes" : "general.save")}>
|
||||||
{isSaving ? L("general.saving") + "…" : (L("general.save") + (hasChanged ? " *" : ""))}
|
{isSaving ?
|
||||||
|
L(sendInvite ? "general.sending" : "general.saving") + "…" :
|
||||||
|
(L(sendInvite ? "general.send" : "general.save") + (hasChanged ? " *" : ""))}
|
||||||
</Button>
|
</Button>
|
||||||
<Button color={"error"}
|
<Button color={"error"}
|
||||||
onClick={onReset}
|
onClick={onReset}
|
||||||
|
@ -127,10 +127,11 @@ export default class API {
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
async editUser(id, username, email, password, groups, confirmed) {
|
async editUser(id, username, email, password, groups, confirmed, active) {
|
||||||
return this.apiCall("user/edit", {
|
return this.apiCall("user/edit", {
|
||||||
id: id, username: username, email: email,
|
id: id, username: username, email: email,
|
||||||
password: password, groups: groups, confirmed: confirmed
|
password: password, groups: groups,
|
||||||
|
confirmed: confirmed, active: active
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -158,12 +159,15 @@ export default class API {
|
|||||||
return this.apiCall("user/fetch", { page: pageNum, count: count, orderBy: orderBy, sortOrder: sortOrder });
|
return this.apiCall("user/fetch", { page: pageNum, count: count, orderBy: orderBy, sortOrder: sortOrder });
|
||||||
}
|
}
|
||||||
|
|
||||||
async inviteUser(username, email) {
|
async inviteUser(username, fullName, email) {
|
||||||
return this.apiCall("user/invite", { username: username, email: email });
|
return this.apiCall("user/invite", { username: username, fullName: fullName, email: email });
|
||||||
}
|
}
|
||||||
|
|
||||||
async createUser(username, email, password, confirmPassword) {
|
async createUser(username, fullName, email, password, confirmPassword) {
|
||||||
return this.apiCall("user/create", { username: username, email: email, password: password, confirmPassword: confirmPassword });
|
return this.apiCall("user/create", { username: username, email: email,
|
||||||
|
fullName: fullName,
|
||||||
|
password: password, confirmPassword: confirmPassword
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async searchUser(query) {
|
async searchUser(query) {
|
||||||
|
Loading…
Reference in New Issue
Block a user