serval-dna/swift-client-api/package/Sources/keyring.swift
Andrew Bettison 12bc773d4d Refactor Keyring Swift API
Factor JSON table parsing into a separate method of ServalRestfulClient
so it can be re-used by other APIs.
2018-04-09 07:50:42 +09:30

205 lines
9.0 KiB
Swift

/*
Serval DNA Swift API
Copyright (C) 2016-2018 Flinders University
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 2
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.
*/
import Foundation
public class ServalKeyring {
public struct Identity {
public let sid : SubscriberId
public let identity : SubscriberId
public let did : String?
public let name : String?
}
private static func unpackIdentity(fromJsonDict json: [String: Any?]) throws -> Identity
{
guard let sidany = json["sid"] else {
throw ServalRestfulClient.Exception.invalidJson(reason: "missing \"sid\" element")
}
guard let sidhex = sidany as? String else {
throw ServalRestfulClient.Exception.invalidJson(reason: "sid value is not String")
}
guard let sid = SubscriberId(fromHex: sidhex) else {
throw ServalRestfulClient.Exception.invalidJson(reason: "sid value is not hex: \(sidhex)")
}
guard let idany = json["identity"] else {
throw ServalRestfulClient.Exception.invalidJson(reason: "missing \"identity\" element")
}
guard let idhex = idany as? String else {
throw ServalRestfulClient.Exception.invalidJson(reason: "identity value is not String")
}
guard let identity = SubscriberId(fromHex: idhex) else {
throw ServalRestfulClient.Exception.invalidJson(reason: "identity value is not hex: \(idhex)")
}
var did: String?
if let value = json["did"], value != nil {
guard let text = value! as? String else {
throw ServalRestfulClient.Exception.invalidJson(reason: "did value is not String")
}
if !text.isEmpty {
did = text
}
}
var name: String?
if let value = json["name"], value != nil {
guard let text = value! as? String else {
throw ServalRestfulClient.Exception.invalidJson(reason: "name value is not String")
}
if !text.isEmpty {
name = text
}
}
return Identity(sid: sid, identity: identity, did: did, name: name)
}
public static func listIdentities(client: ServalRestfulClient = ServalRestfulClient(),
pin: String? = nil,
completionHandler: @escaping ([Identity]?, Error?) -> Void)
-> ServalRestfulClient.Request
{
var param = [String: String]()
if pin != nil { param["pin"] = pin }
return client.createRequest(verb: "GET",
path: "restful/keyring/identities.json",
query: param) { (statusCode, json, error) in
if let error = error {
completionHandler(nil, error)
return
}
guard statusCode! == 200 else {
completionHandler(nil, ServalRestfulClient.Exception.requestFailed(statusCode: statusCode!))
return
}
var identities : [Identity] = []
do {
for row in try ServalRestfulClient.transformJsonTable(json: json) {
identities.append(try unpackIdentity(fromJsonDict: row))
}
}
catch let e {
completionHandler(nil, e)
return
}
completionHandler(identities, nil)
}!
}
private static func singleIdentityRequest(client: ServalRestfulClient = ServalRestfulClient(),
verb: String,
path: String,
query: [String: String] = [:],
successStatusCodes: Set<Int> = [200],
completionHandler: @escaping (Identity?, Error?) -> Void)
-> ServalRestfulClient.Request
{
return client.createRequest(verb:verb, path: path, query: query) { (statusCode, json, error) in
if let error = error {
completionHandler(nil, error)
return
}
do {
guard successStatusCodes.contains(statusCode!) else {
throw ServalRestfulClient.Exception.requestFailed(statusCode: statusCode!)
}
guard let json_top = json as? [String: Any] else {
throw ServalRestfulClient.Exception.invalidJson(reason: "root is not JSON object")
}
guard let json_identity = json_top["identity"] as? [String: Any] else {
completionHandler(nil, ServalRestfulClient.Exception.invalidJson(reason: "'identity' is not JSON object"))
return
}
completionHandler(try unpackIdentity(fromJsonDict: json_identity), nil)
}
catch let e {
completionHandler(nil, e)
}
}!
}
public static func addIdentity(client: ServalRestfulClient = ServalRestfulClient(),
did: String? = nil,
name: String? = nil,
pin: String? = nil,
completionHandler: @escaping (Identity?, Error?) -> Void)
-> ServalRestfulClient.Request
{
var param = [String: String]()
if did != nil { param["did"] = did }
if name != nil { param["name"] = name }
if pin != nil { param["pin"] = pin }
return self.singleIdentityRequest(client: client,
verb: "POST",
path: "restful/keyring/add",
query: param,
successStatusCodes: [201],
completionHandler: completionHandler)
}
public static func getIdentity(client: ServalRestfulClient = ServalRestfulClient(),
sid: SubscriberId,
pin: String? = nil,
completionHandler: @escaping (Identity?, Error?) -> Void)
-> ServalRestfulClient.Request
{
var param = [String: String]()
if pin != nil { param["pin"] = pin }
return self.singleIdentityRequest(client: client,
verb: "GET",
path: "restful/keyring/\(sid.hexUpper)",
query: param,
completionHandler: completionHandler)
}
public static func removeIdentity(client: ServalRestfulClient = ServalRestfulClient(),
sid: SubscriberId,
pin: String? = nil,
completionHandler: @escaping (Identity?, Error?) -> Void)
-> ServalRestfulClient.Request
{
var param = [String: String]()
if pin != nil { param["pin"] = pin }
return self.singleIdentityRequest(client: client,
verb: "DELETE",
path: "restful/keyring/\(sid.hexUpper)",
query: param,
completionHandler: completionHandler)
}
public static func setIdentity(client: ServalRestfulClient = ServalRestfulClient(),
sid: SubscriberId,
did: String? = nil,
name: String? = nil,
pin: String? = nil,
completionHandler: @escaping (Identity?, Error?) -> Void)
-> ServalRestfulClient.Request
{
var param = [String: String]()
if did != nil { param["did"] = did }
if name != nil { param["name"] = name }
if pin != nil { param["pin"] = pin }
return self.singleIdentityRequest(client: client,
verb: "PATCH",
path: "restful/keyring/\(sid.hexUpper)",
query: param,
completionHandler: completionHandler)
}
}