ServiceStack 4 Cookbook
上QQ阅读APP看书,第一时间看更新

Creating a simple admin service

ServiceStack's heavy use of DTOs in the form of Plain Old CLR Objects (POCOs) enables developers to expose data in very simple, elegant ways. A common service you might want to add to your API or web services is an admin interface where you might want to list all your users to administrators. In this recipe, we will see how, using various parts of the ServiceStack framework, this can be achieved in a very readable and concise way.

Getting ready

First, we'll need a project with ServiceStack references to be up and running. To do this, please see Creating a ServiceStack solution with VisualStudio and NuGet in Appendix A, Getting Started.

We are also going to have some basic authentication, settings, and OrmLite set up to work in our application, as follows:

var dbFactory = new OrmLiteConnectionFactory(
                "~/App_Data/db.sqlite".MapHostAbsolutePath(), SqliteDialect.Provider);
container.Register<IDbConnectionFactory>(dbFactory);
var userRep = new OrmLiteAuthRepository(dbFactory);
container.Register<IUserAuthRepository>(userRep);

Plugins.Add(new PostmanFeature());
Plugins.Add(
    new AuthFeature(() =>
        new AuthUserSession(),
        new IAuthProvider[]
        {
            new CredentialsAuthProvider(),
        }));

userRep.DropAndReCreateTables();
CreateUsers(userRep);

Note

For more information on the AuthFeature plugin, see the Getting started with authentication, sessions, registration, and user repositories recipe in Chapter 7, Security and Authentication.

How to do it…

First, we need to create a request object to handle the request for registered users in our application, as follows:

[Route("/admin/users")]
public class RegisteredUsers
{

}

This request object doesn't need any properties as authentication, and the session will be able to identify who is making the request and if they are authenticated. For this example, we are just attributing an object to wire it up to the following service. The Authenticate and RoleRequired attributes are used with ServiceStack's authentication. Marking the class with these attributes means that only authenticated users with the role of Admin can access the service methods within. The Getting started with authentication, sessions, registration, and user repositories recipe in Chapter 7, Security and Authentication, shows an isolated look at how these can be used:

[Authenticate]
[RequiredRole("Admin")]
public class RegisteredUsersService : Service
{
    public object Get(RegisteredUsersRequest request)
    {
        var response = new
        {
            UserAuths = Db.Select<UserAuth>()
        };
        //nulled out for security
        response.UserAuths.ForEach(x => x.PasswordHash = null);
        response.UserAuths.ForEach(x => x.Salt = null);
        response.UserAuths.ForEach(x => x.DigestHa1Hash = null);

        return response;
    }
}

The response object being returned here is an anonymous type that contains a property called UserAuths, which is being populated from the UserAuth table. This UserAuth table was set up by the use of OrmLiteAuthRepository, which is an implementation of IUserAuthRepository.

The result of this request shows the currently registered users with our application:

How to do it…

How it works…

Since ServiceStack allows developers to return any POCO from these services and serializes it into the appropriate requested format, we are able to simply return the UserAuth objects and let ServiceStack take care of the rest. Anything returned from a service will be automatically serialized into the required format, including anonymous types.

Note

If the support of SOAP is required, objects need to be attributed correctly with System.Data attributes, DataContract for classes, and DataMember for properties. See the ServiceStack wiki at https://github.com/ServiceStack/ServiceStack/wiki for more information.

This service also has the Authenticate attribute and RequiresRole attribute to ensure that only authenticated users with the Admin role are able to access this service. If no credentials are provided, the service will return a 401 Unauthorized response, as follows:

How it works…

If we then log in with the guest user by posting credentials to /auth/credentials?format=json, we will have an authenticated session, a glimpse of which is shown in the following screenshot:

How it works…

However, if the guest user attempts to access this endpoint, they will receive a 403 Invalid Role error due to the required role Admin marked on the service, as shown in the following screenshot:

How it works…

See also

The Getting started with authentication, sessions, registration, and user repositories recipe in Chapter 7, Security and Authentication