This commit is contained in:
Wowieee4
2026-05-02 02:43:47 +07:00
parent f8ca77eeb9
commit c8d9eefa74
14 changed files with 1207 additions and 209 deletions
@@ -1,48 +1,48 @@
package com.walkguide.config;
import org.springframework.boot.CommandLineRunner;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Component;
import com.walkguide.entity.User;
import com.walkguide.repository.UserRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.boot.CommandLineRunner;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Component;
@Component
@RequiredArgsConstructor
public class DataSeeder implements CommandLineRunner {
private final UserRepository userRepository;
private final PasswordEncoder passwordEncoder;
@Override
public void run(String... args) throws Exception {
// Mesin enkripsi password
PasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
// Ngecek kalau tabel users kosong, baru diisi
if (userRepository.count() == 0) {
// 1. Bikin akun Guardian (Pendamping)
// 1. Buat Guardian (tanpa connected_to dulu)
User guardian = User.builder()
.email("guardian@walkguide.com")
.password(passwordEncoder.encode("guardian123")) // Password barunya
.role("ROLE_GUARDIAN") // Role udah diganti
.password(passwordEncoder.encode("guardian123"))
.role("ROLE_GUARDIAN")
.build();
guardian = userRepository.save(guardian);
// 2. Bikin akun User (Tunanetra)
// 2. Buat User Tunanetra, langsung sambungkan ke Guardian
User user = User.builder()
.email("user@walkguide.com")
.password(passwordEncoder.encode("user123"))
.role("ROLE_USER")
.connectedTo(guardian)
.build();
user = userRepository.save(user);
// Simpan ke database
// 3. Update Guardian -> sambungkan balik ke User yang dijaganya
guardian.setConnectedTo(user);
userRepository.save(guardian);
userRepository.save(user);
System.out.println("✅ Data Seeder berhasil: Akun Guardian dan User telah masuk ke Database!");
System.out.println("DataSeeder: Guardian (" + guardian.getId()
+ ") <-> User (" + user.getId() + ") berhasil dihubungkan!");
} else {
System.out.println("DataSeeder: Database sudah ada data, skip seeding.");
}
}
}
}
@@ -1,7 +1,12 @@
package com.walkguide.controller;
import java.util.Map;
import com.walkguide.dto.ApiResponse;
import com.walkguide.entity.User;
import com.walkguide.repository.UserRepository;
import com.walkguide.security.JwtUtil;
import com.walkguide.service.MockDataService;
import jakarta.servlet.http.HttpServletRequest;
import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PutMapping;
@@ -9,10 +14,7 @@ import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.walkguide.dto.ApiResponse;
import com.walkguide.service.MockDataService;
import lombok.RequiredArgsConstructor;
import java.util.Map;
@RestController
@RequestMapping("/api/guardian")
@@ -20,24 +22,56 @@ import lombok.RequiredArgsConstructor;
public class GuardianController {
private final MockDataService mockDataService;
private final UserRepository userRepository;
private final JwtUtil jwtUtil;
// 4. Ambil Status User
// 4. Ambil Status User yang dimonitor
@GetMapping("/user-status")
public ResponseEntity<ApiResponse<Map<String, Object>>> getUserStatus() {
return ResponseEntity.ok(new ApiResponse<>(true, mockDataService.getUserStatus(), "Data status user berhasil diambil"));
return ResponseEntity.ok(new ApiResponse<>(true,
mockDataService.getUserStatus(),
"Data status user berhasil diambil"));
}
// 5. Setting Hardware Shortcut
@PutMapping("/settings/shortcuts")
public ResponseEntity<ApiResponse<Map<String, Object>>> updateShortcuts(@RequestBody Map<String, Object> request) {
public ResponseEntity<ApiResponse<Map<String, Object>>> updateShortcuts(
@RequestBody Map<String, Object> request) {
Map<String, Object> updated = mockDataService.updateShortcuts(request);
return ResponseEntity.ok(new ApiResponse<>(true, updated, "Shortcut berhasil diperbarui"));
}
// 6. Setting Sensitivitas AI
@PutMapping("/settings/ai")
public ResponseEntity<ApiResponse<Map<String, Object>>> updateAiSettings(@RequestBody Map<String, Object> request) {
public ResponseEntity<ApiResponse<Map<String, Object>>> updateAiSettings(
@RequestBody Map<String, Object> request) {
Map<String, Object> updated = mockDataService.updateAiSettings(request);
return ResponseEntity.ok(new ApiResponse<>(true, updated, "Setting AI berhasil diperbarui"));
}
}
// 7. Lihat User yang terhubung ke Guardian ini
@GetMapping("/my-user")
public ResponseEntity<ApiResponse<Map<String, Object>>> getMyConnectedUser(
HttpServletRequest request) {
String token = request.getHeader("Authorization").substring(7);
String email = jwtUtil.extractUsername(token);
User guardian = userRepository.findByEmail(email)
.orElseThrow(() -> new RuntimeException("Guardian tidak ditemukan"));
User connectedUser = guardian.getConnectedTo();
if (connectedUser == null) {
return ResponseEntity.ok(new ApiResponse<>(true,
Map.of("message", "Belum ada user yang terhubung"),
"Tidak ada koneksi"));
}
Map<String, Object> data = Map.of(
"userId", connectedUser.getId(),
"userEmail", connectedUser.getEmail(),
"connectedSince", connectedUser.getCreatedAt().toString()
);
return ResponseEntity.ok(new ApiResponse<>(true, data,
"Data user yang dipantau berhasil diambil"));
}
}
@@ -1,24 +1,60 @@
package com.walkguide.controller;
import java.util.Map;
import com.walkguide.dto.ApiResponse;
import com.walkguide.entity.User;
import com.walkguide.repository.UserRepository;
import com.walkguide.security.JwtUtil;
import jakarta.servlet.http.HttpServletRequest;
import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
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.RestController;
import com.walkguide.dto.ApiResponse;
import java.util.Map;
@RestController
@RequestMapping("/api/user")
@RequiredArgsConstructor
public class UserController {
// 7. Sinyal Darurat (Voice Command)
private final UserRepository userRepository;
private final JwtUtil jwtUtil;
// Sinyal Darurat (Voice Command)
@PostMapping("/emergency")
public ResponseEntity<ApiResponse<String>> triggerEmergency(@RequestBody Map<String, Object> request) {
// Simulasi mengirim notif ke Guardian
public ResponseEntity<ApiResponse<String>> triggerEmergency(
@RequestBody Map<String, Object> request) {
String triggerType = (String) request.get("triggerType");
return ResponseEntity.ok(new ApiResponse<>(true, "Darurat Terkirim", "Guardian telah diberi peringatan via: " + triggerType));
return ResponseEntity.ok(new ApiResponse<>(true,
"Darurat Terkirim",
"Guardian telah diberi peringatan via: " + triggerType));
}
}
// Lihat Guardian yang terhubung ke User ini
@GetMapping("/my-guardian")
public ResponseEntity<ApiResponse<Map<String, Object>>> getMyGuardian(
HttpServletRequest request) {
String token = request.getHeader("Authorization").substring(7);
String email = jwtUtil.extractUsername(token);
User user = userRepository.findByEmail(email)
.orElseThrow(() -> new RuntimeException("User tidak ditemukan"));
User guardian = user.getConnectedTo();
if (guardian == null) {
return ResponseEntity.ok(new ApiResponse<>(true,
Map.of("message", "Belum ada guardian yang terhubung"),
"Tidak ada koneksi"));
}
Map<String, Object> data = Map.of(
"guardianId", guardian.getId(),
"guardianEmail", guardian.getEmail()
);
return ResponseEntity.ok(new ApiResponse<>(true, data,
"Data guardian berhasil diambil"));
}
}
@@ -2,15 +2,22 @@ package com.walkguide.entity;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.FetchType;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.ManyToOne;
import jakarta.persistence.PrePersist;
import jakarta.persistence.PreUpdate;
import jakarta.persistence.Table;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.time.Instant;
@Entity
@Table(name = "users")
@Data
@@ -18,20 +25,39 @@ import lombok.NoArgsConstructor;
@NoArgsConstructor
@AllArgsConstructor
public class User {
// Ini otomatis bikin ID angka urut (1, 2, 3, dst)
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
// Email gak boleh kosong dan gak boleh ada yang kembar
@Column(unique = true, nullable = false)
private String email;
@Column(nullable = false)
private String password;
// Buat nandain dia ini ROLE_USER atau ROLE_ADMIN
@Column(nullable = false)
private String role;
}
private String role;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "connected_to")
private User connectedTo;
@Column(name = "created_at", nullable = false, updatable = false)
private Instant createdAt;
@Column(name = "updated_at", nullable = false)
private Instant updatedAt;
@PrePersist
public void onCreate() {
Instant now = Instant.now();
this.createdAt = now;
this.updatedAt = now;
}
@PreUpdate
public void onUpdate() {
this.updatedAt = Instant.now();
}
}
@@ -1,16 +1,21 @@
package com.walkguide.repository;
import com.walkguide.entity.User;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;
import java.util.Optional;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import com.walkguide.entity.User;
@Repository
public interface UserRepository extends JpaRepository<User, Long> {
// Ini fungsi ajaib Spring Boot. Cuma dari nama fungsinya aja,
// dia udah tau maksudnya "Tolong cariin user di database yang emailnya = X"
Optional<User> findByEmail(String email);
}
@Query("SELECT u FROM User u WHERE u.connectedTo.id = :guardianId AND u.role = 'ROLE_USER'")
Optional<User> findUserByGuardianId(@Param("guardianId") Long guardianId);
@Query("SELECT u FROM User u WHERE u.connectedTo.id = :userId AND u.role = 'ROLE_GUARDIAN'")
Optional<User> findGuardianByUserId(@Param("userId") Long userId);
}