casperjs passing params to evaluate fails - casperjs

casper.then(function(){
phone_number = '7wqeqwe6';
phone_password = 'Teqweqweqw34';
});
casper.thenEvaluate(function(phone,password) {
document.querySelector('input#myTMobile-phone').setAttribute('value',phone);
document.querySelector('input#myTMobile-password').setAttribute('value',password);
// document.querySelector('form').submit();
}, {
phone : phone_number,
password : phone_password
});
this throws me
string(307) "[37;41;1mFAIL[0m ReferenceError: Can't find variable: phone_number
Is there a way to pass params to evaluate method?

Try something like this:
var phone_number = '7wqeqwe6',
phone_password = 'Teqweqweqw34';
casper.start('http://…');
casper.thenEvaluate(function(phone, password) {
document.querySelector('input#myTMobile-phone').setAttribute('value', phone);
document.querySelector('input#myTMobile-password').setAttribute('value', password);
// document.querySelector('form').submit();
}, {
phone: phone_number,
password: phone_password
});
Notes:
a cool link on javascript scoping
filling forms? there's an API for that

The other answers are pre 1.0. The preferred way is to pass along the arguments in line
Example
casper.evaluate(function(username, password) {
document.querySelector('#username').value = username;
document.querySelector('#password').value = password;
document.querySelector('#submit').click();
}, 'sheldon.cooper', 'b4z1ng4');
http://docs.casperjs.org/en/latest/modules/casper.html#evaluate

I don't know whats wrong with your code. Have a look at the CasperJS API:
Evaluates an expression in the remote page context, a bit like what PhantomJS' WebPage#evaluate does, but can also handle passed arguments if you define their context:
Example:
casper.evaluate(function(username, password) {
document.querySelector('#username').value = username;
document.querySelector('#password').value = password;
document.querySelector('#submit').click();
}, {
username: 'sheldon.cooper',
password: 'b4z1ng4'
});

Related

Can't insert into table with RLS despite being logged in?

I want to add a row to a profiles table in the public schema immediately after the user has signed up and their auth user has been created in the database.
The user gets created successfully, and I can see the details of the user in the returned user object from the supabase.auth.signUp function.
However when I try to do a manual insert to the table, I get an error back saying the RLS on the table is being violated. However the user is logged in and the uid is correct, so why won't it let me insert data?
async function handleSubmit(e: any) {
e.preventDefault()
const email = emailRef.current.value;
const password = passwordRef.current.value;
// const navigate = useNavigate();
const {user, error} = await signUp({email, password});
if(error){
alert("Error signing in");
} else {
await addUserDetails({
uuid: user.id,
firstName: firstNameRef.current.value,
lastName: lastNameRef.current.value
});
navigate("/dashboard");
}
}
return //rest of component
}
export async function addUserDetails({
uuid, firstName, lastName
}){
const {data, error } = await supabase.from("profiles").insert([{
id: uuid,
first_name: firstName,
last_name: lastName
}])
}
RLS on table
create policy "Users can insert their own profile."
on profiles for insert
with check ( auth.uid() = id );
Try this:
const {data, error } = await supabase.from("profiles").insert([{
id: uuid,
first_name: firstName,
last_name: lastName
}],{ returning: "minimal" })
I was stuck on this for 2 days. It turns out it's because I was running Supabase in a Node test environment, and Supabase silently fails to setup a session and user id when not in a browser environment like Chromium or jsdom.
You can fix it by using a browser environment like jsdom for your testing environment or just using Playwright.
Rough example:
// #vitest-environment jsdom
test('use jsdom in this test file', () => {
const expectedName = 'Sam';
await supabase.from("profiles").insert([{
id: uuid,
first_name: expectedName
}]);
const { data: profile } = await supabase.from("profiles")
.select()
.eq( 'id', uuid )
expect( profile.first_name ).toEqual( expectedName )
});
In Vitest:
https://vitest.dev/config/#environment
In Jest:
https://jestjs.io/docs/configuration#testenvironment-string

How to change password after logging in?

