evantahler/actionHero — pull request #272 by evantahler (2013-12-03 06:45:21+00:00)
Title: new chat authentication patern

This PR solves https://github.com/evantahler/actionHero/issues/266

By popular request, we are changing the chat sub-system to provide more fine-grain control over access to chat rooms to API developers.

## Philosophical Changes

- chat rooms now must be created before anyone can join them
- `api.chatRoom.add` can be used for this, or you can append the array `api.configData.general.startingChatRooms`
- you can remove chatRooms with `api.chatRoom.del`
- the authentication pattern for chat rooms is now about access rather than per message. All members in all rooms will see all messages
- access is still defined by looking at attributes of a connection, but only when the connection first joins a room. This means that if a connection's attributes change, it will not be kicked out of the room
- `api.chatRoom.setAuthenticationPatern` is used to define a room's access rules. 2 examples:
- `api.chatRoom.setAuthenticationPatern('myRoom', 'type', 'websocket')` would only allow websocket clients in
- `api.chatRoom.setAuthenticationPatern('myRoom', 'auteneticated', true)` would only allow clients in which have previously been modified by `connection.auteneticated = true; connection._original_connection.authenticated = true;` probably in an action or middleware.

- connections start without being in any chat room at all and need to explicitly join a room
- connections can leave the room they are in with the new verb `roomLeave` (socket and websocket)
- connections may still `listenToRoom` and `silenceRoom` as they had before, but listening to a room will follow the same authentication logic as joining a room (listen can now return an error)

## API Changes

### `api.chatRoom.add(room, callback)`
- callback will return 1 if you created the room, 0 if it already existed

### `api.chatRoom.del(room, callback)`
- callback is empty

### `api.chatRoom.exists(room, callback)`
- callback returns (error, found); found is a boolean

### `api.chatRoom.setAuthenticationPatern(room, key, value, callback)`
- callback returns (error)

### `api.chatRoom.roomStatus(room, callback)`
- callback return (error, data)
- data is of the form:

```javascript
{
room: "myRoom",
membersCount: 2,
members: {
aaa: {id: "aaa", joinedAt: 123456789 },
bbb: {id: "bbb", joinedAt: 123456789 },
}
}
```

### `api.chatRoom.addMember(connection, room, callback)`
- callback is of the form (error, wasAdded)

### `api.chatRoom.removeMember(connection, callback)`
- callback is of the form (error, wasRemoved)