8000 Remove current user device automatically when logout (#3640) · GetStream/stream-chat-swift@a3dcfdd · GitHub
[go: up one dir, main page]

Skip to content

Commit a3dcfdd

Browse files
authored
Remove current user device automatically when logout (#3640)
1 parent 6774811 commit a3dcfdd

File tree

4 files changed

+110
-19
lines changed

4 files changed

+110
-19
lines changed

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
99
- Add `ChatChannel.canSendPoll` capability [#3635](https://github.com/GetStream/stream-chat-swift/pull/3635)
1010
- Add `ChatChannel.canCastPollVote` capability [#3635](https://github.com/GetStream/stream-chat-swift/pull/3635)
1111
- Add teams role support for users [#3639](https://github.com/GetStream/stream-chat-swift/pull/3639)
12+
- Add `removeDevice: Bool` parameter to `ChatClient.logout()` [#3640](https://github.com/GetStream/stream-chat-swift/pull/3640)
13+
### 🔄 Changed
14+
- The `ChatClient.logout()` function now automatically removes the user's current device if it has not been removed already [#3640](https://github.com/GetStream/stream-chat-swift/pull/3640)
1215

1316
## StreamChatUI
1417
### 🐞 Fixed

DemoApp/Shared/StreamChatWrapper.swift

Lines changed: 1 addition & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -142,20 +142,7 @@ extension StreamChatWrapper {
142142
return
143143
}
144144

145-
let currentUserController = client.currentUserController()
146-
currentUserController.synchronize()
147-
if let deviceId = currentUserController.currentUser?.currentDevice?.id {
148-
currentUserController.removeDevice(id: deviceId) { error in
149-
if let error = error {
150-
log.error("Removing the device failed with an error \(error)")
151-
}
152-
153-
client.logout(completion: completion)
154-
}
155-
} else {
156-
log.error("No deviceId has been found from the current user.")
157-
client.logout(completion: completion)
158-
}
145+
client.logout(completion: completion)
159146
}
160147
}
161148

Sources/StreamChat/ChatClient.swift

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -483,15 +483,33 @@ public class ChatClient {
483483
}
484484
}
485485

486-
/// Disconnects the chat client form the chat servers and removes all the local data related.
486+
/// Disconnects the chat client from the chat servers and removes all the local data related.
487487
@available(*, deprecated, message: "Use the asynchronous version of `logout` for increased safety")
488488
public func logout() {
489489
logout {}
490490
}
491491

492492
/// Disconnects the chat client from the chat servers and removes all the local data related.
493-
public func logout(completion: @escaping () -> Void) {
494-
authenticationRepository.logOutUser()
493+
/// - Parameters:
494+
/// - removeDevice: If `true`, it removes the current device from the user's registered devices automatically.
495+
/// By default it is enabled.
496+
public func logout(
497+
removeDevice: Bool = true,
498+
completion: @escaping () -> Void
499+
) {
500+
let currentUserController = currentUserController()
501+
if removeDevice, let currentUserDevice = currentUserController.currentUser?.currentDevice {
502+
currentUserController.removeDevice(id: currentUserDevice.id) { [weak self] error in
503+
if let error {
504+
log.error(error)
505+
}
506+
self?.authenticationRepository.logOutUser()
507+
}
508+
}
509+
510+
if !removeDevice {
511+
authenticationRepository.logOutUser()
512+
}
495513

496514
// Stop tracking active components
497515
syncRepository.removeAllTracked()
@@ -646,7 +664,7 @@ public class ChatClient {
646664

647665
extension ChatClient: AuthenticationRepositoryDelegate {
648666
func logOutUser(completion: @escaping () -> Void) {
649-
logout(completion: completion)
667+
logout(removeDevice: false, completion: completion)
650668
}
651669

652670
func didFinishSettingUpAuthenticationEnvironment(for state: EnvironmentState) {

Tests/StreamChatTests/ChatClient_Tests.swift

Lines changed: 84 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -309,6 +309,89 @@ final class ChatClient_Tests: XCTestCase {
309309
XCTAssertTrue(testEnv.databaseContainer!.removeAllData_called)
310310
}
311311

312+
func test_logout_whenCurrentDevice_removesDevice() throws {
313+
// GIVEN
314+
let client = ChatClient(
315+
config: inMemoryStorageConfig,
316+
environment: testEnv.environment
317+
)
318+
let connectionRepository = try XCTUnwrap(client.connectionRepository as? ConnectionRepository_Mock)
319+
connectionRepository.disconnectResult = .success(())
320+
321+
// WHEN
322+
let userId = UserId.unique
323+
testEnv.authenticationRepository?.mockedCurrentUserId = userId
324+
try testEnv.databaseContainer?.writeSynchronously {
325+
try $0.saveCurrentUser(payload: .dummy(userId: userId, role: .admin))
326+
try $0.saveCurrentDevice(.unique)
327+
}
328+
let expectation = self.expectation(description: "logout completes")
329+
client.logout {
330+
expectation.fulfill()
331+
}
332+
waitForExpectations(timeout: defaultTimeout)
333+
334+
// THEN
335+
XCTAssertCall(ConnectionRepository_Mock.Signature.disconnect, on: testEnv.connectionRepository!)
336+
XCTAssertEqual(testEnv.apiClient?.request_endpoint?.path, .devices)
337+
XCTAssertEqual(testEnv.apiClient?.request_endpoint?.method, .delete)
338+
}
339+
340+
func test_logout_whenNoCurrentDevice_doesNotRemoveDevice() throws {
341+
// GIVEN
342+
let client = ChatClient(
343+
config: inMemoryStorageConfig,
344+
environment: testEnv.environment
345+
)
346+
let connectionRepository = try XCTUnwrap(client.connectionRepository as? ConnectionRepository_Mock)
347+
connectionRepository.disconnectResult = .success(())
348+
349+
// WHEN
350+
let userId = UserId.unique
351+
testEnv.authenticationRepository?.mockedCurrentUserId = userId
352+
try testEnv.databaseContainer?.writeSynchronously {
353+
try $0.saveCurrentUser(payload: .dummy(userId: userId, role: .admin))
354+
}
355+
let expectation = self.expectation(description: "logout completes")
356+
client.logout {
357+
expectation.fulfill()
358+
}
359+
waitForExpectations(timeout: defaultTimeout)
360+
361+
// THEN
362+
XCTAssertCall(ConnectionRepository_Mock.Signature.disconnect, on: testEnv.connectionRepository!)
363+
XCTAssertNil(testEnv.apiClient?.request_endpoint?.path)
364+
XCTAssertNil(testEnv.apiClient?.request_endpoint?.method)
365+
}
366+
367+
func test_logout_whenRemoveDeviceIsFalse_doesNotRemoveDevice() throws {
368+
// GIVEN
369+
let client = ChatClient(
370+
config: inMemoryStorageConfig,
371+
environment: testEnv.environment
372+
)
373+
let connectionRepository = try XCTUnwrap(client.connectionRepository as? ConnectionRepository_Mock)
374+
connectionRepository.disconnectResult = .success(())
375+
376+
// WHEN
377+
let userId = UserId.unique
378+
testEnv.authenticationRepository?.mockedCurrentUserId = userId
379+
try testEnv.databaseContainer?.writeSynchronously {
380+
try $0.saveCurrentUser(payload: .dummy(userId: userId, role: .admin))
381+
try $0.saveCurrentDevice(.unique)
382+
}
383+
let expectation = self.expectation(description: "logout completes")
384+
client.logout(removeDevice: false) {
385+
expectation.fulfill()
386+
}
387+
waitForExpectations(timeout: defaultTimeout)
388+
389+
// THEN
390+
XCTAssertCall(ConnectionRepository_Mock.Signature.disconnect, on: testEnv.connectionRepository!)
391+
XCTAssertNil(testEnv.apiClient?.request_endpoint?.path)
392+
XCTAssertNil(testEnv.apiClient?.request_endpoint?.method)
393+
}
394+
312395
func test_logout_clearsActiveControllers() throws {
313396
// GIVEN
314397
let client = ChatClient(
@@ -709,7 +792,7 @@ final class ChatClient_Tests: XCTestCase {
709792
connectionRepository.disconnectResult = .success(())
710793

711794
let expectation = self.expectation(description: "logout completes")
712-
client.logout {
795+
client.logout(removeDevice: false) {
713796
expectation.fulfill()
714797
}
715798
waitForExpectations(timeout: defaultTimeout)

0 commit comments

Comments
 (0)
0