-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add Authentication extra features to Comments tab #41
Conversation
Accidentally overwrote some new changes
import com.google.gson.Gson; | ||
import org.javatuples.Pair; | ||
import com.google.appengine.api.users.UserService; | ||
import com.google.appengine.api.users.UserServiceFactory; | ||
import java.io.IOException; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: Imported names should appear in ASCII sort order (https://google.github.io/styleguide/javaguide.html#s3.3.3-import-ordering-and-spacing0
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for pointing this out, I just installed a VSCode extension to sort these.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
RESOLVED
if (userService.isUserLoggedIn()) { | ||
String userEmail = userService.getCurrentUser().getEmail(); | ||
String logoutUrl = userService.createLogoutURL(redirectUrl); | ||
response.getWriter().println("<p>Logout <a href=\"" + logoutUrl + "\">here</a>."); | ||
Pair<String, String> userInfo = new Pair<>(userEmail, logoutUrl); | ||
sendJson(response, userInfo); | ||
} else { | ||
String loginUrl = userService.createLoginURL(redirectUrl); | ||
response.getWriter().println("<p>Login <a href=\"" + loginUrl + "\">here</a>."); | ||
Pair<String, String> userInfo = new Pair<>("N/A", loginUrl); | ||
sendJson(response, userInfo); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This could be a good candidate for the return early pattern (https://www.itamarweiss.com/personal/2018/02/28/return-early-pattern.html)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is an interesting pattern, I've never heard of it. Thanks!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
RESOLVED
private void sendJson(HttpServletResponse response, Pair<String, String> userInfo) throws IOException { | ||
Gson gson = new Gson(); | ||
String json = gson.toJson(userInfo); | ||
response.getWriter().println(json); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: If you are using this in more than one class, you could consider creating a utility class to share this logic
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@gbuenoandrade I just looked into this, I think this is a great idea. However, one of the sendJson() is defined for Pair
and the other is defined for List<String>
. Is there a way to add a type-less parameter with two classes that do not share the same abstract class?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
gson.toJson
accepts Object
as parameter, right? Your function could do the same.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I didn't know this, thanks! I've added it!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
RESOLVED
import com.google.appengine.api.users.UserService; | ||
import com.google.appengine.api.users.UserServiceFactory; | ||
import com.google.appengine.api.datastore.DatastoreService; | ||
import com.google.appengine.api.datastore.DatastoreServiceFactory; | ||
import com.google.appengine.api.datastore.Entity; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: imported names order
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for pointing this out, I just installed a VSCode extension to sort these.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
RESOLVED
} | ||
|
||
function logoutHtml(userEmail, logoutUrl) { | ||
return "<p>Hi " + userEmail + "! Logout <a href=\"" + logoutUrl + "\">here</a>."; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe use a template literal?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good call, thanks!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
RESOLVED
function getEmail(json) { | ||
return json.val0; | ||
} | ||
|
||
function getUrl(json) { | ||
return json.val1; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Consider defining your own type to store user info. That way you will avoid having to reference the generic names defined by Pair
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Apologies for the delay, I have implemented this!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
RESOLVED
} | ||
|
||
function loginHtml(loginUrl) { | ||
return "<p>Login <a href=\"" + loginUrl + "\">here</a>."; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe use a template literal?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good call, thanks!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
RESOLVED
if (userEmail == 'N/A') { | ||
const html = loginHtml(redirectUrl); | ||
document.getElementById('login-status').innerHTML = html; | ||
} else { | ||
const html = logoutHtml(userEmail, redirectUrl); | ||
document.getElementById('login-status').innerHTML = html; | ||
document.getElementById('comments-form').style.display = "block"; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Optional: Maybe return early
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've implemented this as well, thanks!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
RESOLVED
cef2430
to
7c6f54b
Compare
|
||
package com.google.sps.servlets; | ||
|
||
public class Pair { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It doesn't really make sense to call this "Pair". A pair is a particular data structure with a generic "first" and "second" member (or something similar).
This is just a specific class for storing login information, and it should just be called LoginInfo
or something.
Also, please add javadoc-style comments for the class and all public members, including the constructor.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, I agree especially now that's a custom class there's no reason to keep the name as Pair
. I'll change it!
Ohhh I just found out what javadoc comments are. I deleted them throughout my project because I thought \**
looked horrible and didn't add much value. I'll definitely pull a new request for this because I'd have to change this for all the files. #59
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
RESOLVED
#59
} | ||
String loginUrl = userService.createLoginURL(redirectUrl); | ||
Pair userInfo = new Pair("N/A", loginUrl); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's generally a bad idea to use special values like "N/A".
- It's easy to make a mistake and forget to check for the special value.
- It's easy to change the special value and forget to update all clients.
- It's possible that the use of the field will change in the future, and "N/A" may become a possible real value.
It's better to just add another field that holds a boolean to indicate that the user is logged in or not. The documentation on the email field should say that it should be empty when the user is not logged in.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@antmar I agree, having the custom class also makes this easy to do. Just a small consideration, I've altered it such that the constructor has the following function signature: UserInfo(String email, String url, boolean loggedIn)
. However, if loggedIn = false
then I am passing in ""
to email
. Is there a way to set optional parameters easily like in C++ or Python? Otherwise, would it be wise to overload this function and have one that doesn't require email as a parameter?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Another option is to create separate static factory methods for the loggedIn and loggedOut case.
- loggedIn(String email, String url)
- loggedOut(String url)
For details about factory methods, see Item #1 in "Effective Java 3rd Ed."
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like this idea, thanks! I've added it. Great reference to the book too.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
RESOLVED
|
||
Pair(String email, String url) { | ||
this.email = email; | ||
this.url = url; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"url" is a bit too generic. What does the URL point to? I suggest either:
- Use a separate field for login URL and logout URL (only set one of them)
- Call this something like "loginOrLogoutUrl".
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good call, thanks!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
RESOLVED
|
||
function getUrl(json) { | ||
return json["url"]; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think these helpers add any clarity. You can just access the property directly on the json object.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, I agree. I've removed them, thanks!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
RESOLVED
import java.io.IOException; | ||
import javax.servlet.http.HttpServletResponse; | ||
|
||
public final class JsonUtil { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Public classes and methods should have comments.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks! Added the relevant javadoc-style comments for this class. Will go back to the other classes unrelated to this PR here #59
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
RESOLVED
} | ||
String loginUrl = userService.createLoginURL(redirectUrl); | ||
Pair userInfo = new Pair("N/A", loginUrl); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Another option is to create separate static factory methods for the loggedIn and loggedOut case.
- loggedIn(String email, String url)
- loggedOut(String url)
For details about factory methods, see Item #1 in "Effective Java 3rd Ed."
* @param email | ||
* @param logoutUrl | ||
*/ | ||
public void loggedIn(String email, String logoutUrl) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A standard static factory method would have a signature like this:
public static UserInfo loggedIn(String email, String logoutUrl)
The key is that the method would create and initialize the object at the same time. You don't want users of your class to create uninitialized objects. Ideally, you would make the constructor private so that users of the class have to use your factory methods.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the clarification - I did not fully understand why the methods had to be static. I have a better idea of what this means now after reviewing your comment and Austin's code on the prototype. I will change this in a new pull request.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
RESOLVED
#60
Additional features added
Show user e-mail when logged in
Associate user e-mail with user comments