-
Notifications
You must be signed in to change notification settings - Fork 6
/
Copy path06-adding-users.md.erb
165 lines (124 loc) · 15.2 KB
/
06-adding-users.md.erb
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
---
title: เพิ่มบัญชีผู้ใช้
slug: adding-users
date: 0006/01/01
number: 6
contents: รู้วิธีการเพิ่มผู้ใช้งานใน Meteor|ใส่การตรวจสอบที่จำเป็นให้ Microscope|ใช้แพ็คเกจ account-ui สร้างส่วนติดต่อผู้ใช้
paragraphs: 27
---
ที่ผ่านมาเราได้สร้างแอพต้นแบบ โดยนำข้อมูลโพสต์ตัวอย่างมาแสดงผลออกหน้าเว็บในแบบที่ใช้ได้ดีทีเดียว
และเรายังรู้ด้วยว่าหน้าจอจะปรับเปลี่ยนเนื้อหาเมื่อข้อมูลเปลี่ยนแปลงได้ยังไง ไม่ว่าจะแก้ไขหรือเพิ่มข้อมูลมันก็ตอบสนองได้ในทันที แต่ติดตรงที่ว่าแอพเรายังไม่สามารถป้อนข้อมูลเข้าไปได้ อันที่จริงยังไม่รองรับผู้ใช้งานด้วยซ้ำ
ถ้าอย่างนั้น ลองมาดูกันว่าจะแก้ไขเรื่องพวกนี้ได้ยังไง
### บัญชีผู้ใช้: ไม่ยากอย่างที่คิด
เฟรมเวิร์คบนเว็บส่วนมาก เมื่อเราต้องการเพิ่มบัญชีผู้ใช้งานเข้าไปมักเป็นเรื่องน่าเบื่อที่ต้องเจออยู่บ่อยๆ แน่นอนว่าเราต้องทำกับแทบทุกโปรเจกต์ แต่มัันไม่เคยง่ายอย่างที่ควรจะเป็นเลย ยิ่งกว่านั้นถ้าเราต้องยุ่งกับ OAuth หรือ ระบบตรวจสอบผู้ใช้แบบอื่นๆแล้วละก็ โค้ดที่เสร็จแล้วมักจะดูไม่ได้เลย
โชคดีที่ Meteor ช่วยเราได้ ด้วยวิธีจัดการแพคเกจที่ทำให้เราใช้โค้ดร่วมกันได้ทั้งบนเซิร์ฟเวอร์ (จาวาสคริปต์) และไคลเอนต์ (จาวาสคริปต์ HTML และ CSS) นั่นก็คือเราแทบจะได้ระบบบัญชีผู้ใช้มาฟรีๆ
เราอาจเลือกใช้แพ็คเกจบัญชีผู้ใช้ที่มาพร้อมกับ Meteor (ด้วยคำสั่ง `meteor add accounts-ui`) แต่เนื่องจากเราสร้างแอพด้วย Bootstrap เราก็ควรใช้แพ็คเกจ `ian:accounts-ui-bootstrap-3` แทน (ไม่ต้องกังวลไป ที่แตกต่างกันก็แค่สไตล์หน้าเว็บเท่านั้น) โดยให้ป้อนคำสั่งดังนี้ :
~~~bash
meteor add ian:accounts-ui-bootstrap-3
meteor add accounts-password
~~~
<%= caption "Terminal" %>
คำสั่งทั้งสองนี้จะสร้างเทมเพลทบัญชีผู้ใช้เพิ่มให้เรา โดยเราสามารถนำมาใส่ในแอพได้ด้วยตัวช่วย `{{> loginButtons}}` และถ้าคุณต้องการควบคุมตำแหน่งของปุ่มล็อกอินว่าจะให้แสดงที่ด้านไหนก็แค่เพิ่มคุณสมบัติ `align` เข้าไป (เช่น `{{> loginButtons align="right"}}`)
เราจะเพิ่มปุ่มนี้เข้าไปที่ส่วนหัวของหน้าแอพ และเนื่องจากส่วนหัวนี้เริ่มจะมีข้อมูลเยอะขึ้น เราก็จะสร้างเทมเพลทส่วนตัวให้มัน (วางไว้ที่ `client/templtes/includes/`) โดยใส่แท็กและคลาสเพิ่มเติมเข้าไปด้วย [ตามที่ Bootstrap แนะนำ](http://getbootstrap.com/components/#navbar) เพืิ่อให้ทั้งหมดดูดี :
~~~html
<template name="layout">
<div class="container">
{{> header}}
<div id="main">
{{> yield}}
</div>
</div>
</template>
~~~
<%= caption "client/templates/application/layout.html" %>
<%= highlight "3~6" %>
~~~html
<template name="header">
<nav class="navbar navbar-default" role="navigation">
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navigation">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="{{pathFor 'postsList'}}">Microscope</a>
</div>
<div class="collapse navbar-collapse" id="navigation">
<ul class="nav navbar-nav navbar-right">
{{> loginButtons}}
</ul>
</div>
</nav>
</template>
~~~
<%= caption "client/templates/includes/header.html" %>
ตอนนี้เมื่อเราเปิดไปที่หน้าแอพ เราจะเห็นปุ่มล็อกอินที่มุมขวาบนของหน้าจอ
<%= screenshot "6-1", "Meteor's built-in accounts UI" %>
เราสามารถใช้ปุ่มนี้ สร้างบัญชีผู้ใช้ ล็อกอิน ขอแก้รหัสผ่าน และอื่นๆ ที่แอพง่ายๆจำเป็นต้องมีเพื่อจัดการบัญชีผู้ใช้ได้
และเพื่อบอกให้ระบบบัญชีผู้ใช้รู้ว่าเราต้องการให้ผู้ใช้งานล็อกอินด้วยชื่อ เราก็แค่เพิ่มบล็อก `Accounts.ui` ในไฟล์ `config.js` ที่สร้างขึ้นใหม่ใน `client/helpers/` ดังนี้ :
~~~js
Accounts.ui.config({
passwordSignupFields: 'USERNAME_ONLY'
});
~~~
<%= caption "client/helpers/config.js" %>
<%= commit "6-1", "Added accounts and added template to the header" %>
### สร้างผู้ใช้คนแรก
เริ่มสร้างบัญชีผู้ใช้ใหม่กันได้เลย เมื่อทำเรียบร้อยปุ่ม "Sign in" ก็จะเปลี่ยนไปเป็นชื่อผู้ใช้งานของคุณ เพื่อยืนยันว่าบัญชีผู้ใช้ของคุณได้ถูกสร้างขึ้นแล้ว แต่ทว่าข้อมูลบัญชีนี้ถูกเก็บไว้ที่ไหนกันล่ะ
ตอนที่เราเพิ่มแพ็คเกจ `account` เข้าไปนั้น Meteor ก็สร้างคอลเลคชั่นใหม่ขึ้นมาหนึ่งตัว โดยสามารถเรียกใช้ได้จาก `Meteor.users` ซึ่งถ้าเราเปิดคอนโซลของเบราว์เซอร์และพิมพ์คำสั่งต่อไปนี้ :
~~~js
❯ Meteor.users.findOne();
~~~
<%= caption "Browser console" %>
คอนโซลก็จะแสดงอ็อบเจกต์ของผู้ใช้ที่คุณสร้างไว้ และถ้าดูตรงข้อมูลก็จะเห็นชื่อผู้ใช้งานของคุณ รวมทั้ง `_id` ที่มีค่าเฉพาะใช้อ้างถึงคุณได้ นอกจากนี้คุณยังสามารถใช้คำสั่ง `Meteor.user()` เพื่อเรียกข้อมูลผู้ใช้งานปัจจุบันที่ล็อกอินอยู่ได้ด้วย
ตอนนี้ให้คุณล็อกเอาท์ และลองสร้างบัญชีผู้ใช้ใหม่อีกรอบด้วยชื่ออื่น ซึ่งถ้าตอนนี้เราใช้คำสั่ง `Meteor.user()` ก็น่าจะได้ข้อมูลผู้ใช้คนที่สองนี้ออกมา แต่ช้าก่อน ลองรันคำสั่งนี้ดู :
~~~js
❯ Meteor.users.find().count();
1
~~~
<%= caption "Browser console" %>
คอนโซลคืนค่ามาเป็น 1 แต่เดี๋ยวก่อน มันควรจะเป็น 2 นี่ หรือว่ามีใครแอบลบบัญชีแรกออกไปแล้ว ถ้าคุณลองล็อกอินด้วยชื่อบัญชีแรกก็จะเห็นว่ามันยังคงใช้ได้อยู่
เพื่อให้แน่ใจเราลองมาเช็คจากที่เก็บข้อมูลเลยดีกว่า ก็ที่ฐานข้อมูล Mongo ไง โดยเราจะล็อกอินไปที่ Mongo (ด้วยคำสั่ง `meteor mongo` ในเทอร์มินอล) แล้วเช็คดูดังนี้ :
~~~bash
> db.users.count()
2
~~~
<%= caption "Mongo console" %>
มันมีข้อมูลผู้ใช้อยู่ 2 คนจริงๆ แต่ว่าทำไมเราถึงเห็นแค่คนเดียวจากในเบราว์เซอร์ล่ะ
### ความพิศวงของการส่งข้อมูล !
ถ้าคุณคิดย้อนกลับไปถึงบทที่ 4 คุณอาจจำได้ว่าการปิด `autopublish` ก็คือการที่เราห้ามไม่ให้คอลเลคชั่นที่เซิร์ฟเวอร์ส่งข้อมูลทั้งหมดมาให้คอลเลคชั่นในไคลเอนต์ที่เชื่อมต่อกันอยู่โดยอัตโนมัติ ดังนั้นเราถึงต้องสร้างช่องทางการส่งและบอกรับข้อมูลขึ้นมาเอง
แต่เราก็ยังไม่เคยกำหนดให้มีการส่งข้อมูลบัญชีผู้ใช้ด้วยซ้ำ แล้วเราเห็นข้อมูลพวกนี้ได้ยังไงกัน
คำตอบก็คือ แพ็คเกจจัดการบัญชีผู้ใช้ ทำการส่งข้อมูลรายละเอียดผู้ใช้งานปัจจุบันมาให้เองโดยอัตโนมัติ (auto-publish) เพราะถ้าไม่ทำอย่างนั้น ผู้ใช้คงไม่มีทางล็อกอินเข้าแอพได้เลย !
แต่แพ็คเกจจัดการบัญชีผู้ใช้จะส่งเฉพาะค่าของ *ผู้ใช้ปัจจุบัน* มาให้เท่านั้น ทำให้อธิบายได้ว่าทำไมผู้ใช้งานปัจจุบันถึงไม่เห็นข้อมูลของผู้ใช้คนอื่น
นั่นก็คือจะมีการส่งข้อมูลเฉพาะของผู้ใช้งานปัจจุบันที่ล็อกอินเข้ามาแล้วเท่านั้น และไม่ส่งอะไรมาเลยถ้าคุณไม่ได้ล็อกอิน
มากไปกว่านั้น คอลเลคชั่นของข้อมูลผู้ใช้บนเซิร์ฟเวอร์ก็ไม่เหมือนกับที่ไคลเอนต์ด้วย โดย Mongo จะเก็บข้อมูลผู้ใช้ไว้หลายอย่าง ซึ่งเราดูได้จากคำสั่งนี้ในคอนโซล Mongo :
~~~bash
> db.users.find()
{
"_id": "H5kKyxtbkLhmPgtqs",
"createdAt": ISODate("2015-02-10T08:26:48.196Z"),
"profile": {},
"services": {
"password": {
"bcrypt": "$2a$10$yGPywo3/53IHsdffdwe766roZviT03YBGltJ0UG"
},
"resume": {
"loginTokens": [{
"when": ISODate("2015-02-10T08:26:48.203Z"),
"hashedToken": "npxGH7Rmkuxcv098wzz+qR0/jHl0EAGWr0D9ZpOw="
}]
}
},
"username": "sacha"
}
~~~
<%= caption "Mongo console" %>
ส่วนที่เบราว์เซอร์นั้น ข้อมูลผู้ใช้จะเหลือแค่นิดเดียว ดูได้จากคำสั่งที่คล้ายกันดังนี้ :
~~~js
❯ Meteor.users.findOne();
Object {_id: "kYdBd9hr3fWPGPcii", username: "tmeasday"}
~~~
<%= caption "Browser console" %>
ตัวอย่างนี้แสดงให้เราเห็นว่าคอลเลคชั่นที่ไคลเอนต์เป็นเพียง *ชุดข้อมูลย่อย* ของฐานข้อมูลจริงได้อย่างไร ผู้ใช้ที่ล็อกอินจะเห็นเพียงแค่ชุดข้อมูลที่เพียงพอต่อการใช้งานเท่านั้น (แค่ให้ล็อกอินได้) ซึ่งเราจะได้เรียนรู้รูปแบบการทำงานนี้ในโอกาสต่อไป
ทั้งหมดนี้ไม่ได้หมายความว่าคุณไม่สามารถใช้ข้อมูลอื่นจากบัญชีผู้ใช้ได้ ถ้าคุณดูที่ [หน้าเอกสารของ Meteor](http://docs.meteor.com/#meteor_users) ก็จะรู้วิธีการเลือกส่งข้อมูลอื่นๆที่ต้องการจากคอลเลคชั่น `Meteor.users` มาใช้งานได้