Couchbase Lite: Some questions

Recently, I started using Couchbase Lite mobile sdk for iOS. I am exploring chat sample (CouchChat). The sync server and gateway is also setup & running. I am using basic authentication from iOS end. I do have few questions:

  1. Since we attach a CBLAuthenticator object to push / pull replication, how can we be sure that authentication is successful ? Do we have to rely on status (CBLReplicationStatus) as received in notifications for push / pull progress ? If Yes, then which status to focus on ? If No then what is the alternative ?
  2. On Sync server side, I want to see the data (documents) for a particular ‘type’ say for example type = ‘profile’ or type = ‘room’. What will be the corresponding query ? I am simply interested in the latest data only. Is there any server side query guide available that one can use and write query on the server ?

Thanks

https://developer.couchbase.com/documentation/mobile/current/guides/couchbase-lite/native-api/replication/index.html#detecting-unauthorized-credentials

  1. On Sync server side, I want to see the data (documents) for a particular ‘type’ say for example type = ‘profile’ or type = ‘room’. What will be the corresponding query ? I am simply interested in the latest data only. Is there any server side query guide available that one can use and write query on the server ?

Sync Gateway doesn’t really have a query language, you can query documents by id and by channels. For more customised queries, you can use N1QL on the bucket where Sync Gateway is storing documents.

For the point #1, I did not get a proper answer. My observation is that for an invalid authentication, the first notification that we did receive in replicationProgress do not have any error. Only the subsequent notification do come up with error so it is difficult for me to decide if replication failed. Instead the SDK should have returned the status as authenticating and if it failed then it should have status as failed authentication else the status as performing push / pull.

Does it really matter if the 401 Unauthorized in the case of invalid credentials isn’t reported in the first notification?

Alternatively, you can check for the validity of credentials by sending a request to the Sync Gateway /{db}/_session endpoint directly.

PS: could you add some tags (Couchbase Lite, Sync Gateway or Mobile) to this question so it will gain more visibility.

I tried using the rest api //_session and it seems to serve the purpose but I would like to know what this API do on server side besides returning proper response to client ? is it going to create a session on server for the username which is passed in the post body of this rest api call ? If Yes, then how long will this session exists on server and will couchbase lite be able to use this session? Do we need to make another REST API call to close / clear this session ?

Thanks

is it going to create a session on server for the username which is passed in the post body of this rest api call ? If Yes, then how long will this session exists on server and will couchbase lite be able to use this session?

Yes it creates a new session for that user. The session validity is 24 hours (that’s not currently documented but will be when this change is deployed).

Do we need to make another REST API call to close / clear this session ?

Only if you really need to. The session id can be cleared using the DELETE /{db}/_session endpoint.

Thanks for the reply.
Is the sessionID is the value for a key “SyncGatewaySession” in the http header for the returned response?

If I perform a rest api call /dbname/_session with a valid username & password then it returns a successful response. If I again attempt the same call with a username & password that does not exists then this second service call is returning the same response as is returned by the previous one.

I am using swift language for an iOS project. Below is the method that is doing the REST API call:

private func performServerValidation(userName: String, password: String){
    let bodyParameter = ["name": userName, "password": password]
    
    if JSONSerialization.isValidJSONObject(bodyParameter){
        
        let sessionConfiguration = URLSessionConfiguration.default
        let session = URLSession(configuration: sessionConfiguration)
        let urlString = self.serverDatabaseURL + "_session"
        let url = URL(string: urlString)
        
        var request = URLRequest(url: url!)
        request.addValue("application/json", forHTTPHeaderField: "Content-Type")
        request.addValue("application/json", forHTTPHeaderField: "Accept")
        request.httpMethod = "post"
        
        
        var postBody:Data?
        do{
            postBody = try JSONSerialization.data(withJSONObject: bodyParameter, options: .prettyPrinted)
            request.addValue(String(stringInterpolationSegment: postBody?.count), forHTTPHeaderField: "Content-Length")
            request.httpBody = postBody
            request.cachePolicy = .reloadIgnoringLocalCacheData
            
            let dataTask = session.dataTask(with: request) { [weak self] (data, response, error) in
                
                session.finishTasksAndInvalidate()
                
                if error != nil{
                    self?.callAuthenticationFailureCallback()
                }
                do{
                    if let receivedData = data{
                        let result = try JSONSerialization.jsonObject(with: receivedData, options: [])
                        print("result is: \(result)")
                        
                        let httpURLResponse:HTTPURLResponse? = response as? HTTPURLResponse
                        if httpURLResponse?.statusCode == 200{
                            DispatchQueue.main.sync(execute: {
                                
                                //extract sessionID to be sent back to server when signout is performed
                                if let sessionIDPart = httpURLResponse?.allHeaderFields["Set-Cookie"] as? String{
                                    
                                    let components = sessionIDPart.components(separatedBy: ";")
                                    if components.count > 0{
                                        let subComponents = components[0].components(separatedBy: "=")
                                        if subComponents.count == 2{
                                            self?.sessionID = subComponents[1]
                                        }
                                        
                                    }
                                    
                                }                                    
                            })
                        }else{
                            //handle error
                        }
                    }else{
                        //handle error
                    }
                    
                }catch{
                    //handle error
                }
            }
            dataTask.resume()
        }catch{
            //handle error
        }
    }
}