Commit 726c83d6 authored by Romain Bertozzi's avatar Romain Bertozzi

account: add ring account

This patch adds all the mechanism to add a Ring account thanks to the
daemon.
The AccountService now sees a lot more methods speaking to the daemon
itself.
The account addition is still in console only. This feature and its
callbacks must be improved next.

Tuleap: #1454
Change-Id: I72d2c8ce8daf38c0822beb55b6a42f2c76aeb761
Reviewed-by: default avatarSilbino Gonçalves Matado <silbino.gmatado@savoirfairelinux.com>
parent 59f7ea31
......@@ -21,6 +21,13 @@
import Foundation
/**
Errors that can be thrown when trying to build an AccountModel
*/
enum AccountModelError: Error {
case UnexpectedError
}
/**
A class representing an account.
*/
......@@ -42,10 +49,25 @@ class AccountModel {
}
init(withAccountId accountId: String,
details: Dictionary<String, String>?,
volatileDetails: Dictionary<String, String>?) {
details: Dictionary<String, String>,
volatileDetails: Dictionary<String, String>,
credentials: Array<Dictionary<String, String>>,
devices: Dictionary<String, String>) throws {
self.id = accountId
self.details = AccountConfigModel(withDetails: details)
self.volatileDetails = AccountConfigModel(withDetails: details)
for credential in credentials {
do {
let cred = try AccountCredentialsModel(withRawaData: credential)
credentialDetails.append(cred)
} catch CredentialsError.NotEnoughData {
print("Not enough data to build a credential object.")
throw CredentialsError.NotEnoughData
} catch {
print("Unexpected error.")
throw AccountModelError.UnexpectedError
}
}
self.devices = devices
}
}
......@@ -92,6 +92,9 @@ class CreateRingAccountViewModel {
self?.addAccountDisposable = self?.accountService
.sharedResponseStream
.subscribe(onNext:{ (event) in
if event.eventType == ServiceEventType.AccountAdded {
print("Account added.")
}
if event.eventType == ServiceEventType.AccountsChanged {
onSuccessCallback?()
}
......@@ -101,7 +104,13 @@ class CreateRingAccountViewModel {
self?.addAccountDisposable?.addDisposableTo((self?.disposeBag)!)
//~ Launch the action.
self?.accountService.addAccount()
do {
try self?.accountService.addRingAccount(withUsername: nil,
password: "coucou")
}
catch {
onErrorCallback?(error)
}
},
onError: { (error) in
onErrorCallback?(error)
......
......@@ -61,4 +61,8 @@
- (NSArray *)getAccountList;
- (NSArray *)getCredentials:(NSString *)accountID;
- (NSDictionary *)getKnownRingDevices:(NSString *)accountID;
@end
......@@ -94,6 +94,16 @@ static id <AccountAdapterDelegate> _delegate;
auto accountTemplate = getAccountTemplate(std::string([accountType UTF8String]));
return [Utils mapToDictionnary:accountTemplate];
}
- (NSArray *)getCredentials:(NSString *)accountID {
auto credentials = getCredentials(std::string([accountID UTF8String]));
return [Utils vectorOfMapsToArray:credentials];
}
- (NSDictionary *)getKnownRingDevices:(NSString *)accountID {
auto ringDevices = getKnownRingDevices(std::string([accountID UTF8String]));
return [Utils mapToDictionnary:ringDevices];
}
#pragma mark -
#pragma mark AccountAdapterDelegate
......
......@@ -92,7 +92,6 @@ class MeViewController: UIViewController, UITableViewDelegate, UITableViewDataSo
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
if indexPath.row == accountService.accounts.count {
accountService.addAccount()
accountTableView.reloadData()
}
}
......
......@@ -22,6 +22,11 @@
import RxCocoa
import RxSwift
enum AddAccountError: Error {
case TemplateNotConform
case UnknownError
}
class AccountsService: AccountAdapterDelegate {
// MARK: Private members
/**
......@@ -73,6 +78,8 @@ class AccountsService: AccountAdapterDelegate {
*/
var sharedResponseStream: Observable<ServiceEvent>
fileprivate(set) var currentAccount: AccountModel?
init(withAccountAdapter accountAdapter: AccountAdapter) {
self.accountList = []
......@@ -100,18 +107,175 @@ class AccountsService: AccountAdapterDelegate {
//}
}
func addAccount() {
// TODO: This need work for all account type
let details:NSMutableDictionary? = self.accountAdapter.getAccountTemplate("RING")
if details == nil {
print("Error retrieving Ring account template, can not continue");
return;
/**
Entry point to create a brand-new Ring account.
- Parameter username: the username chosen by the user, if any
- Parameter password: the password chosen by the user
- Throws: AddAccountError
*/
func addRingAccount(withUsername username: String?, password: String) throws {
do {
var ringDetails = try self.getRingInitialAccountDetails()
if username != nil {
ringDetails.updateValue(username!, forKey: ConfigKey.AccountRegisteredName.rawValue)
}
ringDetails.updateValue(password, forKey: ConfigKey.ArchivePassword.rawValue)
let accountId = self.accountAdapter.addAccount(ringDetails)
guard accountId != nil else {
throw AddAccountError.UnknownError
}
let account = self.getAccount(fromAccountId: accountId!)
if account == nil {
let details = self.getAccountDetails(fromAccountId: accountId!)
let volatileDetails = self.getVolatileAccountDetails(fromAccountId: accountId!)
let credentials = self.getAccountCredentials(fromAccountId: accountId!)
let devices = getKnownRingDevices(fromAccountId: accountId!)
let newAccount = try AccountModel(withAccountId: accountId!,
details: details,
volatileDetails: volatileDetails,
credentials: credentials,
devices: devices)
//TODO: set registration state as ready for a SIP account
self.setCurrentAccount(newAccount)
let accountModelHelper = AccountModelHelper(withAccount: newAccount)
var accountAddedEvent = ServiceEvent(withEventType: .AccountAdded)
accountAddedEvent.addEventInput(.Id, value: newAccount.id)
accountAddedEvent.addEventInput(.State, value: accountModelHelper.getRegistrationState())
self.responseStream.onNext(accountAddedEvent)
}
}
catch {
throw error
}
}
/**
Entry point to create a brand-new SIP account.
Not supported yet.
*/
fileprivate func addSipAccount() {
print("Not supported yet")
}
/**
Current account setter.
This will reorganize the order of the accounts. The current account needs to be first.
- Parameter account: the account to set as current.
*/
func setCurrentAccount(_ account: AccountModel) {
self.currentAccount = account
//TODO: handle the order of the list of accounts: current account must be first.
}
/**
Gets an account from the list of accounts handled by the application.
- Parameter id: the id of the account to get.
- Returns: the account if found, nil otherwise.
*/
func getAccount(fromAccountId id: String) -> AccountModel? {
for account in self.accountList {
if id.compare(account.id) == ComparisonResult.orderedSame {
return account
}
}
return nil
}
/**
Gets all the details of an account from the daemon.
- Parameter id: the id of the account.
- Returns: the details of the accounts.
*/
func getAccountDetails(fromAccountId id: String) -> Dictionary<String, String> {
let details: NSDictionary = accountAdapter.getAccountDetails(id) as NSDictionary
let accountDetails = details as NSDictionary? as? Dictionary<String, String> ?? nil
return accountDetails!
}
/**
Gets all the volatile details of an account from the daemon.
- Parameter id: the id of the account.
- Returns: the volatile details of the accounts.
*/
func getVolatileAccountDetails(fromAccountId id: String) -> Dictionary<String, String> {
let details: NSDictionary = accountAdapter.getVolatileAccountDetails(id) as NSDictionary
let accountDetails = details as NSDictionary? as? Dictionary<String, String> ?? nil
return accountDetails!
}
/**
Gets the credentials of an account from the daemon.
- Parameter id: the id of the account.
- Returns: the list of credentials.
*/
func getAccountCredentials(fromAccountId id: String) -> Array<Dictionary<String, String>> {
let creds: NSArray = accountAdapter.getCredentials(id) as NSArray
let credentials = creds as NSArray? as? Array<Dictionary<String, String>> ?? nil
return credentials!
}
/**
Gets the known Ring devices of an account from the daemon.
- Parameter id: the id of the account.
- Returns: the known Ring devices.
*/
func getKnownRingDevices(fromAccountId id: String) -> Dictionary<String, String> {
let devices: NSDictionary = accountAdapter.getKnownRingDevices(id) as NSDictionary
let ringDevices = devices as NSDictionary? as? Dictionary<String, String> ?? nil
return ringDevices!
}
/**
Gathers all the initial default details contained by any accounts, Ring or SIP.
- Returns the details.
*/
fileprivate func getInitialAccountDetails() throws -> Dictionary<String, String> {
let details: NSMutableDictionary = accountAdapter.getAccountTemplate(AccountType.Ring.rawValue)
var accountDetails = details as NSDictionary? as? Dictionary<String, String> ?? nil
if accountDetails == nil {
throw AddAccountError.TemplateNotConform
}
accountDetails!.updateValue("false", forKey: ConfigKey.VideoEnabled.rawValue)
accountDetails!.updateValue("sipinfo", forKey: ConfigKey.AccountDTMFType.rawValue)
return accountDetails!
}
/**
Gathers all the initial default details contained in a Ring accounts.
- Returns the details.
*/
fileprivate func getRingInitialAccountDetails() throws -> Dictionary<String, String> {
do {
var defaultDetails = try getInitialAccountDetails()
defaultDetails.updateValue("Ring", forKey: ConfigKey.AccountAlias.rawValue)
defaultDetails.updateValue("bootstrap.ring.cx", forKey: ConfigKey.AccountHostname.rawValue)
defaultDetails.updateValue("true", forKey: ConfigKey.AccountUpnpEnabled.rawValue)
return defaultDetails
} catch {
throw error
}
details!.setValue("iOS", forKey: "Account.alias")
details!.setValue("iOS", forKey: "Account.displayName")
let convertedDetails = details as NSDictionary? as? [AnyHashable: Any] ?? [:]
let addResult:String! = self.accountAdapter.addAccount(convertedDetails)
print(addResult);
}
func removeAccount(_ row: Int) {
......@@ -125,7 +289,7 @@ class AccountsService: AccountAdapterDelegate {
print("Accounts changed.")
reload()
let event = ServiceEvent.init(withEventType: .AccountsChanged)
let event = ServiceEvent(withEventType: .AccountsChanged)
self.responseStream.onNext(event)
}
}
......@@ -22,8 +22,10 @@
Events types that can be configured as identifier for the ServiceEvent.
- AccountChanged: the accounts have been changed daemon-side
- AccountAdded: an account has been added
*/
enum ServiceEventType {
case AccountAdded
case AccountsChanged
}
......@@ -32,6 +34,7 @@ enum ServiceEventType {
*/
enum ServiceEventInput {
case Id
case State
}
/**
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment