Skip to content

Commit

Permalink
Integrate media (#150)
Browse files Browse the repository at this point in the history
* add field in user

* xx

* show image admin page

* fix show header

* config email and view image
  • Loading branch information
khanhduzz authored Sep 27, 2024
1 parent 57bbb81 commit ad8d54c
Show file tree
Hide file tree
Showing 17 changed files with 133 additions and 55 deletions.
4 changes: 3 additions & 1 deletion .env.sample
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,6 @@ EMAIL_SERVER=tranquangg.1108@gmail.com
PASSWORD_EMAIL_SERVER=bfmh plln fzfm llst
RECAPTCHA_SECRET_KEY=6LfblD0qAAAAAO2lT_e5JwmxUFJ55uCpxPrdwk0T
RECAPTCHA_SITE_KEY=6LfblD0qAAAAAC1k-Zd8GfiyXmKjNWBV4xMC1BNP
CAPTCHA_ENABLE=false
CAPTCHA_ENABLE=false

EMAIL_VERIFY=http://localhost:8086/sun/auth/verify?code="
1 change: 1 addition & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ services:
- RECAPTCHA_SITE_KEY
- CAPTCHA_ENABLE=true
- TIMING_SEND_EMAIL
- EMAIL_VERIFY
ports:
- ${SERVER_LOCAL_PORT}:${SERVER_LOCAL_PORT}
volumes:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ public ModelAndView uploadFile(@RequestParam("file") MultipartFile file) {
} catch (Exception ignored) {
throw new BadRequestException("Error when upload file");
}
return new ModelAndView("redirect:/medias");
return new ModelAndView("redirect:/medias/files");
}

