Introduction

In the first part I showed you how to configure ServiceStack and in the second part I showed you how to read from the ServiceStack service with Easyhttp. And now it is time to give Santa the opportunity to add some children.

ServiceStack

I want to use the same request for my Post as I did for my Get. This means I will need to add LastName to the request.

Imports ServiceStack.ServiceInterface

Namespace Request
    <Authenticate>
    Public Class GoodOrBadRequest
        Public Property Good As Boolean?
        Public Property LastName As String
    End Class
End Namespace```
And then we need to add the Post implementation to our service.

```vbnet
Imports SantaGoodAndBad.Response
Imports SantaGoodAndBad.Request
Imports ServiceStack.ServiceInterface

Namespace DefaultNamespace.Service
    Public Class GoodOrBadService
        Inherits RestServiceBase(Of GoodOrBadRequest)

        Dim children As List(Of Child)

        Public Sub New()
            MakeChildren()
        End Sub

        Public Overrides Function OnPost(request As GoodOrBadRequest) As Object
            children.Add(New Child With {.LastName = request.LastName, .Good = request.Good})
            Return children
        End Function

        Public Overrides Function OnGet(request As GoodOrBadRequest) As Object
            If request.Good.HasValue Then
                Return children.Where(Function(child) child.Good.Value = request.Good.Value).ToList
            Else
                Return children
            End If
        End Function

        Private Function MakeChildren() As IList(Of Child)
            children = New List(Of Child)
            children.Add(New Child With {.LastName = "Baes", .Good = True})
            children.Add(New Child With {.LastName = "Hariri", .Good = False})
            children.Add(New Child With {.LastName = "Hanselman", .Good = True})
            children.Add(New Child With {.LastName = "Krueger", .Good = False})
            Return children
        End Function

    End Class
End Namespace```
The above works just fine, trust me.

However, the client changed their minds, they only want Santa to be able to read and add children to the list and the elfs can read the list but not add children to the list.

For this to work I have to create an elf account with a role of elfs and a santa with roles of santa and elfs. We do this in the apphost for now.

```vbnet
Imports ServiceStack.CacheAccess.Providers
Imports ServiceStack.CacheAccess
Imports ServiceStack.ServiceInterface.Auth
Imports SantaGoodAndBad.Request
Imports SantaGoodAndBad.DefaultNamespace.Service
Imports ServiceStack.ServiceInterface
Imports ServiceStack.WebHost.Endpoints

Public Class AppHost
    Inherits AppHostHttpListenerBase

    Public Sub New()
        MyBase.New("Good or bad", GetType(GoodOrBadService).Assembly)
    End Sub

    Public Overrides Sub Configure(container As Funq.Container)
        Routes.Add(Of GoodOrBadRequest)("/GoodOrBad") _
            .Add(Of GoodOrBadRequest)("/GoodOrBad/{Good}")

        Plugins.Add(New AuthFeature(Function() New AuthUserSession(), New AuthProvider() {New CredentialsAuthProvider()}))
        container.Register(Of ICacheClient)(New MemoryCacheClient())
        Dim userRep = New InMemoryAuthRepository()
        container.Register(Of IUserAuthRepository)(userRep)
        Dim hash As String
        Dim salt As String
        Dim s = New SaltedHash()
        s.GetHashAndSaltString("test", hash, salt)
        userRep.CreateUserAuth(New UserAuth With {.Id = 1, .DisplayName = "Santa Claus", .Email = "Santa@Claus.com", .UserName = "santa", .FirstName = "Kris", .LastName = "Kringle", .PasswordHash = hash, .Salt = salt, .Roles = New List(Of String) From {"Santa", "Elfs"}}, "jingle")
        userRep.CreateUserAuth(New UserAuth With {.Id = 2, .DisplayName = "Elf 1", .Email = "Elf1@Claus.com", .UserName = "elf1", .FirstName = "Elf", .LastName = "One", .PasswordHash = hash, .Salt = salt, .Roles = New List(Of String) From {"Elfs"}}, "bells")
    End Sub

End Class```
And we need to tell our request which roles are allowed to do what.

```vbnet
Imports ServiceStack.ServiceInterface

Namespace Request
    <Authenticate>
    <RequiredRole(ApplyTo.Get, "Elfs")>
    <RequiredRole(ApplyTo.Post, "Santa")>
    Public Class GoodOrBadRequest
        Public Property Good As Boolean?
        Public Property LastName As String
    End Class
