diff --git a/backend/RumahSehat/build.gradle b/backend/RumahSehat/build.gradle index 12931c6f2d447dd679ab53dcff8b3d59ab899c4d..f558d3ce99e41319e3abc6ec5716b5b38a934a63 100644 --- a/backend/RumahSehat/build.gradle +++ b/backend/RumahSehat/build.gradle @@ -15,6 +15,8 @@ repositories { dependencies { implementation 'org.springframework.boot:spring-boot-starter-thymeleaf' implementation 'org.springframework.boot:spring-boot-starter-web' + implementation 'org.projectlombok:lombok:1.18.22' + implementation 'org.projectlombok:lombok:1.18.22' developmentOnly 'org.springframework.boot:spring-boot-devtools' testImplementation 'org.springframework.boot:spring-boot-starter-test' implementation 'org.springframework.boot:spring-boot-starter-data-jpa' @@ -24,7 +26,8 @@ dependencies { annotationProcessor('org.projectlombok:lombok:1.18.24') implementation 'com.fasterxml.jackson.core:jackson-databind' implementation 'org.springframework.boot:spring-boot-starter-webflux' - + implementation 'org.springframework.boot:spring-boot-starter-security' + implementation 'com.auth0:java-jwt:4.2.1' } tasks.named('test') { diff --git a/backend/RumahSehat/src/main/java/apap/tugasakhir/RumahSehat/RumahSehatApplication.java b/backend/RumahSehat/src/main/java/apap/tugasakhir/RumahSehat/RumahSehatApplication.java index 51192fdaccc241fbef4d107e3d1da23fe666957e..c9a49cb339152a85f9da78764137c79bb7af2f21 100644 --- a/backend/RumahSehat/src/main/java/apap/tugasakhir/RumahSehat/RumahSehatApplication.java +++ b/backend/RumahSehat/src/main/java/apap/tugasakhir/RumahSehat/RumahSehatApplication.java @@ -1,7 +1,14 @@ package apap.tugasakhir.RumahSehat; +import java.util.ArrayList; + +import org.springframework.boot.CommandLineRunner; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.annotation.Bean; + +import apap.tugasakhir.RumahSehat.models.PasienModel; +import apap.tugasakhir.RumahSehat.service.PasienRestService; @SpringBootApplication public class RumahSehatApplication { @@ -10,4 +17,20 @@ public class RumahSehatApplication { SpringApplication.run(RumahSehatApplication.class, args); } + @Bean + CommandLineRunner run(PasienRestService pasienRestService) { + return args -> { + pasienRestService.addPasien(PasienModel.builder().email("zachra@gmail.com") + .isSso(false) + .listAppointment(new ArrayList<>()) + .nama("zachra") + .password("zachra") + .role("Pasien") + .saldo(0) + .username("zachra") + .umur(20) + .build()); + }; + } + } diff --git a/backend/RumahSehat/src/main/java/apap/tugasakhir/RumahSehat/config/JwtConfig.java b/backend/RumahSehat/src/main/java/apap/tugasakhir/RumahSehat/config/JwtConfig.java new file mode 100644 index 0000000000000000000000000000000000000000..857b232fd14878876af62ccec3e1bbcddf3d24b0 --- /dev/null +++ b/backend/RumahSehat/src/main/java/apap/tugasakhir/RumahSehat/config/JwtConfig.java @@ -0,0 +1,55 @@ +// package apap.tugasakhir.RumahSehat.config; + +// import java.util.Date; +// import java.util.HashMap; +// import java.util.Map; + +// import com.auth0.jwt.JWT; +// import com.auth0.jwt.JWTVerifier; +// import com.auth0.jwt.algorithms.Algorithm; +// import com.auth0.jwt.interfaces.DecodedJWT; + +// import org.springframework.beans.factory.annotation.Autowired; +// import org.springframework.beans.factory.annotation.Value; +// import org.springframework.security.core.userdetails.UserDetails; +// import org.springframework.stereotype.Component; + +// import apap.tugasakhir.RumahSehat.models.UserModel; +// import apap.tugasakhir.RumahSehat.service.UserService; + +// @Component +// public class JwtConfig { + +// @Autowired +// UserService userService; + +// public static final Long JWT_TOKEN_VALIDITY = 180000L; + +// @Value("${jwt.secret}") +// private String secret; + +// public String generateToken(UserDetails userDetails){ +// var now = new Date(System.currentTimeMillis()); +// var expDate = new Date(now.getTime() + JWT_TOKEN_VALIDITY); + +// String username = userDetails.getUsername(); +// UserModel user = userService.getUserByUsername(username); + +// Map<String, Object> claims = new HashMap<>(); +// claims.put("id", user.getUuid()); +// claims.put("username", username); +// claims.put("email", user.getEmail()); +// claims.put("role", user.getRole()); + +// return JWT.create() +// .withSubject(username) // with claim, this will be replaced +// .withExpiresAt(expDate) +// .withClaim("claims", claims) +// .sign(Algorithm.HMAC256(secret.getBytes())); +// } + +// public DecodedJWT verifyToken(String token){ +// JWTVerifier verifier = JWT.require(Algorithm.HMAC256(secret.getBytes())).build(); +// return verifier.verify(token); +// } +// } diff --git a/backend/RumahSehat/src/main/java/apap/tugasakhir/RumahSehat/config/WebSecurityConfig.java b/backend/RumahSehat/src/main/java/apap/tugasakhir/RumahSehat/config/WebSecurityConfig.java new file mode 100644 index 0000000000000000000000000000000000000000..bcf2cf47891fdb61f94c8b51d20eda8f3c3fda55 --- /dev/null +++ b/backend/RumahSehat/src/main/java/apap/tugasakhir/RumahSehat/config/WebSecurityConfig.java @@ -0,0 +1,68 @@ +package apap.tugasakhir.RumahSehat.config; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.authentication.AuthenticationManager; +import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; +import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; +import org.springframework.security.config.http.SessionCreationPolicy; +import org.springframework.security.core.userdetails.UserDetailsService; +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; +import org.springframework.security.web.SecurityFilterChain; +import org.springframework.security.web.util.matcher.AntPathRequestMatcher; + +// import apap.tugasakhir.RumahSehat.config.JwtRequestFilter; + +@Configuration +@EnableWebSecurity +public class WebSecurityConfig /*extends WebSecurityConfigurerAdapter*/{ + + // @Autowired + // private JwtRequestFilter jwtRequestFilter; + + @Autowired + private UserDetailsService userDetailsService; + + @Bean + public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { + http.csrf().disable() + .authorizeRequests() + .antMatchers("/css/**").permitAll() + .antMatchers("/js/**").permitAll() + .antMatchers("/**").permitAll() + .antMatchers("/login-sso", "/validate-ticket", "/authenticate").permitAll() + .anyRequest().authenticated() + .and() + .formLogin() + .loginPage("/login").permitAll() + .and() + .logout().logoutRequestMatcher(new AntPathRequestMatcher("/logout")) + .logoutSuccessUrl("/login").permitAll(); + return http.build(); + } + + // @Bean + // @Override + // public AuthenticationManager authenticationManagerBean() throws Exception{ + // return super.authenticationManagerBean(); + // } + + public BCryptPasswordEncoder encoder = new BCryptPasswordEncoder(); + + @Autowired + public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception { + auth.inMemoryAuthentication() + .passwordEncoder(encoder) + .withUser("Frans") + .password(encoder.encode("apap")) + .roles("Admin"); + } + + @Autowired + public void configAuthentication(AuthenticationManagerBuilder auth) throws Exception { + auth.userDetailsService(userDetailsService).passwordEncoder(encoder); + } +} \ No newline at end of file diff --git a/backend/RumahSehat/src/main/java/apap/tugasakhir/RumahSehat/controller/PageController.java b/backend/RumahSehat/src/main/java/apap/tugasakhir/RumahSehat/controller/PageController.java new file mode 100644 index 0000000000000000000000000000000000000000..9310a7e032078a6caf86bc9e4adae692a1081505 --- /dev/null +++ b/backend/RumahSehat/src/main/java/apap/tugasakhir/RumahSehat/controller/PageController.java @@ -0,0 +1,111 @@ +package apap.tugasakhir.RumahSehat.controller; + +import java.security.Principal; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpSession; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.context.SecurityContext; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.security.core.userdetails.User; +import org.springframework.security.web.context.HttpSessionSecurityContextRepository; +import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.reactive.function.client.WebClient; +import org.springframework.web.servlet.ModelAndView; + +import apap.tugasakhir.RumahSehat.models.AdminModel; +import apap.tugasakhir.RumahSehat.models.UserModel; +import apap.tugasakhir.RumahSehat.security.xml.Attributes; +import apap.tugasakhir.RumahSehat.security.xml.ServiceResponse; +import apap.tugasakhir.RumahSehat.service.AdminService; +import apap.tugasakhir.RumahSehat.service.UserService; +import apap.tugasakhir.RumahSehat.setting.Setting; + +@Controller +public class PageController { + @Autowired + UserService userService; + @Autowired + AdminService adminService; + + private WebClient webClient = WebClient.builder().build(); + + @RequestMapping("/") + private String home(Principal principal, Model model) { + if (principal == null){ + model.addAttribute("status", "annonymous"); + } else { + UserModel userModel = userService.getUserByUsername(principal.getName()); + String role = userModel.getRole(); + model.addAttribute("status", "loggedin"); + model.addAttribute("user", userModel); + model.addAttribute("role", role); + } + return "home"; + } + + @RequestMapping("/login") + private String login() { + return "login"; + } + + @GetMapping("/validate-ticket") + public ModelAndView adminLoginSSO( + @RequestParam(value = "ticket", required = false) String ticket, + HttpServletRequest request + ) { + ServiceResponse serviceResponse = this.webClient.get().uri( + String.format( + Setting.SERVER_VALIDATE_TICKET, + ticket, + Setting.CLIENT_LOGIN + ) + ).retrieve().bodyToMono(ServiceResponse.class).block(); + + Attributes attributes = serviceResponse.getAuthenticationSuccess().getAttributes(); + String username = serviceResponse.getAuthenticationSuccess().getUser(); + + UserModel user = userService.getUserByUsername(username); + + if (user == null) { + user = new AdminModel(); + user.setEmail(username + "@ui.ac.id"); + user.setNama(attributes.getNama()); + user.setPassword("rumahsehat"); + user.setUsername(username); + user.setIsSso(true); + user.setRole("Admin"); + adminService.addUser((AdminModel) user); + } + + Authentication authentication = new UsernamePasswordAuthenticationToken(username, "rumahsehat"); + + SecurityContext securityContext = SecurityContextHolder.getContext(); + securityContext.setAuthentication(authentication); + + HttpSession httpSession = request.getSession(true); + httpSession.setAttribute(HttpSessionSecurityContextRepository.SPRING_SECURITY_CONTEXT_KEY, securityContext); + + return new ModelAndView("redirect:/"); + } + @GetMapping(value = "/login-sso") + public ModelAndView loginSSO(Principal principal){ + return new ModelAndView("redirect:" + Setting.SERVER_LOGIN + Setting.CLIENT_LOGIN); + } + + @GetMapping(value = "/logout-sso") + public ModelAndView logoutSSO(Principal principal){ + UserModel user = userService.getUserByUsername(principal.getName()); + if (user.getIsSso() == false){ + return new ModelAndView("redirect:/logout"); + } + return new ModelAndView("redirect:" + Setting.SERVER_LOGOUT + Setting.CLIENT_LOGOUT); + } +} diff --git a/backend/RumahSehat/src/main/java/apap/tugasakhir/RumahSehat/controller/UserController.java b/backend/RumahSehat/src/main/java/apap/tugasakhir/RumahSehat/controller/UserController.java new file mode 100644 index 0000000000000000000000000000000000000000..c6714213d1ee8b89ca6a01bc77baccc48e295192 --- /dev/null +++ b/backend/RumahSehat/src/main/java/apap/tugasakhir/RumahSehat/controller/UserController.java @@ -0,0 +1,74 @@ +package apap.tugasakhir.RumahSehat.controller; + +import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.ModelAttribute; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; + +import apap.tugasakhir.RumahSehat.models.UserModel; +import apap.tugasakhir.RumahSehat.service.UserService; + +import java.util.ArrayList; +import java.util.List; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.security.core.userdetails.User; +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; + +@Controller +@RequestMapping("/user") +public class UserController { + @Autowired + private UserService userService; + + @GetMapping(value="/add") + private String addUserFormPage(Model model) { + List<String> listRole = new ArrayList<>(); + listRole.add("Dokter"); + listRole.add("Apoteker"); + Authentication auth = SecurityContextHolder.getContext().getAuthentication(); + User users = (User) auth.getPrincipal(); + String username = users.getUsername(); + UserModel userModel = userService.getUserByUsername(username); + if (userModel.getRole().equals("Admin")){ + UserModel user = new UserModel(); + model.addAttribute("user", user); + model.addAttribute("listRole", listRole); + return "form-add-user"; + } else { + return "invalid-role"; + } + } + + @PostMapping(value="/add") + private String addUserSubmit(@ModelAttribute UserModel user, Model model) { + user.setIsSso(false); + userService.addUser(user); + model.addAttribute("user", user); + return "redirect:/"; + } + + @GetMapping(value = "/viewall") + public String viewAllUser(Model model){ + List<UserModel> listUser = userService.findAll(); + Authentication auth = SecurityContextHolder.getContext().getAuthentication(); + User user = (User) auth.getPrincipal(); + String username = user.getUsername(); + UserModel userModel = userService.getUserByUsername(username); + model.addAttribute("user", userModel); + model.addAttribute("listUser", listUser); + if (userModel.getRole().equals("Admin")){ + return "viewall-user"; + } else { + return "invalid-role"; + } + } + + + +} diff --git a/backend/RumahSehat/src/main/java/apap/tugasakhir/RumahSehat/filter/JwtRequestFilter.java b/backend/RumahSehat/src/main/java/apap/tugasakhir/RumahSehat/filter/JwtRequestFilter.java new file mode 100644 index 0000000000000000000000000000000000000000..ed9957ab6dc0ea5df6e7bc6d5c3e49213f11bf38 --- /dev/null +++ b/backend/RumahSehat/src/main/java/apap/tugasakhir/RumahSehat/filter/JwtRequestFilter.java @@ -0,0 +1,74 @@ +// package apap.tugasakhir.RumahSehat.filter; + +// import java.io.IOException; +// import java.util.ArrayList; +// import java.util.List; + +// import javax.servlet.FilterChain; +// import javax.servlet.ServletException; +// import javax.servlet.http.HttpServletRequest; +// import javax.servlet.http.HttpServletResponse; + +// import org.springframework.beans.factory.annotation.Autowired; +// import org.springframework.http.HttpStatus; +// import org.springframework.stereotype.Component; +// import org.springframework.web.filter.OncePerRequestFilter; + +// import apap.tugasakhir.RumahSehat.config.JwtConfig; +// import lombok.RequiredArgsConstructor; +// import static org.springframework.http.HttpHeaders.AUTHORIZATION; + + +// @Component +// @RequiredArgsConstructor +// public class JwtRequestFilter extends OncePerRequestFilter{ + +// @Autowired +// private JwtConfig jwtConfig; + +// @Override +// protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) +// throws ServletException, IOException { + +// if (isPathAllowed(request.getServletPath())){ +// filterChain.doFilter(request,response); +// }else{ +// String authorizationHeader = request.getHeader(AUTHORIZATION); +// if(authorizationHeader!=null && authorizationHeader.startsWith("Bearer ")){ +// try { +// var token = authorizationHeader.substring("Bearer ".length()); +// jwtConfig.verifyToken(token); +// filterChain.doFilter(request,response); +// }catch(Exception e){ +// var authenticationException = new BaseResponse<>(false, HttpStatus.UNAUTHORIZED.value(), MESSAGE, null); +// response.setStatus(HttpStatus.FORBIDDEN.value()); +// response.getWriter().write(convertObjectToJson(authenticationException)); +// } +// } +// else { +// var authenticationException = new BaseResponse<>(false, HttpStatus.UNAUTHORIZED.value(), MESSAGE, null); +// response.setStatus(HttpStatus.FORBIDDEN.value()); +// response.getWriter().write(convertObjectToJson(authenticationException)); +// } +// } + +// } + +// private boolean isPathAllowed(String path) { +// var allowed = false; +// List<String> whiteList = new ArrayList<>(); +// whiteList.add("/api/auth/login"); +// whiteList.add("/api/auth/register"); +// whiteList.add("/v3/api-docs"); +// whiteList.add("/swagger-ui"); +// for (String allowedPath: whiteList) { +// if (path.startsWith(allowedPath)) { +// allowed = true; +// break; +// } +// } +// return allowed; +// } + + +// } diff --git a/backend/RumahSehat/src/main/java/apap/tugasakhir/RumahSehat/models/AppointmentModel.java b/backend/RumahSehat/src/main/java/apap/tugasakhir/RumahSehat/models/AppointmentModel.java index 8382f7699cea0a05adef2f6b98e1cc02dff06ca5..71d7e0817ce281ad11673581af451b2d64c5b06d 100644 --- a/backend/RumahSehat/src/main/java/apap/tugasakhir/RumahSehat/models/AppointmentModel.java +++ b/backend/RumahSehat/src/main/java/apap/tugasakhir/RumahSehat/models/AppointmentModel.java @@ -2,6 +2,7 @@ package apap.tugasakhir.RumahSehat.models; import java.io.Serializable; import java.time.LocalDateTime; +import java.util.List; import javax.persistence.CascadeType; import javax.persistence.Column; @@ -12,6 +13,7 @@ import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.JoinColumn; import javax.persistence.ManyToOne; +import javax.persistence.OneToMany; import javax.persistence.OneToOne; import javax.persistence.Table; import javax.validation.constraints.NotNull; @@ -20,6 +22,8 @@ import org.hibernate.annotations.GenericGenerator; import org.hibernate.annotations.OnDelete; import org.hibernate.annotations.OnDeleteAction; +import com.fasterxml.jackson.annotation.JsonIgnore; + import lombok.AllArgsConstructor; import lombok.Getter; import lombok.NoArgsConstructor; @@ -60,5 +64,10 @@ public class AppointmentModel implements Serializable{ @OneToOne(cascade = CascadeType.ALL) @JoinColumn(name = "kode_tagihan", referencedColumnName = "kode") private TagihanModel tagihan; + + // @JsonIgnore + @OneToOne(cascade = CascadeType.ALL) + @JoinColumn(name = "resep_id", referencedColumnName = "id") + private ResepModel resep; } diff --git a/backend/RumahSehat/src/main/java/apap/tugasakhir/RumahSehat/models/JumlahModel.java b/backend/RumahSehat/src/main/java/apap/tugasakhir/RumahSehat/models/JumlahModel.java index 02f7889ddda2301e83f36b08409cd23f458837e4..c21e1dca4581f3f3b7fb73c3c4dd97be0eb55946 100644 --- a/backend/RumahSehat/src/main/java/apap/tugasakhir/RumahSehat/models/JumlahModel.java +++ b/backend/RumahSehat/src/main/java/apap/tugasakhir/RumahSehat/models/JumlahModel.java @@ -1,9 +1,13 @@ package apap.tugasakhir.RumahSehat.models; import java.io.Serializable; +import java.util.Optional; +import javax.persistence.EmbeddedId; import javax.persistence.Entity; import javax.persistence.FetchType; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.JoinColumn; import javax.persistence.ManyToOne; @@ -13,6 +17,8 @@ import javax.validation.constraints.NotNull; import org.hibernate.annotations.OnDelete; import org.hibernate.annotations.OnDeleteAction; +import com.fasterxml.jackson.annotation.JsonIgnore; + import lombok.AllArgsConstructor; import lombok.Getter; import lombok.NoArgsConstructor; @@ -27,13 +33,17 @@ import lombok.Setter; public class JumlahModel implements Serializable { @Id - @ManyToOne(fetch = FetchType.EAGER, optional=false) + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long idJumlah; + + @JsonIgnore + @ManyToOne(fetch = FetchType.EAGER, optional=true) @JoinColumn(name = "id_obat", referencedColumnName = "id") @OnDelete(action = OnDeleteAction.CASCADE) private ObatModel obat; - @Id - @ManyToOne(fetch = FetchType.EAGER, optional=false) + @JsonIgnore + @ManyToOne(fetch = FetchType.EAGER, optional=true) @JoinColumn(name = "id_resep", referencedColumnName = "id") @OnDelete(action = OnDeleteAction.CASCADE) private ResepModel resep; diff --git a/backend/RumahSehat/src/main/java/apap/tugasakhir/RumahSehat/models/JwtRequest.java b/backend/RumahSehat/src/main/java/apap/tugasakhir/RumahSehat/models/JwtRequest.java new file mode 100644 index 0000000000000000000000000000000000000000..74e863638adced8cace6a6d6ddce196f8d5bd8d2 --- /dev/null +++ b/backend/RumahSehat/src/main/java/apap/tugasakhir/RumahSehat/models/JwtRequest.java @@ -0,0 +1,19 @@ +package apap.tugasakhir.RumahSehat.models; + + +import java.io.Serializable; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.Setter; + +@Setter +@Getter +@AllArgsConstructor +public class JwtRequest implements Serializable{ + + private static final long serialVersionUID = 5926468583005150707L; + + private String username; + private String password; +} diff --git a/backend/RumahSehat/src/main/java/apap/tugasakhir/RumahSehat/models/JwtResponse.java b/backend/RumahSehat/src/main/java/apap/tugasakhir/RumahSehat/models/JwtResponse.java new file mode 100644 index 0000000000000000000000000000000000000000..0a80c2eb69487cf875d8f7aae8454b2303d40689 --- /dev/null +++ b/backend/RumahSehat/src/main/java/apap/tugasakhir/RumahSehat/models/JwtResponse.java @@ -0,0 +1,17 @@ +package apap.tugasakhir.RumahSehat.models; + +import java.io.Serializable; + +public class JwtResponse implements Serializable { + + private static final long serialVersionUID = -8091879091924046844L; + private final String jwttoken; + + public JwtResponse(String jwttoken) { + this.jwttoken = jwttoken; + } + + public String getToken() { + return this.jwttoken; + } +} diff --git a/backend/RumahSehat/src/main/java/apap/tugasakhir/RumahSehat/models/ObatModel.java b/backend/RumahSehat/src/main/java/apap/tugasakhir/RumahSehat/models/ObatModel.java index 9a437031818921571dd6a42decf05f397da64b29..6c78f828cd7827577855ba45895fcef2547f6787 100644 --- a/backend/RumahSehat/src/main/java/apap/tugasakhir/RumahSehat/models/ObatModel.java +++ b/backend/RumahSehat/src/main/java/apap/tugasakhir/RumahSehat/models/ObatModel.java @@ -15,6 +15,7 @@ import javax.persistence.Table; import javax.validation.constraints.NotNull; import javax.validation.constraints.Size; +import org.hibernate.annotations.ColumnDefault; import org.hibernate.annotations.GenericGenerator; import lombok.AllArgsConstructor; @@ -41,7 +42,8 @@ public class ObatModel implements Serializable{ private String nama; @NotNull - private Integer stok = 100; + @ColumnDefault("100") + private Integer Stok; @NotNull private Integer harga; diff --git a/backend/RumahSehat/src/main/java/apap/tugasakhir/RumahSehat/models/PasienModel.java b/backend/RumahSehat/src/main/java/apap/tugasakhir/RumahSehat/models/PasienModel.java index 9dd82796c2ced169aad29c9020fbd7e323eea98e..4a2fbce72b651e15e778ac60680962dfe001633b 100644 --- a/backend/RumahSehat/src/main/java/apap/tugasakhir/RumahSehat/models/PasienModel.java +++ b/backend/RumahSehat/src/main/java/apap/tugasakhir/RumahSehat/models/PasienModel.java @@ -4,6 +4,7 @@ import lombok.AllArgsConstructor; import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; +import lombok.experimental.SuperBuilder; import javax.persistence.*; import javax.validation.constraints.NotNull; @@ -16,6 +17,7 @@ import java.util.List; @Getter @AllArgsConstructor @NoArgsConstructor +@SuperBuilder @Entity @Table(name = "pasien") public class PasienModel extends UserModel implements Serializable { @@ -25,7 +27,6 @@ public class PasienModel extends UserModel implements Serializable { private Integer saldo; @NotNull - @Size(max = 3) @Column(name = "umur", nullable = false) private Integer umur; diff --git a/backend/RumahSehat/src/main/java/apap/tugasakhir/RumahSehat/models/ResepModel.java b/backend/RumahSehat/src/main/java/apap/tugasakhir/RumahSehat/models/ResepModel.java index 6d44099ec4ea2aa31079ff8e31bcd8b6f1a25d37..590f3697fcc0dcce3fda6d77ed5da5fed60678e9 100644 --- a/backend/RumahSehat/src/main/java/apap/tugasakhir/RumahSehat/models/ResepModel.java +++ b/backend/RumahSehat/src/main/java/apap/tugasakhir/RumahSehat/models/ResepModel.java @@ -4,10 +4,15 @@ import lombok.AllArgsConstructor; import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; + +import org.hibernate.annotations.ColumnDefault; import org.hibernate.annotations.OnDelete; import org.hibernate.annotations.OnDeleteAction; import org.springframework.format.annotation.DateTimeFormat; import javax.persistence.*; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import javax.validation.constraints.NotNull; import java.io.Serializable; @@ -21,7 +26,7 @@ import java.util.List; @NoArgsConstructor @Entity @Table(name = "resep") -public class ResepModel implements Serializable { +public class ResepModel implements Serializable { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @@ -30,6 +35,7 @@ public class ResepModel implements Serializable { @NotNull @Column(name = "is_done", nullable = false) + @ColumnDefault("false") private Boolean isDone; @NotNull @@ -37,11 +43,18 @@ public class ResepModel implements Serializable { @DateTimeFormat(pattern = "yyyy-MM-dd'T'HH:mm") private LocalDateTime createdAt; - @ManyToOne(fetch = FetchType.EAGER, optional = false) - @JoinColumn(name = "confirmer_uuid", referencedColumnName = "uuid", nullable = false) + @ManyToOne(fetch = FetchType.EAGER, optional = true) + @JoinColumn(name = "confirmer_uuid", referencedColumnName = "uuid") @OnDelete(action = OnDeleteAction.CASCADE) private ApotekerModel apoteker; + @JsonIgnore @OneToMany(mappedBy = "resep", fetch = FetchType.LAZY, cascade = CascadeType.ALL) List<JumlahModel> listJumlah; + + // @JsonIgnore + @OneToOne(mappedBy = "resep") + private AppointmentModel appointment; + + } diff --git a/backend/RumahSehat/src/main/java/apap/tugasakhir/RumahSehat/models/UserModel.java b/backend/RumahSehat/src/main/java/apap/tugasakhir/RumahSehat/models/UserModel.java index 09c25ae082aee0c1787f799b4838819df8681d72..59612d8420432b1731bc3ed03e52d54d1fe6ef5b 100644 --- a/backend/RumahSehat/src/main/java/apap/tugasakhir/RumahSehat/models/UserModel.java +++ b/backend/RumahSehat/src/main/java/apap/tugasakhir/RumahSehat/models/UserModel.java @@ -3,6 +3,8 @@ import lombok.AllArgsConstructor; import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; +import lombok.experimental.SuperBuilder; + import org.hibernate.annotations.GenericGenerator; import javax.persistence.*; import javax.validation.constraints.NotNull; @@ -13,7 +15,9 @@ import java.io.Serializable; @Getter @AllArgsConstructor @NoArgsConstructor -@MappedSuperclass +@SuperBuilder +@Entity +@Inheritance(strategy = InheritanceType.JOINED) public class UserModel implements Serializable { @Id diff --git a/backend/RumahSehat/src/main/java/apap/tugasakhir/RumahSehat/repository/AdminDb.java b/backend/RumahSehat/src/main/java/apap/tugasakhir/RumahSehat/repository/AdminDb.java new file mode 100644 index 0000000000000000000000000000000000000000..dd3c62b2efd20e7b1a9bfaa8dd306157ec18f767 --- /dev/null +++ b/backend/RumahSehat/src/main/java/apap/tugasakhir/RumahSehat/repository/AdminDb.java @@ -0,0 +1,14 @@ +package apap.tugasakhir.RumahSehat.repository; +import java.util.List; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +import apap.tugasakhir.RumahSehat.models.AdminModel; +import apap.tugasakhir.RumahSehat.models.UserModel; + +@Repository +public interface AdminDb extends JpaRepository<AdminModel, Long> { + List<AdminModel> findAll(); + AdminModel findByUsername(String username); +} \ No newline at end of file diff --git a/backend/RumahSehat/src/main/java/apap/tugasakhir/RumahSehat/repository/PasienDb.java b/backend/RumahSehat/src/main/java/apap/tugasakhir/RumahSehat/repository/PasienDb.java new file mode 100644 index 0000000000000000000000000000000000000000..8d1688c3c9d644bf00b301dc1a4f65c8d5e08486 --- /dev/null +++ b/backend/RumahSehat/src/main/java/apap/tugasakhir/RumahSehat/repository/PasienDb.java @@ -0,0 +1,14 @@ +package apap.tugasakhir.RumahSehat.repository; + +import java.util.List; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; +import apap.tugasakhir.RumahSehat.models.PasienModel; + +@Repository +public interface PasienDb extends JpaRepository<PasienModel, String> { + PasienModel findByUsername(String username); + PasienModel findByEmail(String email); + List<PasienModel> findAll(); +} diff --git a/backend/RumahSehat/src/main/java/apap/tugasakhir/RumahSehat/repository/UserDb.java b/backend/RumahSehat/src/main/java/apap/tugasakhir/RumahSehat/repository/UserDb.java new file mode 100644 index 0000000000000000000000000000000000000000..b9cc08b608219428a693fdb72dcaaf38f0c29465 --- /dev/null +++ b/backend/RumahSehat/src/main/java/apap/tugasakhir/RumahSehat/repository/UserDb.java @@ -0,0 +1,14 @@ +package apap.tugasakhir.RumahSehat.repository; + +import java.util.List; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +import apap.tugasakhir.RumahSehat.models.UserModel; + +@Repository +public interface UserDb extends JpaRepository<UserModel, Long> { + List<UserModel> findAll(); + UserModel findByUsername(String username); +} diff --git a/backend/RumahSehat/src/main/java/apap/tugasakhir/RumahSehat/restController/PasienRestController.java b/backend/RumahSehat/src/main/java/apap/tugasakhir/RumahSehat/restController/PasienRestController.java new file mode 100644 index 0000000000000000000000000000000000000000..a460777fa2894b764d3eecdd94326138a06a990a --- /dev/null +++ b/backend/RumahSehat/src/main/java/apap/tugasakhir/RumahSehat/restController/PasienRestController.java @@ -0,0 +1,81 @@ +package apap.tugasakhir.RumahSehat.restController; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.NoSuchElementException; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.validation.Valid; + +import org.apache.tomcat.util.http.parser.Authorization; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.security.core.userdetails.User; +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; +import org.springframework.util.MimeTypeUtils; +import org.springframework.validation.BindingResult; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.server.ResponseStatusException; + +import com.auth0.jwt.JWT; +import com.auth0.jwt.JWTVerifier; +import com.auth0.jwt.algorithms.Algorithm; +import com.auth0.jwt.interfaces.DecodedJWT; +import com.fasterxml.jackson.databind.ObjectMapper; + +import static org.springframework.http.HttpHeaders.AUTHORIZATION; +import static org.springframework.http.HttpStatus.FORBIDDEN; + +import apap.tugasakhir.RumahSehat.models.PasienModel; +import apap.tugasakhir.RumahSehat.service.PasienRestService; + +@RestController +@RequestMapping("api/v1/pasien") +public class PasienRestController { + @Autowired + private PasienRestService pasienRestService; + + @PostMapping(value = "/register") + private ResponseEntity createPengajar(@RequestBody PasienModel pasien, BindingResult bindingResult) { + try { + if (bindingResult.hasFieldErrors()) { + throw new ResponseStatusException( + HttpStatus.BAD_REQUEST, "Request body has invalid type or missing field."); + } else { + pasien.setListAppointment(new ArrayList<>()); + pasien.setRole("Pasien"); + pasien.setSaldo(0); + pasien.setIsSso(false); + ; + pasien.setPassword(pasienRestService.encrypt(pasien.getPassword())); + PasienModel newPasien = pasienRestService.addPasien(pasien); + + HashMap<String, Object> response = new HashMap<>(); + response.put("status", "success"); + response.put("message", "registrasi pasien berhasil"); + response.put("status_code", 200); + response.put("data", newPasien); + return ResponseEntity.ok(response); + } + } catch (Exception e) { + HashMap<String, Object> response = new HashMap<>(); + response.put("status", "failed"); + response.put("message", "registrasi pasien gagal"); + response.put("status_code", 500); + response.put("data", null); + return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(response); + } + } + + @GetMapping(value = "/list-pasien") + private List<PasienModel> retrieveListCourse() { + return pasienRestService.retrieveListPasien(); + } +} diff --git a/backend/RumahSehat/src/main/java/apap/tugasakhir/RumahSehat/security/UserDetailsServiceImpl.java b/backend/RumahSehat/src/main/java/apap/tugasakhir/RumahSehat/security/UserDetailsServiceImpl.java new file mode 100644 index 0000000000000000000000000000000000000000..fc5146b7d865cecc1225748b7d3e13ebba6f1b05 --- /dev/null +++ b/backend/RumahSehat/src/main/java/apap/tugasakhir/RumahSehat/security/UserDetailsServiceImpl.java @@ -0,0 +1,30 @@ +package apap.tugasakhir.RumahSehat.security; + +import java.util.HashSet; +import java.util.Set; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.authority.SimpleGrantedAuthority; +import org.springframework.security.core.userdetails.User; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.security.core.userdetails.UserDetailsService; +import org.springframework.security.core.userdetails.UsernameNotFoundException; +import org.springframework.stereotype.Service; + +import apap.tugasakhir.RumahSehat.models.UserModel; +import apap.tugasakhir.RumahSehat.repository.UserDb; + +@Service +public class UserDetailsServiceImpl implements UserDetailsService { + @Autowired + private UserDb userDb; + + @Override + public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { + UserModel user = userDb.findByUsername(username); + Set<GrantedAuthority> grantedAuthorities = new HashSet<GrantedAuthority>(); + grantedAuthorities.add(new SimpleGrantedAuthority(user.getRole())); + return new User(user.getUsername(), user.getPassword(), grantedAuthorities); + } +} \ No newline at end of file diff --git a/backend/RumahSehat/src/main/java/apap/tugasakhir/RumahSehat/security/xml/Attributes.java b/backend/RumahSehat/src/main/java/apap/tugasakhir/RumahSehat/security/xml/Attributes.java new file mode 100644 index 0000000000000000000000000000000000000000..0986e6f97fdb647e9430979e06fa1ba6dc7cf2a9 --- /dev/null +++ b/backend/RumahSehat/src/main/java/apap/tugasakhir/RumahSehat/security/xml/Attributes.java @@ -0,0 +1,20 @@ +package apap.tugasakhir.RumahSehat.security.xml; + +import lombok.Getter; +import lombok.Setter; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; + +@Setter +@Getter +@XmlAccessorType(XmlAccessType.FIELD) +public class Attributes { + @XmlElement(namespace = "http://www.yale.edu/tp/cas") + private String ldap_cn; + @XmlElement(namespace = "http://www.yale.edu/tp/cas") + private String kd_org; + @XmlElement(namespace = "http://www.yale.edu/tp/cas") + private String nama; +} \ No newline at end of file diff --git a/backend/RumahSehat/src/main/java/apap/tugasakhir/RumahSehat/security/xml/AuthenticationSuccess.java b/backend/RumahSehat/src/main/java/apap/tugasakhir/RumahSehat/security/xml/AuthenticationSuccess.java new file mode 100644 index 0000000000000000000000000000000000000000..e395caf48d47f88b126ae0fcba1f29038ada9b2c --- /dev/null +++ b/backend/RumahSehat/src/main/java/apap/tugasakhir/RumahSehat/security/xml/AuthenticationSuccess.java @@ -0,0 +1,19 @@ +package apap.tugasakhir.RumahSehat.security.xml; + +import lombok.Getter; +import lombok.Setter; +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; + +@Setter +@Getter +@XmlAccessorType(XmlAccessType.FIELD) +public class AuthenticationSuccess { + @XmlElement(name = "user", namespace = "http://www.yale.edu/tp/cas") + private String user; + + @XmlElement(name = "attributes", namespace = "http://www.yale.edu/tp/cas") + private Attributes attributes; + +} \ No newline at end of file diff --git a/backend/RumahSehat/src/main/java/apap/tugasakhir/RumahSehat/security/xml/ServiceResponse.java b/backend/RumahSehat/src/main/java/apap/tugasakhir/RumahSehat/security/xml/ServiceResponse.java new file mode 100644 index 0000000000000000000000000000000000000000..dd2b0bc8a07c843ea8f85168c5a7d929c3603f80 --- /dev/null +++ b/backend/RumahSehat/src/main/java/apap/tugasakhir/RumahSehat/security/xml/ServiceResponse.java @@ -0,0 +1,21 @@ +package apap.tugasakhir.RumahSehat.security.xml; + +import lombok.Getter; +import lombok.Setter; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; + + +@Setter +@Getter +@XmlRootElement(name = "serviceResponse", namespace = "http://www.yale.edu/tp/cas") +@XmlAccessorType(XmlAccessType.FIELD) +public class ServiceResponse { + @XmlElement(name = "authenticationFailure", namespace = "http://www.yale.edu/tp/cas") + private String authenticationFailure; + @XmlElement(name = "authenticationSuccess", namespace = "http://www.yale.edu/tp/cas") + private AuthenticationSuccess authenticationSuccess; +} \ No newline at end of file diff --git a/backend/RumahSehat/src/main/java/apap/tugasakhir/RumahSehat/service/AdminService.java b/backend/RumahSehat/src/main/java/apap/tugasakhir/RumahSehat/service/AdminService.java new file mode 100644 index 0000000000000000000000000000000000000000..520e04510f62b401ea30d5c74e088d96b43cca54 --- /dev/null +++ b/backend/RumahSehat/src/main/java/apap/tugasakhir/RumahSehat/service/AdminService.java @@ -0,0 +1,12 @@ +package apap.tugasakhir.RumahSehat.service; + +import java.util.List; + +import apap.tugasakhir.RumahSehat.models.AdminModel; + +public interface AdminService { + AdminModel addUser(AdminModel user); + public String encrypt(String password); + AdminModel getUserByUsername(String name); + List<AdminModel> findAll(); +} diff --git a/backend/RumahSehat/src/main/java/apap/tugasakhir/RumahSehat/service/AdminServiceImpl.java b/backend/RumahSehat/src/main/java/apap/tugasakhir/RumahSehat/service/AdminServiceImpl.java new file mode 100644 index 0000000000000000000000000000000000000000..fc59e69f0c1de24be8845779eb960418788d34a4 --- /dev/null +++ b/backend/RumahSehat/src/main/java/apap/tugasakhir/RumahSehat/service/AdminServiceImpl.java @@ -0,0 +1,40 @@ +package apap.tugasakhir.RumahSehat.service; + +import java.util.List; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; +import org.springframework.stereotype.Service; + +import apap.tugasakhir.RumahSehat.models.AdminModel; +import apap.tugasakhir.RumahSehat.repository.AdminDb; + +@Service +public class AdminServiceImpl implements AdminService { + @Autowired + private AdminDb adminDb; + + @Override + public AdminModel addUser(AdminModel user) { + String pass = encrypt(user.getPassword()); + user.setPassword(pass); + return adminDb.save(user); + } + + @Override + public String encrypt(String password) { + BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder(); + String hashedPassword = passwordEncoder.encode(password); + return hashedPassword; + } + + @Override + public AdminModel getUserByUsername(String username) { + return adminDb.findByUsername(username); + } + + @Override + public List<AdminModel> findAll() { + return adminDb.findAll(); + } +} diff --git a/backend/RumahSehat/src/main/java/apap/tugasakhir/RumahSehat/service/PasienRestService.java b/backend/RumahSehat/src/main/java/apap/tugasakhir/RumahSehat/service/PasienRestService.java new file mode 100644 index 0000000000000000000000000000000000000000..7c389af7234728185563dfcfa8144b6183926fa1 --- /dev/null +++ b/backend/RumahSehat/src/main/java/apap/tugasakhir/RumahSehat/service/PasienRestService.java @@ -0,0 +1,15 @@ +package apap.tugasakhir.RumahSehat.service; + +import java.util.List; + +import apap.tugasakhir.RumahSehat.models.PasienModel; + +public interface PasienRestService { + PasienModel addPasien(PasienModel pasien); + + List<PasienModel> retrieveListPasien(); + + String encrypt(String password); + + PasienModel getPasien(String username); +} diff --git a/backend/RumahSehat/src/main/java/apap/tugasakhir/RumahSehat/service/PasienRestServiceImpl.java b/backend/RumahSehat/src/main/java/apap/tugasakhir/RumahSehat/service/PasienRestServiceImpl.java new file mode 100644 index 0000000000000000000000000000000000000000..1537139901646f8f65f79bfa3b5cb7d279f7de71 --- /dev/null +++ b/backend/RumahSehat/src/main/java/apap/tugasakhir/RumahSehat/service/PasienRestServiceImpl.java @@ -0,0 +1,54 @@ +package apap.tugasakhir.RumahSehat.service; + +import java.util.List; + +import javax.transaction.Transactional; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; +import org.springframework.stereotype.Service; + +import apap.tugasakhir.RumahSehat.models.PasienModel; +import apap.tugasakhir.RumahSehat.repository.PasienDb; + +@Service +@Transactional +public class PasienRestServiceImpl implements PasienRestService{ + + @Autowired + private PasienDb pasienDb; + + @Override + public PasienModel addPasien(PasienModel pasien){ + pasien.setPassword(encrypt(pasien.getPassword())); + + if (pasienDb.findByUsername(pasien.getUsername()) != null) { + throw new RuntimeException("Username " + pasien.getUsername() + " sudah terdaftar"); + } + + + if (pasienDb.findByEmail(pasien.getEmail()) != null) { + throw new RuntimeException("Email " + pasien.getEmail() + " sudah terdaftar"); + } + + return pasienDb.save(pasien); + } + + @Override + public List<PasienModel> retrieveListPasien(){ + return pasienDb.findAll(); + } + + @Override + public String encrypt(String password) { + BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder(); + String hashedPassword = passwordEncoder.encode(password); + return hashedPassword; + } + + @Override + public PasienModel getPasien(String username) { + return pasienDb.findByUsername(username); + } + +} diff --git a/backend/RumahSehat/src/main/java/apap/tugasakhir/RumahSehat/service/UserService.java b/backend/RumahSehat/src/main/java/apap/tugasakhir/RumahSehat/service/UserService.java new file mode 100644 index 0000000000000000000000000000000000000000..23bf8abb083422e0f8bf64153b4a8e23dafc0cb7 --- /dev/null +++ b/backend/RumahSehat/src/main/java/apap/tugasakhir/RumahSehat/service/UserService.java @@ -0,0 +1,12 @@ +package apap.tugasakhir.RumahSehat.service; + +import java.util.List; + +import apap.tugasakhir.RumahSehat.models.UserModel; + +public interface UserService { + UserModel addUser(UserModel user); + public String encrypt(String password); + UserModel getUserByUsername(String name); + List<UserModel> findAll(); +} diff --git a/backend/RumahSehat/src/main/java/apap/tugasakhir/RumahSehat/service/UserServiceImpl.java b/backend/RumahSehat/src/main/java/apap/tugasakhir/RumahSehat/service/UserServiceImpl.java new file mode 100644 index 0000000000000000000000000000000000000000..0f8fb6748987e6a8e91c0939c8087a7c4a510d74 --- /dev/null +++ b/backend/RumahSehat/src/main/java/apap/tugasakhir/RumahSehat/service/UserServiceImpl.java @@ -0,0 +1,40 @@ +package apap.tugasakhir.RumahSehat.service; + +import java.util.List; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; +import org.springframework.stereotype.Service; + +import apap.tugasakhir.RumahSehat.models.UserModel; +import apap.tugasakhir.RumahSehat.repository.UserDb; + +@Service +public class UserServiceImpl implements UserService { + @Autowired + private UserDb userDb; + + @Override + public UserModel addUser(UserModel user) { + String pass = encrypt(user.getPassword()); + user.setPassword(pass); + return userDb.save(user); + } + + @Override + public String encrypt(String password) { + BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder(); + String hashedPassword = passwordEncoder.encode(password); + return hashedPassword; + } + + @Override + public UserModel getUserByUsername(String username) { + return userDb.findByUsername(username); + } + + @Override + public List<UserModel> findAll() { + return userDb.findAll(); + } +} diff --git a/backend/RumahSehat/src/main/java/apap/tugasakhir/RumahSehat/setting/Setting.java b/backend/RumahSehat/src/main/java/apap/tugasakhir/RumahSehat/setting/Setting.java new file mode 100644 index 0000000000000000000000000000000000000000..ff61b35c09e4f16faa988fef783f58f5f3830cc6 --- /dev/null +++ b/backend/RumahSehat/src/main/java/apap/tugasakhir/RumahSehat/setting/Setting.java @@ -0,0 +1,13 @@ +package apap.tugasakhir.RumahSehat.setting; + +public class Setting { + final public static String CLIENT_BASE_URL = "http://localhost:2020"; + final public static String CLIENT_LOGIN = CLIENT_BASE_URL + "/validate-ticket"; + final public static String CLIENT_LOGOUT = CLIENT_BASE_URL + "/logout"; + final public static String SERVER_BASE_URL = "https://sso.ui.ac.id/cas2"; + final public static String SERVER_LOGIN = SERVER_BASE_URL + "/login?service="; + final public static String SERVER_LOGOUT = SERVER_BASE_URL + "/logout?url="; + final public static String SERVER_VALIDATE_TICKET + = SERVER_BASE_URL + "/serviceValidate?ticket=%s&service=%s"; +} + diff --git a/backend/RumahSehat/src/main/resources/application.properties b/backend/RumahSehat/src/main/resources/application.properties index 6515465659c67cc916fcd5f4e42f7b4bf65674ae..372833d5a9becf1edd83e10335760be37c9973bf 100644 --- a/backend/RumahSehat/src/main/resources/application.properties +++ b/backend/RumahSehat/src/main/resources/application.properties @@ -13,6 +13,6 @@ spring.datasource.password= spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5InnoDBDialect #pembuatan database (create || create drop || validate || update) -spring.jpa.hibernate.ddl-auto=create +spring.jpa.hibernate.ddl-auto=create-drop server.port=2020 diff --git a/frontend/rumah_sehat/lib/features/registrasi_pasien/registrasi_pasien.dart b/frontend/rumah_sehat/lib/features/registrasi_pasien/registrasi_pasien.dart new file mode 100644 index 0000000000000000000000000000000000000000..ba0130b338397b3f170b5400b01a68bbce0bc2da --- /dev/null +++ b/frontend/rumah_sehat/lib/features/registrasi_pasien/registrasi_pasien.dart @@ -0,0 +1,133 @@ +import 'dart:convert'; + +import 'package:flutter/material.dart'; +import 'package:http/http.dart' as http; +import 'package:flutter_secure_storage/flutter_secure_storage.dart'; + +class SignUpPage extends StatefulWidget { + const SignUpPage({Key? key}) : super(key: key); + + @override + State<SignUpPage> createState() => _SignUpPageState(); +} + +class _SignUpPageState extends State<SignUpPage> { + final TextEditingController _usernameController = TextEditingController(); + final TextEditingController _passwordController = TextEditingController(); + final TextEditingController _nameController = TextEditingController(); + final TextEditingController _emailController = TextEditingController(); + final TextEditingController _umurController = TextEditingController(); + + void displayDialog(context, title, text) => showDialog( + context: context, + builder: (context) => + AlertDialog( + title: Text(title), + content: Text(text) + ), + ); + + + Future<http.Response> attemptSignUp(String username, String password, String umur, String name, String email) async { + // String? access_token_await = await storage.read(key: "access_token"); + // String access_token = ""; + // if(access_token_await != null){ + // access_token = access_token_await; + // } + var res = await http.post( + Uri.parse('http://localhost:2020/api/v1/pasien/register'), + headers: <String, String>{"Content-Type": "application/json", + // "Authorization": "Bearer " + access_token, + "Accept": "application/json"}, + body: jsonEncode(<String, String>{ + "nama": name, + "email": email, + "umur": umur, + "username": username, + "password": password + }) + ); + return res; + } + + + + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar(title: Text("Sign Up"),), + body: Padding( + padding: const EdgeInsets.all(8.0), + child: Column( + children: <Widget>[ + TextField( + controller: _usernameController, + decoration: InputDecoration( + labelText: 'Username' + ), + ), + TextField( + controller: _passwordController, + obscureText: true, + decoration: InputDecoration( + labelText: 'Password' + ), + ), + TextField( + controller: _emailController, + decoration: InputDecoration( + labelText: 'Email' + ), + ), + TextField( + controller: _nameController, + decoration: InputDecoration( + labelText: 'Nama' + ), + ), + TextField( + controller: _umurController, + keyboardType: TextInputType.number, + decoration: InputDecoration( + labelText: 'Umur' + ), + ), + SizedBox( + height: 20 + ), + TextButton( + style: ButtonStyle( + backgroundColor: MaterialStatePropertyAll<Color>(Colors.green), + ), + onPressed: () async { + var response = await attemptSignUp(_usernameController.text, _passwordController.text, _umurController.text, _nameController.text, _emailController.text); + print(response.statusCode); + if(response.statusCode == 200) { + displayDialog(context, "Sign Up success", "Sign Up success"); + //JWT.fromJson(jsonDecode(jwt.body)); + // Navigator.push( + // context, + // MaterialPageRoute( + // builder: (context) => HomePage.fromBase64(jwt) + // ) + // ); + } else if(response.statusCode == 400){ + displayDialog(context, "An Error Occurred", "Request body has invalid type or missing field."); + } else if(response.statusCode == 403) { + displayDialog(context, "An Error Occurred", "Forbidden"); + } else { + displayDialog(context, "An Error Occurred", "No account was found matching that username and password"); + } + }, + child: Text( + "submit", + style: TextStyle(color: Colors.white), + ), + ) + ], + ), + ) + ); + } +} \ No newline at end of file diff --git a/frontend/rumah_sehat/lib/main.dart b/frontend/rumah_sehat/lib/main.dart index b35e788a9fbc6184db1a4b240f6212e1be512cbc..abf973782e20378f46490c8ce5539c928e6aa648 100644 --- a/frontend/rumah_sehat/lib/main.dart +++ b/frontend/rumah_sehat/lib/main.dart @@ -1,26 +1,130 @@ +import 'dart:convert'; + import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:rumah_sehat/core/routes.dart'; +import 'package:flutter_secure_storage/flutter_secure_storage.dart'; import 'package:rumah_sehat/core/theme.dart'; +import 'package:flutter/material.dart'; +import 'package:http/http.dart' as http; +import 'package:rumah_sehat/features/registrasi_pasien/registrasi_pasien.dart'; + +const SERVER_IP = 'http://localhost:8080'; +final storage = FlutterSecureStorage(); void main() { runApp( - const ProviderScope( + ProviderScope( child: RumahSehatApp(), ), ); } class RumahSehatApp extends StatelessWidget { - const RumahSehatApp({Key? key}) : super(key: key); + const RumahSehatApp({super.key}); + + // This widget is the root of your application. @override Widget build(BuildContext context) { return MaterialApp( - debugShowCheckedModeBanner: false, - title: 'RumahSehat', - theme: RumahSehatTheme.theme, - routes: Routes.route, - initialRoute: Routes.home, + title: 'Flutter Demo', + theme: ThemeData( + // This is the theme of your application. + // + // Try running your application with "flutter run". You'll see the + // application has a blue toolbar. Then, without quitting the app, try + // changing the primarySwatch below to Colors.green and then invoke + // "hot reload" (press "r" in the console where you ran "flutter run", + // or simply save your changes to "hot reload" in a Flutter IDE). + // Notice that the counter didn't reset back to zero; the application + // is not restarted. + primarySwatch: Colors.blue, + ), + home: LoginPage(), + ); + } +} + +class LoginPage extends StatelessWidget { + LoginPage({super.key}); + final TextEditingController _usernameController = TextEditingController(); + final TextEditingController _passwordController = TextEditingController(); + + void displayDialog(context, title, text) => showDialog( + context: context, + builder: (context) => + AlertDialog( + title: Text(title), + content: Text(text) + ), + ); + + Future<http.Response> attemptLogIn(String username, String password) async { + var res = await http.post( + Uri.parse('http://localhost:2020/api/login'), + headers: <String, String>{"Content-Type": "application/x-www-form-urlencoded"}, + body: { + "username": username, + "password": password + } + ); + return res; + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar(title: Text("Log In"),), + body: Padding( + padding: const EdgeInsets.all(8.0), + child: Column( + children: <Widget>[ + TextField( + controller: _usernameController, + decoration: InputDecoration( + labelText: 'Username' + ), + ), + TextField( + controller: _passwordController, + obscureText: true, + decoration: InputDecoration( + labelText: 'Password' + ), + ), + TextButton( + onPressed: () async { + var username = _usernameController.text; + var password = _passwordController.text; + var jwt = await attemptLogIn(username, password); + if(jwt != null) { + //storage.write(key: "jwt", value: jwt); + // Navigator.push( + // context, + // MaterialPageRoute( + // builder: (context) => HomePage.fromBase64(jwt) + // ) + // ); + } else { + displayDialog(context, "An Error Occurred", "No account was found matching that username and password"); + } + }, + child: Text("Log In") + ), + TextButton( + onPressed: () { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => SignUpPage() + ) + ); + }, + child: Text("Sign Up") + ) + ], + ), + ) ); } } diff --git a/frontend/rumah_sehat/lib/models/pasien_model.dart b/frontend/rumah_sehat/lib/models/pasien_model.dart new file mode 100644 index 0000000000000000000000000000000000000000..7bad327219134bdc723c6df7ccf1d83a22723183 --- /dev/null +++ b/frontend/rumah_sehat/lib/models/pasien_model.dart @@ -0,0 +1,12 @@ +// class PasienModel { +// final String ; +// final String nama; +// final String instruction; +// final String photoUrl; + +// PasienModel.fromJson(Map<String, dynamic> data) +// : name = data['strMeal'], +// area = data['strArea'], +// instruction = data['strInstructions'], +// photoUrl = data['strMealThumb']; +// } \ No newline at end of file diff --git a/frontend/rumah_sehat/pubspec.lock b/frontend/rumah_sehat/pubspec.lock index 736f6c8413ca89dde28643946c5e0ec33ee9e5a1..cdaee1da7a7035dc09de36d45e90c3b812806710 100644 --- a/frontend/rumah_sehat/pubspec.lock +++ b/frontend/rumah_sehat/pubspec.lock @@ -90,6 +90,48 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "2.1.1" + flutter_secure_storage: + dependency: "direct main" + description: + name: flutter_secure_storage + url: "https://pub.dartlang.org" + source: hosted + version: "6.0.0" + flutter_secure_storage_linux: + dependency: transitive + description: + name: flutter_secure_storage_linux + url: "https://pub.dartlang.org" + source: hosted + version: "1.1.2" + flutter_secure_storage_macos: + dependency: transitive + description: + name: flutter_secure_storage_macos + url: "https://pub.dartlang.org" + source: hosted + version: "1.1.2" + flutter_secure_storage_platform_interface: + dependency: transitive + description: + name: flutter_secure_storage_platform_interface + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.1" + flutter_secure_storage_web: + dependency: transitive + description: + name: flutter_secure_storage_web + url: "https://pub.dartlang.org" + source: hosted + version: "1.1.1" + flutter_secure_storage_windows: + dependency: transitive + description: + name: flutter_secure_storage_windows + url: "https://pub.dartlang.org" + source: hosted + version: "1.1.3" flutter_test: dependency: "direct dev" description: flutter @@ -100,6 +142,13 @@ packages: description: flutter source: sdk version: "0.0.0" + http: + dependency: "direct main" + description: + name: http + url: "https://pub.dartlang.org" + source: hosted + version: "0.13.5" http_parser: dependency: transitive description: diff --git a/frontend/rumah_sehat/pubspec.yaml b/frontend/rumah_sehat/pubspec.yaml index 4b5fb1eb18a34a7b3b1cc797a68f546ecb2ce854..ba78c2d4011cc61613a28bab304a60f911fb10e9 100644 --- a/frontend/rumah_sehat/pubspec.yaml +++ b/frontend/rumah_sehat/pubspec.yaml @@ -18,7 +18,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev version: 1.0.0+1 environment: - sdk: ">=2.12.0 <3.0.0" + sdk: ">=2.17.0 <3.0.0" # Dependencies specify other packages that your package needs in order to work. # To automatically upgrade your package dependencies to the latest versions @@ -37,6 +37,8 @@ dependencies: dio: ^4.0.6 shared_preferences: ^2.0.15 flutter_riverpod: ^2.1.1 + flutter_secure_storage: ^6.0.0 + http: ^0.13.5 dev_dependencies: flutter_test: