Caffeine-Powered Life

The Easiest WebAPI Authorization Tutorial Ever

So, it took a lot of scouring of the internets, but I was finally able to piece together the bare minimum necessary to create your own authoritization client in WebAPI.

Step 1: Create a DelegatingHandler

The DelegatingHandler is a class that will be attached to all requests coming into your API. This is going to be the easiest authorization handler ever. Here are the rules.

  1. If there is a token, any token at all, the request is valid.
  2. Otherwise, the request is unauthorized.

Yes, this is simple. In reality, you’d want to check the value of the token against something, at the very least a local database. That is left as an exercise for the reader.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
public class AuthorizationHeaderHandler : DelegatingHandler
{
  private string authorizationParameter;

  public bool HasAuthorizationParameter
  {
    get { return authorizationParameter != null; }
  }

  protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
  {
    ParseAuthorizationHeader(request);
    if (HasAuthorizationParameter)
    {
      ConfigureClaimsIdentity();
      return base.SendAsync(request, cancellationToken);
    }

    return ConfigureUnauthorizedRequest();
  }

  private void ConfigureClaimsIdentity()
  {
    var claims = new List<Claim>();
    // Ideally, you'd add some claims here.
    var claimsIdentity = new ClaimsIdentity(claims);
    Thread.CurrentPrincipal = new ClaimsPrincipal(claimsIdentity);
  }

  private Task<HttpResponseMessage> ConfigureUnauthorizedRequest()
  {
    var response = new HttpResponseMessage(HttpStatusCode.Unauthorized);
    var taskCompletionSource = new TaskCompletionSource<HttpResponseMessage>();
    taskCompletionSource.SetResult(response);
    return taskCompletionSource.Task;
  }

  private void ParseAuthorizationHeader(HttpRequestMessage request)
  {
    if (request.Headers == null || request.Headers.Authorization == null || request.Headers.Authorization.Parameter == null)
      return;

    authorizationParameter = request.Headers.Authorization.Parameter;
  }
}

Step 2: Wire Your Handler to Your Configuration

Somewhere, you probably have a class that sets up your WebAPI configuration. You need to add this line to your configuration.

1
2
3
4
private static void ConfigureMessageHandlers(HttpConfiguration config)
{
  config.MessageHandlers.Add(new AuthorizationHeaderHandler());
}

Step 3: Add an Authorization Header to Your Requests

For this to work, you’ll need to add an authorization header to all of your requests. It needs to be in the following format.

1
Authorization: <scheme> <parameter>

Here’s a sample. (No don’t actually use this token. It’s just the SHA256 hash of Hello, World!.)

1
Authorization: Token DFFD6021BB2BD5B0AF676290809EC3A53191DD81C7F70A4B28688A362182986F

Step 4: Test With and Without an Authorization Header

Fire up Fiddler. Let’s create a request without an authorization header.

The request.

The reponse. We can see the 401 Unauthorized coming back from the server.

Now, let’s look at the same request with an authorization header.

The response. Now with more 200 OK.

We’re successfully grabbing the token from the request. Everything else is left as an exercise for the reader!

Unit Testing an MVC Authorize Attribute

When working with unit tests, I usually consider it a code smell when you have more fixture setup than production code. Today, I ran into just that condition.

This class has been written for a while, but it wasn’t covered by any tests. I decided to change that. First, I’ll show you the class. The class under question is called SessionBasedAuthorizeAttribute. It looks to the ASP.NET session to get the username, instead of relying on a forms token.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
public class SessionBasedAuthorizeAttibute : AuthorizeAttribute
{
  protected override bool AuthorizeCore(HttpContextBase httpContext)
  {
    // If the session object has not yet been created, then there is nothing
    // we can do with this authorization.
    if (httpContext.Session == null)
      return false;

    IHttpSessionAdapter httpSessionAdapter = HttpSessionAdapter.Deserialize(httpContext.Session);
    if (httpSessionAdapter.IsAuthenticated)
    {
      SetHttpContextUser(httpContext, httpSessionAdapter);
      return true;
    }
    else
    {
      return false;
    }
  }

