Subversion-Projekte lars-tiefland.prado

Revision

Details | Letzte Änderung | Log anzeigen | RSS feed

Revision Autor Zeilennr. Zeile
1 lars 1
<com:TContent ID="Main">
2
 
3
<h1>Creating <tt>NewUser</tt> Page</h1>
4
 
5
<p>
6
The <tt>NewUser</tt> page is provided to the administrator user to create new a new user account. It needs to display a form that collects the information about the new user account. According to our <a href="?page=Day2.CreateDB">database definition</a>, we will need to collect the following information:
7
</p>
8
 
9
<ul>
10
<li><tt>username</tt> - string, required and unique</li>
11
<li><tt>email</tt> - string, required and unique</li>
12
<li><tt>password</tt> - string, required</li>
13
<li><tt>role</tt> - integer, required (either 0 or 1)</li>
14
<li><tt>first_name</tt> - string, optional</li>
15
<li><tt>last_name</tt> - string, optional</li>
16
</ul>
17
 
18
<p>
19
We create two files <tt>protected/pages/users/NewUser.page</tt> and <tt>protected/pages/users/NewUser.php</tt> to save the page template and page class, respectively.
20
</p>
21
 
22
<h2>Creating Page Template</h2>
23
<p>
24
Based on the above analysis, we write the page template as follows:
25
</p>
26
 
27
<com:TTextHighlighter CssClass="source" Language="prado">
28
&lt;%@ Title="My Blog - New User" %>
29
 
30
&lt;com:TContent ID="Main">
31
 
32
<h1>Create New User</h1>
33
 
34
<span>Username:</span>
35
&lt;com:TRequiredFieldValidator
36
    ControlToValidate="Username"
37
    ErrorMessage="Please provide a username."
38
    Display="Dynamic" />
39
&lt;com:TCustomValidator
40
    ControlToValidate="Username"
41
    ErrorMessage="Sorry, your username is taken by someone else. Please choose another username."
42
    OnServerValidate="checkUsername"
43
    Display="Dynamic" />
44
<br/>
45
&lt;com:TTextBox ID="Username" />
46
 
47
<br/>
48
<span>Password:</span>
49
&lt;com:TRequiredFieldValidator
50
    ControlToValidate="Password"
51
    ErrorMessage="Please provide a password."
52
    Display="Dynamic" />
53
<br/>
54
&lt;com:TTextBox ID="Password" TextMode="Password" />
55
 
56
<br/>
57
<span>Re-type Password:</span>
58
&lt;com:TCompareValidator
59
    ControlToValidate="Password"
60
    ControlToCompare="Password2"
61
    ErrorMessage="Your password entries did not match."
62
    Display="Dynamic" />
63
<br/>
64
&lt;com:TTextBox ID="Password2" TextMode="Password" />
65
 
66
<br/>
67
<span>Email Address:</span>
68
&lt;com:TRequiredFieldValidator
69
    ControlToValidate="Email"
70
    ErrorMessage="Please provide your email address."
71
    Display="Dynamic" />
72
&lt;com:TEmailAddressValidator
73
    ControlToValidate="Email"
74
    ErrorMessage="You entered an invalid email address."
75
    Display="Dynamic" />
76
<br/>
77
&lt;com:TTextBox ID="Email" />
78
 
79
<br/>
80
<span>Role:</span>
81
<br/>
82
&lt;com:TDropDownList ID="Role">
83
    &lt;com:TListItem Text="Normal User" Value="0" />
84
    &lt;com:TListItem Text="Administrator" Value="1" />
85
&lt;/com:TDropDownList>
86
 
87
<br/>
88
<span>First Name:</span>
89
<br/>
90
&lt;com:TTextBox ID="FirstName" />
91
 
92
<br/>
93
<span>Last Name:</span>
94
<br/>
95
&lt;com:TTextBox ID="LastName" />
96
 
97
<br/>
98
&lt;com:TButton Text="Create" OnClick="createButtonClicked" />
99
 
100
&lt;/com:TContent>
101
</com:TTextHighlighter>
102
 
103
<p>
104
The template is not much different from the <tt>Contact</tt> template and the <tt>LoginUser</tt> page. It mainly consists of text boxes and validators. Some text boxes, such as username, are associated with two validators because of the multiple validation rules involved.
105
</p>
106
 
107
 
108
<h2>Creating Page Class</h2>
109
 
110
<p>
111
From the above page template, we see that we need to write a page class that implements the two event handlers: <tt>checkUsername()</tt> (attached to the first custom validator's <tt>OnServerValidate</tt> event) and <tt>createButtonClicked()</tt> (attached to the "create" button's <tt>OnClick</tt> event). Therefore, we write the page class as follows:
112
</p>
113
 
