note: in case of reconnect, clients will have to resubmit all subscriptions again
(e *core.RequestEvent)
| 182 | |
| 183 | // note: in case of reconnect, clients will have to resubmit all subscriptions again |
| 184 | func realtimeSetSubscriptions(e *core.RequestEvent) error { |
| 185 | form := new(realtimeSubscribeForm) |
| 186 | |
| 187 | err := e.BindBody(form) |
| 188 | if err != nil { |
| 189 | return e.BadRequestError("", err) |
| 190 | } |
| 191 | |
| 192 | err = form.validate() |
| 193 | if err != nil { |
| 194 | return e.BadRequestError("", err) |
| 195 | } |
| 196 | |
| 197 | // find subscription client |
| 198 | client, err := e.App.SubscriptionsBroker().ClientById(form.ClientId) |
| 199 | if err != nil { |
| 200 | return e.NotFoundError("Missing or invalid client id.", err) |
| 201 | } |
| 202 | |
| 203 | // for just in case to prevent someone changing a guest subscription |
| 204 | // |
| 205 | // note1: this is an extra precaution against clientId bruteforce attempts |
| 206 | // for installations allowing longer realtime connections duration |
| 207 | // |
| 208 | // note2: custom registered clients (aka. those without IP in the store) |
| 209 | // are excluded from the check for backward compatibility |
| 210 | clientIP, _ := client.Get(RealtimeClientIPKey).(string) |
| 211 | if clientIP != "" && clientIP != e.RealIP() { |
| 212 | return e.BadRequestError( |
| 213 | "Invalid realtime client.", |
| 214 | errors.New("the subscription request IP doesn't match with the realtime client IP"), |
| 215 | ) |
| 216 | } |
| 217 | |
| 218 | // for now allow only guest->auth upgrades and any other auth change is forbidden |
| 219 | clientAuth, _ := client.Get(RealtimeClientAuthKey).(*core.Record) |
| 220 | if clientAuth != nil && !isSameAuth(clientAuth, e.Auth) { |
| 221 | return e.ForbiddenError("The current and the previous request authorization don't match.", nil) |
| 222 | } |
| 223 | |
| 224 | event := new(core.RealtimeSubscribeRequestEvent) |
| 225 | event.RequestEvent = e |
| 226 | event.Client = client |
| 227 | event.Subscriptions = form.Subscriptions |
| 228 | |
| 229 | return e.App.OnRealtimeSubscribeRequest().Trigger(event, func(e *core.RealtimeSubscribeRequestEvent) error { |
| 230 | // update auth state |
| 231 | e.Client.Set(RealtimeClientAuthKey, e.Auth) |
| 232 | |
| 233 | // unsubscribe from any previous existing subscriptions |
| 234 | e.Client.Unsubscribe() |
| 235 | |
| 236 | // subscribe to the new subscriptions |
| 237 | e.Client.Subscribe(e.Subscriptions...) |
| 238 | |
| 239 | e.App.Logger().Debug( |
| 240 | "Realtime subscriptions updated", |
| 241 | slog.String("clientId", e.Client.Id()), |
nothing calls this directly
no test coverage detected
searching dependent graphs…