post User by secretary
This commit is contained in:
		| @ -75,6 +75,7 @@ public class ApplicationsController { | ||||
|             authorizedApps.add(Applications.StudentsList);} | ||||
|  | ||||
|         if (!authServ.isNotIn(new Role[]{Role.Secretary,Role.Admin},token)){ | ||||
|             authorizedApps.add(Applications.CreateUser); | ||||
|           authorizedApps.add(Applications.UsersList);} | ||||
|  | ||||
|         if (researchesServ.getResearcherByUser(user) != null) | ||||
|  | ||||
| @ -86,19 +86,20 @@ public class UserController { | ||||
|      * @return a string clarifying the issue (if there is any) | ||||
|      */ | ||||
|     @PatchMapping("/user/{id}") | ||||
|     public ResponseEntity<String> patchUser(@RequestHeader("Authorization") String token, | ||||
|     public ResponseEntity<Map<String,Object>> patchUser(@RequestHeader("Authorization") String token, | ||||
|                                             @RequestBody Map<String,Object> updates, | ||||
|                                             @PathVariable Long id) { | ||||
|  | ||||
|         if (token == null) return new UnauthorizedResponse<>(null); | ||||
|  | ||||
|         User poster = authServ.getUserFromToken(token); | ||||
|         if (poster == null) {return new UnauthorizedResponse<>("bad token");} | ||||
|         if (poster == null) {return new UnauthorizedResponse<>(null);} | ||||
|  | ||||
|         if (!userService.modifyData(id, updates, poster)) | ||||
|         User modified = userService.modifyData(id,updates,poster); | ||||
|         if (modified ==null) | ||||
|             return new ResponseEntity<>(HttpStatus.BAD_REQUEST); | ||||
|  | ||||
|         return new ResponseEntity<>(null, HttpStatus.OK); | ||||
|         return new ResponseEntity<>(ProtectionService.userWithoutPassword(modified), HttpStatus.OK); | ||||
|     } | ||||
|  | ||||
|     @GetMapping("/teachers") | ||||
|  | ||||
| @ -43,61 +43,55 @@ public class UserService { | ||||
|      * @param targetId the id of the user to update | ||||
|      * @return if the changes were done or not | ||||
|      */ | ||||
|     public boolean modifyData(long targetId, Map<String ,Object> updates, User poster){ | ||||
|     public User modifyData(long targetId, Map<String ,Object> updates, User poster){ | ||||
|  | ||||
|         User target = userRepo.findById(targetId); | ||||
|         if (target == null) | ||||
|             return false; | ||||
|             return null; | ||||
|  | ||||
|         if (poster.getRegNo().equals(target.getRegNo())){ | ||||
|             for (Map.Entry<String, Object> entry : updates.entrySet()){ | ||||
|         if (!target.getRegNo().equals(poster.getRegNo()) && !(poster.getRole() == Role.Secretary) && | ||||
|             !(poster.getRole() == Role.Admin)) | ||||
|             return null; | ||||
|  | ||||
|                 switch (entry.getKey()){ | ||||
|                     case "firstName": | ||||
|                         target.setFirstName((String) entry.getValue()); | ||||
|                         break; | ||||
|                     case "lastName": | ||||
|                         target.setLastName((String) entry.getValue()); | ||||
|                         break; | ||||
|                     case "email": | ||||
|                         target.setEmail((String) entry.getValue()); | ||||
|                         break; | ||||
|                     case "address": | ||||
|                         target.setAddress((String) entry.getValue()); | ||||
|                         break; | ||||
|                     case "country": | ||||
|                         target.setCountry((String) entry.getValue()); | ||||
|                         break; | ||||
|                     case "birthDate": | ||||
|                         target.setBirthDate((Date) entry.getValue()); | ||||
|                         break; | ||||
|                     case "profilePictureUrl": | ||||
|                         target.setProfilePictureUrl((String) entry.getValue()); | ||||
|                         break; | ||||
|                     case "password": | ||||
|                         target.setPassword(passwordEncoder.encode((String) entry.getValue())); | ||||
|                         break; | ||||
|                 } | ||||
|             } | ||||
|             userRepo.save(target); | ||||
|             return true; | ||||
|         } | ||||
|         // the secretary can change roles (for example if a student becomes a teacher) | ||||
|         else if (poster.getRole() == Role.Secretary) | ||||
|         { | ||||
|             for (Map.Entry<String, Object> entry : updates.entrySet()){ | ||||
|  | ||||
|                 if ( entry.getKey().equals("role")) { | ||||
|  | ||||
|                     if (entry.getValue() == Role.Admin) {return false;} | ||||
|  | ||||
|                     target.setRole((Role) entry.getValue()); | ||||
|                     userRepo.save(target); | ||||
|                     return true; | ||||
|                 } | ||||
|         for (Map.Entry<String, Object> entry : updates.entrySet()){ | ||||
|             System.out.println(entry.getValue()); | ||||
|             switch (entry.getKey()){ | ||||
|                 case "firstName": | ||||
|                     target.setFirstName((String) entry.getValue()); | ||||
|                     break; | ||||
|                 case "lastName": | ||||
|                     target.setLastName((String) entry.getValue()); | ||||
|                     break; | ||||
|                 case "email": | ||||
|                     target.setEmail((String) entry.getValue()); | ||||
|                     break; | ||||
|                 case "address": | ||||
|                     target.setAddress((String) entry.getValue()); | ||||
|                     break; | ||||
|                 case "country": | ||||
|                     target.setCountry((String) entry.getValue()); | ||||
|                     break; | ||||
|                 case "birthDate": | ||||
|                     target.setBirthDate((Date) entry.getValue()); | ||||
|                     break; | ||||
|                 case "profilePictureUrl": | ||||
|                     target.setProfilePictureUrl((String) entry.getValue()); | ||||
|                     break; | ||||
|                 case "password": | ||||
|                     target.setPassword((String) entry.getValue()); | ||||
|                     break; | ||||
|                 case "role": | ||||
|                     //a user can't change his own role | ||||
|                     if (poster.getRole()==Role.Secretary || poster.getRole() == Role.Admin){ | ||||
|                         Role wanted = Role.valueOf((String) entry.getValue()); | ||||
|                         if (wanted == Role.Admin && poster.getRole() != Role.Admin) | ||||
|                             return null; | ||||
|                         target.setRole(wanted); | ||||
|                     } | ||||
|             } | ||||
|         } | ||||
|         return false; | ||||
|         userRepo.save(target); | ||||
|         return target; | ||||
|     } | ||||
|  | ||||
|  | ||||
| @ -105,7 +99,7 @@ public class UserService { | ||||
|         return passwordEncoder.matches(tryingPassword,  user.getPassword()); | ||||
|     } | ||||
|  | ||||
|     public User save(User  user){ | ||||
|     public User save(User user){ | ||||
|         user.setPassword(passwordEncoder.encode(user.getPassword())); | ||||
|         return userRepo.save(user); | ||||
|     } | ||||
|  | ||||
| @ -23,5 +23,5 @@ public enum Applications { | ||||
|     ManageResearcherProfile, | ||||
|  | ||||
|     //the list of all researches (filterable) | ||||
|     ListResearches, StudentsList | ||||
|     ListResearches, CreateUser, StudentsList | ||||
| } | ||||
|  | ||||
| @ -30,6 +30,7 @@ app.studentList=Students List | ||||
| app.users=Users | ||||
| app.manage.researcherProfile=Manage researcher profile | ||||
| app.list.researches=List researches | ||||
| app.Create.User=Create User | ||||
| request.moreInfos=More Infos | ||||
| request.accept=Accept | ||||
| request.refuse=Refuse | ||||
| @ -123,3 +124,9 @@ Researcher.Delete=Delete Researcher Profile | ||||
| Researcher.Add=Create Researcher Profile | ||||
| Confirm=Confirm | ||||
| Cancel=Cancel | ||||
| LastName=Last Name | ||||
| FirstName=First Name | ||||
| Profile.Picture=Profile Picture | ||||
| Role=Role | ||||
| Password=Password | ||||
| Create.User=Create User | ||||
|  | ||||
| @ -30,6 +30,7 @@ app.studentList=Liste des étudiants | ||||
| app.users=Utilisateurs | ||||
| app.manage.researcherProfile= gérer son profil de chercheur | ||||
| app.list.researches=Lister les recherches | ||||
| app.Create.User=créer un utilisateur | ||||
| request.moreInfos=Plus d'Infos | ||||
| request.accept=Accepter | ||||
| request.refuse=Refuser | ||||
| @ -121,3 +122,9 @@ Country=Pays | ||||
| BirthDate=Date de Naissance | ||||
| Confirm=Confirmer | ||||
| Cancel=Annuler | ||||
| LastName=Nom de Famille | ||||
| FirstName=Prénom | ||||
| Profile.Picture=Photo de Profil | ||||
| Role=Role | ||||
| Password=Mot de Passe | ||||
| Create.User=Créer l'utilisateur | ||||
|  | ||||
| @ -3,36 +3,37 @@ import i18n from "../i18n.js"; | ||||
| import {ref} from "vue"; | ||||
| import {fetchAllResearchers} from "@/rest/ScientificPublications/ManageResearch.js"; | ||||
| import {deleteResearcher, postResearcher} from "@/rest/ScientificPublications/ResearcherProfile.js"; | ||||
| import {patchUser} from "@/rest/Users.js"; | ||||
| const props = defineProps(['user']) | ||||
| const modifying =ref(false) | ||||
| const toModify = Object.assign({},{}) | ||||
| const toCreate = Object.assign({},{}) | ||||
| const allResearcher = ref( await fetchAllResearchers()) | ||||
| const researcher = ref() | ||||
| const user = props.user | ||||
| const user = ref(props.user) | ||||
| const isResearcher = ref(false) | ||||
| const creating = ref(false) | ||||
|  | ||||
| for (let i = 0; i < allResearcher.value.length; i++) { | ||||
|   if (user.regNo === allResearcher.value[i].user.regNo){ | ||||
|   if (user.value.regNo === allResearcher.value[i].user.regNo){ | ||||
|     researcher.value = allResearcher.value[i] | ||||
|     isResearcher.value = true | ||||
|   } | ||||
| } | ||||
|  | ||||
| function getPP(){ | ||||
|   if(user.profilePictureUrl === null){ | ||||
|   if(user.value.profilePictureUrl === null){ | ||||
|     return "/Clyde.png" | ||||
|   } | ||||
|   return user.profilePictureUrl | ||||
|   return user.value.profilePictureUrl | ||||
| } | ||||
|  | ||||
| async function createResearcher(){ | ||||
|   toCreate.user = user | ||||
|   toCreate.user = user.value | ||||
|   await postResearcher(toCreate) | ||||
|   creating.value = false | ||||
|   for (let i = 0; i < allResearcher.value.length; i++) { | ||||
|     if (user.regNo === allResearcher.value[i].user.regNo){ | ||||
|     if (user.value.regNo === allResearcher.value[i].user.regNo){ | ||||
|       researcher.value = allResearcher.value[i] | ||||
|       isResearcher.value = true | ||||
|     } | ||||
| @ -46,6 +47,13 @@ async function deleteResearcherById(){ | ||||
|   allResearcher.value = await fetchAllResearchers() | ||||
| } | ||||
|  | ||||
| async function modify(){ | ||||
|   if (modifying.value){ | ||||
|     user.value = await patchUser(user.value.regNo, toModify) | ||||
|   } | ||||
|   modifying.value =!modifying.value | ||||
| } | ||||
|  | ||||
| </script> | ||||
|  | ||||
| <template> | ||||
| @ -89,7 +97,7 @@ async function deleteResearcherById(){ | ||||
|         </div> | ||||
|       </div> | ||||
|       <div></div> | ||||
|       <button id="ModifyButton" @click="modifying= !modifying"> {{i18n("Modify.Data")}}</button> | ||||
|       <button id="ModifyButton" @click="modify"> {{i18n("Modify.Data")}}</button> | ||||
|       <div></div> | ||||
|       <div> | ||||
|         <button v-if="isResearcher" id="deleteButton" @click="deleteResearcherById"> {{i18n("Researcher.Delete")}}</button> | ||||
| @ -111,8 +119,6 @@ async function deleteResearcherById(){ | ||||
|             {{i18n("Domain")}} : | ||||
|             <input type="text" v-model="toCreate.domain"></li> | ||||
|         </ul> | ||||
|  | ||||
|  | ||||
|       </div> | ||||
|     </div> | ||||
|   </div> | ||||
| @ -133,6 +139,7 @@ async function deleteResearcherById(){ | ||||
| } | ||||
|  | ||||
| .container{ | ||||
|   margin-top: 25px; | ||||
|   min-width:675px; | ||||
|   display:grid; | ||||
|   grid-template-columns:10vw 50vw; | ||||
|  | ||||
							
								
								
									
										117
									
								
								frontend/src/Apps/CreateUser.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										117
									
								
								frontend/src/Apps/CreateUser.vue
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,117 @@ | ||||
| <script setup> | ||||
|  | ||||
| import i18n from "@/i18n.js"; | ||||
| import {uploadProfilePicture} from "@/rest/uploads.js"; | ||||
| import {postUser} from "@/rest/Users.js"; | ||||
| import {ref} from "vue"; | ||||
| let toCreate = Object.assign({},{}) | ||||
| const today =  new Date() | ||||
| const date = today.getFullYear() +"-" + ("0" + (today.getMonth()+1)).slice(-2) + "-" + ("0" + today.getDate()).slice(-2); | ||||
|  | ||||
|  | ||||
| async function createUser(){ | ||||
|  | ||||
|   if (toCreate.lastName === null || toCreate.birthDate === null || toCreate.firstName === null || | ||||
|       toCreate.email === null || toCreate.address === null || toCreate.role === null || toCreate.password === null) | ||||
|     return | ||||
|  | ||||
|   await postUser(toCreate) | ||||
|   toCreate = Object.assign({},{}) | ||||
| } | ||||
|  | ||||
| async function getProfilePic(data){ | ||||
|   const pp= await uploadProfilePicture(data) | ||||
|   toCreate.profilePictureUrl = pp.url | ||||
| } | ||||
|  | ||||
| </script> | ||||
|  | ||||
| <template> | ||||
|   <div class="body"> | ||||
|     <div class="container"> | ||||
|       <div class = "globalInfos"> | ||||
|         <div class="infosContainer"> | ||||
|           <ul> | ||||
|             <li>{{i18n("LastName")}} : <input type="text" v-model="toCreate.lastName"></li> | ||||
|             <li>{{i18n("FirstName")}} : <input type="text" v-model="toCreate.firstName"></li> | ||||
|             <li> E-mail : <input type="text" v-model="toCreate.email"></li> | ||||
|             <li>{{i18n("Country")}} : <input type="text" v-model="toCreate.country"></li> | ||||
|             <li>{{i18n("Address")}} : <input type="text" v-model="toCreate.address"></li> | ||||
|             <li>{{i18n("BirthDate")}} : <input type="date" min="1924-01-01" :max="date" v-model="toCreate.birthDate"></li> | ||||
|  | ||||
|             <li>{{i18n("Profile.Picture")}} : | ||||
|               <input  type="file" @change="getProfilePic($event.target.files);" accept="image/*"> | ||||
|             </li> | ||||
|  | ||||
|  | ||||
|             <li>{{i18n("Role")}} : | ||||
|             <select  v-model="toCreate.role"> | ||||
|               <option value="Student">{{i18n("Student")}}</option> | ||||
|               <option value="Teacher">{{i18n("Teacher")}}</option> | ||||
|               <option value="Secretary">{{i18n("Secretary")}}</option> | ||||
|               <option value="InscriptionService">{{i18n("InscriptionService")}}</option> | ||||
|             </select> | ||||
|             </li> | ||||
|  | ||||
|             <li>{{i18n("Password")}} : <input type="password" v-model="toCreate.password"></li> | ||||
|  | ||||
|           </ul> | ||||
|           <div style="text-align: end"> <button id="createButton" @click="createUser"> {{i18n("Create.User")}}</button></div> | ||||
|         </div> | ||||
|     </div> | ||||
|   </div> | ||||
|   </div> | ||||
| </template> | ||||
|  | ||||
| <style scoped> | ||||
|  | ||||
| .container{ | ||||
|   margin-top: 25px; | ||||
|   min-width:675px; | ||||
|   display:grid; | ||||
|   grid-template-columns:10vw 50vw; | ||||
|   grid-template-rows:200px auto; | ||||
|   column-gap:2.7%; | ||||
|   row-gap:45px; | ||||
|   grid-template-areas: | ||||
|   "profilPic globalInfos" | ||||
|   "minfos minfos"; | ||||
| } | ||||
| .globalInfos { | ||||
|   grid-area:globalInfos; | ||||
|   align-self :center; | ||||
|  | ||||
| } | ||||
|  | ||||
| .body { | ||||
|   min-width:960px; | ||||
|   width:100%; | ||||
|   display:flex; | ||||
|   align-items:center; | ||||
|   justify-content:center; | ||||
|   margin-top:5%; | ||||
| } | ||||
|  | ||||
|  | ||||
| .infosContainer { | ||||
|   border:2px solid black; | ||||
|   font-size:23px; | ||||
|   color:white; | ||||
|   background-color:rgb(50,50,50); | ||||
|   border-radius:10px; | ||||
| } | ||||
|  | ||||
| #createButton{ | ||||
|   align-self: center; | ||||
|   text-align: center; | ||||
|   border: 2px solid black; | ||||
|   color: white; | ||||
|   font-size: x-large; | ||||
|   background-color: #07bc0c; | ||||
|   border-radius: 20px | ||||
| } | ||||
| #createButton:hover{ | ||||
|   background: #4cd964; | ||||
| } | ||||
|  | ||||
| </style> | ||||
| @ -13,6 +13,10 @@ export function disconnect(){ | ||||
| 	setCookie("session_token", ";expires= Thu, 01 Jan 1970 00:00:01 GMT") | ||||
| } | ||||
|  | ||||
| export async function patchUser(id,data){ | ||||
| 	return restPatch("/user/" +id, data) | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Register a user (tokenless) | ||||
|  *  | ||||
| @ -43,31 +47,8 @@ export async function register(firstname, lastname, birthDate, password, email, | ||||
| 	}); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Register a user (by secretary) | ||||
|  *  | ||||
|  * @param firstname | ||||
|  * @param lastname | ||||
|  * @param birthdate | ||||
|  * @param password | ||||
|  * @param mail | ||||
|  * @param address | ||||
|  * @param country | ||||
|  * @param imageId	id of the image in database returned when uploaded | ||||
|  * | ||||
|  * PS: the password is not required as it is generated by the backend and sent to the user | ||||
|  * by mail. it's up to the user to change it if he cares about security | ||||
|  */ | ||||
| export async function createUser(firstname, lastname, birthDate, email, address, country, role, imageId){ | ||||
| 	return restPost("/user", { | ||||
| 		firstname: firstname, | ||||
| 		lastname: lastname, | ||||
| 		birthDate: birthDate, | ||||
| 		password: password, | ||||
| 		email: email, | ||||
| 		address: address, | ||||
| 		country: country, | ||||
| 	}); | ||||
| export async function postUser(data){ | ||||
| 	return restPost("/user", data) | ||||
| } | ||||
|  | ||||
| /** | ||||
|  | ||||
| @ -15,6 +15,7 @@ import ManageRequests from "@/Apps/Inscription/ManageRequests.vue"; | ||||
| import ManageResearcherProfile from "@/Apps/ScientificPublications/ManageResearcherProfile.vue"; | ||||
| import ListResearches from "@/Apps/ScientificPublications/ListResearches.vue"; | ||||
| import ResearcherProfile from "@/Apps/ScientificPublications/ResearcherProfile.vue"; | ||||
| import CreateUser from "@/Apps/CreateUser.vue"; | ||||
|  | ||||
| const apps = { | ||||
| 		'/login': LoginPage, | ||||
| @ -26,7 +27,8 @@ const apps = { | ||||
| 		'/manage-researcher-profile' : ManageResearcherProfile, | ||||
| 		'/msg' : Msg, | ||||
| 		'/researches' : ListResearches, | ||||
| 		'/researcher-profile': ResearcherProfile | ||||
| 		'/researcher-profile': ResearcherProfile, | ||||
| 		'/create-user': CreateUser | ||||
| } | ||||
|  | ||||
| const appsList = { | ||||
| @ -40,6 +42,7 @@ const appsList = { | ||||
| 		'StudentsList':{ path: '#/students-list',icon: 'fa-users',text: i18n("app.studentList")}, | ||||
| 		'UsersList':{ path: '#/users-list',icon: 'fa-users',text: i18n("app.users")}, | ||||
| 		'ManageResearcherProfile':{path:'#/manage-researcher-profile',icon:'fa-book-bookmark',text:i18n("app.manage.researcherProfile")}, | ||||
| 		'CreateUser':{path:'#/create-user',icon:'fa-plus', text:i18n("app.Create.User")} | ||||
|  | ||||
| } | ||||
|  | ||||
|  | ||||
		Reference in New Issue
	
	Block a user