Skip to content

Commit

Permalink
refactor: Migrate GET /admin/users/<iri|email|name> to Tapir (#3020)
Browse files Browse the repository at this point in the history
  • Loading branch information
seakayone committed Feb 6, 2024
1 parent 35ff4ed commit 4b25387
Show file tree
Hide file tree
Showing 13 changed files with 207 additions and 274 deletions.
Expand Up @@ -13,7 +13,6 @@ import java.util.UUID
import dsp.errors.BadRequestException
import dsp.errors.DuplicateValueException
import dsp.errors.ForbiddenException
import dsp.errors.NotFoundException
import dsp.valueobjects.LanguageCode
import org.knora.webapi.*
import org.knora.webapi.messages.StringFormatter
Expand Down Expand Up @@ -87,79 +86,73 @@ class UsersResponderADMSpec extends CoreSpec with ImplicitSender {

"asked about an user identified by 'iri' " should {
"return a profile if the user (root user) is known" in {
appActor ! UserGetByIriADM(
identifier = UserIri.unsafeFrom(rootUser.id),
userInformationTypeADM = UserInformationTypeADM.Full,
requestingUser = KnoraSystemInstances.Users.SystemUser
val actual = UnsafeZioRun.runOrThrow(
UsersResponderADM.findUserByIri(
UserIri.unsafeFrom(rootUser.id),
UserInformationTypeADM.Full,
KnoraSystemInstances.Users.SystemUser
)
)
expectMsg(Some(rootUser.ofType(UserInformationTypeADM.Full)))
actual shouldBe Some(rootUser.ofType(UserInformationTypeADM.Full))
}

"return 'None' when the user is unknown" in {
appActor ! UserGetByIriADM(
identifier = UserIri.unsafeFrom("http://rdfh.ch/users/notexisting"),
userInformationTypeADM = UserInformationTypeADM.Full,
requestingUser = KnoraSystemInstances.Users.SystemUser
val actual = UnsafeZioRun.runOrThrow(
UsersResponderADM.findUserByIri(
UserIri.unsafeFrom("http://rdfh.ch/users/notexisting"),
UserInformationTypeADM.Full,
KnoraSystemInstances.Users.SystemUser
)
)
expectMsg(None)
actual shouldBe None
}
}

"asked about an user identified by 'email'" should {
"return a profile if the user (root user) is known" in {
appActor ! UserGetByEmailADM(
email = Email.unsafeFrom(rootUser.email),
userInformationTypeADM = UserInformationTypeADM.Full,
requestingUser = KnoraSystemInstances.Users.SystemUser
)
expectMsg(Some(rootUser.ofType(UserInformationTypeADM.Full)))
}

"return 'NotFoundException' when the user is unknown" in {
appActor ! UserGetByEmailRequestADM(
email = Email.unsafeFrom("userwrong@example.com"),
userInformationTypeADM = UserInformationTypeADM.Full,
requestingUser = KnoraSystemInstances.Users.SystemUser
val actual = UnsafeZioRun.runOrThrow(
UsersResponderADM.findUserByEmail(
Email.unsafeFrom(rootUser.email),
UserInformationTypeADM.Full,
KnoraSystemInstances.Users.SystemUser
)
)
expectMsg(Failure(NotFoundException(s"User 'userwrong@example.com' not found")))
actual shouldBe Some(rootUser.ofType(UserInformationTypeADM.Full))
}

"return 'None' when the user is unknown" in {
appActor ! UserGetByEmailADM(
email = Email.unsafeFrom("userwrong@example.com"),
userInformationTypeADM = UserInformationTypeADM.Full,
requestingUser = KnoraSystemInstances.Users.SystemUser
val actual = UnsafeZioRun.runOrThrow(
UsersResponderADM.findUserByEmail(
Email.unsafeFrom("userwrong@example.com"),
UserInformationTypeADM.Full,
KnoraSystemInstances.Users.SystemUser
)
)
expectMsg(None)
actual shouldBe None
}
}

"asked about an user identified by 'username'" should {
"return a profile if the user (root user) is known" in {
appActor ! UserGetByUsernameADM(
username = Username.unsafeFrom(rootUser.username),
userInformationTypeADM = UserInformationTypeADM.Full,
requestingUser = KnoraSystemInstances.Users.SystemUser
)
expectMsg(Some(rootUser.ofType(UserInformationTypeADM.Full)))
}

"return 'NotFoundException' when the user is unknown" in {
appActor ! UserGetByUsernameRequestADM(
username = Username.unsafeFrom("userwrong"),
userInformationTypeADM = UserInformationTypeADM.Full,
requestingUser = KnoraSystemInstances.Users.SystemUser
val actual = UnsafeZioRun.runOrThrow(
UsersResponderADM.findUserByUsername(
Username.unsafeFrom(rootUser.username),
UserInformationTypeADM.Full,
KnoraSystemInstances.Users.SystemUser
)
)
expectMsg(Failure(NotFoundException(s"User 'userwrong' not found")))
actual shouldBe Some(rootUser.ofType(UserInformationTypeADM.Full))
}

"return 'None' when the user is unknown" in {
appActor ! UserGetByUsernameADM(
username = Username.unsafeFrom("userwrong"),
userInformationTypeADM = UserInformationTypeADM.Full,
requestingUser = KnoraSystemInstances.Users.SystemUser
val actual = UnsafeZioRun.runOrThrow(
UsersResponderADM.findUserByUsername(
Username.unsafeFrom("userwrong"),
UserInformationTypeADM.Full,
KnoraSystemInstances.Users.SystemUser
)
)
expectMsg(None)
actual shouldBe None
}
}

Expand Down
Expand Up @@ -25,6 +25,8 @@ import org.knora.webapi.messages.admin.responder.permissionsmessages.Permissions
import org.knora.webapi.messages.admin.responder.projectsmessages.ProjectADM
import org.knora.webapi.messages.admin.responder.projectsmessages.ProjectsADMJsonProtocol
import org.knora.webapi.slice.admin.domain.model.*
import org.knora.webapi.slice.common.ToValidation.validateOneWithFrom
import org.knora.webapi.slice.common.ToValidation.validateOptionWithFrom

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// API requests
Expand Down Expand Up @@ -159,58 +161,6 @@ case class UserGetByIriADM(
requestingUser: User
) extends UsersResponderRequestADM

/**
* A message that requests a user's profile by username. A successful response will be a [[User]].
*
* @param username the username of the user to be queried.
* @param userInformationTypeADM the extent of the information returned.
* @param requestingUser the user initiating the request.
*/
case class UserGetByUsernameADM(
username: Username,
userInformationTypeADM: UserInformationTypeADM = UserInformationTypeADM.Short,
requestingUser: User
) extends UsersResponderRequestADM

/**
* A message that requests a user's profile by email. A successful response will be a [[User]].
*
* @param email the email of the user to be queried.
* @param userInformationTypeADM the extent of the information returned.
* @param requestingUser the user initiating the request.
*/
case class UserGetByEmailADM(
email: Email,
userInformationTypeADM: UserInformationTypeADM = UserInformationTypeADM.Short,
requestingUser: User
) extends UsersResponderRequestADM

/**
* A message that requests a user's profile by email. A successful response will be a [[UserResponseADM]].
*
* @param email the email of the user to be queried.
* @param userInformationTypeADM the extent of the information returned.
* @param requestingUser the user initiating the request.
*/
case class UserGetByEmailRequestADM(
email: Email,
userInformationTypeADM: UserInformationTypeADM = UserInformationTypeADM.Short,
requestingUser: User
) extends UsersResponderRequestADM

/**
* A message that requests a user's profile by username. A successful response will be a [[UserResponseADM]].
*
* @param username the username of the user to be queried.
* @param userInformationTypeADM the extent of the information returned.
* @param requestingUser the user initiating the request.
*/
case class UserGetByUsernameRequestADM(
username: Username,
userInformationTypeADM: UserInformationTypeADM = UserInformationTypeADM.Short,
requestingUser: User
) extends UsersResponderRequestADM

/**
* Requests the creation of a new user.
*
Expand Down Expand Up @@ -594,10 +544,10 @@ object UserUpdateBasicInformationPayloadADM {

def make(req: ChangeUserApiRequestADM): Validation[ValidationException, UserUpdateBasicInformationPayloadADM] =
Validation.validateWith(
validateWithOptionOrNone(req.username, Username.validationFrom).mapError(ValidationException(_)),
validateWithOptionOrNone(req.email, Email.validationFrom).mapError(ValidationException(_)),
validateWithOptionOrNone(req.givenName, GivenName.validationFrom).mapError(ValidationException(_)),
validateWithOptionOrNone(req.familyName, FamilyName.validationFrom).mapError(ValidationException(_)),
validateOptionWithFrom(req.username, Username.from, ValidationException.apply),
validateOptionWithFrom(req.email, Email.from, ValidationException.apply),
validateOptionWithFrom(req.givenName, GivenName.from, ValidationException.apply),
validateOptionWithFrom(req.familyName, FamilyName.from, ValidationException.apply),
validateWithOptionOrNone(req.lang, LanguageCode.make)
)(UserUpdateBasicInformationPayloadADM.apply)
}
Expand All @@ -606,11 +556,12 @@ case class UserUpdatePasswordPayloadADM(requesterPassword: Password, newPassword
object UserUpdatePasswordPayloadADM {
def make(apiRequest: ChangeUserPasswordApiRequestADM): Validation[String, UserUpdatePasswordPayloadADM] = {
val requesterPasswordValidation = apiRequest.requesterPassword
.map(Password.validationFrom)
.map(validateOneWithFrom(_, Password.from, a => a))
.getOrElse(Validation.fail("The requester's password is missing."))
val newPasswordValidation = apiRequest.newPassword
.map(Password.validationFrom)
.getOrElse(Validation.fail("The new password is missing."))
val newPasswordValidation =
apiRequest.newPassword
.map(validateOneWithFrom(_, Password.from, a => a))
.getOrElse(Validation.fail("The new password is missing."))
Validation.validateWith(requesterPasswordValidation, newPasswordValidation)(UserUpdatePasswordPayloadADM.apply)
}
}
Expand Down Expand Up @@ -640,19 +591,16 @@ object UserCreatePayloadADM {
def make(apiRequest: CreateUserApiRequestADM): Validation[String, UserCreatePayloadADM] =
Validation
.validateWith(
apiRequest.id
.map(UserIri.validationFrom(_).map(Some(_)).mapError(ValidationException(_)))
.getOrElse(Validation.succeed(None)),
Username.validationFrom(apiRequest.username).mapError(ValidationException(_)),
Email.validationFrom(apiRequest.email).mapError(ValidationException(_)),
GivenName.validationFrom(apiRequest.givenName).mapError(ValidationException(_)),
FamilyName.validationFrom(apiRequest.familyName).mapError(ValidationException(_)),
Password.validationFrom(apiRequest.password).mapError(ValidationException(_)),
validateOptionWithFrom(apiRequest.id, UserIri.from, a => a),
validateOneWithFrom(apiRequest.username, Username.from, a => a),
validateOneWithFrom(apiRequest.email, Email.from, a => a),
validateOneWithFrom(apiRequest.givenName, GivenName.from, a => a),
validateOneWithFrom(apiRequest.familyName, FamilyName.from, a => a),
validateOneWithFrom(apiRequest.password, Password.from, a => a),
Validation.succeed(UserStatus.from(apiRequest.status)),
LanguageCode.make(apiRequest.lang),
LanguageCode.make(apiRequest.lang).mapError(_.getMessage),
Validation.succeed(SystemAdmin.from(apiRequest.systemAdmin))
)(UserCreatePayloadADM.apply)
.mapError(_.getMessage)
}

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Expand Down

0 comments on commit 4b25387

Please sign in to comment.