Vapor validatable UUID

Hi :slight_smile:

I'm trying to make one of my DTOs conform to Validatable and I have never really had any issues with it so far - super easy to use and it has basically all the tools that you need!

But now I'm having an issue trying to validate that a field must be a valid UUID and I am not sure how to do this?

import Vapor

extension PersonReward.CreateDTO: Validatable {
    static func validations(_ validations: inout Validations) {
        validations.add("title", as: String.self, is: !.empty)
        validations.add("title", as: String.self, is: .count(...40))
        validations.add("description", as: String?.self, is: .nil || !.empty, required: false)
        validations.add("price", as: Int32.self, is: .range(...Int32.max))

        // TODO: validate that `personId` is a valid UUID
    }
}

Hey henrikac,

I am afraid currently there is nothing build in. So for the moment your only chance is to combine validators to get what you want.

In wich perimeter do you want to validate the UUID? The first I can think of is .pattern().

I was afraid that you would say something like :sweat_smile:

I'm not familiar with .pattern() - is it a built-in validator like .count()?

Could a possible solution be to validate it as a string and then in the route check if the string is a valid UUID?

guard let personId = UUID(uuidString: someStr) else {
    throw Abort(.badRequest)
}

Yes, it's like the others. For example (untested):

validations.add("personID", as: String.self, is: .pattern("^[0-9a-fA-F]{8}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{12}$"))

But... I am sorry. I didn't notice that it only works for a String.

Blockquote
Could a possible solution be to validate it as a string and then in the route check if the string is a valid UUID?

Yea, you could do. I think, there is no right or wrong. What fits your needs. Of course in many other cases it depends on when you would like to give feedback to your user. But in your case the validation is handled on the server side, wich is after the form submission, so it doesn't really matter, I guess.

1 Like

I like this! Not sure why this is not mentioned in the docs.

Yup, you are right. I will add it.Thanks for noticing.

2 Likes

Does

validations.add("personId", as: UUID.self)

work?

Looks like it works!

If I try to send "personId":"abc" I get the following error {"error":true,"reason":"personId is invalid: Attempted to decode UUID from invalid UUID string."}