  private static void SetHttpContextUser(HttpContextBase httpContext, IHttpSessionAdapter httpSession)
  {
    var mediator = Mediator.Instance;
    var query = new UserByUsernameQuery(httpSession.Username);
    var user = mediator.Request(query);
    httpContext.User = user ?? new Guest();
  }
}

Writing your own AuthorizeAttibute isn’t difficult. It’s just a few lines, really, to pull a value from session, fetch a user from the database, and set the user. But what about unit testing?

Here’s the result.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
[TestFixture]
public class SessionBasedAuthorizeAttribute_Tests
{
  private AuthorizeAttribute attribute;
  private AuthorizationContext authorizationContext;

  [SetUp]
  public void Before_each_test()
  {
    attribute = new SessionBasedAuthorizeAttibute();

    var controller = new FakeController();
    MvcTest.SetupControllerContext(controller);

    authorizationContext = new AuthorizationContext();
    authorizationContext.Controller = controller;
    authorizationContext.HttpContext = controller.HttpContext;

    var controllerDescriptor = new ReflectedControllerDescriptor(typeof(FakeController));
    var method = typeof(FakeController).GetMethod("Nothing");
    authorizationContext.ActionDescriptor = new ReflectedActionDescriptor(method, "Nothing", controllerDescriptor);
  }

  [Test]
  public void Fails_when_session_is_not_authenticated()
  {
    SetupSession(false);
    Authorize();
    AssertUnauthorized();
  }

  [Test]
  public void Fails_when_session_is_null()
  {
    Mock.Get(authorizationContext.HttpContext).SetupGet(x => x.Session).Returns((HttpSessionStateBase)null);
    Authorize();
    AssertUnauthorized();
  }

  [Test]
  public void Succeeds_when_session_is_authenticated()
  {
    SetupSession(true);
    SetupServices();
    Authorize();
    AssertSuccess();
  }

  private void AssertSuccess()
  {
    var user = authorizationContext.HttpContext.User;
    user.Should().BeOfType<User>();
    user.Identity.IsAuthenticated.Should().BeTrue();
    user.Identity.Name.Should().Be("tester");
  }

  private void AssertUnauthorized()
  {
    authorizationContext.Result.Should().BeOfType<HttpUnauthorizedResult>();
  }

  private void Authorize()
  {
    attribute.OnAuthorization(authorizationContext);
  }

  private void SetupServices()
  {
    var mediator = new Mock<IMediator>();
    mediator.Setup(x => x.Request(It.IsAny<UserByUsernameQuery>())).Returns(new User { Username = "tester" });
    Mediator.Instance = mediator.Object;
  }

  private void SetupSession(bool isAuthorized = true)
  {
    var mockContext = Mock.Get(authorizationContext.HttpContext);
    var mockSession = new Mock<HttpSessionStateBase>();
    mockSession.SetupGet(x => x["IsAuthenticated"]).Returns(isAuthorized);

    // Return the mock.
    mockContext.SetupGet(x => x.Session).Returns(mockSession.Object);
  }

  internal class FakeController : Controller
  {
    public ActionResult Nothing()
    {
      return new EmptyResult();
    }
  }
}

By the way, there’s even more setup code that happens as a part of the MvcTest.SetupControllerContext() method call, but I had already written that for another purpose.

13 lines of production code. 25 lines of fixture setup.

It turns out, that’s much more difficult, because we are relying on a lot of the inner guts of MVC. I had to pull up the source code for the OnAuthorize method to see what all the NullReferenceExceptions were. When mocking out the HttpContext, you also have to mock out the Session (knew that) and Items (didn’t know that) properties. There are also some ActionDescriptor values that must be set for OnAuthorize to work, and I have never worked with those classes before, either.

