Add DisconnectNow API endpoint
This commit is contained in:
parent
c7ef254361
commit
96d61614f4
152
docs/API.md
152
docs/API.md
|
@ -27,16 +27,16 @@ Post your desired JWT claims to the endpoint to customize your user and it will
|
|||
|
||||
```json
|
||||
{
|
||||
"APIKey": "from settings.toml",
|
||||
"Claims": {
|
||||
"sub": "username",
|
||||
"nick": "Display Name",
|
||||
"op": false,
|
||||
"img": "/static/photos/avatar.png",
|
||||
"url": "/users/username",
|
||||
"emoji": "🤖",
|
||||
"gender": "m"
|
||||
}
|
||||
"APIKey": "from settings.toml",
|
||||
"Claims": {
|
||||
"sub": "username",
|
||||
"nick": "Display Name",
|
||||
"op": false,
|
||||
"img": "/static/photos/avatar.png",
|
||||
"url": "/users/username",
|
||||
"emoji": "🤖",
|
||||
"gender": "m"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
@ -44,9 +44,9 @@ The return schema looks like:
|
|||
|
||||
```json
|
||||
{
|
||||
"OK": true,
|
||||
"Error": "error string, omitted if none",
|
||||
"JWT": "jwt token string"
|
||||
"OK": true,
|
||||
"Error": "error string, omitted if none",
|
||||
"JWT": "jwt token string"
|
||||
}
|
||||
```
|
||||
|
||||
|
@ -58,7 +58,7 @@ It requires the AdminAPIKey to post:
|
|||
|
||||
```json
|
||||
{
|
||||
"APIKey": "from settings.toml"
|
||||
"APIKey": "from settings.toml"
|
||||
}
|
||||
```
|
||||
|
||||
|
@ -66,8 +66,8 @@ The return schema looks like:
|
|||
|
||||
```json
|
||||
{
|
||||
"OK": true,
|
||||
"Error": "error string, omitted if none"
|
||||
"OK": true,
|
||||
"Error": "error string, omitted if none"
|
||||
}
|
||||
```
|
||||
|
||||
|
@ -110,3 +110,123 @@ The JSON response to this endpoint may look like:
|
|||
"Error": "if error, or this key is omitted if OK"
|
||||
}
|
||||
```
|
||||
|
||||
## POST /api/block/now
|
||||
|
||||
Your website can tell BareRTC to put a block between users "now." For
|
||||
example, if a user on your main website adds a block on another user,
|
||||
and one or both of them are presently logged into the chat room, BareRTC
|
||||
can begin enforcing the block immediately so both users will disappear
|
||||
from each other's view and no longer get one another's messages.
|
||||
|
||||
The request body payload looks like:
|
||||
|
||||
```json
|
||||
{
|
||||
"APIKey": "from your settings.toml",
|
||||
"Usernames": [ "alice", "bob" ]
|
||||
}
|
||||
```
|
||||
|
||||
The pair of usernames should be the two who are blocking each other, in
|
||||
any order. This will put in a two-way block between those chatters.
|
||||
|
||||
If you provide more than two usernames, the block is put between every
|
||||
combination of usernames given.
|
||||
|
||||
The JSON response to this endpoint may look like:
|
||||
|
||||
```json
|
||||
{
|
||||
"OK": true,
|
||||
"Error": "if error, or this key is omitted if OK"
|
||||
}
|
||||
```
|
||||
|
||||
## POST /api/disconnect/now
|
||||
|
||||
Your website can tell BareRTC to remove a user from the chat room "now"
|
||||
in case that user is presently online in the chat.
|
||||
|
||||
The request body payload looks like:
|
||||
|
||||
```json
|
||||
{
|
||||
"APIKey": "from your settings.toml",
|
||||
"Usernames": [ "alice" ],
|
||||
"Message": "a custom ChatServer message to send them, optional",
|
||||
"Kick": false,
|
||||
}
|
||||
```
|
||||
|
||||
The `Message` parameter, if provided, will be sent to that user as a
|
||||
ChatServer error before they are removed from the room. You can use this
|
||||
to provide them context as to why they are being kicked. For example:
|
||||
"You have been logged out of chat because you deactivated your profile on
|
||||
the main website."
|
||||
|
||||
The `Kick` boolean is whether the removal should manifest to other users
|
||||
in chat as a "kick" (sending a presence message of "has been kicked from
|
||||
the room!"). By default (false), BareRTC will tell the user to disconnect
|
||||
and it will manifest as a regular "has left the room" event to other online
|
||||
chatters.
|
||||
|
||||
The JSON response to this endpoint may look like:
|
||||
|
||||
```json
|
||||
{
|
||||
"OK": true,
|
||||
"Removed": 1,
|
||||
"Error": "if error, or this key is omitted if OK"
|
||||
}
|
||||
```
|
||||
|
||||
The "Removed" field is the count of users actually removed from chat; a zero
|
||||
means the user was not presently online.
|
||||
|
||||
# Ajax Endpoints (User API)
|
||||
|
||||
## POST /api/profile
|
||||
|
||||
Fetch profile information from your main website about a user in the
|
||||
chat room.
|
||||
|
||||
Note: this API request is done by the BareRTC chat front-end page, as an
|
||||
ajax request for a current logged-in user. It backs the profile card pop-up
|
||||
widget in the chat room when a user clicks on another user's profile.
|
||||
|
||||
The request body payload looks like:
|
||||
|
||||
```json
|
||||
{
|
||||
"JWTToken": "the caller's chat jwt token",
|
||||
"Username": "soandso"
|
||||
}
|
||||
```
|
||||
|
||||
The JWT token is the current chat user's token. This API only works when
|
||||
your BareRTC config requires the use of JWT tokens for authorization.
|
||||
|
||||
BareRTC will translate the request into the
|
||||
["Profile Webhook"](Webhooks.md#Profile%20Webhook) to fetch the target
|
||||
user's profile from your website.
|
||||
|
||||
The response JSON given to the chat page from /api/profile looks like:
|
||||
|
||||
```json
|
||||
{
|
||||
"OK": true,
|
||||
"Error": "only on error messages",
|
||||
"ProfileFields": [
|
||||
{
|
||||
"Name": "Age",
|
||||
"Value": "30yo"
|
||||
},
|
||||
{
|
||||
"Name": "Gender",
|
||||
"Value": "Man"
|
||||
},
|
||||
...
|
||||
]
|
||||
}
|
||||
```
|
128
pkg/api.go
128
pkg/api.go
|
@ -468,6 +468,134 @@ func (s *Server) BlockNow() http.HandlerFunc {
|
|||
})
|
||||
}
|
||||
|
||||
// DisconnectNow (/api/disconnect/now) allows your website to remove a user from
|
||||
// the chat room if they are currently online.
|
||||
//
|
||||
// For example: a user on your website has deactivated their account, and so
|
||||
// should not be allowed to remain in the chat room.
|
||||
//
|
||||
// It is a POST request with a json body containing the following schema:
|
||||
//
|
||||
// {
|
||||
// "APIKey": "from settings.toml",
|
||||
// "Usernames": [ "alice", "bob" ],
|
||||
// "Message": "An optional ChatServer message to send them first.",
|
||||
// "Kick": false,
|
||||
// }
|
||||
//
|
||||
// The `Message` parameter, if provided, will be sent to that user as a
|
||||
// ChatServer error before they are removed from the room. You can use this
|
||||
// to provide them context as to why they are being kicked. For example:
|
||||
// "You have been logged out of chat because you deactivated your profile on
|
||||
// the main website."
|
||||
//
|
||||
// The `Kick` boolean is whether the removal should manifest to other users
|
||||
// in chat as a "kick" (sending a presence message of "has been kicked from
|
||||
// the room!"). By default (false), BareRTC will tell the user to disconnect
|
||||
// and it will manifest as a regular "has left the room" event to other online
|
||||
// chatters.
|
||||
func (s *Server) DisconnectNow() http.HandlerFunc {
|
||||
type request struct {
|
||||
APIKey string
|
||||
Usernames []string
|
||||
Message string
|
||||
Kick bool
|
||||
}
|
||||
|
||||
type result struct {
|
||||
OK bool
|
||||
Removed int
|
||||
Error string `json:",omitempty"`
|
||||
}
|
||||
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
// JSON writer for the response.
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
enc := json.NewEncoder(w)
|
||||
enc.SetIndent("", " ")
|
||||
|
||||
// Parse the request.
|
||||
if r.Method != http.MethodPost {
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
enc.Encode(result{
|
||||
Error: "Only POST methods allowed",
|
||||
})
|
||||
return
|
||||
} else if r.Header.Get("Content-Type") != "application/json" {
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
enc.Encode(result{
|
||||
Error: "Only application/json content-types allowed",
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
defer r.Body.Close()
|
||||
|
||||
// Parse the request payload.
|
||||
var (
|
||||
params request
|
||||
dec = json.NewDecoder(r.Body)
|
||||
)
|
||||
if err := dec.Decode(¶ms); err != nil {
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
enc.Encode(result{
|
||||
Error: err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
// Validate the API key.
|
||||
if params.APIKey != config.Current.AdminAPIKey {
|
||||
w.WriteHeader(http.StatusUnauthorized)
|
||||
enc.Encode(result{
|
||||
Error: "Authentication denied.",
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
// Check if any of these users are online, and disconnect them from the chat.
|
||||
var removed int
|
||||
for _, username := range params.Usernames {
|
||||
if sub, err := s.GetSubscriber(username); err == nil {
|
||||
// Broadcast to everybody that the user left the chat.
|
||||
message := messages.PresenceExited
|
||||
if params.Kick {
|
||||
message = messages.PresenceKicked
|
||||
}
|
||||
s.Broadcast(messages.Message{
|
||||
Action: messages.ActionPresence,
|
||||
Username: username,
|
||||
Message: message,
|
||||
})
|
||||
|
||||
// Custom message to send to them?
|
||||
if params.Message != "" {
|
||||
sub.ChatServer(params.Message)
|
||||
}
|
||||
|
||||
// Disconnect them.
|
||||
sub.SendJSON(messages.Message{
|
||||
Action: messages.ActionKick,
|
||||
})
|
||||
sub.authenticated = false
|
||||
sub.Username = ""
|
||||
|
||||
removed++
|
||||
}
|
||||
}
|
||||
|
||||
// If any changes to blocklists were made: send the Who List.
|
||||
if removed > 0 {
|
||||
s.SendWhoList()
|
||||
}
|
||||
|
||||
enc.Encode(result{
|
||||
OK: true,
|
||||
Removed: removed,
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
// UserProfile (/api/profile) fetches profile information about a user.
|
||||
//
|
||||
// This endpoint will proxy to your WebhookURL for the "profile" endpoint.
|
||||
|
|
|
@ -160,7 +160,7 @@ func (s *Server) KickCommand(words []string, sub *Subscriber) {
|
|||
s.Broadcast(messages.Message{
|
||||
Action: messages.ActionPresence,
|
||||
Username: username,
|
||||
Message: "has been kicked from the room!",
|
||||
Message: messages.PresenceKicked,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -237,7 +237,7 @@ func (s *Server) BanCommand(words []string, sub *Subscriber) {
|
|||
s.Broadcast(messages.Message{
|
||||
Action: messages.ActionPresence,
|
||||
Username: username,
|
||||
Message: "has been banned!",
|
||||
Message: messages.PresenceBanned,
|
||||
})
|
||||
|
||||
other.ChatServer("You have been banned from the chat room by %s. You may come back after %d hours.", sub.Username, duration/time.Hour)
|
||||
|
|
|
@ -97,7 +97,7 @@ func (s *Server) OnLogin(sub *Subscriber, msg messages.Message) {
|
|||
s.Broadcast(messages.Message{
|
||||
Action: messages.ActionPresence,
|
||||
Username: msg.Username,
|
||||
Message: "has joined the room!",
|
||||
Message: messages.PresenceJoined,
|
||||
})
|
||||
|
||||
// Send the user back their settings.
|
||||
|
@ -379,14 +379,14 @@ func (s *Server) OnMe(sub *Subscriber, msg messages.Message) {
|
|||
s.Broadcast(messages.Message{
|
||||
Action: messages.ActionPresence,
|
||||
Username: sub.Username,
|
||||
Message: "has exited the room!",
|
||||
Message: messages.PresenceExited,
|
||||
})
|
||||
} else if sub.ChatStatus == "hidden" && msg.ChatStatus != "hidden" {
|
||||
// Leaving hidden - fake join message
|
||||
s.Broadcast(messages.Message{
|
||||
Action: messages.ActionPresence,
|
||||
Username: sub.Username,
|
||||
Message: "has joined the room!",
|
||||
Message: messages.PresenceJoined,
|
||||
})
|
||||
}
|
||||
} else if msg.ChatStatus == "hidden" {
|
||||
|
|
|
@ -131,3 +131,12 @@ const (
|
|||
VideoFlagMutualOpen // viewer wants to auto-open viewers' cameras
|
||||
VideoFlagOnlyVIP // can only shows as active to VIP members
|
||||
)
|
||||
|
||||
// Presence message templates.
|
||||
const (
|
||||
PresenceJoined = "has joined the room!"
|
||||
PresenceExited = "has exited the room!"
|
||||
PresenceKicked = "has been kicked from the room!"
|
||||
PresenceBanned = "has been banned!"
|
||||
PresenceTimedOut = "has timed out!"
|
||||
)
|
||||
|
|
|
@ -65,7 +65,7 @@ func (s *Server) KickIdlePollUsers() {
|
|||
s.Broadcast(messages.Message{
|
||||
Action: messages.ActionPresence,
|
||||
Username: sub.Username,
|
||||
Message: "has timed out!",
|
||||
Message: messages.PresenceTimedOut,
|
||||
})
|
||||
s.SendWhoList()
|
||||
}
|
||||
|
|
|
@ -42,6 +42,7 @@ func (s *Server) Setup() error {
|
|||
mux.Handle("/api/statistics", s.Statistics())
|
||||
mux.Handle("/api/blocklist", s.BlockList())
|
||||
mux.Handle("/api/block/now", s.BlockNow())
|
||||
mux.Handle("/api/disconnect/now", s.DisconnectNow())
|
||||
mux.Handle("/api/authenticate", s.Authenticate())
|
||||
mux.Handle("/api/shutdown", s.ShutdownAPI())
|
||||
mux.Handle("/api/profile", s.UserProfile())
|
||||
|
|
|
@ -99,7 +99,7 @@ func (s *Server) NewPollingSubscriber(ctx context.Context, cancelFunc func()) *S
|
|||
s.Broadcast(messages.Message{
|
||||
Action: messages.ActionPresence,
|
||||
Username: sub.Username,
|
||||
Message: "has exited the room!",
|
||||
Message: messages.PresenceExited,
|
||||
})
|
||||
s.SendWhoList()
|
||||
}
|
||||
|
@ -167,7 +167,7 @@ func (sub *Subscriber) ReadLoop(s *Server) {
|
|||
s.Broadcast(messages.Message{
|
||||
Action: messages.ActionPresence,
|
||||
Username: sub.Username,
|
||||
Message: "has exited the room!",
|
||||
Message: messages.PresenceExited,
|
||||
})
|
||||
s.SendWhoList()
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user