114
<com:TTextHighlighter CssClass="source" Language="php">
115
class NewUser extends TPage
116
{
117
    /**
118
     * Checks whether the username exists in the database.
119
     * This method responds to the OnServerValidate event of username's custom validator.
120
     * @param mixed event sender
121
     * @param mixed event parameter
122
     */
123
    public function checkUsername($sender,$param)
124
    {
125
        // valid if the username is not found in the database
126
        $param->IsValid=UserRecord::finder()->findByPk($this->Username->Text)===null;
127
    }
128
 
129
    /**
130
     * Creates a new user account if all inputs are valid.
131
     * This method responds to the OnClick event of the "create" button.
132
     * @param mixed event sender
133
     * @param mixed event parameter
134
     */
135
    public function createButtonClicked($sender,$param)
136
    {
137
        if($this->IsValid)  // when all validations succeed
138
        {
139
            // populates a UserRecord object with user inputs
140
            $userRecord=new UserRecord;
141
            $userRecord->username=$this->Username->Text;
142
            $userRecord->password=$this->Password->Text;
143
            $userRecord->email=$this->Email->Text;
144
            $userRecord->role=(int)$this->Role->SelectedValue;
145
            $userRecord->first_name=$this->FirstName->Text;
146
            $userRecord->last_name=$this->LastName->Text;
147
 
148
            // saves to the database via Active Record mechanism
149
            $userRecord->save();
150
 
151
            // redirects the browser to the homepage
152
			$this->Response->redirect($this->Service->DefaultPageUrl);
153
        }
154
    }
155
}
156
</com:TTextHighlighter>
157
 
158
<p>
159
In the above, calling <tt>save()</tt> will insert a new row in the <tt>users</tt> table. This intuitive feature is enabled by <a href="http://www.pradosoft.com/demos/quickstart/?page=Database.ActiveRecord">Active Record</a>.
160
</p>
161
 
162
<com:NoteBox>
163
For simplicity, usernames in our blog system are case-sensitive! In many practical systems, usernames may be required to be case-sensitive. So special handling needs to be made when creating a new user account as well as <a href="?page=Day3.Auth">performing authentication</a>. Also, the surrounding blanks in a username may need to be trimmed when creating a new account with it.
164
</com:NoteBox>
165
 
166
 
167
<h2>Testing</h2>
168
<p>
169
To test the <tt>NewUser</tt> page, visit the URL <tt>http://hostname/blog/index.php?page=users.NewUser</tt>. We shall see the following page output. Try enter different information into the form and see how the inputs are being validated. If all validation rules are satisfied, we shall expect the user account being created and the browser being redirected to the homepage.
170
</p>
171
 
172
<img src="<%~ output2.gif %>" class="output"/>
173
 
174
 
175
<h2>Adding Permission Check</h2>
176
<p>
177
During testing, you may have asked: shouldn't the <tt>NewUser</tt> page be only accessible by the administrator user? Yes, this is called <a href="http://www.pradosoft.com/demos/quickstart/?page=Advanced.Auth">authorization</a>. We now describe how we add this permission check to the <tt>NewUser</tt> page.
178
</p>
179
 
180
<p>
181
A straightforward way of performing permission check is in the page class where we check whether <tt>$this->User->IsAdmin</tt> is true, and if not we redirect the browser to the <tt>LoginUser</tt> page.
182
</p>
183
 
184
<p>
185
PRADO offers a more systematic way of checking page access permissions. To do so, we need to use <a href="http://www.pradosoft.com/demos/quickstart/?page=Configurations.PageConfig">page configuration</a>. Create a file <tt>protected/pages/users/config.xml</tt> with the content as follows:
186
</p>
187
 
188
<com:TTextHighlighter CssClass="source" Language="xml">
189
<?xml version="1.0" encoding="utf-8"?>
190
<configuration>
191
  <authorization>
192
    <allow roles="admin"/>
193
    <deny users="*"/>
194
  </authorization>
195
</configuration>
196
</com:TTextHighlighter>
197
 
198
<p>
199
The page configuration contains authorization rules that apply to the pages under the directory <tt>protected/pages/users</tt>. The above configuration reads that users in the role <tt>admin</tt> can access all pages (see <a href="?page=Day3.Auth">BlogUser.createUser()</a> for why the word "admin"). For now all other users (<tt>users="*"</tt>) are denied acess to pages in this directory - except for the <tt>LoginUser</tt> page which by convention can always be accessed.
200
</p>
201
 
202
<p>
203
Now if we visit the <tt>NewUser</tt> page as a guest, we will be redirected to the <tt>LoginUser</tt> page first. If our login as <tt>admin</tt> is successful, we will be redirected back to the <tt>NewUser</tt> page.
204
</p>
205
 
206
<com:TipBox>
207
Page configuration can contain more than authorization rules. For example, it can include <a href="http://www.pradosoft.com/demos/quickstart/?page=Fundamentals.Modules">modules</a> like we did in the <a href="?page=Day2.ConnectDB">application configuration</a>. For a PRADO application, each page directory can have a page configuration which applies to the pages in the same directory and all its subdirectories.
208
</com:TipBox>
209
 
210
</com:TContent>