From ba03f92a94aa804574edc29f6ca4e77f629f09c8 Mon Sep 17 00:00:00 2001 From: xilef45 <88111260+xilef45@users.noreply.github.com> Date: Mon, 9 Jan 2023 10:07:55 +0100 Subject: [PATCH 01/23] add backend routes for delete and edit --- .../Deskstar/Controllers/UserController.cs | 114 +++++++++++++++++- .../Deskstar/Usecases/UserUsecases.cs | 77 +++++++++++- 2 files changed, 184 insertions(+), 7 deletions(-) diff --git a/src/deskstar-backend/Deskstar/Controllers/UserController.cs b/src/deskstar-backend/Deskstar/Controllers/UserController.cs index 477faee5..c5e7601b 100644 --- a/src/deskstar-backend/Deskstar/Controllers/UserController.cs +++ b/src/deskstar-backend/Deskstar/Controllers/UserController.cs @@ -13,17 +13,18 @@ namespace Deskstar.Controllers; [Produces("application/json")] public class UserController : ControllerBase { - private readonly IUserUsecases _userUsecases; private readonly ILogger _logger; private readonly IAutoMapperConfiguration _autoMapperConfiguration; - public UserController(ILogger logger, IUserUsecases userUsecases, IAutoMapperConfiguration autoMapperConfiguration) + public UserController(ILogger logger, IUserUsecases userUsecases, + IAutoMapperConfiguration autoMapperConfiguration) { _logger = logger; _userUsecases = userUsecases; _autoMapperConfiguration = autoMapperConfiguration; } + /// /// Returns all users for a specific company /// @@ -65,6 +66,7 @@ public IActionResult Get() return Problem(statusCode: 500); } } + /// /// Returns user specific information /// @@ -212,6 +214,7 @@ public IActionResult DeclineUser(string userId) return Problem(statusCode: 500); } } + /// /// Update user information /// @@ -232,14 +235,13 @@ public IActionResult DeclineUser(string userId) public IActionResult UpdateUser(UserProfileDto userDto) { var userId = RequestInteractions.ExtractIdFromRequest(Request); - try { var mapper = _autoMapperConfiguration.GetConfiguration().CreateMapper(); var user = mapper.Map(userDto); + + _userUsecases.UpdateUser(userId, user); - _userUsecases.UpdateUser(user); - return Ok(); } catch (EntityNotFoundException e) @@ -253,4 +255,106 @@ public IActionResult UpdateUser(UserProfileDto userDto) return Problem(statusCode: 500); } } + + /// + /// Update given user information + /// + /// empty response + /// + /// Sample request: + /// Post /edit + /// + /// + /// Empty Response + /// Bad Request + /// Forbid + /// Not Found + /// Internal Server Error + [HttpPost("edit")] + [Authorize(Policy = "Admin")] + [ProducesResponseType(typeof(void), StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status403Forbidden)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + public IActionResult UpdateGivenUser(UserProfileDto userDto) + { + var adminId = RequestInteractions.ExtractIdFromRequest(Request); + try + { + var mapper = _autoMapperConfiguration.GetConfiguration().CreateMapper(); + var user = mapper.Map(userDto); + _userUsecases.UpdateUser(adminId,user); + return Ok(); + } + catch (ArgumentInvalidException e) + { + _logger.LogError(e, e.Message); + return BadRequest(e.Message); + } + catch (InsufficientPermissionException e) + { + _logger.LogError(e, e.Message); + return Forbid(e.Message); + } + catch (EntityNotFoundException e) + { + _logger.LogError(e, e.Message); + return NotFound(e.Message); + } + catch (Exception e) + { + _logger.LogError(e, e.Message); + return Problem(statusCode: 500); + } + } + + /// + /// Delete given user + /// + /// empty response + /// + /// Sample request: + /// Post /delete/{userId} + /// + /// + /// Empty Response + /// Not Found + /// Internal Server Error + [HttpPost("/delete/{userId}")] + [Authorize(Policy = "Admin")] + [ProducesResponseType(typeof(void), StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status403Forbidden)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + public IActionResult DeleteGivenUser(string userId) + { + var adminId = RequestInteractions.ExtractIdFromRequest(Request); + try + { + _userUsecases.DeleteUser(adminId, userId); + return Ok(); + } + catch (ArgumentInvalidException e) + { + _logger.LogError(e, e.Message); + return BadRequest(e.Message); + } + catch (InsufficientPermissionException e) + { + _logger.LogError(e, e.Message); + return Forbid(e.Message); + } + catch (EntityNotFoundException e) + { + _logger.LogError(e, e.Message); + return NotFound(e.Message); + } + catch (Exception e) + { + _logger.LogError(e, e.Message); + return Problem(statusCode: 500); + } + } } \ No newline at end of file diff --git a/src/deskstar-backend/Deskstar/Usecases/UserUsecases.cs b/src/deskstar-backend/Deskstar/Usecases/UserUsecases.cs index 5a480bb8..8e2a7ad2 100644 --- a/src/deskstar-backend/Deskstar/Usecases/UserUsecases.cs +++ b/src/deskstar-backend/Deskstar/Usecases/UserUsecases.cs @@ -8,10 +8,13 @@ namespace Deskstar.Usecases; public interface IUserUsecases { public List ReadAllUsers(Guid adminId); - public Guid UpdateUser(User user); public User ReadSpecificUser(Guid userId); + + public Guid UpdateUser(string requestUserId, User user); public Guid ApproveUser(Guid adminId, string userId); public Guid DeclineUser(Guid adminId, string userId); + public Guid UpdateUser(Guid adminId, User user); + public Guid DeleteUser(Guid adminId, string userId); } public class UserUsecases : IUserUsecases @@ -100,13 +103,83 @@ public List ReadAllUsers(Guid adminId) return _context.Users.Where(user => user.CompanyId == admin.CompanyId).ToList(); } - public Guid UpdateUser(User user) + + public Guid UpdateUser(string requestUserId, User user) + { + Guid guid; + try + { + guid = new Guid(requestUserId); + } + catch (Exception e) when (e is FormatException or ArgumentNullException or OverflowException) + { + _logger.LogError(e, e.Message); + throw new ArgumentInvalidException($"'{requestUserId}' is not a valid UserId"); + } + + if (!guid.Equals(user.UserId)) + { + throw new ArgumentInvalidException($"'{requestUserId}' is not equals with given userObject"); + } + + return SaveUpdateUser(user); + } + + public Guid UpdateUser(Guid adminId, User user) + { + var userDbInstance = _context.Users.SingleOrDefault(u => u.UserId == user.UserId); + if (userDbInstance == null) + throw new EntityNotFoundException($"There is no user with id '{user.UserId}'"); + CheckSameCompany(adminId,user.UserId); + return SaveUpdateUser(user); + } + private Guid SaveUpdateUser( User user) { var userDbInstance = _context.Users.SingleOrDefault(u => u.UserId == user.UserId); if (userDbInstance == null) throw new EntityNotFoundException($"There is no user with id '{user.UserId}'"); _context.Users.Update(user); _context.SaveChanges(); + //ToDo: uncomment + var body = $"Hello {user.FirstName},
" + + "your account details have been updated.
" + + "Please check if this was ok.
"+ + "If not get in touch with your company admin.
" + + "
" + + "Regards,
" + + "Deskstar Team"; + //EmailHelper.SendEmail(_logger, user.MailAddress, "Your Deskstar account details have been updated!", body); return user.UserId; } + + public Guid DeleteUser(Guid adminId,string userId) + { + Guid guid; + try + { + guid = new Guid(userId); + } + catch (Exception e) when (e is FormatException or ArgumentNullException or OverflowException) + { + _logger.LogError(e, e.Message); + throw new ArgumentInvalidException($"'{userId}' is not a valid UserId"); + } + + var userDbInstance = _context.Users.SingleOrDefault(u => u.UserId == guid); + if (userDbInstance == null) + throw new EntityNotFoundException($"There is no user with id '{userId}'"); + CheckSameCompany(adminId,guid); + var body = $"Hello {userDbInstance.FirstName},
" + + "your account has been releted by your Company admin.
" + + "If you think this was an mistake, get in touch with your company admin.
" + + "
" + + "Regards,
" + + "Deskstar Team"; + //ToDo: uncomment + //EmailHelper.SendEmail(_logger, user.MailAddress, "Your Deskstar account details have been updated!", body); + _context.Users.Remove(userDbInstance); + _context.SaveChanges(); + + return guid; + } } \ No newline at end of file From e02bb19a5eb12923ebdcd45236424bfeec2047cb Mon Sep 17 00:00:00 2001 From: xilef45 <88111260+xilef45@users.noreply.github.com> Date: Mon, 9 Jan 2023 11:20:27 +0100 Subject: [PATCH 02/23] added tests --- .../Deskstar/Usecases/UserUsecases.cs | 1 - .../Teststar.Tests/Tests/UserUsecasesTests.cs | 66 ++++++++++++++++++- 2 files changed, 64 insertions(+), 3 deletions(-) diff --git a/src/deskstar-backend/Deskstar/Usecases/UserUsecases.cs b/src/deskstar-backend/Deskstar/Usecases/UserUsecases.cs index 8e2a7ad2..09ae2a27 100644 --- a/src/deskstar-backend/Deskstar/Usecases/UserUsecases.cs +++ b/src/deskstar-backend/Deskstar/Usecases/UserUsecases.cs @@ -102,7 +102,6 @@ public List ReadAllUsers(Guid adminId) throw new EntityNotFoundException($"There is no admin with id '{adminId}'"); return _context.Users.Where(user => user.CompanyId == admin.CompanyId).ToList(); } - public Guid UpdateUser(string requestUserId, User user) { diff --git a/src/deskstar-backend/Teststar.Tests/Tests/UserUsecasesTests.cs b/src/deskstar-backend/Teststar.Tests/Tests/UserUsecasesTests.cs index 6bd2c618..b3f6267a 100644 --- a/src/deskstar-backend/Teststar.Tests/Tests/UserUsecasesTests.cs +++ b/src/deskstar-backend/Teststar.Tests/Tests/UserUsecasesTests.cs @@ -234,7 +234,7 @@ public void UpdateUser_WhenValidUserIsProvided_ShouldUpdateUser() var userUsecases = new UserUsecases(logger.Object, db); //act - var result = userUsecases.UpdateUser(user); + var result = userUsecases.UpdateUser(user.UserId,user); //assert Assert.That(result == user.UserId); @@ -255,9 +255,31 @@ public void UpdateUser_WhenInvalidUserIsProvided_ShouldThrowEntityNotFoundExcept var userUsecases = new UserUsecases(logger.Object, db); //act + assert - Assert.Throws(() => userUsecases.UpdateUser(new User())); + Assert.Throws(() => userUsecases.UpdateUser(new Guid(),new User())); } + [Test] + public void UpdateUser_AsAdmin_WhenValidUserIsProvided_ShouldUpdateUser() + { + //setup + using var db = new DataContext(); + User user, admin; + bool isUserApproved = true; + + SetupSingleUser(db, isUserApproved, out user, out admin); + + //arrange + var logger = new Mock>(); + var userUsecases = new UserUsecases(logger.Object, db); + + //act + var result = userUsecases.UpdateUser(admin.UserId,user); + + //assert + Assert.That(result == user.UserId); + + } + [Test] public void ReadAllUsers_WhenValidUserIdIsProvided_ShouldReturnListOfAllUsersInTheSameCompany() { @@ -298,6 +320,46 @@ public void ReadAllUsers_WhenInvalidUserIdIsProvided_ShouldThrowEntityNotFoundEx Assert.Throws(() => userUsecases.ReadAllUsers(new Guid())); } + + [Test] + public void DeleteUser_WhenValidUserIsProvided_ShouldUpdateUser() + { + //setup + using var db = new DataContext(); + User user, admin; + const bool isUserApproved = true; + + SetupSingleUser(db, isUserApproved, out user, out admin); + + //arrange + var logger = new Mock>(); + var userUsecases = new UserUsecases(logger.Object, db); + + //act + var result = userUsecases.DeleteUser(admin.UserId,user.UserId.ToString()); + + //assert + Assert.That(result, Is.EqualTo(user.UserId)); + Assert.That(!db.Users.Any(u => u.UserId==user.UserId)); + + } + [Test] + public void DeleteUser_WhenNonValidUserIsProvided_ShouldUpdateUser() + { + //setup + using var db = new DataContext(); + User user, admin; + const bool isUserApproved = true; + + SetupSingleUser(db, isUserApproved, out user, out admin); + + //arrange + var logger = new Mock>(); + var userUsecases = new UserUsecases(logger.Object, db); + + //assert + Assert.Throws(() => userUsecases.DeleteUser(admin.UserId,Guid.NewGuid().ToString())); + } private void SetupSingleUser(DataContext db, bool userApproved, out User user, out User admin) { From 2d8544b6d4229584142128e193d7a18e229b8389 Mon Sep 17 00:00:00 2001 From: xilef45 <88111260+xilef45@users.noreply.github.com> Date: Mon, 9 Jan 2023 12:01:47 +0100 Subject: [PATCH 03/23] added frontend --- .../Deskstar/Controllers/UserController.cs | 2 +- src/deskstar-frontend/lib/api/UserService.ts | 26 +++++++++++ src/deskstar-frontend/pages/users/index.tsx | 44 +++++++++++++++---- 3 files changed, 62 insertions(+), 10 deletions(-) diff --git a/src/deskstar-backend/Deskstar/Controllers/UserController.cs b/src/deskstar-backend/Deskstar/Controllers/UserController.cs index c5e7601b..01f2e266 100644 --- a/src/deskstar-backend/Deskstar/Controllers/UserController.cs +++ b/src/deskstar-backend/Deskstar/Controllers/UserController.cs @@ -321,7 +321,7 @@ public IActionResult UpdateGivenUser(UserProfileDto userDto) /// Empty Response /// Not Found /// Internal Server Error - [HttpPost("/delete/{userId}")] + [HttpDelete("/delete/{userId}")] [Authorize(Policy = "Admin")] [ProducesResponseType(typeof(void), StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status400BadRequest)] diff --git a/src/deskstar-frontend/lib/api/UserService.ts b/src/deskstar-frontend/lib/api/UserService.ts index 6100e1d1..275e4aac 100644 --- a/src/deskstar-frontend/lib/api/UserService.ts +++ b/src/deskstar-frontend/lib/api/UserService.ts @@ -54,6 +54,32 @@ export function declineUser( }); } +export function deleteUser( + session: Session, + userId: string +): Promise { + return fetch(BACKEND_URL + `/users/delete/${userId}`, { + method: "DELETE", + headers: { + Authorization: `Bearer ${session.accessToken}`, + }, + }); +} + +export function editUser( + session: Session, + user: IUser + ): Promise { + return fetch(BACKEND_URL + `/users/edit`, { + method: "POST", + headers: { + Authorization: `Bearer ${session.accessToken}`, + "Content-Type": "application/json", + }, + body: JSON.stringify(user) + }); +} + type UserResponse = { userId: string; firstName: string; diff --git a/src/deskstar-frontend/pages/users/index.tsx b/src/deskstar-frontend/pages/users/index.tsx index 6fd4d5d4..64c7fffb 100644 --- a/src/deskstar-frontend/pages/users/index.tsx +++ b/src/deskstar-frontend/pages/users/index.tsx @@ -5,12 +5,12 @@ import { IUser } from "../../types/users"; import { useSession } from "next-auth/react"; import { useRouter } from "next/router"; import { useState, useEffect } from "react"; -import { getUsers } from "../../lib/api/UserService"; +import { getUsers, deleteUser, editUser } from "../../lib/api/UserService"; import { authOptions } from "../api/auth/[...nextauth]"; import { unstable_getServerSession } from "next-auth"; export default function UsersOverview({ users }: { users: IUser[] }) { - const { data: session } = useSession(); + let { data: session } = useSession(); const [calledRouter, setCalledRouter] = useState(false); const router = useRouter(); @@ -26,6 +26,10 @@ export default function UsersOverview({ users }: { users: IUser[] }) { } }, [router, session, calledRouter]); + if (session == null) { + return; + } + const onPermissionUpdate = async (user: IUser): Promise => { //TODO: Implement if (user.isAdmin) console.log(`Demoting user ${user.userId}...`); @@ -37,16 +41,15 @@ export default function UsersOverview({ users }: { users: IUser[] }) { console.log(`Editing user ${user.userId}...`); }; - const onDelete = async (user: IUser): Promise => { - //TODO: Implement + async function onDelete(user: IUser) { + //Show aller + } + const doDelete = async (user: IUser) => { console.log(`Deleting user ${user.userId}...`); + if (session == null) return; + deleteUser(session, user.userId); }; - if (!session?.user?.isAdmin) { - //TODO: Add loading animation - return
Loading...
; - } - return ( <> @@ -59,6 +62,29 @@ export default function UsersOverview({ users }: { users: IUser[] }) { onEdit={onEdit} onDelete={onDelete} /> +
+
+ + + + Warning: This can't be undone! +
+ +
+
+
); } From 1042e2a821c90a1bc503c660976c217365367a10 Mon Sep 17 00:00:00 2001 From: xilef45 <88111260+xilef45@users.noreply.github.com> Date: Mon, 9 Jan 2023 12:18:13 +0100 Subject: [PATCH 04/23] fix git attributes --- .gitattributes | 1 + src/deskstar-frontend/pages/users/index.tsx | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) create mode 100644 .gitattributes diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 00000000..94f480de --- /dev/null +++ b/.gitattributes @@ -0,0 +1 @@ +* text=auto eol=lf \ No newline at end of file diff --git a/src/deskstar-frontend/pages/users/index.tsx b/src/deskstar-frontend/pages/users/index.tsx index 64c7fffb..c78a02bb 100644 --- a/src/deskstar-frontend/pages/users/index.tsx +++ b/src/deskstar-frontend/pages/users/index.tsx @@ -77,7 +77,7 @@ export default function UsersOverview({ users }: { users: IUser[] }) { d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z" /> - Warning: This can't be undone! + Warning: This can't be undone!
+ + + + + ) +} \ No newline at end of file diff --git a/src/deskstar-frontend/components/EditUserModal.tsx b/src/deskstar-frontend/components/EditUserModal.tsx new file mode 100644 index 00000000..69de112a --- /dev/null +++ b/src/deskstar-frontend/components/EditUserModal.tsx @@ -0,0 +1,41 @@ +import { useState } from 'react'; +import { Dialog } from '@headlessui/react'; +import {IUser} from "../types/users"; +import Input from "./forms/Input"; + +import React from 'react'; + +export default function EditUserModal({ + user, + action, + }: { + user: IUser; + action: Function; + }) { + let [isOpen, setIsOpen] = useState(true) + + const [firstName, setFirstName] = useState(""); + const [lastName, setLastName] = useState(""); + const [email, setEmail] = useState(""); + + return ( + setIsOpen(false)}> + + Edit {user.firstName} {user.lastName} +
+
+ { setFirstName(e.target.value) }} value={user.firstName} placeholder="first name" /> + { setLastName(e.target.value) }} value={user.lastName} placeholder="last name" /> +
+
+
+ { setEmail(e.target.value) }} value={user.firstName} placeholder="E-Mail" /> + +
+
+ + +
+
+ ) +} \ No newline at end of file diff --git a/src/deskstar-frontend/pages/users/index.tsx b/src/deskstar-frontend/pages/users/index.tsx index c78a02bb..37191864 100644 --- a/src/deskstar-frontend/pages/users/index.tsx +++ b/src/deskstar-frontend/pages/users/index.tsx @@ -8,11 +8,16 @@ import { useState, useEffect } from "react"; import { getUsers, deleteUser, editUser } from "../../lib/api/UserService"; import { authOptions } from "../api/auth/[...nextauth]"; import { unstable_getServerSession } from "next-auth"; +import ConfirmModal from "../../components/ConfirmModal"; +import EditUserModal from "../../components/EditUserModal"; + export default function UsersOverview({ users }: { users: IUser[] }) { let { data: session } = useSession(); const [calledRouter, setCalledRouter] = useState(false); const router = useRouter(); + + const [user, setUser] = useState(); // page is only accessable as admin useEffect(() => { @@ -39,6 +44,7 @@ export default function UsersOverview({ users }: { users: IUser[] }) { const onEdit = async (user: IUser): Promise => { //TODO: Implement console.log(`Editing user ${user.userId}...`); + setUser(user); }; async function onDelete(user: IUser) { @@ -49,6 +55,10 @@ export default function UsersOverview({ users }: { users: IUser[] }) { if (session == null) return; deleteUser(session, user.userId); }; + const saveEdit= async (user:IUser)=>{ + console.log(`Edit user ${user.userId}...`); + //send edit + } return ( <> @@ -62,29 +72,8 @@ export default function UsersOverview({ users }: { users: IUser[] }) { onEdit={onEdit} onDelete={onDelete} /> -
-
- - - - Warning: This can't be undone! -
- -
-
-
+ + {/**/} ); } From c8a2cd9efc31492f54badf965479d07f3dc1051a Mon Sep 17 00:00:00 2001 From: Moritz Reich Date: Mon, 9 Jan 2023 15:31:06 +0000 Subject: [PATCH 06/23] optimized design and modal Signed-off-by: Moritz Reich --- .../components/ConfirmModal.tsx | 112 ++++++++++++------ src/deskstar-frontend/pages/users/index.tsx | 41 +++++-- 2 files changed, 102 insertions(+), 51 deletions(-) diff --git a/src/deskstar-frontend/components/ConfirmModal.tsx b/src/deskstar-frontend/components/ConfirmModal.tsx index 3c8d7777..89df2f9b 100644 --- a/src/deskstar-frontend/components/ConfirmModal.tsx +++ b/src/deskstar-frontend/components/ConfirmModal.tsx @@ -1,44 +1,80 @@ -import { useState } from 'react'; -import { Dialog } from '@headlessui/react'; -import React from 'react'; +import { useState } from "react"; +import { Dialog } from "@headlessui/react"; +import React from "react"; export default function ConfirmModal({ - title, - description, - text, - warn, - buttonText, - action - }: { - title: string; - description: string; - text: string; - warn: boolean; - buttonText: string; - action: Function; - }) { - let [isOpen, setIsOpen] = useState(true); - let buttonClass=""; - if( warn) - buttonClass+="btn-warning"; + title, + description, + text, + warn, + buttonText, + action, + isOpen, + setIsOpen, +}: { + title: string; + description: string; + text: string; + warn: boolean; + buttonText: string; + action: () => void; + isOpen: boolean; + setIsOpen: (isOpen: boolean) => void; +}) { + let buttonClass = "btn "; + if (warn) buttonClass += "btn-warning"; return ( setIsOpen(false)}> - - {title} - - {description} - -

- {warn&&( - - )} - {text} -

- - - -
+
- ) -} \ No newline at end of file + ); +} diff --git a/src/deskstar-frontend/pages/users/index.tsx b/src/deskstar-frontend/pages/users/index.tsx index 37191864..a1df0e48 100644 --- a/src/deskstar-frontend/pages/users/index.tsx +++ b/src/deskstar-frontend/pages/users/index.tsx @@ -8,17 +8,18 @@ import { useState, useEffect } from "react"; import { getUsers, deleteUser, editUser } from "../../lib/api/UserService"; import { authOptions } from "../api/auth/[...nextauth]"; import { unstable_getServerSession } from "next-auth"; -import ConfirmModal from "../../components/ConfirmModal"; -import EditUserModal from "../../components/EditUserModal"; - +import ConfirmModal from "../../components/ConfirmModal"; +import EditUserModal from "../../components/EditUserModal"; export default function UsersOverview({ users }: { users: IUser[] }) { let { data: session } = useSession(); const [calledRouter, setCalledRouter] = useState(false); const router = useRouter(); - + const [user, setUser] = useState(); + const [isDeleteUserModalOpen, setDeleteUserModalOpen] = useState(false); + // page is only accessable as admin useEffect(() => { if (!calledRouter && session && !session?.user.isAdmin) { @@ -47,18 +48,23 @@ export default function UsersOverview({ users }: { users: IUser[] }) { setUser(user); }; + async function doDelete() { + if (user) { + console.log(`Deleting user ${user.userId}...`); + if (session == null) return; + deleteUser(session, user.userId); + } + } + async function onDelete(user: IUser) { - //Show aller + setUser(user); + setDeleteUserModalOpen(true); } - const doDelete = async (user: IUser) => { - console.log(`Deleting user ${user.userId}...`); - if (session == null) return; - deleteUser(session, user.userId); - }; - const saveEdit= async (user:IUser)=>{ + + const saveEdit = async (user: IUser) => { console.log(`Edit user ${user.userId}...`); //send edit - } + }; return ( <> @@ -72,7 +78,16 @@ export default function UsersOverview({ users }: { users: IUser[] }) { onEdit={onEdit} onDelete={onDelete} /> - + {/**/} ); From c5d934bf1743a860ed2de5300139ca1c12569d4e Mon Sep 17 00:00:00 2001 From: Moritz Reich Date: Mon, 9 Jan 2023 15:32:16 +0000 Subject: [PATCH 07/23] fixed crlf error in devcontainer Signed-off-by: Moritz Reich --- .devcontainer/devcontainer.json | 1 + 1 file changed, 1 insertion(+) diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 34e603fe..4672f8be 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -29,6 +29,7 @@ // Use 'postCreateCommand' to run commands after the container is created. "postCreateCommand": "dotnet tool install --global dotnet-ef", + "postStartCommand": "git config core.autocrlf true", "remoteEnv": { "PATH": "${containerEnv:PATH}:/home/vscode/.dotnet/tools" } From 79a48e40f63f7f30f86d98bc5be279268089b164 Mon Sep 17 00:00:00 2001 From: xilef45 <88111260+xilef45@users.noreply.github.com> Date: Tue, 10 Jan 2023 09:24:40 +0100 Subject: [PATCH 08/23] fix issues --- .../Deskstar/Controllers/UserController.cs | 2 +- .../components/ConfirmModal.tsx | 71 ++++++++++--------- src/deskstar-frontend/pages/users/index.tsx | 3 + 3 files changed, 41 insertions(+), 35 deletions(-) diff --git a/src/deskstar-backend/Deskstar/Controllers/UserController.cs b/src/deskstar-backend/Deskstar/Controllers/UserController.cs index 01f2e266..27b5f7ca 100644 --- a/src/deskstar-backend/Deskstar/Controllers/UserController.cs +++ b/src/deskstar-backend/Deskstar/Controllers/UserController.cs @@ -321,7 +321,7 @@ public IActionResult UpdateGivenUser(UserProfileDto userDto) /// Empty Response /// Not Found /// Internal Server Error - [HttpDelete("/delete/{userId}")] + [HttpDelete("delete/{userId}")] [Authorize(Policy = "Admin")] [ProducesResponseType(typeof(void), StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status400BadRequest)] diff --git a/src/deskstar-frontend/components/ConfirmModal.tsx b/src/deskstar-frontend/components/ConfirmModal.tsx index 89df2f9b..4369bc3e 100644 --- a/src/deskstar-frontend/components/ConfirmModal.tsx +++ b/src/deskstar-frontend/components/ConfirmModal.tsx @@ -33,43 +33,46 @@ export default function ConfirmModal({ >
-

{title}

- - {warn && ( - - - - )} +
+

{title}

+ {warn && ( + + + + )} +
-

{description}

- -

{text}

- -
- +
+
+

{description}

+

{text}

+
+
+ - + +
diff --git a/src/deskstar-frontend/pages/users/index.tsx b/src/deskstar-frontend/pages/users/index.tsx index a1df0e48..47ad4cb7 100644 --- a/src/deskstar-frontend/pages/users/index.tsx +++ b/src/deskstar-frontend/pages/users/index.tsx @@ -13,6 +13,7 @@ import EditUserModal from "../../components/EditUserModal"; export default function UsersOverview({ users }: { users: IUser[] }) { let { data: session } = useSession(); + const [calledRouter, setCalledRouter] = useState(false); const router = useRouter(); @@ -54,6 +55,8 @@ export default function UsersOverview({ users }: { users: IUser[] }) { if (session == null) return; deleteUser(session, user.userId); } + // reload page + router.reload(); } async function onDelete(user: IUser) { From 4074c6cd122451952d38866423082566936f871e Mon Sep 17 00:00:00 2001 From: xilef45 <88111260+xilef45@users.noreply.github.com> Date: Tue, 10 Jan 2023 10:37:14 +0100 Subject: [PATCH 09/23] ui fixes --- .../components/EditUserModal.tsx | 112 +++++++++++++----- .../components/forms/Input.tsx | 2 +- src/deskstar-frontend/pages/users/index.tsx | 32 +++-- 3 files changed, 102 insertions(+), 44 deletions(-) diff --git a/src/deskstar-frontend/components/EditUserModal.tsx b/src/deskstar-frontend/components/EditUserModal.tsx index 69de112a..a64cbce3 100644 --- a/src/deskstar-frontend/components/EditUserModal.tsx +++ b/src/deskstar-frontend/components/EditUserModal.tsx @@ -1,41 +1,91 @@ -import { useState } from 'react'; -import { Dialog } from '@headlessui/react'; -import {IUser} from "../types/users"; +import { useState } from "react"; +import { Dialog } from "@headlessui/react"; +import { IUser } from "../types/users"; import Input from "./forms/Input"; - -import React from 'react'; +import React from "react"; export default function EditUserModal({ - user, - action, - }: { - user: IUser; - action: Function; - }) { - let [isOpen, setIsOpen] = useState(true) - + user, + action, + isOpen, + setIsOpen, +}: { + user?: IUser; + action: Function; + isOpen: boolean; + setIsOpen: (isOpen: boolean) => void; +}) { const [firstName, setFirstName] = useState(""); const [lastName, setLastName] = useState(""); const [email, setEmail] = useState(""); return ( setIsOpen(false)}> - - Edit {user.firstName} {user.lastName} -
-
- { setFirstName(e.target.value) }} value={user.firstName} placeholder="first name" /> - { setLastName(e.target.value) }} value={user.lastName} placeholder="last name" /> -
-
-
- { setEmail(e.target.value) }} value={user.firstName} placeholder="E-Mail" /> - -
-
- - -
+
- ) -} \ No newline at end of file + ); +} diff --git a/src/deskstar-frontend/components/forms/Input.tsx b/src/deskstar-frontend/components/forms/Input.tsx index b5d16647..e6aab785 100644 --- a/src/deskstar-frontend/components/forms/Input.tsx +++ b/src/deskstar-frontend/components/forms/Input.tsx @@ -5,7 +5,7 @@ type InputProps = { onChange: (event: React.ChangeEvent) => void; value: string; className?: string; - placeholder: string; + placeholder?: string; type?: string; }; diff --git a/src/deskstar-frontend/pages/users/index.tsx b/src/deskstar-frontend/pages/users/index.tsx index 47ad4cb7..9aef9c7d 100644 --- a/src/deskstar-frontend/pages/users/index.tsx +++ b/src/deskstar-frontend/pages/users/index.tsx @@ -20,6 +20,7 @@ export default function UsersOverview({ users }: { users: IUser[] }) { const [user, setUser] = useState(); const [isDeleteUserModalOpen, setDeleteUserModalOpen] = useState(false); + const [isEditUserModalOpen, setEditUserModalOpen] = useState(false); // page is only accessable as admin useEffect(() => { @@ -44,11 +45,15 @@ export default function UsersOverview({ users }: { users: IUser[] }) { }; const onEdit = async (user: IUser): Promise => { - //TODO: Implement - console.log(`Editing user ${user.userId}...`); setUser(user); + setEditUserModalOpen(true); }; + async function onDelete(user: IUser): Promise { + setUser(user); + setDeleteUserModalOpen(true); + } + async function doDelete() { if (user) { console.log(`Deleting user ${user.userId}...`); @@ -59,16 +64,14 @@ export default function UsersOverview({ users }: { users: IUser[] }) { router.reload(); } - async function onDelete(user: IUser) { - setUser(user); - setDeleteUserModalOpen(true); + async function doEdit() { + if (user) { + console.log(`Edit user ${user.userId}...`); + if (session == null) return; + editUser(session, user); + } } - const saveEdit = async (user: IUser) => { - console.log(`Edit user ${user.userId}...`); - //send edit - }; - return ( <> @@ -82,7 +85,7 @@ export default function UsersOverview({ users }: { users: IUser[] }) { onDelete={onDelete} /> - {/**/} + ); } From 90d833c9aa83c478207fd4d493c6d458062e788d Mon Sep 17 00:00:00 2001 From: Moritz Reich Date: Wed, 11 Jan 2023 11:34:26 +0000 Subject: [PATCH 10/23] changed to lf --- src/deskstar-backend/Deskstar/Controllers/UserController.cs | 0 src/deskstar-frontend/components/ConfirmModal.tsx | 0 src/deskstar-frontend/components/EditUserModal.tsx | 0 src/deskstar-frontend/components/forms/Input.tsx | 0 src/deskstar-frontend/pages/users/index.tsx | 0 5 files changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 src/deskstar-backend/Deskstar/Controllers/UserController.cs mode change 100644 => 100755 src/deskstar-frontend/components/ConfirmModal.tsx mode change 100644 => 100755 src/deskstar-frontend/components/EditUserModal.tsx mode change 100644 => 100755 src/deskstar-frontend/components/forms/Input.tsx mode change 100644 => 100755 src/deskstar-frontend/pages/users/index.tsx diff --git a/src/deskstar-backend/Deskstar/Controllers/UserController.cs b/src/deskstar-backend/Deskstar/Controllers/UserController.cs old mode 100644 new mode 100755 diff --git a/src/deskstar-frontend/components/ConfirmModal.tsx b/src/deskstar-frontend/components/ConfirmModal.tsx old mode 100644 new mode 100755 diff --git a/src/deskstar-frontend/components/EditUserModal.tsx b/src/deskstar-frontend/components/EditUserModal.tsx old mode 100644 new mode 100755 diff --git a/src/deskstar-frontend/components/forms/Input.tsx b/src/deskstar-frontend/components/forms/Input.tsx old mode 100644 new mode 100755 diff --git a/src/deskstar-frontend/pages/users/index.tsx b/src/deskstar-frontend/pages/users/index.tsx old mode 100644 new mode 100755 From 954742f2c0076f2b3bed187b3554622b387752fa Mon Sep 17 00:00:00 2001 From: Moritz Reich Date: Wed, 11 Jan 2023 12:25:55 +0000 Subject: [PATCH 11/23] fixed delete user Signed-off-by: Moritz Reich --- src/deskstar-frontend/components/ConfirmModal.tsx | 4 ++-- src/deskstar-frontend/lib/api/UserService.ts | 9 +++------ src/deskstar-frontend/pages/users/index.tsx | 6 +++--- 3 files changed, 8 insertions(+), 11 deletions(-) diff --git a/src/deskstar-frontend/components/ConfirmModal.tsx b/src/deskstar-frontend/components/ConfirmModal.tsx index 4369bc3e..5b0d0f8f 100755 --- a/src/deskstar-frontend/components/ConfirmModal.tsx +++ b/src/deskstar-frontend/components/ConfirmModal.tsx @@ -32,7 +32,7 @@ export default function ConfirmModal({ className={"card bg-white dark:bg-gray-300 dark:text-black w-96"} >
- +

{title}

{warn && ( @@ -52,7 +52,7 @@ export default function ConfirmModal({ )}
- +

{description}

diff --git a/src/deskstar-frontend/lib/api/UserService.ts b/src/deskstar-frontend/lib/api/UserService.ts index 275e4aac..cdf7f459 100644 --- a/src/deskstar-frontend/lib/api/UserService.ts +++ b/src/deskstar-frontend/lib/api/UserService.ts @@ -54,7 +54,7 @@ export function declineUser( }); } -export function deleteUser( +export async function deleteUser( session: Session, userId: string ): Promise { @@ -66,17 +66,14 @@ export function deleteUser( }); } -export function editUser( - session: Session, - user: IUser - ): Promise { +export function editUser(session: Session, user: IUser): Promise { return fetch(BACKEND_URL + `/users/edit`, { method: "POST", headers: { Authorization: `Bearer ${session.accessToken}`, "Content-Type": "application/json", }, - body: JSON.stringify(user) + body: JSON.stringify(user), }); } diff --git a/src/deskstar-frontend/pages/users/index.tsx b/src/deskstar-frontend/pages/users/index.tsx index 9aef9c7d..d65e1dd9 100755 --- a/src/deskstar-frontend/pages/users/index.tsx +++ b/src/deskstar-frontend/pages/users/index.tsx @@ -58,10 +58,10 @@ export default function UsersOverview({ users }: { users: IUser[] }) { if (user) { console.log(`Deleting user ${user.userId}...`); if (session == null) return; - deleteUser(session, user.userId); + await deleteUser(session, user.userId); + // reload page + router.reload(); } - // reload page - router.reload(); } async function doEdit() { From 8ae9171b6b10e47d4199e8913b9fe5807d71018b Mon Sep 17 00:00:00 2001 From: Moritz Reich Date: Wed, 11 Jan 2023 12:33:48 +0000 Subject: [PATCH 12/23] update for the devcontainer to fix the permission issues Signed-off-by: Moritz Reich --- .devcontainer/devcontainer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 4672f8be..3ed5f7b8 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -29,7 +29,7 @@ // Use 'postCreateCommand' to run commands after the container is created. "postCreateCommand": "dotnet tool install --global dotnet-ef", - "postStartCommand": "git config core.autocrlf true", + "postStartCommand": "git config core.autocrlf true && git config core.filemode false", "remoteEnv": { "PATH": "${containerEnv:PATH}:/home/vscode/.dotnet/tools" } From c2c4fac0f0f2dcc3118dc436c71e06e4d436a7bd Mon Sep 17 00:00:00 2001 From: xilef45 <88111260+xilef45@users.noreply.github.com> Date: Wed, 11 Jan 2023 13:59:11 +0100 Subject: [PATCH 13/23] ui fixes Co-Authored-By: Fiona <55480320+Faoilthiama@users.noreply.github.com> --- .../Deskstar/Usecases/UserUsecases.cs | 30 +++++++++---------- .../components/EditUserModal.tsx | 5 ++-- src/deskstar-frontend/pages/users/index.tsx | 2 +- src/deskstar-frontend/yarn.lock | 12 ++++++++ 4 files changed, 30 insertions(+), 19 deletions(-) diff --git a/src/deskstar-backend/Deskstar/Usecases/UserUsecases.cs b/src/deskstar-backend/Deskstar/Usecases/UserUsecases.cs index cedd1861..3ee6f4a4 100644 --- a/src/deskstar-backend/Deskstar/Usecases/UserUsecases.cs +++ b/src/deskstar-backend/Deskstar/Usecases/UserUsecases.cs @@ -19,7 +19,7 @@ public interface IUserUsecases { public List ReadAllUsers(Guid adminId); public User ReadSpecificUser(Guid userId); - + public Guid UpdateUser(string requestUserId, User user); public Guid ApproveUser(Guid adminId, string userId); public Guid DeclineUser(Guid adminId, string userId); @@ -129,7 +129,7 @@ public List ReadAllUsers(Guid adminId) throw new EntityNotFoundException($"There is no admin with id '{adminId}'"); return _context.Users.Where(user => user.CompanyId == admin.CompanyId).ToList(); } - + public Guid UpdateUser(string requestUserId, User user) { Guid guid; @@ -147,38 +147,37 @@ public Guid UpdateUser(string requestUserId, User user) { throw new ArgumentInvalidException($"'{requestUserId}' is not equals with given userObject"); } - + return SaveUpdateUser(user); } - + public Guid UpdateUser(Guid adminId, User user) { var userDbInstance = _context.Users.SingleOrDefault(u => u.UserId == user.UserId); if (userDbInstance == null) throw new EntityNotFoundException($"There is no user with id '{user.UserId}'"); - CheckSameCompany(adminId,user.UserId); + CheckSameCompany(adminId, user.UserId); return SaveUpdateUser(user); } - private Guid SaveUpdateUser( User user) + private Guid SaveUpdateUser(User user) { var userDbInstance = _context.Users.SingleOrDefault(u => u.UserId == user.UserId); if (userDbInstance == null) throw new EntityNotFoundException($"There is no user with id '{user.UserId}'"); _context.Users.Update(user); _context.SaveChanges(); - //ToDo: uncomment var body = $"Hello {user.FirstName},
" + "your account details have been updated.
" + - "Please check if this was ok.
"+ + "Please check if this was ok.
" + "If not get in touch with your company admin.
" + "
" + "Regards,
" + "Deskstar Team"; - //EmailHelper.SendEmail(_logger, user.MailAddress, "Your Deskstar account details have been updated!", body); + EmailHelper.SendEmail(_logger, user.MailAddress, "Your Deskstar account details have been updated!", body); return user.UserId; } - - public Guid DeleteUser(Guid adminId,string userId) + + public Guid DeleteUser(Guid adminId, string userId) { Guid guid; try @@ -190,22 +189,21 @@ public Guid DeleteUser(Guid adminId,string userId) _logger.LogError(e, e.Message); throw new ArgumentInvalidException($"'{userId}' is not a valid UserId"); } - + var userDbInstance = _context.Users.SingleOrDefault(u => u.UserId == guid); if (userDbInstance == null) throw new EntityNotFoundException($"There is no user with id '{userId}'"); - CheckSameCompany(adminId,guid); + CheckSameCompany(adminId, guid); var body = $"Hello {userDbInstance.FirstName},
" + "your account has been releted by your Company admin.
" + "If you think this was an mistake, get in touch with your company admin.
" + "
" + "Regards,
" + "Deskstar Team"; - //ToDo: uncomment - //EmailHelper.SendEmail(_logger, user.MailAddress, "Your Deskstar account details have been updated!", body); + EmailHelper.SendEmail(_logger, user.MailAddress, "Your Deskstar account details have been updated!", body); _context.Users.Remove(userDbInstance); _context.SaveChanges(); - + return guid; } } \ No newline at end of file diff --git a/src/deskstar-frontend/components/EditUserModal.tsx b/src/deskstar-frontend/components/EditUserModal.tsx index a64cbce3..9ab40771 100755 --- a/src/deskstar-frontend/components/EditUserModal.tsx +++ b/src/deskstar-frontend/components/EditUserModal.tsx @@ -24,15 +24,16 @@ export default function EditUserModal({