I suppose the first conclusion is to praise the powers at Microsoft for open sourcing the MVC framework. Without access to the source, I would have never been able to write these tests. Even with the source, the terrible nature of the NullReferenceException made this much more difficult than it ought to be. Any time you have a chain of w.x.y.z, finding which of those threw the exception becomes a total PITA. Yeah, I know. The Law of Demeter is in play, too.

Check out Code Contracts. It makes this kind of in-code documentation much easier.

The second conclusion is the value of this kind of test. I’ve already had one coworker respond with, “this is where I begin to question the value add of unit testing.” I kinda have to agree with him. This was a hard test to write, even though the production code itself was quite easy. On one extreme, some people say that if it is important enough to write, then it is important enough to test. I think I agree with that sentiment. I believe in the value of testing. I’m just not sure what I could have done to make this testing easier and still remain within the bounds set by the MVC framework.

BCrypt Is Slow

For some reason, this just made my day.

See those yellow dots? That’s NCrunch telling me that these tests are slow. It’s BCrypt. It’s supposed to be slow! That’s the whole point of using BCrypt. If you’re storing passwords, it’s the only hashing algorithm you should be using.

JavaScript Objects

This is always a good topic to review. There are just too many developers who don’t know what they are doing when it comes to writing good JavaScript. The code for this project has been published to Github.

Understanding Scope

The first thing we must understand is how variables are scoped in JavaScript. When it comes to JS: there’s only one rule.

Variables are scoped to the function that defines them.

There’s no concept of block scope like in C# or Java. This means that we’re going to make use of something called a functional closure.

The Specs

Specs are a wonderful way of defining how a class should work. Don’t tell me this is BDUF or not how TDD is supposed to work. Both of these methodologies would say to only write one test, then write the code. Repeat until you are finished. This is why I refuse to strictly follow a dogma. If you know the specs up front, then write the specs.

The following tests are written with the Jasmine unit testing framework.

1
2
3
4
5
6
7
8
9
10
11
describe("Speaker", function () {

  it("can be instantiated");                     // 1.
  it("has a name attribute");                    // 2.
  it("can change the name in the constructor");  // 3.
  it("returns the expected message");            // 4.
  it("adds the message to an output buffer");    // 5.
  it("counts the number of times spoken");       // 6.
  it("counts the number of things said");        // 7.

});

Declaring the Constructor

1
2
3
4
5
6
7
8
var Speaker = (function () {

  function Speaker() {
  }

  return Speaker;

})();

Yes, we had to type the name of the class three times and the word function twice. I’m sorry.

The Functional Closure

The above code example is a functional closure. The more you work with good JavaScript, the more you’ll see this pattern. Yes, it’s a lot of character noise. I’m sorry Ruby developers.

1
(function(){})();

The above line creates an anonymous function that is executed immediately. In this example, we are creating a new Speaker function and then returning that function. The functional closure will let us hide variables that we don’t want exposed outside of class.

This will let us create new instances of our Speaker class.

1
var speaker = new Speaker(); // Passes #1.

Objects Are Instances of Functions

What syntax makes function Speaker() any different from function speaker()? Nothing at all. The only reason that we are capitalizing Speaker is by convention of those who have come before us.

1
2
3
console.log(typeof Speaker);   // returns "function"
var speaker = new Speaker();
console.log(typeof speaker);   // returns "object"

Adding Properties

We also think our speaker should have a name. I like to know to whom I am speaking.

1
2
3
4
5
6
7
8
9
var Speaker = (function () {

  function Speaker() {
    this.name = "Ann";
  }

  return Speaker;

})();

We can now test that the speaker really does have a name attribute now.

1
2
3
4
it("has a name attribute", function () {
  var speaker = new Speaker();
  expect(speaker.name).toBe("Ann"); // Passes #2.
});

Constructor Options

We should get used to using an options object in our JavaScript. Instead of having an explicit list of arguments, we instead accept a single options object as a method parameter. Remembering that JavaScript does not have a compiler, this allows us to be very clear about the expected inputs to our methods.

