nolint:gocyclo
(ctx context.Context, req *api.QueryKeysRequest, res *api.QueryKeysResponse)
| 219 | |
| 220 | // nolint:gocyclo |
| 221 | func (a *KeyInternalAPI) QueryKeys(ctx context.Context, req *api.QueryKeysRequest, res *api.QueryKeysResponse) { |
| 222 | res.DeviceKeys = make(map[string]map[string]json.RawMessage) |
| 223 | res.MasterKeys = make(map[string]gomatrixserverlib.CrossSigningKey) |
| 224 | res.SelfSigningKeys = make(map[string]gomatrixserverlib.CrossSigningKey) |
| 225 | res.UserSigningKeys = make(map[string]gomatrixserverlib.CrossSigningKey) |
| 226 | res.Failures = make(map[string]interface{}) |
| 227 | |
| 228 | // get cross-signing keys from the database |
| 229 | a.crossSigningKeysFromDatabase(ctx, req, res) |
| 230 | |
| 231 | // make a map from domain to device keys |
| 232 | domainToDeviceKeys := make(map[string]map[string][]string) |
| 233 | domainToCrossSigningKeys := make(map[string]map[string]struct{}) |
| 234 | for userID, deviceIDs := range req.UserToDevices { |
| 235 | _, serverName, err := gomatrixserverlib.SplitID('@', userID) |
| 236 | if err != nil { |
| 237 | continue // ignore invalid users |
| 238 | } |
| 239 | domain := string(serverName) |
| 240 | // query local devices |
| 241 | if serverName == a.ThisServer { |
| 242 | deviceKeys, err := a.DB.DeviceKeysForUser(ctx, userID, deviceIDs, false) |
| 243 | if err != nil { |
| 244 | res.Error = &api.KeyError{ |
| 245 | Err: fmt.Sprintf("failed to query local device keys: %s", err), |
| 246 | } |
| 247 | return |
| 248 | } |
| 249 | |
| 250 | // pull out display names after we have the keys so we handle wildcards correctly |
| 251 | var dids []string |
| 252 | for _, dk := range deviceKeys { |
| 253 | dids = append(dids, dk.DeviceID) |
| 254 | } |
| 255 | var queryRes userapi.QueryDeviceInfosResponse |
| 256 | err = a.UserAPI.QueryDeviceInfos(ctx, &userapi.QueryDeviceInfosRequest{ |
| 257 | DeviceIDs: dids, |
| 258 | }, &queryRes) |
| 259 | if err != nil { |
| 260 | util.GetLogger(ctx).Warnf("Failed to QueryDeviceInfos for device IDs, display names will be missing") |
| 261 | } |
| 262 | |
| 263 | if res.DeviceKeys[userID] == nil { |
| 264 | res.DeviceKeys[userID] = make(map[string]json.RawMessage) |
| 265 | } |
| 266 | for _, dk := range deviceKeys { |
| 267 | if len(dk.KeyJSON) == 0 { |
| 268 | continue // don't include blank keys |
| 269 | } |
| 270 | // inject display name if known (either locally or remotely) |
| 271 | displayName := dk.DisplayName |
| 272 | if queryRes.DeviceInfo[dk.DeviceID].DisplayName != "" { |
| 273 | displayName = queryRes.DeviceInfo[dk.DeviceID].DisplayName |
| 274 | } |
| 275 | dk.KeyJSON, _ = sjson.SetBytes(dk.KeyJSON, "unsigned", struct { |
| 276 | DisplayName string `json:"device_display_name,omitempty"` |
| 277 | }{displayName}) |
| 278 | res.DeviceKeys[userID][dk.DeviceID] = dk.KeyJSON |
no test coverage detected