diff --git a/Mixonomer/Network/AuthApi.swift b/Mixonomer/Network/AuthApi.swift index f792eb8..5a80d16 100644 --- a/Mixonomer/Network/AuthApi.swift +++ b/Mixonomer/Network/AuthApi.swift @@ -13,6 +13,7 @@ import SwiftyJSON public enum AuthApi { case token(username: String, password: String, expiry: Int) + case register(username: String, password: String, password2: String) } extension AuthApi: ApiRequest { @@ -24,6 +25,8 @@ extension AuthApi: ApiRequest { switch self { case .token: return "auth/token" + case .register: + return "auth/register" } } @@ -32,6 +35,8 @@ extension AuthApi: ApiRequest { switch self { case .token: return .post + case .register: + return .post } } @@ -39,6 +44,8 @@ extension AuthApi: ApiRequest { switch self { case .token(let username, let password, let expiry): return JSON(["username": username, "password": password, "expiry": expiry]) + case .register(let username, let password, let password2): + return JSON(["username": username, "password": password, "password_again": password2]) } } @@ -46,6 +53,8 @@ extension AuthApi: ApiRequest { switch self { case .token: return JSONParameterEncoder.default + case.register: + return JSONParameterEncoder.default } } diff --git a/Mixonomer/Router.swift b/Mixonomer/Router.swift index 4f2e22b..ccd1827 100644 --- a/Mixonomer/Router.swift +++ b/Mixonomer/Router.swift @@ -27,5 +27,6 @@ struct Router: View { struct Router_Previews: PreviewProvider { static var previews: some View { Router() + .environmentObject(LiveUser(playlists: [], tags: [], username: "user", loggedIn: false)) } } diff --git a/Mixonomer/Views/LoginScreen.swift b/Mixonomer/Views/LoginScreen.swift index 6abe670..2452b14 100644 --- a/Mixonomer/Views/LoginScreen.swift +++ b/Mixonomer/Views/LoginScreen.swift @@ -11,15 +11,24 @@ import ToastUI import KeychainAccess import SwiftyJSON +enum ScreenMode { + case None + case Login + case Register +} + struct LoginScreen: View { @EnvironmentObject var liveUser: LiveUser @State private var username: String = "" @State private var password: String = "" + @State private var password2: String = "" @State private var showingToast = false @State private var toastText = "" + + @State public var screenMode = ScreenMode.None var body: some View { VStack { @@ -29,17 +38,50 @@ struct LoginScreen: View { .cornerRadius(18) .shadow(radius: /*@START_MENU_TOKEN@*/10/*@END_MENU_TOKEN@*/) .padding(.bottom, 20) - Text("Sarsoo's Mixonomer") + Text("Mixonomer") .font(.largeTitle) - TextField("Username", text: $username) - SecureField("Password", text: $password) - HStack { + .padding(.bottom, 20) + + if screenMode != .None { + TextField("Username", text: $username) + .textFieldStyle(.roundedBorder) + SecureField("Password", text: $password) + .textFieldStyle(.roundedBorder) + } + + if screenMode == .Register { + SecureField("Password Again", text: $password2) + .textFieldStyle(.roundedBorder) + .padding(.bottom, 20) + } + + if screenMode == .None { + HStack { + Button(action: { + + screenMode = .Login + + }) { + Text("Log In") + } + .buttonStyle(.bordered) + .padding(.trailing, 20.0) + Button(action: { + + screenMode = .Register + + }) { + Text("Register") + }.buttonStyle(.bordered) + } + } + + if screenMode == .Login { Button(action: { let keychain = Keychain(service: "xyz.sarsoo.music.login") keychain["username"] = username -// keychain["password"] = password let api = AuthApi.token(username: username, password: password, expiry: 604800) RequestBuilder.buildRequest(apiRequest: api) @@ -65,7 +107,6 @@ struct LoginScreen: View { case _: keychain["username"] = nil - keychain["password"] = nil keychain["jwt"] = nil toastText = "Login Failed" @@ -75,16 +116,73 @@ struct LoginScreen: View { }) { Text("Log In") } - .padding(.trailing, 20.0) - Button(action: /*@START_MENU_TOKEN@*/{}/*@END_MENU_TOKEN@*/) { + .buttonStyle(.bordered) + .padding(.top, 20) + } + + if screenMode == .Register { + Button(action: { + + let keychain = Keychain(service: "xyz.sarsoo.music.login") + + keychain["username"] = username + + let api = AuthApi.register(username: username, password: password, password2: password2) + RequestBuilder.buildRequest(apiRequest: api) + .validate() + .responseJSON { response in + + switch response.response?.statusCode { + case 200, 201: + + let token_api = AuthApi.token(username: username, password: password, expiry: 604800) + RequestBuilder.buildRequest(apiRequest: token_api) + .validate() + .responseJSON { response in + + switch response.response?.statusCode { + case 200, 201: + + guard let data = response.data else { + fatalError("error getting token") + } + + guard let json = try? JSON(data: data) else { + fatalError("error parsing reponse") + } + + let token = json["token"].stringValue + + keychain["jwt"] = token + self.liveUser.loggedIn = true + + case _: + + keychain["username"] = nil + keychain["jwt"] = nil + + toastText = "Token Generation Failed" + showingToast = true + } + } + + // TODO: add handling for 400, password dont match + // TODO: add handling for 409, conflict + + case _: + + keychain["username"] = nil + keychain["jwt"] = nil + + toastText = "Register Failed" + showingToast = true + } + } + }) { Text("Register") } + .buttonStyle(.bordered) } - .toast(isPresented: $showingToast, dismissAfter: 3.0){ - ToastView(toastText) - .toastViewStyle(.failure) - } - .toastDimmedBackground(false) } .padding() } @@ -92,6 +190,13 @@ struct LoginScreen: View { struct LoginScreen_Previews: PreviewProvider { static var previews: some View { - LoginScreen() + Group{ + LoginScreen(screenMode: .None) + .environmentObject(LiveUser(playlists: [], tags: [], username: "user", loggedIn: false)) + LoginScreen(screenMode: .Login) + .environmentObject(LiveUser(playlists: [], tags: [], username: "user", loggedIn: false)) + LoginScreen(screenMode: .Register) + .environmentObject(LiveUser(playlists: [], tags: [], username: "user", loggedIn: false)) + } } }