How to check url change after login - codeceptjs

How can I check if URL change after login to know that the login was success....
'use strict';
let I;
module.exports = {
_init() {
I = actor();
},
fields: {
email: '[bo-email]',
password: '[bo-password]'
},
submitButton:'button',
sendForm(email, password,utills) {
I.fillField(this.fields.email, email);
I.fillField(this.fields.password, password);
I.click(this.submitButton);
//how to check if navigation was success...
Tnx!

I.seeInCurrentUrl("page=2");
This method is the only way you can check if there is a URL change and you need not bother about using a wait method because this method would not execute until there is a URL change. However, you would need to increase your method timeout, to accommodate the long wait probably because of bad internet access.

I.seeInCurrentUrl('/register');
http://codecept.io/helpers/WebDriverIO/#seeincurrenturl

Related

Parse - Delete another user as super admin from iOS app

I use back4app for my app, I would like to delete another user (not authorised user on this device).
The app throws this:
[Error]: User cannot be deleted unless they have been authenticated. (Code: 206, Version: 1.19.1)
which make sense to me if I am not a super admin of the product. But in case I have super admin rights I would like to remove a user from the system completely.
Is there any solution for this purpose? I've tried to find some function from Parse.Cloud code.
The idea was to create cloud code and execute it form the iOS device by calling smth like this:
PFCloud.callFunctionInBackground("deleteUserAsSuperAdmin",
withParameters: user id param here)
{ success, error) -> Void in
}
I have not found such a solution and for me it's a bit difficult to write such code in a right way using cloud code, for sure if this is an option.
You will have to create a cloud code function for that, and use useMasterKey option to delete the user. Something like:
Parse.Cloud.define('deleteUser', async ({ user, params: { userIdToDelete } }) => {
if (user) {
const query = new Parse.Query(Parse.Role);
query.equalTo('name', 'admin');
query.equalTo('users', user);
const count = await query.count({ useMasterKey: true });
if (count === 1) {
const userToDelete = new Parse.User();
userToDelete = userIdToDelete;
return userToDelete.destroy({ useMasterKey: true });
}
}
throw new Error('Not an admin');
});

Snoowrap requester fromAuthCode returns API Error: invalid_grant - undefined

I am able to generate the authorization url, and the code is sucessfully returned to my express endpoint. All this is done in separate methods that I won't bother showing here - simple express routes. They have no affect on the code. I have copy/pasted the auth code from my browser cookies and made a test script that simply calls these functions:
const snoowrap = require('snoowrap');
module.exports = {
getAuthURL: async (managerId, modelId) => {
return snoowrap.getAuthUrl({
clientId: process.env.RDT_CLIENT,
scope: ['privatemessages', 'identity', 'read', 'submit'],
redirectUri: process.env.REDIRECT_URI,
permanent: false,
state: `${managerId}-${modelId}`
});
},
requester: async (token) => {
let s;
try {
s = await snoowrap.fromAuthCode({
code: token,
userAgent: process.env.RDT_AGENT,
clientId: process.env.RDT_CLIENT,
redirectUri: process.env.REDIRECT_URI,
clientSecret: process.env.RDT_SECRET,
});
} catch (err) {
if (err) {
console.log(err);
}
}
return s;
}
}
require('dotenv').config();
(async () => {
const requester = await require('./reddit/snoowrap').requester('<CODE GOES HERE>');
const me = await requester.getMe();
console.log(me);
})();
Calling this function results in this error:
RequestError: API Error: invalid_grant - undefined
I have a feeling I am just making a simple mistake here. If anyone with more experience than me could show me the path I would be eternally grateful!
Edit:
Made some progress - I am able to use the grant code a single time, even though I set it to permanent. I think what is happening is when I stop the application, the instance of snoowrap that created the grant code is now destroyed, leaving a useless session cookie behind with it. Can anyone confirm this?
Edit 2:
I made a new access token from authUrl, made a call to snoowrap.me() with that token once, used updateAccessToken() method to update the token and set it to browser cookies, and tried to use the updated token for the next request and it still said invalid_grant on the second function call. Why??

Url.Page automatically ToLowers any values passed in

I'm working on a .netcore3 app with IdentityServer, and in the example ForgotPassword page (which I'm using), they generate a token for the user and email it like this:
var code = await _userManager.GeneratePasswordResetTokenAsync(user);
var callbackUrl = Url.Page(
"/Account/ResetPassword",
pageHandler: null,
values: new { code },
protocol: Request.Scheme);
await _emailSender.SendEmailAsync(
Input.Email,
"Reset Password",
$"Please reset your password by <a href='{HtmlEncoder.Default.Encode(callbackUrl)}'>clicking here</a>.");
Then in the ResetPassword class, it resets the password using the token passed in (plus the user and the new password) var result = await _userManager.ResetPasswordAsync(user, Input.Code, Input.Password);
However, the Url.Page call at the top takes the code and lowercases the whole thing, which I believe is causing the ResetPasswordAsync to throw InvalidToken.
Any idea how I can get Url.Page to generate an absolute url without lowercasing the code?
In my Startup.cs, I had
services.Configure<RouteOptions>(options =>
{
options.LowercaseUrls = true;
options.LowercaseQueryStrings = true;
});
Once I removed that, it fixed the reset password. Now I just have to make sure I didn't break anything else in the process

Returning multiple Parse classes in one PFQuery?

I currently have my parse classes set up as follows
User - objectid, usename, password, location
Profile - birthday, weight, height, et....
Settings - user app preferences such as "Show my location"
Both profile and settings have a pointer to the user objectid called "user"
Is there anyway I can call a query knowing the Users.objectid that returns both Profile and Settings?
I have played around with includes key and matches query but only get back empty results.
If it isn't possible is there a way to execute a function once both queries have completed? (using getFirstObjectInBackgroundWithBlock)
Any help would greatly be appreciated.
No, but you could hide the combination in a function....
function profileAndSettingsForUser(user) {
var profiles;
var profileQuery = new Parse.Query("Profile");
profileQuery.equalTo("user", user);
return profileQuery.find().then(function(result) {
profiles = result;
settingsQuery = new Parse.Query("Settings");
settingsQuery.equalTo("user", user);
return settingsQuery.find();
}).then(function(settings) {
return profiles.concat(settings);
});
};
You could even locate that function in the cloud, so to hide the combination from the client.
Parse.Cloud.define("profileAndSettingsForUser", function(request, response) {
// we could pass a userId in params, then start by querying for that user
// or, if we know its always the current user who's calling for his own profile and settings...
var user = request.user;
profileAndSettingsForUser(user).then(function(profileAndSettings) {
response.success(profileAndSettings);
}, function(error) {
response.error(error);
});
});

How to do Oauth Authentication using seperate new tab for verification of account?

What is the Authentication Strategy for opening new (tab) Window for Oauth Authentication and returning to previous tab (logged In) upon successful authentication?
I am using passportjs authentication strategies for Twitter, Facebook and Google. But all of that does authentication in the same window-tab. Is there a predefined strategy which I can follow to do the above?
I can open the permission window in new account using a(target="_blank"), but it does not return to previous tab upon account authentication (by user).
Edit (based on following answer)
Login Page looks like:-
!!!
html
head
script.(type='text/javascript')
function newWindow (auth_target) {
authWindow = window.open(auth_target);
var authenticationSuccessUrl = "/home"
authWindow.onClose = function () {
alert('onClose called.');
authWindow.close();
window.location = authenticationSuccessUrl;
}
}
body
button(type="button", onclick="newWindow('auth/google');").btnLogin with Gmail
For New Window (home) i wrote:-
!!!
html
head
script(type='text/javascript').
function onAuthSuccess() {
authWindow=window.location;
window.onClose();
}
body(onload='onAuthSuccess();')
Its not a full code i was suppose to write, but even this does not work. If the Home page is called after an intermediate authentication window (by google, for password entry) the above code does not work, and window does not close.
// just as some more information, ignore if not necessary
Also please note, that,
window.close()
works only if the parent window that triggered it open is open. If the current window is a standalone the above window.close() will not close the window. Likewise, the above Home page code fails to close current window.
When creating the new window for authentication you can get the reference to the window object.
var authWindow = window.open("location","");
In the authentication tab you on authentication success you can call a method which would close the window and set a property or call a method on the source window suggesting that authentication is complete.
var authenticationSuccessUrl = "http://auth-sucess.url"
authWindow.onClose = function () {
authWindow.close();
window.location = authenticationSuccessUrl;
}
On the authentication window javascript:
var onAuthSuccess = function (){
window.onClose();
}
Be sure to remove the reference to the authWindow at the end of processing. Having window objects as references could potentially lead to memory leaks in the application.
Here is how I see the code can be changed as: This would just create one popup window and it will get closed after authentication.
You have Login page code as :
!!!
html
head
script.(type='text/javascript')
function newWindow (auth_target) {
authWindow = window.open(auth_target);
authWindow.onClose = function (authenticationSuccessUrl) {
alert('onClose called.');
authWindow.close();
window.location = authenticationSuccessUrl;
}
}
body
button(type="button", onclick="newWindow('auth/google');").btnLogin with Gmail
The newWindow('auth/google') should have the following code.
!!!
html
head
script(type='text/javascript').
function onAuthSuccess(authSuccessUrl) {
window.onClose(authSuccessUrl);
}
function ajaxPost() {
var uname = $("#name");
var pass = $("#password");
$.ajax({
url: "/auth/google/",
type: "POST",
data: {username : uname, password: pass}
}).success(function(data){
var redirectUrl = data.url; // or "/home" as you had mentioned
onAuthSuccess(redirectUrl);
});
}
body
p UserName:
input#name(type="text", name="username")
p Password:
input#password(type="text", name="password")
p: button(type="submit", onclick="ajaxPost()").btnLogin
If you can post through ajax to the google authentication service and get the the success response you can use this method.
Hope this works out well for you.

Resources