Skip to content

Commit 51a5944

Browse files
committed
enforce access-question on anonymous page edits
This commit causes an access-question form field to appear on the edit page for anonymous (logged out) users when require-authentication = none and the access-question variables are non-empty. If the field is present, and if the wrong answer is provided by the user, then the user is returned to the edit page with an error message "Access code is invalid.". This new form field behaves in the same way as the access-question form field on the unauthenticated registration page.
1 parent 1b1f598 commit 51a5944

File tree

2 files changed

+54
-33
lines changed

2 files changed

+54
-33
lines changed

data/default.conf

+8-3
Original file line numberDiff line numberDiff line change
@@ -196,12 +196,17 @@ recaptcha-public-key:
196196
access-question:
197197
access-question-answers:
198198
# specifies a question that users must answer when they attempt to create
199-
# an account, along with a comma-separated list of acceptable answers.
200-
# This can be used to institute a rudimentary password for signing up as
201-
# a user on the wiki, or as an alternative to reCAPTCHA.
199+
# an account or edit a page anonymously, along with a comma-separated list
200+
# of acceptable answers. This can be used to institute a rudimentary
201+
# password for signing up as a user on the wiki, or as an alternative to
202+
# reCAPTCHA.
202203
# Example:
203204
# access-question: What is the code given to you by Ms. X?
204205
# access-question-answers: RED DOG, red dog
206+
# Another example which shows how it could be used as an alternative to
207+
# reCAPTCHA:
208+
# access-question: how many legs in a tripod?
209+
# access-question-answers: three, Three, 3
205210

206211
rpx-domain:
207212
rpx-key:

src/Network/Gitit/Handlers.hs

+46-30
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ import qualified Control.Exception as E
6767
import System.FilePath
6868
import Network.Gitit.State
6969
import Text.XHtml hiding ( (</>), dir, method, password, rev )
70-
import qualified Text.XHtml as X ( method )
70+
import qualified Text.XHtml as X ( method, password )
7171
import Data.List (intercalate, intersperse, delete, nub, sortBy, find, isPrefixOf, inits, sort, (\\))
7272
import Data.List.Split (wordsBy)
7373
import Data.Maybe (fromMaybe, mapMaybe, isJust, catMaybes)
@@ -501,6 +501,7 @@ editPage' params = do
501501
fs <- getFileStore
502502
page <- getPage
503503
cfg <- getConfig
504+
mbUser <- getLoggedInUser
504505
let getRevisionAndText = E.catch
505506
(do c <- liftIO $ retrieve fs (pathForPage page $ defaultExtension cfg) rev
506507
-- even if pRevision is set, we return revId of latest
@@ -529,12 +530,19 @@ editPage' params = do
529530
then [strAttr "readonly" "yes",
530531
strAttr "style" "color: gray"]
531532
else []
533+
let accessQ = case mbUser of
534+
Just _ -> noHtml
535+
Nothing -> case accessQuestion cfg of
536+
Nothing -> noHtml
537+
Just (prompt, _) -> label ! [thefor "accessCode"] << prompt +++ br +++
538+
X.password "accessCode" +++ br
532539
base' <- getWikiBase
533540
let editForm = gui (base' ++ urlForPage page) ! [identifier "editform"] <<
534541
[ sha1Box
535542
, textarea ! (readonly ++ [cols "80", name "editedText",
536543
identifier "editedText"]) << raw
537544
, br
545+
, accessQ
538546
, label ! [thefor "logMsg"] << "Description of changes:"
539547
, br
540548
, textfield "logMsg" ! (readonly ++ [value (logMsg `orIfNull` defaultSummary cfg) ])
@@ -630,39 +638,47 @@ updatePage = withData $ \(params :: Params) -> do
630638
Just b -> applyPreCommitPlugins b
631639
let logMsg = pLogMsg params `orIfNull` defaultSummary cfg
632640
let oldSHA1 = pSHA1 params
641+
let accessCode = pAccessCode params
642+
let isValidAccessCode = case mbUser of
643+
Just _ -> True
644+
Nothing -> case accessQuestion cfg of
645+
Nothing -> True
646+
Just (_, answers) -> accessCode `elem` answers
633647
fs <- getFileStore
634648
base' <- getWikiBase
635649
if null . filter (not . isSpace) $ logMsg
636650
then withMessages ["Description cannot be empty."] editPage
637-
else do
638-
when (length editedText > fromIntegral (maxPageSize cfg)) $
639-
error "Page exceeds maximum size."
640-
-- check SHA1 in case page has been modified, merge
641-
modifyRes <- if null oldSHA1
642-
then liftIO $ create fs (pathForPage page $ defaultExtension cfg)
643-
(Author user email) logMsg editedText >>
644-
return (Right ())
645-
else do
646-
expireCachedFile (pathForPage page $ defaultExtension cfg) `mplus` return ()
647-
liftIO $ E.catch (modify fs (pathForPage page $ defaultExtension cfg)
648-
oldSHA1 (Author user email) logMsg
649-
editedText)
650-
(\e -> if e == Unchanged
651-
then return (Right ())
652-
else E.throwIO e)
653-
case modifyRes of
654-
Right () -> seeOther (base' ++ urlForPage page) $ toResponse $ p << "Page updated"
655-
Left (MergeInfo mergedWithRev conflicts mergedText) -> do
656-
let mergeMsg = "The page has been edited since you checked it out. " ++
657-
"Changes from revision " ++ revId mergedWithRev ++
658-
" have been merged into your edits below. " ++
659-
if conflicts
660-
then "Please resolve conflicts and Save."
661-
else "Please review and Save."
662-
editPage' $
663-
params{ pEditedText = Just mergedText,
664-
pSHA1 = revId mergedWithRev,
665-
pMessages = [mergeMsg] }
651+
else if not isValidAccessCode
652+
then withMessages ["Access code is invalid."] editPage
653+
else do
654+
when (length editedText > fromIntegral (maxPageSize cfg)) $
655+
error "Page exceeds maximum size."
656+
-- check SHA1 in case page has been modified, merge
657+
modifyRes <- if null oldSHA1
658+
then liftIO $ create fs (pathForPage page $ defaultExtension cfg)
659+
(Author user email) logMsg editedText >>
660+
return (Right ())
661+
else do
662+
expireCachedFile (pathForPage page $ defaultExtension cfg) `mplus` return ()
663+
liftIO $ E.catch (modify fs (pathForPage page $ defaultExtension cfg)
664+
oldSHA1 (Author user email) logMsg
665+
editedText)
666+
(\e -> if e == Unchanged
667+
then return (Right ())
668+
else E.throwIO e)
669+
case modifyRes of
670+
Right () -> seeOther (base' ++ urlForPage page) $ toResponse $ p << "Page updated"
671+
Left (MergeInfo mergedWithRev conflicts mergedText) -> do
672+
let mergeMsg = "The page has been edited since you checked it out. " ++
673+
"Changes from revision " ++ revId mergedWithRev ++
674+
" have been merged into your edits below. " ++
675+
if conflicts
676+
then "Please resolve conflicts and Save."
677+
else "Please review and Save."
678+
editPage' $
679+
params{ pEditedText = Just mergedText,
680+
pSHA1 = revId mergedWithRev,
681+
pMessages = [mergeMsg] }
666682

667683
indexPage :: Handler
668684
indexPage = do

0 commit comments

Comments
 (0)