Skip to content

sveri/friend-ui

Repository files navigation

Warning

This project is not used in a production environment yet, so try it at your own risk.

friendui

A Clojure library designed to wrap cemerick's friend ([https://github.com/cemerick/friend]) library. It provides templates for login / signup with email activation. Additionally there is an admin interface where one can edit existing users or add new ones.

Dependencies

  • enlive (v1.1.5) as templating library.
  • friend (0.2.1)
  • Bootstrap (> 3.0) is required too if you want it to look nice.

"Installation"

Friendui is available in Clojars: Clojars Project

Related

There is an implementation for this which uses SQL Korma as a backend: https://github.com/sventechie/friendui-sql. It uses JDBC; MySQL and PostgreSQL schemas are provided, and other DBs could be supported too if you customize the schemas.

Usage

Config

Friendui looks for a configuration file named: friendui-config.edn in the classpath. An example config can be found here: [https://github.com/sveri/friend-ui/blob/master/dev-resources/friendui-config.edn]

Then you have to alter the root binding of the base template var like this:

(:require [de.sveri.friendui.globals :as f-global])

(html/deftemplate base (str template-path "base.html")
                  [{:keys [title content]}]
                  [:#title] (util/maybe-content title)         ; this corresponds to the :base-template-title-key key in the config
                  [:#content] (util/maybe-substitute content)) ; this corresponds to the :base-template-content-key key in the config

(alter-var-root #'f-global/base-template (fn [_] (partial base)))

E-Mail

Friendui supports two different ways of sending email which are configured in friendui-config.edn by the :mail-type tag.

  1. :sendmail Expects a running sendmail on localhost by which the mail will be delivered.
  2. :smtp An extra :smtp-data map must be provided in the config which is passed as is to postal: [https://github.com/drewr/postal]

Protocol

And finally you have to implement a protocol to retrieve and store user data:

(defprotocol FrienduiStorage
  "Defines methods to access user storage for retrieval and update."
  (account-activated? [this activationid]
                      "Provides an id. Expects a boolean return value indicating if the user, belonging to the id is
                      activated or not.")
  (activate-account [this activationid]
                    "Should set the user with the given id to activated. After this function was called successfully
                    (account-activated?) should return true.")
  (create-user [this email password role activationid]
               "Should add a new user to your data store. Return value is not checked.")
  (get-all-users [this]
                 "Called from the admin view. Expects a list of all known users in this format:
                 ({:user/activated false, :user/role :user/admin, :user/email unique-email@host.com}
                 ...)
                 Where each key corresponds to the configured keyword from friendui-config.edn")
  (get-user-for-activation-id [this id]
                              "Should return a map containing the username and role of this user like this:
                              {:username username :roles #{role}}")
  (update-user [this username data-map]
               "Updates the user with the given data map of the form: {:user/activated boolean :user/role :user/free}")
  (username-exists? [this username]
                    "Expects true if the username exists already in the storage, false otherwise."))

Then you pass this storage to the friendui routes like this:

(:require [de.sveri.friendui.routes.user :refer [friend-routes]])

(defroutes allroutes
    (friend-routes FrienduiStorageImpl)
    ...)

(def app
  (handler/site
    (friend/authenticate allroutes friend-settings)))

Your friend settings

Of course you have to define your friend settings yourself in your application, this is an example of mine:

(def friend-settings
  {:credential-fn             (partial creds/bcrypt-credential-fn user/login-user)
   :workflows                 [(workflows/interactive-form)]
   :login-uri                 "/user/login"
   :unauthorized-redirect-uri "/user/login"
   :default-landing-uri       "/"})

This should get you up and running.

Provided Resources:

(GET "/user/login")   ; expects a "username" / "password" combination
(GET "/user/signup")
(POST "/user/signup") ; expects email / password / confirm parameters
(GET "/user/accountcreated")
(GET "/user/activate/:id")
(GET "/user/accountactivated")
(GET "/user/admin" [filter])
(POST "/user/update" [username role active])
(POST "/user/add" [email password confirm]) ; used in admin view
(ANY "/user/logout")

Callback functions

Friendui provides support for callback functions. These are called under certain circumstances. You can pass them as a map to the friend-routes function like this:

(friend-routes (db/FrienduiStorageImpl db-conn) {:signup-succ-func (fn [] (println "succ func"))})

Currently these two are supported:

  • signup-succ-func Called after a successfull signup - no arguments
  • activate-account-succ-func Called after a successful user activation, takes a user map as argument (provides username and roles key)

Screenshots

Signup

Alt Signup

Signup Error

Alt Signup Error

Account Created

Alt Account Created

Admin View

Alt Admin View

Version History

  • 0.4.6 rendering with (apply str again

  • 0.4.5 Added success message when password was changed

  • 0.4.4 Removing utils and switching to clojure test

  • 0.4.3 Do not authenticate with friend after account activation

  • 0.4.2 Added SMTP authentication in config

    • Switched to postal
  • 0.4.0 Added get-loggedin-user-map function

    • accountactivated page will redirect after three seconds to index page
    • Added anti-forgery hidden input fields for forms
  • 0.3.3 Added two callback functions

  • 0.3.2 Added default unauthorized handler and an example storage protocol implementation at: sveri/friendui-datomic

  • 0.3.1 Bugfix and documentation release

  • 0.3.0 decoupled from Datomic which caused a lot of API changes.

  • 0.2.4 - Broken build - don't use it

    • Added Administrator interface for users.
    • User roles and activation status can be updated by administrators.
    • New Users can be added by administrators.
    • A filter is available for the user list
  • 0.2.3 First working release with an implementation that dependson enlive and Datomic.

License

Distributed under the Eclipse Public License either version 1.0 or any later version.

About

a web frontend for friend using enlive

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published