Skip to content

Commit

Permalink
tests: email/password retry custom confirmation function (#515)
Browse files Browse the repository at this point in the history
* Create tests for email/password register user
  • Loading branch information
desistefanova committed May 5, 2022
1 parent 6ff8e4b commit a1776c0
Show file tree
Hide file tree
Showing 3 changed files with 108 additions and 43 deletions.
71 changes: 53 additions & 18 deletions lib/src/cli/deployapps/baas_client.dart
Expand Up @@ -20,13 +20,27 @@ import 'package:http/http.dart' as http;
import 'dart:convert';

class BaasClient {
static const String _confirmFuncSource = '''exports = ({ token, tokenId, username }) => {
static const String _confirmFuncSource = '''exports = async ({ token, tokenId, username }) => {
// process the confirm token, tokenId and username
if (username.includes("realm_tests_do_autoverify")) {
return { status: 'success' }
}
// do not confirm the user
return { status: 'fail' };
else if (username.includes("realm_tests_pending_confirm")) {
const mdb = context.services.get("BackingDB");
const collection = mdb.db("custom-auth").collection("users");
const existing = await collection.findOne({ username: username });
if (existing) {
return { status: 'success' };
}
await collection.insertOne({ username: username });
return { status: 'pending' }
}
else
{
// do not confirm the user
return { status: 'fail' };
}
};''';

static const String _resetFuncSource = '''exports = ({ token, tokenId, username, password }) => {
Expand All @@ -37,6 +51,7 @@ class BaasClient {
// will not reset the password
return { status: 'fail' };
};''';
static const String defaultAppName = "flexible";

final String _baseUrl;
final String? _clusterName;
Expand Down Expand Up @@ -90,21 +105,16 @@ class BaasClient {
result[app.name] = app;
}
}
String appName = "flexible";
if (!result.containsKey(appName)) {
result[appName] = await _createApp(appName);
}
appName = "autoConfirm";
if (!result.containsKey(appName)) {
result[appName] = await _createApp(appName, confirmationType: 'auto');
}
await _createAppIfNotExists(result, defaultAppName);
await _createAppIfNotExists(result, "autoConfirm", confirmationType: "auto");
await _createAppIfNotExists(result, "emailConfirm", confirmationType: "email");
return result;
}

appName = "emailConfirm";
if (!result.containsKey(appName)) {
result[appName] = await _createApp(appName, confirmationType: 'email');
Future<void> _createAppIfNotExists(Map<String, BaasApp> existingApps, String appName, {String? confirmationType}) async {
if (!existingApps.containsKey(appName)) {
existingApps[appName] = await _createApp(appName, confirmationType: confirmationType);
}

return result;
}

Future<List<BaasApp>> _getApps() async {
Expand All @@ -124,7 +134,21 @@ class BaasClient {
.toList();
}

Future<BaasApp> _createApp(String name, {String confirmationType = "func"}) async {
Future<void> updateAppConfirmFunction(String name, [String? source]) async {
final dynamic docs = await _get('groups/$_groupId/apps');
dynamic doc = docs.firstWhere((dynamic d) => d["name"] == "$name$_appSuffix", orElse: () => throw Exception("BAAS app not found"));
final appId = doc['_id'] as String;
final clientAppId = doc['client_app_id'] as String;
final app = BaasApp(appId, clientAppId, name);

final dynamic functions = await _get('groups/$_groupId/apps/$appId/functions');
dynamic function = functions.firstWhere((dynamic f) => f["name"] == "confirmFunc", orElse: () => throw Exception("Func 'confirmFunc' not found"));
final confirmFuncId = function['_id'] as String;

await _updateFunction(app, 'confirmFunc', confirmFuncId, source ?? _confirmFuncSource);
}

Future<BaasApp> _createApp(String name, {String? confirmationType}) async {
print('Creating app $name');

final dynamic doc = await _post('groups/$_groupId/apps', '{ "name": "$name$_appSuffix" }');
Expand All @@ -147,7 +171,7 @@ class BaasClient {
"resetFunctionId": "$resetFuncId",
"resetPasswordSubject": "",
"resetPasswordUrl": "http://localhost/resetPassword",
"runConfirmationFunction": ${(confirmationType == "func").toString()},
"runConfirmationFunction": ${(confirmationType != "email" && confirmationType != "auto").toString()},
"runResetFunction": true
}''');

Expand Down Expand Up @@ -213,6 +237,17 @@ class BaasClient {
return response['_id'] as String;
}

Future<void> _updateFunction(BaasApp app, String name, String functionId, String source) async {
print('Updating function $name for ${app.name}...');

await _put('groups/$_groupId/apps/$app/functions/$functionId', '''{
"name": "$name",
"source": ${jsonEncode(source)},
"private": false,
"can_evaluate": {}
}''');
}

Future<String> _createMongoDBService(BaasApp app, String syncConfig) async {
final serviceName = _clusterName == null ? 'mongodb' : 'mongodb-atlas';
final mongoConfig = _clusterName == null ? '{ "uri": "mongodb://localhost:26000" }' : '{ "clusterName": "$_clusterName" }';
Expand Down
77 changes: 53 additions & 24 deletions test/credentials_test.dart
Expand Up @@ -35,6 +35,9 @@ Future<User> retryLogin(int retries, Future<User> Function(Credentials credentia
}

Future<void> main([List<String>? args]) async {

const String strongPassword = "SWV23R#@T#VFQDV";

print("Current PID $pid");

await setupTests(args);
Expand All @@ -53,44 +56,40 @@ Future<void> main([List<String>? args]) async {
final app = App(configuration);
final authProvider = EmailPasswordAuthProvider(app);
String username = "${generateRandomString(5)}@bar.com";
String password = "SWV23R#@T#VFQDV";
expect(() async {
// For application with name 'func' and with confirmationType = 'runConfirmationFunction'
// For confirmationType = 'runConfirmationFunction' as it is by default
// only usernames that contain 'realm_tests_do_autoverify' are confirmed.
await authProvider.registerUser(username, password);
await authProvider.registerUser(username, strongPassword);
}, throws<RealmException>("failed to confirm user"));
});

baasTest('Email/Password - register user', (configuration) async {
final app = App(configuration);
final authProvider = EmailPasswordAuthProvider(app);
String username = "realm_tests_do_autoverify${generateRandomString(5)}@bar.com";
String password = "SWV23R#@T#VFQDV";
await authProvider.registerUser(username, password);
final user = await retryLogin(3, app.logIn, Credentials.emailPassword(username, password));
await authProvider.registerUser(username, strongPassword);
final user = await retryLogin(3, app.logIn, Credentials.emailPassword(username, strongPassword));
expect(user, isNotNull);
});

baasTest('Email/Password - register user auto confirm', (configuration) async {
final app = App(configuration);
final authProvider = EmailPasswordAuthProvider(app);
String username = "${generateRandomString(5)}@bar.com";
String password = "SWV23R#@T#VFQDV";
// For application with name 'autoConfirm' and with confirmationType = 'auto'
// all the usernames are automatically confirmed.
await authProvider.registerUser(username, password);
final user = await retryLogin(3, app.logIn, Credentials.emailPassword(username, password));
await authProvider.registerUser(username, strongPassword);
final user = await retryLogin(3, app.logIn, Credentials.emailPassword(username, strongPassword));
expect(user, isNotNull);
}, appName: "autoConfirm");

baasTest('Email/Password - register user twice throws', (configuration) async {
final app = App(configuration);
final authProvider = EmailPasswordAuthProvider(app);
String username = "${generateRandomString(5)}@bar.com";
String password = "SWV23R#@T#VFQDV";
await authProvider.registerUser(username, password);
await authProvider.registerUser(username, strongPassword);
expect(() async {
await authProvider.registerUser(username, password);
await authProvider.registerUser(username, strongPassword);
}, throws<RealmException>("name already in use"));
}, appName: "autoConfirm");

Expand Down Expand Up @@ -118,8 +117,7 @@ Future<void> main([List<String>? args]) async {
final app = App(configuration);
final authProvider = EmailPasswordAuthProvider(app);
String username = "${generateRandomString(5)}@hotmail.com";
String password = "SWV23R#@T#VFQDV";
await authProvider.registerUser(username, password);
await authProvider.registerUser(username, strongPassword);
expect(() async {
await authProvider.confirmUser(
"0e6340a446e68fe02a1af1b53c34d5f630b601ebf807d73d10a7fed5c2e996d87d04a683030377ac6058824d8555b24c1417de79019b40f1299aada7ef37fddc",
Expand All @@ -131,8 +129,7 @@ Future<void> main([List<String>? args]) async {
final app = App(configuration);
final authProvider = EmailPasswordAuthProvider(app);
String username = "${generateRandomString(5)}@hotmail.com";
String password = "SWV23R#@T#VFQDV";
await authProvider.registerUser(username, password);
await authProvider.registerUser(username, strongPassword);
expect(() async {
await authProvider.confirmUser("abc", "123");
}, throws<RealmException>("invalid token data"));
Expand All @@ -144,27 +141,59 @@ Future<void> main([List<String>? args]) async {
// Set the variables with token details and then run test 2.
// Go to the application and check whether the new registered user is confirmed.
// Make sure the email haven't been already registered in apllication.
group("Manual Email/Password - confirm user", () {
group("Manual test: Email/Password - confirm user", () {
// Enter a valid email that is not registered
String username = "existing_email@mail.com";
String password = "SWV23R#@T#VFQDV";
const String validUsername = "valid_email@mail.com";

baasTest('Manual 1. Register a valid user for email confirmation', (configuration) async {
baasTest('Manual test 1. Register a valid user for email confirmation', (configuration) async {
final app = App(configuration);
final authProvider = EmailPasswordAuthProvider(app);
await authProvider.registerUser(username, password);
await authProvider.registerUser(validUsername, strongPassword);
}, appName: "emailConfirm", skip: "It is a manual test");

baasTest('Manual 2. Take the recieved token from the email and confirm the user', (configuration) async {
//Enter valid token and tokenId from the received email
baasTest('Manual test 2. Take the recieved token from the email and confirm the user', (configuration) async {
// Enter valid token and tokenId from the received email
String token = "3a8bdfa28e147f38e531cf5aca93d452a11efc4fc9a81f00219b0cb29cfb93858f6b174123659a6ef47b58a2b80eac3b406d7803605c17ef44401ec6cf2c8fa6";
String tokenId = "626934dcb4e7e5a0e2f1d85e";

final app = App(configuration);
final authProvider = EmailPasswordAuthProvider(app);
await authProvider.confirmUser(token, tokenId);
final user = await retryLogin(3, app.logIn, Credentials.emailPassword(username, password));
final user = await retryLogin(3, app.logIn, Credentials.emailPassword(validUsername, strongPassword));
expect(user, isNotNull);
}, appName: "emailConfirm", skip: "Run this test manually after test 1 and after setting token and tokenId");
});

baasTest('Email/Password - retry custom confirmation function', (configuration) async {
final app = App(configuration);
final authProvider = EmailPasswordAuthProvider(app);
String username = "realm_tests_pending_confirm_${generateRandomString(5)}@bar.com";
await authProvider.registerUser(username, strongPassword);

await authProvider.retryCustomConfirmationFunction(username);

final user = await retryLogin(3, app.logIn, Credentials.emailPassword(username, strongPassword));
expect(user, isNotNull);
});

baasTest('Email/Password - retry custom confirmation after user is confirmed', (configuration) async {
final app = App(configuration);
final authProvider = EmailPasswordAuthProvider(app);
String username = "realm_tests_do_autoverify_${generateRandomString(5)}@bar.com";
// Custom confirmation function confirms automatically username with 'realm_tests_do_autoverify'.
await authProvider.registerUser(username, strongPassword);

expect(() async {
await authProvider.retryCustomConfirmationFunction(username);
}, throws<RealmException>("already confirmed"));
});

baasTest('Email/Password - retry custom confirmation for not registered user', (configuration) async {
final app = App(configuration);
final authProvider = EmailPasswordAuthProvider(app);
String username = "${generateRandomString(5)}@bar.com";
expect(() async {
await authProvider.retryCustomConfirmationFunction(username);
}, throws<RealmException>("user not found"));
});
}
3 changes: 2 additions & 1 deletion test/test.dart
Expand Up @@ -225,7 +225,8 @@ Future<void> baasTest(
}

test(name, () async {
final app = baasApps[appName] ?? baasApps.values.firstWhere((element) => true, orElse: () => throw RealmError("No BAAS apps"));
final app =
baasApps[appName] ?? baasApps.values.firstWhere((element) => element.name == BaasClient.defaultAppName, orElse: () => throw RealmError("No BAAS apps"));
final temporaryDir = await Directory.systemTemp.createTemp('realm_test_');
final appConfig = AppConfiguration(
app.clientAppId,
Expand Down

0 comments on commit a1776c0

Please sign in to comment.