Browse Source
Architecture improvements and validation
Architecture improvements and validation
Improved system architecture and added sample regex validation to registrationmaster
Rohan Sircar
5 years ago
31 changed files with 978 additions and 338 deletions
-
19chatto/pom.xml
-
2chatto/src/main/java/org/ros/chatto/RESTAuthenticationEntryPoint.java
-
21chatto/src/main/java/org/ros/chatto/controller/AdminController.java
-
87chatto/src/main/java/org/ros/chatto/controller/AdminRESTController.java
-
49chatto/src/main/java/org/ros/chatto/controller/ChatMessageController.java
-
53chatto/src/main/java/org/ros/chatto/controller/DemoRestController.java
-
31chatto/src/main/java/org/ros/chatto/controller/RegistrationController.java
-
2chatto/src/main/java/org/ros/chatto/dto/ChatMessageDTO.java
-
25chatto/src/main/java/org/ros/chatto/dto/MessageCipherDTO.java
-
14chatto/src/main/java/org/ros/chatto/dto/ReencryptionDTO.java
-
14chatto/src/main/java/org/ros/chatto/dto/UserPublicDTO.java
-
16chatto/src/main/java/org/ros/chatto/dto/UserRegistrationDTO.java
-
21chatto/src/main/java/org/ros/chatto/model/ApplicationStatus.java
-
2chatto/src/main/java/org/ros/chatto/model/MessageCipher.java
-
12chatto/src/main/java/org/ros/chatto/repository/ChatMessageRepository.java
-
3chatto/src/main/java/org/ros/chatto/repository/UserRoleRepository.java
-
25chatto/src/main/java/org/ros/chatto/service/ChatService.java
-
38chatto/src/main/java/org/ros/chatto/service/ChatServiceImpl.java
-
60chatto/src/main/java/org/ros/chatto/service/DBInitializerService.java
-
42chatto/src/main/java/org/ros/chatto/service/MyConversionService.java
-
1chatto/src/main/java/org/ros/chatto/service/UserService.java
-
6chatto/src/main/java/org/ros/chatto/service/UserServiceImpl.java
-
3chatto/src/main/resources/queries.properties
-
135chatto/src/main/resources/static/js/admin.js
-
396chatto/src/main/resources/static/js/chat.js
-
109chatto/src/main/resources/templates/admin/home.html
-
18chatto/src/main/resources/templates/chat.html
-
20chatto/src/main/resources/templates/fragments/navbar.html
-
13chatto/src/main/resources/templates/home.html
-
2chatto/src/main/resources/templates/login.html
-
77chatto/src/main/resources/templates/registration.html
@ -1,14 +1,25 @@ |
|||||
package org.ros.chatto.controller; |
package org.ros.chatto.controller; |
||||
|
|
||||
|
import java.security.Principal; |
||||
|
|
||||
|
import org.ros.chatto.service.UserService; |
||||
|
import org.springframework.beans.factory.annotation.Autowired; |
||||
import org.springframework.stereotype.Controller; |
import org.springframework.stereotype.Controller; |
||||
import org.springframework.web.bind.annotation.RequestMapping; |
import org.springframework.web.bind.annotation.RequestMapping; |
||||
|
import org.springframework.web.servlet.ModelAndView; |
||||
|
|
||||
@Controller |
@Controller |
||||
@RequestMapping("/admin") |
@RequestMapping("/admin") |
||||
public class AdminController { |
public class AdminController { |
||||
|
|
||||
@RequestMapping |
|
||||
public String viewManageUsers() { |
|
||||
return "/admin/home"; |
|
||||
} |
|
||||
|
|
||||
|
@Autowired |
||||
|
private UserService userService; |
||||
|
|
||||
|
@RequestMapping |
||||
|
public ModelAndView viewManageUsers(Principal principal) { |
||||
|
ModelAndView modelAndView = new ModelAndView("/admin/home"); |
||||
|
modelAndView.addObject("user", new String()); |
||||
|
modelAndView.addObject("userNames", userService.getAllRegularUsers()); |
||||
|
return modelAndView; |
||||
|
} |
||||
} |
} |
@ -0,0 +1,87 @@ |
|||||
|
package org.ros.chatto.controller; |
||||
|
|
||||
|
import java.security.Principal; |
||||
|
import java.time.OffsetDateTime; |
||||
|
import java.time.format.DateTimeFormatter; |
||||
|
import java.time.format.DateTimeFormatterBuilder; |
||||
|
import java.util.Date; |
||||
|
import java.util.List; |
||||
|
|
||||
|
import org.ros.chatto.dto.ChatMessageDTO; |
||||
|
import org.ros.chatto.dto.ReencryptionDTO; |
||||
|
import org.ros.chatto.model.ChatMessage; |
||||
|
import org.ros.chatto.service.ChatService; |
||||
|
import org.ros.chatto.service.UserService; |
||||
|
import org.springframework.beans.factory.annotation.Autowired; |
||||
|
import org.springframework.http.HttpStatus; |
||||
|
import org.springframework.http.ResponseEntity; |
||||
|
import org.springframework.web.bind.annotation.GetMapping; |
||||
|
import org.springframework.web.bind.annotation.PathVariable; |
||||
|
import org.springframework.web.bind.annotation.PostMapping; |
||||
|
import org.springframework.web.bind.annotation.RequestBody; |
||||
|
import org.springframework.web.bind.annotation.RequestMapping; |
||||
|
import org.springframework.web.bind.annotation.ResponseBody; |
||||
|
import org.springframework.web.bind.annotation.RestController; |
||||
|
|
||||
|
@RestController |
||||
|
@RequestMapping("/api/admin") |
||||
|
public class AdminRESTController { |
||||
|
@Autowired |
||||
|
private ChatService chatService; |
||||
|
|
||||
|
@Autowired |
||||
|
private UserService userService; |
||||
|
|
||||
|
@PostMapping(value = "/post/re-encrypt", consumes = { "application/json" }) |
||||
|
@ResponseBody |
||||
|
public ResponseEntity<ReencryptionDTO> reencryptMessages(@RequestBody List<ReencryptionDTO> reencryptionDTOs, |
||||
|
Principal principal) { |
||||
|
if (reencryptionDTOs.size() > 0) { |
||||
|
chatService.reencryptMessages(reencryptionDTOs); |
||||
|
} |
||||
|
return new ResponseEntity<ReencryptionDTO>(HttpStatus.OK); |
||||
|
} |
||||
|
|
||||
|
@GetMapping(value = "/get/messages/{userName}") |
||||
|
@ResponseBody |
||||
|
public List<ReencryptionDTO> sendAllMessages(@PathVariable String userName, Principal principal) { |
||||
|
List<ReencryptionDTO> reencryptionDTOs = chatService.getAllMessagesForReencryption(principal.getName(), userName); |
||||
|
return reencryptionDTOs; |
||||
|
} |
||||
|
|
||||
|
@GetMapping(value = "/get/messages/{userName}/{lastMessageTime}") |
||||
|
@ResponseBody |
||||
|
public List<ChatMessageDTO> sendNewMessages(@PathVariable String userName, @PathVariable String lastMessageTime, |
||||
|
Principal principal) { |
||||
|
System.out.println("Last message time = " + lastMessageTime); |
||||
|
DateTimeFormatter formatter = new DateTimeFormatterBuilder() |
||||
|
// date/time |
||||
|
.append(DateTimeFormatter.ISO_LOCAL_DATE_TIME) |
||||
|
// offset (hh:mm - "+00:00" when it's zero) |
||||
|
.optionalStart().appendOffset("+HH:MM", "+00:00").optionalEnd() |
||||
|
// offset (hhmm - "+0000" when it's zero) |
||||
|
.optionalStart().appendOffset("+HHMM", "+0000").optionalEnd() |
||||
|
// offset (hh - "Z" when it's zero) |
||||
|
.optionalStart().appendOffset("+HH", "Z").optionalEnd() |
||||
|
// create formatter |
||||
|
.toFormatter(); |
||||
|
Date date = Date.from(OffsetDateTime.parse(lastMessageTime, formatter).toInstant()); |
||||
|
|
||||
|
List<ChatMessageDTO> chatMessageDTOs = chatService.getNewMessages(principal.getName(), userName, date); |
||||
|
return chatMessageDTOs; |
||||
|
} |
||||
|
|
||||
|
@GetMapping("/get/users") |
||||
|
public List<String> getAllOtherUsers(Principal principal) { |
||||
|
return userService.findAllOtherUsers(principal.getName()); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
//public ResponseEntity<List<ChatMessage>> getMessages(@PathVariable String userName, Principal principal) { |
||||
|
////List<ChatMessage> chatMessages = chatMessageRepository.getAllMessages(principal.getName(), userName); |
||||
|
// |
||||
|
//// return posts.stream() |
||||
|
//// .map(post -> convertToDto(post)) |
||||
|
//// .collect(Collectors.toList()); |
||||
|
//return new ResponseEntity<List<ChatMessage>>(chatMessages, HttpStatus.OK); |
||||
|
//} |
@ -1,34 +1,37 @@ |
|||||
package org.ros.chatto.controller; |
package org.ros.chatto.controller; |
||||
|
|
||||
import javax.servlet.http.HttpServletRequest; |
|
||||
import javax.servlet.http.HttpServletResponse; |
|
||||
|
import javax.validation.Valid; |
||||
|
|
||||
import org.ros.chatto.dto.UserRegistrationDTO; |
import org.ros.chatto.dto.UserRegistrationDTO; |
||||
import org.ros.chatto.service.UserService; |
import org.ros.chatto.service.UserService; |
||||
import org.springframework.beans.factory.annotation.Autowired; |
import org.springframework.beans.factory.annotation.Autowired; |
||||
import org.springframework.stereotype.Controller; |
import org.springframework.stereotype.Controller; |
||||
|
import org.springframework.ui.Model; |
||||
|
import org.springframework.validation.BindingResult; |
||||
import org.springframework.web.bind.annotation.GetMapping; |
import org.springframework.web.bind.annotation.GetMapping; |
||||
import org.springframework.web.bind.annotation.ModelAttribute; |
import org.springframework.web.bind.annotation.ModelAttribute; |
||||
import org.springframework.web.bind.annotation.PostMapping; |
import org.springframework.web.bind.annotation.PostMapping; |
||||
import org.springframework.web.servlet.ModelAndView; |
|
||||
|
|
||||
@Controller |
@Controller |
||||
public class RegisterController { |
|
||||
|
|
||||
|
public class RegistrationController { |
||||
|
|
||||
@Autowired |
@Autowired |
||||
private UserService userService; |
private UserService userService; |
||||
|
|
||||
@GetMapping("/registration") |
@GetMapping("/registration") |
||||
public ModelAndView registrationForm() |
|
||||
{ |
|
||||
ModelAndView modelAndView = new ModelAndView("registration"); |
|
||||
modelAndView.addObject("userDTO",new UserRegistrationDTO()); |
|
||||
return modelAndView; |
|
||||
|
public String registrationForm(Model model) { |
||||
|
model.addAttribute("userRegistrationDTO", new UserRegistrationDTO()); |
||||
|
return "registration"; |
||||
} |
} |
||||
|
|
||||
@PostMapping("/perform_registration") |
@PostMapping("/perform_registration") |
||||
public ModelAndView performRegistration(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, @ModelAttribute("userDTO") UserRegistrationDTO userRegistrationDTO) |
|
||||
{ |
|
||||
ModelAndView modelAndView = new ModelAndView("user/home"); |
|
||||
|
public String performRegistration(Model model, |
||||
|
@ModelAttribute("userRegistrationDTO") @Valid UserRegistrationDTO userRegistrationDTO, BindingResult bindingResult) { |
||||
|
if (bindingResult.hasErrors()) { |
||||
|
System.out.println("Input has errors!"); |
||||
|
return "registration"; |
||||
|
} |
||||
userService.registerUser(userRegistrationDTO); |
userService.registerUser(userRegistrationDTO); |
||||
return modelAndView; |
|
||||
|
return "user/home"; |
||||
} |
} |
||||
} |
} |
@ -0,0 +1,25 @@ |
|||||
|
package org.ros.chatto.dto; |
||||
|
|
||||
|
import com.fasterxml.jackson.annotation.JsonProperty; |
||||
|
|
||||
|
import lombok.Getter; |
||||
|
import lombok.Setter; |
||||
|
|
||||
|
@Getter |
||||
|
@Setter |
||||
|
public class MessageCipherDTO { |
||||
|
private String iv; |
||||
|
private int v; |
||||
|
@JsonProperty("iter") |
||||
|
private int iterations; |
||||
|
@JsonProperty("ks") |
||||
|
private int keySize; |
||||
|
@JsonProperty("ts") |
||||
|
private int tagSize; |
||||
|
private String mode; |
||||
|
private String adata; |
||||
|
private String cipher; |
||||
|
private String salt; |
||||
|
@JsonProperty("ct") |
||||
|
private String cipherText; |
||||
|
} |
@ -0,0 +1,14 @@ |
|||||
|
package org.ros.chatto.dto; |
||||
|
|
||||
|
import java.util.Date; |
||||
|
|
||||
|
import org.ros.chatto.model.MessageCipher; |
||||
|
|
||||
|
import lombok.Data; |
||||
|
|
||||
|
@Data |
||||
|
public class ReencryptionDTO { |
||||
|
private String toUser, fromUser; |
||||
|
private MessageCipher messageCipher; |
||||
|
private Date messageTime; |
||||
|
} |
@ -1,14 +0,0 @@ |
|||||
package org.ros.chatto.dto; |
|
||||
|
|
||||
import java.sql.Date; |
|
||||
|
|
||||
import org.ros.chatto.model.MessageCipher; |
|
||||
|
|
||||
import lombok.Data; |
|
||||
|
|
||||
@Data |
|
||||
public class UserPublicDTO { |
|
||||
String fromUser, toUser; |
|
||||
MessageCipher messageCipher; |
|
||||
Date messageTime; |
|
||||
} |
|
@ -1,23 +1,35 @@ |
|||||
package org.ros.chatto.dto; |
package org.ros.chatto.dto; |
||||
|
|
||||
import javax.persistence.Transient; |
import javax.persistence.Transient; |
||||
|
import javax.validation.constraints.NotBlank; |
||||
|
import javax.validation.constraints.Pattern; |
||||
|
import javax.validation.constraints.Size; |
||||
|
|
||||
public class UserRegistrationDTO { |
public class UserRegistrationDTO { |
||||
|
@Size(min = 4, max = 10, message = "Username must be between 4 and 10 characters") |
||||
|
@NotBlank(message = " Username should not be blank") |
||||
|
@Pattern(regexp = "^[A-Za-z0-9]+$", message = "Username must be alphanumeric") |
||||
private String userName; |
private String userName; |
||||
@Transient |
@Transient |
||||
|
@Size(min = 4, max = 75, message = "Username must be between 4 and 75 characters") |
||||
|
@NotBlank(message = " Password should not be blank") |
||||
|
@Pattern(regexp = "^.*(?=.{6,})(?=.*d)(?=.*[A-Z])(?=.*[a-z])(?=.*[!@#$%^&*? ]).*$", message = "Invalid password format") |
||||
private String password; |
private String password; |
||||
|
|
||||
public String getUserName() { |
public String getUserName() { |
||||
return userName; |
return userName; |
||||
} |
} |
||||
|
|
||||
public void setUserName(String userName) { |
public void setUserName(String userName) { |
||||
this.userName = userName; |
this.userName = userName; |
||||
} |
} |
||||
|
|
||||
public String getPassword() { |
public String getPassword() { |
||||
return password; |
return password; |
||||
} |
} |
||||
|
|
||||
public void setPassword(String password) { |
public void setPassword(String password) { |
||||
this.password = password; |
this.password = password; |
||||
} |
} |
||||
|
|
||||
|
|
||||
|
|
||||
} |
} |
@ -0,0 +1,21 @@ |
|||||
|
package org.ros.chatto.model; |
||||
|
|
||||
|
import javax.persistence.Column; |
||||
|
import javax.persistence.Entity; |
||||
|
import javax.persistence.Id; |
||||
|
import javax.persistence.Table; |
||||
|
|
||||
|
import lombok.Getter; |
||||
|
import lombok.Setter; |
||||
|
|
||||
|
@Entity |
||||
|
@Getter |
||||
|
@Setter |
||||
|
@Table(name="status") |
||||
|
public class ApplicationStatus { |
||||
|
@Id |
||||
|
private int id; |
||||
|
private String name; |
||||
|
@Column(name="value") |
||||
|
private boolean done; |
||||
|
} |
@ -1 +1,2 @@ |
|||||
num-tables = SELECT COUNT(*) as num_tables FROM information_schema.tables WHERE table_schema = ? and TABLE_TYPE='BASE TABLE' |
|
||||
|
num-tables = SELECT COUNT(*) as num_tables FROM information_schema.tables WHERE table_schema = ? and TABLE_TYPE='BASE TABLE' |
||||
|
#tables-created = |
@ -0,0 +1,135 @@ |
|||||
|
console.log('Hello world!'); |
||||
|
|
||||
|
var getAllMessagesURL = `http://${hostAddress}/api/admin/get/messages/`; //hostAddress set in thymeleaf backend
|
||||
|
var reencryptURL = `http://${hostAddress}/api/admin/post/re-encrypt`; |
||||
|
var getAllRegularUsersURL = `http://${hostAddress}/api/regular-users`; |
||||
|
var username = sessionStorage.getItem('username'); |
||||
|
var password = sessionStorage.getItem('password'); |
||||
|
var authToken = 'Basic ' + btoa(username + ":" + password); |
||||
|
var iterations = 10000; |
||||
|
|
||||
|
function handleAddToAdminForm() { |
||||
|
document.getElementById('addUserToAdminForm').addEventListener( |
||||
|
'submit', |
||||
|
function(e) { |
||||
|
e.preventDefault(); |
||||
|
getAllRegularUsers() |
||||
|
// .then(usernamesArray => {
|
||||
|
// console.lo
|
||||
|
// });
|
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
function handleChangePassphraseForm() { |
||||
|
document.getElementById('changePassphraseForm').addEventListener( |
||||
|
'submit', |
||||
|
function(e) { |
||||
|
e.preventDefault(); |
||||
|
let changePassphraseDropDown = document.getElementById('changePassphraseDropDown'); |
||||
|
let user = changePassphraseDropDown.value; |
||||
|
let passphraseOld = document.getElementById('passphraseOld'); |
||||
|
let passphraseNew = document.getElementById('passphraseNew'); |
||||
|
// let messageCipherNew = {};
|
||||
|
console.log(user); |
||||
|
getAllMessages(user) |
||||
|
.then(json => { |
||||
|
console.log(json); |
||||
|
|
||||
|
return json; |
||||
|
}) |
||||
|
.then(json => { |
||||
|
let jsonNew = []; |
||||
|
let messageCiphers = []; |
||||
|
let chatMessageDTOs = []; |
||||
|
if (json.length > 0) { |
||||
|
json.forEach(function(obj) { |
||||
|
let newObj = obj; |
||||
|
let messageID = obj.messageCipher.id; |
||||
|
let plainText = sjcl.decrypt(passphraseOld.value, JSON.stringify(obj.messageCipher)); |
||||
|
let messageCipherNew = sjcl.encrypt(passphraseNew.value, plainText, { mode: "gcm", ts: 128, adata: "", iter: iterations }); |
||||
|
// let plainText = sjcl.decrypt("password", JSON.stringify(obj.messageCipher));
|
||||
|
// let messageCipherNew = sjcl.encrypt("password2", plainText, { mode: "gcm", ts: 128, adata: "", iter: iterations });
|
||||
|
// console.log(messageCipherNew)
|
||||
|
let messageCipherNewObj = JSON.parse(messageCipherNew); |
||||
|
// console.log(messageCipherNewObj);
|
||||
|
messageCipherNewObj.id = messageID; |
||||
|
newObj.messageCipher = messageCipherNewObj; |
||||
|
// obj.messageCipher = messageCipherNewObj;
|
||||
|
// console.log(obj.messageCipher);
|
||||
|
// console.log(plainText);
|
||||
|
// console.log(messageCipherNewObj);
|
||||
|
jsonNew.push(newObj); |
||||
|
messageCiphers.push(messageCipherNewObj); |
||||
|
|
||||
|
// let messageCipherJson = JSON.stringify(messageCipherNewObj);
|
||||
|
let fromUser = sessionStorage.getItem('username'); |
||||
|
let chatMessageDTO = { |
||||
|
"toUser": user, |
||||
|
"fromUser": username, |
||||
|
"messageCipher": messageCipherNewObj |
||||
|
} |
||||
|
chatMessageDTOs.push(chatMessageDTO); |
||||
|
}); |
||||
|
// console.log(jsonNew);
|
||||
|
|
||||
|
} |
||||
|
// sendReencryptedMessages(JSON.stringify(jsonNew));
|
||||
|
console.log |
||||
|
sendReencryptedMessages(JSON.stringify(chatMessageDTOs)); |
||||
|
// sendReencryptedMessages(JSON.stringify(messageCiphers));
|
||||
|
|
||||
|
return jsonNew; |
||||
|
}) |
||||
|
.then(json => { |
||||
|
json.forEach(function(obj) { |
||||
|
let plainText = sjcl.decrypt("password2", JSON.stringify(obj.messageCipher)); |
||||
|
console.log(plainText); |
||||
|
}) |
||||
|
|
||||
|
}); |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
async function getAllMessages(user) { |
||||
|
let headers = new Headers(); |
||||
|
// headers.append('Accept','application/json')
|
||||
|
// headers.append('Content-Type', 'application/json');
|
||||
|
headers.append('Authorization', authToken); |
||||
|
let response = await fetch(`${getAllMessagesURL}${user}`, { |
||||
|
method: 'GET', |
||||
|
headers: headers |
||||
|
}); |
||||
|
let data = await response.json(); |
||||
|
return data; |
||||
|
} |
||||
|
|
||||
|
async function getAllRegularUsers() { |
||||
|
let headers = new Headers(); |
||||
|
// headers.append('Accept','application/json')
|
||||
|
// headers.append('Content-Type', 'application/json');
|
||||
|
headers.append('Authorization', authToken); |
||||
|
let response = await fetch(`${getAllRegularUsersURL}`, { |
||||
|
method: 'GET', |
||||
|
headers: headers |
||||
|
}); |
||||
|
let data = await response.json(); |
||||
|
return data; |
||||
|
} |
||||
|
|
||||
|
function sendReencryptedMessages(chatMessageDTOs) { |
||||
|
let headers = new Headers(); |
||||
|
// console.log("Token = " + btoa("hmm" + ":" + "hmm"))
|
||||
|
|
||||
|
// headers.append('Accept','application/json')
|
||||
|
headers.append('Content-Type', 'application/json'); |
||||
|
headers.append('Authorization', authToken); |
||||
|
fetch(reencryptURL, { |
||||
|
method: 'POST', |
||||
|
headers: headers, |
||||
|
body: chatMessageDTOs |
||||
|
}) |
||||
|
.then(response => console.log(response)); |
||||
|
} |
||||
|
|
||||
|
handleAddToAdminForm(); |
||||
|
handleChangePassphraseForm(); |
@ -1,13 +1,110 @@ |
|||||
<!DOCTYPE html> |
<!DOCTYPE html> |
||||
<html xmlns:th="http://www.thymeleaf.org"> |
<html xmlns:th="http://www.thymeleaf.org"> |
||||
|
|
||||
<head> |
<head> |
||||
<meta charset="UTF-8"> |
|
||||
<title>Insert title here</title> |
|
||||
|
<div th:replace="fragments/head :: headFragment"> |
||||
|
<title id="pageTitle">Admin Home</title> |
||||
|
</div> |
||||
|
<script src="https://code.jquery.com/jquery-2.1.4.min.js" th:if="false"></script> |
||||
|
<script src="http://blackpeppersoftware.github.io/thymeleaf-fragment.js/thymeleaf-fragment.js" data-template-prefix="../" defer="defer" th:if="false"></script> |
||||
|
<script th:src="@{js/admin.js}" src="../../static/js/admin.js" defer="defer"></script> |
||||
|
<link th:href="@{/css/master.css}" href="../../static/css/master.css" rel="stylesheet" th:if="false"> |
||||
|
<link th:href="@{/css/colors.css}" href="../../static/css/colors.css" rel="stylesheet" th:if="false"> |
||||
</head> |
</head> |
||||
|
<!-- TODO |
||||
|
Make user admin / remove user from admin |
||||
|
Change E2E passphrase |
||||
|
Delete Messages |
||||
|
--> |
||||
|
|
||||
<body> |
<body> |
||||
admin page |
|
||||
<form action="#" th:action="@{/perform_logout}" method="POST"> |
|
||||
<input type="submit" value="logout"> |
|
||||
</form> |
|
||||
|
<div th:include="fragments/navbar :: navbarFragment"></div> |
||||
|
|
||||
|
<header> |
||||
|
<div class="container bg-primary"> |
||||
|
<div class="row"> |
||||
|
<div class="col-sm py-5"> |
||||
|
<h1 class="display-4 text-center">Admin Page</h1> |
||||
|
<p class="alert-danger px-2">Warning: these settings can be dangerous..</p> |
||||
|
</div> |
||||
|
</div> |
||||
|
<div class="row"> |
||||
|
<div class="col-sm col-md-4"> |
||||
|
<h4>Make User an Admin</h4> |
||||
|
<form id="addUserToAdminForm"> |
||||
|
<div class="form-group"> |
||||
|
<label for="addUserToDropDown">Select User:</label> |
||||
|
<select class="form-control custom-select" size="4" id="addUserToAdminDropDown"> |
||||
|
|
||||
|
<option th:each="userName : ${userNames}" |
||||
|
th:value="${userName}" |
||||
|
th:text="#{${userName}}"> |
||||
|
Wireframe |
||||
|
</option> |
||||
|
|
||||
|
</select> |
||||
|
|
||||
|
|
||||
|
</div> |
||||
|
<div class="form-group"> |
||||
|
<button class="btn btn-danger form-control">Make admin</button> |
||||
|
</div> |
||||
|
</form> |
||||
|
</div> |
||||
|
<div class="col-sm col-md-4"> |
||||
|
<h4>Change passphrases</h4> |
||||
|
<form id="changePassphraseForm"> |
||||
|
<div class="form-group"> |
||||
|
<label for="changePassphraseDropDown">Select User:</label> |
||||
|
<select class="form-control" id="changePassphraseDropDown"> |
||||
|
|
||||
|
<option th:each="userName : ${userNames}" |
||||
|
th:value="${userName}" |
||||
|
th:text="#{${userName}}"> |
||||
|
Wireframe |
||||
|
</option> |
||||
|
|
||||
|
</select> |
||||
|
|
||||
|
</div> |
||||
|
<div class="form-group"> |
||||
|
<label for="passphraseOld">Passphrase Old</label> |
||||
|
<input type="password" id="passphraseOld" class="form-control"> |
||||
|
</div> |
||||
|
<div class="form-group"> |
||||
|
<label for="passphraseNew">Passphrase New</label> |
||||
|
<input type="password" id="passphraseNew" class="form-control"> |
||||
|
</div> |
||||
|
<div class="form-group"> |
||||
|
<button class="btn btn-danger form-control">Change Passphrase</button> |
||||
|
</div> |
||||
|
</form> |
||||
|
</div> |
||||
|
</div> |
||||
|
<div class="row"> |
||||
|
<!-- <div class="col-sm"></div> --> |
||||
|
|
||||
|
<div class="col-sm d-lg-block"> |
||||
|
<div class="d-flex justify-content-center"> |
||||
|
<div class="py-5"> |
||||
|
<h4 class="p-2 text-center">Logout</h4> |
||||
|
<form action="#" th:action="@{/logout}" method="POST"> |
||||
|
<!-- <input type="submit" value="logout"> --> |
||||
|
<!-- <input type="hidden" th:name="${_csrf.parameterName}" |
||||
|
th:value="${_csrf.token}" /> --> |
||||
|
<div class="form-group"> |
||||
|
<button class="btn btn-secondary form-control">Logout</button> |
||||
|
</div> |
||||
|
</form> |
||||
|
|
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
|
||||
|
</div> |
||||
|
</div> |
||||
|
</header> |
||||
|
|
||||
</body> |
</body> |
||||
|
|
||||
</html> |
</html> |
@ -1,18 +1,73 @@ |
|||||
<!DOCTYPE html> |
<!DOCTYPE html> |
||||
<html xmlns:th="http://www.thymeleaf.org"> |
<html xmlns:th="http://www.thymeleaf.org"> |
||||
|
|
||||
<head> |
<head> |
||||
<meta charset="UTF-8"> |
|
||||
<title>Insert title here</title> |
|
||||
|
<div th:replace="fragments/head :: headFragment"> |
||||
|
<title id="pageTitle">Registration</title> |
||||
|
</div> |
||||
|
<script src="https://code.jquery.com/jquery-2.1.4.min.js" th:if="false"></script> |
||||
|
<script src="http://blackpeppersoftware.github.io/thymeleaf-fragment.js/thymeleaf-fragment.js" defer="defer" th:if="false"></script> |
||||
|
|
||||
</head> |
</head> |
||||
|
|
||||
<body> |
<body> |
||||
<form action="#" th:action="@{/perform_registration}" |
|
||||
th:object=${userDTO} method="POST"> |
|
||||
<label>Enter user name: </label> <input th:field="*{userName}" |
|
||||
type="text" name="username" id="username"> <br> <br> |
|
||||
<label>Enter password: </label> <input th:field="*{password}" |
|
||||
type="password" name="password" id="password"> <br> <br> |
|
||||
<input type="password" id="password-repeat"> |
|
||||
<input type="submit" value="Submit"> |
|
||||
</form> |
|
||||
|
<div th:include="fragments/navbar :: navbarFragment"></div> |
||||
|
<header> |
||||
|
<div class="container"> |
||||
|
<div class="row"> |
||||
|
<div class="col-sm py-5"> |
||||
|
<!-- <h4 class="display-4 text-center py-2">Chat</h4> --> |
||||
|
<div class="card text-white bg-primary mb-3 text-center card-form rounded mx-auto" id="login-card"> |
||||
|
|
||||
|
<div class="card-body rounded"> |
||||
|
<!-- <h4 class="card-title">Chat</h4> --> |
||||
|
<!-- <div class="form-group"> |
||||
|
<textarea id="chatTextArea" class="form-control-lg py-2" disabled></textarea> |
||||
|
</div> --> |
||||
|
<!-- <form action="#" th:action="@{/seedstartermng}" th:object="${seedStarter}" method="post"> --> |
||||
|
<!-- th:action="@{/api/chat}" --> |
||||
|
|
||||
|
|
||||
|
<!-- <label>First Name</label> |
||||
|
<div th:classappend="${#fields.hasErrors('firstName')} ? 'input-icon right' : ''"> |
||||
|
<i th:if="${#fields.hasErrors('firstName')}" class="fa fa-exclamation tooltips" data-original-title="please enter a valid first name" data-container="body"></i> |
||||
|
<input type="text" class="form-control" maxlength="32" th:field="*{firstName}" placeholder="Between 1 and 32 characters" /> |
||||
|
<span th:if="${#fields.hasErrors('firstName')}" class="help-block" th:errors="*{firstName}"></span> |
||||
|
</div> --> |
||||
|
|
||||
|
<div class="card-text"> |
||||
|
<h2 class="card-title">Register</h2> |
||||
|
<form action="#" th:action="@{/perform_registration}" th:object=${userRegistrationDTO} method="POST"> |
||||
|
|
||||
|
<div class="form-group"> |
||||
|
<label>Enter username: </label> |
||||
|
<div th:classappend="${#fields.hasErrors('userName')} ? 'input-icon right' : ''"> |
||||
|
<i th:if="${#fields.hasErrors('userName')}" class="fa fa-exclamation tooltips" data-original-title="please enter a valid username" data-container="body"></i> |
||||
|
<input class="form-control" th:field="*{userName}" type="text" name="username" id="username" required> |
||||
|
<span th:if="${#fields.hasErrors('userName')}" class="help-block" th:errors="*{userName}"></span> |
||||
|
</div> |
||||
|
</div> |
||||
|
<div class="form-group"> |
||||
|
<label>Enter password: </label> |
||||
|
<i th:if="${#fields.hasErrors('password')}" class="fa fa-exclamation tooltips" data-original-title="please enter a valid first name" data-container="body"></i> |
||||
|
<input class="form-control" th:field="*{password}" type="password" name="password" id="password" required> |
||||
|
<span th:if="${#fields.hasErrors('password')}" class="help-block" th:errors="*{password}"></span> |
||||
|
</div> |
||||
|
<div class="form-group"> |
||||
|
<label for="password-repeat">Repeat password: </label> |
||||
|
<input class="form-control" type="password" id="password-repeat" required> |
||||
|
</div> |
||||
|
<div class="form-group"> |
||||
|
<input class="form-control btn btn-secondary" type="submit" value="Submit"> |
||||
|
</div> |
||||
|
</form> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
</header> |
||||
</body> |
</body> |
||||
|
|
||||
</html> |
</html> |
Write
Preview
Loading…
Cancel
Save
Reference in new issue