Having an options parameter also lets us set some defaults. Both jQuery and Underscore have an extend method that let us map settings. They both do the exact same thing. For no particular reason, I’m choosing Underscore over jQuery.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
var Speaker = (function () {

  var defaults = {
    name: "Ann"
  };

  function Speaker(options) {
    this.options = _.extend({}, defaults, options);
    this.name = this.options.name; // Passes #3.
  }

  return Speaker;

})();

So, by default, our speaker will be named “Ann,” but we can still change it by adding a name attribute to our options argument.

1
var speaker = new Speaker({ name: "Bonnie" });

Also, notice that the defaults are private to the functional closure. There is no way to access these defaults from outside the Speaker object. While we can access speaker.options.name, we cannot, in any way, access speaker.defaults.

Adding a Functional Prototype

To expose a public function, we need to use the prototype attribute.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
var Speaker = (function () {

  var defaults = {
    name: "Ann"
  };

  function Speaker(options) {
    this.options = _.extend({}, defaults, options);
    this.name = this.options.name;
  }

  Speaker.prototype.say = function(toSay) {
    var message = '"' + toSay + '," said ' + this.name + '.';
    return message; // Passes #4.
  };

  return Speaker;

})();

Duck Typing

I’m not going to get into duck typing today. A lot has already been said by developers much smarter than I. Check out Eric Lippert’s post and Phil Haack’s first and second posts. Instead, here’s the short, short version…

I’m going to call something – a method or property – and you had better just “work.”

That’s all we are going to do with the output buffer in this case. I’m going to call a .write() method. I don’t care what you give me, but I’m going to call that method.

We’re going to go back to our constructor here.

  • AlertBuffer: Writes to window.alert.
  • ConsoleBuffer: Writes to console.log.
  • MemoryBuffer: Writes to an internal array.

I wrote all three versions. They are available in the repository linked above. Here’s the code for the MemoryBuffer.

1
2
3
4
5
6
7
8
var MemoryBuffer = (function () {
  function MemoryBuffer() {
    this.messages = [];
  }
  MemoryBuffer.prototype.write = function(message) {
    this.messages.push(message);
  };
})();

We’ll set our buffer in the constructor of Speaker. We’ll go ahead and default to the MemoryBuffer. If you want the MemoryBuffer, then leave it alone. If not, then give us a new buffer when you create your Speaker instance.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
var Speaker = (function () {

  var defaults = {
    buffer: new MemoryBuffer(),
    name: "Ann"
  };

  function Speaker(options) {
    this.options = _.extend({}, defaults, options);
    this.name = this.options.name;
  }

  Speaker.prototype.say = function(toSay) {
    var message = '"' + toSay + '," said ' + this.name + '.';
    this.options.buffer.write(message); // Passes #5.
    return message;
  };

  return Speaker;

})();

Creating a Private Function

Now we want to create a private function. This function needs to be exposed to the Speaker instance, but not outside of the instance. We can’t use a prototype for this, so how do we accomplish this? Answer: we just create a method inside of the function. This will scope it locally, preventing it from being exposed.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
var Speaker = (function () {

  var defaults = {
    buffer: new MemoryBuffer(),
    name: "Ann"
  };

  function Speaker(options) {
    this.options = _.extend({}, defaults, options);
    this.name = this.options.name;
    this.thingsSaid = [];
    this.timesSpoken = 0;
  }

  Speaker.prototype.say = function(toSay) {
    var message = '"' + toSay + '," said ' + this.name + '.';
    this.options.buffer.write(message);
    addToThingsSaid(this, toSay);
    this.timesSpoken += 1; // Passes #7.
    return message;
  };

  function addToThingsSaid(speaker, toSay) {
    if (!_.contains(speaker.thingsSaid, toSay)) {
      speaker.thingsSaid.push(toSay); // Passes #6.
    }
  }

  return Speaker;

})();

With that, we will now pass all of our specs.

Relying on Unreliable IDs

Relying on IDs means that we are checking that a value set by the database. This may be an autoincrementing value — a SQL Server identity or an Oracle sequence.

Why This Happens?

