diff --git a/src/main/kotlin/team8/fruitable/FruitableApplication.kt b/src/main/kotlin/team8/fruitable/FruitableApplication.kt index 0d43ce1..d08b4f6 100644 --- a/src/main/kotlin/team8/fruitable/FruitableApplication.kt +++ b/src/main/kotlin/team8/fruitable/FruitableApplication.kt @@ -5,7 +5,6 @@ import org.springframework.boot.runApplication import org.springframework.web.bind.annotation.RequestMapping import org.springframework.web.bind.annotation.RestController - @RestController @SpringBootApplication class FruitableApplication { diff --git a/src/main/kotlin/team8/fruitable/constant/UserType.kt b/src/main/kotlin/team8/fruitable/constant/UserType.kt new file mode 100644 index 0000000..839a359 --- /dev/null +++ b/src/main/kotlin/team8/fruitable/constant/UserType.kt @@ -0,0 +1,7 @@ +package team8.fruitable.constant + +enum class UserType { + Admin, + User, + Guest +} diff --git a/src/main/kotlin/team8/fruitable/controller/api/Account.kt b/src/main/kotlin/team8/fruitable/controller/api/Account.kt index a917d71..6d36daa 100644 --- a/src/main/kotlin/team8/fruitable/controller/api/Account.kt +++ b/src/main/kotlin/team8/fruitable/controller/api/Account.kt @@ -3,121 +3,128 @@ package team8.fruitable.controller.api import jakarta.servlet.http.Cookie import jakarta.servlet.http.HttpServletResponse import org.springframework.web.bind.annotation.* +import team8.fruitable.constant.UserType import team8.fruitable.datebase.entity.User import team8.fruitable.datebase.repository.UserRepository import team8.fruitable.util.ResultBuilder - @RestController class Account(private val repository: UserRepository) { - @GetMapping("/api/v1/account/info/{id}") - fun info( - @PathVariable id: Long, - @CookieValue(value = "TOKEN", required = false) token: String? - ): String { - val queryUser = repository.findById(id).orElse(null) ?: return ResultBuilder("账户不存在").toJson() - var currentUser: User? = null - if (token != null) currentUser = repository.findByToken(token) - val result = mapOf( - "id" to queryUser.id, - "name" to queryUser.name, - "gender" to queryUser.gender, - "createTime" to queryUser.createTime, - "loginTime" to queryUser.loginTime - ) - if (currentUser != null && (currentUser.id == id || currentUser.isAdmin)) result + mapOf( - "address" to queryUser.address, - "admin" to queryUser.isAdmin, - "carts" to queryUser.carts, - "orders" to queryUser.orders, - "phone" to queryUser.phone - ) - return ResultBuilder(result).toJson() + private fun getCurrentUser(token: String?): User? { + return token?.let(repository::findByToken) } - @PostMapping("/api/v1/account/login") + private fun hasAdminPermissions(token: String?): Boolean { + return this.getCurrentUser(token)?.isAdmin ?: false + } + + private fun updateToken(response: HttpServletResponse, token: String, path: String = "/", age: Int = 2678400) { + val cookie = Cookie("TOKEN", token) + cookie.path = path + cookie.maxAge = age + response.addCookie(cookie) + } + + @GetMapping("/api/v1/account/info", produces = ["application/json"]) + fun infoMe( + @CookieValue(value = "TOKEN", required = false) token: String? + ): String { + val user = this.getCurrentUser(token) ?: return ResultBuilder("账户未登录").toJson() + return ResultBuilder(user.asMap(UserType.User)).toJson() + } + + @GetMapping("/api/v1/account/info/{id}", produces = ["application/json"]) + fun info( + @CookieValue(value = "TOKEN", required = false) token: String?, @PathVariable id: Long + ): String { + val queryUser = repository.findById(id).orElse(null) ?: return ResultBuilder("账户不存在").toJson() + val currentUser = this.getCurrentUser(token) + return ResultBuilder( + queryUser.asMap(if (currentUser != null && (currentUser.id == id || currentUser.isAdmin)) UserType.User else UserType.Guest) + ).toJson() + } + + //@PostMapping + @RequestMapping("/api/v1/account/login", produces = ["application/json"]) fun login( response: HttpServletResponse, + @CookieValue(value = "TOKEN", required = false) token: String?, @RequestParam(name = "name") name: String, @RequestParam(name = "password") password: String ): String { + if (this.getCurrentUser(token) != null) return ResultBuilder("当前已登录账户").toJson() val user = repository.findByName(name) ?: return ResultBuilder("账户不存在").toJson() - if (!user.testPassword(password)) { - return ResultBuilder("密码错误").toJson() - } + if (!user.testPassword(password)) return ResultBuilder("密码错误").toJson() user.updateToken() - val cookie = Cookie("TOKEN", user.token) - cookie.maxAge = 2678400 - response.addCookie(cookie) + user.updateLoginTime() repository.save(user) + updateToken(response, user.token) return ResultBuilder("success", "登录成功").toJson() } - @PostMapping("/api/v1/account/logout") + @RequestMapping("/api/v1/account/logout", produces = ["application/json"]) fun logout(response: HttpServletResponse): String { - val cookie = Cookie("TOKEN", "") - cookie.maxAge = 0 - response.addCookie(cookie) + updateToken(response, "", age = 0) return ResultBuilder("success", "注销成功").toJson() } - @PostMapping("/api/v1/account/register") + @RequestMapping("/api/v1/account/register", produces = ["application/json"]) fun register( response: HttpServletResponse, + @CookieValue(value = "TOKEN", required = false) token: String?, @RequestParam(name = "name") name: String, @RequestParam(name = "password") password: String, @RequestParam(name = "age", required = false) age: Int?, @RequestParam(name = "gender", required = false) gender: String?, + @RequestParam(name = "phone", required = false) phone: String?, @RequestParam(name = "email", required = false) email: String?, - @RequestParam(name = "address", required = false) address: String?, - @RequestParam(name = "phone", required = false) phone: String? + @RequestParam(name = "address", required = false) address: String? ): String { - // TODO: 完成注册方法 - return "TODO" + if (this.getCurrentUser(token) != null) return ResultBuilder("当前已登录账户").toJson() + val user = repository.save(User(name, password, age, gender, phone, email, address)) + updateToken(response, user.token) + return ResultBuilder("success", "注册成功").toJson() } - @PostMapping("/api/v1/account/update") + @RequestMapping("/api/v1/account/update", produces = ["application/json"]) fun update( response: HttpServletResponse, - @CookieValue(name = "TOKEN", required = false) token: String, + @CookieValue(name = "TOKEN", required = false) token: String?, @RequestParam(name = "name") name: String, @RequestParam(name = "password") password: String, @RequestParam(name = "age", required = false) age: Int?, @RequestParam(name = "gender", required = false) gender: String?, + @RequestParam(name = "phone", required = false) phone: String?, @RequestParam(name = "email", required = false) email: String?, - @RequestParam(name = "address", required = false) address: String?, - @RequestParam(name = "phone", required = false) phone: String? + @RequestParam(name = "address", required = false) address: String? ): String { - // TODO: 完成更新账户数据方法 - return "TODO" + val user = this.getCurrentUser(token) ?: return ResultBuilder("账户未登录").toJson() + user.update(name, password, age, gender, phone, email, address) + repository.save(user) + updateToken(response, user.token) + return ResultBuilder("success", "更新账户信息成功").toJson() } - @GetMapping("/api/v1/account/admin/info/{id}") + @GetMapping("/api/v1/account/admin/info/{id}", produces = ["application/json"]) fun infoAdmin( @CookieValue(value = "TOKEN", required = false) token: String?, @PathVariable id: Long, ): String { - var currentUser: User? = null - if (token != null) currentUser = repository.findByToken(token) - if (currentUser == null) return ResultBuilder("账户未登录").toJson() - if (!currentUser.isAdmin) return ResultBuilder("无管理员权限").toJson() + if (this.hasAdminPermissions(token)) return ResultBuilder("无管理员权限").toJson() return ResultBuilder(repository.findById(id)).toJson() } - @DeleteMapping("/api/v1/account/admin/remove/{id}") + @DeleteMapping("/api/v1/account/admin/remove/{id}", produces = ["application/json"]) fun removeAdmin( @CookieValue(value = "TOKEN", required = false) token: String?, @PathVariable id: Long, ): String { - var currentUser: User? = null - if (token != null) currentUser = repository.findByToken(token) - if (currentUser == null) return ResultBuilder("账户未登录").toJson() - if (!currentUser.isAdmin) return ResultBuilder("无管理员权限").toJson() + if (this.hasAdminPermissions(token)) return ResultBuilder("无管理员权限").toJson() // TODO: 完成管理员删除方法 return ResultBuilder(repository.findById(id)).toJson() } - @PostMapping("/api/v1/account/admin/update/{id}") + @PostMapping("/api/v1/account/admin/update/{id}", produces = ["application/json"]) fun updateAdmin( @CookieValue(value = "TOKEN", required = false) token: String?, @PathVariable id: Long, @@ -125,14 +132,11 @@ class Account(private val repository: UserRepository) { @RequestParam(name = "password") password: String, @RequestParam(name = "age", required = false) age: Int?, @RequestParam(name = "gender", required = false) gender: String?, + @RequestParam(name = "phone", required = false) phone: String?, @RequestParam(name = "email", required = false) email: String?, - @RequestParam(name = "address", required = false) address: String?, - @RequestParam(name = "phone", required = false) phone: String? + @RequestParam(name = "address", required = false) address: String? ): String { - var currentUser: User? = null - if (token != null) currentUser = repository.findByToken(token) - if (currentUser == null) return ResultBuilder("账户未登录").toJson() - if (!currentUser.isAdmin) return ResultBuilder("无管理员权限").toJson() + if (this.hasAdminPermissions(token)) return ResultBuilder("无管理员权限").toJson() // TODO: 完成管理员更新账户数据方法 return ResultBuilder(repository.findById(id)).toJson() } diff --git a/src/main/kotlin/team8/fruitable/controller/api/Cart.kt b/src/main/kotlin/team8/fruitable/controller/api/Cart.kt index 1d5ca72..aa98d1f 100644 --- a/src/main/kotlin/team8/fruitable/controller/api/Cart.kt +++ b/src/main/kotlin/team8/fruitable/controller/api/Cart.kt @@ -1,4 +1,4 @@ package team8.fruitable.controller.api class Cart { -} \ No newline at end of file +} diff --git a/src/main/kotlin/team8/fruitable/controller/api/Item.kt b/src/main/kotlin/team8/fruitable/controller/api/Item.kt index bbb57a8..1bede53 100644 --- a/src/main/kotlin/team8/fruitable/controller/api/Item.kt +++ b/src/main/kotlin/team8/fruitable/controller/api/Item.kt @@ -1,4 +1,26 @@ package team8.fruitable.controller.api -class Item { -} \ No newline at end of file +import org.springframework.web.bind.annotation.CookieValue +import org.springframework.web.bind.annotation.GetMapping +import org.springframework.web.bind.annotation.PathVariable +import org.springframework.web.bind.annotation.RestController +import team8.fruitable.datebase.entity.User +import team8.fruitable.datebase.repository.ItemRepository +import team8.fruitable.datebase.repository.UserRepository +import team8.fruitable.util.ResultBuilder + +@RestController +class Item(private val itemRepository: ItemRepository, private val userRepository: UserRepository) { + private fun getCurrentUser(token: String?): User? { + return token?.let(userRepository::findByToken) + } + + private fun hasAdminPermissions(token: String?): Boolean { + return this.getCurrentUser(token)?.isAdmin ?: false + } + + @GetMapping("/api/v1/item/info/{id}", produces = ["application/json"]) + fun info(@PathVariable id: Long): String { + return ResultBuilder(itemRepository.findById(id).orElse(null)).toJson() + } +} diff --git a/src/main/kotlin/team8/fruitable/controller/api/Order.kt b/src/main/kotlin/team8/fruitable/controller/api/Order.kt index 1a18373..83b0286 100644 --- a/src/main/kotlin/team8/fruitable/controller/api/Order.kt +++ b/src/main/kotlin/team8/fruitable/controller/api/Order.kt @@ -1,4 +1,4 @@ package team8.fruitable.controller.api class Order { -} \ No newline at end of file +} diff --git a/src/main/kotlin/team8/fruitable/datebase/entity/Item.kt b/src/main/kotlin/team8/fruitable/datebase/entity/Item.kt index 97e8344..03ea6fb 100644 --- a/src/main/kotlin/team8/fruitable/datebase/entity/Item.kt +++ b/src/main/kotlin/team8/fruitable/datebase/entity/Item.kt @@ -2,7 +2,6 @@ package team8.fruitable.datebase.entity import jakarta.persistence.* - @Entity @Table(name = "items") class Item( @@ -17,7 +16,7 @@ class Item( @Column(name="price", nullable = false) var price: Double? = null, - @Column(name="DESCRIPTION", length=320, nullable = true) + @Column(name="description", length=320, nullable = true) var description: String? = null, @ManyToOne @@ -29,5 +28,8 @@ class Item( var ordered: Order? = null, @OneToMany(cascade = [(CascadeType.ALL)], fetch = FetchType.LAZY, mappedBy = "tagedItem") - var tags: MutableList = mutableListOf() + var tags: MutableList = mutableListOf(), + + @OneToOne(mappedBy = "item") + var recommend: Recommend? = null, ) diff --git a/src/main/kotlin/team8/fruitable/datebase/entity/Order.kt b/src/main/kotlin/team8/fruitable/datebase/entity/Order.kt index e6495ac..3b31b74 100644 --- a/src/main/kotlin/team8/fruitable/datebase/entity/Order.kt +++ b/src/main/kotlin/team8/fruitable/datebase/entity/Order.kt @@ -3,7 +3,6 @@ package team8.fruitable.datebase.entity import jakarta.persistence.* import java.time.LocalDateTime - @Entity @Table(name = "orders") class Order( diff --git a/src/main/kotlin/team8/fruitable/datebase/entity/PayType.kt b/src/main/kotlin/team8/fruitable/datebase/entity/PayType.kt index f2ccf14..784c2a4 100644 --- a/src/main/kotlin/team8/fruitable/datebase/entity/PayType.kt +++ b/src/main/kotlin/team8/fruitable/datebase/entity/PayType.kt @@ -2,7 +2,6 @@ package team8.fruitable.datebase.entity import jakarta.persistence.* - @Entity @Table(name = "pay_type") class PayType( diff --git a/src/main/kotlin/team8/fruitable/datebase/entity/Recommend.kt b/src/main/kotlin/team8/fruitable/datebase/entity/Recommend.kt new file mode 100644 index 0000000..602d819 --- /dev/null +++ b/src/main/kotlin/team8/fruitable/datebase/entity/Recommend.kt @@ -0,0 +1,19 @@ +package team8.fruitable.datebase.entity + +import jakarta.persistence.* + +@Entity +@Table(name = "recommends") +class Recommend ( + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "id", nullable = false) + var id: Long? = null, + + @OneToOne + @JoinColumn(name = "item") + var item: Item, + + @Column(name="description", length=32, nullable = false) + var description: String? = null, +) \ No newline at end of file diff --git a/src/main/kotlin/team8/fruitable/datebase/entity/Tag.kt b/src/main/kotlin/team8/fruitable/datebase/entity/Tag.kt index c7d6210..95eaff9 100644 --- a/src/main/kotlin/team8/fruitable/datebase/entity/Tag.kt +++ b/src/main/kotlin/team8/fruitable/datebase/entity/Tag.kt @@ -2,7 +2,6 @@ package team8.fruitable.datebase.entity import jakarta.persistence.* - @Entity @Table(name = "tags") class Tag( diff --git a/src/main/kotlin/team8/fruitable/datebase/entity/User.kt b/src/main/kotlin/team8/fruitable/datebase/entity/User.kt index df169ff..6a0c66f 100644 --- a/src/main/kotlin/team8/fruitable/datebase/entity/User.kt +++ b/src/main/kotlin/team8/fruitable/datebase/entity/User.kt @@ -1,6 +1,7 @@ package team8.fruitable.datebase.entity import jakarta.persistence.* +import team8.fruitable.constant.UserType import team8.fruitable.util.Util import java.time.LocalDateTime import java.util.* @@ -21,7 +22,7 @@ class User( var password: String? = null, @Column(name = "time_create", nullable = false) - val createTime: LocalDateTime = LocalDateTime.now(), + var createTime: LocalDateTime = LocalDateTime.now(), @Column(name = "time_login", nullable = false) var loginTime: LocalDateTime = LocalDateTime.now(), @@ -53,15 +54,89 @@ class User( @OneToMany(cascade = [(CascadeType.ALL)], fetch = FetchType.LAZY, mappedBy = "user") var orders: MutableList = mutableListOf() ) { + constructor(name: String, password: String) : this() { + this.name = name + this.password = this.genPassword(password) + } + + constructor( + name: String, + password: String, + age: Int?, + gender: String?, + phone: String?, + email: String?, + address: String? + ) : this(name, password) { + this.age = age + this.gender = gender + this.phone = phone + this.email = email + this.address = address + } + + final fun genPassword(password: String): String { + return Util.hash(password) + } + + fun update( + name: String, + password: String, + age: Int?, + gender: String?, + phone: String?, + email: String?, + address: String?, + isAdmin: Boolean = false + ) { + this.name = name + this.updatePassword(password) + this.age = age + this.gender = gender + this.phone = phone + this.email = email + this.address = address + this.isAdmin = isAdmin + this.updateToken() + } + fun testPassword(password: String): Boolean { return Util.hash(password) == this.password } fun updatePassword(password: String) { - this.password = Util.hash(password) + this.password = this.genPassword(password) + } + + fun updateLoginTime() { + this.loginTime = LocalDateTime.now() } fun updateToken() { this.token = UUID.randomUUID().toString() } + + fun asMap(userType: UserType): Map { + val result: MutableMap = mutableMapOf( + "id" to this.id, + "name" to this.name, + "createTime" to this.createTime, + "loginTime" to this.loginTime, + "age" to this.age, + "gender" to this.gender, + "email" to this.email, + ) + if (userType == UserType.User || userType == UserType.Admin) result += mapOf( + "phone" to this.phone, + "address" to this.address, + "isAdmin" to this.isAdmin, + "carts" to this.carts, + "orders" to this.orders + ) + if (userType == UserType.Admin) result += mapOf( + "password" to this.password, + "token" to this.token, + ) + return result + } } diff --git a/src/main/kotlin/team8/fruitable/datebase/repository/ItemRepository.kt b/src/main/kotlin/team8/fruitable/datebase/repository/ItemRepository.kt new file mode 100644 index 0000000..aee4239 --- /dev/null +++ b/src/main/kotlin/team8/fruitable/datebase/repository/ItemRepository.kt @@ -0,0 +1,8 @@ +package team8.fruitable.datebase.repository + +import org.springframework.data.repository.CrudRepository +import team8.fruitable.datebase.entity.Item + +interface ItemRepository : CrudRepository { + fun findByName(name: String): Item? +} diff --git a/src/main/kotlin/team8/fruitable/datebase/repository/UserRepository.kt b/src/main/kotlin/team8/fruitable/datebase/repository/UserRepository.kt index 644291b..cd9460b 100644 --- a/src/main/kotlin/team8/fruitable/datebase/repository/UserRepository.kt +++ b/src/main/kotlin/team8/fruitable/datebase/repository/UserRepository.kt @@ -3,7 +3,6 @@ package team8.fruitable.datebase.repository import org.springframework.data.repository.CrudRepository import team8.fruitable.datebase.entity.User - interface UserRepository : CrudRepository { fun findByName(name: String): User? fun findByToken(token: String): User? diff --git a/src/main/kotlin/team8/fruitable/util/ResultBuilder.kt b/src/main/kotlin/team8/fruitable/util/ResultBuilder.kt index db4c514..551a190 100644 --- a/src/main/kotlin/team8/fruitable/util/ResultBuilder.kt +++ b/src/main/kotlin/team8/fruitable/util/ResultBuilder.kt @@ -4,7 +4,6 @@ import com.alibaba.fastjson2.toJSONString import java.time.LocalDateTime import java.util.* - class ResultBuilder { var status: String = "auto" var message: String = "" diff --git a/src/main/kotlin/team8/fruitable/util/Util.kt b/src/main/kotlin/team8/fruitable/util/Util.kt index b947518..3c73b9b 100644 --- a/src/main/kotlin/team8/fruitable/util/Util.kt +++ b/src/main/kotlin/team8/fruitable/util/Util.kt @@ -2,12 +2,11 @@ package team8.fruitable.util import java.security.MessageDigest - class Util { companion object { fun hash(input: String, algorithm: String = "SHA-256"): String { return MessageDigest.getInstance(algorithm).digest(input.toByteArray()) - .fold("", { str, it -> str + "%02x".format(it) }) + .fold("") { str, it -> str + "%02x".format(it) } } } } diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties deleted file mode 100644 index f982dd6..0000000 --- a/src/main/resources/application.properties +++ /dev/null @@ -1,10 +0,0 @@ - -spring.datasource.url=jdbc:mariadb://localhost:3306/fruitable -spring.datasource.username=root -spring.datasource.password=password - -#???????updata:????????????,????????? -spring.jpa.hibernate.ddl-auto=update -spring.jpa.show-sql=true -#?????????? Unable to build Hibernate SessionFactory -#spring.jpa.properties.hibernate.hbm2ddl.auto=validate diff --git a/src/main/resources/application.yaml b/src/main/resources/application.yaml new file mode 100644 index 0000000..88ce562 --- /dev/null +++ b/src/main/resources/application.yaml @@ -0,0 +1,9 @@ +spring: + datasource: + url: jdbc:mariadb://localhost:3306/fruitable + username: root + password: password + jpa: + show-sql: true + hibernate: + ddl-auto: update