SlideShare a Scribd company logo
Creating a Facebook Clone - Part XXII
UserService is a big class and it makes sense to cover in two parts
setProps(user, u);
if (u.getPassword() != null) {
u.setPassword(encoder.encode(user.getPassword()));
}
users.save(u);
}
public byte[] getAvatar(String userId) {
User u = users.findById(userId).get();
if (u.getAvatar() != null) {
return u.getAvatar().getData();
}
return null;
}
public void setAvatar(String authToken, String mediaId) {
Media m = medias.findById(mediaId).get();
User u = users.findByAuthtoken(authToken).get(0);
u.setAvatar(m);
users.save(u);
}
public void sendFriendRequest(String auth, String userId) {
User me = users.findByAuthtoken(auth).get(0);
User him = users.findById(userId).get();
UserService
Next on the agenda is getAvatar, it returns the avatar picture of the user as a byte array
setProps(user, u);
if (u.getPassword() != null) {
u.setPassword(encoder.encode(user.getPassword()));
}
users.save(u);
}
public byte[] getAvatar(String userId) {
User u = users.findById(userId).get();
if (u.getAvatar() != null) {
return u.getAvatar().getData();
}
return null;
}
public void setAvatar(String authToken, String mediaId) {
Media m = medias.findById(mediaId).get();
User u = users.findByAuthtoken(authToken).get(0);
u.setAvatar(m);
users.save(u);
}
public void sendFriendRequest(String auth, String userId) {
User me = users.findByAuthtoken(auth).get(0);
User him = users.findById(userId).get();
UserService
Notice we need an id and not a token to get the avatar as anyone who is familiar with the user ID should be able to see the avatar
setProps(user, u);
if (u.getPassword() != null) {
u.setPassword(encoder.encode(user.getPassword()));
}
users.save(u);
}
public byte[] getAvatar(String userId) {
User u = users.findById(userId).get();
if (u.getAvatar() != null) {
return u.getAvatar().getData();
}
return null;
}
public void setAvatar(String authToken, String mediaId) {
Media m = medias.findById(mediaId).get();
User u = users.findByAuthtoken(authToken).get(0);
u.setAvatar(m);
users.save(u);
}
public void sendFriendRequest(String auth, String userId) {
User me = users.findByAuthtoken(auth).get(0);
User him = users.findById(userId).get();
UserService
If the avatar reference is null we return null instantly
setProps(user, u);
if (u.getPassword() != null) {
u.setPassword(encoder.encode(user.getPassword()));
}
users.save(u);
}
public byte[] getAvatar(String userId) {
User u = users.findById(userId).get();
if (u.getAvatar() != null) {
return u.getAvatar().getData();
}
return null;
}
public void setAvatar(String authToken, String mediaId) {
Media m = medias.findById(mediaId).get();
User u = users.findByAuthtoken(authToken).get(0);
u.setAvatar(m);
users.save(u);
}
public void sendFriendRequest(String auth, String userId) {
User me = users.findByAuthtoken(auth).get(0);
User him = users.findById(userId).get();
UserService
The setAvatar method works in a similar way
setProps(user, u);
if (u.getPassword() != null) {
u.setPassword(encoder.encode(user.getPassword()));
}
users.save(u);
}
public byte[] getAvatar(String userId) {
User u = users.findById(userId).get();
if (u.getAvatar() != null) {
return u.getAvatar().getData();
}
return null;
}
public void setAvatar(String authToken, String mediaId) {
Media m = medias.findById(mediaId).get();
User u = users.findByAuthtoken(authToken).get(0);
u.setAvatar(m);
users.save(u);
}
public void sendFriendRequest(String auth, String userId) {
User me = users.findByAuthtoken(auth).get(0);
User him = users.findById(userId).get();
UserService
Notice that unlike getAvatar with setAvatar we need a token as this is a set operation. This prevents other users from changing our avatar.

When we map this to the webservice we need to first create a media entry and only then set the avatar value.
u.setAvatar(m);
users.save(u);
}
public void sendFriendRequest(String auth, String userId) {
User me = users.findByAuthtoken(auth).get(0);
User him = users.findById(userId).get();
him.getFriendRequests().add(me);
users.save(him);
notifications.sendNotification(him,
new NotificationDAO(null, me.getDAO(),
"wants to be friends",
"uE7FC", 0x587EBE,
0, true, null, null));
}
public void acceptFriendRequest(String auth, String userId) {
User me = users.findByAuthtoken(auth).get(0);
User him = users.findById(userId).get();
if (me.getFriendRequests().contains(him)) {
me.getFriendRequests().remove(him);
me.getFriends().add(him);
him.getFriendRequests().remove(me);
him.getFriends().add(me);
users.saveAll(Arrays.asList(me, him));
UserService
The friend request includes a few moving parts. First we need to send a request.
u.setAvatar(m);
users.save(u);
}
public void sendFriendRequest(String auth, String userId) {
User me = users.findByAuthtoken(auth).get(0);
User him = users.findById(userId).get();
him.getFriendRequests().add(me);
users.save(him);
notifications.sendNotification(him,
new NotificationDAO(null, me.getDAO(),
"wants to be friends",
"uE7FC", 0x587EBE,
0, true, null, null));
}
public void acceptFriendRequest(String auth, String userId) {
User me = users.findByAuthtoken(auth).get(0);
User him = users.findById(userId).get();
if (me.getFriendRequests().contains(him)) {
me.getFriendRequests().remove(him);
me.getFriends().add(him);
him.getFriendRequests().remove(me);
him.getFriends().add(me);
users.saveAll(Arrays.asList(me, him));
UserService
We need an auth token as this is a secure operation
u.setAvatar(m);
users.save(u);
}
public void sendFriendRequest(String auth, String userId) {
User me = users.findByAuthtoken(auth).get(0);
User him = users.findById(userId).get();
him.getFriendRequests().add(me);
users.save(him);
notifications.sendNotification(him,
new NotificationDAO(null, me.getDAO(),
"wants to be friends",
"uE7FC", 0x587EBE,
0, true, null, null));
}
public void acceptFriendRequest(String auth, String userId) {
User me = users.findByAuthtoken(auth).get(0);
User him = users.findById(userId).get();
if (me.getFriendRequests().contains(him)) {
me.getFriendRequests().remove(him);
me.getFriends().add(him);
him.getFriendRequests().remove(me);
him.getFriends().add(me);
users.saveAll(Arrays.asList(me, him));
UserService
We obviously don't have the auth token of the person we are "friending"
u.setAvatar(m);
users.save(u);
}
public void sendFriendRequest(String auth, String userId) {
User me = users.findByAuthtoken(auth).get(0);
User him = users.findById(userId).get();
him.getFriendRequests().add(me);
users.save(him);
notifications.sendNotification(him,
new NotificationDAO(null, me.getDAO(),
"wants to be friends",
"uE7FC", 0x587EBE,
0, true, null, null));
}
public void acceptFriendRequest(String auth, String userId) {
User me = users.findByAuthtoken(auth).get(0);
User him = users.findById(userId).get();
if (me.getFriendRequests().contains(him)) {
me.getFriendRequests().remove(him);
me.getFriends().add(him);
him.getFriendRequests().remove(me);
him.getFriends().add(me);
users.saveAll(Arrays.asList(me, him));
UserService
This is a special case where we modify his entity without an auth-token, that's a bit risky...
u.setAvatar(m);
users.save(u);
}
public void sendFriendRequest(String auth, String userId) {
User me = users.findByAuthtoken(auth).get(0);
User him = users.findById(userId).get();
him.getFriendRequests().add(me);
users.save(him);
notifications.sendNotification(him,
new NotificationDAO(null, me.getDAO(),
"wants to be friends",
"uE7FC", 0x587EBE,
0, true, null, null));
}
public void acceptFriendRequest(String auth, String userId) {
User me = users.findByAuthtoken(auth).get(0);
User him = users.findById(userId).get();
if (me.getFriendRequests().contains(him)) {
me.getFriendRequests().remove(him);
me.getFriends().add(him);
him.getFriendRequests().remove(me);
him.getFriends().add(me);
users.saveAll(Arrays.asList(me, him));
UserService
The notification service should notify the user that he got a new friend request. We'll dig into the notification service soon…
public void sendFriendRequest(String auth, String userId) {
User me = users.findByAuthtoken(auth).get(0);
User him = users.findById(userId).get();
him.getFriendRequests().add(me);
users.save(him);
notifications.sendNotification(him,
new NotificationDAO(null, me.getDAO(),
"wants to be friends",
"uE7FC", 0x587EBE,
0, true, null, null));
}
public void acceptFriendRequest(String auth, String userId) {
User me = users.findByAuthtoken(auth).get(0);
User him = users.findById(userId).get();
if (me.getFriendRequests().contains(him)) {
me.getFriendRequests().remove(him);
me.getFriends().add(him);
him.getFriendRequests().remove(me);
him.getFriends().add(me);
users.saveAll(Arrays.asList(me, him));
}
}
public void uploadContacts(String auth, List<ShadowUserDAO> contacts) {
Long c = shadows.countByUser(auth);
UserService
But first lets check out the other side of the equation. The acceptFriendRequest method.
public void sendFriendRequest(String auth, String userId) {
User me = users.findByAuthtoken(auth).get(0);
User him = users.findById(userId).get();
him.getFriendRequests().add(me);
users.save(him);
notifications.sendNotification(him,
new NotificationDAO(null, me.getDAO(),
"wants to be friends",
"uE7FC", 0x587EBE,
0, true, null, null));
}
public void acceptFriendRequest(String auth, String userId) {
User me = users.findByAuthtoken(auth).get(0);
User him = users.findById(userId).get();
if (me.getFriendRequests().contains(him)) {
me.getFriendRequests().remove(him);
me.getFriends().add(him);
him.getFriendRequests().remove(me);
him.getFriends().add(me);
users.saveAll(Arrays.asList(me, him));
}
}
public void uploadContacts(String auth, List<ShadowUserDAO> contacts) {
Long c = shadows.countByUser(auth);
UserService
This time me & him are flipped
public void sendFriendRequest(String auth, String userId) {
User me = users.findByAuthtoken(auth).get(0);
User him = users.findById(userId).get();
him.getFriendRequests().add(me);
users.save(him);
notifications.sendNotification(him,
new NotificationDAO(null, me.getDAO(),
"wants to be friends",
"uE7FC", 0x587EBE,
0, true, null, null));
}
public void acceptFriendRequest(String auth, String userId) {
User me = users.findByAuthtoken(auth).get(0);
User him = users.findById(userId).get();
if (me.getFriendRequests().contains(him)) {
me.getFriendRequests().remove(him);
me.getFriends().add(him);
him.getFriendRequests().remove(me);
him.getFriends().add(me);
users.saveAll(Arrays.asList(me, him));
}
}
public void uploadContacts(String auth, List<ShadowUserDAO> contacts) {
Long c = shadows.countByUser(auth);
UserService
This checks against a potential weakness where a hacker could potentially call accept friend request for a person that didn't request it
public void sendFriendRequest(String auth, String userId) {
User me = users.findByAuthtoken(auth).get(0);
User him = users.findById(userId).get();
him.getFriendRequests().add(me);
users.save(him);
notifications.sendNotification(him,
new NotificationDAO(null, me.getDAO(),
"wants to be friends",
"uE7FC", 0x587EBE,
0, true, null, null));
}
public void acceptFriendRequest(String auth, String userId) {
User me = users.findByAuthtoken(auth).get(0);
User him = users.findById(userId).get();
if (me.getFriendRequests().contains(him)) {
me.getFriendRequests().remove(him);
me.getFriends().add(him);
him.getFriendRequests().remove(me);
him.getFriends().add(me);
users.saveAll(Arrays.asList(me, him));
}
}
public void uploadContacts(String auth, List<ShadowUserDAO> contacts) {
Long c = shadows.countByUser(auth);
UserService
When a request is accepted we need to update the friend list on both sides. I didn't add a removeFriendRequest method which I probably should have added. I think it's
trivial to add so I'm leaving it as an exercise.
users.saveAll(Arrays.asList(me, him));
}
}
public void uploadContacts(String auth, List<ShadowUserDAO> contacts) {
Long c = shadows.countByUser(auth);
User u = users.findByAuthtoken(auth).get(0);
if (c == null || c == 0) {
List<ShadowUser> shadowList = new ArrayList<>();
for (ShadowUserDAO d : contacts) {
shadowList.add(new ShadowUser(d, u));
updatePeopleYouMayKnow(d, u);
}
shadows.saveAll(shadowList);
} else {
for (ShadowUserDAO d : contacts) {
List<ShadowUser> results = shadows.findByFullName(auth, d.
getFullName());
if (!results.isEmpty()) {
shadows.save(new ShadowUser(d, u));
} else {
ShadowUser current = results.get(0);
current.setEmail(d.getEmail());
current.setPhone(d.getPhone());
current.setSecondaryPhone(d.getSecondaryPhone());
shadows.save(current);
UserService
The last method for UserService is the `uploadContacts` method...

It's invoked when the user uploads the contacts from his phone.
users.saveAll(Arrays.asList(me, him));
}
}
public void uploadContacts(String auth, List<ShadowUserDAO> contacts) {
Long c = shadows.countByUser(auth);
User u = users.findByAuthtoken(auth).get(0);
if (c == null || c == 0) {
List<ShadowUser> shadowList = new ArrayList<>();
for (ShadowUserDAO d : contacts) {
shadowList.add(new ShadowUser(d, u));
updatePeopleYouMayKnow(d, u);
}
shadows.saveAll(shadowList);
} else {
for (ShadowUserDAO d : contacts) {
List<ShadowUser> results = shadows.findByFullName(auth, d.
getFullName());
if (!results.isEmpty()) {
shadows.save(new ShadowUser(d, u));
} else {
ShadowUser current = results.get(0);
current.setEmail(d.getEmail());
current.setPhone(d.getPhone());
current.setSecondaryPhone(d.getSecondaryPhone());
shadows.save(current);
UserService
If we uploaded contacts in the past its a good idea to try and merge with what we have. We can check that by running a count query
users.saveAll(Arrays.asList(me, him));
}
}
public void uploadContacts(String auth, List<ShadowUserDAO> contacts) {
Long c = shadows.countByUser(auth);
User u = users.findByAuthtoken(auth).get(0);
if (c == null || c == 0) {
List<ShadowUser> shadowList = new ArrayList<>();
for (ShadowUserDAO d : contacts) {
shadowList.add(new ShadowUser(d, u));
updatePeopleYouMayKnow(d, u);
}
shadows.saveAll(shadowList);
} else {
for (ShadowUserDAO d : contacts) {
List<ShadowUser> results = shadows.findByFullName(auth, d.
getFullName());
if (!results.isEmpty()) {
shadows.save(new ShadowUser(d, u));
} else {
ShadowUser current = results.get(0);
current.setEmail(d.getEmail());
current.setPhone(d.getPhone());
current.setSecondaryPhone(d.getSecondaryPhone());
shadows.save(current);
UserService
For every contact we find we check to see if there is a user in the system and if so we add that user to the people you may know list
users.saveAll(Arrays.asList(me, him));
}
}
public void uploadContacts(String auth, List<ShadowUserDAO> contacts) {
Long c = shadows.countByUser(auth);
User u = users.findByAuthtoken(auth).get(0);
if (c == null || c == 0) {
List<ShadowUser> shadowList = new ArrayList<>();
for (ShadowUserDAO d : contacts) {
shadowList.add(new ShadowUser(d, u));
updatePeopleYouMayKnow(d, u);
}
shadows.saveAll(shadowList);
} else {
for (ShadowUserDAO d : contacts) {
List<ShadowUser> results = shadows.findByFullName(auth, d.
getFullName());
if (!results.isEmpty()) {
shadows.save(new ShadowUser(d, u));
} else {
ShadowUser current = results.get(0);
current.setEmail(d.getEmail());
current.setPhone(d.getPhone());
current.setSecondaryPhone(d.getSecondaryPhone());
shadows.save(current);
UserService
When adding a lot of elements using saveAll is much faster than save
if (c == null || c == 0) {
List<ShadowUser> shadowList = new ArrayList<>();
for (ShadowUserDAO d : contacts) {
shadowList.add(new ShadowUser(d, u));
updatePeopleYouMayKnow(d, u);
}
shadows.saveAll(shadowList);
} else {
for (ShadowUserDAO d : contacts) {
List<ShadowUser> results = shadows.findByFullName(auth, d.
getFullName());
if (!results.isEmpty()) {
shadows.save(new ShadowUser(d, u));
} else {
ShadowUser current = results.get(0);
current.setEmail(d.getEmail());
current.setPhone(d.getPhone());
current.setSecondaryPhone(d.getSecondaryPhone());
shadows.save(current);
updatePeopleYouMayKnow(d, u);
}
}
}
}
private void updatePeopleYouMayKnow(ShadowUserDAO d, User u) {
UserService
For simplicity I chose to merge based on full name. In retrospect it might have been wiser to use the device unique ID for every contact but that might breed duplicates
too.

I oversimplified a very complex process of handling shadow users. If you take the time to build something like this then make sure to analyze the data more thoroughly
and create a more robust social graph.
current.setEmail(d.getEmail());
current.setPhone(d.getPhone());
current.setSecondaryPhone(d.getSecondaryPhone());
shadows.save(current);
updatePeopleYouMayKnow(d, u);
}
}
}
}
private void updatePeopleYouMayKnow(ShadowUserDAO d, User u) {
User friend = findHim(d);
if (friend != null) {
if (!u.getFriends().contains(friend)
&& !u.getPeopleYouMayKnow().contains(friend)) {
u.getPeopleYouMayKnow().add(friend);
users.save(u);
}
}
}
private User findHim(ShadowUserDAO d) {
if (d.getEmail() != null) {
List<User> l = users.findByEmailIgnoreCase(d.getEmail());
if (l != null && !l.isEmpty()) {
return l.get(0);
UserService
Notice that we still need to declare the updatePeopleYouMayKnow method we mentioned before
current.setEmail(d.getEmail());
current.setPhone(d.getPhone());
current.setSecondaryPhone(d.getSecondaryPhone());
shadows.save(current);
updatePeopleYouMayKnow(d, u);
}
}
}
}
private void updatePeopleYouMayKnow(ShadowUserDAO d, User u) {
User friend = findHim(d);
if (friend != null) {
if (!u.getFriends().contains(friend)
&& !u.getPeopleYouMayKnow().contains(friend)) {
u.getPeopleYouMayKnow().add(friend);
users.save(u);
}
}
}
private User findHim(ShadowUserDAO d) {
if (d.getEmail() != null) {
List<User> l = users.findByEmailIgnoreCase(d.getEmail());
if (l != null && !l.isEmpty()) {
return l.get(0);
UserService
We search for the shadow user in the table of users using the findHim method which we'll cover soon
current.setEmail(d.getEmail());
current.setPhone(d.getPhone());
current.setSecondaryPhone(d.getSecondaryPhone());
shadows.save(current);
updatePeopleYouMayKnow(d, u);
}
}
}
}
private void updatePeopleYouMayKnow(ShadowUserDAO d, User u) {
User friend = findHim(d);
if (friend != null) {
if (!u.getFriends().contains(friend)
&& !u.getPeopleYouMayKnow().contains(friend)) {
u.getPeopleYouMayKnow().add(friend);
users.save(u);
}
}
}
private User findHim(ShadowUserDAO d) {
if (d.getEmail() != null) {
List<User> l = users.findByEmailIgnoreCase(d.getEmail());
if (l != null && !l.isEmpty()) {
return l.get(0);
UserService
If a friend was found & isn't already a friend or in the "People You May Know" list...
current.setEmail(d.getEmail());
current.setPhone(d.getPhone());
current.setSecondaryPhone(d.getSecondaryPhone());
shadows.save(current);
updatePeopleYouMayKnow(d, u);
}
}
}
}
private void updatePeopleYouMayKnow(ShadowUserDAO d, User u) {
User friend = findHim(d);
if (friend != null) {
if (!u.getFriends().contains(friend)
&& !u.getPeopleYouMayKnow().contains(friend)) {
u.getPeopleYouMayKnow().add(friend);
users.save(u);
}
}
}
private User findHim(ShadowUserDAO d) {
if (d.getEmail() != null) {
List<User> l = users.findByEmailIgnoreCase(d.getEmail());
if (l != null && !l.isEmpty()) {
return l.get(0);
UserService
Then we can add that user to the people you may know
}
}
}
private User findHim(ShadowUserDAO d) {
if (d.getEmail() != null) {
List<User> l = users.findByEmailIgnoreCase(d.getEmail());
if (l != null && !l.isEmpty()) {
return l.get(0);
}
}
if (d.getPhone() != null) {
List<User> l = users.findByPhone(d.getPhone());
if (l != null && !l.isEmpty()) {
return l.get(0);
}
}
if (d.getSecondaryPhone() != null) {
List<User> l = users.findByPhone(d.getSecondaryPhone());
if (l != null && !l.isEmpty()) {
return l.get(0);
}
}
return null;
}
}
UserService
The findHim method is simple boilerplate that searches based on all the meta data in the shadow user. We use findByEmail/phone etc. to find the shadow user in our
regular user database.

With that we finished the UserService class which is the largest service class!

More Related Content

Similar to Creating a Facebook Clone - Part XXII - Transcript.pdf

Creating a Facebook Clone - Part XXIV.pdf
Creating a Facebook Clone - Part XXIV.pdfCreating a Facebook Clone - Part XXIV.pdf
Creating a Facebook Clone - Part XXIV.pdf
ShaiAlmog1
 
Creating a Facebook Clone - Part XXVIII.pdf
Creating a Facebook Clone - Part XXVIII.pdfCreating a Facebook Clone - Part XXVIII.pdf
Creating a Facebook Clone - Part XXVIII.pdf
ShaiAlmog1
 
Creating an Uber Clone - Part XXXX.pdf
Creating an Uber Clone - Part XXXX.pdfCreating an Uber Clone - Part XXXX.pdf
Creating an Uber Clone - Part XXXX.pdf
ShaiAlmog1
 
Creating a Facebook Clone - Part XXVIII - Transcript.pdf
Creating a Facebook Clone - Part XXVIII - Transcript.pdfCreating a Facebook Clone - Part XXVIII - Transcript.pdf
Creating a Facebook Clone - Part XXVIII - Transcript.pdf
ShaiAlmog1
 
Creating a Facebook Clone - Part XLV.pdf
Creating a Facebook Clone - Part XLV.pdfCreating a Facebook Clone - Part XLV.pdf
Creating a Facebook Clone - Part XLV.pdf
ShaiAlmog1
 
SenchaTouch 2 and Sencha.io
SenchaTouch 2 and Sencha.ioSenchaTouch 2 and Sencha.io
SenchaTouch 2 and Sencha.io
Nils Dehl
 
Creating a Facebook Clone - Part XXXVII.pdf
Creating a Facebook Clone - Part XXXVII.pdfCreating a Facebook Clone - Part XXXVII.pdf
Creating a Facebook Clone - Part XXXVII.pdf
ShaiAlmog1
 
Lesson_07_Spring_Security_Register_NEW.pdf
Lesson_07_Spring_Security_Register_NEW.pdfLesson_07_Spring_Security_Register_NEW.pdf
Lesson_07_Spring_Security_Register_NEW.pdf
Scott Anderson
 
Creating a Facebook Clone - Part XXVI - Transcript.pdf
Creating a Facebook Clone - Part XXVI - Transcript.pdfCreating a Facebook Clone - Part XXVI - Transcript.pdf
Creating a Facebook Clone - Part XXVI - Transcript.pdf
ShaiAlmog1
 
Creating a Facebook Clone - Part XXXVIII.pdf
Creating a Facebook Clone - Part XXXVIII.pdfCreating a Facebook Clone - Part XXXVIII.pdf
Creating a Facebook Clone - Part XXXVIII.pdf
ShaiAlmog1
 
Angular 2 Component Communication - Talk by Rob McDiarmid
Angular 2 Component Communication - Talk by Rob McDiarmidAngular 2 Component Communication - Talk by Rob McDiarmid
Angular 2 Component Communication - Talk by Rob McDiarmid
Amrita Chopra
 
Creating a Whatsapp Clone - Part XIV - Transcript.pdf
Creating a Whatsapp Clone - Part XIV - Transcript.pdfCreating a Whatsapp Clone - Part XIV - Transcript.pdf
Creating a Whatsapp Clone - Part XIV - Transcript.pdf
ShaiAlmog1
 
Command-Oriented Architecture
Command-Oriented ArchitectureCommand-Oriented Architecture
Command-Oriented Architecture
Luiz Messias
 
Testando API's de forma unitária mocando as dependências
Testando API's de forma unitária mocando as dependênciasTestando API's de forma unitária mocando as dependências
Testando API's de forma unitária mocando as dependências
Marcelo Aymone
 
Creating a Whatsapp Clone - Part XI.pdf
Creating a Whatsapp Clone - Part XI.pdfCreating a Whatsapp Clone - Part XI.pdf
Creating a Whatsapp Clone - Part XI.pdf
ShaiAlmog1
 
Guard Authentication: Powerful, Beautiful Security
Guard Authentication: Powerful, Beautiful SecurityGuard Authentication: Powerful, Beautiful Security
Guard Authentication: Powerful, Beautiful Security
Ryan Weaver
 
Scala UA: Big Step To Functional Programming
Scala UA: Big Step To Functional ProgrammingScala UA: Big Step To Functional Programming
Scala UA: Big Step To Functional Programming
Alex Fruzenshtein
 
Codemotion appengine
Codemotion appengineCodemotion appengine
Codemotion appengine
Ignacio Coloma
 

Similar to Creating a Facebook Clone - Part XXII - Transcript.pdf (18)

Creating a Facebook Clone - Part XXIV.pdf
Creating a Facebook Clone - Part XXIV.pdfCreating a Facebook Clone - Part XXIV.pdf
Creating a Facebook Clone - Part XXIV.pdf
 
Creating a Facebook Clone - Part XXVIII.pdf
Creating a Facebook Clone - Part XXVIII.pdfCreating a Facebook Clone - Part XXVIII.pdf
Creating a Facebook Clone - Part XXVIII.pdf
 
Creating an Uber Clone - Part XXXX.pdf
Creating an Uber Clone - Part XXXX.pdfCreating an Uber Clone - Part XXXX.pdf
Creating an Uber Clone - Part XXXX.pdf
 
Creating a Facebook Clone - Part XXVIII - Transcript.pdf
Creating a Facebook Clone - Part XXVIII - Transcript.pdfCreating a Facebook Clone - Part XXVIII - Transcript.pdf
Creating a Facebook Clone - Part XXVIII - Transcript.pdf
 
Creating a Facebook Clone - Part XLV.pdf
Creating a Facebook Clone - Part XLV.pdfCreating a Facebook Clone - Part XLV.pdf
Creating a Facebook Clone - Part XLV.pdf
 
SenchaTouch 2 and Sencha.io
SenchaTouch 2 and Sencha.ioSenchaTouch 2 and Sencha.io
SenchaTouch 2 and Sencha.io
 
Creating a Facebook Clone - Part XXXVII.pdf
Creating a Facebook Clone - Part XXXVII.pdfCreating a Facebook Clone - Part XXXVII.pdf
Creating a Facebook Clone - Part XXXVII.pdf
 
Lesson_07_Spring_Security_Register_NEW.pdf
Lesson_07_Spring_Security_Register_NEW.pdfLesson_07_Spring_Security_Register_NEW.pdf
Lesson_07_Spring_Security_Register_NEW.pdf
 
Creating a Facebook Clone - Part XXVI - Transcript.pdf
Creating a Facebook Clone - Part XXVI - Transcript.pdfCreating a Facebook Clone - Part XXVI - Transcript.pdf
Creating a Facebook Clone - Part XXVI - Transcript.pdf
 
Creating a Facebook Clone - Part XXXVIII.pdf
Creating a Facebook Clone - Part XXXVIII.pdfCreating a Facebook Clone - Part XXXVIII.pdf
Creating a Facebook Clone - Part XXXVIII.pdf
 
Angular 2 Component Communication - Talk by Rob McDiarmid
Angular 2 Component Communication - Talk by Rob McDiarmidAngular 2 Component Communication - Talk by Rob McDiarmid
Angular 2 Component Communication - Talk by Rob McDiarmid
 
Creating a Whatsapp Clone - Part XIV - Transcript.pdf
Creating a Whatsapp Clone - Part XIV - Transcript.pdfCreating a Whatsapp Clone - Part XIV - Transcript.pdf
Creating a Whatsapp Clone - Part XIV - Transcript.pdf
 
Command-Oriented Architecture
Command-Oriented ArchitectureCommand-Oriented Architecture
Command-Oriented Architecture
 
Testando API's de forma unitária mocando as dependências
Testando API's de forma unitária mocando as dependênciasTestando API's de forma unitária mocando as dependências
Testando API's de forma unitária mocando as dependências
 
Creating a Whatsapp Clone - Part XI.pdf
Creating a Whatsapp Clone - Part XI.pdfCreating a Whatsapp Clone - Part XI.pdf
Creating a Whatsapp Clone - Part XI.pdf
 
Guard Authentication: Powerful, Beautiful Security
Guard Authentication: Powerful, Beautiful SecurityGuard Authentication: Powerful, Beautiful Security
Guard Authentication: Powerful, Beautiful Security
 
Scala UA: Big Step To Functional Programming
Scala UA: Big Step To Functional ProgrammingScala UA: Big Step To Functional Programming
Scala UA: Big Step To Functional Programming
 
Codemotion appengine
Codemotion appengineCodemotion appengine
Codemotion appengine
 

More from ShaiAlmog1

The Duck Teaches Learn to debug from the masters. Local to production- kill ...
The Duck Teaches  Learn to debug from the masters. Local to production- kill ...The Duck Teaches  Learn to debug from the masters. Local to production- kill ...
The Duck Teaches Learn to debug from the masters. Local to production- kill ...
ShaiAlmog1
 
create-netflix-clone-06-client-ui.pdf
create-netflix-clone-06-client-ui.pdfcreate-netflix-clone-06-client-ui.pdf
create-netflix-clone-06-client-ui.pdf
ShaiAlmog1
 
create-netflix-clone-01-introduction_transcript.pdf
create-netflix-clone-01-introduction_transcript.pdfcreate-netflix-clone-01-introduction_transcript.pdf
create-netflix-clone-01-introduction_transcript.pdf
ShaiAlmog1
 
create-netflix-clone-02-server_transcript.pdf
create-netflix-clone-02-server_transcript.pdfcreate-netflix-clone-02-server_transcript.pdf
create-netflix-clone-02-server_transcript.pdf
ShaiAlmog1
 
create-netflix-clone-04-server-continued_transcript.pdf
create-netflix-clone-04-server-continued_transcript.pdfcreate-netflix-clone-04-server-continued_transcript.pdf
create-netflix-clone-04-server-continued_transcript.pdf
ShaiAlmog1
 
create-netflix-clone-01-introduction.pdf
create-netflix-clone-01-introduction.pdfcreate-netflix-clone-01-introduction.pdf
create-netflix-clone-01-introduction.pdf
ShaiAlmog1
 
create-netflix-clone-06-client-ui_transcript.pdf
create-netflix-clone-06-client-ui_transcript.pdfcreate-netflix-clone-06-client-ui_transcript.pdf
create-netflix-clone-06-client-ui_transcript.pdf
ShaiAlmog1
 
create-netflix-clone-03-server.pdf
create-netflix-clone-03-server.pdfcreate-netflix-clone-03-server.pdf
create-netflix-clone-03-server.pdf
ShaiAlmog1
 
create-netflix-clone-04-server-continued.pdf
create-netflix-clone-04-server-continued.pdfcreate-netflix-clone-04-server-continued.pdf
create-netflix-clone-04-server-continued.pdf
ShaiAlmog1
 
create-netflix-clone-05-client-model_transcript.pdf
create-netflix-clone-05-client-model_transcript.pdfcreate-netflix-clone-05-client-model_transcript.pdf
create-netflix-clone-05-client-model_transcript.pdf
ShaiAlmog1
 
create-netflix-clone-03-server_transcript.pdf
create-netflix-clone-03-server_transcript.pdfcreate-netflix-clone-03-server_transcript.pdf
create-netflix-clone-03-server_transcript.pdf
ShaiAlmog1
 
create-netflix-clone-02-server.pdf
create-netflix-clone-02-server.pdfcreate-netflix-clone-02-server.pdf
create-netflix-clone-02-server.pdf
ShaiAlmog1
 
create-netflix-clone-05-client-model.pdf
create-netflix-clone-05-client-model.pdfcreate-netflix-clone-05-client-model.pdf
create-netflix-clone-05-client-model.pdf
ShaiAlmog1
 
Creating a Whatsapp Clone - Part II.pdf
Creating a Whatsapp Clone - Part II.pdfCreating a Whatsapp Clone - Part II.pdf
Creating a Whatsapp Clone - Part II.pdf
ShaiAlmog1
 
Creating a Whatsapp Clone - Part IX - Transcript.pdf
Creating a Whatsapp Clone - Part IX - Transcript.pdfCreating a Whatsapp Clone - Part IX - Transcript.pdf
Creating a Whatsapp Clone - Part IX - Transcript.pdf
ShaiAlmog1
 
Creating a Whatsapp Clone - Part II - Transcript.pdf
Creating a Whatsapp Clone - Part II - Transcript.pdfCreating a Whatsapp Clone - Part II - Transcript.pdf
Creating a Whatsapp Clone - Part II - Transcript.pdf
ShaiAlmog1
 
Creating a Whatsapp Clone - Part V - Transcript.pdf
Creating a Whatsapp Clone - Part V - Transcript.pdfCreating a Whatsapp Clone - Part V - Transcript.pdf
Creating a Whatsapp Clone - Part V - Transcript.pdf
ShaiAlmog1
 
Creating a Whatsapp Clone - Part IV - Transcript.pdf
Creating a Whatsapp Clone - Part IV - Transcript.pdfCreating a Whatsapp Clone - Part IV - Transcript.pdf
Creating a Whatsapp Clone - Part IV - Transcript.pdf
ShaiAlmog1
 
Creating a Whatsapp Clone - Part IV.pdf
Creating a Whatsapp Clone - Part IV.pdfCreating a Whatsapp Clone - Part IV.pdf
Creating a Whatsapp Clone - Part IV.pdf
ShaiAlmog1
 
Creating a Whatsapp Clone - Part I - Transcript.pdf
Creating a Whatsapp Clone - Part I - Transcript.pdfCreating a Whatsapp Clone - Part I - Transcript.pdf
Creating a Whatsapp Clone - Part I - Transcript.pdf
ShaiAlmog1
 

More from ShaiAlmog1 (20)

The Duck Teaches Learn to debug from the masters. Local to production- kill ...
The Duck Teaches  Learn to debug from the masters. Local to production- kill ...The Duck Teaches  Learn to debug from the masters. Local to production- kill ...
The Duck Teaches Learn to debug from the masters. Local to production- kill ...
 
create-netflix-clone-06-client-ui.pdf
create-netflix-clone-06-client-ui.pdfcreate-netflix-clone-06-client-ui.pdf
create-netflix-clone-06-client-ui.pdf
 
create-netflix-clone-01-introduction_transcript.pdf
create-netflix-clone-01-introduction_transcript.pdfcreate-netflix-clone-01-introduction_transcript.pdf
create-netflix-clone-01-introduction_transcript.pdf
 
create-netflix-clone-02-server_transcript.pdf
create-netflix-clone-02-server_transcript.pdfcreate-netflix-clone-02-server_transcript.pdf
create-netflix-clone-02-server_transcript.pdf
 
create-netflix-clone-04-server-continued_transcript.pdf
create-netflix-clone-04-server-continued_transcript.pdfcreate-netflix-clone-04-server-continued_transcript.pdf
create-netflix-clone-04-server-continued_transcript.pdf
 
create-netflix-clone-01-introduction.pdf
create-netflix-clone-01-introduction.pdfcreate-netflix-clone-01-introduction.pdf
create-netflix-clone-01-introduction.pdf
 
create-netflix-clone-06-client-ui_transcript.pdf
create-netflix-clone-06-client-ui_transcript.pdfcreate-netflix-clone-06-client-ui_transcript.pdf
create-netflix-clone-06-client-ui_transcript.pdf
 
create-netflix-clone-03-server.pdf
create-netflix-clone-03-server.pdfcreate-netflix-clone-03-server.pdf
create-netflix-clone-03-server.pdf
 
create-netflix-clone-04-server-continued.pdf
create-netflix-clone-04-server-continued.pdfcreate-netflix-clone-04-server-continued.pdf
create-netflix-clone-04-server-continued.pdf
 
create-netflix-clone-05-client-model_transcript.pdf
create-netflix-clone-05-client-model_transcript.pdfcreate-netflix-clone-05-client-model_transcript.pdf
create-netflix-clone-05-client-model_transcript.pdf
 
create-netflix-clone-03-server_transcript.pdf
create-netflix-clone-03-server_transcript.pdfcreate-netflix-clone-03-server_transcript.pdf
create-netflix-clone-03-server_transcript.pdf
 
create-netflix-clone-02-server.pdf
create-netflix-clone-02-server.pdfcreate-netflix-clone-02-server.pdf
create-netflix-clone-02-server.pdf
 
create-netflix-clone-05-client-model.pdf
create-netflix-clone-05-client-model.pdfcreate-netflix-clone-05-client-model.pdf
create-netflix-clone-05-client-model.pdf
 
Creating a Whatsapp Clone - Part II.pdf
Creating a Whatsapp Clone - Part II.pdfCreating a Whatsapp Clone - Part II.pdf
Creating a Whatsapp Clone - Part II.pdf
 
Creating a Whatsapp Clone - Part IX - Transcript.pdf
Creating a Whatsapp Clone - Part IX - Transcript.pdfCreating a Whatsapp Clone - Part IX - Transcript.pdf
Creating a Whatsapp Clone - Part IX - Transcript.pdf
 
Creating a Whatsapp Clone - Part II - Transcript.pdf
Creating a Whatsapp Clone - Part II - Transcript.pdfCreating a Whatsapp Clone - Part II - Transcript.pdf
Creating a Whatsapp Clone - Part II - Transcript.pdf
 
Creating a Whatsapp Clone - Part V - Transcript.pdf
Creating a Whatsapp Clone - Part V - Transcript.pdfCreating a Whatsapp Clone - Part V - Transcript.pdf
Creating a Whatsapp Clone - Part V - Transcript.pdf
 
Creating a Whatsapp Clone - Part IV - Transcript.pdf
Creating a Whatsapp Clone - Part IV - Transcript.pdfCreating a Whatsapp Clone - Part IV - Transcript.pdf
Creating a Whatsapp Clone - Part IV - Transcript.pdf
 
Creating a Whatsapp Clone - Part IV.pdf
Creating a Whatsapp Clone - Part IV.pdfCreating a Whatsapp Clone - Part IV.pdf
Creating a Whatsapp Clone - Part IV.pdf
 
Creating a Whatsapp Clone - Part I - Transcript.pdf
Creating a Whatsapp Clone - Part I - Transcript.pdfCreating a Whatsapp Clone - Part I - Transcript.pdf
Creating a Whatsapp Clone - Part I - Transcript.pdf
 

Recently uploaded

A Comprehensive Guide to DeFi Development Services in 2024
A Comprehensive Guide to DeFi Development Services in 2024A Comprehensive Guide to DeFi Development Services in 2024
A Comprehensive Guide to DeFi Development Services in 2024
Intelisync
 
Main news related to the CCS TSI 2023 (2023/1695)
Main news related to the CCS TSI 2023 (2023/1695)Main news related to the CCS TSI 2023 (2023/1695)
Main news related to the CCS TSI 2023 (2023/1695)
Jakub Marek
 
Deep Dive: Getting Funded with Jason Jason Lemkin Founder & CEO @ SaaStr
Deep Dive: Getting Funded with Jason Jason Lemkin Founder & CEO @ SaaStrDeep Dive: Getting Funded with Jason Jason Lemkin Founder & CEO @ SaaStr
Deep Dive: Getting Funded with Jason Jason Lemkin Founder & CEO @ SaaStr
saastr
 
Salesforce Integration for Bonterra Impact Management (fka Social Solutions A...
Salesforce Integration for Bonterra Impact Management (fka Social Solutions A...Salesforce Integration for Bonterra Impact Management (fka Social Solutions A...
Salesforce Integration for Bonterra Impact Management (fka Social Solutions A...
Jeffrey Haguewood
 
Skybuffer AI: Advanced Conversational and Generative AI Solution on SAP Busin...
Skybuffer AI: Advanced Conversational and Generative AI Solution on SAP Busin...Skybuffer AI: Advanced Conversational and Generative AI Solution on SAP Busin...
Skybuffer AI: Advanced Conversational and Generative AI Solution on SAP Busin...
Tatiana Kojar
 
Skybuffer SAM4U tool for SAP license adoption
Skybuffer SAM4U tool for SAP license adoptionSkybuffer SAM4U tool for SAP license adoption
Skybuffer SAM4U tool for SAP license adoption
Tatiana Kojar
 
June Patch Tuesday
June Patch TuesdayJune Patch Tuesday
June Patch Tuesday
Ivanti
 
HCL Notes and Domino License Cost Reduction in the World of DLAU
HCL Notes and Domino License Cost Reduction in the World of DLAUHCL Notes and Domino License Cost Reduction in the World of DLAU
HCL Notes and Domino License Cost Reduction in the World of DLAU
panagenda
 
Nunit vs XUnit vs MSTest Differences Between These Unit Testing Frameworks.pdf
Nunit vs XUnit vs MSTest Differences Between These Unit Testing Frameworks.pdfNunit vs XUnit vs MSTest Differences Between These Unit Testing Frameworks.pdf
Nunit vs XUnit vs MSTest Differences Between These Unit Testing Frameworks.pdf
flufftailshop
 
Nordic Marketo Engage User Group_June 13_ 2024.pptx
Nordic Marketo Engage User Group_June 13_ 2024.pptxNordic Marketo Engage User Group_June 13_ 2024.pptx
Nordic Marketo Engage User Group_June 13_ 2024.pptx
MichaelKnudsen27
 
System Design Case Study: Building a Scalable E-Commerce Platform - Hiike
System Design Case Study: Building a Scalable E-Commerce Platform - HiikeSystem Design Case Study: Building a Scalable E-Commerce Platform - Hiike
System Design Case Study: Building a Scalable E-Commerce Platform - Hiike
Hiike
 
Generating privacy-protected synthetic data using Secludy and Milvus
Generating privacy-protected synthetic data using Secludy and MilvusGenerating privacy-protected synthetic data using Secludy and Milvus
Generating privacy-protected synthetic data using Secludy and Milvus
Zilliz
 
Choosing The Best AWS Service For Your Website + API.pptx
Choosing The Best AWS Service For Your Website + API.pptxChoosing The Best AWS Service For Your Website + API.pptx
Choosing The Best AWS Service For Your Website + API.pptx
Brandon Minnick, MBA
 
Monitoring and Managing Anomaly Detection on OpenShift.pdf
Monitoring and Managing Anomaly Detection on OpenShift.pdfMonitoring and Managing Anomaly Detection on OpenShift.pdf
Monitoring and Managing Anomaly Detection on OpenShift.pdf
Tosin Akinosho
 
Driving Business Innovation: Latest Generative AI Advancements & Success Story
Driving Business Innovation: Latest Generative AI Advancements & Success StoryDriving Business Innovation: Latest Generative AI Advancements & Success Story
Driving Business Innovation: Latest Generative AI Advancements & Success Story
Safe Software
 
Programming Foundation Models with DSPy - Meetup Slides
Programming Foundation Models with DSPy - Meetup SlidesProgramming Foundation Models with DSPy - Meetup Slides
Programming Foundation Models with DSPy - Meetup Slides
Zilliz
 
AWS Cloud Cost Optimization Presentation.pptx
AWS Cloud Cost Optimization Presentation.pptxAWS Cloud Cost Optimization Presentation.pptx
AWS Cloud Cost Optimization Presentation.pptx
HarisZaheer8
 
Fueling AI with Great Data with Airbyte Webinar
Fueling AI with Great Data with Airbyte WebinarFueling AI with Great Data with Airbyte Webinar
Fueling AI with Great Data with Airbyte Webinar
Zilliz
 
Artificial Intelligence for XMLDevelopment
Artificial Intelligence for XMLDevelopmentArtificial Intelligence for XMLDevelopment
Artificial Intelligence for XMLDevelopment
Octavian Nadolu
 
Introduction of Cybersecurity with OSS at Code Europe 2024
Introduction of Cybersecurity with OSS  at Code Europe 2024Introduction of Cybersecurity with OSS  at Code Europe 2024
Introduction of Cybersecurity with OSS at Code Europe 2024
Hiroshi SHIBATA
 

Recently uploaded (20)

A Comprehensive Guide to DeFi Development Services in 2024
A Comprehensive Guide to DeFi Development Services in 2024A Comprehensive Guide to DeFi Development Services in 2024
A Comprehensive Guide to DeFi Development Services in 2024
 
Main news related to the CCS TSI 2023 (2023/1695)
Main news related to the CCS TSI 2023 (2023/1695)Main news related to the CCS TSI 2023 (2023/1695)
Main news related to the CCS TSI 2023 (2023/1695)
 
Deep Dive: Getting Funded with Jason Jason Lemkin Founder & CEO @ SaaStr
Deep Dive: Getting Funded with Jason Jason Lemkin Founder & CEO @ SaaStrDeep Dive: Getting Funded with Jason Jason Lemkin Founder & CEO @ SaaStr
Deep Dive: Getting Funded with Jason Jason Lemkin Founder & CEO @ SaaStr
 
Salesforce Integration for Bonterra Impact Management (fka Social Solutions A...
Salesforce Integration for Bonterra Impact Management (fka Social Solutions A...Salesforce Integration for Bonterra Impact Management (fka Social Solutions A...
Salesforce Integration for Bonterra Impact Management (fka Social Solutions A...
 
Skybuffer AI: Advanced Conversational and Generative AI Solution on SAP Busin...
Skybuffer AI: Advanced Conversational and Generative AI Solution on SAP Busin...Skybuffer AI: Advanced Conversational and Generative AI Solution on SAP Busin...
Skybuffer AI: Advanced Conversational and Generative AI Solution on SAP Busin...
 
Skybuffer SAM4U tool for SAP license adoption
Skybuffer SAM4U tool for SAP license adoptionSkybuffer SAM4U tool for SAP license adoption
Skybuffer SAM4U tool for SAP license adoption
 
June Patch Tuesday
June Patch TuesdayJune Patch Tuesday
June Patch Tuesday
 
HCL Notes and Domino License Cost Reduction in the World of DLAU
HCL Notes and Domino License Cost Reduction in the World of DLAUHCL Notes and Domino License Cost Reduction in the World of DLAU
HCL Notes and Domino License Cost Reduction in the World of DLAU
 
Nunit vs XUnit vs MSTest Differences Between These Unit Testing Frameworks.pdf
Nunit vs XUnit vs MSTest Differences Between These Unit Testing Frameworks.pdfNunit vs XUnit vs MSTest Differences Between These Unit Testing Frameworks.pdf
Nunit vs XUnit vs MSTest Differences Between These Unit Testing Frameworks.pdf
 
Nordic Marketo Engage User Group_June 13_ 2024.pptx
Nordic Marketo Engage User Group_June 13_ 2024.pptxNordic Marketo Engage User Group_June 13_ 2024.pptx
Nordic Marketo Engage User Group_June 13_ 2024.pptx
 
System Design Case Study: Building a Scalable E-Commerce Platform - Hiike
System Design Case Study: Building a Scalable E-Commerce Platform - HiikeSystem Design Case Study: Building a Scalable E-Commerce Platform - Hiike
System Design Case Study: Building a Scalable E-Commerce Platform - Hiike
 
Generating privacy-protected synthetic data using Secludy and Milvus
Generating privacy-protected synthetic data using Secludy and MilvusGenerating privacy-protected synthetic data using Secludy and Milvus
Generating privacy-protected synthetic data using Secludy and Milvus
 
Choosing The Best AWS Service For Your Website + API.pptx
Choosing The Best AWS Service For Your Website + API.pptxChoosing The Best AWS Service For Your Website + API.pptx
Choosing The Best AWS Service For Your Website + API.pptx
 
Monitoring and Managing Anomaly Detection on OpenShift.pdf
Monitoring and Managing Anomaly Detection on OpenShift.pdfMonitoring and Managing Anomaly Detection on OpenShift.pdf
Monitoring and Managing Anomaly Detection on OpenShift.pdf
 
Driving Business Innovation: Latest Generative AI Advancements & Success Story
Driving Business Innovation: Latest Generative AI Advancements & Success StoryDriving Business Innovation: Latest Generative AI Advancements & Success Story
Driving Business Innovation: Latest Generative AI Advancements & Success Story
 
Programming Foundation Models with DSPy - Meetup Slides
Programming Foundation Models with DSPy - Meetup SlidesProgramming Foundation Models with DSPy - Meetup Slides
Programming Foundation Models with DSPy - Meetup Slides
 
AWS Cloud Cost Optimization Presentation.pptx
AWS Cloud Cost Optimization Presentation.pptxAWS Cloud Cost Optimization Presentation.pptx
AWS Cloud Cost Optimization Presentation.pptx
 
Fueling AI with Great Data with Airbyte Webinar
Fueling AI with Great Data with Airbyte WebinarFueling AI with Great Data with Airbyte Webinar
Fueling AI with Great Data with Airbyte Webinar
 
Artificial Intelligence for XMLDevelopment
Artificial Intelligence for XMLDevelopmentArtificial Intelligence for XMLDevelopment
Artificial Intelligence for XMLDevelopment
 
Introduction of Cybersecurity with OSS at Code Europe 2024
Introduction of Cybersecurity with OSS  at Code Europe 2024Introduction of Cybersecurity with OSS  at Code Europe 2024
Introduction of Cybersecurity with OSS at Code Europe 2024
 

Creating a Facebook Clone - Part XXII - Transcript.pdf

  • 1. Creating a Facebook Clone - Part XXII UserService is a big class and it makes sense to cover in two parts
  • 2. setProps(user, u); if (u.getPassword() != null) { u.setPassword(encoder.encode(user.getPassword())); } users.save(u); } public byte[] getAvatar(String userId) { User u = users.findById(userId).get(); if (u.getAvatar() != null) { return u.getAvatar().getData(); } return null; } public void setAvatar(String authToken, String mediaId) { Media m = medias.findById(mediaId).get(); User u = users.findByAuthtoken(authToken).get(0); u.setAvatar(m); users.save(u); } public void sendFriendRequest(String auth, String userId) { User me = users.findByAuthtoken(auth).get(0); User him = users.findById(userId).get(); UserService Next on the agenda is getAvatar, it returns the avatar picture of the user as a byte array
  • 3. setProps(user, u); if (u.getPassword() != null) { u.setPassword(encoder.encode(user.getPassword())); } users.save(u); } public byte[] getAvatar(String userId) { User u = users.findById(userId).get(); if (u.getAvatar() != null) { return u.getAvatar().getData(); } return null; } public void setAvatar(String authToken, String mediaId) { Media m = medias.findById(mediaId).get(); User u = users.findByAuthtoken(authToken).get(0); u.setAvatar(m); users.save(u); } public void sendFriendRequest(String auth, String userId) { User me = users.findByAuthtoken(auth).get(0); User him = users.findById(userId).get(); UserService Notice we need an id and not a token to get the avatar as anyone who is familiar with the user ID should be able to see the avatar
  • 4. setProps(user, u); if (u.getPassword() != null) { u.setPassword(encoder.encode(user.getPassword())); } users.save(u); } public byte[] getAvatar(String userId) { User u = users.findById(userId).get(); if (u.getAvatar() != null) { return u.getAvatar().getData(); } return null; } public void setAvatar(String authToken, String mediaId) { Media m = medias.findById(mediaId).get(); User u = users.findByAuthtoken(authToken).get(0); u.setAvatar(m); users.save(u); } public void sendFriendRequest(String auth, String userId) { User me = users.findByAuthtoken(auth).get(0); User him = users.findById(userId).get(); UserService If the avatar reference is null we return null instantly
  • 5. setProps(user, u); if (u.getPassword() != null) { u.setPassword(encoder.encode(user.getPassword())); } users.save(u); } public byte[] getAvatar(String userId) { User u = users.findById(userId).get(); if (u.getAvatar() != null) { return u.getAvatar().getData(); } return null; } public void setAvatar(String authToken, String mediaId) { Media m = medias.findById(mediaId).get(); User u = users.findByAuthtoken(authToken).get(0); u.setAvatar(m); users.save(u); } public void sendFriendRequest(String auth, String userId) { User me = users.findByAuthtoken(auth).get(0); User him = users.findById(userId).get(); UserService The setAvatar method works in a similar way
  • 6. setProps(user, u); if (u.getPassword() != null) { u.setPassword(encoder.encode(user.getPassword())); } users.save(u); } public byte[] getAvatar(String userId) { User u = users.findById(userId).get(); if (u.getAvatar() != null) { return u.getAvatar().getData(); } return null; } public void setAvatar(String authToken, String mediaId) { Media m = medias.findById(mediaId).get(); User u = users.findByAuthtoken(authToken).get(0); u.setAvatar(m); users.save(u); } public void sendFriendRequest(String auth, String userId) { User me = users.findByAuthtoken(auth).get(0); User him = users.findById(userId).get(); UserService Notice that unlike getAvatar with setAvatar we need a token as this is a set operation. This prevents other users from changing our avatar. When we map this to the webservice we need to first create a media entry and only then set the avatar value.
  • 7. u.setAvatar(m); users.save(u); } public void sendFriendRequest(String auth, String userId) { User me = users.findByAuthtoken(auth).get(0); User him = users.findById(userId).get(); him.getFriendRequests().add(me); users.save(him); notifications.sendNotification(him, new NotificationDAO(null, me.getDAO(), "wants to be friends", "uE7FC", 0x587EBE, 0, true, null, null)); } public void acceptFriendRequest(String auth, String userId) { User me = users.findByAuthtoken(auth).get(0); User him = users.findById(userId).get(); if (me.getFriendRequests().contains(him)) { me.getFriendRequests().remove(him); me.getFriends().add(him); him.getFriendRequests().remove(me); him.getFriends().add(me); users.saveAll(Arrays.asList(me, him)); UserService The friend request includes a few moving parts. First we need to send a request.
  • 8. u.setAvatar(m); users.save(u); } public void sendFriendRequest(String auth, String userId) { User me = users.findByAuthtoken(auth).get(0); User him = users.findById(userId).get(); him.getFriendRequests().add(me); users.save(him); notifications.sendNotification(him, new NotificationDAO(null, me.getDAO(), "wants to be friends", "uE7FC", 0x587EBE, 0, true, null, null)); } public void acceptFriendRequest(String auth, String userId) { User me = users.findByAuthtoken(auth).get(0); User him = users.findById(userId).get(); if (me.getFriendRequests().contains(him)) { me.getFriendRequests().remove(him); me.getFriends().add(him); him.getFriendRequests().remove(me); him.getFriends().add(me); users.saveAll(Arrays.asList(me, him)); UserService We need an auth token as this is a secure operation
  • 9. u.setAvatar(m); users.save(u); } public void sendFriendRequest(String auth, String userId) { User me = users.findByAuthtoken(auth).get(0); User him = users.findById(userId).get(); him.getFriendRequests().add(me); users.save(him); notifications.sendNotification(him, new NotificationDAO(null, me.getDAO(), "wants to be friends", "uE7FC", 0x587EBE, 0, true, null, null)); } public void acceptFriendRequest(String auth, String userId) { User me = users.findByAuthtoken(auth).get(0); User him = users.findById(userId).get(); if (me.getFriendRequests().contains(him)) { me.getFriendRequests().remove(him); me.getFriends().add(him); him.getFriendRequests().remove(me); him.getFriends().add(me); users.saveAll(Arrays.asList(me, him)); UserService We obviously don't have the auth token of the person we are "friending"
  • 10. u.setAvatar(m); users.save(u); } public void sendFriendRequest(String auth, String userId) { User me = users.findByAuthtoken(auth).get(0); User him = users.findById(userId).get(); him.getFriendRequests().add(me); users.save(him); notifications.sendNotification(him, new NotificationDAO(null, me.getDAO(), "wants to be friends", "uE7FC", 0x587EBE, 0, true, null, null)); } public void acceptFriendRequest(String auth, String userId) { User me = users.findByAuthtoken(auth).get(0); User him = users.findById(userId).get(); if (me.getFriendRequests().contains(him)) { me.getFriendRequests().remove(him); me.getFriends().add(him); him.getFriendRequests().remove(me); him.getFriends().add(me); users.saveAll(Arrays.asList(me, him)); UserService This is a special case where we modify his entity without an auth-token, that's a bit risky...
  • 11. u.setAvatar(m); users.save(u); } public void sendFriendRequest(String auth, String userId) { User me = users.findByAuthtoken(auth).get(0); User him = users.findById(userId).get(); him.getFriendRequests().add(me); users.save(him); notifications.sendNotification(him, new NotificationDAO(null, me.getDAO(), "wants to be friends", "uE7FC", 0x587EBE, 0, true, null, null)); } public void acceptFriendRequest(String auth, String userId) { User me = users.findByAuthtoken(auth).get(0); User him = users.findById(userId).get(); if (me.getFriendRequests().contains(him)) { me.getFriendRequests().remove(him); me.getFriends().add(him); him.getFriendRequests().remove(me); him.getFriends().add(me); users.saveAll(Arrays.asList(me, him)); UserService The notification service should notify the user that he got a new friend request. We'll dig into the notification service soon…
  • 12. public void sendFriendRequest(String auth, String userId) { User me = users.findByAuthtoken(auth).get(0); User him = users.findById(userId).get(); him.getFriendRequests().add(me); users.save(him); notifications.sendNotification(him, new NotificationDAO(null, me.getDAO(), "wants to be friends", "uE7FC", 0x587EBE, 0, true, null, null)); } public void acceptFriendRequest(String auth, String userId) { User me = users.findByAuthtoken(auth).get(0); User him = users.findById(userId).get(); if (me.getFriendRequests().contains(him)) { me.getFriendRequests().remove(him); me.getFriends().add(him); him.getFriendRequests().remove(me); him.getFriends().add(me); users.saveAll(Arrays.asList(me, him)); } } public void uploadContacts(String auth, List<ShadowUserDAO> contacts) { Long c = shadows.countByUser(auth); UserService But first lets check out the other side of the equation. The acceptFriendRequest method.
  • 13. public void sendFriendRequest(String auth, String userId) { User me = users.findByAuthtoken(auth).get(0); User him = users.findById(userId).get(); him.getFriendRequests().add(me); users.save(him); notifications.sendNotification(him, new NotificationDAO(null, me.getDAO(), "wants to be friends", "uE7FC", 0x587EBE, 0, true, null, null)); } public void acceptFriendRequest(String auth, String userId) { User me = users.findByAuthtoken(auth).get(0); User him = users.findById(userId).get(); if (me.getFriendRequests().contains(him)) { me.getFriendRequests().remove(him); me.getFriends().add(him); him.getFriendRequests().remove(me); him.getFriends().add(me); users.saveAll(Arrays.asList(me, him)); } } public void uploadContacts(String auth, List<ShadowUserDAO> contacts) { Long c = shadows.countByUser(auth); UserService This time me & him are flipped
  • 14. public void sendFriendRequest(String auth, String userId) { User me = users.findByAuthtoken(auth).get(0); User him = users.findById(userId).get(); him.getFriendRequests().add(me); users.save(him); notifications.sendNotification(him, new NotificationDAO(null, me.getDAO(), "wants to be friends", "uE7FC", 0x587EBE, 0, true, null, null)); } public void acceptFriendRequest(String auth, String userId) { User me = users.findByAuthtoken(auth).get(0); User him = users.findById(userId).get(); if (me.getFriendRequests().contains(him)) { me.getFriendRequests().remove(him); me.getFriends().add(him); him.getFriendRequests().remove(me); him.getFriends().add(me); users.saveAll(Arrays.asList(me, him)); } } public void uploadContacts(String auth, List<ShadowUserDAO> contacts) { Long c = shadows.countByUser(auth); UserService This checks against a potential weakness where a hacker could potentially call accept friend request for a person that didn't request it
  • 15. public void sendFriendRequest(String auth, String userId) { User me = users.findByAuthtoken(auth).get(0); User him = users.findById(userId).get(); him.getFriendRequests().add(me); users.save(him); notifications.sendNotification(him, new NotificationDAO(null, me.getDAO(), "wants to be friends", "uE7FC", 0x587EBE, 0, true, null, null)); } public void acceptFriendRequest(String auth, String userId) { User me = users.findByAuthtoken(auth).get(0); User him = users.findById(userId).get(); if (me.getFriendRequests().contains(him)) { me.getFriendRequests().remove(him); me.getFriends().add(him); him.getFriendRequests().remove(me); him.getFriends().add(me); users.saveAll(Arrays.asList(me, him)); } } public void uploadContacts(String auth, List<ShadowUserDAO> contacts) { Long c = shadows.countByUser(auth); UserService When a request is accepted we need to update the friend list on both sides. I didn't add a removeFriendRequest method which I probably should have added. I think it's trivial to add so I'm leaving it as an exercise.
  • 16. users.saveAll(Arrays.asList(me, him)); } } public void uploadContacts(String auth, List<ShadowUserDAO> contacts) { Long c = shadows.countByUser(auth); User u = users.findByAuthtoken(auth).get(0); if (c == null || c == 0) { List<ShadowUser> shadowList = new ArrayList<>(); for (ShadowUserDAO d : contacts) { shadowList.add(new ShadowUser(d, u)); updatePeopleYouMayKnow(d, u); } shadows.saveAll(shadowList); } else { for (ShadowUserDAO d : contacts) { List<ShadowUser> results = shadows.findByFullName(auth, d. getFullName()); if (!results.isEmpty()) { shadows.save(new ShadowUser(d, u)); } else { ShadowUser current = results.get(0); current.setEmail(d.getEmail()); current.setPhone(d.getPhone()); current.setSecondaryPhone(d.getSecondaryPhone()); shadows.save(current); UserService The last method for UserService is the `uploadContacts` method... It's invoked when the user uploads the contacts from his phone.
  • 17. users.saveAll(Arrays.asList(me, him)); } } public void uploadContacts(String auth, List<ShadowUserDAO> contacts) { Long c = shadows.countByUser(auth); User u = users.findByAuthtoken(auth).get(0); if (c == null || c == 0) { List<ShadowUser> shadowList = new ArrayList<>(); for (ShadowUserDAO d : contacts) { shadowList.add(new ShadowUser(d, u)); updatePeopleYouMayKnow(d, u); } shadows.saveAll(shadowList); } else { for (ShadowUserDAO d : contacts) { List<ShadowUser> results = shadows.findByFullName(auth, d. getFullName()); if (!results.isEmpty()) { shadows.save(new ShadowUser(d, u)); } else { ShadowUser current = results.get(0); current.setEmail(d.getEmail()); current.setPhone(d.getPhone()); current.setSecondaryPhone(d.getSecondaryPhone()); shadows.save(current); UserService If we uploaded contacts in the past its a good idea to try and merge with what we have. We can check that by running a count query
  • 18. users.saveAll(Arrays.asList(me, him)); } } public void uploadContacts(String auth, List<ShadowUserDAO> contacts) { Long c = shadows.countByUser(auth); User u = users.findByAuthtoken(auth).get(0); if (c == null || c == 0) { List<ShadowUser> shadowList = new ArrayList<>(); for (ShadowUserDAO d : contacts) { shadowList.add(new ShadowUser(d, u)); updatePeopleYouMayKnow(d, u); } shadows.saveAll(shadowList); } else { for (ShadowUserDAO d : contacts) { List<ShadowUser> results = shadows.findByFullName(auth, d. getFullName()); if (!results.isEmpty()) { shadows.save(new ShadowUser(d, u)); } else { ShadowUser current = results.get(0); current.setEmail(d.getEmail()); current.setPhone(d.getPhone()); current.setSecondaryPhone(d.getSecondaryPhone()); shadows.save(current); UserService For every contact we find we check to see if there is a user in the system and if so we add that user to the people you may know list
  • 19. users.saveAll(Arrays.asList(me, him)); } } public void uploadContacts(String auth, List<ShadowUserDAO> contacts) { Long c = shadows.countByUser(auth); User u = users.findByAuthtoken(auth).get(0); if (c == null || c == 0) { List<ShadowUser> shadowList = new ArrayList<>(); for (ShadowUserDAO d : contacts) { shadowList.add(new ShadowUser(d, u)); updatePeopleYouMayKnow(d, u); } shadows.saveAll(shadowList); } else { for (ShadowUserDAO d : contacts) { List<ShadowUser> results = shadows.findByFullName(auth, d. getFullName()); if (!results.isEmpty()) { shadows.save(new ShadowUser(d, u)); } else { ShadowUser current = results.get(0); current.setEmail(d.getEmail()); current.setPhone(d.getPhone()); current.setSecondaryPhone(d.getSecondaryPhone()); shadows.save(current); UserService When adding a lot of elements using saveAll is much faster than save
  • 20. if (c == null || c == 0) { List<ShadowUser> shadowList = new ArrayList<>(); for (ShadowUserDAO d : contacts) { shadowList.add(new ShadowUser(d, u)); updatePeopleYouMayKnow(d, u); } shadows.saveAll(shadowList); } else { for (ShadowUserDAO d : contacts) { List<ShadowUser> results = shadows.findByFullName(auth, d. getFullName()); if (!results.isEmpty()) { shadows.save(new ShadowUser(d, u)); } else { ShadowUser current = results.get(0); current.setEmail(d.getEmail()); current.setPhone(d.getPhone()); current.setSecondaryPhone(d.getSecondaryPhone()); shadows.save(current); updatePeopleYouMayKnow(d, u); } } } } private void updatePeopleYouMayKnow(ShadowUserDAO d, User u) { UserService For simplicity I chose to merge based on full name. In retrospect it might have been wiser to use the device unique ID for every contact but that might breed duplicates too. I oversimplified a very complex process of handling shadow users. If you take the time to build something like this then make sure to analyze the data more thoroughly and create a more robust social graph.
  • 21. current.setEmail(d.getEmail()); current.setPhone(d.getPhone()); current.setSecondaryPhone(d.getSecondaryPhone()); shadows.save(current); updatePeopleYouMayKnow(d, u); } } } } private void updatePeopleYouMayKnow(ShadowUserDAO d, User u) { User friend = findHim(d); if (friend != null) { if (!u.getFriends().contains(friend) && !u.getPeopleYouMayKnow().contains(friend)) { u.getPeopleYouMayKnow().add(friend); users.save(u); } } } private User findHim(ShadowUserDAO d) { if (d.getEmail() != null) { List<User> l = users.findByEmailIgnoreCase(d.getEmail()); if (l != null && !l.isEmpty()) { return l.get(0); UserService Notice that we still need to declare the updatePeopleYouMayKnow method we mentioned before
  • 22. current.setEmail(d.getEmail()); current.setPhone(d.getPhone()); current.setSecondaryPhone(d.getSecondaryPhone()); shadows.save(current); updatePeopleYouMayKnow(d, u); } } } } private void updatePeopleYouMayKnow(ShadowUserDAO d, User u) { User friend = findHim(d); if (friend != null) { if (!u.getFriends().contains(friend) && !u.getPeopleYouMayKnow().contains(friend)) { u.getPeopleYouMayKnow().add(friend); users.save(u); } } } private User findHim(ShadowUserDAO d) { if (d.getEmail() != null) { List<User> l = users.findByEmailIgnoreCase(d.getEmail()); if (l != null && !l.isEmpty()) { return l.get(0); UserService We search for the shadow user in the table of users using the findHim method which we'll cover soon
  • 23. current.setEmail(d.getEmail()); current.setPhone(d.getPhone()); current.setSecondaryPhone(d.getSecondaryPhone()); shadows.save(current); updatePeopleYouMayKnow(d, u); } } } } private void updatePeopleYouMayKnow(ShadowUserDAO d, User u) { User friend = findHim(d); if (friend != null) { if (!u.getFriends().contains(friend) && !u.getPeopleYouMayKnow().contains(friend)) { u.getPeopleYouMayKnow().add(friend); users.save(u); } } } private User findHim(ShadowUserDAO d) { if (d.getEmail() != null) { List<User> l = users.findByEmailIgnoreCase(d.getEmail()); if (l != null && !l.isEmpty()) { return l.get(0); UserService If a friend was found & isn't already a friend or in the "People You May Know" list...
  • 24. current.setEmail(d.getEmail()); current.setPhone(d.getPhone()); current.setSecondaryPhone(d.getSecondaryPhone()); shadows.save(current); updatePeopleYouMayKnow(d, u); } } } } private void updatePeopleYouMayKnow(ShadowUserDAO d, User u) { User friend = findHim(d); if (friend != null) { if (!u.getFriends().contains(friend) && !u.getPeopleYouMayKnow().contains(friend)) { u.getPeopleYouMayKnow().add(friend); users.save(u); } } } private User findHim(ShadowUserDAO d) { if (d.getEmail() != null) { List<User> l = users.findByEmailIgnoreCase(d.getEmail()); if (l != null && !l.isEmpty()) { return l.get(0); UserService Then we can add that user to the people you may know
  • 25. } } } private User findHim(ShadowUserDAO d) { if (d.getEmail() != null) { List<User> l = users.findByEmailIgnoreCase(d.getEmail()); if (l != null && !l.isEmpty()) { return l.get(0); } } if (d.getPhone() != null) { List<User> l = users.findByPhone(d.getPhone()); if (l != null && !l.isEmpty()) { return l.get(0); } } if (d.getSecondaryPhone() != null) { List<User> l = users.findByPhone(d.getSecondaryPhone()); if (l != null && !l.isEmpty()) { return l.get(0); } } return null; } } UserService The findHim method is simple boilerplate that searches based on all the meta data in the shadow user. We use findByEmail/phone etc. to find the shadow user in our regular user database. With that we finished the UserService class which is the largest service class!