This anti-pattern occurs because it is thought to be easier to hard code values into the software than to make changes to the database schema. When the schema is wrong, fix it!

Example: Include/Exclude by Value

In this case, this particular department is a virtual department, not a real department, and we don’t want it displayed in this particular UI screen.

1
var departments = departmentRepository.Where(d => d.ID != 6).ToList();

However, in this program, the ID column is a SQL Server identity. The value of 6 was assigned to the row in the developer’s environment. However, there are three more environments to consider: QA, Staging, and Production.

There are two anti-patterns to this approach.

  1. It assumes that data will be entered in the exact same order. It also assumes that if there was a mistake before, the mistake would be repeated, since a failed insert will increment the identity.
  2. It assumes there will never be another department that we wish to exclude.

Solution: alter the schema to reflect the intent

The solution is to alter the database to reflect this logic.

1
2
ALTER TABLE [departments] ADD [exclude_from_user_management_ui] BIT NOT NULL DEFAULT (0);
UPDATE [departments] SET [exclude_from_user_management_ui] = 1 WHERE [id] = 6;

The application code is now extremely easy to understand, and there is no reliance on “magic” values.

1
var departments = departmentRepository.Where(d => d.ExcludeFromUserManagementUI == false).ToList();

Example: Setting a Default Value

In this example, we are using a value to reflect that something should have a default setting.

1
2
3
4
var task = new Task();
task.Description = "Be more awesome!";
task.Status = statuses.First(s => s.ID == "new");
task.CreatedAt = DateTime.UtcNow;

Again, this assumes that the “new” status will always be present. If you, ask the developer have complete control over the environments and deployments, then this does work. Also, you’re luckier than I, since I have never been at a client where I have complete control over deployments.

Solution: alter the schema to reflect the intent

1
2
ALTER TABLE [statuses] ADD [is_default] BIT NOT NULL DEFAULT (0);
UPDATE TABLE [statuses] SET [is_default] = 1 WHERE [id] = 'new';

The application code is similarly trivial.

1
2
3
4
var task = new Task();
task.Description = "Be more awesome!";
task.Status = statuses.First(s => s.IsDefault);
task.CreatedAt = DateTime.UtcNow;

Now, whether the query for .IsDefault should be a call to .First() or .Single() is an argument I don’t really want to get into. Ideally, it is probably correct that only one value can ever be the default value. However, I’ve been places where I don’t have any control over those particular administration screens, and the code quality is rather dubious. In that case, I chose the .First() method because I didn’t want my code to break because of another developer’s poor decisions.

Yes, I realize my code will still break if there are no default statuses. The [status_id] column in the database is not nullable, so .FirstOrDefault() is just prolonging the issue.

Lesson Learned: Don’t rely on magic.

See Also

DRYing Up Controller Actions With Responders

I read a few books over the long weekend. One of those books was Crafting Rails 4 Applications by José Valim. I’m going to say that this is a pretty advanced book on Rails, since it really digs into the Rails framework internals, especially when it comes to overriding the default functionality.

One of the topics is how to DRY up your controllers by writing custom responders. That got me thinking. Can we do the same thing in .NET?

The “Before”

I have two controllers in my Portfolio application: a TagsController and a TasksController. These controllers contain the following lines.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// In TasksController
[HttpDelete]
public ActionResult Delete(DeleteTaskCommand command)
{
  var task = mediator.Send(command);
  var message = string.Format("Successfully deleted task: {0}", task.Title);
  this.Flash("success", message);
  return Json(new { success = true });
}

// In TagsController
[HttpDelete]
public ActionResult Delete(DeleteTagCommand command)
{
  var tag = mediator.Send(command);
  var message = string.Format("Successfully deleted tag: {0}", tag.Description));
  this.Flash("success", message);
  return Json(new { success = true });
}

That is some pretty similar code. In fact, that’s about as un-DRY as you can get. One might say that’s going to happen if you try to create some sort of standard in what your controllers and actions should look like.

Delete Is Easy