End Namespace```
Yep that was pretty simple.

Now to test this.

## Easyhttp

I added a method to do the post and then read the results and I added another Authorize for easy testing. Here is the complete copy pasteable code

```vbnet
Option Strict Off

Imports EasyHttp.Http

Module Module1

    Sub Main()
        Dim response As HttpResponse
        InitializeClient()
        PrintChild(DoGet("http://localhost:58241/GoodOrBad", Nothing))
        Console.WriteLine("")
        AuthorizeSanta()
        PrintChild(DoGet("http://localhost:58241/GoodOrBad", Nothing))
        Console.WriteLine("")
        PrintChild(DoPost("http://localhost:58241/GoodOrBad", New With {.LastName = "Stack", .Good = False}))
        Console.WriteLine("")
        LogOut()
        AuthorizeElf1()
        PrintChild(DoGet("http://localhost:58241/GoodOrBad", Nothing))
        Console.WriteLine("")
        PrintChild(DoPost("http://localhost:58241/GoodOrBad", New With {.LastName = "Hamilton", .Good = False}))
        Console.WriteLine("")
        LogOut()
        PrintChild(DoGet("http://localhost:58241/GoodOrBad", Nothing))
        Console.WriteLine("")
        Console.ReadLine()
    End Sub

    Private Sub PrintChild(ByVal children As Object)
        If children IsNot Nothing Then
            For Each child In children
                If child.Good = False Then
                    Console.ForegroundColor = ConsoleColor.Red
                Else
                    Console.ForegroundColor = ConsoleColor.Green
                End If
                Console.WriteLine(child.LastName)
            Next
        End If
        Console.ForegroundColor = ConsoleColor.White
    End Sub

    Private Function DoGet(ByVal url As String, ByVal parameters As Object) As Object
        Dim response As HttpResponse = Nothing
        If parameters IsNot Nothing Then
            response = http.Get(url, parameters)
        Else
            response = http.Get(url)
        End If
        If response.StatusCode = Net.HttpStatusCode.Unauthorized Then
            Console.WriteLine("Unauthorized")
            response = Nothing
        End If
        If response IsNot Nothing Then
            Return response.DynamicBody
        Else
            Return Nothing
        End If
    End Function

    Private Function DoPost(ByVal url As String, ByVal parameters As Object) As Object
        Dim response As HttpResponse = Nothing
        If parameters IsNot Nothing Then
            response = http.Post(url, parameters, HttpContentTypes.ApplicationJson)
        Else
            response = Nothing
        End If
        If response.StatusCode = Net.HttpStatusCode.Unauthorized Then
            Console.WriteLine("Unauthorized")
            response = Nothing
        End If
        If response IsNot Nothing Then
            Return response.DynamicBody
        Else
            Return Nothing
        End If
    End Function

    Private Sub AuthorizeSanta()
        Dim response = http.Post("http://localhost:58241/auth", New With {.UserName = "santa", .Password = "jingle"}, HttpContentTypes.ApplicationJson)
        http.Request.Cookies = response.Cookie
        Console.WriteLine(response.DynamicBody.SessionId)
        Console.WriteLine(response.DynamicBody.UserName)
        Console.WriteLine("")
    End Sub

    Private Sub AuthorizeElf1()
        Dim response = http.Post("http://localhost:58241/auth", New With {.UserName = "elf1", .Password = "bells"}, HttpContentTypes.ApplicationJson)
        http.Request.Cookies = response.Cookie
        Console.WriteLine(response.DynamicBody.SessionId)
        Console.WriteLine(response.DynamicBody.UserName)
        Console.WriteLine("")
    End Sub

    Private Sub LogOut()
        Dim response = http.Get("http://localhost:58241/auth/logout")
        http.Request.Cookies = response.Cookie
    End Sub

    Private http As HttpClient

    Private Sub InitializeClient()
        If http Is Nothing Then
            http = New HttpClient()
            http.Request.Accept = HttpContentTypes.ApplicationJson
        End If
    End Sub

End Module

And here is the result.

Which is just as we expected.

Conclusion

It works but not as I intended. I did not plan on putting santa in the elfs role. I wanted him to be in the sanat role only and then give requiredrole to elfs and santa but that didn’t work. My mind probably needs to get around this.