When I run meteor it says "location is not defined"
// redirect on start to dashboard on file protocol
if(location.origin === 'file://') {
FlowRouter.wait();
FlowRouter.initialize({hashbang: true});
Meteor.startup(function() {
FlowRouter.go('dashboard');
});
}
Do you mean window.location.origin ?
Documentation
https://github.com/TylerL-uxai/decentralized-website
I solved it with an if statement
// redirect on start to dahsboard on file protocol
if (typeof location != 'undefined') {
if(location.origin === 'file://') {
FlowRouter.wait();
FlowRouter.initialize({hashbang: true});
Meteor.startup(function() {
FlowRouter.go('whatIdo');
});
}
}
Related
I have set up a NEXTJS app that is under a subdomain and basically the structure is the following:
/Pages->
--/Sites
--/api
--/home
--/subdomain_logic
--_app.tsx
...config files...
As of this moment, if you go to domain.com you will be landing into another app that I developed so there is nothing configured outside of subdomain logic. If you go to subdomain.domain.com then you get all the logic ocurring into subdomain_logic. I want to set api routes but nextjs doesn't allow to set them outside of your api folder and if I leave them there those routes actually belong the domain.com app that I have in isolation. How would you create api routes on my situation?
Here is my middleware.ts file:
import { NextRequest, NextResponse } from "next/server";
export const config = {
matcher: [
"/",
"/([^/.]*)", // exclude `/public` files by matching all paths except for paths containing `.` (e.g. /logo.png)
"/site/:path*",
"/post/:path*",
"/_sites/:path*"
]
};
export default function middleware(req: NextRequest) {
const url = req.nextUrl;
const pathname = req.nextUrl.pathname.toString();
const hostname = req.headers.get("host");
if (!hostname)
return new Response(null, {
status: 400,
statusText: "No hostname found in request headers"
});
const currentHost =
process.env.VERCEL_ENV === `production` ||
process.env.VERCEL_ENV === `preview`
?
hostname
.replace(`.domain.com`, "")
.replace(`${process.env.VERCEL_URL}`, "")
.replace(`${process.env.NEXT_PUBLIC_VERCEL_URL}`, "")
: hostname.replace(`.localhost:3000`, "");
if (pathname.startsWith(`/_sites`))
return new Response(null, {
status: 404
});
if (
!pathname.includes(".")
) {
if (currentHost === "subdomain") {
if (
pathname === "/login" &&
(req.cookies["next-auth.session-token"] ||
req.cookies["__Secure-next-auth.session-token"])
) {
url.pathname = "/";
return NextResponse.redirect(url);
}
url.pathname = `/subdomain${url.pathname}`;
console.log(url);
return NextResponse.rewrite(url);
}
url.pathname = `${pathname}`;
return NextResponse.rewrite(url);
}
}
I would like to set up properly NextAuth if that give more clues into what could be the solution for my problem. Thanks for the help!
So where you are doing your redirect you basically want to do a check if its the api directory and not run those rewrites. Not sure what some of your code is doing but here is something that i am doing in a project with a similar setup.
If you reference your api endpoints via either the main or the subdomain it should still route correctly.
I am a bit confused by your question and how you are looking to integrate next auth, feel free to drop a comment if i've misunderstood anything.
import { NextRequest, NextResponse } from "next/server";
export default function middleware(req: NextRequest) {
const { pathname } = req.nextUrl;
const url = req.nextUrl.clone();
let hostname = req.headers.get("host");
hostname = hostname?.split(":")[0] ?? null;
const rootUrls = `${process.env.ROOT_URLS}`.split(",");
// only continue if its not a custom domain happening.
if (!rootUrls?.includes(hostname!)) {
// get the current subdomain or custom domain
const currentHost = hostname!.replace(`.${process.env.ROOT_URL}`, "");
if (pathname.endsWith("sitemap.xml")) {
url.pathname = `/_sites/${currentHost}/sitemap`;
return NextResponse.rewrite(url);
}
if (pathname.endsWith("robots.txt")) {
url.pathname = `/_sites/${currentHost}/robots`;
return NextResponse.rewrite(url);
}
// fail if trying to access the site directory
if (pathname.startsWith(`/_sites`)) {
return new Response(null, { status: 404 });
}
if (pathname.startsWith(`/_sites_previews`)) {
return new Response(null, { status: 404 });
}
if (
!pathname.includes(".") && // exclude all files in the public folder
!pathname.startsWith("/api") // exclude all API routes
) {
if (req.nextUrl.searchParams.get("preview")) {
url.pathname = `/_sites_previews/${currentHost}${pathname}`;
} else {
url.pathname = `/_sites/${currentHost}${pathname}`;
}
// rewrite to the current hostname under the pages/sites folder
// the main logic component will happen in pages/sites/[site]/index.tsx
return NextResponse.rewrite(url);
}
}
}
This Meteor app has the insecure and autopublish removed and accounts-password added.
It uses Accounts.createUser({username: someName, password: somePwrd});
It avoids using allow/deny and uses instead Meteor.call to insert documents because reading in the docs, it says that
Server code is trusted and isn't subject to allow and deny restrictions. That includes methods that are called with Meteor.call — they are expected to do their own access checking rather than relying on allow and deny.
But when I fire up the Meteor.logout(), I am still able to insert new documents to Tasks1 collection. How can that be? I though logout will stop inserting any new documents. How can I fix it? Thanks
///////////////////////////
//both/both.js
///////////////////////////
Tasks1 = new Mongo.Collection('tasks1');
///////////////////////////
//server/server.js
///////////////////////////
Meteor.publish('tasks1', function(){
return Tasks1.find({userId: this.userId});
});
Meteor.methods({
addTasks1: function (doc) {
Tasks1.insert(doc);
}
});
///////////////////////////
//client/client.js
///////////////////////////
Template.footer.events({
'click button': function () {
if ( this.text === "SUBMIT" ) {
var inputs = document.getElementsByTagName('input');
for (var i = 0; i < inputs.length; i++) {
var params = {};
params[inputs[i].name] = inputs[i].value;
Meteor.call('addTasks1', params);
}
}
}
});
Template.mainMenu.events({
'click #logout': function () {
Meteor.logout();
}
});
In your server addTasks1 method, you should first check if the user is a user like so:
Meteor.methods({
addTasks1: function(doc) {
if (!Meteor.userId()) {
throw new Meteor.Error("Not Authorized");
} else {
Tasks1.insert(doc);
}
}
})
Logout alone doesn't stop users from being able to insert. You must edit your method code to achieve this.
addTasks1: function (doc) {
if (Meteor.userId()) {
Tasks1.insert(doc);
}
}
I'm attempting to use Meteorjs Accounts on the server to create a new user and then send them an email to set their initial password. The idea is that an admin user can add new users.
I can successfully add the new user (I can see the new user ID in the server console if I log it), but that ID is never returned to the client. This is my server-side
Meteor.methods({
createNewUser: function(email){
return Accounts.createUser({email: email});
}
});
And the relevant client-side JS:
if (isNotEmpty(email) && isEmail(email)) {
Meteor.call("createNewUser", email, function(ret){
if (typeof ret.message !== 'undefined') {
if (ret.message === 'Email already exists. [403]') {
alert("exists");
} else {
alert("not created");
}
} else {
Accounts.sendEnrollmentEmail(ret, function(err){
if (err){
alert("email didn't get sent");
} else {
alert('success');
}
});
}
});
}
I get this in my browser console:
Exception in delivering result of invoking 'createNewUser': TypeError: Cannot read property 'message' of undefined
It's probably worth noting that I also get the "exists" alert if I try to submit the same email address twice in a row, so the error is getting returned to the client just fine.
The first argument in callback is always error object.
error equals null if everything is fine.
Meteor.call('createNewUser', email, function( error, result ){
if( error ){
console.error("ERROR -> ", error )
}else{
console.log("User was created!")
}
})
but that ID is never returned to the client.
Thats because you don't have any console.log on the client. also the meteor call look incorrect.
if (isNotEmpty(email) && isEmail(email)) {
Meteor.call("createNewUser", email, function(err,result){
if (typeof ret.message !== 'undefined') {
if (ret.message === 'Email already exists. [403]') {
alert("exists");
} else {
console.log(result) //here for example you should get the id
}
} else {
Accounts.sendEnrollmentEmail(ret, function(err){
if (err){
alert("email didn't get sent");
} else {
alert('success');
}
});
}
});
}
I'm using the built in loginButtons options with Meteor and I would like to redirect after a user logs in. Using the built in web snippets means I can't use the callback with Meteor.loginwithPassword and I can't see any hooks inside Iron-Router to do the redirect.
Any suggestions?
Meteor often renders so quickly that the page is being loaded before the user has been defined. You need to use Meteor.loggingIn() to account for the situation in which you are in the process of logging in. This code works for me:
this.route('myAccount', {
path: '/',
onBeforeAction: function () {
if (! Meteor.user()) {
if (!Meteor.loggingIn()) Router.go('login');
}
}
}
This example might be useful
// main route render a template
Router.route('/', function () {
this.render('main');
});
// render login template
Router.route('/login', function () {
this.render('login');
});
// we want to be sure that the user is logging in
// for all routes but login
Router.onBeforeAction(function () {
if (!Meteor.user() && !Meteor.loggingIn()) {
this.redirect('/login');
} else {
// required by Iron to process the route handler
this.next();
}
}, {
except: ['login']
});
// add here other routes
// catchall route
Router.route('/(.*)', function () {
this.redirect('/catchallpage');
});
it should be very easy just add something like:
Tracker.autorun(function() {
var currentRoute = Router.current();
if (currentRoute === null) {
return;
}
if (currentRoute.route.getName() === 'login' && Meteor.user() !== null)
Router.go('WelcomeNewUser');
}
You can also just use the same route with another template in case the user is not logged in.
just something like this:
this.route('myAccount', {
before: function () {
if (!Meteor.user()) {
this.render('login');
this.stop();
}
}
}
There is no magic, just looked into the docs ;)
You can simply use one of your existing routes you have configured in Ireland route
Router.go('/myRouterPathToTemplate')
I have made an facebook app. Now i need to take user information using a pop-up permission box. If a user has authenticated the app, facebook should not open dialog box for permission but if a user comes to app first time then it must open a dialog box. What I am trying to do here is...and getting error like...
Cannot call method 'showPermissionDialog' of undefined
FB.getLoginStatus(function (response) {
if (response.status === 'connected') {
alert("1");
// the user is logged in and has authenticated your
// app, and response.authResponse supplies
// the user's ID, a valid access token, a signed
// request, and the time the access token
// and signed request each expire
var uid = response.authResponse.userID;
//alert(uid);
var accessToken = response.authResponse.accessToken;
jQuery("#<%= accessToken.ClientID %>").val(accessToken);
// alert(accessToken);
fqlQuerynew();
} else if (response.status === 'not_authorized') {
// the user is logged in to Facebook,
// but has not authenticated your app
alert('not_authorized');
OnRequestPermission();
} else {
alert("3");
//alert('the user isnt logged in to Facebook');
}
});
};
function OnRequestPermission() {
var myPermissions = "publish_stream, manage_pages"; // permissions your app needs
FB.Connect.showPermissionDialog("email,offline_access", function (perms) {
if (!perms) {
alert("hi");
// document.location.href = 'YouNeedToAuthorize.html';
} else {
alert("buy");
document.location.href = 'homePage.html';
}
});
}
If you have just copied and pasted it from your code then I think you have added one extra closing bracket after FB.getLoginStatus '};'.
After removing that try your code. If it doesn't work then can we know when you want to check login status like after clicking some social button or while loading page.
Here's a modified version of your code, I haven't tested it and it's not complete, but should give you an idea of what to do:
FB.getLoginStatus(function (response) {
if (response.status === 'connected') {
var uid = response.authResponse.userID;
var accessToken = response.authResponse.accessToken;
jQuery("#<%= accessToken.ClientID %>").val(accessToken);
fqlQuerynew();
} else if (response.status === 'not_authorized') {
OnRequestPermission();
} else {
...
}
});
function OnRequestPermission() {
var myPermissions = "publish_stream, manage_pages"; // permissions your app needs
FB.login(function(response) {
if (response.status === 'connected') {
FB.api("me/permissions", checkPermissions);
}
else {
....
}
}, { scope: "email,offline_access" });
}
function checkPermissions(response) {
if (response.data && response.data.legth == 1) {
var perms = response.data[0];
// iterate over perms and check if the user has all needed permissions
}
}