I used the following code to change the password, but I get "Request failed with status code 400". Can someone give me an indication of where the problem is?
axios.post ('http: // localhost: 1337 / auth / reset-password', {
       code: '',
       password: '1234567',
       passwordConfirmation: '1234567',
     }
     , {
       headers: {
           Authorization: `Bearer $ {this.currentUser.jwt}`
       }
     }
     ) .then (response => {
       // Handle success.
       console.log ('Your user \' s password has been changed. ');
     })
     .catch (error => {
       // Handle error.
       console.log ('An error occurred:', error);
     });
   }
Thanks in advance
Another alternative way is by using a password reset controller. The scenario is by POST a password object to http://localhost:1337/password, the controller will validate the current password then update the password with given newPassword, and return a new jwt token.
We will post a password object as follows:
{
"identifier": "yohanes",
"password": "123456789",
"newPassword": "123456",
"confirmPassword": "123456"
}
The steps are:
Create password reset route /api/password/config/routes.json:
{
"routes": [
{
"method": "POST",
"path": "/password",
"handler": "password.index"
}
]
}
Create password reset controller at /api/password/controllers/password.js
module.exports = {
index: async ctx => {
return 'Hello World!';
}
}
Note: Don't forget to enable password index at Roles -> Permission -> Application.
Point Postman to http://localhost:1337/password. The response will display the text Hello World!.
Update the password controller:
module.exports = {
index: async ctx => {
// Get posted params
// const params = JSON.parse(ctx.request.body); //if post raw object using Postman
const params = ctx.request.body;
// The identifier is required.
if (!params.identifier) {
return ctx.badRequest(
null,
formatError({
id: 'Auth.form.error.email.provide',
message: 'Please provide your username or your e-mail.',
})
);
}
// Other params validation
.
.
.
// Get User based on identifier
const user = await strapi.query('user', 'users-permissions').findOne({username: params.identifier});
// Validate given password against user query result password
const validPassword = await strapi.plugins['users-permissions'].services.user.validatePassword(params.password, user.password);
if (!validPassword) {
return ctx.badRequest(
null,
formatError({
id: 'Auth.form.error.invalid',
message: 'Identifier or password invalid.',
})
);
} else {
// Generate new hash password
const password = await strapi.plugins['users-permissions'].services.user.hashPassword({password: params.newPassword});
// Update user password
await strapi
.query('user', 'users-permissions')
.update({ id: user.id }, { resetPasswordToken: null, password });
// Return new jwt token
ctx.send({
jwt: strapi.plugins['users-permissions'].services.jwt.issue({ id: user.id }),
user: sanitizeEntity(user.toJSON ? user.toJSON() : user, { model: strapi.query('user', 'users-permissions').model }),
});
}
}
}
Once the password object posted, the controller will update the user password and return a newly created jwt token.
The complete code can be found here. Tested on Strapi v.3.3.2
You will have to use the PUT /users/:id route (from the User API)
If you want this route used by a user, you will have to create a isOwner policy and apply it to this route.
To let only the current user udpate it's own password and not all users password.
Here some documentation:
Create a policy
Get the current user in the request
Customize the User plugin
Here is yohanes's solution adapted to Strapi v4
For some reason the Strapi team has removed the hashPassword method of the users-permission.user service, so we need to generate the hash ourselves now. For this we use the same having method as v3 did. We need to import bcrypt like this: const bcrypt = require("bcryptjs");
Out new changePassword needs to look something like this:
async changePassword(ctx) {
const userId = ctx.request.body.userId;
const currentPassword = ctx.request.body.currentPassword;
const newPassword = ctx.request.body.newPassword;
if (!userId || !currentPassword || !newPassword) {
return ctx.throw(400, "provide-userId-currentPassword-newPassword");
}
let user = await strapi
.query("plugin::users-permissions.user")
.findOne({ id: userId });
const validPassword = await strapi
.service("plugin::users-permissions.user")
.validatePassword(currentPassword, user.password);
if (!validPassword) {
return ctx.throw(401, "wrong-current-password");
} else {
// Generate new hashed password
const password = bcrypt.hashSync(newPassword, 10);
user = await strapi.query("plugin::users-permissions.user").update({
where: { id: user.id },
data: { resetPasswordToken: null, password },
});
// Return new jwt token
ctx.send({
jwt: strapi.service("plugin::users-permissions.jwt").issue({
id: user.id,
}),
user: sanitizeOutput(user),
});
}
},

VueJS: Is there an easy way to validate email and password on client side based on the server side's validator?

