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
}
}