@GetMapping("/files")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,13 @@ public ModelAndView getUserInfo() {

@PreAuthorize("hasRole('USER') or hasRole('ADMIN')")
@PostMapping("/edit-infor")
public ModelAndView editUserInfo(@ModelAttribute("userInfor") UserResponseDTO userResponseDTO) {
public ModelAndView editUserInfo(@ModelAttribute("userInfor") UserResponseDTO userResponseDTO,
BindingResult bindingResult) {
ModelAndView modelAndView = new ModelAndView();
boolean editInfor = userService.editUser(userResponseDTO);
if (bindingResult.hasErrors()) {
return new ModelAndView("redirect:/user/edit-infor");
}
if (editInfor) {
modelAndView.setViewName(Constants.ApiConstant.USER_CHANGE_INFO_SUCCESS);
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import java.time.LocalDateTime;
import lombok.Getter;
import lombok.Setter;
import org.springframework.web.multipart.MultipartFile;

@Getter
@Setter
Expand All @@ -20,4 +21,5 @@ public class CreateAndEditUserByAdminDTO {
private LocalDateTime createdDate;
private String lastModifiedBy;
private LocalDateTime lastModifiedDate;
private MultipartFile fileCode;
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,5 @@ public class UserResponseDTO {
private String email;
private String phone;
private String role;
private String fileCode;
}
4 changes: 4 additions & 0 deletions src/main/java/com/fjb/sunrise/mappers/UserMapper.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,16 @@
import com.fjb.sunrise.dtos.responses.UserResponseDTO;
import com.fjb.sunrise.models.User;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;

@Mapper(componentModel = "spring")
public interface UserMapper {
@Mapping(target = "fileCode", ignore = true)
User toEntity(RegisterRequest request);

@Mapping(target = "fileCode", ignore = true)
User toEntityCreateByAdmin(CreateAndEditUserByAdminDTO byAdminDTO);

@Mapping(target = "fileCode", ignore = true)
UserResponseDTO toUserResponse(User user);
}
3 changes: 3 additions & 0 deletions src/main/java/com/fjb/sunrise/models/User.java
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,9 @@ public class User extends AuditEntity<String> implements Serializable, UserDetai
@Column(name = "verification_code")
private String verificationCode;

@Column(name = "file_code")
private String fileCode;

@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return List.of(new SimpleGrantedAuthority("ROLE_" + this.role.name()));
Expand Down
21 changes: 14 additions & 7 deletions src/main/java/com/fjb/sunrise/services/MediaService.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,18 +19,24 @@ public class MediaService {

private final MediaRepository mediaRepository;

public Media store(MultipartFile file) throws IOException {
@Transactional
public Media store(MultipartFile file) {
if (file == null || file.getOriginalFilename() == null) {
throw new BadRequestException("File is null");
}
String fileName = StringUtils.cleanPath(file.getOriginalFilename());
String fileCode = UUID.randomUUID().toString();
Media media = Media.builder()
.name(fileName)
.type(file.getContentType())
.data(file.getBytes())
.fileCode(fileCode)
.build();
Media media;
try {
media = Media.builder()
.name(fileName)
.type(file.getContentType())
.data(file.getBytes())
.fileCode(fileCode)
.build();
} catch (IOException e) {
throw new BadRequestException("Error when save file");
}

return mediaRepository.save(media);
}
Expand All @@ -40,6 +46,7 @@ public Media getMedia(String fileCode) {
return mediaRepository.findByFileCode(fileCode);
}

@Transactional
public Stream<Media> getAllMedias() {
return mediaRepository.findAll().stream();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@ public class EmailServiceImpl implements EmailService {
@Value("${spring.mail.username}")
private String emailServer;

@Value("${email.verify-link}")
private String emailLink;

private static final int TIME = 300;

private final UserRepository userRepository;
Expand Down Expand Up @@ -71,7 +74,7 @@ private void sendMailAsync(VerificationByEmail verification, String code) {

String htmlMsg = "<h3>Thay đổi mật khẩu</h3>"
+ "<p>Nhấn vào nút dưới đây để thay đổi mật khẩu:</p>"
+ "<a href=\"http://localhost:8086/sun/auth/verify?code=" + code + "\" "
+ "<a href=\"" + emailLink + code + "\" "
+ "style=\"display:inline-block;"
+ "padding:10px 20px;"
+ "background-color:#4CAF50;"
Expand Down
16 changes: 15 additions & 1 deletion src/main/java/com/fjb/sunrise/services/impl/UserServiceImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,10 @@
import com.fjb.sunrise.exceptions.DuplicatedException;
import com.fjb.sunrise.exceptions.NotFoundException;
import com.fjb.sunrise.mappers.UserMapper;
import com.fjb.sunrise.models.Media;
import com.fjb.sunrise.models.User;
import com.fjb.sunrise.repositories.UserRepository;
import com.fjb.sunrise.services.MediaService;
import com.fjb.sunrise.services.UserService;
import com.fjb.sunrise.utils.Constants;
import java.util.List;
Expand All @@ -25,17 +27,20 @@
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

@Service
@RequiredArgsConstructor
@Transactional
public class UserServiceImpl implements UserService {
private final UserMapper userMapper;
@Value("${default.admin-create-key}")
private String key;
private final UserMapper mapper;
private final UserRepository userRepository;
private final PasswordEncoder passwordEncoder;
private final MediaService mediaService;

@Override
public String checkRegister(RegisterRequest registerRequest) {
Expand Down Expand Up @@ -75,8 +80,13 @@ public String changePassword(String email, String password) {
}

@Override
@Transactional
public User createUserByAdmin(CreateAndEditUserByAdminDTO byAdminDTO) {
User user = mapper.toEntityCreateByAdmin(byAdminDTO);
if (byAdminDTO.getFileCode() != null) {
Media media = mediaService.store(byAdminDTO.getFileCode());
user.setFileCode(media.getFileCode());
}
user.setUsername(byAdminDTO.getUsername());
user.setPassword(passwordEncoder.encode(byAdminDTO.getPassword()));
user.setFirstname(byAdminDTO.getFirstname());
Expand All @@ -91,10 +101,14 @@ public User createUserByAdmin(CreateAndEditUserByAdminDTO byAdminDTO) {
}

@Override
@Transactional
public boolean updateUserByAdmin(CreateAndEditUserByAdminDTO byAdminDTO) {
User user = userRepository.findById(byAdminDTO.getId())
.orElseThrow(() -> new NotFoundException("User not found"));

if (byAdminDTO.getFileCode() != null) {
Media media = mediaService.store(byAdminDTO.getFileCode());
user.setFileCode(media.getFileCode());
}
user.setUsername(byAdminDTO.getUsername());
user.setFirstname(byAdminDTO.getFirstname());
user.setLastname(byAdminDTO.getLastname());
Expand Down
5 changes: 4 additions & 1 deletion src/main/resources/application.yml
Original file line number Diff line number Diff line change
Expand Up @@ -70,4 +70,7 @@ default:
type-encode: ${TYPE_ENCODE}
recaptcha-secret-key: ${RECAPTCHA_SECRET_KEY}
recaptcha-site-key: ${RECAPTCHA_SITE_KEY}
captcha-enable: ${CAPTCHA_ENABLE}
captcha-enable: ${CAPTCHA_ENABLE}

email:
verify-link: ${EMAIL_VERIFY}
9 changes: 8 additions & 1 deletion src/main/resources/templates/header.html
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,14 @@
data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"
onkeydown="">
<span class="mr-2 d-none d-lg-inline text-gray-600 small" sec:authentication="name"></span>
<img alt="profile" class="img-profile rounded-circle" th:src="@{/img/undraw_profile.svg}">
<div sec:authorize="isAuthenticated()">
<img alt="profile" class="img-profile rounded-circle" th:src="@{/img/undraw_profile.svg}">
</div>
<!-- <div sec:authorize="isAuthenticated()">-->
<!-- <img alt="profile" class="img-profile rounded-circle"-->
<!-- th:src="@{/medias/media/${#authentication.principal.fileCode}}" />-->
<!-- File Code: <span th:text="${#authentication.principal.fileCode}"></span>-->
<!-- </div>-->
</a>
<!-- Dropdown - User Information -->
<div class="dropdown-menu dropdown-menu-right shadow animated--grow-in"
Expand Down
11 changes: 4 additions & 7 deletions src/main/resources/templates/health.html
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,10 @@ <h2>Welcome</h2>
<div class="nav-item me-3" sec:authorize="isAuthenticated()">
<a class="btn btn-outline-danger" style="width: 300px" th:href="@{/logout}">Logout</a>
</div>
<!-- <div sec:authorize="isAuthenticated()">-->
<!-- Roles: <span sec:authentication="principal.authorities"></span><br>-->
<!-- File Code: <span th:text="${#authentication.principal.fileCode}"></span>-->
<!-- </div>-->
</div>
<div th:replace="~{footer :: footer}"></div>
</div>
Expand All @@ -58,13 +62,6 @@ <h2>Welcome</h2>
<!-- Custom scripts for all pages-->
<script src="js/sb-admin-2.min.js"></script>

<!-- Page level plugins -->
<script src="vendor/chart.js/Chart.min.js"></script>

<!-- Page level custom scripts -->
<script src="js/demo/chart-area-demo.js"></script>
<script src="js/demo/chart-pie-demo.js"></script>

<!-- Page level plugins -->
<script src="vendor/datatables/jquery.dataTables.min.js"></script>
<script src="vendor/datatables/dataTables.bootstrap4.min.js"></script>
Expand Down
82 changes: 50 additions & 32 deletions src/main/resources/templates/user/admin-page.html
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ <h6 class="m-0 font-weight-bold text-primary">Danh sách người dùng</h6>
<thead>
<tr>
<th>ID</th>
<th>Avatar</th>
<th>Địa chỉ Email</th>
<th>Trạng thái tài khoản</th>
<th>Vai trò</th>
Expand Down Expand Up @@ -107,9 +108,6 @@ <h5 class="modal-title" id="exampleModalLabel">Bạn có muốn thoát?</h5>
<script th:src="@{/vendor/bootstrap/js/bootstrap.bundle.min.js}" type="application/javascript"></script>
<script th:src="@{/vendor/jquery-easing/jquery.easing.min.js}" type="application/javascript"></script>
<script th:src="@{/js/sb-admin-2.min.js}" type="application/javascript"></script>
<script th:src="@{/vendor/chart.js/Chart.min.js}" type="application/javascript"></script>
<script th:src="@{/js/demo/chart-area-demo.js}" type="application/javascript"></script>
<script th:src="@{/js/demo/chart-pie-demo.js}" type="application/javascript"></script>
<script th:src="@{/vendor/datatables/jquery.dataTables.min.js}" type="application/javascript"></script>
<script th:src="@{/vendor/datatables/dataTables.bootstrap4.min.js}" type="application/javascript"></script>

Expand Down Expand Up @@ -158,46 +156,66 @@ <h5 class="modal-title" id="exampleModalLabel">Bạn có muốn thoát?</h5>
};

const cols = [
{"data": "id"},
{"data": "email"},
{"data": "status", "render": function(data, type, row) {
{"data": "id", "className": "text-center align-middle"},
{
"data": "fileCode",
"render": function(data, type, row) {
return `<div class="d-flex justify-content-center align-items-center" style="height: 100%"><img src="/sun/medias/media/${data}" alt="user" style="width:50px;height:50px;"></div>`;
},
"className": "text-center align-middle"
},
{"data": "email", "className": "text-center align-middle"},
{
"data": "status",
"render": function(data, type, row) {
return translateStatus(data);
}
},
"className": "text-center align-middle"
},
{"data": "role", "render": function(data, type, row) {
{
"data": "role",
"render": function(data, type, row) {
return translateRole(data);
}
},
"className": "text-center align-middle"
},
{"data": null, "render": function(data, type, row) {
{
"data": null,
"render": function(data, type, row) {
if (row.id === currentUserId) {
return `
<div class="btn-group" role="group" aria-label="User Actions">
<button class="btn btn-outline-info" disabled>
<i class="fas fa-info-circle"></i>
</button>
<button class="btn btn-outline-danger" disabled>
<i class="fas fa-trash-alt"></i>
</button>
<button class="btn btn-outline-warning" disabled>
<i class="fas fa-ban"></i>
</button>
<div class="d-flex justify-content-center align-items-center" style="height: 100%">
<div class="btn-group" role="group" aria-label="User Actions">
<button class="btn btn-outline-info" disabled>
<i class="fas fa-info-circle"></i>
</button>
<button class="btn btn-outline-danger" disabled>
<i class="fas fa-trash-alt"></i>
</button>
<button class="btn btn-outline-warning" disabled>
<i class="fas fa-ban"></i>
</button>
</div>
</div>`;
} else {
return `
<div class="btn-group" role="group" aria-label="User Actions">
<button class="btn btn-outline-info" onclick="viewUserDetail(${row.id})">
<i class="fas fa-info-circle"></i>
</button>
<button class="btn btn-outline-danger" onclick="deleteUser(${row.id})">
<i class="fas fa-trash-alt"></i>
</button>
<button class="btn ${row.status === 'ACTIVE' ? 'btn-outline-warning' : 'btn-outline-success'}"
onclick="changeUserStatus(${row.id}, '${row.status === 'ACTIVE' ? 'deactivate' : 'activate'}')">
<i class="fas ${row.status === 'ACTIVE' ? 'fa-ban' : 'fa-check-circle'}"></i>
</button>
<div class="d-flex justify-content-center align-items-center" style="height: 100%">
<div class="btn-group" role="group" aria-label="User Actions">
<button class="btn btn-outline-info" onclick="viewUserDetail(${row.id})">
<i class="fas fa-info-circle"></i>
</button>
<button class="btn btn-outline-danger" onclick="deleteUser(${row.id})">
<i class="fas fa-trash-alt"></i>
</button>
<button class="btn ${row.status === 'ACTIVE' ? 'btn-outline-warning' : 'btn-outline-success'}"
onclick="changeUserStatus(${row.id}, '${row.status === 'ACTIVE' ? 'deactivate' : 'activate'}')">
<i class="fas ${row.status === 'ACTIVE' ? 'fa-ban' : 'fa-check-circle'}"></i>
</button>
</div>
</div>`;
}
}
},
"className": "text-center align-middle"
}
];

Expand Down
Loading

0 comments on commit ad8d54c

Please sign in to comment.