Note, Branden was the TA for ICS 314 from 2020 til 2022.
This page provides answers to some of the questions about Meteor asked by students during the past few semesters0.
Since the initial passwords for the template are stored in plain text in /config/settings.development.json, should projects based on this template be stored in a private repository?
No. The settings.development.json file provides an example to developers of how to define admin accounts on startup. As you will learn in the deployment module, you will define a different file named settings.json in which you store “real” account credentials for initial startup. For more details on settings files in Meteor, please see The Meteor Chef: Making use of settings.json.
More generally, you should always make repositories public unless there is a compelling reason to make them private. You should make as much of your professional work visible as possible: even “draft” versions of systems provide evidence to graduate schools and future employers that you are actually attempting to do development.
When should we use .jsx files instead of .js files and vice versa?
In general, use .jsx whenever you use (React) components in the file and .js otherwise.
Do the functions (ex. addData in /app/imports/startup/server/stuff.js) have to be in specific files?
Functions can be in any file that is import
ed where the function is used. However, if a function is only used on one file it makes sense to place the function in that one file. addData
is only used in initializing the seed data for the Stuffs
collection, so it is located in the file that handles the Stuffs
collection on the server side.
How does if (this.userId) {…} check if the user is logged in or not? What does the this keyword refer to here?
The documentation for this.userId
is here. If the user is logged in, this.userId
exists and is a truthy value. If the user is not logged in, this.userId
is undefined
, which is a falsy value.
See the Meteor Guide for documentation on why this.userId
works.
How does if (Meteor.settings.defaultData) work?
As with the previous question, Meteor.settings.defaultData
will be a truthy value if it exists and a falsy value otherwise.
How would we make a Meteor project from scratch (that is, without using meteor-application-template-react)? What files would we have to create?
You have already done something like this; note though that the template basically includes everything that you would need on a site. Most websites that are complex enough to merit using Meteor will have some sort of user accounts and data associated with those accounts.
That said, it is typically not in your best interest to start a Meteor project without using some sort of boilerplate template. This is because templates help ensure that as your application grows in complexity, the organization of the system remains stable. Templates also implement a “design pattern”: a commonly recognized idiom for software development. meteor-application-template-react is not the only template available for Meteor, but it’s the one that will best serve you for developing your final project.
Are the names of the directories significant?
At the top-level, yes. Meteor has rules for where to place file in order for them to be automatically loaded. Essentially, anything covered in Example directory layout should be exactly as is; you have some flexibility in naming anything else.
Directory names are also useful as documentation: the files in /app/imports/startup should have something to do with what happens when the server starts up, /client directories are only visible on the client side, /server directories contain files only visible on the server side, etc. Something like the stuff directory for /app/imports/api/stuff/stuff.js could be named differently though; however, we name it stuff in accordance with convention and general common sense.
Is it safe to log in while already logged in?
Yes.
Can we just write HTML files in /app/client?
Technically yes, but this is a design-level error. Restricting yourself to only HTML means that you will not benefit from all the features that Meteor (and React) provide. All of your content should appear in the imports/ directory.
Is the landing page basically the home page?
No. In this class, we distinguish between the landing page, which is the page that all users see when they navigate to the site, and the home page, which is the page that users see immediately after successfully logging in.
So, the home page shows private content specific to a user, while the landing page shows public content to any visitor to the site.
What is the relationship between /app/client/main.html, /app/imports/startup/client/startup.jsx, and /app/imports/ui/layouts/App.jsx?
/app/client/main.html is the base of the HTML rendered in the browser. Although this main.html file does not directly load the main.js or style.css files, Meteor automatically loads everything in /app/client, and it is /app/client/main.js that imports all files in /app/imports/startup/client, including /app/imports/startup/client/startup.jsx. This startup.jsx file then import
s and render
s /app/imports/ui/layouts/App.jsx.
What is the difference between /app/client and /app/imports/startup/client? /app/server and /app/imports/startup/server?
/app/client/main.js and /app/server/main.js are defined as special files that load other files for the client and server sides respectively; see the relevant documentation here. The /app/imports directory is not directly loaded into the application by default, making it necessary to import
files within those directories in /app/client/main.js and /app/server/main.js.
Why the split between /client and /server? Why not make all data visible on both sides?
Because server-side code has complete access to the database, and you almost never want every user to have access to all of the data (such as a list of all registered users and their email addresses).
What is the difference between meteor run and meteor npm run start?
meteor run
is a built-in Meteor command that will start the application. meteor npm run start
is a project-specific command that will start the application. You may have noticed that we used meteor run
for the MongoDB experiences and many of the Meteor 1 experiences and meteor npm run start
for the Meteor 2 experiences. This is because the latter command depends upon the files in the templates you have used.
If you look at the package.json file in meteor-application-template-react, you should see the following (with … to truncate the parts not of immediate concern):
{
"name": "meteor-application-template-react",
"private": true,
"dependencies": {
...
},
"devDependencies": {
...
},
"scripts": {
"start": "meteor --no-release-check --settings ../config/settings.development.json",
"lint": "eslint --quiet --ext .jsx --ext .js ./imports"
}
}
The "scripts"
contain "start"
and "lint"
members. You may have noticed the similarity between meteor npm run start
and meteor npm run lint
. This is because both are shortcuts defined within package.json. By this definition, meteor npm run start
will run the meteor --no-release-check --settings ../config/settings.development.json
command.
--no-release-check
prevents Meteor from searching for and downloading updates, which would otherwise take some time to complete--settings ../config/settings.development.json
specifies the ../config/settings.development.json file as the settings file to use for the applicationIf you are using the templates provided for this course, you will almost always want to use meteor npm run start
to run your Meteor applications. (The one exception that your teaching assistant can think of is when you want to test your ./app/.deploy/settings.json file before deploying to Digital Ocean.)
Why does IntelliJ IDEA suddenly not recognize that some of my .jsx files are React JSX files? The syntax highlighting is broken and the icon for the file looks different from the other .jsx files.
Your teaching assistant is not certain of the exact cause of this problem; it may have something to do with your file being mistakenly created as a text file (or a file without a file extension, which IntelliJ will treat as a regular text file). To fix this, open Settings (Ubuntu/Windows) or Preferences (MacOS), then Editor > File Types, then find Text in the Recognized File Types list. If the file causing problems appears in the File Name Patterns list, select that item in the list and click the - button to the right to remove that item.
How does the application remember the user accounts and other data even after terminating the Meteor process?
When you use a computer, you have to save your work before shutting down the computer. That data is stored in a file and you can open that file later to resume your work. Databases serve the same purpose: your application stores data in the database so the data is preserved even after the application has closed.
Where is all of the data stored?
The technically correct answer is /app/.meteor/local/db, though that is probably not of direct use to you since the data is not stored in a human-readable format. Aside from a tired attempt at sarcasm, this does show that the data is in the project directory, so you do not have to worry about data from one project intermingling with data from another project1.
The more useful answer is that you do not have to worry about where the data is stored: MongoDB takes care of preserving the data for you.
How are passwords stored? What prevents an attacker2 from accessing those passwords?
If we look at the users
collection in the MongoDB console, we see:
meteor:PRIMARY> db.users.find()
{ "_id" : "RvkbtmXXDoRDYeohc", "createdAt" : ISODate("2019-03-11T01:48:08.812Z"), "services" : { "password" : { "bcrypt" : "$2a$10$mS4VO9apDZC.Ul6U1YtfHOtgsY8JwVlCNq7muej4GgCTGTRyiW9K6" } }, "username" : "admin@foo.com", "emails" : [ { "address" : "admin@foo.com", "verified" : false } ], "roles" : [ "admin" ] }
{ "_id" : "Bf2XizdLC5fRq4BCk", "createdAt" : ISODate("2019-03-11T01:48:09.014Z"), "services" : { "password" : { "bcrypt" : "$2a$10$OZh60hVYwNNBVJ.SZ4q6oegTEHdFRS4SSpDKbNMTxSZIa7y/pnE7." }, "resume" : { "loginTokens" : [ { "when" : ISODate("2019-03-11T02:24:40.264Z"), "hashedToken" : "Oz02OPH48WBQeyIJ3M6nIztlYHfok6V/uWBG9VDPuSM=" } ] } }, "username" : "john@foo.com", "emails" : [ { "address" : "john@foo.com", "verified" : false } ] }
In particular, note that the password
field for the first user has a value of { "bcrypt" : "$2a$10$mS4VO9apDZC.Ul6U1YtfHOtgsY8JwVlCNq7muej4GgCTGTRyiW9K6" }
. This is very clearly not the default password provided in /config/settings.development.json. Storing passwords as plain text is very much a bad idea; instead, we apply a hash function to the password and store that hashed value. When someone attempts to log in as the user, we then use the same hash function. If the hashed value of the input matches the value stored in the database, then we are reasonably certain that the password is correct3; otherwise we know we can reject the login.
The Meteor > MiniMongo tab shows all of the collections in the database that are published on the current page; what stops the users collection from displaying passwords?
Per the documentation for meteor/accounts-base
, “by default, the current user’s username
, emails
and profile
are published to the client”; our users
have no profile
field and we add in roles
, but the password
field is not included in the list of published fields and therefore will not appear in the developer tools.
bcrypt allows us to hash passwords.
Is it possible to get rid of the bcrypt warning message in the Meteor console?
NOTE: June 2022 More recent versions of Meteor no longer have this error.
Yes, but it is probably not worth the time. As noted on the course website, the performance issues with bcrypt will only occur on logins and those are relatively uncommon. One might even argue that slower logins are a security feature as it forces an attacker to wait longer between attempts to break in, and after a certain point said attacker may well decide that your site is not a time-efficient target.
What is the purpose of having sample data in /config/settings.development.json?
We use the seed data in /config/settings.development.json to populate the database the first time that we start the application. This gives us enough data to test the application: the seed data for meteor-application-template-react allows us to immediately log in and interact with the website without having to touch the MongoDB console.
Can you define multiple schemas for the same collection?
Yes; see the attachSchema
documentation. meteor-application-template-react provides an alternate approach that does not necessarily attach schemas to collections: AddStuff
defines a formSchema
constant to use within the file while EditStuff
uses the StuffSchema
defined along with the Stuffs
collection in /imports/api/stuff/Stuff.js. meteor-example-form-react creates a separate forms directory to store these schemas.
Can we expand the Meteor.users collection to contain more data?
Yes, but this is not recommended practice as the Meteor.users
collection has a number of specialized behaviors that might interact negatively with your design goals. A more simple approach is to define a new collection called something like UserProfiles
, and provide a field in that collection that stores the userID associated with that document.
How can we enforce password constraints (ex. a minimum length, must contain numbers, etc.)?
See the Simple Schema documentation; min
is easy enough for the minimum length, though you may have to write a separate function to perform custom validation or use regular expressions.
How can we allow users to change their passwords?
See the documentation for Accounts.changePassword
.
How are passwords case-sensitive while user names are not?
See the Meteor notes on case sensitivity. In other systems that do not provide helper methods to take care of this, you might convert the usernames or email addresses to lowercase before saving them or comparing them to values in the database.
What is that “verified” : false in the “emails” field? How do we change that value?
This indicates that the email address has not been verified yet: it may be a valid email address but we do not know that it actually exists and belongs to the user. Accounts.sendVerificationEmail
allows us to start that verification process.
What is the { tracker: Tracker } in /app/imports/api/stuff/stuff.js used for?
Tracker
listens for changes on your data sources; see the Simple Schema documentation for notes on how this is integrated with Simple Schema.
If we remove “defaultData” from /config/settings.development.json after running the application for the first time, will those values be removed from the database?
No, by that point the values from "defaultData"
are already in the database and removing them from the seed data will have no impact on the database.
Is StuffAdmin another database that runs alongside Stuff?
No, both Stuff
and StuffAdmin
are publications: they contain data from the database but are not databases themselves.
What does withTracker do in some of the pages (ex. /app/imports/ui/pages/EditStuff.jsx)?
The withTracker
function provides access to the necessary publications from the database through setting up subscriptions; see more details in the official documentation.
Does Meteor + MongoDB allow users to create immutable data?
It is possible in MongoDB to define collection-level access control that prevents users from modifying the contents of the database. This effectively results in immutable data.
However, since the MongoDB admin defines the access control, the data is still not completely immutable: admin users can still modify it. This was pretty much a fundamental fact of life for databases—that admins can alter data—until the invention of the blockchain. Indeed, one way to look at the motivation for the development of blockchain technology was to prevent database admins from being able to alter the contents of a database!
Can Meteor be used with databases other than MongoDB?
Yes, through GraphQL.
The template shows how to add, edit, and show documents in a collection; how do you delete a document?
Use Collection#remove
.
Why do we need export statements for the components? Does import not load in everything from the file?
import
is not analagous to the #include
in C and C++: it does not insert the entire imported file. Instead, you must export whatever you want to import in a different file. This may seem cumbersome at first, but this system allows for more flexibility and efficiency since you only import what you actually need. For example, you only import the Semantic UI React components that you actually use in the file, not the entire semantic-ui-react
library.
Why do some import statements have curly braces, and other import statements do not?
See the next question.
Why do we use export in some files and export default in others?
Use export default
when there is only a single entity in a file that must be made visible to other files. When there are multiple entities in a file that must be made visible to other files, then use export
.
The choice of export
vs. export default
impacts on the syntax of the import statement. Take a look at the following code:
import { Stuffs } from '/imports/api/stuff/stuff';
import StuffItem from '/imports/ui/components/StuffItem';
In general, you use curly braces in your import statement when the associated file exported multiple entities. You don’t use curly braces when the associated file exported a default entity. So, the stuff.js
file exported multiple entities (one of which was named Stuffs
) while the StuffItem.jsx file exported (by default) a single item.
Note that the name referenced when importing a default export is irrelevant. The export
statement in /app/imports/ui/components/NavBar.jsx is:
export default withRouter(NavBarContainer);
However, the import
statement in /app/imports/ui/layouts/App.jsx is:
import NavBar from '../components/NavBar';
Even though the value exported from NavBar.jsx is the return value from calling withRouter on NavBarContainer, we can refer to it as NavBar
in App.jsx.
How does publish work? Does it just send data from the server to the client? When does this data transfer happen?
‘publish’ defines a set of data on the server. The subscriptions you create on the client side with Meteor.subscribe
retrieve that data from the server to use in your components and pages. Unlike SQL views, MongoDB will automatically update these subscriptions if the original collection is modified.
Can we use object-oriented programming in Meteor?
You already are; everything in /app/imports/ui extends React.Component
. You could thus make a component that extends React.Component
and have other components that inherit from the first component.
How is a protected route different from a regular route?
Both ProtectedRoute
and AdminProtectedRoute
are defined in /app/imports/ui/layouts/App.jsx; ProtectedRoute
is a Route
with additional logic to determine whether the user is logged in (the const isLogged = Meteor.userId() !== null
).
How is an exact path different from a regular path?
An exact path must be an exact match. The Landing
page requires that we be at ”/”, not some other path such as “/signin” that merely contains a /.
The pages export withTracker; where is withTracker called?
withTracker
is actually called in the export
itself; note the presence of parentheses for the withTracker
function.
Is it possible to conditionally render parts of pages depending on whether the user is an admin or not?
Yes; see /app/imports/ui/components/NavBar.jsx for an example.
Can users add their own fields to the table in /app/imports/ui/pages/ListStuff.jsx?
Yes. You would have to make changes to the user interface (i.e. the ui/ directory), the database (i.e. the api/ directory), and to the default initialization data (i.e. settings.development.json).
What happens if you remove the subscription from /app/imports/ui/pages/ListStuff.jsx?
Without the subscription to Stuff
, the ListStuff page would not have access to the Stuffs
to display. Try it and see what happens.
Are the Route, ProtectedRoute, and AdminProtectedRoute components built into Meteor?
No. Look through the rest of the file: Route
is imported from react-router-dom
and both ProtectedRoute
and AdminProtectedRoute
are defined in App.jsx.
How exactly does ProtectedRoute create a new route?
ProtectedRoute
is a function that returns a Route
. This Route
has all of the properties that were passed to the ProtectedRoute
.
What is the relationship between publications and subscriptions?
The publication on the server side specifies a subset of the data in the database; the subscription on the client side requests that this data be mirrored in the client-side MiniMongo database. By analogy, Dr. Johnson publishes a screencast and you subscribe to it (in the form of watching the video).
What would happen if you removed the return this.ready() from the publications?
The this.ready()
call signals that the data transfer is complete. Without this, any subscriptions on the publications would continue to wait for data indefinitely.
Is it possible to place the header and footer into individual pages rather than in /app/imports/ui/layouts/App.jsx?
Yes, though the question itself hints at why this is a bad idea: you would have to include the header and footer in each page in your application. Placing the header and footer in /layouts/App.jsx makes the header and footer appear on every page.
Is it possible to modify ProtectedRoute to only allow users with some combination of roles?
Yes, though you would have to &&
the clauses together yourself.
What is the :_id in the “/edit/:_id” route?
The :_id
is replaced with the _id
of the Stuff
being edited.
How does the <Switch> statement work in /app/imports/ui/layouts/App.jsx?
Switch
is very much like the switch
statement that you are familiar with: it directs program flow based on a single value. This is a very specific switch
that decides which page to render based on the path
of the current page. If the path
for a Route
within the Switch
is equal to the current path in the browser, then Meteor will render the component
for that Route
. The last Route
in the Switch
does not include a path
, making it behave much as the default
case would: if none of the above paths match, the NotFound
component is rendered.
You will note the lack of any break
statements for the Switch
. break
is necessary for general-purpose switch
statements because they must support fall-through. In this case though, we know that there is a one-to-one relationship between paths and pages: each path corresponds to a single page and vice versa, so there is no need for fall-through here.
Can we make routes that are visible to regular users but not admins?
Yes, you would just have to write conditional logic to prevent admins from seeing those pages.
What does the render function do?
The render
method of a React.Component
returns the JSX code to display for that component.
How do you generate the URL of a Stuff?
The URLs are defined in /app/imports/ui/layouts/App.jsx; these paths can be whatever you want them to be. For example, if we wanted to create a page for the user to edit his or her account information, we cannot reuse the path "/edit/:_id"
because that is already the path for the EditStuff
page. However, we could instead create a new ProtectedRoute
with a path "/user/edit/:_id"
.
Why do we split the components on a page across multiple files in Meteor when we did everything in a single file in React?
You used a single .js file for your React projects because those applications only had a single page (ex. the home page for Island Snow). From a pedagogical standpoint, this let you focus on learning about React instead of having to figure out how various files interact with one another. From a software engineering standpoint, a single web page does not provide much opportunity for code reuse outside of the CSS, so the benefits of splitting the code across multiple files are not as apparent.
At this point in your development, neither of those motives for using a single file still hold true. You are already familiar with React, at least enough to use the Semantic UI React documentation as a reference. You are now working on increasingly complex projects with multiple pages, all of which share the same header and footer along with some smaller components.
One might argue that it is still possible to have multiple components in the same file. However, it is much easier to import components when they are in their own files: if NavBar
was in /app/imports/ui/pages/Landing.jsx you would have to somehow remember that every time you wanted to use or modify that NavBar
. With NavBar
defined within a file named NavBar.jsx, there should be no confusion as to where that component is located.
Why are ProtectedRoute and AdminProtectedRoute separate?
ProtectedRoute
requires a user who is logged in whereas AdminProtectedRoute
requires an admin user who is logged in.
Is ProtectedRoute similar to the protected header in C++?
Not really; they both restrict access in some way, but protected
has to do with class inheritance whereas ProtectedRoute
is defined in the template as a route requiring the user to be logged in.
If you have multiple subscriptions on a page, is it possible to wait for a set of those subscriptions to become ready before updating the page or will the page automatically update upon any change to any of the subscriptions?
Yes; see the Meteor documentation on subscription readiness.
Is this publication and subscription model similar to how Google, Amazon, Facebook, etc. retrieve and display data?
Meteor’s publish/subscribe technology is an implementation of the publish-subscribe design pattern which is in wide use across the industry. For example, any technology stack employing Redis for data caching or ZeroMQ for distributed messaging is using the publish-subscribe model. So, it’s extremely likely that Google, Amazon, Facebook and all the rest are using publish-subscribe at some point in their tech stack.
Facebook has open sourced one of its primary data retrieval technologies, which is called GraphQL (https://graphql.org/). As noted above, it is simple to use GraphQL in Meteor applications in conjunction with or to entirely replace publish-subscribe.
This course uses Uniforms in conjunction with Simple Schema to accomplish this; see the documentation for those tools for more details. Essentially, Uniforms uses the schema created with Simple Schema to generate and format the form displayed on the page.
Dr. Johnson mentions “spinners” in the screencast, but the actual component is Loader. Why the difference?
The Semantic UI developers did not want you to confuse the Loader
component with Spinners.
How should we handle forgotten passwords: provide a button or link to reset the password or automatically reset the password after n invalid login attempts?
These are not mutually exclusive options: you can provide the Reset Password link while still tracking the number of unsuccessful login attempts. You could add an integer field to the users
collection to store the number of consecutive failed logins and update that in handleSubmit
in the Signin
page.
How can we validate that an email address is an actual email address?
To verify that the string is a valid email address, use SimpleSchema.RegEx.Email
or SimpleSchema.RegEx.EmailWithTLD
. Checking if the email address actually exists is more difficult and your teaching assistant does not have an answer to that beyond sending an email to that address.
Is it possible to sort the data displayed on the page?
Yes, and you have already done something like this.
Can we combine pages together? For example, could we merge the Add Stuff, Edit Stuff, and List Stuff pages to form one Stuff page where we can see the existing Stuffs as we add and modify items?
This is absolutely possible; you would just have to modify the relevant .jsx files. Whether you should do this is a philosophical question. On one hand, combining all of the possible actions on a collection into a single page reduces the amount of navigation necessary, and seeing what is already in the collection may be useful when adding new items (ex. ensuring that you are not creating a duplicate of something already in the database). On the other hand, doing this will put a lot of data on one page, resulting in a potentially confusing and cluttered user interface.
Is it possible to combine the two Meteor.publish calls in /app/imports/startup/server/stuff.js so the application only uses one subscription for Stuffs?
It is certainly possible to combine the conditional logic so the Stuff
subscription returns all Stuffs
for admins and only the items that the user owns for non-admins. The template application separates the publications because it displays the Stuffs
differently on different pages: an admin may want to see all Stuffs
or just the Stuffs
that he or she is directly associated with.
How can we further customize the forms? Can we use CSS to add new styles to the form elements?
See the documentation and assigned reading for Uniforms; in particular, note that you are not restricted to only text fields and dropdowns. You may also use /app/client/style.css (or any other .css file that you import) to style the elements in the form.
Is it possible to validate the AutoForm without the fake username?
Try moving the const owner
line from submit
to render
and setting the value
of the HiddenField
to { owner }
.
/app/imports/ui/pages/AddStuff.jsx defines insertCallback and submit methods with parameters, but those parameters are not provided when the method is used. How does the method receive those parameters?
The methods are used as follows:
<AutoForm ref={(ref) => { this.formRef = ref; }} schema={StuffSchema} onSubmit={this.submit}>
Stuffs.insert({ name, quantity, condition, owner }, this.insertCallback);
In both cases, the method is not actually called at that point: this.submit
is set as the handler for the onSubmit
event and this.insertCallback
is passed as an argument to Stuffs.insert
. As you will recall from the functional programming module earlier in the semester, functions are data in JavaScript and so you can store them in variables, pass them as arguments to other functions, etc. The methods are actually called at some other time within the code for AutoForm
and Collection#insert
respectively.
Are there any restrictions on the components we can create?
You are restricted only by your imagination.
Where does the error in /app/imports/ui/pages/EditStuff.jsx come from?
The code referenced is:
(error) => (error ?
swal('Error', error.message, 'error') :
swal('Success', 'Item updated successfully', 'success')));
This is an arrow function, so error
is the parameter for the function defined here. The function is not being called, only defined. For a complete look at how this function is used:
/** On successful submit, insert the data. */
submit(data) {
const { name, quantity, condition, _id } = data;
Stuffs.update(_id, { $set: { name, quantity, condition } }, (error) => (error ?
swal('Error', error.message, 'error') :
swal('Success', 'Item updated successfully', 'success')));
}
So the arrow function (with error
as its parameter) is passed as an argument to Stuffs.update
.
Is it possible to filter the range of possible inputs based on a specific set of valid values?
If you want to restrict the range of inputs, it is best to design the form to only allow those specific inputs rather than waiting until the user submits the form to perform validation. If the input is a string, use a dropdown; if the input is a number, use a number field, etc.
How does the Uniforms package save the form data into the database?
The onSubmit
attribute for the AutoForm
component indicates the code to execute when the form is submitted. In both /app/imports/ui/pages/AddStuff.jsx and /app/imports/ui/pages/EditStuff.jsx, onSubmit
is set to this.submit
, referring to a submit
method defined within the class. This submit
function takes care of the database operations.
Can we perform more specific validations, ex. limiting the name to only alphanumeric characters?
Yes, though this would likely require you to use regular expressions (and not just the constants referenced in the Simple Schema documentation).
Does input prevent users from overflowing the input to gain admin access?
No, though the type of vulnerability you are referring to would be attacked through a different route.
The Add Stuff and Edit Stuff pages are essentially the same; why do we need two separate pages to do the same thing?
Although the pages look the same, they serve different roles. Add Stuff creates an entirely new Stuff
whereas Edit Stuff modifies an existing Stuff
. One uses insert
while the other uses update
. If you made a single page for both tasks, you would have to perform some conditional logic to set up the form for the correct operation and that would be more complex than just having two separate pages/
Separating the add and edit processes also matches the CRUD operations.
With that being written, it is perfectly valid to argue that while the pages may have different purposes the forms within those pages are nearly identical. It would then be reasonable to extract the form fields into a new component that you could then use in both AddStuff.jsx and EditStuff.jsx.
Can users specify the unit of measurement (ex. for the quantity in the sample application)?
You could do this with another field in the document and a corresponding input
in the form.
What is the model={this.props.doc} attribute in the AutoForm in /app/imports/ui/pages/EditStuff.jsx?
The model
contains the data to display in the form.
Why does meteor-example-form-react place schemas into a forms directory?
Both CreateStudent
and EditStudent
use the StudentFormSchema
defined in StudentFormInfo.js. The forms directory therefore serves as a convenient location to store these schemas. Also note that CreateStudent
and EditStudent
modify multiple collections in their respective submit
methods. The schemas attached to the collections defined in the /api directory are specific to those individual schemas, but CreateStudent
and EditStudent
need to modify both StudentData
and EnrollmentData
. StudentFormSchema
therefore serves as a separate schema that includes all of the fields to pass to the AutoForm
.
This differs from what you have seen in meteor-application-template-react where the forms modify only a single collection. EditStuff
uses the StuffSchema
defined for the Stuffs
collection. AddStuff
defines a new formSchema
that omits the owner
field that would have been required in StuffSchema
.
How does the application differentiate between regular and admin users?
One example of this is in /app/imports/ui/components/Navbar.jsx:
{Roles.userIsInRole(Meteor.userId(), 'admin') ? (
<Menu.Item as={NavLink} activeClassName="active" exact to="/admin" key='admin'>Admin</Menu.Item>
) : ''}
This uses the ternary operator to display the Admin menu item if the user is an admin and ''
otherwise. The condition here is Roles.userIsInRole(Meteor.userId(), 'admin')
; Roles.userIsInRole
takes the ID of the user to examine and the role to search for as its arguments. For more details, see the documentation for Roles.userIsInRole
.
Why is there no explicit check for the user being a regular user?
In the template you are using, the roles
property is set to ['admin']
if the user is an admin user; if that is not the case, the only other option is that the user is a standard user.
How do you add new admin users without using /config/settings.development.json?
You can add the “admin” role to an existing user through a MongoDB command, ex. db.users.update({username: "john@foo.com"}, { $set: { roles: ["admin"] }});
.
However, note that this must be done on the server-side.
Are there any roles besides “user” and “admin” in the template?
The template only provides these two roles; these roles are ultimately just strings stored in an array field in the users
collection though, so all you need to do in order to create new roles is decide on a name for the role and add conditional logic to perform certain actions for that role. For more information, see the documentation for meteor-roles
.
Are there any limits on the number of regular or admin users?
After a while your machine would probably run out of memory, but other than that there are no limits on the number of documents in a collection.
How can a user modify a document that he or she did not create?
Creating data does not inherently protect it from modification by others; if you want to ensure that users can only modify their own data, you would have to add in the logic for that yourself. For example, you can publish to the client-side only documents owned by the logged-in user.
Are there ethical concerns about having an admin user who can see all of the data on the site?
Absolutely; we have an Ethics in Software Engineering module later in the semester and you might also consider ICS 390 for further discussion of ethical issues in Computer Science.
What prevents users from changing their own roles, ex. a regular user changing his or her role to be an admin?
Mostly the fact that not even admins can make new admins in the template application. If you add that functionality in, you can use AdminProtectedRoute
from /app/imports/ui/layouts/App.jsx to prevent standard users from accessing pages that only admins should have access to.
Does Meteor support group roles for users?
Yes, though it is more accurate to write that meteor/alanning:roles
provides this; documentation is available here.
What prevents users from accessing admin pages?
/app/imports/ui/layouts/App.jsx uses AdminProtectedRoute
for the admin page. AdminProtectdRoute
redirects the user to the signin page if the current user is not an admin (the isLogged && isAdmin
). Consequently, the current user must be an admin to access the page even if the user has typed in the URL of the admin page manually.
If there are multiple admins, can each admin see the _Stuff_s associated with other admins?
Yes, the ListStuffAdmin page displays everything in the Stuffs
collection.
Can we show an error message (perhaps using swal) when the user attempts to access an admin page instead of redirecting to the signin page?
Yes.
How are we able to use ProtectedRoute and AdminProtectedRoute in the same way as a React component when they do not extend React.Component?
Although neither ProtectedRoute
or AdminProtectedRoute
extend React.Component
, they are functions that return a Route
, which is a component we can use in the render
method.
Are there roles that allow the user to view or modify the source code for the website?
No, not to my knowledge. The source code for the website should only be available on GitHub, so without access to the repository there should not be any means of viewing or modifying the source code.
Can users change the roles of other users?
Yes.
What happens when you forget your password?
The answer to this depends on how much the IT staff likes you.
Should a user be able to see that someone else has modified an item that he or she owns?
This would depend on the application.
Are there alternatives to meteor/accounts-base and meteor/alanning:roles? Why did we choose this combination of libraries? Are there benefits to using any alternatives that may exist?
There are almost always alternative libraries for anything you might use; meteor/accounts-base
and meteor/alanning:roles
are the libraries used in the offical Meteor documentation though.
How would we record IP addresses for logins?
See the answers to this Stack Overflow question.
How would we add more sophisticated login processes (ex. multi-factor authentication, CAPTCHA)?
One way to support multi-factor authentication is through CAS. For example, the RadGrad application uses CAS authentication, which can be multi-factor.
For reCAPTCHA, see the Meteor-reCAPTCHA project (with the caveat that your teaching assistant has not tested this code).
Warning: React.createElement: type is invalid – expected a string (for built-in components) or a class/function (for composite components) but got: object.
As the warning message indicates, one of your components is most likely missing an export
keyword. The rest of the error message will suggest the component that you should start looking at. See the Named vs. Default Exports screencast for more details.
The meteor command is not found on the command line.
Ensure that the path to your .meteor directory is on the PATH
.
The eslint command is not found on the command line.
See the Troubleshooting portion of the ESLint installation instructions.
Is Meteor used for real-life applications4?
Meteor is one of the top 10 most used web application frameworks. Also see the Meteor showcase, though the most important example for you is clearly RadGrad.
See the answers to this Stack Overflow question.
How can we easily know what Semantic UI tools are available to us?
See the Semantic UI React documentation.
Are React and Meteor related, and if so what is that relationship?
There is no direct relationship between React and Meteor; Meteor supports React but is not inherently tied to React in order to work. Recall that one of the early steps in the Meteor React Tutorial (specifically https://www.meteor.com/tutorials/react/components) was to install React, so Meteor is not dependent on React. In turn, you used React before learning about Meteor, so React does not require Meteor either.
How difficult would it be to use another UI framework in Meteor?
Not difficult. Meteor is entirely decoupled from the UI framework.
Can Meteor be used for real-time apps involving large quantities of data (ex. multiplayer games)?
Yes, of course. Interestingly, real-time communication is one area in which Meteor excels. For example, it is almost trivial to create a real-time chat app in Meteor—for example, Make a live chat app in under 2 hours with Meteor. Meteor’s publish-subscribe technology makes it possible to create real-time apps with significantly less code and less opportunity for errors than traditional web application frameworks, which require HTML hacks such as AJAX to do real-time updates.
That said, as the amount of data to be manipulated grows, the developer must become increasingly thoughtful about how to manage it, and that is just as true for a Meteor-based app as it is for a non-Meteor-based app. Note that the publish-subscribe technology is not the only way to manage communication of data between client and server in Meteor. Another approach is Meteor Methods, which is the Meteor implementation of remote procedure calls.
What makes Meteor unique among all the web application frameworks out there?
It is the only one named Meteor.
More seriously, here are some interesting features of Meteor:
It provides a layer of abstraction over a duck soup of underlying JS technologies. For example, you don’t need to deal with the horror that is webpack: Meteor takes care of it for you.
It provides built-in accounts management. This is a huge win and time-saver for getting a useful web app up and running with a minimum of coding.
It has extremely tight and well designed integration with MongoDB, which also reduces the time required to get an app up and running.
It is Javascript all the way down. Many other web application frameworks require users to learn Javascript plus another language. For example, Ruby on Rails requires Ruby + Javascript. Laravel requires PHP + Javascript. Spring requires Java + Javascript. It’s easier to have all the code in a single language.
The above features combine to make Meteor one of the easiest web framework for newbies to learn and use to develop interesting applications in a short time. Philip has experimented with a variety of web frameworks for ICS 314 over the years, including Stripes, Wicket, and Play. The applications that students build in a few short weeks with Meteor are generally more sophisticated and featureful than those developed with these prior technologies. What this implies is that while there is a heavy learning curve associated with Meteor, there is an even heavier learning curve associated with more traditional technologies!
Meteor is one of the top 10 most used web application frameworks.
These questions were from previous semesters and are no longer pertinent to current course material; however, the questions and answers are preserved here for posterity.
What options are available so that Bert alert does not block the navbar?
See the Bert documentation, especially the API & Defaults and Customization sections.
This section contains questions I haven’t yet answered or am still working on.