Skip to content

Commit

Permalink
Add user controller
Browse files Browse the repository at this point in the history
  • Loading branch information
BilledTrain380 committed Oct 7, 2018
1 parent f66bdaa commit eb7663c
Show file tree
Hide file tree
Showing 5 changed files with 188 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -103,8 +103,12 @@ interface UserManager {

/**
* Deletes the user matching the given {@code userId}.
*
* The user representing the administrator can not be deleted.
*
* @param userId id of the user to delete
*
* @throws IllegalArgumentException if the given id belongs to the administrator user
*/
fun delete(userId: Int)
}
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,15 @@ class UserManagerImpl(

override fun getOne(username: String): Optional<User> = userRepository.findByUsername(username).map { it.toModel() }

override fun delete(userId: Int) = userRepository.deleteById(userId)
override fun delete(userId: Int) {

val user = userRepository.findById(userId)

if (user.isPresent && user.get().username == USER_ADMIN)
throw IllegalArgumentException("Not allowed to delete administrator")

userRepository.deleteById(userId)
}

private fun String.encode(): String = BCryptPasswordEncoder(4).encode(this)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,12 @@ data class RestResult(
val discipline: Discipline
)

data class RestUser(
val id: Int,
val username: String,
val enabled: Boolean
)

// Factory functions to create a data class representing the the JSON object of the given parameter.

fun json(participant: Participant): RestParticipant {
Expand Down Expand Up @@ -125,3 +131,11 @@ fun json(result: Result): RestResult {
result.discipline
)
}

fun json(user: User): RestUser {
return RestUser(
user.id,
user.username,
user.enabled
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/*
* Copyright (c) 2018 by Nicolas Märchy
*
* This file is part of Sporttag PSA.
*
* Sporttag PSA is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Sporttag PSA is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Sporttag PSA. If not, see <http://www.gnu.org/licenses/>.
*
* Diese Datei ist Teil von Sporttag PSA.
*
* Sporttag PSA ist Freie Software: Sie können es unter den Bedingungen
* der GNU General Public License, wie von der Free Software Foundation,
* Version 3 der Lizenz oder (nach Ihrer Wahl) jeder späteren
* veröffentlichten Version, weiterverbreiten und/oder modifizieren.
*
* Sporttag PSA wird in der Hoffnung, dass es nützlich sein wird, aber
* OHNE JEDE GEWÄHRLEISTUNG, bereitgestellt; sogar ohne die implizite
* Gewährleistung der MARKTFÄHIGKEIT oder EIGNUNG FÜR EINEN BESTIMMTEN ZWECK.
* Siehe die GNU General Public License für weitere Details.
*
* Sie sollten eine Kopie der GNU General Public License zusammen mit diesem
* Programm erhalten haben. Wenn nicht, siehe <http://www.gnu.org/licenses/>.
*
*
*/

package ch.schulealtendorf.sporttagpsa.controller.rest.user

data class NewUser(
val username: String,
val enabled: Boolean,
val password: String
)

data class UpdateUser(
val username: String,
val enabled: Boolean
)

data class PasswordWrapper(
val password: String
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
/*
* Copyright (c) 2018 by Nicolas Märchy
*
* This file is part of Sporttag PSA.
*
* Sporttag PSA is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Sporttag PSA is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Sporttag PSA. If not, see <http://www.gnu.org/licenses/>.
*
* Diese Datei ist Teil von Sporttag PSA.
*
* Sporttag PSA ist Freie Software: Sie können es unter den Bedingungen
* der GNU General Public License, wie von der Free Software Foundation,
* Version 3 der Lizenz oder (nach Ihrer Wahl) jeder späteren
* veröffentlichten Version, weiterverbreiten und/oder modifizieren.
*
* Sporttag PSA wird in der Hoffnung, dass es nützlich sein wird, aber
* OHNE JEDE GEWÄHRLEISTUNG, bereitgestellt; sogar ohne die implizite
* Gewährleistung der MARKTFÄHIGKEIT oder EIGNUNG FÜR EINEN BESTIMMTEN ZWECK.
* Siehe die GNU General Public License für weitere Details.
*
* Sie sollten eine Kopie der GNU General Public License zusammen mit diesem
* Programm erhalten haben. Wenn nicht, siehe <http://www.gnu.org/licenses/>.
*
*
*/

package ch.schulealtendorf.sporttagpsa.controller.rest.user

import ch.schulealtendorf.sporttagpsa.business.user.UserManager
import ch.schulealtendorf.sporttagpsa.business.user.validation.InvalidPasswordException
import ch.schulealtendorf.sporttagpsa.controller.rest.BadRequestException
import ch.schulealtendorf.sporttagpsa.controller.rest.NotFoundException
import ch.schulealtendorf.sporttagpsa.controller.rest.RestUser
import ch.schulealtendorf.sporttagpsa.controller.rest.json
import ch.schulealtendorf.sporttagpsa.model.User
import org.springframework.web.bind.annotation.*

/**
* Rest controller for user domain.
*
* @author nmaerchy <billedtrain380@gmail.com>
* @since 2.0.0
*/
@RestController
@RequestMapping("/api")
class UserController(
private val userManager: UserManager
) {

@GetMapping("/users")
fun getUsers(): List<RestUser> {
return userManager.getAll().map { json(it) }
}

@PostMapping("/users")
fun createUser(newUser: NewUser) {

val user = User(0, newUser.username, listOf("ROLE_USER"), newUser.enabled, newUser.password)
userManager.save(user)
}

@GetMapping("/user/{user_id}")
fun getUser(@PathVariable("user_id") id: Int): RestUser {
return json(userManager.findOne(id))
}

@PatchMapping("/user/{user_id")
fun updateUser(@PathVariable("user_id") id: Int, @RequestBody updateUser: UpdateUser) {

val user = userManager.findOne(id)

userManager.save(
user.copy(username = updateUser.username, enabled = updateUser.enabled)
)
}

@PutMapping("/user/{user_id}")
fun updateUser(@PathVariable("user_id") id: Int, @RequestBody wrapper: PasswordWrapper) {

try {

val user = userManager.findOne(id)
userManager.changePassword(user, wrapper.password)

} catch (ex: InvalidPasswordException) {
throw BadRequestException(ex.message, ex)
}
}

@DeleteMapping("/user/{user_id}")
fun deleteUser(@PathVariable("user_id") id: Int) {
userManager.delete(id)
}

private fun UserManager.findOne(id: Int): User {
return getOne(id)
.orElseThrow { NotFoundException("Could not find user: user_id=$id") }
}
}

0 comments on commit eb7663c

Please sign in to comment.