Skip to content

Instantly share code, notes, and snippets.

@vmic2002
Created August 17, 2022 17:30
Show Gist options
  • Save vmic2002/68bdfb71a55a1410ba0e708a81b24af1 to your computer and use it in GitHub Desktop.
Save vmic2002/68bdfb71a55a1410ba0e708a81b24af1 to your computer and use it in GitHub Desktop.
//
// DBHelper.swift
// GroupAccounting
//
// Created by Victor Micha on 8/17/22.
//
import Foundation
//variables
let ASTRA_DB_ID = "REPLACE_ME"
let ASTRA_DB_TOKEN = "REPLACE_ME"
let ASTRA_DB_REGION = "REPLACE_ME"
let ASTRA_DB_KEYSPACENAME = "REPLACE_ME"
//model
struct UserInfo : Codable {
let userName : String
let password : String
}
struct Password : Codable {
let password : String
}
//backend functions
func deleteDoc(docID:String, collection:String) async throws {
let urlRequest = getURLRequest(httpMethod: "DELETE", endURL: "/namespaces/\(ASTRA_DB_KEYSPACENAME)/collections/\(collection)/\(docID)")
let (_, response) = try await URLSession.shared.data(for: urlRequest)
guard let response = response as? HTTPURLResponse,
response.statusCode == 204 else {
//successful DELETE using DOC API has status code of 204
print("Response: \(response)")
print("Error: could not DELETE doc: \(docID)")
return
}
print("No error occurred while DELETING doc \(docID)")
}
func printUserInfoDict(userName:String) async throws {
let dict = try await getUserInfo(userName: userName)
if (dict.count==0) {
print("No account for \(userName)")
} else {
//usernames are unique so dict.count must be equal 1
let userInfo = dict[dict.startIndex].value
let docID = dict[dict.startIndex].key
print("Username: \(userInfo.userName)")
print("Password: \(userInfo.password)")
print("DocID: \(docID)")
}
}
func getUserInfo(userName:String) async throws -> [String:UserInfo] {
let dataString = try await getRequest(endURL: "/namespaces/\(ASTRA_DB_KEYSPACENAME)/collections/userInfo?where={\"userName\":{\"$eq\":\"\(userName)\"}}&page-size=1")
let (formattedData, _) = processDataString(dataString: dataString)
if let jsonData = formattedData.data(using: .utf8){
do{
let userInfoDict = try JSONDecoder().decode([String:UserInfo].self, from: jsonData)
//userInfoDict is a dictionary of [String:UserInfo] or [DocID:UserInfo]
//if userInfoDict.count==0, there is no account for userName
//if userInfoDict.count==1, there is an account for userName
return userInfoDict
} catch {
print("Could not decode into a dictionary")
return [String:UserInfo]()
}
} else {
print("Could not convert string to Data")
return [String:UserInfo]()
}
}
func processDataString(dataString:String)->(String, String){
var dataString = dataString
/*
JSON dataString is of the form
{“data”:
{
“docID”:Order,
“docID”:Order
}
}
OR (if there are more docs than <page-size> or <20>)
{"pageState":"JDZjN2Y5MGQ5LWYyZGItNGRkNS05Mzk3LTZiNDE5NzYzNGMwZQDwf_____B_____","data":{
“docID”:Order,
“docID”:Order
}
}
*/
var pageState = ""
let y = 64//length of page-state
if (dataString[dataString.index(dataString.startIndex, offsetBy: 2)]=="p"){
pageState = String(dataString[dataString.index(dataString.startIndex, offsetBy: 14)...dataString.index(dataString.startIndex, offsetBy: 14+y-1)])
}
//need to clean up/proccess dataString
var indx = dataString.startIndex//arbitrary, val is changed in if/else statement
if (dataString[dataString.index(dataString.startIndex, offsetBy: 2)]=="p"){
//there is page state
//length of {"pageState":"JDZjN2Y5MGQ5LWYyZGItNGRkNS05Mzk3LTZiNDE5NzYzNGMwZQDwf_____B_____","data":
//is 87 which is equal to 23+y
indx = dataString.index(dataString.startIndex, offsetBy: 23+y)
} else {
//there is no page state
//length of {“data”: is 8
indx = dataString.index(dataString.startIndex, offsetBy: 8)
}
let x = dataString.startIndex..<indx
dataString.removeSubrange(x)
dataString.removeLast()//to remove last }
//print("dataString: \(dataString)")
/*
by now dataString is of form:
{
“docID”:Order,
“docID”:Order
} or {"docID":UserInfo}
*/
return (dataString, pageState)
}
func getRequest(endURL:String) async throws -> String {
let urlRequest = getURLRequest(httpMethod: "GET", endURL: endURL)
let (data, response) = try await URLSession.shared.data(for: urlRequest)
guard let response = response as? HTTPURLResponse,
response.statusCode == 200 else {
//successful GET request using the Document API has status code 200
print("Response: \(response)")
print("Error occured during GET request")
return""
}
if response.mimeType == "application/json",
let dataString = String(data:data, encoding: .utf8){
print("got data: \(dataString)")
/*
dataString is of the form:
{"data":{"documentId":UserInfo}}
*/
return dataString
}
print("Data could not be converted into a String")
return ""
}
func changePassword(docID:String, newPassword:String) async throws {
let encoder = JSONEncoder()
guard let uploadData = try? encoder.encode(Password(password: newPassword)) else {
print("Could not convert struct to JSON")
return
}
let urlRequest = getURLRequest(httpMethod: "PATCH", endURL: "/namespaces/\(ASTRA_DB_KEYSPACENAME)/collections/userInfo/\(docID)")
let (data, response) = try await URLSession.shared.upload(for: urlRequest, from: uploadData)
guard let response = response as? HTTPURLResponse,
response.statusCode == 200 else {
//successful PATCH to astra using the Document API has status code 200
print("Response: \(response)")
print("Could not PATCH to collection userInfo")
return
}
if response.mimeType == "application/json",
let dataString = String(data: data, encoding: .utf8){
print("got data: \(dataString)")
print("PATCH to collection userInfo is successful!")
/*
dataString is of the form:
{"documentId":"..."}
*/
return
}
print("Data could not be converted to String")
}
func postUserInfo(userInfo:UserInfo) async throws {
let encoder = JSONEncoder()
guard let uploadData = try? encoder.encode(userInfo) else {
print("Could not convert struct to JSON")
return
}
let urlRequest = getURLRequest(httpMethod: "POST", endURL: "/namespaces/\(ASTRA_DB_KEYSPACENAME)/collections/userInfo")
let (data, response) = try await URLSession.shared.upload(for: urlRequest, from: uploadData)
guard let response = response as? HTTPURLResponse,
response.statusCode == 201 else {
//successful POST to astra using the Document API has status code 201
print("Response: \(response)")
print("Could not POST to collection userInfo")
return
}
if response.mimeType == "application/json",
let dataString = String(data: data, encoding: .utf8){
print("got data: \(dataString)")
print("POST to collection userInfo is successful!")
/*
dataString is of the form:
{"documentId":"..."}
*/
return
}
print("Data could not be converted to String")
}
//this function is called everytime a HTTP request is performed to connect to ASTRA
func getURLRequest(httpMethod:String, endURL:String) -> URLRequest {
let str = "https://"+ASTRA_DB_ID+"-"+ASTRA_DB_REGION+".apps.astra.datastax.com/api/rest/v2"+endURL
let encodedStr = str.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed)!
let url = URL.init(string:encodedStr)!
var urlRequest = URLRequest(url: url)
urlRequest.httpMethod = httpMethod //POST, PATCH, DELETE, GET
if (httpMethod == "POST") {
urlRequest.setValue("application/json", forHTTPHeaderField: "Content-Type")
}
urlRequest.setValue("application/json", forHTTPHeaderField: "accept")
urlRequest.setValue(ASTRA_DB_TOKEN, forHTTPHeaderField: "X-Cassandra-Token")
return urlRequest
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment