allow admin to see all users even not self created, admin can delete admin accounts
This commit is contained in:
parent
edb30286fa
commit
3a5c203664
|
|
@ -498,6 +498,20 @@ public class Controller : ControllerBase
|
||||||
.ToList();
|
.ToList();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[HttpGet(nameof(GetAllUsers))]
|
||||||
|
public ActionResult<IEnumerable<User>> GetAllUsers(Token authToken)
|
||||||
|
{
|
||||||
|
var user = Db.GetSession(authToken)?.User;
|
||||||
|
if (user == null)
|
||||||
|
return Unauthorized();
|
||||||
|
if (user.UserType != 2) // admins only
|
||||||
|
return Unauthorized();
|
||||||
|
|
||||||
|
return Db.Users
|
||||||
|
.Select(u => u.HidePassword())
|
||||||
|
.ToList();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
[HttpGet(nameof(GetAllInstallationsFromProduct))]
|
[HttpGet(nameof(GetAllInstallationsFromProduct))]
|
||||||
public ActionResult<IEnumerable<Installation>> GetAllInstallationsFromProduct(int product,Token authToken)
|
public ActionResult<IEnumerable<Installation>> GetAllInstallationsFromProduct(int product,Token authToken)
|
||||||
|
|
|
||||||
|
|
@ -368,11 +368,16 @@ public static class SessionMethods
|
||||||
var sessionUser = session?.User;
|
var sessionUser = session?.User;
|
||||||
var originalUser = Db.GetUserById(editedUser?.Id);
|
var originalUser = Db.GetUserById(editedUser?.Id);
|
||||||
|
|
||||||
return editedUser is not null
|
if (editedUser is null || sessionUser is null || originalUser is null)
|
||||||
&& sessionUser is not null
|
return false;
|
||||||
&& originalUser is not null
|
|
||||||
&& sessionUser.UserType !=0
|
// email must stay unique; pre-check to avoid hitting the DB [Unique] constraint (500)
|
||||||
&& sessionUser.HasAccessTo(originalUser)
|
var emailOwner = Db.GetUserByEmail(editedUser.Email);
|
||||||
|
|
||||||
|
return sessionUser.UserType != 0
|
||||||
|
&& originalUser.Id != 0 // never edit the root user
|
||||||
|
&& (sessionUser.UserType == 2 || sessionUser.HasAccessTo(originalUser)) // admins may edit any user
|
||||||
|
&& (emailOwner is null || emailOwner.Id == editedUser.Id) // email not taken by another user
|
||||||
&& editedUser
|
&& editedUser
|
||||||
.WithParentOf(originalUser) // prevent moving
|
.WithParentOf(originalUser) // prevent moving
|
||||||
.WithPasswordOf(originalUser)
|
.WithPasswordOf(originalUser)
|
||||||
|
|
@ -397,7 +402,9 @@ public static class SessionMethods
|
||||||
return sessionUser is not null
|
return sessionUser is not null
|
||||||
&& userToDelete is not null
|
&& userToDelete is not null
|
||||||
&& sessionUser.UserType !=0
|
&& sessionUser.UserType !=0
|
||||||
&& sessionUser.HasAccessTo(userToDelete)
|
&& userToDelete.Id != 0 // never delete the root user
|
||||||
|
&& userToDelete.Id != sessionUser.Id // never self-delete (avoid lockout)
|
||||||
|
&& (sessionUser.UserType == 2 || sessionUser.HasAccessTo(userToDelete)) // admins may delete any user
|
||||||
&& Db.Delete(userToDelete);
|
&& Db.Delete(userToDelete);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -164,8 +164,18 @@ public static partial class Db
|
||||||
|
|
||||||
Boolean DeleteUserAndHisDependencies()
|
Boolean DeleteUserAndHisDependencies()
|
||||||
{
|
{
|
||||||
|
// Re-parent the deleted user's children up to its own parent so no subtree is orphaned
|
||||||
|
// (a dangling ParentId would make the children invisible/unmanageable in the tree).
|
||||||
|
var children = Users.Where(u => u.ParentId == user.Id).ToList();
|
||||||
|
foreach (var child in children)
|
||||||
|
{
|
||||||
|
child.ParentId = user.ParentId;
|
||||||
|
Connection.Update(child);
|
||||||
|
}
|
||||||
|
|
||||||
FolderAccess .Delete(u => u.UserId == user.Id);
|
FolderAccess .Delete(u => u.UserId == user.Id);
|
||||||
InstallationAccess.Delete(u => u.UserId == user.Id);
|
InstallationAccess.Delete(u => u.UserId == user.Id);
|
||||||
|
Sessions .Delete(s => s.UserId == user.Id); // kill the deleted user's login sessions immediately
|
||||||
return Users.Delete(u => u.Id == user.Id) > 0;
|
return Users.Delete(u => u.Id == user.Id) > 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -20,8 +20,8 @@ import { UserType } from '../../../interfaces/UserTypes';
|
||||||
function UsersSearch() {
|
function UsersSearch() {
|
||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
const [searchTerm, setSearchTerm] = useState('');
|
const [searchTerm, setSearchTerm] = useState('');
|
||||||
const { availableUsers, fetchAvailableUsers } = useContext(AccessContext);
|
const { allUsers, fetchAllUsers } = useContext(AccessContext);
|
||||||
const [filteredData, setFilteredData] = useState(availableUsers);
|
const [filteredData, setFilteredData] = useState(allUsers);
|
||||||
const [openModal, setOpenModal] = useState(false);
|
const [openModal, setOpenModal] = useState(false);
|
||||||
const context = useContext(UserContext);
|
const context = useContext(UserContext);
|
||||||
const [userCreated, setUserCreated] = useState(false);
|
const [userCreated, setUserCreated] = useState(false);
|
||||||
|
|
@ -29,19 +29,19 @@ function UsersSearch() {
|
||||||
const { currentUser } = context;
|
const { currentUser } = context;
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
fetchAvailableUsers();
|
fetchAllUsers();
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const fetchDataAgain = () => {
|
const fetchDataAgain = () => {
|
||||||
fetchAvailableUsers();
|
fetchAllUsers();
|
||||||
};
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const filtered = availableUsers.filter((item) =>
|
const filtered = allUsers.filter((item) =>
|
||||||
item.name.toLowerCase().includes(searchTerm.toLowerCase())
|
item.name.toLowerCase().includes(searchTerm.toLowerCase())
|
||||||
);
|
);
|
||||||
setFilteredData(filtered);
|
setFilteredData(filtered);
|
||||||
}, [searchTerm, availableUsers]);
|
}, [searchTerm, allUsers]);
|
||||||
|
|
||||||
const handleSubmit = () => {
|
const handleSubmit = () => {
|
||||||
setOpenModal(true);
|
setOpenModal(true);
|
||||||
|
|
@ -50,7 +50,7 @@ function UsersSearch() {
|
||||||
setOpenModal(false);
|
setOpenModal(false);
|
||||||
setUserCreated(true);
|
setUserCreated(true);
|
||||||
|
|
||||||
fetchAvailableUsers();
|
fetchAllUsers();
|
||||||
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
setUserCreated(false);
|
setUserCreated(false);
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,8 @@ interface AccessContextProviderProps {
|
||||||
accessibleInstallationsForUser: I_Installation[];
|
accessibleInstallationsForUser: I_Installation[];
|
||||||
availableUsers: InnovEnergyUser[];
|
availableUsers: InnovEnergyUser[];
|
||||||
fetchAvailableUsers: () => Promise<void>;
|
fetchAvailableUsers: () => Promise<void>;
|
||||||
|
allUsers: InnovEnergyUser[];
|
||||||
|
fetchAllUsers: () => Promise<void>;
|
||||||
usersWithDirectAccess: InnovEnergyUser[];
|
usersWithDirectAccess: InnovEnergyUser[];
|
||||||
fetchUsersWithDirectAccessForResource: (
|
fetchUsersWithDirectAccessForResource: (
|
||||||
tempresourceType: string,
|
tempresourceType: string,
|
||||||
|
|
@ -53,6 +55,10 @@ export const AccessContext = createContext<AccessContextProviderProps>({
|
||||||
fetchAvailableUsers: () => {
|
fetchAvailableUsers: () => {
|
||||||
return Promise.resolve();
|
return Promise.resolve();
|
||||||
},
|
},
|
||||||
|
allUsers: [],
|
||||||
|
fetchAllUsers: () => {
|
||||||
|
return Promise.resolve();
|
||||||
|
},
|
||||||
usersWithDirectAccess: [],
|
usersWithDirectAccess: [],
|
||||||
fetchUsersWithDirectAccessForResource: () => Promise.resolve(),
|
fetchUsersWithDirectAccessForResource: () => Promise.resolve(),
|
||||||
usersWithInheritedAccess: [],
|
usersWithInheritedAccess: [],
|
||||||
|
|
@ -80,6 +86,7 @@ const AccessContextProvider = ({ children }: { children: ReactNode }) => {
|
||||||
InnovEnergyUser[]
|
InnovEnergyUser[]
|
||||||
>([]);
|
>([]);
|
||||||
const [availableUsers, setAvailableUsers] = useState<InnovEnergyUser[]>([]);
|
const [availableUsers, setAvailableUsers] = useState<InnovEnergyUser[]>([]);
|
||||||
|
const [allUsers, setAllUsers] = useState<InnovEnergyUser[]>([]);
|
||||||
const [accessibleInstallationsForUser, setAccessibleInstallationsForUser] =
|
const [accessibleInstallationsForUser, setAccessibleInstallationsForUser] =
|
||||||
useState<I_Installation[]>([]);
|
useState<I_Installation[]>([]);
|
||||||
|
|
||||||
|
|
@ -141,6 +148,13 @@ const AccessContextProvider = ({ children }: { children: ReactNode }) => {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Admin-only: every user in the system (for the Users management page).
|
||||||
|
const fetchAllUsers = async (): Promise<void> => {
|
||||||
|
return axiosConfig.get('/GetAllUsers').then((res) => {
|
||||||
|
setAllUsers(res.data);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
const RevokeAccessFromResource = useCallback(
|
const RevokeAccessFromResource = useCallback(
|
||||||
async (
|
async (
|
||||||
resourceType: string,
|
resourceType: string,
|
||||||
|
|
@ -187,6 +201,8 @@ const AccessContextProvider = ({ children }: { children: ReactNode }) => {
|
||||||
accessibleInstallationsForUser,
|
accessibleInstallationsForUser,
|
||||||
availableUsers,
|
availableUsers,
|
||||||
fetchAvailableUsers,
|
fetchAvailableUsers,
|
||||||
|
allUsers,
|
||||||
|
fetchAllUsers,
|
||||||
usersWithDirectAccess,
|
usersWithDirectAccess,
|
||||||
fetchUsersWithDirectAccessForResource,
|
fetchUsersWithDirectAccessForResource,
|
||||||
usersWithInheritedAccess,
|
usersWithInheritedAccess,
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue