Skip to content

feat: Added Api Key support and new tests. #5

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
Jul 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/swift.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ jobs:
"hostname": "${{ secrets.SQ_LITE_CLOUD_HOST }}",
"username": "${{ secrets.SQ_LITE_CLOUD_USER }}",
"password": "${{ secrets.SQ_LITE_CLOUD_PASS }}",
"apyKey": "${{ secrets.SQ_LITE_CLOUD_APIKEY }}"
"apiKey": "${{ secrets.SQ_LITE_CLOUD_APIKEY }}"
}
' >> Tests/SQLiteCloudTests/Secrets/secrets.json

Expand Down
10 changes: 8 additions & 2 deletions Sources/SQLiteCloud/Core/SQLiteCloudConfig+Internal.swift
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,14 @@ extension SQLiteCloudConfig {
var sqConfig: SQCloudConfig {
var sqConfig = SQCloudConfig()
sqConfig.family = family.rawValue
sqConfig.username = (username as NSString).utf8String
sqConfig.password = (password as NSString).utf8String
if let username,
let password {
sqConfig.username = (username as NSString).utf8String
sqConfig.password = (password as NSString).utf8String
}
if let apiKey {
sqConfig.api_key = (apiKey as NSString).utf8String
}
sqConfig.password_hashed = passwordHashed
sqConfig.non_linearizable = nonlinearizable
sqConfig.timeout = Int32(timeout)
Expand Down
138 changes: 127 additions & 11 deletions Sources/SQLiteCloud/Core/SQLiteCloudConfig.swift
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,9 @@ import Foundation
public struct SQLiteCloudConfig: Sendable {
public let hostname: String
public let port: Port
public let username: String
public let password: String
public let username: String?
public let password: String?
public let apiKey: String?
public let family: Family
public let passwordHashed: Bool
public let nonlinearizable: Bool
Expand All @@ -49,6 +50,52 @@ public struct SQLiteCloudConfig: Sendable {
public let clientCertificate: String?
public let clientCertificateKey: String?

public init(hostname: String,
apiKey: String,
port: Port = .default,
family: Family = .ipv4,
passwordHashed: Bool = false,
nonlinearizable: Bool = false,
timeout: Int = 0,
compression: Bool = false,
zerotext: Bool = false,
memory: Bool = false,
dbCreate: Bool = false,
insecure: Bool = false,
noblob: Bool = false,
isReadonlyConnection: Bool = false,
maxData: Int = 0,
maxRows: Int = 0,
maxRowset: Int = 0,
dbname: String? = nil,
rootCertificate: String? = nil,
clientCertificate: String? = nil,
clientCertificateKey: String? = nil) {
self.init(hostname: hostname,
username: nil,
password: nil,
apiKey: apiKey,
port: port,
family: family,
passwordHashed: passwordHashed,
nonlinearizable: nonlinearizable,
timeout: timeout,
compression: compression,
zerotext: zerotext,
memory: memory,
dbCreate: dbCreate,
insecure: insecure,
noblob: noblob,
isReadonlyConnection: isReadonlyConnection,
maxData: maxData,
maxRows: maxRows,
maxRowset: maxRowset,
dbname: dbname,
rootCertificate: rootCertificate,
clientCertificate: clientCertificate,
clientCertificateKey: clientCertificateKey)
}

public init(hostname: String,
username: String,
password: String,
Expand All @@ -71,10 +118,59 @@ public struct SQLiteCloudConfig: Sendable {
rootCertificate: String? = nil,
clientCertificate: String? = nil,
clientCertificateKey: String? = nil) {
self.init(hostname: hostname,
username: username,
password: password,
apiKey: nil,
port: port,
family: family,
passwordHashed: passwordHashed,
nonlinearizable: nonlinearizable,
timeout: timeout,
compression: compression,
zerotext: zerotext,
memory: memory,
dbCreate: dbCreate,
insecure: insecure,
noblob: noblob,
isReadonlyConnection: isReadonlyConnection,
maxData: maxData,
maxRows: maxRows,
maxRowset: maxRowset,
dbname: dbname,
rootCertificate: rootCertificate,
clientCertificate: clientCertificate,
clientCertificateKey: clientCertificateKey)
}

private init(hostname: String,
username: String?,
password: String?,
apiKey: String?,
port: Port = .default,
family: Family = .ipv4,
passwordHashed: Bool = false,
nonlinearizable: Bool = false,
timeout: Int = 0,
compression: Bool = false,
zerotext: Bool = false,
memory: Bool = false,
dbCreate: Bool = false,
insecure: Bool = false,
noblob: Bool = false,
isReadonlyConnection: Bool = false,
maxData: Int = 0,
maxRows: Int = 0,
maxRowset: Int = 0,
dbname: String? = nil,
rootCertificate: String? = nil,
clientCertificate: String? = nil,
clientCertificateKey: String? = nil) {
self.hostname = hostname
self.port = port
self.username = username
self.password = password
self.apiKey = apiKey
self.family = family
self.passwordHashed = passwordHashed
self.nonlinearizable = nonlinearizable
Expand All @@ -94,7 +190,7 @@ public struct SQLiteCloudConfig: Sendable {
self.clientCertificate = clientCertificate
self.clientCertificateKey = clientCertificateKey
}

public init?(connectionString: String) {
guard let url = URL(string: connectionString) else { return nil }

Expand All @@ -103,22 +199,38 @@ public struct SQLiteCloudConfig: Sendable {

/// sqlitecloud://user:pass@host.com:port/dbname?timeout=10&key2=value2&key3=value3.
public init?(connectionURL: URL) {
guard let username = connectionURL.user else { return nil }
guard let password = connectionURL.password else { return nil }
guard let hostname = connectionURL.host else { return nil }
let port = connectionURL.port.map { Port.custom(portNumber: $0) } ?? .default


let urlComponents = URLComponents(string: connectionURL.absoluteString)
let queryItems = urlComponents?.queryItems


// There are 2 kind of possibile credentials types
// - based on an apikey
// - based on the username and the password combo
// We need to search for this credential info in the connection string.
// First we check for apikey, if fails we fallback on the user/pass combo.

if let apiKey = UrlParser.parse(items: queryItems, name: "apikey") {
self.username = nil
self.password = nil
self.apiKey = apiKey
} else {
guard let username = connectionURL.user else { return nil }
guard let password = connectionURL.password else { return nil }

self.username = username
self.password = password
self.apiKey = nil
}

let port = connectionURL.port.map { Port.custom(portNumber: $0) } ?? .default

// external
self.hostname = hostname
self.port = port
self.isReadonlyConnection = UrlParser.parse(items: queryItems, name: "readonly")

// in config
self.username = username
self.password = password
self.dbname = urlComponents?.path.replacingOccurrences(of: "/", with: "")
self.family = Family(rawValue: UrlParser.parse(items: queryItems, name: "family")) ?? .ipv4
self.passwordHashed = UrlParser.parse(items: queryItems, name: "passwordHashed")
Expand All @@ -143,7 +255,11 @@ public struct SQLiteCloudConfig: Sendable {

extension SQLiteCloudConfig {
var connectionString: String {
"sqlitecloud://\(username):****@\(hostname):\(port.number)/\(dbname ?? .empty)"
if let apiKey {
"sqlitecloud://\(hostname):\(port.number)/\(dbname ?? .empty)?apikey=\(apiKey)"
} else {
"sqlitecloud://\(username ?? ""):****@\(hostname):\(port.number)/\(dbname ?? .empty)"
}
}
}

Expand Down
16 changes: 8 additions & 8 deletions Sources/libsqcloud.xcframework/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -10,34 +10,32 @@
<key>HeadersPath</key>
<string>Headers</string>
<key>LibraryIdentifier</key>
<string>ios-arm64_x86_64-simulator</string>
<string>ios-arm64</string>
<key>LibraryPath</key>
<string>libsqcloud.a</string>
<key>SupportedArchitectures</key>
<array>
<string>arm64</string>
<string>x86_64</string>
</array>
<key>SupportedPlatform</key>
<string>ios</string>
<key>SupportedPlatformVariant</key>
<string>simulator</string>
</dict>
<dict>
<key>BinaryPath</key>
<string>libsqcloud.a</string>
<key>HeadersPath</key>
<string>Headers</string>
<key>LibraryIdentifier</key>
<string>ios-arm64</string>
<string>macos-arm64_x86_64</string>
<key>LibraryPath</key>
<string>libsqcloud.a</string>
<key>SupportedArchitectures</key>
<array>
<string>arm64</string>
<string>x86_64</string>
</array>
<key>SupportedPlatform</key>
<string>ios</string>
<string>macos</string>
</dict>
<dict>
<key>BinaryPath</key>
Expand All @@ -64,7 +62,7 @@
<key>HeadersPath</key>
<string>Headers</string>
<key>LibraryIdentifier</key>
<string>macos-arm64_x86_64</string>
<string>ios-arm64_x86_64-simulator</string>
<key>LibraryPath</key>
<string>libsqcloud.a</string>
<key>SupportedArchitectures</key>
Expand All @@ -73,7 +71,9 @@
<string>x86_64</string>
</array>
<key>SupportedPlatform</key>
<string>macos</string>
<string>ios</string>
<key>SupportedPlatformVariant</key>
<string>simulator</string>
</dict>
</array>
<key>CFBundlePackageType</key>
Expand Down
Binary file modified Sources/libsqcloud.xcframework/ios-arm64/libsqcloud.a
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file modified Sources/libsqcloud.xcframework/macos-arm64_x86_64/libsqcloud.a
Binary file not shown.
10 changes: 5 additions & 5 deletions Sources/libtls.xcframework/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -29,32 +29,32 @@
<key>HeadersPath</key>
<string>Headers</string>
<key>LibraryIdentifier</key>
<string>ios-arm64</string>
<string>macos-arm64_x86_64</string>
<key>LibraryPath</key>
<string>libtls.a</string>
<key>SupportedArchitectures</key>
<array>
<string>arm64</string>
<string>x86_64</string>
</array>
<key>SupportedPlatform</key>
<string>ios</string>
<string>macos</string>
</dict>
<dict>
<key>BinaryPath</key>
<string>libtls.a</string>
<key>HeadersPath</key>
<string>Headers</string>
<key>LibraryIdentifier</key>
<string>macos-arm64_x86_64</string>
<string>ios-arm64</string>
<key>LibraryPath</key>
<string>libtls.a</string>
<key>SupportedArchitectures</key>
<array>
<string>arm64</string>
<string>x86_64</string>
</array>
<key>SupportedPlatform</key>
<string>macos</string>
<string>ios</string>
</dict>
<dict>
<key>BinaryPath</key>
Expand Down
Binary file modified Sources/libtls.xcframework/ios-arm64/libtls.a
Binary file not shown.
Binary file modified Sources/libtls.xcframework/ios-arm64_x86_64-maccatalyst/libtls.a
Binary file not shown.
Binary file modified Sources/libtls.xcframework/ios-arm64_x86_64-simulator/libtls.a
Binary file not shown.
Binary file modified Sources/libtls.xcframework/macos-arm64_x86_64/libtls.a
Binary file not shown.
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ final class SQLiteCloudTests_Blob: XCTestCase {
hostname = secrets.hostname
username = secrets.username
password = secrets.password

let config = SQLiteCloudConfig(hostname: hostname, username: username, password: password)
cloud = SQLiteCloud(config: config)
try await cloud.connect()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,14 @@ final class SQLiteCloudTests_Connection: XCTestCase {
private var hostname: String = .empty
private var username: String = .empty
private var password: String = .empty
private var apiKey: String = .empty

override func setUpWithError() throws {
let secrets = try Secrets.load()
hostname = secrets.hostname
username = secrets.username
password = secrets.password
apiKey = secrets.apiKey
}

func test_connect_withValidCredentials_shouldConnectWithoutError() async throws {
Expand All @@ -48,7 +50,18 @@ final class SQLiteCloudTests_Connection: XCTestCase {
XCTFail("An error was thrown: \(error)")
}
}


func test_connect_withValidCredentialAPIKey_shouldConnectWithoutError() async throws {
let config = SQLiteCloudConfig(hostname: hostname, apiKey: apiKey)
let cloud = SQLiteCloud(config: config)

do {
try await cloud.connect()
} catch {
XCTFail("An error was thrown: \(error)")
}
}

func test_connect_withInvalidCredentials_shouldThrowError() async throws {
let config = SQLiteCloudConfig(hostname: hostname, username: "!!invalid!!", password: "!!credentials!!")
let cloud = SQLiteCloud(config: config)
Expand All @@ -60,7 +73,19 @@ final class SQLiteCloudTests_Connection: XCTestCase {
XCTAssert(error is SQLiteCloudError)
}
}


func test_connect_withInvalidCredentialAPIKey_shouldThrowError() async throws {
let config = SQLiteCloudConfig(hostname: hostname, apiKey: "!!invalid!!")
let cloud = SQLiteCloud(config: config)

do {
try await cloud.connect()
XCTFail("No errors were thrown.")
} catch {
XCTAssert(error is SQLiteCloudError)
}
}

func test_disconnect_withValidConnection_shouldDisconnectWithoutError() async throws {
let config = SQLiteCloudConfig(hostname: hostname, username: username, password: password)
let cloud = SQLiteCloud(config: config)
Expand Down
1 change: 1 addition & 0 deletions Tests/SQLiteCloudTests/Secrets/Secrets.swift
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ struct Secrets: Decodable {
let hostname: String
let username: String
let password: String
let apiKey: String
}

extension Secrets {
Expand Down
3 changes: 2 additions & 1 deletion Tests/SQLiteCloudTests/Secrets/secrets.json.sample
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
{
"hostname": "<your host>",
"username": "<your user>",
"password": "<your pass>"
"password": "<your pass>",
"apiKey": "<your apikey>"
}
Loading