SSR and user management

Hi everyone.

I am starting an app with SSR and I followed this great article :

Everything worked fine and easy until I reached accounts management. I’d like to know more about handling users Method from accounts-base which apparently are not rechable on server side.

I used to have client rendered apps and it was easy to manage but now I am struggling a lot. For example I like to give an isAdmin boolean to my users and publish it as userData. This boolean is compulsory to reach my /admin panel, and now the only way I found to make this work was this :

export class Admin extends React.Component {
  render () {
		if (Meteor.isClient){
				if(Meteor.user()) {
					if(Meteor.user().isAdmin){
						return (
							<div className="admin">
								Admin
							</div>
						)
					} else {
						return (<Redirect to="/" />)
					}
				} else if(this.props.loggingIn) {
					return null;
				} else {
					return (<Redirect to="/" />)
				}
    } else {
      return (<Redirect to="/" />)
		}
  }
}

export default withTracker(() => {
	if (Meteor.isClient){
		const loggingIn = Meteor.loggingIn()
		return { loggingIn }
	}
	return {}
})(Admin)

Seems very complicated to me, anyone has any idea how I could manage this better ?

You can turn off ssr for admin pages.

Any leads on where to find the doc about this, still very new to SSR. But thanks for the tip.

Here is an example:

onPageLoad(async (sink) => {
  // try to disable server render for some pages
  const { url } = sink.request;
  const adminRegex = new RegExp('^/admin/');
  if (adminRegex.test(url.path)) {
    return;
  }
  // do the rest server render here
}
1 Like

Ok thanks, will try that, though not yet sure or where to put it in relation to the StaticRouter on the server side.

Right now I have this:

onPageLoad((sink) => {
  const context = {};
  const store = createStore(mainReducer, { selectedIndex : 0}, applyMiddleware(thunk))

  const App = props => (
		<Provider store={store}>
			<StaticRouter location={props.location} context={context}>
				{routes}
			</StaticRouter>
		</Provider>
  );

  App.propTypes = {
    location: object.isRequired,
  };

	const preloadedState = store.getState();

  sink.renderIntoElementById('app', renderToString(<App location={sink.request.url} />));

  sink.appendToBody(`
    <script>
      window.__PRELOADED_STATE__ = ${JSON.stringify(preloadedState).replace(/</g, '\\u003c')}
    </script>
  `);
});

Shall I return before I even reach the Router ?

Yes. Try to return on very top of function.

Thanks a lot, seems to work, code now is like that :
render () {

		if(!this.props.ready){
			return null
		}
		if (!this.props.user || !this.props.user.isAdmin){
			return (<Redirect to="/" />)
		}
		return (
			<div className="admin">
				<h1>Admin</h1>
				<AddCategory />
			</div>
		)
	}
}

export default withTracker(() => {
	let subUSerData = Meteor.subscribe('userData');
	const loggingIn = Meteor.loggingIn();
	const user = Meteor.user()
		return { loggingIn, ready: subUSerData.ready(), user }
})(Admin)

and added following lines right after onPageLoad on server side:

  if(['/login','/signup', '/admin'].indexOf(sink.request.url.pathname) > -1){
    return
  }