User:Ric Sherlock/Temp/UserLogin

From J Wiki
Jump to navigation Jump to search

Intro

The initial request for critique on this JHP application led Oleg Kobchenko to propose the Markup-Behind model as a mechanism for separating the programming logic and presentation in a web application. Hopefully the more detailed example here will serve as an additional illustration of how both JHP and Markup-Behind can be used.

Please feel free to critique/comment on the following.

Code

The following file is the default URL when visiting the root of the site. It also handles a number of other requests dependent on the query string. The HTML markup for two of the resulting pages is contained in the welcome.html and logout.html files shown below. [{{#file: "default.jhp"}} Download script: default.jhp ]

<%
load '~.CGI/code/user.ijs'
try.
  action=. qparam 'action'
    select. action
    case. 'logout' do.
      if. loggedIn'' do. DeleteCookie 'UserID' end.
      page=:'~CGI/welcome.html'
    case. 'loginfail' do.
      page=:'~CGI/loginfail.html'
    case. 'nouser' do.
      page=:'~CGI/nouser.html'
    case. do. NB. default action
      page=:'~CGI/welcome.html'
    end.
      transfer page
catch.
  ContentType'text/html'[ Expires 0
  println '<html><body><p>There was an error: ',13!:12''
  println '</p></body></html>'
end.
%>

The following file contains the HTML markup for the default web page for the site. [{{#file: "welcome.html"}} Download script: welcome.html ]

<html><head>
<title>Login Demo</title>
</head>
<body>
<h2>Welcome to this site</h2>
<p>If you have registered before, you can log in below.</p>
<form action="login.jhp" method="post" name="login" id="login">
  <p>User: <input name="usrname"></p>
  <p>Password: <input name="passwd" type="password"></p>
  <p><input type=submit></p>
</form>
</body></html>

The following file contains the JHP code to handle a user login request. The verbs validLogin and getUserInfo_puserdb_ are not shown here but just, validate a login and do a lookup for user info respectively. [{{#file: "login.jhp"}} Download script: login.jhp ]

<%
load '~.CGI/code/user.ijs'
try.
  uid=: validLogin qparam each 'usrname';'passwd'
  if. 0>uid do. NB. invalid login
    redirect 'default.jhp?action=loginfail'
  else.
    page=. '~CGI/userhome.asp'  NB. destination page
    'fname lname'=: 'greeting' getUserInfo_puserdb_ uid
    uid SetCookie 'UserID'
    transfer page
  end.
catch.
  ContentType'text/html'[ Expires 0
  println '<html><body><p>There was an error: ',13!:12''
  println '</p></body></html>'
end.
%>

The following file is both valid JHP and ASP. It is given the .asp extension to distinguish it both from files containing only JHP code, and files containing only HTML markup. The .asp extension also means the file will be handled appropriately by HTML editors. The transfer verb will do the variable replacement using the variables created in login.jhp. [{{#file: "userhome.asp"}} Download script: userhome.asp ]

<html><head>
<title>My Site</title>
</head>
<body>
  <h2>User Home</h2>
  <p>You are currently logged in as <%= fname %> <%= lname %>.
  If that is not correct, <a href="default.jhp?action=logout">log out</a>
  and login again using your username and password.</p>
</body>
</html>

[{{#file: "logout.html"}} Download script: logout.html ]

<html><head>
<title>Login Demo</title>
</head>
<body>
<h2>Logout Successful</h2>
<p>Thanks for using my site.</p>
<p>If you wish, you can login again below, otherwise, until next time!</p>
<form action="login.jhp" method="post" name="login" id="login">
  <p>User: <input name="usrname"></p>
  <p>Password: <input name="passwd" type="password"></p>
  <p><input type=submit></p>
</form>
</body></html>

I envisage that the functionality in the following script would eventually be added to JHP (probably in a much more complete and robust way). [{{#file: "jhpadd.ijs"}} Download script: jhpadd.ijs ]

require 'files'
NB. require 'web/jhp/jhp'

coclass 'z'

fext=:'.'&(>:@i:~}.]) NB. get file extension
isJHP=: (;:'jhp asp') e.~ [:<fext

transfer=: 3 : 0
  fnme=.y
  NB. map to physical path
  if. isJHP fnme do.
    ContentType'text/html'[ Expires 0
    markup fnme
  else.
    ContentType'text/html'[ Expires 0  NB. Need to determine Content-Type here
    stdout fread jpath fnme
  end.
)

redirect=: 3 : 0
  uri=.y
  NB. if relative URL, convert to absolute
  println 'Location: ',uri
  ContentType'text/html'
)

refresh=: 3 : 0
  uri=.y
  NB. if relative URL, convert to absolute
  println 'Refresh: 0; url=',uri
  ContentType'text/html'
)

The following script contains verbs to do the "heavy" lifting for dealing with user-related operations. They are not displayed here. [{{#file: "user.ijs"}} Download script: user.ijs ]

NB.*loggedIn v Checks if a user is currently authenticated
NB.  y is ''
NB.  result is boolean

NB.*validLogin v checks if login is valid returns userid
NB.  y is boxed list of two strings 'username';'password'
NB.  result is numeric _1 if not valid, string userid if valid

NB.*getUserInfo v gets user info from database
NB. y is values to look up in database
NB. x is string specifying name of sqlquery to run