From 6d3eced51fe873f70822b889a38cef5037431714 Mon Sep 17 00:00:00 2001 From: Nawar Nory Date: Mon, 9 Jan 2017 12:30:08 -0400 Subject: [PATCH 1/5] Adding functionality to destroy the token and clean it from the token store --- Sources/Account.swift | 10 ++++++++-- Sources/AuthHandlersJSON.swift | 3 +++ Sources/Tokens.swift | 9 +++++++++ 3 files changed, 20 insertions(+), 2 deletions(-) diff --git a/Sources/Account.swift b/Sources/Account.swift index b3120d1..6c891aa 100755 --- a/Sources/Account.swift +++ b/Sources/Account.swift @@ -28,6 +28,9 @@ open class AuthAccount : MySQLStORM, Account { /// Stored Google ID when logging in with Google public var googleID: String = "" + + /// Stored LinkedIn ID when logging in with Google + public var linkedInID: String = "" /// Optional first name public var firstname: String = "" @@ -41,9 +44,11 @@ open class AuthAccount : MySQLStORM, Account { /// Internal container variable for the current Token object public var internal_token: AccessTokenStore = AccessTokenStore() - /// The table to store the data + /// The table to store the data + public var tableName: String = "users" + override open func table() -> String { - return "users" + return tableName } /// Shortcut to store the id @@ -58,6 +63,7 @@ open class AuthAccount : MySQLStORM, Account { password = this.data["password"] as? String ?? "" facebookID = this.data["facebookID"] as? String ?? "" googleID = this.data["googleID"] as? String ?? "" + linkedInID = this.data["linkedInID"] as? String ?? "" firstname = this.data["firstname"] as? String ?? "" lastname = this.data["lastname"] as? String ?? "" email = this.data["email"] as? String ?? "" diff --git a/Sources/AuthHandlersJSON.swift b/Sources/AuthHandlersJSON.swift index b6acfa3..acde0cf 100755 --- a/Sources/AuthHandlersJSON.swift +++ b/Sources/AuthHandlersJSON.swift @@ -127,6 +127,9 @@ public class AuthHandlersJSON { response.setHeader(.contentType, value: "application/json") var resp = [String: String]() + // Destroy the token and clean the token store + tokenStore?.destroy() + request.user.logout() resp["error"] = "none" resp["logout"] = "complete" diff --git a/Sources/Tokens.swift b/Sources/Tokens.swift index 6e60e06..1e20069 100755 --- a/Sources/Tokens.swift +++ b/Sources/Tokens.swift @@ -91,4 +91,13 @@ open class AccessTokenStore : MySQLStORM { } return token } + + /// Destroy the token, after logout, by deleting it from token store + public func destroy() { + do { + try delete(token, idName: "token") + } catch { + print(error) + } + } } From 73a3863f31f9f8d0d3ab2dd89bb3f924dbe3f2b0 Mon Sep 17 00:00:00 2001 From: Nawar Nory Date: Mon, 9 Jan 2017 15:53:47 -0400 Subject: [PATCH 2/5] Adding destroy() function to clean out the token --- Sources/Account.swift | 4 +--- Sources/AuthHandlersJSON.swift | 6 +++++- Sources/Tokens.swift | 7 ++++++- 3 files changed, 12 insertions(+), 5 deletions(-) diff --git a/Sources/Account.swift b/Sources/Account.swift index 6c891aa..c4a3ae5 100755 --- a/Sources/Account.swift +++ b/Sources/Account.swift @@ -45,10 +45,8 @@ open class AuthAccount : MySQLStORM, Account { public var internal_token: AccessTokenStore = AccessTokenStore() /// The table to store the data - public var tableName: String = "users" - override open func table() -> String { - return tableName + return "people" } /// Shortcut to store the id diff --git a/Sources/AuthHandlersJSON.swift b/Sources/AuthHandlersJSON.swift index acde0cf..645b6db 100755 --- a/Sources/AuthHandlersJSON.swift +++ b/Sources/AuthHandlersJSON.swift @@ -128,7 +128,11 @@ public class AuthHandlersJSON { var resp = [String: String]() // Destroy the token and clean the token store - tokenStore?.destroy() + if let headerValue = request.header(HTTPRequestHeader.Name.authorization) { + if let res = tokenStore?.destroy(headerValue), !res { + Log.warning(message: "Couldn't delete token from the store") + } + } request.user.logout() resp["error"] = "none" diff --git a/Sources/Tokens.swift b/Sources/Tokens.swift index 1e20069..cdf704f 100755 --- a/Sources/Tokens.swift +++ b/Sources/Tokens.swift @@ -93,11 +93,16 @@ open class AccessTokenStore : MySQLStORM { } /// Destroy the token, after logout, by deleting it from token store - public func destroy() { + public func destroy(_ headerValue: String) -> Bool { + + guard let range = headerValue.range(of: "Bearer ") else { return false } + + let token = headerValue.substring(from: range.upperBound) do { try delete(token, idName: "token") } catch { print(error) } + return true } } From b99972fa3e650943af2403a6d88086976e320f4a Mon Sep 17 00:00:00 2001 From: Nawar Nory Date: Wed, 18 Jan 2017 19:53:26 -0400 Subject: [PATCH 3/5] adding a MYSQL-StORM that supports joins --- Package.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Package.swift b/Package.swift index 4dc0ce0..6c04871 100644 --- a/Package.swift +++ b/Package.swift @@ -5,7 +5,7 @@ let package = Package( name: "PerfectTurnstileMySQL", targets: [], dependencies: [ - .Package(url: "https://github.com/SwiftORM/MySQL-StORM.git", majorVersion: 1, minor: 0), + .Package(url: "https://github.com/nawar/MySQL-StORM.git", majorVersion: 1, minor: 0), .Package(url: "https://github.com/PerfectlySoft/Perfect-HTTPServer.git", majorVersion: 2, minor: 1), .Package(url: "https://github.com/PerfectlySoft/Perfect-Mustache.git", majorVersion: 2, minor: 0), .Package(url: "https://github.com/iamjono/SwiftString.git", majorVersion: 1, minor: 0), From 555962439ab5a42aaa75a548a59b618453f31a6a Mon Sep 17 00:00:00 2001 From: Nawar Nory Date: Wed, 18 Jan 2017 22:46:04 -0400 Subject: [PATCH 4/5] adding support for join --- Sources/Account.swift | 19 ++++++++++++++++--- Sources/AuthHandlersJSON.swift | 6 ++++++ 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/Sources/Account.swift b/Sources/Account.swift index c4a3ae5..4146d63 100755 --- a/Sources/Account.swift +++ b/Sources/Account.swift @@ -43,6 +43,12 @@ open class AuthAccount : MySQLStORM, Account { /// Internal container variable for the current Token object public var internal_token: AccessTokenStore = AccessTokenStore() + + /// xmpp username + public var _xmpp_un: String = "" + + /// xmpp password + public var _xmpp_pw: String = "" /// The table to store the data override open func table() -> String { @@ -65,6 +71,8 @@ open class AuthAccount : MySQLStORM, Account { firstname = this.data["firstname"] as? String ?? "" lastname = this.data["lastname"] as? String ?? "" email = this.data["email"] as? String ?? "" + _xmpp_un = this.data["xmpp_un"] as? String ?? "" + _xmpp_pw = this.data["xmpp_pw"] as? String ?? "" } /// Iterate through rows and set to object data @@ -92,7 +100,14 @@ open class AuthAccount : MySQLStORM, Account { func get(_ un: String, _ pw: String) throws -> AuthAccount { let cursor = StORMCursor(limit: 1, offset: 0) do { - try select(whereclause: "username = ?", params: [un], orderby: [], cursor: cursor) + let joins = StORMDataSourceJoin(table: "users", + onCondition: "people.uniqueID = users.people_uniqueID", + direction: .INNER) + try select(columns: ["people.username", "people.password", + "users.username as xmpp_un","users.password as xmpp_pw"], + whereclause: "people.username = ?", params: [un], orderby: [], cursor: cursor, + joins: [joins], having: [], groupBy: []) + if self.results.rows.count == 0 { throw StORMError.noRecordFound } @@ -124,5 +139,3 @@ open class AuthAccount : MySQLStORM, Account { } } } - - diff --git a/Sources/AuthHandlersJSON.swift b/Sources/AuthHandlersJSON.swift index 645b6db..36c8ee0 100755 --- a/Sources/AuthHandlersJSON.swift +++ b/Sources/AuthHandlersJSON.swift @@ -55,6 +55,12 @@ public class AuthHandlersJSON { resp["error"] = "none" resp["login"] = "ok" resp["token"] = token + + if let authAccount = request.user.authDetails?.account as? AuthAccount { + resp["xmpp_un"] = authAccount._xmpp_un + resp["xmpp_pw"] = authAccount._xmpp_pw + } + } catch { resp["error"] = "Invalid username or password" } From 6d576752f216bfb5019af88c9b621253ff5ac140 Mon Sep 17 00:00:00 2001 From: Nawar Nory Date: Thu, 19 Jan 2017 14:42:55 -0400 Subject: [PATCH 5/5] Pushing new changes to register --- Sources/AuthHandlersJSON.swift | 90 ++++++++++++++++++++++++++++++++-- 1 file changed, 85 insertions(+), 5 deletions(-) diff --git a/Sources/AuthHandlersJSON.swift b/Sources/AuthHandlersJSON.swift index 36c8ee0..0f93309 100755 --- a/Sources/AuthHandlersJSON.swift +++ b/Sources/AuthHandlersJSON.swift @@ -6,11 +6,12 @@ // // - import PerfectLib import PerfectHTTP import PerfectMustache import StORM +import MySQL +import MySQLStORM import Foundation import TurnstilePerfect @@ -18,6 +19,12 @@ import Turnstile import TurnstileCrypto import TurnstileWeb +#if os(Linux) + import SwiftGlibc +#else + import Darwin +#endif + /// public var that houses the Token object public var tokenStore: AccessTokenStore? @@ -100,17 +107,62 @@ public class AuthHandlersJSON { do { try request.user.register(credentials: credentials) - + + // if the registeration is good, register for the xmpp as well + if let authAccount = request.user.authDetails?.account as? AuthAccount { + + // now register for the xmpp server using ejablibswiftCore.soberdctl + let res = try runProc(cmd: "ejabberdctl", args: ["register",username, "localhost", password]) + Log.info(message: "Ejabberdctl result:\(res)") + + // using the returned data, update the just created ejabberd user with + // foreign key of people_uniqueID + + let server = MySQL() + let conn = server.connect(host: MySQLConnector.host , user: MySQLConnector.username, password: MySQLConnector.password, db: MySQLConnector.database, port: UInt32(MySQLConnector.port)) + + if conn { + + let sql = "UPDATE users SET people_uniqueID = '\(authAccount.uniqueID)' WHERE username = '\(authAccount.username)'" + if server.query(statement: sql) { + Log.info(message: "Successfull update") + } else { + Log.warning(message: "Update issue") + } + + defer { server.close() } + + } else { + Log.warning(message: "Issue with opening:\(server.errorMessage())") + } + } + + // login as you go and send the user the info try request.user.login(credentials: credentials) + //register resp["error"] = "none" resp["login"] = "ok" resp["token"] = response.request.user.authDetails?.sessionID + + if let authAccount = request.user.authDetails?.account as? AuthAccount { + resp["xmpp_un"] = authAccount._xmpp_un + resp["xmpp_pw"] = authAccount._xmpp_pw + } + } catch let e as TurnstileError { resp["error"] = e.description - } catch { - resp["error"] = "An unknown error occurred." - } + } catch let e as PerfectError { + if case .systemError(let (_,text)) = e { + Log.debug(message: text) + resp["error"] = text + } + resp["error"] = "An unknown error occurred. \(e.localizedDescription)" + } catch let e { + Log.debug(message: e.localizedDescription) + resp["error"] = e.localizedDescription + } + do { try response.setBody(json: resp) } catch { @@ -271,5 +323,33 @@ public class AuthHandlersJSON { } response.completed() } + + private static func runProc(cmd: String, args: [String], read: Bool = false) throws -> String? { + let envs = [("PATH", "/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin")] + let proc = try SysProcess(cmd, args: args, env: envs) + var ret: String? + if read { + var ary = [UInt8]() + while true { + do { + guard let s = try proc.stdout?.readSomeBytes(count: 1024), s.count > 0 else { + break + } + ary.append(contentsOf: s) + } catch PerfectLib.PerfectError.fileError(let code, _) { + if code != EINTR { + break + } + } + } + ret = UTF8Encoding.encode(bytes: ary) + } + let res = try proc.wait(hang: true) + if res != 0 { + let s = try proc.stderr?.readString() + throw PerfectError.systemError(Int32(res), s!) + } + return ret + } }