Commit 4361db30 authored by Romain Bertozzi's avatar Romain Bertozzi

accountModel: create model stack

This patch creates the stack of models that the AccountModel will need
to exist.

It also makes a little refactor to make the AccountModel very simple:
variables and init methods.
Some of these elements that have been moved are now gathered in a
dedicated helper that exposes some getters and setters.

Finally, some code is now commented in the high layers to allow code
compilation. This code refers to parts that are not designed or
written yet.

Tuleap: #1542
Change-Id: Ie52075c9f06d6efaa824caac457d30b859c17658
parent 3b289ad5
......@@ -30,6 +30,9 @@
02B22E031DF755F7000358C9 /* WalkthroughStoryboard.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 02B22E021DF755F7000358C9 /* WalkthroughStoryboard.storyboard */; };
02B22E091DF7585F000358C9 /* DaemonService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02B22E081DF7585F000358C9 /* DaemonService.swift */; };
02C9B63F1E1D4E8C00F82F0C /* ServiceEvent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02C9B63E1E1D4E8C00F82F0C /* ServiceEvent.swift */; };
02DD80C81E1EAD70009A3510 /* AccountConfigModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02DD80C71E1EAD70009A3510 /* AccountConfigModel.swift */; };
02DD80CA1E1EAF1A009A3510 /* AccountCredentialsModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02DD80C91E1EAF1A009A3510 /* AccountCredentialsModel.swift */; };
02DD80CD1E1EB2E4009A3510 /* ConfigKeyModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02DD80CC1E1EB2E4009A3510 /* ConfigKeyModel.swift */; };
02E1A0251DDE4ABA00D75B59 /* BoolStringExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 043866371D2304A700E06CE2 /* BoolStringExtension.swift */; };
043866211D218B1100E06CE2 /* AudioToolbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 043866201D218B1100E06CE2 /* AudioToolbox.framework */; };
043866331D22CE8C00E06CE2 /* MeViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 043866321D22CE8C00E06CE2 /* MeViewController.swift */; };
......@@ -97,6 +100,7 @@
04399B131D1C341A00E99CD9 /* libvpx.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 04399AE11D1C341A00E99CD9 /* libvpx.a */; };
04399B141D1C341A00E99CD9 /* libx264.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 04399AE21D1C341A00E99CD9 /* libx264.a */; };
04399B151D1C341A00E99CD9 /* libyaml-cpp.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 04399AE31D1C341A00E99CD9 /* libyaml-cpp.a */; };
5516C29F1E71CEFF009D3D2D /* AccountModelHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5516C29E1E71CEFF009D3D2D /* AccountModelHelper.swift */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
......@@ -144,6 +148,9 @@
02B22E021DF755F7000358C9 /* WalkthroughStoryboard.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; name = WalkthroughStoryboard.storyboard; path = Walkthrough/WalkthroughStoryboard.storyboard; sourceTree = "<group>"; };
02B22E081DF7585F000358C9 /* DaemonService.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = DaemonService.swift; path = Services/DaemonService.swift; sourceTree = "<group>"; };
02C9B63E1E1D4E8C00F82F0C /* ServiceEvent.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = ServiceEvent.swift; path = Services/ServiceEvent.swift; sourceTree = "<group>"; };
02DD80C71E1EAD70009A3510 /* AccountConfigModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = AccountConfigModel.swift; path = Account/AccountConfigModel.swift; sourceTree = "<group>"; };
02DD80C91E1EAF1A009A3510 /* AccountCredentialsModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = AccountCredentialsModel.swift; path = Account/AccountCredentialsModel.swift; sourceTree = "<group>"; };
02DD80CC1E1EB2E4009A3510 /* ConfigKeyModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = ConfigKeyModel.swift; path = Account/ConfigKeyModel.swift; sourceTree = "<group>"; };
043866201D218B1100E06CE2 /* AudioToolbox.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AudioToolbox.framework; path = System/Library/Frameworks/AudioToolbox.framework; sourceTree = SDKROOT; };
043866321D22CE8C00E06CE2 /* MeViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MeViewController.swift; sourceTree = "<group>"; };
043866351D22D06500E06CE2 /* AccountTableViewCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AccountTableViewCell.swift; sourceTree = "<group>"; };
......@@ -221,6 +228,7 @@
04399AE11D1C341A00E99CD9 /* libvpx.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libvpx.a; path = ../fat/lib/libvpx.a; sourceTree = "<group>"; };
04399AE21D1C341A00E99CD9 /* libx264.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libx264.a; path = ../fat/lib/libx264.a; sourceTree = "<group>"; };
04399AE31D1C341A00E99CD9 /* libyaml-cpp.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = "libyaml-cpp.a"; path = "../fat/lib/libyaml-cpp.a"; sourceTree = "<group>"; };
5516C29E1E71CEFF009D3D2D /* AccountModelHelper.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = AccountModelHelper.swift; path = Account/AccountModelHelper.swift; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
......@@ -371,7 +379,11 @@
isa = PBXGroup;
children = (
02B22DFA1DF755BB000358C9 /* AccountModel.swift */,
5516C29E1E71CEFF009D3D2D /* AccountModelHelper.swift */,
02B22DFB1DF755BB000358C9 /* CreateRingAccountViewModel.swift */,
02DD80C71E1EAD70009A3510 /* AccountConfigModel.swift */,
02DD80C91E1EAF1A009A3510 /* AccountCredentialsModel.swift */,
02DD80CC1E1EB2E4009A3510 /* ConfigKeyModel.swift */,
);
name = Account;
sourceTree = "<group>";
......@@ -719,9 +731,12 @@
0273C3051E0C68B100CF00BA /* CreateProfileViewController.swift in Sources */,
02E1A0251DDE4ABA00D75B59 /* BoolStringExtension.swift in Sources */,
04399AAC1D1C304300E99CD9 /* AccountAdapter.mm in Sources */,
02DD80C81E1EAD70009A3510 /* AccountConfigModel.swift in Sources */,
02B22E091DF7585F000358C9 /* DaemonService.swift in Sources */,
0273C3061E0C68B100CF00BA /* CreateRingAccountViewController.swift in Sources */,
02C9B63F1E1D4E8C00F82F0C /* ServiceEvent.swift in Sources */,
02DD80CD1E1EB2E4009A3510 /* ConfigKeyModel.swift in Sources */,
5516C29F1E71CEFF009D3D2D /* AccountModelHelper.swift in Sources */,
02B22E011DF755E5000358C9 /* MainTabBarViewController.swift in Sources */,
043999F71D1C2D9D00E99CD9 /* AppDelegate.swift in Sources */,
02B22DFC1DF755BB000358C9 /* AccountModel.swift in Sources */,
......@@ -730,6 +745,7 @@
02B22DFD1DF755BB000358C9 /* CreateRingAccountViewModel.swift in Sources */,
043999FA1D1C2D9D00E99CD9 /* Ring.xcdatamodeld in Sources */,
0438663B1D2313B700E06CE2 /* AccountDetailsViewController.swift in Sources */,
02DD80CA1E1EAF1A009A3510 /* AccountCredentialsModel.swift in Sources */,
0273C3081E0C68BF00CF00BA /* RoundedButton.swift in Sources */,
043866361D22D06500E06CE2 /* AccountTableViewCell.swift in Sources */,
04399AAD1D1C304300E99CD9 /* DRingAdapter.mm in Sources */,
......
/*
* Copyright (C) 2017 Savoir-faire Linux Inc.
*
* Author: Romain Bertozzi <romain.bertozzi@savoirfairelinux.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
/**
The different states that an account can have during time.
Contains :
- lifecycle account states
- errors concerning the state of the accounts
*/
enum AccountState: String {
case Registered = "REGISTERED"
case Ready = "READY"
case Unregistered = "UNREGISTERED"
case Trying = "TRYING"
case Error = "ERROR"
case ErrorGeneric = "ERROR_GENERIC"
case ErrorAuth = "ERROR_AUTH"
case ErrorNetwork = "ERROR_NETWORK"
case ErrorHost = "ERROR_HOST"
case ErrorConfStun = "ERROR_CONF_STUN"
case ErrorExistStun = "ERROR_EXIST_STUN"
case ErrorServiceUnavailable = "ERROR_SERVICE_UNAVAILABLE"
case ErrorNotAcceptable = "ERROR_NOT_ACCEPTABLE"
case ErrorRequestTimeout = "Request Timeout"
case ErrorNeedMigration = "ERROR_NEED_MIGRATION"
case Initializing = "INITIALIZING"
}
/**
The different types of account handled by Ring.
*/
enum AccountType: String {
case Ring = "RING"
case SIP = "SIP"
}
/**
A structure representing the configuration of an account.
The collection uses ConfigKeyModels as keys.
Its responsabilities:
- expose a clear interface to manipulate the configuration of an account
- keep this configuration
*/
struct AccountConfigModel {
/**
The collection of configuration elements.
*/
fileprivate var configValues = Dictionary<ConfigKeyModel, String>()
/**
Default constructor.
*/
init() {
//~ Empty initializer
}
/**
Constructor.
The keys of the configuration elements must be known from Ring to be taken in account.
- Parameter details: an optional collection of configuration elements
*/
init(withDetails details: Dictionary<String, String>?) {
if details != nil {
for (key, value) in details! {
if let confKey = ConfigKey(rawValue: key) {
let configKeyModel = ConfigKeyModel(withKey: confKey)
configValues.updateValue(value, forKey: configKeyModel)
} else {
//~ The key given in parameter is not known from Ring.
print("Can't find key", key)
}
}
}
}
/**
Getter for the configuration elements.
- Parameter configKeyModel: the ConfigKeyModel identifying the configuration element to get
- Returns: a boolean indicating the value of the configuration element.
*/
func getBool(forConfigKeyModel configKeyModel : ConfigKeyModel) -> Bool {
return "true".caseInsensitiveCompare(self.get(withConfigKeyModel: configKeyModel))
== ComparisonResult.orderedSame
}
/**
Getter for the configuration elements.
- Parameter configKeyModel: the ConfigKeyModel identifying the configuration element to get
- Returns: the value of the configuration element as a String. The result will be an empty
string in case of an issue.
*/
func get(withConfigKeyModel configKeyModel : ConfigKeyModel) -> String {
let value:String? = self.configValues[configKeyModel]
return value != nil ? value! : ""
}
}
/*
* Copyright (C) 2017 Savoir-faire Linux Inc.
*
* Author: Romain Bertozzi <romain.bertozzi@savoirfairelinux.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
/**
Errors that can be thrown when trying create an AccountCredentialsModel
- NotEnoughData: some information are missing to create the object
*/
enum CredentialsError: Error {
case NotEnoughData
}
/**
A structure representing the credentials of an account.
Its responsability:
- keep the credentials of an account.
*/
struct AccountCredentialsModel {
fileprivate(set) var username: String
fileprivate(set) var password: String
fileprivate(set) var realm: String
/**
Constructor.
- Parameters:
- username: the username of the account
- password: the password of the account
- realm : the realm of the account
*/
init(withUsername username: String, password: String, realm: String) {
self.username = username
self.password = password
self.realm = realm
}
/**
Constructor.
- Parameter raw: raw data to populate the credentials. This collection must contain all the
needed elements (username, password, realm).
- Throws: CredentialsError
*/
init(withRawaData raw: Dictionary<String, String>) throws {
let username = raw[ConfigKey.AccountUsername.rawValue]
let password = raw[ConfigKey.AccountPassword.rawValue]
let realm = raw[ConfigKey.AccountRealm.rawValue]
if username == nil || password == nil || realm == nil {
throw CredentialsError.NotEnoughData
}
self.username = username!
self.password = password!
self.realm = realm!
}
}
/*
* Copyright (C) 2016 Savoir-faire Linux Inc.
* Copyright (C) 2017 Savoir-faire Linux Inc.
*
* Author: Edric Ladent-Milaret <edric.ladent-milaret@savoirfairelinux.com>
* Author: Romain Bertozzi <romain.bertozzi@savoirfairelinux.com>
......@@ -21,107 +21,31 @@
import Foundation
enum AccountType: String {
case SIP = "SIP"
case RING = "RING"
}
struct AccountModel {
// MARK: - Keys
fileprivate let accountAliasKey = "Account.alias"
fileprivate let accountVideoEnabledKey = "Account.videoEnabled"
fileprivate let accountUsernameKey = "Account.username"
fileprivate let accountAutoAnswerKey = "Account.autoAnswer"
fileprivate let accountTurnEnabledKey = "TURN.enable"
fileprivate let accountTurnUsernameKey = "TURN.username"
fileprivate let accountTurnServerKey = "TURN.server"
fileprivate let accountTurnPasswordKey = "TURN.password"
fileprivate let accountEnabledKey = "Account.enable"
fileprivate let accountUpnpEnabledKey = "Account.upnpEnabled"
fileprivate let accountHostnameKey = "Account.hostname"
fileprivate let accountTypeKey = "Account.type"
fileprivate let accountDisplayNameKey = "Account.displayName"
// MARK: - Properties
/**
A class representing an account.
*/
class AccountModel {
// MARK: Public members
let id: String
fileprivate var details: Dictionary<String, String>
var alias: String? {
get {return details[accountAliasKey]}
set {details[accountAliasKey] = newValue}
}
var videoEnabled: Bool {
get {return (details[accountVideoEnabledKey]?.toBool())!}
set {details[accountVideoEnabledKey] = newValue.toString()}
}
var username: String? {
get {return details[accountUsernameKey]}
set {details[accountUsernameKey] = newValue}
}
var autoAnswer: Bool {
get {return (details[accountAutoAnswerKey]?.toBool())!}
set {details[accountAutoAnswerKey] = newValue.toString()}
}
var turnEnabled: Bool {
get {return (details[accountTurnEnabledKey]?.toBool())!}
set {details[accountTurnEnabledKey] = newValue.toString()}
}
var turnUsername: String? {
get {return details[accountTurnUsernameKey]}
set {details[accountTurnUsernameKey] = newValue}
}
var turnServer: String? {
get {return details[accountTurnServerKey]}
set {details[accountTurnServerKey] = newValue}
}
var turnPassword: String? {
get {return details[accountTurnPasswordKey]}
set {details[accountTurnPasswordKey] = newValue}
}
var isEnabled: Bool {
get {return (details[accountEnabledKey]?.toBool())!}
set {
details[accountEnabledKey] = newValue.toString()
(AccountAdapter.sharedManager() as AnyObject).setAccountActive(self.id, active: newValue)
}
}
var upnpEnabled: Bool {
get {return (details[accountUpnpEnabledKey]?.toBool())!}
set {details[accountUpnpEnabledKey] = newValue.toString()}
}
var accountHostname: String? {
get {return details[accountHostnameKey]}
set {details[accountHostnameKey] = newValue}
}
var accountType: AccountType {
get {return AccountType(rawValue: details[accountTypeKey]!)!}
set {details[accountTypeKey] = newValue.rawValue}
}
var displayName: String? {
get {return details[accountDisplayNameKey]}
set {details[accountDisplayNameKey] = newValue}
}
// MARK: - Init
init(accountID: String) {
id = accountID
details = (AccountAdapter.sharedManager() as AnyObject).getAccountDetails(id) as! Dictionary<String, String>
}
func save() {
(AccountAdapter.sharedManager() as AnyObject).setAccountDetails(id, details: details)
var registeringUsername = false
var devices = Dictionary<String,String>()
var details: AccountConfigModel
var volatileDetails: AccountConfigModel
var credentialDetails = Array<AccountCredentialsModel>()
// MARK: Init
init(withAccountId accountId: String) {
self.id = accountId
self.details = AccountConfigModel()
self.volatileDetails = AccountConfigModel()
}
init(withAccountId accountId: String,
details: Dictionary<String, String>?,
volatileDetails: Dictionary<String, String>?) {
self.id = accountId
self.details = AccountConfigModel(withDetails: details)
self.volatileDetails = AccountConfigModel(withDetails: details)
}
}
/*
* Copyright (C) 2017 Savoir-faire Linux Inc.
*
* Author: Romain Bertozzi <romain.bertozzi@savoirfairelinux.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
/**
A structure exposing the fields and methods for an Account
*/
struct AccountModelHelper {
fileprivate var account: AccountModel
/**
Constructor
- Parameter account: the account to expose
*/
init (withAccount account: AccountModel) {
self.account = account
}
/**
Getter exposing the type of the account.
- Returns: true if the account is considered as a SIP account
*/
func isAccountSip() -> Bool {
let sipString = AccountType.SIP.rawValue
let accountType = self.account.details
.get(withConfigKeyModel: ConfigKeyModel.init(withKey: .AccountType))
return sipString.compare(accountType) == ComparisonResult.orderedSame
}
/**
Getter exposing the type of the account.
- Returns: true if the account is considered as a Ring account
*/
func isAccountRing() -> Bool {
let ringString = AccountType.Ring.rawValue
let accountType = self.account.details
.get(withConfigKeyModel: ConfigKeyModel.init(withKey: .AccountType))
return ringString.compare(accountType) == ComparisonResult.orderedSame
}
/**
Getter exposing the enable state of the account.
- Returns: true if the account is enabled, false otherwise.
*/
func isEnabled() -> Bool {
return (self.account.details
.getBool(forConfigKeyModel: ConfigKeyModel.init(withKey: .AccountEnable)))
}
/**
Getter exposing the registration state of the account.
- Returns: the registration state of the account as a String.
*/
func getRegistrationState() -> String {
return (self.account.volatileDetails
.get(withConfigKeyModel: ConfigKeyModel.init(withKey: .AccountRegistrationStatus)))
}
/**
Getter exposing the error state of the account.
- Returns: true if the account is considered as being in error, false otherwise.
*/
func isInError() -> Bool {
let state = self.getRegistrationState()
return (state.compare(AccountState.Error.rawValue) == ComparisonResult.orderedSame) ||
(state.compare(AccountState.ErrorAuth.rawValue) == ComparisonResult.orderedSame) ||
(state.compare(AccountState.ErrorConfStun.rawValue) == ComparisonResult.orderedSame) ||
(state.compare(AccountState.ErrorExistStun.rawValue) == ComparisonResult.orderedSame) ||
(state.compare(AccountState.ErrorGeneric.rawValue) == ComparisonResult.orderedSame) ||
(state.compare(AccountState.ErrorHost.rawValue) == ComparisonResult.orderedSame) ||
(state.compare(AccountState.ErrorNetwork.rawValue) == ComparisonResult.orderedSame) ||
(state.compare(AccountState.ErrorNotAcceptable.rawValue) == ComparisonResult.orderedSame) ||
(state.compare(AccountState.ErrorServiceUnavailable.rawValue) == ComparisonResult.orderedSame) ||
(state.compare(AccountState.ErrorRequestTimeout.rawValue) == ComparisonResult.orderedSame)
}
/**
Setter on the credentials of the account.
- Parameter: a list of credentials to apply to the account. A nil parameter will clear the
credentials of the account.
*/
mutating func setCredentials(_ credentials: Array<Dictionary<String, String>>?) -> AccountModel {
self.account.credentialDetails.removeAll()
if credentials != nil {
for (credential) in credentials! {
do {
let accountCredentialModel = try AccountCredentialsModel(withRawaData: credential)
self.account.credentialDetails.append(accountCredentialModel)
}
catch CredentialsError.NotEnoughData {
print("Not enough data to create a credential")
}
catch {
print("Unexpected error")
}
}
}
return self.account
}
}
/*
* Copyright (C) 2017 Savoir-faire Linux Inc.
*
* Author: Romain Bertozzi <romain.bertozzi@savoirfairelinux.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
/**
The different configuration keys handled by Ring.
*/
enum ConfigKey: String {
case Mailbox = "Account.mailbox"
case RegistrationExpire = "Account.registrationExpire"
case CredentialNumber = "Credential.count"
case AccountDTMFType = "Account.dtmfType"
case RingtonePath = "Account.ringtonePath"
case RingtoneEnabled = "Account.ringtoneEnabled"
case KeepAliveEnabled = "Account.keepAliveEnabled"
case LocalInterface = "Account.localInterface"
case PublishedSameAsLocal = "Account.publishedSameAsLocal"
case LocalPort = "Account.localPort"
case PublishedPort = "Account.publishedPort"
case PublishedAddress = "Account.publishedAddress"
case StunServer = "STUN.server"
case StunEnable = "STUN.enable"
case TurnServer = "TURN.server"
case TurnEnable = "TURN.enable"
case TurnUsername = "TURN.username"
case TurnPassword = "TURN.password"
case TurnRealm = "TURN.realm"
case AudioPortMin = "Account.audioPortMin"
case AudioPortMax = "Account.audioPortMax"
case AccountUserAgent = "Account.useragent"
case AccountUpnpEnabled = "Account.upnpEnabled"
case AccountRouteSet = "Account.routeset"
case AccountAutoAnswer = "Account.autoAnswer"
case AccountAlias = "Account.alias"
case AccountHostname = "Account.hostname"
case AccountUsername = "Account.username"
case AccountPassword = "Account.password"
case AccountRealm = "Account.realm"
case AccountType = "Account.type"
case AccountEnable = "Account.enable"
case AccountActive = "Account.active"
case AccountDeviceId = "Account.deviceID"
case VideoEnabled = "Account.videoEnabled"
case VideoPortMin = "Account.videoPortMin"
case VideoPortMax = "Account.videoPortMax"
case PresenceEnabled = "Account.presenceEnabled"
case ArchivePassword = "Account.archivePassword"
case ArchivePIN = "Account.archivePIN"