Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Conversation

@tobinus
Copy link
Owner

@tobinus tobinus commented Mar 8, 2018

Please don't merge or close

We're trying out Github as a code review tool. This pull request is an attempt at achieving that, by letting us comment on code. By using the first commit with all skeletons in place, we make it easier to see what was written by the group members and not part of the automatic skeletons of Angular and Sails.

Shamzaa and others added 30 commits February 9, 2018 11:58
And clarify command presentation
navbar, register and login
and moved service and models into shared folder. Also generated mypage
component
DeimosA and others added 24 commits March 3, 2018 10:50
…qually

Make login and register great again
behaviour subject does this
and show correct price for percent sales
list concatenation 🤷
This reverts commit 01d67ca, reversing
changes made to 874b2ba.
Revert "Merge branch 'master' into dev"
create: function (req, res) {
// The body should contain an array of objects with productId and quantity
if (!req.body instanceof Array)
return res.badRequest({error: 'Expected an array of objects with productId and quantity'});
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use braces with all multi-line blocks. (https://github.com/airbnb/javascript#blocks--braces)

let orderQuantity = {};

for (let product of req.body) {
// Check valid product format and store key: value for easy quantity lookup
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't use iterators. Use .forEach instead. (https://github.com/airbnb/javascript#iterators--nope)

}); // Order callback end
}); // Product callback end
}); // User callback end

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

General feedback.

In order to be maintainable, this function create needs some improvements. The function is too large. With 88 lines, it is so long that the developer found it necessary to comment each block ending. That is a bad sign.

Use Promises instead of callbacks

In this functions, there are three callbacks inside of each other. That can quickly create a mess - and all of your code disappears out of the screen to the right, because of all the indentation. This problem is largely solved if you make use of Promises.

Use forEach, map, filter and reduce instead of iterators

Javascript has excellent built-in functions for dealing with arrays - amongst them are forEach, map, filter and reduce. Learning those functions and when to use them would create more readable and maintainable code.

Split the function into several smaller functions

Every function should ideally fit into one computer screen, and should only do one thing. This function could be split into several smaller functions. One for finding the user. One for finding the products. One for calculating the price of a product based on sales. And one for creating an order. Then the next developer who sees this code would easier understand what is going on here.

Use more brackets

Many if statements in this functions does not use brackets. While somewhat frowned upon, dropping the brackets in small one-liners is ok - but it is important that the entire statement is on one line. Otherwise it can be easy to create confusing code, like this:

if (x > 3)
    x = 5;
    y = 2;

* Give a user admin privileges
*/
makeAdmin: function (req, res) {
User.update(parseInt(req.params.id), {isAdmin: true}).exec(function (err, user) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What would happen if req.params.id is not an int?

* Remove a users admin privileges
*/
removeAdmin: function (req, res) {
User.update(parseInt(req.params.id), {isAdmin: false}).exec(function (err, user) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What would happen if req.params.id is not an int?

isAdmin: boolean;

constructor(user) {
if (user.hasOwnProperty('id') && user.hasOwnProperty('email') && user.hasOwnProperty('isAdmin')) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is really being checked here? With this check, you could still pass inn undefined for id, email and isAdmin, and this would return true.

const user = {
    id: undefined,
    email: undefined,
    isAdmin: undefined
};

user.hasOwnProperty('id') && user.hasOwnProperty('email') && user.hasOwnProperty('isAdmin')
> true

} else {
url = '/api/product';
return this.http.post<ProductModel>(url, product);
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ternary statements can be useful sometimes.

const url = product.id ? `/api/product/${product.id}` : '/api/product';
return this.http.post<ProductModel>(url, product);

let url = '/api/user/login';
return this.http.post(url, body)
.map(result => new UserModel(result))
.do(result => this.userLoggedIn(result));
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What does do do? I have never seen it before in this context.

this.router.navigate(['/']);
}else if(statusCode === 401){
// handle username or password wrong
alert("Wrong username or password.");
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A better solution could have been made here.

// Iterate over our products and calculate price
for (let product of products) {

let quantity = orderQuantity[product.id];
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does not check for quantity > 0. Numerical values received from users should always be validated.
Also does not do a strict check on the quantity, allowing arrays and null to be used.

required: true,
minLength: 8,
maxLength: 72,
},
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does not do strict type checking, allowing ["a", "b", "c", "d", "e", "f", "g", "h"] as a password, which turns into "a,c,b,d,e,f,g,h" when logging in. It won't happen from a well-written client, but can be abused.

});
}

};
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Data validation in database structures

While it is quite convenient to use Sails for a lot of the validation, it does not catch obvious type coercions that happen in Javascript. Most notably is the coercion of arrays into strings.

Apart from that, most of the data validation works as expected.

}

private findItem(id: number){
return this.cart.filter((e) => e.productId == id)[0];
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fetching the first element of an array regardless of its size puts burden on outside code, and should generally be avoided.

this.searchTerm,
this.sort,
this.minPrice
).subscribe(products => {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When is this callback unsubscribed?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants