FEAT : Mise en place de l'architecture + instription d'un utilisateur
This commit is contained in:
@@ -0,0 +1,57 @@
|
||||
package local.epul4a.fotosharing.controller;
|
||||
|
||||
import local.epul4a.fotosharing.model.Utilisateur;
|
||||
import local.epul4a.fotosharing.repository.UtilisateurRepository;
|
||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.Model;
|
||||
import org.springframework.validation.BindingResult;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import jakarta.validation.Valid;
|
||||
|
||||
@Controller
|
||||
public class AuthController {
|
||||
|
||||
private final UtilisateurRepository utilisateurRepository;
|
||||
private final PasswordEncoder passwordEncoder;
|
||||
|
||||
public AuthController(UtilisateurRepository utilisateurRepository, PasswordEncoder passwordEncoder) {
|
||||
this.utilisateurRepository = utilisateurRepository;
|
||||
this.passwordEncoder = passwordEncoder;
|
||||
}
|
||||
|
||||
@GetMapping("/login")
|
||||
public String loginPage(@RequestParam(value = "error", required = false) String error,
|
||||
@RequestParam(value = "logout", required = false) String logout,
|
||||
Model model) {
|
||||
model.addAttribute("error", error != null);
|
||||
model.addAttribute("logout", logout != null);
|
||||
return "login";
|
||||
}
|
||||
|
||||
@GetMapping("/register")
|
||||
public String registerForm(Model model) {
|
||||
model.addAttribute("utilisateur", new Utilisateur());
|
||||
return "register";
|
||||
}
|
||||
|
||||
@PostMapping("/register")
|
||||
public String doRegister(@ModelAttribute("utilisateur") @Valid Utilisateur utilisateur,
|
||||
BindingResult bindingResult, Model model) {
|
||||
if (bindingResult.hasErrors()) {
|
||||
return "register";
|
||||
}
|
||||
|
||||
if (utilisateurRepository.findByEmail(utilisateur.getEmail()).isPresent()) {
|
||||
model.addAttribute("error", "Email déjà utilisé");
|
||||
return "register";
|
||||
}
|
||||
|
||||
// encoder le mot de passe puis sauvegarder
|
||||
utilisateur.setMotDePasse(passwordEncoder.encode(utilisateur.getMotDePasse()));
|
||||
utilisateur.setActif(true);
|
||||
utilisateurRepository.save(utilisateur);
|
||||
return "redirect:/login?registered";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
package local.epul4a.fotosharing.controller;
|
||||
|
||||
import local.epul4a.fotosharing.model.Photo;
|
||||
import local.epul4a.fotosharing.security.CustomUserDetails;
|
||||
import local.epul4a.fotosharing.service.PhotoService;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.core.io.PathResource;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.security.core.annotation.AuthenticationPrincipal;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.Model;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import java.nio.file.Path;
|
||||
|
||||
@Controller
|
||||
public class PhotoController {
|
||||
|
||||
private final PhotoService photoService;
|
||||
|
||||
public PhotoController(PhotoService photoService) {
|
||||
this.photoService = photoService;
|
||||
}
|
||||
|
||||
@GetMapping("/")
|
||||
public String home() {
|
||||
return "home"; // créer une page home.html simple
|
||||
}
|
||||
|
||||
@GetMapping("/upload")
|
||||
public String uploadForm() {
|
||||
return "upload";
|
||||
}
|
||||
|
||||
@PostMapping("/upload")
|
||||
public String doUpload(@RequestParam("file") MultipartFile file,
|
||||
@RequestParam(value="visibilite", defaultValue = "PRIVATE") String visibilite,
|
||||
@AuthenticationPrincipal CustomUserDetails user,
|
||||
Model model) {
|
||||
try {
|
||||
Photo p = photoService.store(file, visibilite, user.getUsername());
|
||||
model.addAttribute("message", "Upload OK : " + p.getId());
|
||||
return "redirect:/"; // ou page d'affichage
|
||||
} catch (Exception e) {
|
||||
model.addAttribute("error", e.getMessage());
|
||||
return "upload";
|
||||
}
|
||||
}
|
||||
|
||||
@GetMapping("/photo/{id}/raw")
|
||||
public ResponseEntity<Resource> rawPhoto(@PathVariable("id") String idOrUuid) {
|
||||
// idOrUuid peut être uuid stocké ou id numeric ; ici on assume uuid
|
||||
Path p = photoService.loadAsPath(idOrUuid);
|
||||
Resource r = new PathResource(p);
|
||||
if (!r.exists()) {
|
||||
return ResponseEntity.notFound().build();
|
||||
}
|
||||
String contentType = "application/octet-stream";
|
||||
try {
|
||||
// tentative de détection basique
|
||||
contentType = java.nio.file.Files.probeContentType(p);
|
||||
} catch (Exception ignored) {}
|
||||
return ResponseEntity.ok()
|
||||
.contentType(MediaType.parseMediaType(contentType != null ? contentType : "application/octet-stream"))
|
||||
.header(HttpHeaders.CONTENT_DISPOSITION, "inline; filename=\"" + p.getFileName().toString() + "\"")
|
||||
.body(r);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
package local.epul4a.fotosharing.model;
|
||||
|
||||
import jakarta.persistence.*;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Entity
|
||||
@Getter
|
||||
@Setter
|
||||
public class Commentaire {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
private Long id;
|
||||
|
||||
private String contenu;
|
||||
|
||||
private LocalDateTime dateCommentaire;
|
||||
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "id_photo")
|
||||
private Photo photo;
|
||||
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "id_utilisateur")
|
||||
private Utilisateur auteur;
|
||||
|
||||
// Getters & Setters
|
||||
}
|
||||
25
src/main/java/local/epul4a/fotosharing/model/Partage.java
Normal file
25
src/main/java/local/epul4a/fotosharing/model/Partage.java
Normal file
@@ -0,0 +1,25 @@
|
||||
package local.epul4a.fotosharing.model;
|
||||
|
||||
import jakarta.persistence.*;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
@Entity
|
||||
@Getter
|
||||
@Setter
|
||||
public class Partage {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
private Long id;
|
||||
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "id_photo")
|
||||
private Photo photo;
|
||||
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "id_utilisateur")
|
||||
private Utilisateur utilisateur;
|
||||
|
||||
// Getters & Setters
|
||||
}
|
||||
32
src/main/java/local/epul4a/fotosharing/model/Photo.java
Normal file
32
src/main/java/local/epul4a/fotosharing/model/Photo.java
Normal file
@@ -0,0 +1,32 @@
|
||||
package local.epul4a.fotosharing.model;
|
||||
|
||||
import jakarta.persistence.*;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
|
||||
@Entity
|
||||
@Getter
|
||||
@Setter
|
||||
public class Photo {
|
||||
public enum Visibilite { PRIVATE, PUBLIC, SHARED }
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
private Long id;
|
||||
|
||||
private String nomFichierOriginal;
|
||||
private String uuidFichier;
|
||||
private LocalDateTime dateUpload;
|
||||
|
||||
@Enumerated(EnumType.STRING)
|
||||
private Visibilite visibilite;
|
||||
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "id_utilisateur")
|
||||
private Utilisateur proprietaire;
|
||||
|
||||
// getters & setters
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
package local.epul4a.fotosharing.model;
|
||||
|
||||
import jakarta.persistence.*;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Entity
|
||||
@Getter
|
||||
@Setter
|
||||
public class Utilisateur {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
private Long id;
|
||||
|
||||
private String email;
|
||||
|
||||
private String motDePasse;
|
||||
|
||||
private String nom;
|
||||
|
||||
private String prenom;
|
||||
|
||||
private boolean actif = true;
|
||||
|
||||
@OneToMany(mappedBy = "proprietaire")
|
||||
private List<
|
||||
Photo> photos;
|
||||
|
||||
// Getters & Setters avec lombok
|
||||
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package local.epul4a.fotosharing.repository;
|
||||
|
||||
import local.epul4a.fotosharing.model.Photo;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
|
||||
public interface PhotoRepository extends JpaRepository<Photo, Long> {
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package local.epul4a.fotosharing.repository;
|
||||
|
||||
import local.epul4a.fotosharing.model.Utilisateur;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
public interface UtilisateurRepository extends JpaRepository<Utilisateur, Long> {
|
||||
Optional<Utilisateur> findByEmail(String email);
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
package local.epul4a.fotosharing.security;
|
||||
|
||||
import local.epul4a.fotosharing.model.Utilisateur;
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
|
||||
public class CustomUserDetails implements UserDetails {
|
||||
|
||||
private final Utilisateur user;
|
||||
|
||||
public CustomUserDetails(Utilisateur user) {
|
||||
this.user = user;
|
||||
}
|
||||
|
||||
public Utilisateur getUtilisateur() {
|
||||
return user;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<? extends GrantedAuthority> getAuthorities() {
|
||||
// Si tu veux ajouter des rôles, adapte ici.
|
||||
return Collections.singletonList(new SimpleGrantedAuthority("ROLE_USER"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPassword() {
|
||||
return user.getMotDePasse();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUsername() {
|
||||
return user.getEmail();
|
||||
}
|
||||
|
||||
@Override public boolean isAccountNonExpired() { return true; }
|
||||
@Override public boolean isAccountNonLocked() { return true; }
|
||||
@Override public boolean isCredentialsNonExpired() { return true; }
|
||||
@Override public boolean isEnabled() { return user.isActif(); }
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package local.epul4a.fotosharing.security;
|
||||
|
||||
import local.epul4a.fotosharing.model.Utilisateur;
|
||||
import local.epul4a.fotosharing.repository.UtilisateurRepository;
|
||||
import org.springframework.security.core.userdetails.UsernameNotFoundException;
|
||||
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Service
|
||||
public class CustomUserDetailsService implements UserDetailsService {
|
||||
|
||||
private final UtilisateurRepository utilisateurRepository;
|
||||
|
||||
public CustomUserDetailsService(UtilisateurRepository utilisateurRepository) {
|
||||
this.utilisateurRepository = utilisateurRepository;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CustomUserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
|
||||
Utilisateur u = utilisateurRepository.findByEmail(username)
|
||||
.orElseThrow(() -> new UsernameNotFoundException("Utilisateur introuvable: " + username));
|
||||
return new CustomUserDetails(u);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
package local.epul4a.fotosharing.security;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.security.authentication.AuthenticationManager;
|
||||
import org.springframework.security.config.Customizer;
|
||||
import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;
|
||||
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||
import org.springframework.security.web.SecurityFilterChain;
|
||||
|
||||
@Configuration
|
||||
@EnableMethodSecurity
|
||||
public class SecurityConfig {
|
||||
|
||||
private final CustomUserDetailsService customUserDetailsService;
|
||||
|
||||
public SecurityConfig(CustomUserDetailsService customUserDetailsService) {
|
||||
this.customUserDetailsService = customUserDetailsService;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
|
||||
|
||||
http
|
||||
.authorizeHttpRequests(auth -> auth
|
||||
.requestMatchers("/login", "/register", "/css/**", "/js/**").permitAll()
|
||||
.anyRequest().authenticated()
|
||||
)
|
||||
.formLogin(form -> form
|
||||
.loginPage("/login")
|
||||
.defaultSuccessUrl("/", true)
|
||||
.permitAll()
|
||||
)
|
||||
.logout(logout -> logout
|
||||
.logoutSuccessUrl("/login?logout=true")
|
||||
.permitAll()
|
||||
)
|
||||
.csrf(csrf -> csrf.disable());
|
||||
|
||||
return http.build();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public UserDetailsService userDetailsService() {
|
||||
// Spring Security 6.2 utilise ce bean automatiquement
|
||||
return customUserDetailsService;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public AuthenticationManager authenticationManager(AuthenticationConfiguration config) throws Exception {
|
||||
// Spring Boot crée automatiquement un DaoAuthenticationProvider interne
|
||||
return config.getAuthenticationManager();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public PasswordEncoder passwordEncoder() {
|
||||
return new BCryptPasswordEncoder();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package local.epul4a.fotosharing.security;
|
||||
|
||||
import local.epul4a.fotosharing.model.Photo;
|
||||
import local.epul4a.fotosharing.repository.PhotoRepository;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
@Service("securityService")
|
||||
public class SecurityService {
|
||||
|
||||
private final PhotoRepository photoRepository;
|
||||
|
||||
public SecurityService(PhotoRepository photoRepository) {
|
||||
this.photoRepository = photoRepository;
|
||||
}
|
||||
|
||||
public boolean canAccessPhoto(org.springframework.security.core.Authentication authentication, Long photoId) {
|
||||
if (authentication == null || !authentication.isAuthenticated()) return false;
|
||||
String username = authentication.getName(); // email
|
||||
Optional<Photo> p = photoRepository.findById(photoId);
|
||||
if (p.isEmpty()) return false;
|
||||
Photo photo = p.get();
|
||||
if (photo.getVisibilite() == Photo.Visibilite.PUBLIC) return true;
|
||||
if (photo.getProprietaire() != null && photo.getProprietaire().getEmail().equals(username)) return true;
|
||||
// TODO: vérifier table partage
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
package local.epul4a.fotosharing.service;
|
||||
|
||||
import local.epul4a.fotosharing.model.Photo;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Path;
|
||||
|
||||
public interface PhotoService {
|
||||
Photo store(MultipartFile file, String visibilite, String ownerEmail) throws IOException;
|
||||
Path loadAsPath(String uuidFile);
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
package local.epul4a.fotosharing.service.impl;
|
||||
|
||||
import local.epul4a.fotosharing.model.Photo;
|
||||
import local.epul4a.fotosharing.model.Utilisateur;
|
||||
import local.epul4a.fotosharing.repository.PhotoRepository;
|
||||
import local.epul4a.fotosharing.repository.UtilisateurRepository;
|
||||
import local.epul4a.fotosharing.service.PhotoService;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.*;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.UUID;
|
||||
|
||||
@Service
|
||||
public class PhotoServiceImpl implements PhotoService {
|
||||
|
||||
@Value("${file.upload-dir}")
|
||||
private String uploadDir;
|
||||
|
||||
private final PhotoRepository photoRepository;
|
||||
private final UtilisateurRepository utilisateurRepository;
|
||||
|
||||
public PhotoServiceImpl(PhotoRepository photoRepository, UtilisateurRepository utilisateurRepository) {
|
||||
this.photoRepository = photoRepository;
|
||||
this.utilisateurRepository = utilisateurRepository;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Photo store(MultipartFile file, String visibilite, String ownerEmail) throws IOException {
|
||||
if (file.isEmpty()) throw new IOException("Fichier vide");
|
||||
|
||||
// Vérifier taille / type si besoin (ici basique)
|
||||
String original = StringUtils.cleanPath(file.getOriginalFilename());
|
||||
String uuid = UUID.randomUUID().toString() + "-" + original;
|
||||
|
||||
Path uploadPath = Paths.get(uploadDir);
|
||||
if (!Files.exists(uploadPath)) Files.createDirectories(uploadPath);
|
||||
|
||||
Path target = uploadPath.resolve(uuid);
|
||||
Files.copy(file.getInputStream(), target, StandardCopyOption.REPLACE_EXISTING);
|
||||
|
||||
Photo p = new Photo();
|
||||
p.setNomFichierOriginal(original);
|
||||
p.setUuidFichier(uuid);
|
||||
p.setDateUpload(LocalDateTime.now());
|
||||
p.setVisibilite(Photo.Visibilite.valueOf(visibilite));
|
||||
Utilisateur u = utilisateurRepository.findByEmail(ownerEmail).orElseThrow(() -> new IOException("Utilisateur introuvable"));
|
||||
p.setProprietaire(u);
|
||||
|
||||
return photoRepository.save(p);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Path loadAsPath(String uuidFile) {
|
||||
return Paths.get(uploadDir).resolve(uuidFile);
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,7 @@ spring.application.name=FotoSharing
|
||||
# ===============================
|
||||
# DATABASE
|
||||
# ===============================
|
||||
spring.datasource.url=jdbc:mariadb://192.168.124.171:3306/fotoshareDB
|
||||
spring.datasource.url=jdbc:mariadb://192.168.112.10:3306/fotoshareDB
|
||||
spring.datasource.username=ufoto
|
||||
spring.datasource.password=4AinfoRep-25
|
||||
# ===============================
|
||||
@@ -12,6 +12,14 @@ spring.datasource.password=4AinfoRep-25
|
||||
spring.jpa.hibernate.ddl-auto=update
|
||||
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MariaDBDialect
|
||||
spring.jpa.show-sql=true
|
||||
spring.jpa.properties.hibernate.format_sql=true
|
||||
spring.thymeleaf.prefix=classpath:/templates/
|
||||
spring.thymeleaf.suffix=.html
|
||||
spring.thymeleaf.mode=HTML
|
||||
spring.jpa.properties.hibernate.jdbc.time_zone=UTC
|
||||
# ===============================
|
||||
# EMPLACEMENT DE STICKAGE
|
||||
# ===============================
|
||||
file.upload-dir=/opt/photo-app/uploads
|
||||
spring.servlet.multipart.max-file-size=20MB
|
||||
spring.servlet.multipart.max-request-size=20MB
|
||||
9
src/main/resources/templates/home.html
Normal file
9
src/main/resources/templates/home.html
Normal file
@@ -0,0 +1,9 @@
|
||||
<!doctype html>
|
||||
<html xmlns:th="http://www.thymeleaf.org">
|
||||
<head><meta charset="utf-8"/><title>Accueil</title></head>
|
||||
<body>
|
||||
<h1>Bienvenue sur FotoSharing</h1>
|
||||
<p><a th:href="@{/upload}">Uploader une photo</a></p>
|
||||
<p><a th:href="@{/logout}">Se déconnecter</a></p>
|
||||
</body>
|
||||
</html>
|
||||
23
src/main/resources/templates/login.html
Normal file
23
src/main/resources/templates/login.html
Normal file
@@ -0,0 +1,23 @@
|
||||
<!doctype html>
|
||||
<html xmlns:th="http://www.thymeleaf.org">
|
||||
<head>
|
||||
<meta charset="utf-8"/>
|
||||
<title>Login - FotoSharing</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Connexion</h1>
|
||||
<form th:action="@{/login}" method="post">
|
||||
<label>Email: <input type="text" name="username"/></label><br/>
|
||||
<label>Mot de passe: <input type="password" name="password"/></label><br/>
|
||||
<button type="submit">Se connecter</button>
|
||||
</form>
|
||||
|
||||
<div th:if="${param.logout}">
|
||||
Déconnecté avec succès.
|
||||
</div>
|
||||
<div th:if="${param.error}">
|
||||
Erreur d'authentification.
|
||||
</div>
|
||||
<p><a th:href="@{/register}">Créer un compte</a></p>
|
||||
</body>
|
||||
</html>
|
||||
17
src/main/resources/templates/register.html
Normal file
17
src/main/resources/templates/register.html
Normal file
@@ -0,0 +1,17 @@
|
||||
<!doctype html>
|
||||
<html xmlns:th="http://www.thymeleaf.org">
|
||||
<head>
|
||||
<meta charset="utf-8"/>
|
||||
<title>Inscription - FotoSharing</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Inscription</h1>
|
||||
<form th:action="@{/register}" th:object="${utilisateur}" method="post">
|
||||
<label>Email: <input th:field="*{email}" /></label><br/>
|
||||
<label>Nom: <input th:field="*{nom}" /></label><br/>
|
||||
<label>Prénom: <input th:field="*{prenom}" /></label><br/>
|
||||
<label>Mot de passe: <input th:field="*{motDePasse}" type="password"/></label><br/>
|
||||
<button type="submit">Créer</button>
|
||||
</form>
|
||||
</body>
|
||||
</html>
|
||||
23
src/main/resources/templates/upload.html
Normal file
23
src/main/resources/templates/upload.html
Normal file
@@ -0,0 +1,23 @@
|
||||
<!doctype html>
|
||||
<html xmlns:th="http://www.thymeleaf.org">
|
||||
<head>
|
||||
<meta charset="utf-8"/>
|
||||
<title>Upload - FotoSharing</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Uploader une photo</h1>
|
||||
<form th:action="@{/upload}" method="post" enctype="multipart/form-data">
|
||||
<input type="file" name="file"/><br/>
|
||||
<label>Visibilité:
|
||||
<select name="visibilite">
|
||||
<option value="PRIVATE">Privée</option>
|
||||
<option value="PUBLIC">Publique</option>
|
||||
<option value="SHARED">Partagée</option>
|
||||
</select>
|
||||
</label><br/>
|
||||
<button type="submit">Envoyer</button>
|
||||
</form>
|
||||
<div th:if="${error}" th:text="${error}"></div>
|
||||
<div th:if="${message}" th:text="${message}"></div>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user