Skip to content
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

Integrate "Add Account (advanced)" in WelcomeLogIn.swift #1246

Open
wants to merge 1 commit into
base: develop
Choose a base branch
from
Open
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
9 changes: 5 additions & 4 deletions Monal/Classes/MLSettingsTableViewController.m
Original file line number Diff line number Diff line change
Expand Up @@ -366,15 +366,16 @@ -(void)tableView:(UITableView*) tableView didSelectRowAtIndexPath:(NSIndexPath*)
else
{
switch(indexPath.row - [self getAccountNum]) {
case QuickSettingsRow:
{
case QuickSettingsRow: {
UIViewController* loginView = [[SwiftuiInterface new] makeViewWithName:@"LogIn"];
[self showDetailViewController:loginView sender:self];
break;
}
case AdvancedSettingsRow:
[self performSegueWithIdentifier:@"editXMPP" sender:self];
case AdvancedSettingsRow: {
UIViewController* advancedLoginView = [[SwiftuiInterface new] makeViewWithName:@"AdvancedLogIn"];
[self showDetailViewController:advancedLoginView sender:self];
break;
}
default:
unreachable();
}
Expand Down
1 change: 1 addition & 0 deletions Monal/Classes/MLXMPPManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ NS_ASSUME_NONNULL_BEGIN
-(NSDate *) connectedTimeFor:(NSNumber*) accountID;

-(NSNumber* _Nullable) login:(NSString*) jid password:(NSString*) password;
-(NSNumber*) login:(NSString*) jid password:(NSString*) password hardcodedServer:(NSString* _Nullable) hardcodedServer hardcodedPort:(NSString* _Nullable) hardcodedPort forceDirectTLS:(BOOL) directTLS allowPlainAuth:(BOOL) plainActivated;
-(void) removeAccountForAccountID:(NSNumber*) accountID;
-(void) addNewAccountToKeychainAndConnectWithPassword:(NSString*) password andAccountID:(NSNumber*) accountID;

Expand Down
37 changes: 26 additions & 11 deletions Monal/Classes/MLXMPPManager.m
Original file line number Diff line number Diff line change
Expand Up @@ -713,6 +713,26 @@ -(void) sendChatState:(BOOL) isTyping toContact:(MLContact*) contact
#pragma mark - login/register

-(NSNumber*) login:(NSString*) jid password:(NSString*) password
{
NSArray* elements = [jid componentsSeparatedByString:@"@"];
MLAssert([elements count] > 1, @"Got invalid jid", (@{@"jid": nilWrapper(jid), @"elements": elements}));
NSString* domain = ((NSString*)[elements objectAtIndex:1]).lowercaseString;

//we don't want to set kPlainActivated (not even according to our preload list) and default to plain_activated=false,
//because the error message will warn the user and direct them to the advanced account creation menu to activate PLAIN
//if they still want to connect to this server
//only exception: yax.im --> we don't want to suggest a server during account creation that has a scary warning
//when logging in using another device afterwards
//TODO: to be removed once yax.im and quicksy.im supports SASL2 and SSDP!!
//TODO: use preload list and allow PLAIN for all others once enough domains are on this list
//allow plain for all servers not on preload list, since prosody with SASL2 wasn't even released yet
BOOL defaultPlainActivated = YES;
BOOL plainActivated = ([domain isEqualToString:@"yax.im"] || [domain isEqualToString:@"quicksy.im"]) ? YES : defaultPlainActivated;

return [self login:jid password:password hardcodedServer:nil hardcodedPort:nil forceDirectTLS:NO allowPlainAuth:plainActivated];
}

-(NSNumber*) login:(NSString*) jid password:(NSString*) password hardcodedServer:(NSString*) hardcodedServer hardcodedPort:(NSString*) hardcodedPort forceDirectTLS:(BOOL) directTLS allowPlainAuth:(BOOL) plainActivated
{
//check if it is a JID
NSArray* elements = [jid componentsSeparatedByString:@"@"];
Expand All @@ -737,17 +757,12 @@ -(NSNumber*) login:(NSString*) jid password:(NSString*) password
[dic setObject:user forKey:kUsername];
[dic setObject:[HelperTools encodeRandomResource] forKey:kResource];
[dic setObject:@YES forKey:kEnabled];
[dic setObject:@NO forKey:kDirectTLS];
//we don't want to set kPlainActivated (not even according to our preload list) and default to plain_activated=false,
//because the error message will warn the user and direct them to the advanced account creation menu to activate PLAIN
//if they still want to connect to this server
//only exception: yax.im --> we don't want to suggest a server during account creation that has a scary warning
//when logging in using another device afterwards
//TODO: to be removed once yax.im and quicksy.im supports SASL2 and SSDP!!
//TODO: use preload list and allow PLAIN for all others once enough domains are on this list
//allow plain for all servers not on preload list, since prosody with SASL2 wasn't even released yet
NSNumber* defaultPlainActivated = @YES;
[dic setObject:([domain isEqualToString:@"yax.im"] || [domain isEqualToString:@"quicksy.im"] ? @YES : defaultPlainActivated) forKey:kPlainActivated];
if(hardcodedServer != nil)
[dic setObject:hardcodedServer forKey:kServer];
if(hardcodedPort != nil)
[dic setObject:hardcodedPort forKey:kPort];
[dic setObject:@(directTLS) forKey:kDirectTLS];
[dic setObject:@(plainActivated) forKey:kPlainActivated];

NSNumber* accountID = [[DataLayer sharedInstance] addAccountWithDictionary:dic];
if(accountID == nil)
Expand Down
2 changes: 2 additions & 0 deletions Monal/Classes/SwiftuiHelpers.swift
Original file line number Diff line number Diff line change
Expand Up @@ -809,6 +809,8 @@ class SwiftuiInterface : NSObject {
host = UIHostingController(rootView:AnyView(AddTopLevelNavigation(withDelegate:delegate, to:WelcomeLogIn(delegate:delegate))))
case "LogIn":
host = UIHostingController(rootView:AnyView(UIKitWorkaround(WelcomeLogIn(delegate:delegate))))
case "AdvancedLogIn":
host = UIHostingController(rootView:AnyView(UIKitWorkaround(WelcomeLogIn(advancedMode: true, delegate: delegate))))
case "ChatPlaceholder":
host = UIHostingController(rootView:AnyView(ChatPlaceholder()))
case "GeneralSettings" :
Expand Down
81 changes: 71 additions & 10 deletions Monal/Classes/WelcomeLogIn.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,19 @@
struct WelcomeLogIn: View {
static private let credFaultyPattern = "^.+@.+\\..{2,}$"

var advancedMode: Bool = false
var delegate: SheetDismisserProtocol

@State private var isEditingJid: Bool = false
@State private var jid: String = ""
@State private var isEditingPassword: Bool = false
@State private var password: String = ""

@State private var hardcodedServer: String = ""
@State private var hardcodedPort: String = ""
@State private var allowPlainAuth: Bool = false
@State private var forceDirectTLS: Bool = false

@State private var showAlert = false
@State private var showQRCodeScanner = false

Expand All @@ -26,7 +32,7 @@ struct WelcomeLogIn: View {
@State private var loginComplete = false
@State private var isLoadingOmemoBundles = false

@State private var alertPrompt = AlertPrompt(dismissLabel: Text("Close"))
@State private var alertPrompt = AlertPrompt()
@StateObject private var overlay = LoadingOverlayState()

#if IS_ALPHA
Expand All @@ -40,18 +46,21 @@ struct WelcomeLogIn: View {
private var credentialsEnteredAlert: Bool {
alertPrompt.title = Text("Empty Values!")
alertPrompt.message = Text("Please make sure you have entered both a username and password.")
alertPrompt.dismissLabel = Text("Close")
return credentialsEntered
}

private var credentialsFaultyAlert: Bool {
alertPrompt.title = Text("Invalid Credentials!")
alertPrompt.message = Text("Your XMPP jid should be in in the format [email protected]. For special configurations, use manual setup.")
alertPrompt.dismissLabel = Text("Close")
return credentialsFaulty
}

private var credentialsExistAlert: Bool {
alertPrompt.title = Text("Duplicate jid!")
alertPrompt.message = Text("This account already exists in Monal.")
alertPrompt.dismissLabel = Text("Close")
return credentialsExist
}

Expand All @@ -60,20 +69,30 @@ struct WelcomeLogIn: View {
hideLoadingOverlay(overlay)
alertPrompt.title = Text("Timeout Error")
alertPrompt.message = Text("We were not able to connect your account. Please check your username and password and make sure you are connected to the internet.")
alertPrompt.dismissLabel = Text("Close")
showAlert = true
}

private func showSuccessAlert() {
hideLoadingOverlay(overlay)
alertPrompt.title = Text("Success!")
alertPrompt.message = Text("You are set up and connected.")
alertPrompt.dismissLabel = Text("Close")
showAlert = true
}

private func showLoginErrorAlert(errorMessage: String) {
hideLoadingOverlay(overlay)
alertPrompt.title = Text("Error")
alertPrompt.message = Text(String(format: NSLocalizedString("We were not able to connect your account. Please check your username and password and make sure you are connected to the internet.\n\nTechnical error message: %@", comment: ""), errorMessage))
alertPrompt.dismissLabel = Text("Close")
showAlert = true
}

private func showPlainAuthWarningAlert() {
alertPrompt.title = Text("Warning")
alertPrompt.message = Text("If you turn this on, you will no longer be safe from man-in-the-middle attacks. Such attacks enable the adversary to manipulate your incoming and outgoing messages, add their own OMEMO keys, change your account details and even know or change your password!\n\nYou should rather switch to another server than turning this on.")
alertPrompt.dismissLabel = Text("Understood")
showAlert = true
}

Expand Down Expand Up @@ -126,11 +145,16 @@ struct WelcomeLogIn: View {
.frame(width: CGFloat(120), height: CGFloat(120), alignment: .center)
.clipShape(RoundedRectangle(cornerRadius: 10, style: .continuous))
.padding()

Text("Log in to your existing account or register a new account. If required you will find more advanced options in Monal settings.")
.padding()
.padding(.leading, -16.0)


if advancedMode {
Text("Log in to your existing account or register a new account.")
.padding()
.padding(.leading, -16.0)
} else {
Text("Log in to your existing account or register a new account. If required you will find more advanced options in Monal settings.")
.padding()
.padding(.leading, -16.0)
}
}
}
.frame(maxWidth: .infinity)
Expand All @@ -154,7 +178,34 @@ struct WelcomeLogIn: View {
SecureField(NSLocalizedString("Password", comment: "placeholder when adding account"), text: $password)
.addClearButton(isEditing: password.count > 0, text: $password)
.listRowSeparator(.hidden)


if advancedMode {
TextField("Optional Hardcoded Hostname", text: $hardcodedServer)
.textInputAutocapitalization(.never)
.autocorrectionDisabled()
.keyboardType(.URL)
.addClearButton(isEditing: hardcodedServer.count > 0, text: $hardcodedServer)
.listRowSeparator(.hidden)

TextField("Optional Port", text: $hardcodedPort)
.keyboardType(.numberPad)
.addClearButton(isEditing: hardcodedPort.count > 0, text: $hardcodedPort)
.listRowSeparator(.hidden)

Toggle(isOn: $forceDirectTLS){
Text("Always use direct TLS, not STARTTLS")
}

Toggle(isOn: $allowPlainAuth){
Text("Allow MITM-prone PLAIN authentication")
}
.onChange(of: allowPlainAuth) { _ in
if allowPlainAuth {
showPlainAuthWarningAlert()
}
}
}

HStack() {
Button(action: {
showAlert = !credentialsEnteredAlert || credentialsFaultyAlert || credentialsExistAlert
Expand All @@ -163,7 +214,11 @@ struct WelcomeLogIn: View {
startLoginTimeout()
showLoadingOverlay(overlay, headline:NSLocalizedString("Logging in", comment: ""))
self.errorObserverEnabled = true
self.newAccountID = MLXMPPManager.sharedInstance().login(self.jid, password: self.password)
if advancedMode {
self.newAccountID = MLXMPPManager.sharedInstance().login(self.jid, password: self.password, hardcodedServer:self.hardcodedServer, hardcodedPort:self.hardcodedPort, forceDirectTLS: self.forceDirectTLS, allowPlainAuth: self.allowPlainAuth)
} else {
self.newAccountID = MLXMPPManager.sharedInstance().login(self.jid, password: self.password)
}
if(self.newAccountID == nil) {
currentTimeout = nil // <- disable timeout on error
errorObserverEnabled = false
Expand Down Expand Up @@ -214,7 +269,12 @@ struct WelcomeLogIn: View {
)
}
}

.listRowSeparator(.hidden, edges: .top)
// Align the (bottom) list row separator to the very left
.alignmentGuide(.listRowSeparatorLeading) { _ in
return 0
}

NavigationLink(destination: LazyClosureView(RegisterAccount(delegate: self.delegate))) {
Text("Register a new account")
.foregroundColor(Color.accentColor)
Expand Down Expand Up @@ -243,7 +303,8 @@ struct WelcomeLogIn: View {
}
}
.addLoadingOverlay(overlay)
.navigationBarTitle(Text("Welcome"), displayMode:.large)
.navigationTitle(Text("Welcome"))
.navigationBarTitleDisplayMode(advancedMode ? .inline : .large)
.onDisappear {UITableView.appearance().tableHeaderView = nil} //why that??
.onReceive(NotificationCenter.default.publisher(for: NSNotification.Name("kXMPPError")).receive(on: RunLoop.main)) { notification in
if(self.errorObserverEnabled == false) {
Expand Down