Appendix B
- Designing a database: Member table
Due to the importance
of a database in managing a membership-based community, starting with a careful design of
the information to be collected proves invaluable in the subsequent development steps.
- Establishing a New Member
Establishing a New Account
means implementing a New Account sign up process and recording the information necessary
to track that New Member.
- Managing logon and validation
In developing a
membership-based Web site, it is critical that you provide an efficient method to log a
user onto the site and to validate a user's membership status.
- Users maintaining their own account information
To
manage a membership-based site without incurring unreasonable administrative expenses, the
site must provide facilities that enable users to maintain their own account information.
Building a membership-based community immediately demands certain features and
functionality requirements that should be provided as part of the site. These features
almost always require a database and generally include a New Account sign up process,
logon/validation, and a series of account maintenance and administrative features.
You should begin the design process by assessing the membership database
required for collecting the necessary membership information and for tracking user
activity. The membership- related database tables will store user information for
customizing the user's experience at the site, for evaluating current status and
permissions, and for assessing appropriate billing. These critical features highlight the
importance of properly design. The design decisions will ensure that the required fields
of information are available and the performance requirements for the database are met.
Generally, membership means a database. Any other method of tracking
membership-related information is unreasonably costly and inefficient.
Once a well-designed data structure has been established, the following sections
detail the features necessary to manage the membership-based environment including the New
Account sign up process, logon/validation features, and users account maintenance.
Establishing a New Account sign up process provides a good starting point, as it often
highlights required features that may have been overlooked in the initial design process.
The logon and account validation code should have a focus on efficiency and security for
the site. The logon and validation components primarily focus on controlling which aspects
of the site users can reach, and they provide an important mechanism to ensure security
and fee collection features of the site are properly enforced.
As you turn your development activities toward managing account status and
history tracking, as well as account maintenance and administrative activities, your focus
turns toward automating the administrative activities involved in account upkeep and
reporting requirements.
The database design process for creating the Membership table provides a system
for defining various types of information to be used by the system. Minimally, the
information collected should include a unique ID to track the various members. In
practice, additional information will be collected in several categories:
- System Status information: unique ID, account status, date stamps, and
more
- Administrative information: billing-related information and other account
management information
- Profile-related information: information updated by the members themselves
In the Love@1st Site Introduction Service (Service), we undertook a
comprehensive design phase, involving the key constituencies involved in creating,
financing, and using the site to determine the necessary information to track about the
user community. The information includes system information, administrative information,
e-mail services related flags, Member Profile data, and a profile of the member's Ideal
Mate.
The table information illustrated as follows shows field information based on a
Microsoft Access table; this maintains consistency with the presentation of this book and
was the environment used during testing of the site. The production version of this site
is Microsoft SQL Server.
From the system level, we determined a series of fields of information we had to
collect to manage the member at the site. The specific fields of the Membership table,
which can be found on the book's Web site are listed in Table B.1:
Table B.1 The Database Structure of the Primary System Information of the
Membership Table
| Field Name |
Data Type |
Size |
Description |
| MemberID |
Number (Long) |
4 |
Core account number-hidden from user |
| SignOnID |
Number (Long) |
4 |
Session ID-temporary value for tracking |
| Download |
Number (Long) |
4 |
Flag for downloading information to accounting system |
| ReferredBy |
Text |
25 |
Information on accounts referred from partner Websites |
| InactivateReason |
Number (Long) |
4 |
Reason flag for inactive status |
| CompletedProcess |
Yes/No |
1 |
Flag to show successful completion of New Account sign up and billing process |
Some of fields utilized for system-related functionality are classified as
Administrative fields to illustrate that they can be updated by site administrators
through Active Server Pages. Together, System and Administrative fields form the set of
information used by the system to manage members. System information is updated only by
the core program itself and not by members or administrative users of the site.
Administrative information, like System information, provides key data for
tracking and managing the member, the key distinction being that Administrative
information can be edited by administrative users of the site. Allowing key
membership-related information to be administered by site users is a fundamental method
for distributing control and management tasks away from the code writer to the site users.
This creates the mechanism for avoiding continual upgrades to code. The key administrative
fields for the Membership table are listed in Table B.2.
The key value of editable information will be demonstrated in more depth in the
administrative Appendix, as you note the parameter-driven nature of core features ranging
from drop-down box options to billing structures.
Table B.2 The Database Structure of the Primary Administrative Information of
the Membership Table
| Field Name |
Data Type |
Size |
Description |
| AdmCreateDate |
Date/Time |
8 |
Initial account creation data |
| AdmModDate |
Date/Time |
8 |
Date account last modified |
| AdmStartDate |
Date/Time |
8 |
Date paid membership began |
| AdmExpDate |
Date/Time |
8 |
Date valid membership status expired |
| AdmOnlineDate |
Date/Time |
8 |
Date user last logged onto site |
| AdmPublic |
Yes/No |
1 |
Flag denoting searchable account |
| AdmStatus |
Number (Long) |
4 |
Status of member account, i.e. active, inactive |
| Admingraphics |
Yes/No |
1 |
Graphic images submitted for display by member, a prerequisite for active
account status |
The profile information displays information entered by the users themselves for
other members to view. The profile information enables the searching features of the site
and allows members to get to know each other while deciding whether or not to introduce
themselves. The specific information includes all the fields illustrated in Table B.3.
Table B.3 The Database Structure of Profile and General Demographic
Information of the Membership Table
| Field Name |
Data Type |
Size |
Description |
| Pass |
Text |
50 |
Password for secure access |
| FName |
Text |
30 |
First name |
| LName |
Text |
50 |
Last name |
| Address1 |
Text |
150 |
Address line one |
| Address2 |
Text |
150 |
Address line two |
| City |
Text |
50 |
City |
| StateID |
Text |
2 |
State |
| Zip |
Text |
20 |
Zip code |
| HMPhone |
Text |
30 |
Home phone number |
| HMAreaCode |
Text |
3 |
Home area code (for searching) |
| WKPhone |
Text |
30 |
Work phone number |
| WKAreaCode |
Text |
3 |
Work area code (for searching) |
| PublicPhone |
Number (Long) |
4 |
Flag denoting phone number can be released |
| Email |
Text |
50 |
E-mail address |
| PublicEmail |
Yes/No |
1 |
Flag denoting e-mail address can be released |
| Maiden |
Text |
50 |
Mother's maiden name for validation if password is lost |
| ProfSex |
Yes/No |
1 |
Male or female |
| ProfPrefID |
Yes/No |
1 |
Preferred sex (can not be altered) |
| ProfRaceID |
Number (Long) |
4 |
Ethnic/racial background |
| ProfRlgnID |
Number (Long) |
4 |
Religion |
| Profdob |
Date/Time |
8 |
Date of birth for custom birthday notes and user validation |
| ProfHeightF |
Number (Long) |
4 |
Member height (feet) |
| ProfHeightI |
Number (Long) |
4 |
Member height (inches) |
| ProfBodyID |
Number (Long) |
4 |
Member body type |
| ProfStatusID |
Text |
50 |
Marital status (Married is not an option) |
| ProfEdID |
Number (Long) |
4 |
Education level |
| ProfOcc |
Text |
150 |
Occupation description |
| ProfChldNum |
Number (Long) |
4 |
Number of children |
| ProfChldExist |
Number (Long) |
4 |
Flag whether or not member has children |
| ProfChldNew |
Number (Long) |
4 |
Interest in having children |
| ProfSmkgID |
Number (Long) |
4 |
Smoking status |
| ProfDrkgID |
Number (Long) |
4 |
Drinking status |
| ProfEyeID |
Text |
15 |
Member's eye color |
| ProfHairID |
Text |
15 |
Member's hair color |
| ProfAct |
Memo |
- |
Member general entry of activities they enjoy |
| ProfMovie |
Text |
100 |
Favorite movies |
| ProfMusic |
Text |
50 |
Multiple selection list for music IDs |
| ProfBook |
Text |
100 |
Last book read |
| ProfWhat |
Memo |
- |
What are you looking for in a relationship question |
| ProfQ1ID |
Number (Long) |
4 |
ID of second parameter-driven question |
| ProfQ1Info |
Memo |
- |
Answer to parameter-driven question |
This profile and demographic information is used to dynamically build profile
pages for display to users interested in learning more about a certain member that they
find in a search or who requests their introduction.
The Service provides extensive e-mail features for its membership community as a
method of communication between members. Members may generate e-mails to other members
through the system without the identity of either member being released. And based on
profiles and flag selections, the system may automatically generate an e-mail message to
notify a member of an introduction request or that someone matching her Ideal Mate profile
has joined the membership community. The flags in the Membership table that manage this
set of features are included in Table B.4.
Table B.4 The Database Structure of Automatic E-mail Services Flags in the
Membership Table
| Field Name |
Data Type |
Size |
Description |
| Eselect |
Yes/No |
1 |
Send me a message when another member selects me. |
| Eaccept |
Yes/No |
1 |
Send me a message when a member I have selected accepts my request. |
| EGenie |
Yes/No |
1 |
Send me a message if a member matching my Ideal Mate profile joins. |
| EGen |
Yes/No |
1 |
Send me general site announcements of events. |
| EOK |
Yes/No |
1 |
Allow members to send me notes after they have selected me. |
Microsoft SQL Server's "send mail stored" procedure drives these
e-mail services that are executed through database calls by Active Server Pages through
the ActiveX Data Object (ADO) component.
The Ideal Mate-related profile very closely mirrors the Member Profile
information and enables a member to customize the search utilities to the profile that she
will use most often when searching the system. In addition, the Ideal Mate profile
provides a mechanism that enables the system to attempt matching New Members with members
already in the system. This automated matching feature sends users e-mail notifications
that encourage them to return to the site and provides them with value-added services to
facilitate members finding members. The specific fields associated with managing these
features are illustrated in Table B.5.
Table B.5 The Database Structure of Ideal Mate Profile Information in the
Membership Table
| Field Name |
Data Type |
Size |
Description |
| idlRaceID |
Number (Long) |
4 |
Ideal Mate race |
| idlagehigh |
Number (Long) |
4 |
Ideal Mate age range (high) |
| idlagelow |
Number (Long) |
4 |
Ideal Mate age range (low) |
| idlRlgnID |
Number (Long) |
4 |
Ideal Mate religion |
| idlHeightFlag |
Number (Long) |
4 |
Ideal Mate height above or below flag |
| idlHeightF |
Number (Long) |
4 |
Ideal Mate height (feet) |
| idlHeightI |
Number (Long) |
4 |
Ideal Mate height (inches) |
| idlSmkgID |
Number (Long) |
4 |
Ideal Mate smoking status |
| idlDrkgID |
Number (Long) |
4 |
Ideal Mate drinking status |
| idllocflag |
Yes/No |
1 |
Ideal Mate location flag, i.e. is location relevant? |
| idllocarea1 |
Text |
3 |
Ideal Mate area code if relevant |
| idllocarea2 |
Text |
3 |
Ideal Mate area code, number two if relevant |
With the table design completed for the Membership table, developing a member
sign up process becomes the first step of site creation. This enables the testing users to
enter members and to work with the site almost immediately, leading to a clarification of
missing information that has to be added to the site.. The New Account sign up process
results in five separate Active Server Pages or .asp files. The initial development of the
pages focused entirely on functionality, with graphic design and general look enhancement
taking place at the very end of the development process.
The five-step New Account process walked the prospective member through the
entering of Ideal Mate, Profile, demographic information, billing selection, and payment
choices. Whereas the final two steps relating to billing are dealt with extensively in a
later chapter, at this point we will explore the creation of a New Account.
The initial page largely presents standard HTML, providing information within a
standard form that enables users to enter data and to select options. The only significant
use of Active Server Pages features includes the lookup of parameters to populate
drop-down lists and the server-side include of a validation .asp file, which will be
explored in more detail later in this chapter. This page, however, initiates the session
and collects the Ideal Mate information used to initially insert a New Member record in
step 2.
Listing B.1 illustrates the Server-Side Include feature and the defaulting of
drop-down values for ethnic background.
Listing B.1 NEWACCT1.ASP-First Page in the New Account Sign up Process
<!--#include file="validatenew.asp"-->
<%
Set Conn = Server.CreateObject("ADODB.Connection")
Conn.Open("firstsite")
' --------------------------------
' --------------------------------
' Output HTML Area
' --------------------------------
' --------------------------------
%>
...
<tr><td width=20%><font color="#0000A0">
Ethnic Background:</font></td><td width=50%>
<select name="idlraceid" size=1 >
<option checked value="0"><font color="#0000A0">No
Preference</font></option>
<%
Set RS = Conn.Execute("SELECT * FROM AdminParameters where (systypeparam =
1)[ic:ccc] order by colatingorder;")
Do While Not RS.EOF
%>
<option
value="<%=rs("sysparamid")%>"><%=rs("paramvalue")%></option>
<%
RS.MoveNext
Loop
RS.Close
%>
</select></td></tr>
...
The code illustrated in Listing B.1 includes an example of how a parameter table
can be used for populating options in the system. This parameter table can then be
maintained by site administrators through standard Active Server Pages.
During step 2 the initial account record is created with the add new method. In addition to the Server-Side Include
validation in step 1 and the parameter-driven populating of drop-down boxes illustrated in
step 1, step 2 checks logon status to ensure that the current user has not already
inserted the initial record; then step 2 either does an database insert or simply
redisplays the account ID, depending on the logonstatus
of the session ID. Listing B.2 illustrates the database insert and user validations done
in step 2.
Listing B.2 NEWACCT2.ASP-Inserting the Initial Record with Ideal Mate
Information from Step 1 and System/Administrative Defaults for the New Account
<!--#include file="validatenew.asp"-->
<%
Set Conn = Server.CreateObject("ADODB.Connection")
Conn.Open("firstsite")
Select Case session("logonstatus")
Case 3 ' Already Past this insert step
msg = "<blink>Please Record your New Member ID:</blink> [ic:ccc]"
& session("memberid") & " "
Case 2 ' Proper Status for Insert of New Account
set rsInsert = Server.CreateObject("ADO.RecordSet")
'Conn.BeginTrans
rsInsert.Open "Members", Conn, 3, 3
rsInsert.AddNew
rsInsert("SignOnID") = session.sessionid
rsInsert("AdmCreateDate") = Date()
rsInsert("AdmModDate") = Date()
rsInsert("AdmStartDate") = Date()
rsInsert("AdmOnlineDate") = Date()
rsInsert("AdmPublic") = 0
rsInsert("AdmStatus") = 0
rsInsert("publicphone") = 0
'Testing Uncertain Values
heightF = request.form("idlHeightF")
heightI = request.form("idlHeightI")
if heightF = "" then heightF = 0
if heighti = "" then heightI = 0
rsInsert("idlRaceID") =
request.form("idlRaceID")
rsInsert("idlAgeHigh") =
request.form("idlAgeHigh")
rsInsert("idlAgeLow") =
request.form("idlAgeLow")
rsInsert("idlRlgnID") =
request.form("idlRlgnID")
rsInsert("idlHeightFlag") =
request.form("idlHeightFlag")
rsInsert("idlHeightF") = heightf
rsInsert("idlHeightI") = heighti
rsInsert("idlSmkgID") =
request.form("idlSmkgID")
rsInsert("idlDrkgID") =
request.form("idlDrkgID")
rsInsert("idlLocFlag") =
request.form("idllocflag")
rsInsert("idlLocArea1") = request.form("idllocarea1")
rsInsert("idlLocArea2") = request.form("idllocarea2")
rsInsert("download") = 0
rsInsert("stateid") = "CA"
rsInsert.Update
'Conn.CommitTrans
rsInsert.Close
sql = "SELECT Members.SignOnID, Members.memberid, Members.AdmCreateDate
FROM Members WHERE[ic:ccc] (((Members.SignOnID)=" & session.sessionid &
") AND ((Members.AdmCreateDate)=Date()));"
Set RS = Conn.Execute(sql)
msg = "<blink>Please Record your New Member ID:</blink>
" & rs("memberid") & " "
' ---------------------------------------
' Set Session Object with memberid value
' ---------------------------------------
memval = rs("memberid")
session("memberid") = memval
session("logonstatus") = 3
rs.close
End Select
' --------------------------------
' --------------------------------
' Output HTML Area
' --------------------------------
' --------------------------------
%>
...
Step 3 provides an update SQL statement to
add additional profile information to the New Members record. To update the record, step 3
performs a series of data evaluations and manipulations to prepare the information for the
update statement. Conditional processing such as If/Then
statements and For/Next loops are used to evaluate
form-based information, and in addition to simple evaluations, a callable string function
is invoked for modifying various fields to strip out single and double quotation marks,
which can affect the SQL-based update statement.
The code in Listing B.3 illustrates several important features associated with
the update of an existing account. In addition to the update of the account record in the
database, Listing B.3 also illustrates callable functions and variable testing.
Listing B.3 NEWACCT3.ASP-The Use of a Callable Function, Variable Testing,
and Update SQL Statement
<!--#include file="validatenew.asp"-->
<script language=vbscript runat=server>
Function StripChars(txtstring)
tempstring = ""
length = Len(txtstring)
For i = 1 To length
singlechar = Mid(txtstring, i, 1)
If singlechar = Chr(34) then
tempstring = tempstring & Chr(180)
& Chr(180)
ElseIf singlechar = Chr(39) then
tempstring = tempstring & Chr(180)
Else
tempstring = tempstring & singlechar
End If
Next
StripChars = tempstring
End Function
</script>
<%
Set Conn = Server.CreateObject("ADODB.Connection")
Conn.Open("firstsite")
'Set Conn = Session("Conn")
' -------------------------------------------
' Update based on member id in session object
' -------------------------------------------
'Testing Uncertain Values
'--------------------------
OCC = request.form("profocc")
act = request.form("profact")
movie = request.form("profmovie")
music = request.form("profmusic")
book = request.form("profbook")
what = request.form("profwhat")
Q1Info = request.form("profQ1Info")
heightF = request.form("profHeightF")
heightI = request.form("profHeightI")
dob = request.form("profdob")
profhairid = request.form("profhairid")
profeyeid = request.form("profeyeid")
if occ = "" then occ = "NA"
if act = "" then act = "NA"
if movie = "" then movie = "NA"
if music = "" then music = 0
if book = "" then book = "NA"
if what = "" then what = "NA"
if Q1info = "" then Q1info = "NA"
if HeightF = "" then HeightF = 0
if Heighti = "" then HeightI = 0
if dob = "" then dob = "01/01/01"
'------------------------
if request.form("profsex") <> "" then
sql = "UPDATE Members SET"
sql = sql & " Members.ProfSex =" &
request.form("profsex") & ","
sql = sql & " Members.ProfPrefID =" &
request.form("ProfPrefID") & ","
sql = sql & " Members.ProfRaceID =" &
request.form("profRaceID") & ","
sql = sql & " Members.ProfRlgnID =" &
request.form("profRlgnID") & ","
sql = sql & " Members.Profdob =#" &
stripchars(dob) & "#,"
sql = sql & " Members.ProfHeightF =" &
stripchars(HeightF) & ","
sql = sql & " Members.ProfHeightI =" &
stripchars(HeightI) & ","
sql = sql & " Members.ProfBodyID =" &
request.form("profBodyID") & ","
sql = sql & " Members.ProfStatusID ='" &
request.form("profStatusID") & "',"
sql = sql & " Members.ProfEdID =" &
request.form("profEdID") & ","
sql = sql & " Members.ProfOcc ='" &
stripchars(occ) & "',"
sql = sql & " Members.ProfChldNum =" &
request.form("ProfChldNum") & ","
sql = sql & " Members.ProfChldExist =1,"
'& request.form("ProfChldExist") & ","
sql = sql & " Members.ProfChldNew =1," '&
request.form("ProfChldNew") & ","
sql = sql & " Members.ProfSmkgID =" &
request.form("ProfSmkgID") & ","
sql = sql & " Members.ProfDrkgID =" &
request.form("ProfDrkgID") & ","
sql = sql & " Members.ProfEyeID ='" &
ProfEyeID & "',"
sql = sql & " Members.ProfHairID ='" &
ProfHairID & "',"
sql = sql & " Members.ProfAct ='" &
stripchars(act) & "',"
sql = sql & " Members.ProfMovie ='" &
stripchars(movie) & "',"
sql = sql & " Members.ProfMusic ='" &
stripchars(music) & "',"
sql = sql & " Members.ProfBook ='" &
stripchars(book) & "',"
sql = sql & " Members.ProfWhat ='" &
stripchars(what) & "',"
sql = sql & " Members.ProfQ1ID =" &
request.form("ProfQ1ID") & ","
sql = sql & " Members.ProfQ1Info ='" &
stripchars(Q1Info) & "' "
sql = sql & " WHERE
(((Members.AdmCreateDate)=Date()) AND"
sql = sql & " ((Members.memberID)=" &
session("memberid") & "))"
Set rsupdate =
Server.CreateObject("ADO.Recordset")
rsupdate.Open sql, Conn, 3
end if
Set rsStates = Conn.Execute("SELECT StatePostalCode FROM States;")
' --------------------------------
' --------------------------------
sql = "SELECT * FROM Members WHERE MemberID=" &
session("MemberID") & ";"
Set rs = Conn.Execute(sql)
%>
The New Account Sign Up process involves the creation of a New Account record; a
prospective member's data is carefully entered into the database, tracked, and evaluated
for potential matches as the prospective member moves through a series of screens that
guides the entry of information. Some of the key Active Server features invoked include:
- Session ID for tracking state during the initial insert and retrieval of a member
record
- Request Object for gathering data entered in form fields
- VBScript for the conditional processing related to data validation and
manipulation
- ADO Component for the active use of a database to store information entered
Once a New Member Profile has been successfully created and activated by
whatever administrative process has been created, a logon process must be created to
validate a user's identity. In addition, with a membership paradigm, users who attempt to
open an .asp file without logging on must be trapped and routed to a logon screen for
validation. At first glance, this process seems to require the use of Windows NT Server's
User Manager. After a quick review, however, it becomes clear that managing the
authentication process through a database has many benefits over the user manager from
maintainability and efficiency perspectives. As a result, I leave the user manager for
highly sensitive security issues such as site administration and immediately rely on
database lookups for membership authentication.
The components of an effective Logon and Validation model include a logon
screen, which can set a session variable for tracking the logon status, and a validation
.asp file, which is included at the top of every page and which redirects users to the
logon screen if they do not pass a simple check of the logon session variable. These
components immediately provide much better security than most solutions found on the Web
today. One of the benefits of a session variable is that it only resides at the server.
Rather than writing a status with a cookie, which can be "spoofed", the logon
status relates to a given Session ID on the browser and, therefore, does not get directly
passed over the Internet.
Generally, on the Internet, spoofing refers to creating a transaction where the
one computer pretends to the have the address, or identity, of another computer. We use
this imagery because with a faked cookie, a computer could send a transaction to the Web
server that would lead it to mistakenly assume it was a different computer.
The logon process can be more or less complicated, depending on your method for
authenticating the member. The logon screens should also be candidates for two types of
security measures. First, the field in which a password or other type of information is
entered should be set as a password so that asterisks are displays in the browser in place
of the data entered by the user; second, this screen may also be used with an SSL socket
(i.e. HTTPS:// reference) to ensure the encryption of password information as it
passes over the network. These security decisions depend on the level of security required
at your site.
Secure Sockets Layer (SSL)
SSL provides the most widely used mechanism for securing Web-related
information in transit on the Internet. In summary, SSL provides an encryption standard
for Web browsers and Web Servers to securely share information.
The initial logon page simply requires a form field for the entry of whatever
validation information needs to be submitted.
In addition to the basic data entry fields, our Service displays a system
message that explains why the user ended up at this page. The appropriate message string
is set to a Session property and subsequently displayed if a failed logon attempt occurs
or if the user gets routed to the logon screen from a validation in some other .asp file.
In addition, if the Session property used for storing messages is left empty, then the
current session is abandoned to enable the user to log on again. Listing B.4 illustrates
the code used at the top of the .asp file to check the Session property containing the
message and either display the message, if the logon attempt failed, or abandon the
current Session and allow a new logon to occur.
Listing B.4 LOGON.ASP-Illustration of Message Display at the Top of the Logon
Page
<% msg = session("msg")
'--------------------------------------'
Output HTML Section
'--------------------------------------
%>
<html><head><title>
Love@1st Site - Interactive Introductions-Logon
</title></head><body bgcolor="#FFFFFF">
<%=msg%>
<%
If session("msg") = "" then
session.abandon
End If
session("msg") = ""
%>
Once the initial logon request is submitted, the Service begins a comprehensive
set of evaluation routines to identify whether or not the logon attempt authenticates the
user, and if not, to determine why the authentication attempt failed.
The logon.asp invokes the logoncheck.asp file, which directly outputs nothing. The
authentication file simply evaluates the logon attempt and either redirects a successful
logon to the start.asp page or sets a message to the
session (msg) variable and redirects the user back
to the logon.asp page. If a successful logon occurs,
the logoncheck.asp also writes an update back to the
Membership table to change to the current date/time, the date/time field used for tracking
the last time the user logged on to the Service.
The code illustrated in Listing B.5 shows the process for authenticating the
user on the Service. The code also handles the different failure conditions that can
result by carefully reviewing all possible failures followed by a comprehensive message
back to the user.
The logoncheck.asp cannot directly write HTML output because the redirect
feature does not function once HTTP headers have been sent (see format of HTTP record for
more details about what the headers include). Headers are sent as soon as a response.write event occurs.
Listing B.5 LOGONCHECK.ASP-Authentication Process for Logon
<Script Language=VBScript runat=server>
Function redirect()
Response.Redirect "logon.asp"
end function
</script>
<%
Set Conn = Server.CreateObject("ADO.Connection")
Conn.Open("firstsite")
'-----------------------------------------------------
'-----------------------------------------------------
'Level 1 Basic Validation Testing
'-----------------------------------------------------
'-----------------------------------------------------
'Test for Entry of Member ID prior to Running Search
'-----------------------------------------------------
if request.form("memberid")="" then ' No Member ID Entered
session("msg") = "<h3><center>Oops! The Member ID#
didn't work. Try the Member ID# search
below.</center></h3>"
Redirect 'Call Function to Exit Back to Logon Screen
'Run Search
'-----------------------------------------------------
else 'Run Database Lookup
sql = "SELECT members.admonlinedate, Members.MemberID, members.pass,
Members.FName, Members.LName, Members.AdmExpDate, Members.AdmStatus,
Members.InactivateReason, Members.AdminGraphics,
Members.AdmCreateDate FROM Members "
sql = sql & "WHERE (((Members.MemberID)=" &
request.form("memberid") & "));"
set rs = conn.execute(sql)
end if
'------------------------------------------
'------------------------------------------
'Level 2 Validation Testing
'------------------------------------------
'------------------------------------------
If not rs.eof then
test = rs("memberid")
session("memberid") = test
End If
'Member ID Entered Now Run Search for Record
'-------------------------------------------
If rs.eof Then 'No Record Found Bad ID
rs.close
session("msg") = "<h3><center>Oops! We couldn't find
Member ID# <em>" & request.form("memberid")
& "</em>. Please try again or use our Member ID# [ic:ccc]Search
below.</center></h3>"
Redirect 'Call Function to Exit Back to Logon Screen
'Customer Record Found Now Check Password
'-----------------------------------------
elseif not request.form("password") = rs("pass") then
rs.close
session("msg") = "<h3><center>Oops! Your ID# is
okay, but the password didn't work. (Remember it is
case sensitive) Try again.</center></h3>"
Redirect 'Call Function to Exit Back to Logon Screen
'Check for inactive status
'-------------------------------------------
elseif rs("admstatus") = 0 then
if rs("CompletedProcess") = 0 then
rs.close
session("msg") = "<h3><center>Not
Active or Expired Account</center></h3>"
Redirect 'Call Function to Exit Back to Logon Screen
end if
'Password OK now check to see if pictures arrived. They have 30 days.
'---------------------------------------------------------------------
elseif (rs("admingraphics") = 0) and (rs("admcreatedate") + 30 <
date()) then
session("msg") = "<center><font color=" &
"""" & "#FF0000" & """" &
">[ic:ccc]<strong>We have not received your photos yet. You are not
able to access Member Services until we receive your
photos.</strong></font></center>"
session("scanaction") = "lockout"
Response.Redirect "scan.asp"
'See if pictures arrived. After 15 days they get a warning message.
'---------------------------------------------------------------------
elseif (rs("admingraphics") = 0) and (rs("admcreatedate") + 15 <
date()) then
session("msg") = "<center><font color=" &
"""" & "#FF0000" & """" &
"><strong>[ic:ccc]We have not received your photos yet. If we do not
receive your photos prior to " & rs("admcreatedate") + 15
& ", we will remove your access to Member
Services.</strong></font></center>"
session("scanaction") = "warning"
Response.Redirect "scan.asp"
'-----------------------------------------------------
'-----------------------------------------------------
' Step 3. Success Logon Approved
'-----------------------------------------------------
'-----------------------------------------------------
else
session("logonstatus") = 1
session("AdmOnlineDate") = rs("AdmOnlineDate")
sql = "UPDATE Members SET"
sql = sql & " Members.AdmOnlineDate =
#" & Date() & "#"
sql = sql & " WHERE
Members.MemberID=" & request.form("memberid") & ";"
set rs2 = conn.execute(sql)
response.redirect "start.asp"
end if
rs.close
%>
Two discrete validation .asps are used in the Service. The first validate.asp file is used in every page with the exception of
the New Account pages, while the second validatenew.asp
is used on all New Account pages. Both validation pages rely on the Session property named
logonstatus.
The New Account validation pages uses the logon status Session property
extensively to monitor what point in the New Account process New Members have reached.
This file relies on the select case statement to evaluate all possible statuses of the
logon status Session property. Currently only Case 0 and 1 are in use. Listing B.6
illustrates the code of the Select Case statement used to
evaluate the Logon Status on New Account Pages
Listing B.6 VALIDATENEW.ASP-The Select Case Evaluation of the Logon Status
Variable for Users in the New Account Pages
<%
'Set ADO Object variable for use in remainder of page processing
Set Conn = Server.CreateObject("ADODB.Connection")
Conn.Open("firstsite")
Select Case session("logonstatus")
Case 0 'New Session No Status
session("logonstatus") = 2
Case 1
session("logonstatus") = 2
Case 2 'New Member in Sign Up Process first page
Case 3 'New Member in Sign Up Process Record Created
Case 4 'New Member in Sign Up Process Error Status
End Select
%>
The standard validate.asp file, which is
invoked with a Server-Side Include statement on all other pages, provides evaluations very
similar to the validatenew.asp file, with one minor
exception: It only takes action if a logon status is 0. Every other status qualifies
either as a New Member in process or as a properly logged on member account. The code for
this evaluation is illustrated in Listing B.7.
Listing B.7 VALIDATE.ASP-Validation File Included in All .asp Files
Other than the New Account Pages
<%
Set Conn = Server.CreateObject("ADODB.Connection")
Conn.Open("firstsite")
Select Case session("logonstatus")
Case 0 'New Session No Status
session("msg") = "<h3><center>
Your are currently not logged in or your [ic:ccc]login has timed out
</center></h3> Please logon to continue your session, sorry for
any inconvenience</h4>"
Response.Redirect "logon.asp"
Case 1 'Authenticated User Properly Logged On
Case 2 'New Member in Sign Up Process first page
Case 3 'New Member in Sign Up Process Record Created
End Select
%>
The Logon and Validation process requires a small amount of code and only a
couple of .asp files, but based on Server-Side Includes, these files find their way into
every single Active Server Page processed for delivery to the client. Although not complex
in implementation, this file provides the heart of membership security features and should
be carefully put into effect. Some of the key Active Server features invoked include:
- Custom Session Variable for tracking logon status
- Response.Redirect feature for re-routing
users from any page to the logon.asp
- VBScript for the conditional processing related to authentication.
- ADO Component for the active use of a database to look up account information
Implementing a cost-effective, fee-based subscription service requires
automating the costly administrative responsibilities that can develop due in part to
member account maintenance and site enhancement. As one effective step in controlling
these costs and at the same time empowering the user community with additional control and
convenience, a site should place as much maintenance responsibility as possible with the
end user community. The Introduction Service places extensive maintenance features in the
hands of the members. From Ideal Mate settings to billing information, the member has
control.
Enabling members to edit these pages simply involves taking the New Account pages and
adapting them for update. The primary change involves defaulting all values in the form
fields to be populated with a member's currently set information. In addition, these pages
will be updated out of order rather than linearly as with the New Account process. Without
going into repetitive detail with the editacctX.asp
files, in Listing B.8 I will illustrate just the editacct3.asp,
which contains Member Information. The key task involves looking up the customer record
and ensuring that the member ID of the currently logged on user matches the one used to
look up customer information so that no other user can accidentally edit another member's
account.
Listing B.8 EDITACCT3.ASP-Member Editing of Account Information Based on
Defaulted Form Field Values
<%
Set Conn = Server.CreateObject("ADODB.Connection")
Conn.Open("firstsite")
sql = "SELECT * FROM Members WHERE MemberID=" &
session("MemberID") & ";"
Set rs = Conn.Execute(sql)
Set rsStates = Conn.Execute("SELECT StatePostalCode FROM States;")
'Testing Uncertain Values
'--------------------------
OCC = request.form("profocc")
act = request.form("profact")
movie = request.form("profmovie")
book = request.form("profbook")
what = request.form("profwhat")
Q1Info = request.form("profQ1Info")
heightF = request.form("profHeightF")
heightI = request.form("profHeightI")
dob = request.form("profdob")
if occ = "" then occ = "NA"
if act = "" then act = "NA"
if movie = "" then movie = "NA"
if book = "" then book = "NA"
if what = "" then what = "NA"
if Q1info = "" then Q1info = "NA"
if HeightF = "" then HeightF = 0
if Heighti = "" then HeightI = 0
if dob = "" then dob = "01/01/01"
%>
<html>
<base href="http://www.1st-site.com/">
<head>
<title>Edit Membership Information</title>
</head>
<form action="editacctupdate.asp" target="_top"
method="POST">
<body bgcolor="#FFFFFF" text="#0000A0">
<table border=1 cellpadding=8 cellspacing=0 width=604>
<tr><td>
<p>Changed your home or e-mail address? Want to change
your password? Care to change your e-mail notification
preferences? Modify your information and preferences
below, then click on the Update button. Your changes
will take effect immediately.
</p>
</td>
</tr>
<tr>
<td align="center">
<br>
<br>
<table width=100%>
<tr><td width=30% valign="top">Password:</td><td
colspan=2 width=40% valign="top"><input type=password
size=10 maxlength=10 name="pass"
value="<%=rs("pass")%>"></td></tr>
...
All edit files invoke the one editaccountupdate.asp
file illustrated in Listing B.9. This file centralizes all of the update statements into
one file to isolate the code associated with updating accounts. This process of organizing
.asp files in an intuitive manner for managing your
code can provide invaluable support when you need to edit your code. The editaccountupdate.asp simply executes an update sql statement
based on the fields entered.
Listing B.9 EDITACCOUNTUPDATE.ASP-Centralized .asp for Updating Member
Accounts Based on Member-Intiated Updates of their Member Information
...
sql = "UPDATE Members SET"
if request.form("fname")
<> "" then
sql = sql & "
Members.fname ='" & stripchars(request.form("fname")) &
"',"
end if
if request.form("lname")
<> "" then
sql = sql & "
Members.lname ='" & stripchars(request.form("lname")) &
"',"
end if
sql = sql & " Members.pass
='" & stripchars(pass) & "',"
sql = sql & " Members.address1
='" & stripchars(address1) & "',"
sql = sql & " Members.address2
='" & stripchars(address2) & "',"
sql = sql & " Members.city
='" & stripchars(city) & "',"
sql = sql & " Members.stateid
='" & request.form("stateid") & "',"
sql = sql & " Members.zip
='" & stripchars(zip) & "',"
sql = sql & " Members.hmareacode
='" & stripchars(hmareacode) & "',"
sql = sql & " Members.hmphone
='" & stripchars(hmphone) & "',"
sql = sql & " Members.wkareacode
='" & stripchars(wkareacode) & "',"
sql = sql & " Members.wkphone
='" & stripchars(wkphone) & "',"
sql = sql & "
Members.publicphone =" & request.form("publicphone") &
","
if request.form("email")
<> "" then
sql = sql & "
Members.email ='" & stripchars(request.form("email")) &
"',"
end if
sql = sql & "
Members.publicemail =" & request.form("publicemail") &
","
sql = sql & " Members.maiden
='" & stripchars(maiden) & "',"
sql = sql & " Members.ESelect
=" & request.form("eselect") & ","
sql = sql & " Members.Eaccept
=" & request.form("eaccept") & ","
sql = sql & " Members.EGenie
=" & request.form("egenie") & ","
sql = sql & " Members.EGen
=" & request.form("egen") & ","
sql = sql & " Members.download =
1,"
sql = sql & " Members.AdmModDate
= #" & Date() & "#,"
sql = sql & " Members.EOK
=" & request.form("eok") & " "
sql = sql & " WHERE
Members.memberID=" & session("memberid") & ";"
Set rs =
Server.CreateObject("ADO.Recordset")
rs.Open sql,Conn,3
End If
newpage = "profile.asp?memberid=" & session("memberid")
response.redirect newpage
%>
The process of managing account information follows the pages utilized for
creating a New Account very closely. Although these pages can be fairly easily copied over
and modified for use, I recommend that you leave these edit account pages until late in
the development process because changes in the New Account pages and Member table have
cascading impact on the Edit Account Pages. Most test users have little need to manage
accounts and can easily live without this set of features until late in the development
process.
Summing Up
Establishing a membership-based community relies upon effective management of
the New Account process, logon and account validation, and effective distribution of
account maintenance into the membership community. However, if the community sponsor
intends to charge fees for products and services, providing a compelling and interactive
user experience coupled with effective administration and a convenient billing/payment
service will determine the overall effectiveness of the site as a business venture.
Appendix C, "Delivering an Interactive Introduction
Service," explores delivering an interactive service, followed by a look at the
administrative and payment services included the Introduction Service site.
© 1997, QUE Corporation, an imprint of Macmillan
Publishing USA, a Simon and Schuster Company.
Back
page. |