Meteor Tutorial: Build chat Web Applications with Meteor

2016-10-17 11:46:53

let’s spent a little time to explain the assessment.first,this is my homework about meteor on coursera.I have to complete three task below

You should download and run the starter application, then test it out by logging in as different users in two different web browsers at the same time, seeing if the users if the users can talk to each other. It creates a set of test user accounts automatically, so you can log in as user1@test.comuser8@test.com with the password test123.

Task 1: Improve the look and feel

Adapt the templates and helper functions so that the messaging window displays users’ avatars next to their messages. Feel free to add other enhancements!

Task 2: Implement data writing security

Remove the insecure package from the application and implement a Meteor method to allow the insertion of chat items in the Chats collection. Test that you cannot insert items directly any more.

Task 3: Implement data reading security

Remove the autopublish package from the application and implement publish and subscribe for Chats. Users should only be able to retrieve chats that have their user id in either the user1Id field or the user2Id field. Test by logging in as different users and checking what you can see

Challenge: Implement emoticons

Can you implement emoticon functionality which allows the user to insert graphical emoticons into their message? Emoticons are small icons such as smiley faces which are typical of this kind of application.

this is html file: minstant.html

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
<head>
<title>minstant</title>
</head>

<body>
</body>

<!-- this is the main template used by iron:router to build the page -->
<template name="ApplicationLayout">
{{> yield "header"}}

<div class="container">
{{> yield "main"}}
</div>
</template>

<!-- top level template for the nav bar -->
<template name="navbar">
<nav class="navbar navbar-default">
<div class="container-fluid">
<div class="navbar-header">
<a class="navbar-brand" href="/">
Minstant!
</a>
</div>
<div class="nav navbar-nav">
{{> loginButtons}}
</div>
</div>
</nav>
</template>

<!-- Top level template for the lobby page -->
<template name="lobby_page">
{{> available_user_list}}
</template>