I'm new to VueJS. I'm creating signup and login page and users are supposed to send the email and password to the back-end (I'm using Django) to check if the data is valid. I'd like to show error messages on form if one of them are not valid.
I saw some documentation about validation and seems like I have to write a bunch of validation code. Now I'm wondering if there's an easy way to do it.
I'd like to validate them based on the server side's validators.
Login.vue
export default {
data() {
return {
form: {
email: '',
password: '',
}
}
},
methods: {
onSubmit(event) {
event.preventDefault()
// validate the inputs here and shows error messages if they are not valid
const path = `http://127.0.0.1:8000/users/login/`
axios.post(path, this.form).then((resp) => {
location.href = '/'
})
.catch((err) => {
console.log(err)
})
}
}
}
Can anyone give me tips?
Yes, Here is the code you can follow.
In data make a reg object like this.
data(){
return{
email:null,
reg: /^(([^<>()\[\]\\.,;:\s#"]+(\.[^<>()\[\]\\.,;:\s#"]+)*)|(".+"))#((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,24}))$/
}
},
add then in your submit method
if(this.email == null || this.email == '')
{
this.errorEmail = "Please Enter Email";
}
else if(!this.reg.test(this.email))
{
this.errorEmail = "Please Enter Correct Email";
}

How to limit User access to a User API to it's own :ID only?

I have created an API that contains many pieces of information related to each "User". By default "User" only have a model containing e-mail, password, username and lang.
So I have created a "UserInfo" API/Model that contains firstName, lastName, age, address and so on.
I want to give non-admin users access to it's own "UserInfo" data, which means the user would be able to access the api using localhost/userinfo/:id. But each user will only get authorized to call it's own ID and not other users IDs.
How can I create such a "policy"/ restriction for the final users "role"?
Hope I have been clear enough. My questions is probably quite trivial.
You will have to play with role's permissions or policies.
I think this issue is really close to what you want: https://github.com/strapi/strapi/issues/624
In strapi after the authentication the ctx.state.user.id is assigned with the user entity so you can use it to validate.
you can either create a policy
module.exports = async (ctx, next) => {
const { params } = ctx;
if (ctx.state.user.id === params.id) {
return next();
} else {
return ctx.badRequest(
'Not Authorized'
);
}
};
and set policy in the route file
{
"method": "GET",
"path": "/userinfo/:id",
"handler": "userinfo.findOne",
"config": {
"policies": [
"admin::hasPermissions",
"isOwner"]
}
}
Or custom write the findOne method
async findOne(ctx) {
const { query, params } = ctx;
if (ctx.state.user.id === params.id) {
const entity = await service.findOne({ ...query, id: params.id });
}
else {
return ctx.badRequest(
'Not Authorized'
)
}
return sanitize(entity);
},

Custom jquery.validate method always shows invalid

I have a custom validation method that checks for duplicate usernames. The json returns correctly for notDuplicateUsername but the validation always shows up as invalid.
$('#register-form').validate({
//see source of http://jquery.bassistance.de/validate/demo/ for example
rules: {
schoolname: {
required: true
},
username: {
required: true,
notDuplicateUsername: true
},
password: {
required: true
},
email: {
required: true,
email: true
}
},
messages: {
schoolname: 'Please tell us where you want to use Word Strip.',
username: {
required: 'Please choose a username.',
notDuplicateUsername: 'Sorry, that username is already being used.'
},
password: 'Please choose a password.',
email: 'Please can we have your email address.'
}
});
jQuery.validator.addMethod(
'notDuplicateUsername',
function(value, element, params){
var toCheck = new Object();
toCheck['username'] = $('#username').val();
var data_string = $.toJSON(toCheck);//this is a method of the jquery.json plug in
$.post('check_duplicate_username.php', {username_data: data_string}, function(result){
var noDuplicate = true;
var returned_data = $.evalJSON(result);//this is a method of the jquery.json plug in
if (returned_data.status == 'duplicate'){
noDuplicate = false;
}
console.log('value of noDuplicate: '+noDuplicate);
return noDuplicate;
});
}
);
Any clues anyone?
Probably you might have sorted this out already, but just in case. I faced a similar problem and found that I was comparing wrong types. May be your server sends the status as a boolean or some other datatype and its comparison to a string fails and always returns false.

Resources