Notice that [HttpDelete] attribute on our Delete() methods? That means that the only way these methods are ever going to be called is via XHR. Currently, no browsers can create a DELETE request without the support of JavaScript. That means that our controller pattern has no reason to be complicated.

The DeleteResponder

It’s pretty obvious what we’re trying to achieve here, so let’s start by creating a branch and stubbing out some tests.

> git checkout -b responder-spike

Writing out your tests first is a good way to define a spec, so let’s do that. We can already tell what happens in our controller action, and we want our responder to mimic this behavior.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
public class DeleteResponderTests
{
  private DeleteResponder deleteResponder;

  [SetUp]
  public void Before_each_test()
  {

  }

  [Test]
  public void It_should_send_a_request_to_the_mediator()
  {
    Assert.Fail();
  }

  [Test]
  public void It_should_add_a_successful_flash_message()
  {
    Assert.Fail();
  }

  [Test]
  public void It_should_have_an_expected_JSON_result()
  {
    Assert.Fail();
  }
}

What is our responder going to look like? I have a good idea what I think it should look like up front.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class DeleteResponder
{
  private readonly ApplicationController controller;

  public DeleteResponder(ApplicationController controller)
  {
    if (controller == null) throw new ArgumentNullException("controller");
    this.controller = controller;
  }

  public ActionResult RespondWith<T>(IMediator mediator, ICommand<T> command)
  {
    throw new NotImplementedException();
  }
}

The easiest part is to send the command to the mediator. We can write that test fairly easily. We’re also going to need a fake controller.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
public class DeleteResponderTests
{
  private ICommand<object> command;
  private DeleteResponder deleteResponder;
  private Mock<IMediator> mockMediator;

  [SetUp]
  public void Before_each_test()
  {
    mockMediator = new Mock<IMediator> { DefaultValue = DefaultValue.Mock };
    deleteResponder = new DeleteResponder(new FakeController());
    command = new FakeCommand();
  }

  [Test]
  public void It_should_send_a_command_to_the_mediator()
  {
    deleteResponder.RespondWith(mockMediator.Object, command);
    mockMediator.Verify(x => x.Send(command));
  }

  class FakeCommand : ICommand<object> { }

  class FakeController : Controller { }
}

This command implementation is extremely simple.

1
2
3
4
5
public ActionResult RespondWith<T>(IMediator mediator, ICommand<T> command)
{
  mediator.Send(command);
  return null;
}

Next, we want to make sure that the JSON result is returned appropriately.

1
2
3
4
5
6
7
8
[Test]
public void It_should_have_an_expected_JSON_result()
{
  var result = deleteResponder.RespondWith(mockMediator.Object, command);
  var jsonResult = MvcTest.HasExpectedActionResult<JsonResult>(result);
  var objectDictionary = jsonResult.Data.ToDictionary();
  Assert.IsTrue(objectDictionary["success"]);
}

This implementation is also fairly simple.

1
2
3
4
5
6
7
8
9
10
public ActionResult RespondWith<T>(IMediator mediator, ICommand<T> command)
{
  mediator.Send(command);
  var jsonResult = new JsonResult();
  jsonResult.Data = new
  {
    success = true
  };
  return jsonResult;
}

The only remaining piece is how we add the flash message. I’m actually going to leave this piece alone. If you want to see how I did it, then check out my version of the DeleteResponder.

The “After”

Our TagsController and TasksController now look like the following:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// TagsController
[HttpDelete]
public ActionResult Delete(DeleteTagCommand command)
{
  return new DeleteResponder(this)
      .RespondWith(mediator, command);
}

// TasksController
[HttpDelete]
public ActionResult Delete(DeleteTaskCommand command)
{
  return new DeleteResponder(this)
      .RespondWith(mediator, command);
}

Eight total lines of code become two total lines of code, and the common functionality is moved to a utility class.

Also, just because the delete is easy, that doesn’t mean that everything has to be difficult. Your controllers should be rather thin. They invoke a service. They do a query. They return an ActionResult. This responder pattern can be applied to any form post.