I'm migrating my Meteor application from Meteor 1.2 to Meteor 1.3 and following the guide on http://guide.meteor.com/methods.html#validated-method to create a validated method.
When I call the method, I believe client-side simulation is happening, as I can log out to console, but this is always followed by the error Method '...' not found.
/imports/ui/pages/register.js
import {Meteor} from 'meteor/meteor';
import {Template} from 'meteor/templating';
import {FlowRouter} from 'meteor/kadira:flow-router';
// Methods
import {createAccount} from '/imports/api/accounts/methods.js';
// HTML
import './register.html';
Template.Register_page.events({
'submit form': function(event) {
event.preventDefault();
var user = {
email: $('#email').val(),
password: $('#password').val(),
profile: {
firstName: $('#firstName').val(),
lastName: $('#lastName').val()
}
};
createAccount.call(user, function(err) {
if (err) {
console.error(err);
} else {
console.log('User successfully registered');
FlowRouter.go('Dashboard');
}
});
}
});
/imports/api/accounts/methods.js
import {Meteor} from 'meteor/meteor';
import {ValidatedMethod} from 'meteor/mdg:validated-method';
import {SimpleSchema} from 'meteor/aldeed:simple-schema';
import {Accounts} from 'meteor/accounts-base';
export const createAccount = new ValidatedMethod({
name: 'createAccount',
validate: new SimpleSchema({
email: { type: String },
password: { type: String },
profile: { type: Object },
"profile.firstName": { type: String },
"profile.lastName": { type: String }
}).validator(),
run(user) {
console.log(user);
Accounts.createUser(user);
},
});
Client console
Object {email: "test#mailinator.com", password: "testPassw0rd", profile: Object} methods.js:18
errorClass {error: 404, reason: "Method 'createAccount' not found", details: undefined, message: "Method 'createAccount' not found [404]", errorType: "Meteor.Error"} register.js:28
I believe the reason this wasn't working was because I was not initialising the javascript on the server at startup.
Adding the following fixed the issue:
/imports/startup/server/index.js
import './register-api.js';
/imports/startup/server/register-api.js
import '/imports/api/accounts/methods.js';
Related
It seems that every that the updated recoverTypedSignature function on #metamask/eth-sig-util is not working properly. As soon as I add it into the project, it gives out an error.
The error is:
bundle.js:6306 Uncaught ReferenceError: Buffer is not defined at Object../node_modules/#metamask/eth-sig-util/node_modules/ethereumjs-util/dist/secp256k1v3-lib/der.js (bundle.js:6306:40) at Object.options.factory (bundle.js:84170:31) at webpack_require (bundle.js:83608:33) at fn (bundle.js:83841:21) at Object../node_modules/#metamask/eth-sig-util/node_modules/ethereumjs-util/dist/secp256k1v3-adapter.js (bundle.js:5932:11) at Object.options.factory (bundle.js:84170:31) at webpack_require (bundle.js:83608:33) at fn (bundle.js:83841:21) at Object../node_modules/#metamask/eth-sig-util/node_modules/ethereumjs-util/dist/index.js (bundle.js:5724:17) at Object.options.factory (bundle.js:84170:31)
The code is:
import { SignTypedDataVersion, recoverTypedSignature } from '#metamask/eth-sig-util';
const Request_Signature = (props: any) => {
// Step 2: Once user has authorized the use of its crypto wallet a signature can
// be requested
async function sign_TypedDataV4() {
const msgParamsOg = {
domain: {
// Defining the chain: 1 - Ethereum Main Net
chainId: 1,
// Friendly name
name: "Initial Example Contract",
// Additional way of verifying contract to make sure you are establishing contracts with the proper entity
verifyingContract: "this",
// Just let's you know the latest version. Definitely make sure the field name is correct.
version: "1",
},
// Defining the message signing data content.
message: {
Request: "Please complete your authentication by signing this",
username: "test_user",
},
// Refers to the keys of the *types* object below.
primaryType: "LogIn",
types: {
EIP712Domain: [
{
name: "name",
type: "string",
},
{
name: "version",
type: "string",
},
{
name: "chainId",
type: "uint256",
},
{
name: "verifyingContract",
type: "address",
},
],
// Refer to PrimaryType
LogIn: [
{
name: "username",
type: "string",
},
],
},
};
let msgParams = JSON.stringify(msgParamsOg);
let account = props.account;
var params = [account, msgParams];
var method = "eth_signTypedData_v4";
console.log('User Address:' + account);
(window as any).ethereum.sendAsync(
{
method,
params,
account,
},
async function (err: Error, result: any) {
if (err) return console.dir(err);
if (result.error) {
alert(result.error.message);
return console.error("ERROR", result);
}
//console.log('TYPED SIGNED:' + JSON.stringify(result.result));
let signature = result.result;
const restored = recoverTypedSignature({
data: msgParamsOg as any,
signature,
version: SignTypedDataVersion.V4,
});
console.log(restored);
}
);
}
return (
<div>
<button
className='btn_main'
type="button"
onClick={async (e) => {
e.preventDefault();
sign_TypedDataV4();
}}
>
Sign Now
</button>
</div>
)
};
export default Request_Signature;
If you are using react, I don't know the exact fix but this is a workaround:
downgrade react-scripts to version 4.0.3
In my case I needed to do the following also:
In package.json use react-script 4.0.3
Remove package-lock.json
remove node_modules folder
run npm install
After all this everything seems to be working fine.
I had to use webpack (https://webpack.js.org/) with Babel (https://babeljs.io/docs/en/babel-preset-react) to solve this. I as well had to install Buffer (https://www.npmjs.com/package/buffer) and stream-browserify (https://www.npmjs.com/package/stream-browserify)
This resolved the problem
Hi I'm writing my slack bot, and I want after select, change prev message to a new variat, this is my action which is triggerd after select:
slackInteractions.action({ type: "static_select" }, (payload, res) => {
console.log(payload);
web.chat
.update({
token: slackSigningSecret,
channel: payload.container.channel_id,
ts: payload.container.message_ts,
as_user: true,
text: "Hello World"
})
.catch(err => {
console.log(err);
});
});
And I got error:
Error: An API error occurred: invalid_auth
at Object.platformErrorFromResult (/home/codex/Documents/dan-bot/node_modules/#slack/web-api/dist/errors.js:50:33)
at WebClient.apiCall (/home/codex/Documents/dan-bot/node_modules/#slack/web-api/dist/WebClient.js:485:28)
at processTicksAndRejections (internal/process/task_queues.js:97:5) {
code: 'slack_webapi_platform_error',
data: { ok: false, error: 'invalid_auth', response_metadata: {} }
}
This is payload:
{
type: 'block_actions',
team: { id: '//', domain: '*** },
user: {
id: 'U010Q9X59QT',
username: '**',
name: '***',
team_id: '//'
},
api_app_id: '///',
token: '***',
container: {
type: 'message',
message_ts: '1585662258.008100',
channel_id: '****',
is_ephemeral: true
},
trigger_id: '1038328652789.1035324920279.b84d3403b8e44ab0cd53c997ba8b4c72',
channel: { id: '***', name: 'directmessage' },
response_url: 'https://hooks.slack.com/actions/T01119JT287/1040413692903/6TWTQqXhcp453TPREb7uRcPn',
actions: [
{
type: 'static_select',
action_id: 'wkR',
block_id: 'LM9',
selected_option: [Object],
placeholder: [Object],
action_ts: '1585662260.040519'
}
]
}
As token I use my main slack token, using this I'm trying to change block where I seelcted variant to another block, at the moment trying to change as string "Hello world"
Thanks in forward!!!!
Looking back at their documentation for chat.update, the token should be the access token you see on the Oauth & Permissions tab and it starts with xoxb or xoxp. Please check more about their Oauth documentation here: https://api.slack.com/authentication/oauth-v2
I faced the same issue, and eventually found out it was caused by passing the wrong token (copy-paste issues).
What helped me debug it:
Check the structure of the token. Most modern tokens start with xoxb- and have a length of 56 characters
Test that the token works before wrapping it in code, using e.g. Slack's auth test API
I am very new to Meteor and trying to develop an online synchronous game experiment. Generally, once participants AGREE to the consent form, I want to create a user and add that user into my Players collection.
My consent_page.js looks like this:
import './consent_page.html';
import { FlowRouter } from 'meteor/kadira:flow-router';
import { Template } from 'meteor/templating';
import { Meteor } from 'meteor/meteor'
import '../../../api/players/methods.js'
Template.consent_page.events({
'submit .consent-form'(event) {
event.preventDefault();
Meteor.call('players.addPlayer');
FlowRouter.go('/instructions')
}
});
and my players.addPlayer method looks like this
import { Meteor } from 'meteor/meteor';
import { Accounts } from 'meteor/accounts-base';
import { Players } from './players.js';
import { Random } from 'meteor/random'
Meteor.methods({
'players.addPlayer'() {
console.log('I am in the method');
username = Random.id();
user = create_user(username);
alert(username);
alert(user);
Players.insert({
_id: this.userId,
enterTime: new Date(),
status: 'instructions',
passedQuiz: false,
quizAttempts: 0,
needRematch: false,
condition: 'control'
});
}
});
/*
* Helper functions for the methods
*/
//create user in the server
create_user = function (username) {
return Accounts.createUser({
username: username,
});
};
The collection Players.js has the definition of the collection.
import { Mongo } from 'meteor/mongo'
export const Players = new Mongo.Collection('players');
However, this doesn't work. I do get redirected to the instructions page, but the user doesn't get created .. I get the following error:
Error invoking Method 'players.addPlayer': Method 'players.addPlayer' not found [404]
Although, I get the I am in the method message printed in the console. The alert with the return of create_user is undefined. Also, I want to create the users without a password (how can I do that?).
Accounts.createUser() method is a part of accounts-base package. You need to import that at first. I'm sharing a snippet from my working project. Hope this helps:
import { Meteor } from 'meteor/meteor';
import { Accounts } from 'meteor/accounts-base';
const bcrypt = require('bcrypt');
Meteor.methods({
'user.create':function(data){
return Accounts.createUser({
name: data.name,
username: data.userId,
password: data.password,
});
}
});
I'm invoking my methods from main.js(server) then i used Meteor.call() on main.js(client) and then I recieved an internal error[500]
here is my file structure
this is the console error
main.js(client):
import Tasks from '../imports/api/task.js';
import './main.html';
Template.tasks.helpers({
tasks() {
return Tasks.find({},{sort: {createdAt: -1}})
}
});
Template.tasks.events({
'submit .add-task': function(event){
var name = event.target.name.value;
Meteor.call('addTask', name);
return false;
},
'click .delete-task': function(event){
if(confirm('Delete Task?')){
Meteor.call('deleteTask', this._id)
}
}
});
main.js(server):
import { Meteor } from 'meteor/meteor';
import '../imports/api/task.js';
Meteor.startup(() => {
// code to run on server at startup
Meteor.methods({
addTask: function(name){
if(!Meteor.userId()){
throw new Meteor.Error('Access Denied');
}
Tasks.insert({
name: name,
createdAt: new Date(),
userId: Meteor.userId()
});
},
deleteTask: function(taskId){
Tasks.remove(taskId);
}
});
});
You need to define your methods on server side only.
Meteor.startup(() => {
// code to run on server at startup
if(Meteor.isServer){
Meteor.methods({
addTask: function(name){
if(!Meteor.userId()){
throw new Meteor.Error('Access Denied');
}
Tasks.insert({
name: name,
createdAt: new Date(),
userId: Meteor.userId()
});
},
deleteTask: function(taskId){
Tasks.remove(taskId);
}
});
}
});
Ok I already found out the answer, I though doing import '../imports/api/task.js'; in main.js(server-side) will include all the variables inside of it, the answer is that I need to this import Tasks from '../imports/api/task.js'; can someone explain the differences?
I want when user coming check if he login before - if not -> redirect to login page -> if his email & password are okay -> redirect back to welcome page.
What problem I have -> service work properly with login class but welcome class totally ignore any changes in service.
Code
users.js
export class Users {
users = [
{ name: 'Lucian', email: 'lucian1992#zalando.de', password: 'lucian' },
{ name: 'Corki', email: 'corki2010#supplier.de', password: 'corki' },
{ name: 'Vayne', email: 'vaynii#zalando.de', password: 'vayne' }];
securedUser = {};
error = {};
usedOnce = 0;
check(checkUser) {
this.usedOnce = 1;
this.securedUser = this.users.filter((user) => user.email === checkUser.email
&& user.password === checkUser.password)[0];
if (typeof this.securedUser === 'undefined'){
this.error = { message: "No such kind of user or wrong password" };
}
}
}
login.js
import {inject} from 'aurelia-framework';
import {Users} from 'users-list';
import {Router} from 'aurelia-router';
#inject(Users, Router)
export class Login {
constructor(userData, router) {
this.router = router;
this.users = userData.users;
this.check = userData.check;
this.securedUser = userData.securedUser; // Changed after check function
this.userError = userData.error;
}
checkUser = {};
login() {
this.check(this.checkUser);
if (typeof this.userError === 'undefined') {
alert(this.error.message);
} else {
this.router.navigate("")
}
}
}
welcome.js
import {inject} from 'aurelia-framework';
import {Users} from 'users-list';
import {Redirect} from 'aurelia-router';
#inject(Users)
export class Overview {
constructor(userData) {
this.usedOnce = userData.usedOnce;
this.securedUser = userData.securedUser; // This object changed in login.js, but totally ignores in this class
}
heading = 'Welcome to the Article Manager Prototype!';
canActivate() {
if (this.securedUser) {
return new Redirect('/login')
}
}
}
So, tech issue that securedUser changed in login.js, but totally ignored in welcome.js. Is this because of canActivate method? Because I also use activate() - the same problem.
Will appreciate any help with understanding the issue.
There is a solution for your problem in the official documentation:
import {Redirect} from 'aurelia-router';
export class App {
configureRouter(config) {
config.title = 'Aurelia';
config.addPipelineStep('authorize', AuthorizeStep);
config.map([
{ route: ['welcome'], name: 'welcome', moduleId: 'welcome', nav: true, title:'Welcome' },
{ route: 'flickr', name: 'flickr', moduleId: 'flickr', nav: true, auth: true },
{ route: 'child-router', name: 'childRouter', moduleId: 'child-router', nav: true, title:'Child Router' },
{ route: '', redirect: 'welcome' }
]);
}
}
class AuthorizeStep {
run(navigationInstruction, next) {
if (navigationInstruction.getAllInstructions().some(i => i.config.auth)) {
var isLoggedIn = /* insert magic here */false;
if (!isLoggedIn) {
return next.cancel(new Redirect('login'));
}
}
return next();
}
}
Notice the addition of config.addPipelineStep('authorize', AuthorizeStep); compared to the regular router config logic.
Source: http://aurelia.io/docs.html#/aurelia/framework/1.0.0-beta.1.2.2/doc/article/cheat-sheet/7
(you need to scroll down a bit to section "Customizing the Navigation Pipeline")
I tried an own example with this and maybe i found your Problem.
You are checking if your securedUser is null. If it is NOT null you will reditect to login
canActivate() {
if (this.securedUser) { // change to !this.securedUser
return new Redirect('/login')
}
}
And you are setting your securedUser initial to an empty object:
securedUser = {};
Because of that your first redirect was working even your if condition was wrong.
DonĀ“t set a initial value, set undefined or change your if condition and check on sercuredUser properties.
Your solution might work, but if you have 50 routes that must be authorised you would have to use canActivate hook 50 times! That is not an elegant solution for an authorising workflow.
This is a more elegant solution:
Instead of having a "route" to login, create an isolated root component and then update your main.js file:
//for example, imagine that your root component is located at src/app/app.js
//and your login component at src/login/login.js
//app.isLoggedIn() checks if the credentials/tokens are OK
aurelia.start().then(a => {
let rootComponent = '' app.isLoggedIn() ? 'app/app' : 'login/login';
a.setRoot(rootComponent, document.body);
});
Now, in your login/login.js root component you have to configure the router:
configureRouter(config, router) {
config.title = 'YourTitle';
config.map([
{ route: '', name: 'user-password', moduleId: './user-password', title: 'Sign In' }, //route for "username/password" screen
{ route: 'forgot-password', name: 'forgot-pwd', moduleId: './forgot-pwd', title: 'Forgot Password?' } //example of "forgot password" screen
]);
config.mapUnknownRoutes(instruction => {
//if an unknown route has been found,
//a route from the app component, 'users/add' for example
//redirect to sign-in component
return './user-password';
});
this.router = router;
}
Create appropriated methods to authenticate the user and then redirect it to the app/app component:
//import and inject { Aurelia } from 'aurelia-framework';
this.aurelia.setRoot('app/app');
Now, if an unauthorised user access 'users/add', it will be redirected to the login page. If the login succeeds, the 'users/add' page will be shown.
Hope this helps!