sdk/communication/AzureCommunicationCommon/Source/Identifiers.swift (199 lines of code) (raw):

// -------------------------------------------------------------------------- // // Copyright (c) Microsoft Corporation. All rights reserved. // // The MIT License (MIT) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the ""Software""), to // deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS // IN THE SOFTWARE. // // -------------------------------------------------------------------------- import Foundation import os.log /** The IdentifierKind for a given CommunicationIdentifier. */ @objcMembers public class IdentifierKind: NSObject { private var rawValue: String public static let communicationUser = IdentifierKind(rawValue: "communicationUser") public static let phoneNumber = IdentifierKind(rawValue: "phoneNumber") public static let microsoftTeamsUser = IdentifierKind(rawValue: "microsoftTeamsUser") public static let microsoftTeamsApp = IdentifierKind(rawValue: "microsoftTeamsApp") public static let unknown = IdentifierKind(rawValue: "unknown") public init(rawValue: String) { self.rawValue = rawValue } } /** Common Communication Identifier protocol for all Azure Communication Services. All Communication Identifiers conform to this protocol. */ @objc public protocol CommunicationIdentifier: NSObjectProtocol { var rawId: String { get } var kind: IdentifierKind { get } } internal enum Prefix { public static let PhoneNumber = "4:" public static let TeamsAppPublicCloud = "28:orgid:" public static let TeamsAppDodCloud = "28:dod:" public static let TeamsAppGcchCloud = "28:gcch:" public static let TeamsUserAnonymous = "8:teamsvisitor:" public static let TeamsUserPublicCloud = "8:orgid:" public static let TeamsUserDodCloud = "8:dod:" public static let TeamsUserGcchCloud = "8:gcch:" public static let AcsUser = "8:acs:" public static let AcsUserDodCloud = "8:dod-acs:" public static let AcsUserGcchCloud = "8:gcch-acs:" public static let SpoolUser = "8:spool:" } /** Creates a CommunicationIdentifierKind from a given rawId. When storing rawIds use this function to restore the identifier that was encoded in the rawId. - Parameter fromRawId: Id of the Microsoft Teams user. If the user isn't anonymous,The rawId to be translated to its identifier representation. */ public func createCommunicationIdentifier(fromRawId rawId: String) -> CommunicationIdentifier { if rawId.hasPrefix(Prefix.PhoneNumber) { return PhoneNumberIdentifier(phoneNumber: String(rawId.dropFirst(Prefix.PhoneNumber.count)), rawId: rawId) } let segments = rawId.split(separator: ":") let segmentCounts = segments.count if segmentCounts != 3 { return UnknownIdentifier(rawId) } let scope = segments[0] + ":" + segments[1] + ":" let suffix = String(segments[2]) switch scope { case Prefix.TeamsUserAnonymous: return MicrosoftTeamsUserIdentifier(userId: suffix, isAnonymous: true) case Prefix.TeamsUserPublicCloud: return MicrosoftTeamsUserIdentifier(userId: suffix, isAnonymous: false, rawId: rawId, cloudEnvironment: .Public) case Prefix.TeamsUserDodCloud: return MicrosoftTeamsUserIdentifier(userId: suffix, isAnonymous: false, rawId: rawId, cloudEnvironment: .Dod) case Prefix.TeamsUserGcchCloud: return MicrosoftTeamsUserIdentifier(userId: suffix, isAnonymous: false, rawId: rawId, cloudEnvironment: .Gcch) case Prefix.TeamsAppPublicCloud: return MicrosoftTeamsAppIdentifier(appId: suffix, cloudEnvironment: .Public) case Prefix.TeamsAppDodCloud: return MicrosoftTeamsAppIdentifier(appId: suffix, cloudEnvironment: .Dod) case Prefix.TeamsAppGcchCloud: return MicrosoftTeamsAppIdentifier(appId: suffix, cloudEnvironment: .Gcch) case Prefix.AcsUser, Prefix.SpoolUser, Prefix.AcsUserDodCloud, Prefix.AcsUserGcchCloud: return CommunicationUserIdentifier(rawId) default: return UnknownIdentifier(rawId) } } /** Communication identifier for Communication Services Users */ @objcMembers public class CommunicationUserIdentifier: NSObject, CommunicationIdentifier { public var rawId: String { return identifier } public var kind: IdentifierKind { return .communicationUser } public let identifier: String /** Creates a CommunicationUserIdentifier object - Parameter identifier: identifier representing the object identity */ @objc(initWithIdentifier:) public init(_ identifier: String) { self.identifier = identifier } } /** Catch-all for all other Communication identifiers for Communication Services It is not advisable to rely on this type of identifier, as UnknownIdentifier could become a new or existing distinct type in the future. */ @objcMembers public class UnknownIdentifier: NSObject, CommunicationIdentifier { public var rawId: String { return identifier } public var kind: IdentifierKind { return .unknown } public let identifier: String /** Creates a UnknownIdentifier object - Parameter identifier: identifier representing the object identity */ @objc(initWithIdentifier:) public init(_ identifier: String) { self.identifier = identifier super.init() logUsageWarning() } private func logUsageWarning() { let subsystem = "com.azure" let category = "AzureCommunicationCommon" let message = "It is not advisable to rely on this type of identifier" + "as UnknownIdentifier could become a new or existing distinct type in the future." let osLog = OSLog(subsystem: subsystem, category: category) if #available(macOS 11.0, iOS 14.0, watchOS 7.0, tvOS 14.0, *) { let logger = Logger(osLog) logger.info("\(message)") } else { os_log("%@", log: osLog, type: .info, message) } } } /** Communication identifier for Communication Services representing a Phone Number */ @objcMembers public class PhoneNumberIdentifier: NSObject, CommunicationIdentifier { public let phoneNumber: String public private(set) var rawId: String public var kind: IdentifierKind { return .phoneNumber } /** Creates a PhoneNumberIdentifier object - Parameter phoneNumber: phone number to create the object, different from identifier - Parameter rawId: The optional raw id of the phone number. */ public init(phoneNumber: String, rawId: String? = nil) { self.phoneNumber = phoneNumber if let rawId = rawId { self.rawId = rawId } else { self.rawId = "4:" + phoneNumber } } // swiftlint:disable:next nsobject_prefer_isequal /** Returns a Boolean value indicating whether two values are equal. Note: In Objective-C favor isEqual() method - Parameter lhs PhoneNumberIdentifier to compare. - Parameter rhs Another PhoneNumberIdentifier to compare. */ public static func == (lhs: PhoneNumberIdentifier, rhs: PhoneNumberIdentifier) -> Bool { return lhs.rawId == rhs.rawId } /** Returns a Boolean value that indicates whether the receiver is equal to another given object. This will automatically return false if object being compared to is not a PhoneNumberIdentifier. - Parameter object The object with which to compare the receiver. */ override public func isEqual(_ object: Any?) -> Bool { guard let object = object as? PhoneNumberIdentifier else { return false } return rawId == object.rawId } } /** Communication identifier for Microsoft Teams Users */ @objcMembers public class MicrosoftTeamsUserIdentifier: NSObject, CommunicationIdentifier { public let userId: String public let isAnonymous: Bool public private(set) var rawId: String public var kind: IdentifierKind { return .microsoftTeamsUser } @available(*, deprecated, renamed: "cloudEnvironment") public let cloudEnviroment: CommunicationCloudEnvironment public let cloudEnvironment: CommunicationCloudEnvironment /** Creates a MicrosoftTeamsUserIdentifier object - Parameter userId: Id of the Microsoft Teams user. If the user isn't anonymous, the id is the AAD object id of the user. - Parameter isAnonymous: Set this to true if the user is anonymous: for example when joining a meeting with a share link. - Parameter rawId: The optional raw id of the Microsoft Teams User identifier. - Parameter cloudEnvironment: The cloud that the Microsoft Team user belongs to. A null value translates to the Public cloud. */ public init( userId: String, isAnonymous: Bool = false, rawId: String? = nil, cloudEnvironment: CommunicationCloudEnvironment = .Public ) { self.userId = userId self.isAnonymous = isAnonymous self.cloudEnvironment = cloudEnvironment self.cloudEnviroment = cloudEnvironment if let rawId = rawId { self.rawId = rawId } else { if isAnonymous { self.rawId = Prefix.TeamsUserAnonymous + userId } else { switch cloudEnvironment { case .Dod: self.rawId = Prefix.TeamsUserDodCloud + userId case .Gcch: self.rawId = Prefix.TeamsUserGcchCloud + userId default: self.rawId = Prefix.TeamsUserPublicCloud + userId } } } } /** Creates a MicrosoftTeamsUserIdentifier object. cloudEnvironment is defaulted to Public cloud. - Parameter userId: Id of the Microsoft Teams user. If the user isn't anonymous, the id is the AAD object id of the user. - Parameter isAnonymous: Set this to true if the user is anonymous: for example when joining a meeting with a share link. */ convenience init(userId: String, isAnonymous: Bool) { self.init(userId: userId, isAnonymous: isAnonymous, rawId: nil, cloudEnvironment: .Public) } // swiftlint:disable:next nsobject_prefer_isequal /** Returns a Boolean value indicating whether two values are equal. Note: In Objective-C favor isEqual() method - Parameter lhs MicrosoftTeamsUserIdentifier to compare. - Parameter rhs Another MicrosoftTeamsUserIdentifier to compare. */ public static func == (lhs: MicrosoftTeamsUserIdentifier, rhs: MicrosoftTeamsUserIdentifier) -> Bool { return lhs.rawId == rhs.rawId } /** Returns a Boolean value that indicates whether the receiver is equal to another given object. This will automatically return false if object being compared to is not a MicrosoftTeamsUserIdentifier. - Parameter object The object with which to compare the receiver. */ override public func isEqual(_ object: Any?) -> Bool { guard let object = object as? MicrosoftTeamsUserIdentifier else { return false } return rawId == object.rawId } } /** Communication identifier for Microsoft Teams applications. */ @objcMembers public class MicrosoftTeamsAppIdentifier: NSObject, CommunicationIdentifier { public let appId: String public let cloudEnvironment: CommunicationCloudEnvironment public var rawId: String public var kind: IdentifierKind { return .microsoftTeamsApp } /** Creates a MicrosoftTeamsAppIdentifier object - Parameter appId: The id of the Microsoft Teams application. - Parameter cloudEnvironment: The cloud that the Microsoft Teams application belongs to. A null value translates to the Public cloud. */ public init( appId: String, cloudEnvironment: CommunicationCloudEnvironment = .Public ) { self.appId = appId self.cloudEnvironment = cloudEnvironment switch cloudEnvironment { case .Dod: self.rawId = Prefix.TeamsAppDodCloud + appId case .Gcch: self.rawId = Prefix.TeamsAppGcchCloud + appId default: self.rawId = Prefix.TeamsAppPublicCloud + appId } } // swiftlint:disable:next nsobject_prefer_isequal /** Returns a Boolean value indicating whether two values are equal. Note: In Objective-C favor isEqual() method - Parameter lhs MicrosoftTeamsAppIdentifier to compare. - Parameter rhs Another MicrosoftTeamsAppIdentifier to compare. */ public static func == (lhs: MicrosoftTeamsAppIdentifier, rhs: MicrosoftTeamsAppIdentifier) -> Bool { return lhs.rawId == rhs.rawId } /** Returns a Boolean value that indicates whether the receiver is equal to another given object. This will automatically return false if object being compared to is not a MicrosoftTeamsAppIdentifier. - Parameter object The object with which to compare the receiver. */ override public func isEqual(_ object: Any?) -> Bool { guard let object = object as? MicrosoftTeamsAppIdentifier else { return false } return rawId == object.rawId } }