@ -1036,7 +1036,6 @@ public final class OpenGroupAPI: NSObject {
return Promise ( error : Error . signingFailed )
}
// TODO: ' r e m o v e A u t h T o k e n ' a s a m i g r a t i o n ? ? ? ( w o u l d p r e v i o u s l y d o t h i s w h e n g e t t i n g a ` 4 0 1 ` )
return dependencies . api . sendOnionRequest ( signedRequest , to : request . server , with : publicKey )
}
@ -1045,640 +1044,4 @@ public final class OpenGroupAPI: NSObject {
preconditionFailure ( " It's currently not allowed to send non onion routed requests. " )
}
// MARK: -
// MARK: -
// MARK: - L e g a c y R e q u e s t s ( T o b e r e m o v e d )
// TODO: R e m o v e t h e l e g a c y r e q u e s t s ( s h o u l d b e u n u s e d o n c e w e r e l e a s e - j u s t h e r e f o r t e s t i n g )
public static var legacyDefaultRoomsPromise : Promise < [ LegacyRoomInfo ] >?
// MARK: - - L e g a c y A u t h
@ available ( * , deprecated , message : " Use request signing instead " )
private static func legacyGetAuthToken ( for room : String , on server : String ) -> Promise < String > {
let storage = SNMessagingKitConfiguration . shared . storage
if let authToken : String = storage . getAuthToken ( for : room , on : server ) {
return Promise . value ( authToken )
}
if let authTokenPromise : Promise < String > = legacyAuthTokenPromises . wrappedValue [ " \( server ) . \( room ) " ] {
return authTokenPromise
}
let promise : Promise < String > = legacyRequestNewAuthToken ( for : room , on : server )
. then ( on : OpenGroupAPI . workQueue ) { legacyClaimAuthToken ( $0 , for : room , on : server ) }
. then ( on : OpenGroupAPI . workQueue ) { authToken -> Promise < String > in
let ( promise , seal ) = Promise < String > . pending ( )
storage . write ( with : { transaction in
storage . setAuthToken ( for : room , on : server , to : authToken , using : transaction )
} , completion : {
seal . fulfill ( authToken )
} )
return promise
}
promise
. done ( on : OpenGroupAPI . workQueue ) { _ in
legacyAuthTokenPromises . wrappedValue [ " \( server ) . \( room ) " ] = nil
}
. catch ( on : OpenGroupAPI . workQueue ) { _ in
legacyAuthTokenPromises . wrappedValue [ " \( server ) . \( room ) " ] = nil
}
legacyAuthTokenPromises . wrappedValue [ " \( server ) . \( room ) " ] = promise
return promise
}
@ available ( * , deprecated , message : " Use request signing instead " )
public static func legacyRequestNewAuthToken ( for room : String , on server : String ) -> Promise < String > {
SNLog ( " Requesting auth token for server: \( server ) . " )
guard let userKeyPair : ECKeyPair = SNMessagingKitConfiguration . shared . storage . getUserKeyPair ( ) else {
return Promise ( error : Error . generic )
}
let request : Request = Request (
server : server ,
room : room ,
endpoint : . legacyAuthTokenChallenge ( legacyAuth : true ) ,
queryParameters : [
. publicKey : getUserHexEncodedPublicKey ( )
] ,
isAuthRequired : false
)
return legacySend ( request ) . map ( on : OpenGroupAPI . workQueue ) { _ , maybeData in
guard let data : Data = maybeData else { throw Error . parsingFailed }
let response = try data . decoded ( as : LegacyAuthTokenResponse . self , customError : Error . parsingFailed )
let symmetricKey = try AESGCM . generateSymmetricKey ( x25519PublicKey : response . challenge . ephemeralPublicKey , x25519PrivateKey : userKeyPair . privateKey )
guard let tokenAsData = try ? AESGCM . decrypt ( response . challenge . ciphertext , with : symmetricKey ) else {
throw Error . decryptionFailed
}
return tokenAsData . toHexString ( )
}
}
@ available ( * , deprecated , message : " Use request signing instead " )
public static func legacyClaimAuthToken ( _ authToken : String , for room : String , on server : String ) -> Promise < String > {
let requestBody : LegacyPublicKeyBody = LegacyPublicKeyBody ( publicKey : getUserHexEncodedPublicKey ( ) )
guard let body : Data = try ? JSONEncoder ( ) . encode ( requestBody ) else {
return Promise ( error : HTTP . Error . invalidJSON )
}
let request : Request = Request (
method : . post ,
server : server ,
room : room ,
endpoint : . legacyAuthTokenClaim ( legacyAuth : true ) ,
headers : [
// S e t e x p l i c i t l y h e r e b e c a u s e i s i s n ' t i n t h e d a t a b a s e y e t a t t h i s p o i n t
. authorization : authToken
] ,
body : body ,
isAuthRequired : false
)
return legacySend ( request ) . map ( on : OpenGroupAPI . workQueue ) { _ in authToken }
}
// / S h o u l d b e c a l l e d w h e n l e a v i n g a g r o u p .
@ available ( * , deprecated , message : " Use request signing instead " )
public static func legacyDeleteAuthToken ( for room : String , on server : String ) -> Promise < Void > {
let request : Request = Request (
method : . delete ,
server : server ,
room : room ,
endpoint : . legacyAuthToken ( legacyAuth : true )
)
return legacySend ( request ) . map ( on : OpenGroupAPI . workQueue ) { _ in
let storage = SNMessagingKitConfiguration . shared . storage
storage . write { transaction in
storage . removeAuthToken ( for : room , on : server , using : transaction )
}
}
}
// MARK: - - L e g a c y R e q u e s t s
@ available ( * , deprecated , message : " Use poll or batch instead " )
public static func legacyCompactPoll ( _ server : String ) -> Promise < LegacyCompactPollResponse > {
let storage : SessionMessagingKitStorageProtocol = SNMessagingKitConfiguration . shared . storage
let rooms : [ String ] = storage . getAllOpenGroups ( ) . values
. filter { $0 . server = = server }
. map { $0 . room }
var getAuthTokenPromises : [ String : Promise < String > ] = [ : ]
let useMessageLimit = ( hasPerformedInitialPoll [ server ] != true && timeSinceLastOpen > OpenGroupAPI . Poller . maxInactivityPeriod )
hasPerformedInitialPoll [ server ] = true
if ! legacyHasUpdatedLastOpenDate {
UserDefaults . standard [ . lastOpen ] = Date ( )
legacyHasUpdatedLastOpenDate = true
}
for room in rooms {
getAuthTokenPromises [ room ] = legacyGetAuthToken ( for : room , on : server )
}
let requestBody : LegacyCompactPollBody = LegacyCompactPollBody (
requests : rooms
. map { roomId -> LegacyCompactPollBody . Room in
LegacyCompactPollBody . Room (
id : roomId ,
fromMessageServerId : ( useMessageLimit ? nil :
storage . getLastMessageServerID ( for : roomId , on : server )
) ,
fromDeletionServerId : ( useMessageLimit ? nil :
storage . getLastDeletionServerID ( for : roomId , on : server )
) ,
legacyAuthToken : nil
)
}
)
return when ( fulfilled : [ Promise < String > ] ( getAuthTokenPromises . values ) )
. then ( on : OpenGroupAPI . workQueue ) { _ -> Promise < LegacyCompactPollResponse > in
let requestBodyWithAuthTokens : LegacyCompactPollBody = LegacyCompactPollBody (
requests : requestBody . requests . compactMap { oldRoom -> LegacyCompactPollBody . Room ? in
guard let authToken : String = getAuthTokenPromises [ oldRoom . id ] ? . value else { return nil }
return LegacyCompactPollBody . Room (
id : oldRoom . id ,
fromMessageServerId : oldRoom . fromMessageServerId ,
fromDeletionServerId : oldRoom . fromDeletionServerId ,
legacyAuthToken : authToken
)
}
)
guard let body : Data = try ? JSONEncoder ( ) . encode ( requestBodyWithAuthTokens ) else {
return Promise ( error : HTTP . Error . invalidJSON )
}
let request = Request (
method : . post ,
server : server ,
endpoint : . legacyCompactPoll ( legacyAuth : true ) ,
body : body ,
isAuthRequired : false
)
return legacySend ( request )
. then ( on : OpenGroupAPI . workQueue ) { _ , maybeData -> Promise < LegacyCompactPollResponse > in
guard let data : Data = maybeData else { throw Error . parsingFailed }
let response : LegacyCompactPollResponse = try data . decoded ( as : LegacyCompactPollResponse . self , customError : Error . parsingFailed )
return when (
fulfilled : response . results
. compactMap { ( result : LegacyCompactPollResponse . Result ) -> Promise < [ LegacyDeletion ] >? in
// A 4 0 1 m e a n s t h a t w e d i d n ' t p r o v i d e a ( v a l i d ) a u t h t o k e n f o r a r o u t e t h a t
// r e q u i r e d o n e . W e u s e t h i s a s a n i n d i c a t i o n t h a t t h e t o k e n w e ' r e u s i n g h a s
// e x p i r e d . N o t e t h a t a 4 0 3 h a s a d i f f e r e n t m e a n i n g ; i t m e a n s t h a t w e p r o v i d e d
// a v a l i d t o k e n b u t i t d o e s n ' t h a v e a h i g h e n o u g h p e r m i s s i o n l e v e l f o r t h e
// r o u t e i n q u e s t i o n .
guard result . statusCode != 401 else {
storage . writeSync { transaction in
storage . removeAuthToken ( for : result . room , on : server , using : transaction )
}
return nil
}
return legacyProcess ( messages : result . messages , for : result . room , on : server )
. then ( on : OpenGroupAPI . workQueue ) { _ -> Promise < [ LegacyDeletion ] > in
legacyProcess ( deletions : result . deletions , for : result . room , on : server )
}
}
) . then ( on : OpenGroupAPI . workQueue ) { _ in Promise . value ( response ) }
}
}
}
@ available ( * , deprecated , message : " Use getDefaultRoomsIfNeeded instead " )
public static func legacyGetDefaultRoomsIfNeeded ( ) {
Storage . shared . write (
with : { transaction in
Storage . shared . setOpenGroupPublicKey ( for : defaultServer , to : defaultServerPublicKey , using : transaction )
} ,
completion : {
let promise = attempt ( maxRetryCount : 8 , recoveringOn : DispatchQueue . main ) {
OpenGroupAPI . legacyGetAllRooms ( from : defaultServer )
}
_ = promise . done ( on : OpenGroupAPI . workQueue ) { items in
items . forEach { legacyGetGroupImage ( for : $0 . id , on : defaultServer ) . retainUntilComplete ( ) }
}
promise . catch ( on : OpenGroupAPI . workQueue ) { _ in
OpenGroupAPI . legacyDefaultRoomsPromise = nil
}
legacyDefaultRoomsPromise = promise
}
)
}
@ available ( * , deprecated , message : " Use rooms(for:) instead " )
public static func legacyGetAllRooms ( from server : String ) -> Promise < [ LegacyRoomInfo ] > {
let request : Request = Request (
server : server ,
endpoint : . legacyRooms ,
isAuthRequired : false
)
return legacySend ( request )
. map ( on : OpenGroupAPI . workQueue ) { _ , maybeData in
guard let data : Data = maybeData else { throw Error . parsingFailed }
let response : LegacyRoomsResponse = try data . decoded ( as : LegacyRoomsResponse . self , customError : Error . parsingFailed )
return response . rooms
}
}
@ available ( * , deprecated , message : " Use room(for:on:) instead " )
public static func legacyGetRoomInfo ( for room : String , on server : String ) -> Promise < LegacyRoomInfo > {
let request : Request = Request (
server : server ,
room : room ,
endpoint : . legacyRoomInfo ( room ) ,
isAuthRequired : false
)
return legacySend ( request )
. map ( on : OpenGroupAPI . workQueue ) { _ , maybeData in
guard let data : Data = maybeData else { throw Error . parsingFailed }
let response : LegacyGetInfoResponse = try data . decoded ( as : LegacyGetInfoResponse . self , customError : Error . parsingFailed )
return response . room
}
}
@ available ( * , deprecated , message : " Use roomImage(_:for:on:) instead " )
public static func legacyGetGroupImage ( for room : String , on server : String ) -> Promise < Data > {
// N o r m a l l y t h e i m a g e f o r a g i v e n g r o u p i s s t o r e d w i t h t h e g r o u p t h r e a d , s o i t ' s o n l y
// f e t c h e d o n c e . H o w e v e r , o n t h e j o i n o p e n g r o u p s c r e e n w e s h o w i m a g e s f o r g r o u p s t h e
// u s e r * h a s n ' t * j o i n e d y e t . W e d o n ' t w a n t t o r e - f e t c h t h e s e i m a g e s e v e r y t i m e t h e
// u s e r o p e n s t h e a p p b e c a u s e t h a t c o u l d s l o w t h e a p p d o w n o r b e d a t a - i n t e n s i v e . S o
// i n s t e a d w e a s s u m e t h a t t h e s e i m a g e s d o n ' t c h a n g e t h a t o f t e n a n d j u s t f e t c h t h e m o n c e
// a w e e k . W e a l s o a s s u m e t h a t t h e y ' r e a l l f e t c h e d a t t h e s a m e t i m e a s w e l l , s o t h a t
// w e o n l y n e e d t o m a i n t a i n o n e d a t e i n u s e r d e f a u l t s . O n t o p o f a l l o f t h i s w e a l s o
// d o n ' t d o u b l e u p o n f e t c h r e q u e s t s b y s t o r i n g t h e e x i s t i n g r e q u e s t a s a p r o m i s e i f
// t h e r e i s o n e .
let lastOpenGroupImageUpdate : Date ? = UserDefaults . standard [ . lastOpenGroupImageUpdate ]
let now : Date = Date ( )
let timeSinceLastUpdate : TimeInterval = ( given ( lastOpenGroupImageUpdate ) { now . timeIntervalSince ( $0 ) } ? ? . greatestFiniteMagnitude )
let updateInterval : TimeInterval = ( 7 * 24 * 60 * 60 )
if let data = Storage . shared . getOpenGroupImage ( for : room , on : server ) , server = = defaultServer , timeSinceLastUpdate < updateInterval {
return Promise . value ( data )
}
if let promise = legacyGroupImagePromises [ " \( server ) . \( room ) " ] {
return promise
}
let request : Request = Request (
server : server ,
room : room ,
endpoint : . legacyRoomImage ( room ) ,
isAuthRequired : false
)
let promise : Promise < Data > = legacySend ( request ) . map ( on : OpenGroupAPI . workQueue ) { _ , maybeData in
guard let data : Data = maybeData else { throw Error . parsingFailed }
let response : LegacyFileDownloadResponse = try data . decoded ( as : LegacyFileDownloadResponse . self , customError : Error . parsingFailed )
if server = = defaultServer {
Storage . shared . write { transaction in
Storage . shared . setOpenGroupImage ( to : response . data , for : room , on : server , using : transaction )
}
UserDefaults . standard [ . lastOpenGroupImageUpdate ] = now
}
return response . data
}
legacyGroupImagePromises [ " \( server ) . \( room ) " ] = promise
return promise
}
@ available ( * , deprecated , message : " Use room(for:on:) instead " )
public static func legacyGetMemberCount ( for room : String , on server : String ) -> Promise < UInt64 > {
let request : Request = Request (
server : server ,
room : room ,
endpoint : . legacyMemberCount ( legacyAuth : true )
)
return legacySend ( request )
. map ( on : OpenGroupAPI . workQueue ) { _ , maybeData in
guard let data : Data = maybeData else { throw Error . parsingFailed }
let response : LegacyMemberCountResponse = try data . decoded ( as : LegacyMemberCountResponse . self , customError : Error . parsingFailed )
let storage = SNMessagingKitConfiguration . shared . storage
storage . write { transaction in
storage . setUserCount ( to : response . memberCount , forOpenGroupWithID : " \( server ) . \( room ) " , using : transaction )
}
return response . memberCount
}
}
// MARK: - L e g a c y F i l e S t o r a g e
@ available ( * , deprecated , message : " Use uploadFile(_:fileName:to:on:) instead " )
public static func legacyUpload ( _ file : Data , to room : String , on server : String ) -> Promise < UInt64 > {
let requestBody : FileUploadBody = FileUploadBody ( file : file . base64EncodedString ( ) )
guard let body : Data = try ? JSONEncoder ( ) . encode ( requestBody ) else {
return Promise ( error : HTTP . Error . invalidJSON )
}
let request = Request ( method : . post , server : server , room : room , endpoint : . legacyFiles , body : body )
return legacySend ( request ) . map ( on : OpenGroupAPI . workQueue ) { _ , maybeData in
guard let data : Data = maybeData else { throw Error . parsingFailed }
let response : LegacyFileUploadResponse = try data . decoded ( as : LegacyFileUploadResponse . self , customError : Error . parsingFailed )
return response . fileId
}
}
@ available ( * , deprecated , message : " Use downloadFile(_:from:on:) instead " )
public static func legacyDownload ( _ file : UInt64 , from room : String , on server : String ) -> Promise < Data > {
let request = Request ( server : server , room : room , endpoint : . legacyFile ( file ) )
return legacySend ( request ) . map ( on : OpenGroupAPI . workQueue ) { _ , maybeData in
guard let data : Data = maybeData else { throw Error . parsingFailed }
let response : LegacyFileDownloadResponse = try data . decoded ( as : LegacyFileDownloadResponse . self , customError : Error . parsingFailed )
return response . data
}
}
// MARK: - L e g a c y M e s s a g e S e n d i n g & R e c e i v i n g
@ available ( * , deprecated , message : " Use send(_:to:on:whisperTo:whisperMods:with:) instead " )
public static func legacySend ( _ message : LegacyOpenGroupMessageV2 , to room : String , on server : String , with publicKey : String ) -> Promise < LegacyOpenGroupMessageV2 > {
guard let signedMessage = message . sign ( with : publicKey ) else { return Promise ( error : Error . signingFailed ) }
guard let body : Data = try ? JSONEncoder ( ) . encode ( signedMessage ) else {
return Promise ( error : Error . parsingFailed )
}
let request = Request ( method : . post , server : server , room : room , endpoint : . legacyMessages , body : body )
return legacySend ( request ) . map ( on : OpenGroupAPI . workQueue ) { _ , maybeData in
guard let data : Data = maybeData else { throw Error . parsingFailed }
let message : LegacyOpenGroupMessageV2 = try data . decoded ( as : LegacyOpenGroupMessageV2 . self , customError : Error . parsingFailed )
Storage . shared . write { transaction in
Storage . shared . addReceivedMessageTimestamp ( message . sentTimestamp , using : transaction )
}
return message
}
}
@ available ( * , deprecated , message : " Use recentMessages(in:on:) or messagesSince(seqNo:in:on:) instead " )
public static func legacyGetMessages ( for room : String , on server : String ) -> Promise < [ LegacyOpenGroupMessageV2 ] > {
let storage = SNMessagingKitConfiguration . shared . storage
let request : Request = Request (
server : server ,
room : room ,
endpoint : . legacyMessages ,
queryParameters : [
. fromServerId : storage . getLastMessageServerID ( for : room , on : server ) . map { String ( $0 ) }
] . compactMapValues { $0 }
)
return legacySend ( request ) . then ( on : OpenGroupAPI . workQueue ) { _ , maybeData -> Promise < [ LegacyOpenGroupMessageV2 ] > in
guard let data : Data = maybeData else { throw Error . parsingFailed }
let messages : [ LegacyOpenGroupMessageV2 ] = try data . decoded ( as : [ LegacyOpenGroupMessageV2 ] . self , customError : Error . parsingFailed )
return legacyProcess ( messages : messages , for : room , on : server )
}
}
// MARK: - L e g a c y M e s s a g e D e l e t i o n
// TODO: N o d e l e t e m e t h o d ? ? ? ? .
@ available ( * , deprecated , message : " Use v4 endpoint instead " )
public static func legacyDeleteMessage ( with serverID : Int64 , from room : String , on server : String ) -> Promise < Void > {
let request : Request = Request (
method : . delete ,
server : server ,
room : room ,
endpoint : . legacyMessagesForServer ( serverID )
)
return legacySend ( request ) . map ( on : OpenGroupAPI . workQueue ) { _ in }
}
@ available ( * , deprecated , message : " Use v4 endpoint instead " )
public static func legacyGetDeletedMessages ( for room : String , on server : String ) -> Promise < [ LegacyDeletion ] > {
let storage = SNMessagingKitConfiguration . shared . storage
let request : Request = Request (
server : server ,
room : room ,
endpoint : . legacyDeletedMessages ,
queryParameters : [
. fromServerId : storage . getLastDeletionServerID ( for : room , on : server ) . map { String ( $0 ) }
] . compactMapValues { $0 }
)
return legacySend ( request ) . then ( on : OpenGroupAPI . workQueue ) { _ , maybeData -> Promise < [ LegacyDeletion ] > in
guard let data : Data = maybeData else { throw Error . parsingFailed }
let response : LegacyDeletedMessagesResponse = try data . decoded ( as : LegacyDeletedMessagesResponse . self , customError : Error . parsingFailed )
return legacyProcess ( deletions : response . deletions , for : room , on : server )
}
}
// MARK: - L e g a c y M o d e r a t i o n
@ available ( * , deprecated , message : " Use v4 endpoint instead " )
public static func legacyGetModerators ( for room : String , on server : String ) -> Promise < [ String ] > {
let request : Request = Request (
server : server ,
room : room ,
endpoint : . legacyModerators
)
return legacySend ( request )
. map ( on : OpenGroupAPI . workQueue ) { _ , maybeData in
guard let data : Data = maybeData else { throw Error . parsingFailed }
let response : LegacyModeratorsResponse = try data . decoded ( as : LegacyModeratorsResponse . self , customError : Error . parsingFailed )
if var x = self . moderators [ server ] {
x [ room ] = Set ( response . moderators )
self . moderators [ server ] = x
}
else {
self . moderators [ server ] = [ room : Set ( response . moderators ) ]
}
return response . moderators
}
}
@ available ( * , deprecated , message : " Use v4 endpoint instead " )
public static func legacyBan ( _ publicKey : String , from room : String , on server : String ) -> Promise < Void > {
let requestBody : LegacyPublicKeyBody = LegacyPublicKeyBody ( publicKey : getUserHexEncodedPublicKey ( ) )
guard let body : Data = try ? JSONEncoder ( ) . encode ( requestBody ) else {
return Promise ( error : HTTP . Error . invalidJSON )
}
let request : Request = Request (
method : . post ,
server : server ,
room : room ,
endpoint : . legacyBlockList ,
body : body
)
return legacySend ( request ) . map ( on : OpenGroupAPI . workQueue ) { _ in }
}
@ available ( * , deprecated , message : " Use v4 endpoint instead " )
public static func legacyBanAndDeleteAllMessages ( _ publicKey : String , from room : String , on server : String ) -> Promise < Void > {
let requestBody : LegacyPublicKeyBody = LegacyPublicKeyBody ( publicKey : getUserHexEncodedPublicKey ( ) )
guard let body : Data = try ? JSONEncoder ( ) . encode ( requestBody ) else {
return Promise ( error : HTTP . Error . invalidJSON )
}
let request : Request = Request (
method : . post ,
server : server ,
room : room ,
endpoint : . legacyBanAndDeleteAll ,
body : body
)
return legacySend ( request ) . map ( on : OpenGroupAPI . workQueue ) { _ in }
}
@ available ( * , deprecated , message : " Use v4 endpoint instead " )
public static func legacyUnban ( _ publicKey : String , from room : String , on server : String ) -> Promise < Void > {
let request : Request = Request (
method : . delete ,
server : server ,
room : room ,
endpoint : . legacyBlockListIndividual ( publicKey )
)
return legacySend ( request ) . map ( on : OpenGroupAPI . workQueue ) { _ in }
}
// MARK: - P r o c e s s i n g
// TODO: M o v e t h e s e m e t h o d s t o t h e O p e n G r o u p M a n a g e r ? ( s e e m s o d d f o r t h e m t o b e i n t h e A P I )
@ available ( * , deprecated , message : " Use v4 endpoint instead " )
private static func legacyProcess ( messages : [ LegacyOpenGroupMessageV2 ] ? , for room : String , on server : String ) -> Promise < [ LegacyOpenGroupMessageV2 ] > {
guard let messages : [ LegacyOpenGroupMessageV2 ] = messages , ! messages . isEmpty else { return Promise . value ( [ ] ) }
let storage = SNMessagingKitConfiguration . shared . storage
let serverID : Int64 = ( messages . compactMap { $0 . serverID } . max ( ) ? ? 0 )
let lastMessageServerID : Int64 = ( storage . getLastMessageServerID ( for : room , on : server ) ? ? 0 )
if serverID > lastMessageServerID {
let ( promise , seal ) = Promise < [ LegacyOpenGroupMessageV2 ] > . pending ( )
storage . write (
with : { transaction in
storage . setLastMessageServerID ( for : room , on : server , to : serverID , using : transaction )
} ,
completion : {
seal . fulfill ( messages )
}
)
return promise
}
return Promise . value ( messages )
}
@ available ( * , deprecated , message : " Use v4 endpoint instead " )
private static func legacyProcess ( deletions : [ LegacyDeletion ] ? , for room : String , on server : String ) -> Promise < [ LegacyDeletion ] > {
guard let deletions : [ LegacyDeletion ] = deletions else { return Promise . value ( [ ] ) }
let storage = SNMessagingKitConfiguration . shared . storage
let serverID : Int64 = ( deletions . compactMap { $0 . id } . max ( ) ? ? 0 )
let lastDeletionServerID : Int64 = ( storage . getLastDeletionServerID ( for : room , on : server ) ? ? 0 )
if serverID > lastDeletionServerID {
let ( promise , seal ) = Promise < [ LegacyDeletion ] > . pending ( )
storage . write (
with : { transaction in
storage . setLastDeletionServerID ( for : room , on : server , to : serverID , using : transaction )
} ,
completion : {
seal . fulfill ( deletions )
}
)
return promise
}
return Promise . value ( deletions )
}
// MARK: - L e g a c y C o n v e n i e n c e
@ available ( * , deprecated , message : " Use v4 endpoint instead " )
private static func legacySend ( _ request : Request , through api : OnionRequestAPIType . Type = OnionRequestAPI . self ) -> Promise < ( OnionRequestResponseInfoType , Data ? ) > {
guard let url : URL = request . url else { return Promise ( error : Error . invalidURL ) }
var urlRequest : URLRequest = URLRequest ( url : url )
urlRequest . httpMethod = request . method . rawValue
urlRequest . allHTTPHeaderFields = request . headers
. setting ( . room , request . room ) // TODO: I s t h i s n e e d e d a n y m o r e ? A d d a t t h e r e q u e s t l e v e l ? .
. toHTTPHeaders ( )
urlRequest . httpBody = request . body
if request . useOnionRouting {
guard let publicKey = SNMessagingKitConfiguration . shared . storage . getOpenGroupPublicKey ( for : request . server ) else {
return Promise ( error : Error . noPublicKey )
}
if request . isAuthRequired {
// B e c a u s e l e g a c y a u t h h a p p e n s o n a p e r - r o o m b a s i s , w e n e e d t o h a v e a r o o m t o
// m a k e a n a u t h e n t i c a t e d r e q u e s t
guard let room = request . room else {
return api . sendOnionRequest ( urlRequest , to : request . server , using : . v3 , with : publicKey )
}
return legacyGetAuthToken ( for : room , on : request . server )
. then ( on : OpenGroupAPI . workQueue ) { authToken -> Promise < ( OnionRequestResponseInfoType , Data ? ) > in
urlRequest . setValue ( authToken , forHTTPHeaderField : Header . authorization . rawValue )
let promise = api . sendOnionRequest ( urlRequest , to : request . server , using : . v3 , with : publicKey )
promise . catch ( on : OpenGroupAPI . workQueue ) { error in
// A 4 0 1 m e a n s t h a t w e d i d n ' t p r o v i d e a ( v a l i d ) a u t h t o k e n f o r a r o u t e
// t h a t r e q u i r e d o n e . W e u s e t h i s a s a n i n d i c a t i o n t h a t t h e t o k e n w e ' r e
// u s i n g h a s e x p i r e d . N o t e t h a t a 4 0 3 h a s a d i f f e r e n t m e a n i n g ; i t m e a n s
// t h a t w e p r o v i d e d a v a l i d t o k e n b u t i t d o e s n ' t h a v e a h i g h e n o u g h
// p e r m i s s i o n l e v e l f o r t h e r o u t e i n q u e s t i o n .
if case OnionRequestAPI . Error . httpRequestFailedAtDestination ( let statusCode , _ , _ ) = error , statusCode = = 401 {
let storage = SNMessagingKitConfiguration . shared . storage
storage . writeSync { transaction in
storage . removeAuthToken ( for : room , on : request . server , using : transaction )
}
}
}
return promise
}
}
return api . sendOnionRequest ( urlRequest , to : request . server , using : . v3 , with : publicKey )
}
preconditionFailure ( " It's currently not allowed to send non onion routed requests. " )
}
}