How to delete Meteor Users on client side? - angularjs

I'm using meteor ui twitter accounts. What I'm attempting to do is basically delete all the users from the Meteor collection when the button clear is clicked on. This is my code:
HTML File:
<div ng-controller="TweetsCtrl">
<meteor-include src="loginButtons"></meteor-include>
<ul>
<br>
<div ng-repeat="t in twitterAccs">
<img src = "{{t.services.twitter.profile_image_url_https}}">
<br>
<i>#{{t.services.twitter.screenName}}</i>
<br>
<br>
</div>
<button ng-click="clearUsers()">Clear</button>
</ul>
JS File:
if (Meteor.isClient) {
angular.module('twitter-example',['angular-meteor']);
angular.module('twitter-example').controller('TweetsCtrl',['$scope','$meteor',function($scope,$meteor) {
$scope.twitterAccs = $meteor.collection(Meteor.users);
$scope.clearUsers = function () {
$scope.twitterAccs = $meteor.collection(Meteor.users.remove({}) );
console.log("hello");
}
}]);
}

I assume this is only for development purposes right? It would suck to allow a visitor to your site to delete all your users. The fact you have a nice button set up for it has me worried it's a feature!
The easiest way to do it is hook up a Meteor.method like
if (Meteor.isServer) {
Meteor.methods({
clearUsers: function() {
Meteor.users.remove({});
}
});
}
Then do a Meteor.call('clearUsers') where your console.log("hello") is. You can also run the call via the browser console, I do this setup sometimes instead of going directly to the db via the terminal.
You could also do it via allow deny rules (see: http://docs.meteor.com/#/full/allow), by default a rule is setup so a user can only edit their own profile object.
Lastly you could include the meteor package insecure (I assume you must have already removed it) which will allow anyone to edit any collections assuming you haven't set up any of the allow, deny rules mentioned above.

Related

How to change domain name (entire url) in react-router-dom

If I am in http://localhost:3000/Authpage I want to redirect to new URL http://www.example.com/
Usehostory() -> histor.push() is appending new url to old url.
http://localhost:3000/Authpage/http://www.example.com/
But I need new location something like below
http://www.example.com/
You can have a look at this thread here for an answer.
To summarize it, in your event handler you can add
const eventHandler = () => {
window.location.assign('http://www.example.com/')
}
However, the way I see it, it's just easier to create a simple regular HTML <a> tag:
<a href='http://www.example.com/'>click to redirect</a>
you have 2 options
use tag to redirect the user into a new web page.
or use one of the javascript methods like window.open("yourUrl.com")
but be careful when you are using javascript methods to redirect the user because the safari browser would not let you use some of them( because of some security filters)
You should use window.location.assign. For example
handleClick() {
window.location.assign('http://www.example.com/');
}
render() {
return (
<button onClick={this.handleClick.bind(this)} />
);
}`

Twilio flex UI get worker attributes and show sideNav button to admin only

I am building a custom twilio flex react-plugin.
I am trying to add an custom view with a sidenav button.So the button should be visible for admin only.
I am trying to access current worker attribute and check if the role includes "admin".
init(flex, manager) {
// adds the sms button to the navbar
flex.SideNav.Content.add(<customButton key="nav-custom-button"/>,
{
sortOrder: 1,
if: (props) => props.worker.attributes.roles.includes( 'admin'),
});
But the flex local instance can not load and trying to authenticate repeatedly.
I have also tried
if( manager.worker.attributes.roles.includes( 'admin')){
flex.SideNav.Content.add(<OutboundSmsButton key="nav-outbound-sms-button"/>);
}
It logs error in console can not read property attributes of undefined.
Whats the right way to fetch worker(for current agent)attributes in a twilio react plugins?
The solution would be as below:
if( manager.workClient.attributes.roles.includes( 'admin')){
flex.SideNav.Content.add(<OutboundSmsButton key="nav-outbound-sms-button"/>);
}
or if its not inside init(flex,manager), it will be needed to import flex
like below:
import * as Flex from '#twilio/flex-ui';
let mgr = Flex.Manager.getInstance()
let roleName = mgr.workerClient.attributes.roles
if( roleName.includes( 'admin')){
flex.SideNav.Content.add(<OutboundSmsButton key="nav-outbound-sms-button"/>);
}
source:
https://www.twilio.com/docs/flex/developer/ui/manager
https://twilio.github.io/twilio-taskrouter.js/Worker.html

Meteor React tutorial interacting with mongo not working

I have been trying for a while to learn how to build mobile apps with Javascript, and honestly I have no idea how anyone is able to do anything. Everything is broken. Every tutorial I've tried has failed to work for some bizarre reason. I am at my wits end.
I've finally decided to try and be even simpler, and just do the most basic tutorial I can find. What could go wrong. Well, it only took 3 pages of almost no code to completely stop working. I've done this, and I cannot insert anything to my db. My app fetches no data. When trying to add a new task, it gets added then disappears almost immediately, with a message stating insert failed: Method '/tasks/insert' not found (not even an error with some traceback).
The code really couldn't be simpler:
// imports/api/tasks.js
import { Mongo } from 'meteor/mongo';
export const Tasks = new Mongo.Collection('tasks');
// imports/ui/App.js
import React, { Component } from 'react';
import ReactDOM from 'react-dom';
import { withTracker } from 'meteor/react-meteor-data'
import { Tasks } from '../api/tasks.js';
import Task from './Task.js';
// App component - represents the whole app
class App extends Component {
handleSubmit(event) {
event.preventDefault();
// find the text field via the react ref
const text = ReactDOM.findDOMNode(this.refs.textInput).value.trim();
Tasks.insert({ text, createdAt: new Date() });
// Clear form
ReactDOM.findDOMNode(this.refs.textInput).value = '';
}
renderTasks() {
return this.props.tasks.map((task) => (
<Task key={task._id} task={task} />
));
}
render() {
return (
<div className="container">
<header>
<h1>Todo List</h1>
<form className="new-task" onSubmit={this.handleSubmit.bind(this)} >
<input
type="text"
ref="textInput"
placeholder="Type to add new tasks"
/>
</form>
</header>
<ul>
{this.renderTasks()}
</ul>
</div>
);
}
};
export default withTracker(() => {
return {
tasks: Tasks.find({}).fetch(),
};
})(App);
What is wrong? What am I missing?
The tutorial is indeed out of date and should be updated.
Background
In June 2017 there was a big security issue with allow/deny identified and the feature has been blocked since then.
Meteor allowed you to define client collection, that automatically synced with the server when the methods insert, update, remove were called on the client.
In order to control the access permissions, the allow/deny feature was implemented.
Now without allow/deny you will get the insert failed: Method '/tasks/insert' not found when classing SomeCollectionOnClient.insert but since this feature is obsolete (you will even get a big warning when setting it up), you need to create a server side method and call it from the client in order resolve this issue:
On the server create this method and ensure it is in the import chain from server/main.js:
new ValidatedMethod({
name: 'tasks.insert',
validate(args) {
// better use simpl-schema here
if (!args.text || !args.createdAt) {
throw new Meteor.Error('incompleteArgs', 'args are incomplete')
}
},
run (args) {
// check user permissions...
return Tasks.insert({ text, createdAt })
}
})
In your client component you can then call it via:
// find the text field via the react ref
const text = ReactDOM.findDOMNode(this.refs.textInput).value.trim();
Meteor.call('tasks.insert', {text, createdAt: new Date()}, (err, res) => {
// do something on err / on res
})
Note that this couples your component to the server side method and you may rather try to implement some containers for your pages that handle all the connection / pub-sub / method calling activity wile your components solely render content.
More to read / used in this answer:
https://guide.meteor.com/react.html
https://guide.meteor.com/security.html
https://docs.meteor.com/api/methods.html#Meteor-call
https://guide.meteor.com/methods.html#validated-method

Symfony4 backend with frontend react. best and safest way to pass information?

I am learning React and want to create an application with Symfony4 as my backend and React frontend. I am stuck now when I need to pass some kind of data to the frontend from my backend. I don't really know what is the right way to do it? Following some tutorials I am doing it like this:
From the controller I send some data to the twig file:
/**
* #Route("/")
*/
public function homepage()
{
$date = new DateTime();
$curr_date = $date->format('Y-m-d H:i:s');
return $this->render('base.html.twig', [
'gameDate' => $curr_date
]);
}
In the twig file, I set it as a data-attribute
base.html.twig:
<div id="root" data-event-date="{{ gameDate }}">
Then I can get the variable as a dataset in my JavaScript
App.js:
const root = document.getElementById('root');
ReactDOM.render(<Homepage {...(root.dataset)}/>, root);
And render it from props.
Homepage.js:
class Homepage extends Component {
constructor(props) {
super(props)
this.state = {
prizePool: '',
gameDate: '',
numberOfPlayers: ''
}
}
onParticipateClick = (event) => {
this.setState({prizePool: Math.random()})
}
render()
{
return (
<div className="mt-c-10">
<GameInfoBox gameDate={this.props.eventDate}/>
</div>
)
}
}
This actually works, but I am concerned with showing all the information in data variables because anyone can see it. What if I want to pass user ID or something secret? There should be another way to do it right?
It depend on what you attemps, if you are working on big project, you can use API to serve backend data. Take a look here: https://www.modernjsforphpdevs.com/react-symfony-4-starter-repo/. There is a simple example.
But if you want something more use api-platform or FOSRestBundle.
"Best and safest" is a little ambiguous - do you need strict security, or safe as in code stability etc?
Instead of passing your data from controller to view (twig) and then into HTML elements or global, another way is this:
Controller loads the view file with your nav and other stuff
Controller loads React (however you do this, Webpack etc)
React calls another controller (i.e. fetch()). This controller is probably somewhere like src/Api/Controller/ as it wont render a view so keep it separate to the other controllers which do render a view
The API controller calls your DB or remote API (etc) and gets the data and sends it back as JsonResponse back to React.
React can then show the data, or an error message depending on the response status
The API controller in your MW can also handle errors and do some logging, so React just gets a 200 and the data or a 400 (or whatever) and it can show a nice message to the user as normal.

Update on dashboard

Well, I'm working on a mobile application with ionic framework. In one of my views, the user can edit your name, password and also its image. For this I am using the CordovaFileTransfer plugin and it works great for me. I'm managing to change the image and all the data I need. But not even like getting to change the data in my database, update the application. Let me explain.
When the user changes their image or their data, the web service response returns a "status 1" if achievement make the change successfully and also the URL of the image and the new name change. This we have in localStorage variables and $ rootScope within my application which update once it receives a status one from my server but to return to my dashboard application that is not updated, I close and open the application again and reflected the changes. As a way to do it, maybe my question is very basic but that works for more than one person.
JSON WEBSERVICE RESPONSE :
Object {status: 1, photo: "www.google.cl/de5a0cc049d0f3c394befb83d2cb44e3.jpg", name: "Test"}
Code controller angularjs
$cordovaFileTransfer.upload(encodeURI(server),image,ftOptions,true)
.then(function(result) {
var respuestaJSON = jQuery.parseJSON(result.response);
if(respuestaJSON.status == 1){
sessionService.set("user",respuestaJSON.name);
sessionService.set("photo", respuestaJSON.photo);
$rootScope.username = sessionService.get("user");
$rootScope.photo = sessionService.get("photo");
sessionService :
.factory('sessionService',['$http',function($http){
return {
set:function(key,value){
return localStorage.setItem(key,JSON.stringify(value));
},
get:function(key){
return JSON.parse(localStorage.getItem(key));
},
destroy:function(key){
return localStorage.removeItem(key);
},
};
}])
HTML CODE :
<div id="dashboard-header">
<center>
<div id="home-avatar" style="background-image:url('{{photo}}')"></div>
</center>
</div>

Resources