<!-- display a list of users -->
<template name="available_user_list">
<h2>Choose someone to chat with:</h2>
<div class="row">
{{#each users}}
{{> available_user}}
{{/each}}
</div>
</template>

<!-- display an individual user -->
<template name="available_user">
<div class="col-md-2">
<div class="user_avatar">
{{#if isMyUser _id}}
<div class="bg-success">{{getUsername _id}} (YOU)
<br/>
<img src="/{{profile.avatar}}" class="avatar_img">
</div>
{{else}}
<a href="/chat/{{_id}}">
{{getUsername _id}}
<br/>
<img src="/{{profile.avatar}}" class="avatar_img">
</a>
{{/if}}
</div>
</div>
</template>

<!-- display an individual user avatar -->



<!-- Top level template for the chat page -->
<template name="chat_page">
<h2>Type in the box below to send a message!</h2>
<div class="row">
<div class="col-md-12">
<div class="well well-lg">
{{#each messages}}

{{> chat_message}}
{{/each}}
</div>
</div>
</div>
<div class="row">
<div class="col-md-12">
<form class="js-send-chat">
<input class="input" type="text" name="chat" placeholder="type a message here...">
<button class="btn btn-default">send</button>
</form>
</div>
</div>
</template>

<!-- simple template that displays a message -->
<template name="chat_message">
{{#if currentUser}}
<img src="/{{avatar}}" class="avatar_img">{{Username}} said: {{text}}
{{else}}
someone said {{text}}
{{/if}}

<br>
</template>

this is css file: minstant.css

1
2
3
4
5
6
7
8
9
10
/* CSS declarations go here */

.user_avatar{
min-height:100px;
text-align: center;

}
.avatar_img{
height:75px;
}

this is js file: minstant.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
Chats = new Mongo.Collection("chats");

if (Meteor.isClient) {
// set up the main template the the router will use to build pages
Router.configure({
layoutTemplate: 'ApplicationLayout'
});
// specify the top level route, the page users see when they arrive at the site
Router.route('/', function () {
console.log("rendering root /");
this.render("navbar", {to:"header"});
this.render("lobby_page", {to:"main"});
});

// specify a route that allows the current user to chat to another users
Router.route('/chat/:_id', function () {
// the user they want to chat to has id equal to
// the id sent in after /chat/...
var otherUserId = this.params._id;
// find a chat that has two users that match current user id
// and the requested user id
var filter = {$or:[
{user1Id:Meteor.userId(), user2Id:otherUserId},
{user2Id:Meteor.userId(), user1Id:otherUserId}
]};
var chat = Chats.findOne(filter);
if (!chat){// no chat matching the filter - need to insert a new one
//chatId = Chats.insert({user1Id:Meteor.userId(), user2Id:otherUserId});
chatId = Meteor.call("createChat", Meteor.userId(), otherUserId, function (error) {
if (error && error.error === "logged-out") {
// show a nice error message
alert("Please, log in or create an account.");
}
});
}
else {// there is a chat going already - use that.
chatId = chat._id;
}
if (chatId){// looking good, save the id to the session
Session.set("chatId",chatId);
}
this.render("navbar", {to:"header"});
this.render("chat_page", {to:"main"});
});


Meteor.subscribe("users");
Meteor.subscribe("chats");

///
// helper functions
///
Template.available_user_list.helpers({
users:function(){
return Meteor.users.find();
}
})
Template.available_user.helpers({
getUsername:function(userId){
user = Meteor.users.findOne({_id:userId});
return user.profile.username;
},
isMyUser:function(userId){
if (userId == Meteor.userId()){
return true;
}
else {
return false;
}
}
})

Template.chat_page.helpers({
messages:function(){
var chat = Chats.findOne({_id:Session.get("chatId")});
return chat.messages;
},
other_user:function(){
return ""
},

})

Template.chat_page.events({
// this event fires when the user sends a message on the chat page
'submit .js-send-chat':function(event){
// stop the form from triggering a page reload
event.preventDefault();
// see if we can find a chat object in the database
// to which we'll add the message
var chat = Chats.findOne({_id:Session.get("chatId")});
if (chat){// ok - we have a chat to use
var msgs = chat.messages; // pull the messages property
if (!msgs){// no messages yet, create a new array
msgs = [];
}
// is a good idea to insert data straight from the form
// (i.e. the user) into the database?? certainly not.
// push adds the message to the end of the array
msgs.push({text: event.target.chat.value,avatar: Meteor.user().profile.avatar, Username: Meteor.user().profile.username});
// reset the form
event.target.chat.value = "";
// put the messages array onto the chat object
chat.messages = msgs;
// update the chat object in the database.
//Chats.update(chat._id, chat);
Meteor.call("newMessages", chat._id, chat);
}
}
})
}


// start up script that creates some users for testing
// users have the username 'user1@test.com' .. 'user8@test.com'
// and the password test123

if (Meteor.isServer) {
Meteor.startup(function () {
if (!Meteor.users.findOne()){
for (var i=1;i<9;i++){
var email = "user"+i+"@test.com";
var username = "user"+i;
var avatar = "ava"+i+".png"
console.log("creating a user with password 'test123' and username/ email: "+email);
Meteor.users.insert({profile:{username:username, avatar:avatar}, emails:[{address:email}],services:{ password:{"bcrypt" : "$2a$10$I3erQ084OiyILTv8ybtQ4ON6wusgPbMZ6.P33zzSDei.BbDL.Q4EO"}}});
}
}
});

Meteor.publish("chats",function(){
return Chats.find({$or:[
{user1Id:this.userId},
{user2Id:this.userId}
]});
});

Meteor.publish("users",function(){
return Meteor.users.find();
});

Meteor.methods({

createChat: function (user1, user2) {
//Check user logged. If no userID throw a Meteor error
if (!this.userId){
throw new Meteor.Error("logged-out", "The user must be logged in to post a comment.");
}

// start - createChat
if (Meteor.users.find({_id: user1}) && Meteor.users.find({_id: user2})) {
Chats.insert({user1Id:user1, user2Id:user2}, function(err, result){
if (err) {return err;}
else {
return result;}
});
}
},
//end - createChat

newMessages: function (chatId, messages) {
Chats.update(chatId, messages);
}
})
}