diff --git a/database/diagram/gcs_back_end.drawio b/database/diagram/gcs_back_end.drawio index bf1269c..51b670e 100644 --- a/database/diagram/gcs_back_end.drawio +++ b/database/diagram/gcs_back_end.drawio @@ -287,7 +287,7 @@ - + diff --git a/database/diagram/gcs_back_end.png b/database/diagram/gcs_back_end.png index bbf317a..9b7b77d 100644 Binary files a/database/diagram/gcs_back_end.png and b/database/diagram/gcs_back_end.png differ diff --git a/database/table/t_user.sql b/database/table/t_user.sql index 6165b77..b1bd10b 100644 --- a/database/table/t_user.sql +++ b/database/table/t_user.sql @@ -2,7 +2,7 @@ CREATE TABLE public.t_user ( id bigint NOT NULL, username character varying(50) NOT NULL, email character varying(254) NOT NULL, - user_password character(128) NOT NULL, + user_password character(32) NOT NULL, gmt_created timestamp without time zone DEFAULT CURRENT_TIMESTAMP NOT NULL, gmt_updated timestamp without time zone DEFAULT CURRENT_TIMESTAMP NOT NULL, gmt_deleted timestamp without time zone diff --git a/src/main/java/edu/cmipt/gcs/controller/SwaggerTmpController.java b/src/main/java/edu/cmipt/gcs/controller/SwaggerTmpController.java deleted file mode 100644 index 8ef1713..0000000 --- a/src/main/java/edu/cmipt/gcs/controller/SwaggerTmpController.java +++ /dev/null @@ -1,23 +0,0 @@ -package edu.cmipt.gcs.controller; - -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestParam; -import org.springframework.web.bind.annotation.RestController; - -@RestController -@RequestMapping("/api") -public class SwaggerTmpController { - - @GetMapping("/users/{id}") - public boolean getUser(@PathVariable Long id) { - // implementation - return true; - } - - @GetMapping("/hello") - public String hello(@RequestParam(value = "name", defaultValue = "World") String name) { - return "Hello " + name; - } -} diff --git a/src/main/java/edu/cmipt/gcs/controller/UserController.java b/src/main/java/edu/cmipt/gcs/controller/UserController.java new file mode 100644 index 0000000..c328b9d --- /dev/null +++ b/src/main/java/edu/cmipt/gcs/controller/UserController.java @@ -0,0 +1,49 @@ +package edu.cmipt.gcs.controller; + +import edu.cmipt.gcs.pojo.user.UserDTO; +import edu.cmipt.gcs.pojo.user.UserPO; +import edu.cmipt.gcs.service.UserService; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.responses.ApiResponses; +import io.swagger.v3.oas.annotations.tags.Tag; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; + +@Controller +@RequestMapping("/user") +@Tag(name = "User", description = "User Related APIs") +public class UserController { + @Autowired private UserService userService; + + @PostMapping + @Operation( + summary = "Create a new user", + description = "Create a new user with the given information", + tags = {"User", "Post Method"}) + @ApiResponses({ + @ApiResponse(responseCode = "200", description = "User created successfully"), + @ApiResponse(responseCode = "400", description = "User creation failed") + }) + public ResponseEntity createUser(@RequestBody UserDTO user) { + if (user == null + || user.getUsername() == null + || user.getEmail() == null + || user.getUserPassword() == null) { + return ResponseEntity.badRequest().build(); + } + // there may be some check before.... + boolean res = userService.save(new UserPO(user)); + if (res) { + return ResponseEntity.ok().build(); + } else { + return ResponseEntity.badRequest().build(); + } + } +} diff --git a/src/main/java/edu/cmipt/gcs/dao/UserMapper.java b/src/main/java/edu/cmipt/gcs/dao/UserMapper.java index 38e42a0..8c2ff9c 100644 --- a/src/main/java/edu/cmipt/gcs/dao/UserMapper.java +++ b/src/main/java/edu/cmipt/gcs/dao/UserMapper.java @@ -2,6 +2,6 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; -import edu.cmipt.gcs.pojo.UserPO; +import edu.cmipt.gcs.pojo.user.UserPO; public interface UserMapper extends BaseMapper {} diff --git a/src/main/java/edu/cmipt/gcs/pojo/UserPO.java b/src/main/java/edu/cmipt/gcs/pojo/UserPO.java deleted file mode 100644 index 4b7bd3e..0000000 --- a/src/main/java/edu/cmipt/gcs/pojo/UserPO.java +++ /dev/null @@ -1,16 +0,0 @@ -package edu.cmipt.gcs.pojo; - -import com.baomidou.mybatisplus.annotation.TableId; -import com.baomidou.mybatisplus.annotation.TableName; - -import java.time.LocalDateTime; - -@TableName("t_user") -public record UserPO( - @TableId Long pkUserId, - String username, - String email, - String userPassword, - LocalDateTime gmtCreated, - LocalDateTime gmtUpdated, - LocalDateTime gmtDeleted) {} diff --git a/src/main/java/edu/cmipt/gcs/pojo/user/UserDTO.java b/src/main/java/edu/cmipt/gcs/pojo/user/UserDTO.java new file mode 100644 index 0000000..873abd9 --- /dev/null +++ b/src/main/java/edu/cmipt/gcs/pojo/user/UserDTO.java @@ -0,0 +1,30 @@ +package edu.cmipt.gcs.pojo.user; + +import io.swagger.v3.oas.annotations.media.Schema; + +import lombok.Data; + +@Data +@Schema(description = "User Data Transfer Object") +public class UserDTO { + @Schema(accessMode = Schema.AccessMode.READ_ONLY, description = "User ID") + private Long id; + + @Schema( + description = "Username", + requiredMode = Schema.RequiredMode.REQUIRED, + example = "admin") + private String username; + + @Schema( + description = "Email", + requiredMode = Schema.RequiredMode.REQUIRED, + example = "admin@cmipt.edu") + private String email; + + @Schema( + description = "User Password (Unencrypted)", + requiredMode = Schema.RequiredMode.REQUIRED, + example = "admin") + private String userPassword; +} diff --git a/src/main/java/edu/cmipt/gcs/pojo/user/UserPO.java b/src/main/java/edu/cmipt/gcs/pojo/user/UserPO.java new file mode 100644 index 0000000..7de798b --- /dev/null +++ b/src/main/java/edu/cmipt/gcs/pojo/user/UserPO.java @@ -0,0 +1,31 @@ +package edu.cmipt.gcs.pojo.user; + +import com.baomidou.mybatisplus.annotation.TableLogic; +import com.baomidou.mybatisplus.annotation.TableName; + +import edu.cmipt.gcs.util.MD5Converter; + +import lombok.AllArgsConstructor; +import lombok.Data; + +import java.time.LocalDateTime; + +@Data +@AllArgsConstructor +@TableName("t_user") +public class UserPO { + private Long id; + private String username; + private String email; + private String userPassword; + private LocalDateTime gmtCreated; + private LocalDateTime gmtUpdated; + @TableLogic private LocalDateTime gmtDeleted; + + public UserPO(UserDTO userDTO) { + this.id = userDTO.getId(); + this.username = userDTO.getUsername(); + this.email = userDTO.getEmail(); + this.userPassword = MD5Converter.convertToMD5(userDTO.getUserPassword()); + } +} diff --git a/src/main/java/edu/cmipt/gcs/service/UserService.java b/src/main/java/edu/cmipt/gcs/service/UserService.java new file mode 100644 index 0000000..500f1dc --- /dev/null +++ b/src/main/java/edu/cmipt/gcs/service/UserService.java @@ -0,0 +1,7 @@ +package edu.cmipt.gcs.service; + +import com.baomidou.mybatisplus.extension.service.IService; + +import edu.cmipt.gcs.pojo.user.UserPO; + +public interface UserService extends IService {} diff --git a/src/main/java/edu/cmipt/gcs/service/UserServiceImpl.java b/src/main/java/edu/cmipt/gcs/service/UserServiceImpl.java new file mode 100644 index 0000000..275d752 --- /dev/null +++ b/src/main/java/edu/cmipt/gcs/service/UserServiceImpl.java @@ -0,0 +1,11 @@ +package edu.cmipt.gcs.service; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; + +import edu.cmipt.gcs.dao.UserMapper; +import edu.cmipt.gcs.pojo.user.UserPO; + +import org.springframework.stereotype.Service; + +@Service +public class UserServiceImpl extends ServiceImpl implements UserService {} diff --git a/src/main/java/edu/cmipt/gcs/util/MD5Converter.java b/src/main/java/edu/cmipt/gcs/util/MD5Converter.java new file mode 100644 index 0000000..8f41ae4 --- /dev/null +++ b/src/main/java/edu/cmipt/gcs/util/MD5Converter.java @@ -0,0 +1,23 @@ +package edu.cmipt.gcs.util; + +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; + +public class MD5Converter { + public static String convertToMD5(String input) { + try { + byte[] hashBytes = MessageDigest.getInstance("MD5").digest(input.getBytes()); + StringBuilder hexString = new StringBuilder(); + for (byte b : hashBytes) { + String hex = Integer.toHexString(0xff & b); + if (hex.length() == 1) { + hexString.append('0'); + } + hexString.append(hex); + } + return hexString.toString(); + } catch (NoSuchAlgorithmException e) { + throw new RuntimeException("MD5 algorithm not found", e); + } + } +} diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index b245895..72769a0 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -40,5 +40,12 @@ spring: reset-enable: false allow: # empty means allow all +mybatis-plus: + global-config: + db-config: + logic-delete-field: gmt_deleted + logic-delete-value: now() + logic-not-delete-value: "null" + logging: include-application-name: false diff --git a/src/test/java/edu/cmipt/gcs/controller/SwaggerTmpControllerITest.java b/src/test/java/edu/cmipt/gcs/controller/SwaggerTmpControllerITest.java deleted file mode 100644 index fd85057..0000000 --- a/src/test/java/edu/cmipt/gcs/controller/SwaggerTmpControllerITest.java +++ /dev/null @@ -1,21 +0,0 @@ -package edu.cmipt.gcs.controller; - -import static org.assertj.core.api.Assertions.assertThat; - -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.boot.test.web.client.TestRestTemplate; -import org.springframework.http.ResponseEntity; - -@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) -public class SwaggerTmpControllerITest { - - @Autowired private TestRestTemplate template; - - @Test - public void getHello() throws Exception { - ResponseEntity response = template.getForEntity("/api/hello", String.class); - assertThat(response.getBody()).isEqualTo("Hello World"); - } -} diff --git a/src/test/java/edu/cmipt/gcs/controller/SwaggerTmpControllerTest.java b/src/test/java/edu/cmipt/gcs/controller/UserControllerTest.java similarity index 66% rename from src/test/java/edu/cmipt/gcs/controller/SwaggerTmpControllerTest.java rename to src/test/java/edu/cmipt/gcs/controller/UserControllerTest.java index 31792fd..d03e688 100644 --- a/src/test/java/edu/cmipt/gcs/controller/SwaggerTmpControllerTest.java +++ b/src/test/java/edu/cmipt/gcs/controller/UserControllerTest.java @@ -11,16 +11,16 @@ import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; -@SpringBootTest +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) @AutoConfigureMockMvc -public class SwaggerTmpControllerTest { +public class UserControllerTest { @Autowired private MockMvc mvc; @Test - public void testGetUser() throws Exception { - mvc.perform(MockMvcRequestBuilders.get("/api/users/1")) - .andExpect(status().isOk()) - .andExpect(content().string(equalTo("true"))); + public void testCreateUser() throws Exception { + mvc.perform(MockMvcRequestBuilders.post("/user").content("{\"name\": \"test\"}")) + .andExpect(status().isBadRequest()) + .andExpect(content().string(equalTo(""))); } } diff --git a/src/test/java/edu/cmipt/gcs/controller/dao/UserMapperTest.java b/src/test/java/edu/cmipt/gcs/dao/UserMapperTest.java similarity index 70% rename from src/test/java/edu/cmipt/gcs/controller/dao/UserMapperTest.java rename to src/test/java/edu/cmipt/gcs/dao/UserMapperTest.java index 424f593..c6a76e1 100644 --- a/src/test/java/edu/cmipt/gcs/controller/dao/UserMapperTest.java +++ b/src/test/java/edu/cmipt/gcs/dao/UserMapperTest.java @@ -1,9 +1,6 @@ -package edu.cmipt.gcs.controller.dao; +package edu.cmipt.gcs.dao; -import com.baomidou.mybatisplus.core.toolkit.Assert; - -import edu.cmipt.gcs.dao.UserMapper; -import edu.cmipt.gcs.pojo.UserPO; +import edu.cmipt.gcs.pojo.user.UserPO; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; @@ -20,7 +17,6 @@ public class UserMapperTest { public void testSelect() { System.out.println(("----- selectAll method test ------")); List userList = userMapper.selectList(null); - Assert.isTrue(1 == userList.size(), ""); userList.forEach(System.out::println); } }