mirror of
https://github.com/appwrite/sdk-for-apple.git
synced 2026-04-07 19:17:50 +00:00
Merge pull request #108 from appwrite/dev
This commit is contained in:
@@ -1,5 +1,17 @@
|
|||||||
# Change Log
|
# Change Log
|
||||||
|
|
||||||
|
## 16.0.0
|
||||||
|
|
||||||
|
* [BREAKING] Changed `$sequence` type from `Int` to `String` for `Row` and `Document` models
|
||||||
|
* Added impersonation support: `setImpersonateUserId()`, `setImpersonateUserEmail()`, `setImpersonateUserPhone()` on `Client`
|
||||||
|
* Added `impersonator` and `impersonatorUserId` optional fields to `User` model
|
||||||
|
* Updated `Log` model field descriptions to clarify impersonation behavior for `userId`, `userEmail`, `userName`
|
||||||
|
* Fixed `NIOFoundationCompat` import to be conditional with `#if canImport` for platform compatibility
|
||||||
|
* Fixed `ByteBuffer` to `Data` conversion to use `readableBytesView` throughout (Client and WebSocket handler)
|
||||||
|
* Fixed `ByteBuffer(data:)` calls replaced with `ByteBuffer(bytes:)` for file/data loading
|
||||||
|
* Updated `X-Appwrite-Response-Format` header to `1.9.0`
|
||||||
|
* Updated API version badge to `1.9.0` and compatibility note to server version `1.9.x` in README
|
||||||
|
|
||||||
## 15.0.0
|
## 15.0.0
|
||||||
|
|
||||||
* Breaking: RealtimeChannel API required explicit IDs and threw errors.
|
* Breaking: RealtimeChannel API required explicit IDs and threw errors.
|
||||||
|
|||||||
@@ -2,12 +2,12 @@
|
|||||||
|
|
||||||

|

|
||||||

|

|
||||||

|

|
||||||
[](https://travis-ci.com/appwrite/sdk-generator)
|
[](https://travis-ci.com/appwrite/sdk-generator)
|
||||||
[](https://twitter.com/appwrite)
|
[](https://twitter.com/appwrite)
|
||||||
[](https://appwrite.io/discord)
|
[](https://appwrite.io/discord)
|
||||||
|
|
||||||
**This SDK is compatible with Appwrite server version latest. For older versions, please check [previous releases](https://github.com/appwrite/sdk-for-apple/releases).**
|
**This SDK is compatible with Appwrite server version 1.9.x. For older versions, please check [previous releases](https://github.com/appwrite/sdk-for-apple/releases).**
|
||||||
|
|
||||||
Appwrite is an open-source backend as a service server that abstracts and simplifies complex and repetitive development tasks behind a very simple to use REST API. Appwrite aims to help you develop your apps faster and in a more secure way. Use the Apple SDK to integrate your app with the Appwrite server to easily start interacting with all of Appwrite backend APIs and tools. For full API documentation and tutorials go to [https://appwrite.io/docs](https://appwrite.io/docs)
|
Appwrite is an open-source backend as a service server that abstracts and simplifies complex and repetitive development tasks behind a very simple to use REST API. Appwrite aims to help you develop your apps faster and in a more secure way. Use the Apple SDK to integrate your app with the Appwrite server to easily start interacting with all of Appwrite backend APIs and tools. For full API documentation and tutorials go to [https://appwrite.io/docs](https://appwrite.io/docs)
|
||||||
|
|
||||||
@@ -31,7 +31,7 @@ Add the package to your `Package.swift` dependencies:
|
|||||||
|
|
||||||
```swift
|
```swift
|
||||||
dependencies: [
|
dependencies: [
|
||||||
.package(url: "git@github.com:appwrite/sdk-for-apple.git", from: "15.0.0"),
|
.package(url: "git@github.com:appwrite/sdk-for-apple.git", from: "16.0.0"),
|
||||||
],
|
],
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
import NIO
|
import NIO
|
||||||
import NIOCore
|
import NIOCore
|
||||||
|
#if canImport(NIOFoundationCompat)
|
||||||
import NIOFoundationCompat
|
import NIOFoundationCompat
|
||||||
|
#endif
|
||||||
import NIOSSL
|
import NIOSSL
|
||||||
import Foundation
|
import Foundation
|
||||||
import AsyncHTTPClient
|
import AsyncHTTPClient
|
||||||
@@ -24,8 +26,8 @@ open class Client {
|
|||||||
"x-sdk-name": "Apple",
|
"x-sdk-name": "Apple",
|
||||||
"x-sdk-platform": "client",
|
"x-sdk-platform": "client",
|
||||||
"x-sdk-language": "apple",
|
"x-sdk-language": "apple",
|
||||||
"x-sdk-version": "15.0.0",
|
"x-sdk-version": "16.0.0",
|
||||||
"x-appwrite-response-format": "1.8.0"
|
"x-appwrite-response-format": "1.9.0"
|
||||||
]
|
]
|
||||||
|
|
||||||
internal var config: [String: String] = [:]
|
internal var config: [String: String] = [:]
|
||||||
@@ -162,6 +164,51 @@ open class Client {
|
|||||||
return self
|
return self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Set ImpersonateUserId
|
||||||
|
///
|
||||||
|
/// Impersonate a user by ID on an already user-authenticated request. Requires the current request to be authenticated as a user with impersonator capability; X-Appwrite-Key alone is not sufficient. Impersonator users are intentionally granted users.read so they can discover a target before impersonation begins. Internal audit logs still attribute actions to the original impersonator and record the impersonated target only in internal audit payload data.
|
||||||
|
///
|
||||||
|
/// @param String value
|
||||||
|
///
|
||||||
|
/// @return Client
|
||||||
|
///
|
||||||
|
open func setImpersonateUserId(_ value: String) -> Client {
|
||||||
|
config["impersonateuserid"] = value
|
||||||
|
_ = addHeader(key: "X-Appwrite-Impersonate-User-Id", value: value)
|
||||||
|
return self
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Set ImpersonateUserEmail
|
||||||
|
///
|
||||||
|
/// Impersonate a user by email on an already user-authenticated request. Requires the current request to be authenticated as a user with impersonator capability; X-Appwrite-Key alone is not sufficient. Impersonator users are intentionally granted users.read so they can discover a target before impersonation begins. Internal audit logs still attribute actions to the original impersonator and record the impersonated target only in internal audit payload data.
|
||||||
|
///
|
||||||
|
/// @param String value
|
||||||
|
///
|
||||||
|
/// @return Client
|
||||||
|
///
|
||||||
|
open func setImpersonateUserEmail(_ value: String) -> Client {
|
||||||
|
config["impersonateuseremail"] = value
|
||||||
|
_ = addHeader(key: "X-Appwrite-Impersonate-User-Email", value: value)
|
||||||
|
return self
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Set ImpersonateUserPhone
|
||||||
|
///
|
||||||
|
/// Impersonate a user by phone on an already user-authenticated request. Requires the current request to be authenticated as a user with impersonator capability; X-Appwrite-Key alone is not sufficient. Impersonator users are intentionally granted users.read so they can discover a target before impersonation begins. Internal audit logs still attribute actions to the original impersonator and record the impersonated target only in internal audit payload data.
|
||||||
|
///
|
||||||
|
/// @param String value
|
||||||
|
///
|
||||||
|
/// @return Client
|
||||||
|
///
|
||||||
|
open func setImpersonateUserPhone(_ value: String) -> Client {
|
||||||
|
config["impersonateuserphone"] = value
|
||||||
|
_ = addHeader(key: "X-Appwrite-Impersonate-User-Phone", value: value)
|
||||||
|
return self
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
///
|
///
|
||||||
/// Set self signed
|
/// Set self signed
|
||||||
@@ -378,7 +425,7 @@ open class Client {
|
|||||||
if data.readableBytes == 0 {
|
if data.readableBytes == 0 {
|
||||||
return true as! T
|
return true as! T
|
||||||
}
|
}
|
||||||
let dict = try JSONSerialization.jsonObject(with: data) as? [String: Any]
|
let dict = try JSONSerialization.jsonObject(with: Data(data.readableBytesView)) as? [String: Any]
|
||||||
|
|
||||||
return converter?(dict!) ?? dict! as! T
|
return converter?(dict!) ?? dict! as! T
|
||||||
}
|
}
|
||||||
@@ -388,7 +435,7 @@ open class Client {
|
|||||||
var responseString = ""
|
var responseString = ""
|
||||||
|
|
||||||
do {
|
do {
|
||||||
let dict = try JSONSerialization.jsonObject(with: data) as? [String: Any]
|
let dict = try JSONSerialization.jsonObject(with: Data(data.readableBytesView)) as? [String: Any]
|
||||||
|
|
||||||
message = dict?["message"] as? String ?? response.status.reasonPhrase
|
message = dict?["message"] as? String ?? response.status.reasonPhrase
|
||||||
type = dict?["type"] as? String ?? ""
|
type = dict?["type"] as? String ?? ""
|
||||||
@@ -420,9 +467,9 @@ open class Client {
|
|||||||
|
|
||||||
switch(input.sourceType) {
|
switch(input.sourceType) {
|
||||||
case "path":
|
case "path":
|
||||||
input.data = ByteBuffer(data: try! Data(contentsOf: URL(fileURLWithPath: input.path)))
|
input.data = ByteBuffer(bytes: try! Data(contentsOf: URL(fileURLWithPath: input.path)))
|
||||||
case "data":
|
case "data":
|
||||||
input.data = ByteBuffer(data: input.data as! Data)
|
input.data = ByteBuffer(bytes: input.data as! Data)
|
||||||
default:
|
default:
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,8 @@
|
|||||||
import Foundation
|
import Foundation
|
||||||
import NIO
|
import NIO
|
||||||
|
#if canImport(NIOFoundationCompat)
|
||||||
|
import NIOFoundationCompat
|
||||||
|
#endif
|
||||||
import NIOHTTP1
|
import NIOHTTP1
|
||||||
import NIOWebSocket
|
import NIOWebSocket
|
||||||
|
|
||||||
@@ -18,7 +21,7 @@ class MessageHandler {
|
|||||||
self.client = client
|
self.client = client
|
||||||
self.buffer = ByteBufferAllocator().buffer(capacity: 0)
|
self.buffer = ByteBufferAllocator().buffer(capacity: 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
private func unmaskedData(frame: WebSocketFrame) -> ByteBuffer {
|
private func unmaskedData(frame: WebSocketFrame) -> ByteBuffer {
|
||||||
var frameData = frame.data
|
var frameData = frame.data
|
||||||
if let maskingKey = frame.maskKey {
|
if let maskingKey = frame.maskKey {
|
||||||
@@ -31,7 +34,7 @@ class MessageHandler {
|
|||||||
extension MessageHandler: ChannelInboundHandler, RemovableChannelHandler {
|
extension MessageHandler: ChannelInboundHandler, RemovableChannelHandler {
|
||||||
|
|
||||||
typealias InboundIn = WebSocketFrame
|
typealias InboundIn = WebSocketFrame
|
||||||
|
|
||||||
public func channelRead(context: ChannelHandlerContext, data: NIOAny) {
|
public func channelRead(context: ChannelHandlerContext, data: NIOAny) {
|
||||||
let frame = self.unwrapInboundIn(data)
|
let frame = self.unwrapInboundIn(data)
|
||||||
switch frame.opcode {
|
switch frame.opcode {
|
||||||
@@ -56,18 +59,14 @@ extension MessageHandler: ChannelInboundHandler, RemovableChannelHandler {
|
|||||||
case .binary:
|
case .binary:
|
||||||
let data = unmaskedData(frame: frame)
|
let data = unmaskedData(frame: frame)
|
||||||
if frame.fin {
|
if frame.fin {
|
||||||
guard let binaryData = data.getData(at: 0, length: data.readableBytes) else {
|
let binaryData = Data(data.readableBytesView)
|
||||||
return
|
|
||||||
}
|
|
||||||
if let delegate = client.delegate {
|
if let delegate = client.delegate {
|
||||||
try! delegate.onMessage(data: binaryData)
|
try! delegate.onMessage(data: binaryData)
|
||||||
} else {
|
} else {
|
||||||
client.onBinaryMessage(binaryData)
|
client.onBinaryMessage(binaryData)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
guard let binaryData = data.getData(at: 0, length: data.readableBytes) else {
|
let binaryData = Data(data.readableBytesView)
|
||||||
return
|
|
||||||
}
|
|
||||||
binaryBuffer = binaryData
|
binaryBuffer = binaryData
|
||||||
}
|
}
|
||||||
case .continuation:
|
case .continuation:
|
||||||
@@ -92,9 +91,7 @@ extension MessageHandler: ChannelInboundHandler, RemovableChannelHandler {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if frame.fin {
|
if frame.fin {
|
||||||
guard let binaryData = data.getData(at: 0, length: data.readableBytes) else {
|
let binaryData = Data(data.readableBytesView)
|
||||||
return
|
|
||||||
}
|
|
||||||
binaryBuffer.append(binaryData)
|
binaryBuffer.append(binaryData)
|
||||||
if let delegate = client.delegate {
|
if let delegate = client.delegate {
|
||||||
try! delegate.onMessage(data: binaryBuffer)
|
try! delegate.onMessage(data: binaryBuffer)
|
||||||
@@ -102,9 +99,7 @@ extension MessageHandler: ChannelInboundHandler, RemovableChannelHandler {
|
|||||||
client.onBinaryMessage(binaryBuffer)
|
client.onBinaryMessage(binaryBuffer)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
guard let binaryData = data.getData(at: 0, length: data.readableBytes) else {
|
let binaryData = Data(data.readableBytesView)
|
||||||
return
|
|
||||||
}
|
|
||||||
binaryBuffer.append(binaryData)
|
binaryBuffer.append(binaryData)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -114,18 +109,18 @@ extension MessageHandler: ChannelInboundHandler, RemovableChannelHandler {
|
|||||||
}
|
}
|
||||||
let data = frame.data
|
let data = frame.data
|
||||||
if !client.closeSent {
|
if !client.closeSent {
|
||||||
client.close(data: frame.data.getData(at: 0, length: frame.data.readableBytes) ?? Data())
|
client.close(data: Data(frame.data.readableBytesView))
|
||||||
}
|
}
|
||||||
if let delegate = client.delegate {
|
if let delegate = client.delegate {
|
||||||
delegate.onClose(channel: context.channel, data: data.getData(at: 0, length: data.readableBytes)!)
|
delegate.onClose(channel: context.channel, data: Data(data.readableBytesView))
|
||||||
} else {
|
} else {
|
||||||
client.onClose(context.channel, data.getData(at: 0, length: data.readableBytes)!)
|
client.onClose(context.channel, Data(data.readableBytesView))
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public func errorCaught(context: ChannelHandlerContext, error: Swift.Error) {
|
public func errorCaught(context: ChannelHandlerContext, error: Swift.Error) {
|
||||||
if client.delegate != nil {
|
if client.delegate != nil {
|
||||||
try! client.delegate?.onError(error: error, status: nil)
|
try! client.delegate?.onError(error: error, status: nil)
|
||||||
|
|||||||
@@ -1,9 +1,11 @@
|
|||||||
import Foundation
|
import Foundation
|
||||||
import NIO
|
import NIO
|
||||||
|
#if canImport(NIOFoundationCompat)
|
||||||
|
import NIOFoundationCompat
|
||||||
|
#endif
|
||||||
import NIOHTTP1
|
import NIOHTTP1
|
||||||
import NIOWebSocket
|
import NIOWebSocket
|
||||||
import Dispatch
|
import Dispatch
|
||||||
import NIOFoundationCompat
|
|
||||||
import NIOSSL
|
import NIOSSL
|
||||||
|
|
||||||
public let WEBSOCKET_LOCKER_QUEUE = "SyncLocker"
|
public let WEBSOCKET_LOCKER_QUEUE = "SyncLocker"
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ open class Document<T : Codable>: Codable {
|
|||||||
/// Document ID.
|
/// Document ID.
|
||||||
public let id: String
|
public let id: String
|
||||||
/// Document sequence ID.
|
/// Document sequence ID.
|
||||||
public let sequence: Int
|
public let sequence: String
|
||||||
/// Collection ID.
|
/// Collection ID.
|
||||||
public let collectionId: String
|
public let collectionId: String
|
||||||
/// Database ID.
|
/// Database ID.
|
||||||
@@ -34,7 +34,7 @@ open class Document<T : Codable>: Codable {
|
|||||||
|
|
||||||
init(
|
init(
|
||||||
id: String,
|
id: String,
|
||||||
sequence: Int,
|
sequence: String,
|
||||||
collectionId: String,
|
collectionId: String,
|
||||||
databaseId: String,
|
databaseId: String,
|
||||||
createdAt: String,
|
createdAt: String,
|
||||||
@@ -56,7 +56,7 @@ open class Document<T : Codable>: Codable {
|
|||||||
let container = try decoder.container(keyedBy: CodingKeys.self)
|
let container = try decoder.container(keyedBy: CodingKeys.self)
|
||||||
|
|
||||||
self.id = try container.decode(String.self, forKey: .id)
|
self.id = try container.decode(String.self, forKey: .id)
|
||||||
self.sequence = try container.decode(Int.self, forKey: .sequence)
|
self.sequence = try container.decode(String.self, forKey: .sequence)
|
||||||
self.collectionId = try container.decode(String.self, forKey: .collectionId)
|
self.collectionId = try container.decode(String.self, forKey: .collectionId)
|
||||||
self.databaseId = try container.decode(String.self, forKey: .databaseId)
|
self.databaseId = try container.decode(String.self, forKey: .databaseId)
|
||||||
self.createdAt = try container.decode(String.self, forKey: .createdAt)
|
self.createdAt = try container.decode(String.self, forKey: .createdAt)
|
||||||
@@ -94,7 +94,7 @@ open class Document<T : Codable>: Codable {
|
|||||||
public static func from(map: [String: Any] ) -> Document {
|
public static func from(map: [String: Any] ) -> Document {
|
||||||
return Document(
|
return Document(
|
||||||
id: map["$id"] as? String ?? "",
|
id: map["$id"] as? String ?? "",
|
||||||
sequence: map["$sequence"] as? Int ?? 0,
|
sequence: map["$sequence"] as? String ?? "",
|
||||||
collectionId: map["$collectionId"] as? String ?? "",
|
collectionId: map["$collectionId"] as? String ?? "",
|
||||||
databaseId: map["$databaseId"] as? String ?? "",
|
databaseId: map["$databaseId"] as? String ?? "",
|
||||||
createdAt: map["$createdAt"] as? String ?? "",
|
createdAt: map["$createdAt"] as? String ?? "",
|
||||||
|
|||||||
@@ -30,11 +30,11 @@ open class Log: Codable {
|
|||||||
|
|
||||||
/// Event name.
|
/// Event name.
|
||||||
public let event: String
|
public let event: String
|
||||||
/// User ID.
|
/// User ID of the actor recorded for this log. During impersonation, this is the original impersonator, not the impersonated target user.
|
||||||
public let userId: String
|
public let userId: String
|
||||||
/// User Email.
|
/// User email of the actor recorded for this log. During impersonation, this is the original impersonator.
|
||||||
public let userEmail: String
|
public let userEmail: String
|
||||||
/// User Name.
|
/// User name of the actor recorded for this log. During impersonation, this is the original impersonator.
|
||||||
public let userName: String
|
public let userName: String
|
||||||
/// API mode when event triggered.
|
/// API mode when event triggered.
|
||||||
public let mode: String
|
public let mode: String
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ open class Row<T : Codable>: Codable {
|
|||||||
/// Row ID.
|
/// Row ID.
|
||||||
public let id: String
|
public let id: String
|
||||||
/// Row sequence ID.
|
/// Row sequence ID.
|
||||||
public let sequence: Int
|
public let sequence: String
|
||||||
/// Table ID.
|
/// Table ID.
|
||||||
public let tableId: String
|
public let tableId: String
|
||||||
/// Database ID.
|
/// Database ID.
|
||||||
@@ -34,7 +34,7 @@ open class Row<T : Codable>: Codable {
|
|||||||
|
|
||||||
init(
|
init(
|
||||||
id: String,
|
id: String,
|
||||||
sequence: Int,
|
sequence: String,
|
||||||
tableId: String,
|
tableId: String,
|
||||||
databaseId: String,
|
databaseId: String,
|
||||||
createdAt: String,
|
createdAt: String,
|
||||||
@@ -56,7 +56,7 @@ open class Row<T : Codable>: Codable {
|
|||||||
let container = try decoder.container(keyedBy: CodingKeys.self)
|
let container = try decoder.container(keyedBy: CodingKeys.self)
|
||||||
|
|
||||||
self.id = try container.decode(String.self, forKey: .id)
|
self.id = try container.decode(String.self, forKey: .id)
|
||||||
self.sequence = try container.decode(Int.self, forKey: .sequence)
|
self.sequence = try container.decode(String.self, forKey: .sequence)
|
||||||
self.tableId = try container.decode(String.self, forKey: .tableId)
|
self.tableId = try container.decode(String.self, forKey: .tableId)
|
||||||
self.databaseId = try container.decode(String.self, forKey: .databaseId)
|
self.databaseId = try container.decode(String.self, forKey: .databaseId)
|
||||||
self.createdAt = try container.decode(String.self, forKey: .createdAt)
|
self.createdAt = try container.decode(String.self, forKey: .createdAt)
|
||||||
@@ -94,7 +94,7 @@ open class Row<T : Codable>: Codable {
|
|||||||
public static func from(map: [String: Any] ) -> Row {
|
public static func from(map: [String: Any] ) -> Row {
|
||||||
return Row(
|
return Row(
|
||||||
id: map["$id"] as! String,
|
id: map["$id"] as! String,
|
||||||
sequence: map["$sequence"] as! Int,
|
sequence: map["$sequence"] as! String,
|
||||||
tableId: map["$tableId"] as! String,
|
tableId: map["$tableId"] as! String,
|
||||||
databaseId: map["$databaseId"] as! String,
|
databaseId: map["$databaseId"] as! String,
|
||||||
createdAt: map["$createdAt"] as! String,
|
createdAt: map["$createdAt"] as! String,
|
||||||
|
|||||||
@@ -24,6 +24,8 @@ open class User<T : Codable>: Codable {
|
|||||||
case prefs = "prefs"
|
case prefs = "prefs"
|
||||||
case targets = "targets"
|
case targets = "targets"
|
||||||
case accessedAt = "accessedAt"
|
case accessedAt = "accessedAt"
|
||||||
|
case impersonator = "impersonator"
|
||||||
|
case impersonatorUserId = "impersonatorUserId"
|
||||||
}
|
}
|
||||||
|
|
||||||
/// User ID.
|
/// User ID.
|
||||||
@@ -64,6 +66,10 @@ open class User<T : Codable>: Codable {
|
|||||||
public let targets: [Target]
|
public let targets: [Target]
|
||||||
/// Most recent access date in ISO 8601 format. This attribute is only updated again after 24 hours.
|
/// Most recent access date in ISO 8601 format. This attribute is only updated again after 24 hours.
|
||||||
public let accessedAt: String
|
public let accessedAt: String
|
||||||
|
/// Whether the user can impersonate other users.
|
||||||
|
public let impersonator: Bool?
|
||||||
|
/// ID of the original actor performing the impersonation. Present only when the current request is impersonating another user. Internal audit logs attribute the action to this user, while the impersonated target is recorded only in internal audit payload data.
|
||||||
|
public let impersonatorUserId: String?
|
||||||
|
|
||||||
init(
|
init(
|
||||||
id: String,
|
id: String,
|
||||||
@@ -84,7 +90,9 @@ open class User<T : Codable>: Codable {
|
|||||||
mfa: Bool,
|
mfa: Bool,
|
||||||
prefs: Preferences<T>,
|
prefs: Preferences<T>,
|
||||||
targets: [Target],
|
targets: [Target],
|
||||||
accessedAt: String
|
accessedAt: String,
|
||||||
|
impersonator: Bool?,
|
||||||
|
impersonatorUserId: String?
|
||||||
) {
|
) {
|
||||||
self.id = id
|
self.id = id
|
||||||
self.createdAt = createdAt
|
self.createdAt = createdAt
|
||||||
@@ -105,6 +113,8 @@ open class User<T : Codable>: Codable {
|
|||||||
self.prefs = prefs
|
self.prefs = prefs
|
||||||
self.targets = targets
|
self.targets = targets
|
||||||
self.accessedAt = accessedAt
|
self.accessedAt = accessedAt
|
||||||
|
self.impersonator = impersonator
|
||||||
|
self.impersonatorUserId = impersonatorUserId
|
||||||
}
|
}
|
||||||
|
|
||||||
public required init(from decoder: Decoder) throws {
|
public required init(from decoder: Decoder) throws {
|
||||||
@@ -129,6 +139,8 @@ open class User<T : Codable>: Codable {
|
|||||||
self.prefs = try container.decode(Preferences<T>.self, forKey: .prefs)
|
self.prefs = try container.decode(Preferences<T>.self, forKey: .prefs)
|
||||||
self.targets = try container.decode([Target].self, forKey: .targets)
|
self.targets = try container.decode([Target].self, forKey: .targets)
|
||||||
self.accessedAt = try container.decode(String.self, forKey: .accessedAt)
|
self.accessedAt = try container.decode(String.self, forKey: .accessedAt)
|
||||||
|
self.impersonator = try container.decodeIfPresent(Bool.self, forKey: .impersonator)
|
||||||
|
self.impersonatorUserId = try container.decodeIfPresent(String.self, forKey: .impersonatorUserId)
|
||||||
}
|
}
|
||||||
|
|
||||||
public func encode(to encoder: Encoder) throws {
|
public func encode(to encoder: Encoder) throws {
|
||||||
@@ -153,6 +165,8 @@ open class User<T : Codable>: Codable {
|
|||||||
try container.encode(prefs, forKey: .prefs)
|
try container.encode(prefs, forKey: .prefs)
|
||||||
try container.encode(targets, forKey: .targets)
|
try container.encode(targets, forKey: .targets)
|
||||||
try container.encode(accessedAt, forKey: .accessedAt)
|
try container.encode(accessedAt, forKey: .accessedAt)
|
||||||
|
try container.encodeIfPresent(impersonator, forKey: .impersonator)
|
||||||
|
try container.encodeIfPresent(impersonatorUserId, forKey: .impersonatorUserId)
|
||||||
}
|
}
|
||||||
|
|
||||||
public func toMap() -> [String: Any] {
|
public func toMap() -> [String: Any] {
|
||||||
@@ -175,7 +189,9 @@ open class User<T : Codable>: Codable {
|
|||||||
"mfa": mfa as Any,
|
"mfa": mfa as Any,
|
||||||
"prefs": prefs.toMap() as Any,
|
"prefs": prefs.toMap() as Any,
|
||||||
"targets": targets.map { $0.toMap() } as Any,
|
"targets": targets.map { $0.toMap() } as Any,
|
||||||
"accessedAt": accessedAt as Any
|
"accessedAt": accessedAt as Any,
|
||||||
|
"impersonator": impersonator as Any,
|
||||||
|
"impersonatorUserId": impersonatorUserId as Any
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -199,7 +215,9 @@ open class User<T : Codable>: Codable {
|
|||||||
mfa: map["mfa"] as! Bool,
|
mfa: map["mfa"] as! Bool,
|
||||||
prefs: Preferences.from(map: map["prefs"] as! [String: Any]),
|
prefs: Preferences.from(map: map["prefs"] as! [String: Any]),
|
||||||
targets: (map["targets"] as! [[String: Any]]).map { Target.from(map: $0) },
|
targets: (map["targets"] as! [[String: Any]]).map { Target.from(map: $0) },
|
||||||
accessedAt: map["accessedAt"] as! String
|
accessedAt: map["accessedAt"] as! String,
|
||||||
|
impersonator: map["impersonator"] as? Bool,
|
||||||
|
impersonatorUserId: map["impersonatorUserId"] as? String
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -90,7 +90,7 @@ extension ExampleView {
|
|||||||
fileId: fileId
|
fileId: fileId
|
||||||
)
|
)
|
||||||
DispatchQueue.main.async {
|
DispatchQueue.main.async {
|
||||||
self.downloadedImage = Image(data: Data(buffer: data))
|
self.downloadedImage = Image(data: Data(data.readableBytesView))
|
||||||
}
|
}
|
||||||
} catch {
|
} catch {
|
||||||
DispatchQueue.main.async {
|
DispatchQueue.main.async {
|
||||||
|
|||||||
@@ -87,7 +87,7 @@ class ViewController: UIViewController {
|
|||||||
bucketId: bucketId,
|
bucketId: bucketId,
|
||||||
fileId: fileId
|
fileId: fileId
|
||||||
)
|
)
|
||||||
let data = response.getData(at: 0, length: response.readableBytes)!
|
let data = Data(response.readableBytesView)
|
||||||
self.image.image = UIImage(data: data)
|
self.image.image = UIImage(data: data)
|
||||||
} catch {
|
} catch {
|
||||||
self.response = String(describing: error)
|
self.response = String(describing: error)
|
||||||
|
|||||||
Reference in New Issue
Block a user