Creating a Wiki with UCW

Adding a Login Page 

Let's pretend that, in order to avoid spurious spamming, we want to make users login before editing pages.

NB: If you are comparing the two wiki implementations you need to remeber that both interfaces use the same session object. Logging in through the "regular style" wiki will couse you to be logged into the "UCW style" wiki and vice versa.

Regular Style 

Redefining edit.ucw 

The only way to edit a page is to go through the edit.ucw, so we'll put the login logic there. Every time a user attempts to edit a page we look in the current session for something (anything other than NIL will do) under the key USER. If we find something then continue as before, if we don't we redirect to the wiki-login.ucw page.

(defentry-point "edit.ucw" (:application *example-application*)
  ((page-name "WelcomePage") name summary contents)
  (cond
    ((not (get-session-value 'user))
     (call 'redirect-component :target "wiki-login.ucw"))
    (contents
     (update-wiki-page page-name
                       (make-instance 'wiki-edit
                                      :author name
                                      :summary summary
                                      :contents contents))
     (call 'thankyou :page-name page-name))
    (t
     (call 'edit-wiki-page :page-name page-name))))

New page wiki-login.ucw 

wiki-login.ucw looks for two request parameters, username and password. If they're found, and if they're both equal to "wiki" then we put the username in the session table under the key USER (so that the edit.ucw entry point will find it) and we redirect to view.ucw. If the username and password parameters aren't passed, or they're aren't equal to "wiki" then we show a wiki-login-for-edit component.

(defentry-point "wiki-login.ucw" (:application *example-application*)
    ((username "") (password ""))
  (if (and (string= "wiki" username) (string= "wiki" password))
      (progn
        (setf (get-session-value 'user) username)
        (call 'redirect-component :target "view.ucw"))
      (call 'wiki-login-for-edit)))

This wiki-login-for-edit component simply creates a very minimal page with a form for the username and password values.

(defcomponent wiki-login-for-edit (window-component)
  ())
(defmethod render-on ((res response) (login wiki-login-for-edit))
  (<:html
   (<:head (<:title "Login"))
   (<:body
    (<:form :action "wiki-login.ucw"
      (<:p "Login with wiki/wiki")
      (<:p
        (<:label :for "username" "Username: ")
        (<:input :type "text" :name "username" :id "username"))
      (<:p
        (<:label :for "password" "Password: ")
        (<:input :type "text" :name "password" :id "password"))
      (<:p (<:submit :value "Login"))))))

UCW Style 

Redefining the edit-page action 

As with the regular style wiki we'll put the login checking just before editing a page. If the the value of (get-session-value 'user) is null than we call wiki-login component and store whatever it answers in the session under the key user. When the wiki-login component has finished (or when we're already logged in) we simply continue as before by calling wiki-editor and wiki-editor-thankyou.

(defaction edit-page ((w wiki-viewer) page-name)
  (unless (get-session-value 'user)
    (setf (get-session-value 'user) (call 'wiki-login)))
  (call 'wiki-editor          :page-name page-name)
  (call 'wiki-editor-thankyou :page-name page-name))

The wiki-login component and actions 

(while we could use ucw's login component we're going to try to keep this example as self contained as possible)

(defcomponent wiki-login ()
  ())
(defmethod render-on ((res response) (login wiki-login))
  (let ((username "")
        (password ""))
    (<ucw:form :action (wiki-login login username password)
      (<:p
        "Login with wiki/wiki.")
      (<:p
        (<:label :for "username" "Username: ")
        (<ucw:text :accessor username :id "username"))
      (<:p
        (<:label :for "password" "Password: ")
        (<ucw:password :accessor password :id "password"))
      (<:p
        (<ucw:submit :action (wiki-login login username password))))))
(defaction wiki-login ((login wiki-login) username password)
  (when (and (string= "wiki" username) (string= "wiki" password))
    (answer username)))