// // Copyright 2020 Signal Messenger, LLC // SPDX-License-Identifier: AGPL-3.0-only // import Foundation @objc public enum GroupV2Access: UInt, Codable, CustomStringConvertible { case unknown = 0 case any case member case administrator case unsatisfiable public static func access(forProtoAccess value: GroupsProtoAccessControlAccessRequired) -> GroupV2Access { switch value { case .any: return .any case .member: return .member case .administrator: return .administrator case .unsatisfiable: return .unsatisfiable default: return .unknown } } public var protoAccess: GroupsProtoAccessControlAccessRequired { switch self { case .any: return .any case .member: return .member case .administrator: return .administrator case .unsatisfiable: return .unsatisfiable default: return .unknown } } // MARK: - CustomStringConvertible public var description: String { switch self { case .unknown: return "unknown" case .any: return "any" case .member: return "member" case .administrator: return "administrator" case .unsatisfiable: return "unsatisfiable" } } } // MARK: - // This class is immutable. @objc public class GroupAccess: MTLModel { @objc public var members: GroupV2Access = .unknown @objc public var attributes: GroupV2Access = .unknown @objc public var addFromInviteLink: GroupV2Access = .unknown public init(members: GroupV2Access, attributes: GroupV2Access, addFromInviteLink: GroupV2Access) { // Ensure we always have valid values. self.members = Self.filter(forMembers: members) self.attributes = Self.filter(forAttributes: attributes) self.addFromInviteLink = Self.filter(forAddFromInviteLink: addFromInviteLink) super.init() } public static func filter(forMembers value: GroupV2Access) -> GroupV2Access { switch value { case .member, .administrator: return value default: owsFailDebug("Invalid access level: \(value)") return .unknown } } public static func filter(forAttributes value: GroupV2Access) -> GroupV2Access { switch value { case .member, .administrator: return value default: owsFailDebug("Invalid access level: \(value)") return .unknown } } public static func filter(forAddFromInviteLink value: GroupV2Access) -> GroupV2Access { switch value { case .unknown: // .unknown is valid for groups created before group links were added. return value case .unsatisfiable, .administrator, .any: return value default: owsFailDebug("Invalid access level: \(value)") return .unknown } } @objc public override init() { super.init() } @objc public required init!(coder: NSCoder) { super.init(coder: coder) } @objc public required init(dictionary dictionaryValue: [String: Any]!) throws { try super.init(dictionary: dictionaryValue) } @objc public static var allAccess: GroupAccess { return GroupAccess(members: .member, attributes: .member, addFromInviteLink: .any) } @objc public static var adminOnly: GroupAccess { return GroupAccess(members: .administrator, attributes: .administrator, addFromInviteLink: .administrator) } @objc public static var defaultForV1: GroupAccess { return GroupAccess(members: .member, attributes: .member, addFromInviteLink: .unsatisfiable) } @objc public static var defaultForV2: GroupAccess { return GroupAccess(members: .member, attributes: .member, addFromInviteLink: .unsatisfiable) } public override var debugDescription: String { return "[members: \(members), attributes: \(attributes), addFromInviteLink: \(addFromInviteLink), ]" } } // MARK: - @objc public extension GroupAccess { var canJoinFromInviteLink: Bool { // TODO: Should this include .member? (addFromInviteLink == .any || addFromInviteLink == .administrator) } }