Adding reCAPTCHA rather than the custom captcha.
Signed-off-by: Euan Torano <euantorano@gmail.com>
This commit is contained in:
parent
d5892db647
commit
c1bd44b997
8 changed files with 35 additions and 47 deletions
37
captchas.nim
37
captchas.nim
|
|
@ -1,37 +0,0 @@
|
||||||
#
|
|
||||||
#
|
|
||||||
# The Nim Forum
|
|
||||||
# (c) Copyright 2012 Andreas Rumpf, Dominik Picheta
|
|
||||||
# Look at license.txt for more info.
|
|
||||||
# All rights reserved.
|
|
||||||
#
|
|
||||||
|
|
||||||
import cairo, os, strutils, jester
|
|
||||||
|
|
||||||
proc getCaptchaFilename*(i: int): string {.inline.} =
|
|
||||||
result = "public/captchas/capture_" & $i & ".png"
|
|
||||||
|
|
||||||
proc getCaptchaUrl*(req: Request, i: int): string =
|
|
||||||
result = req.makeUri("/captchas/capture_" & $i & ".png", absolute = false)
|
|
||||||
|
|
||||||
proc createCaptcha*(file, text: string) =
|
|
||||||
var surface = imageSurfaceCreate(FORMAT_ARGB32, int32(10*text.len), int32(10))
|
|
||||||
var cr = create(surface)
|
|
||||||
|
|
||||||
selectFontFace(cr, "serif", FONT_SLANT_NORMAL, FONT_WEIGHT_BOLD)
|
|
||||||
setFontSize(cr, 12.0)
|
|
||||||
|
|
||||||
setSourceRgb(cr, 1.0, 0.5, 0.0)
|
|
||||||
moveTo(cr, 0.0, 10.0)
|
|
||||||
showText(cr, repeat('O', text.len))
|
|
||||||
|
|
||||||
setSourceRgb(cr, 0.0, 0.0, 1.0)
|
|
||||||
moveTo(cr, 0.0, 10.0)
|
|
||||||
showText(cr, text)
|
|
||||||
|
|
||||||
destroy(cr)
|
|
||||||
discard writeToPng(surface, file)
|
|
||||||
destroy(surface)
|
|
||||||
|
|
||||||
when isMainModule:
|
|
||||||
createCaptcha("test.png", "1+33")
|
|
||||||
|
|
@ -249,10 +249,12 @@
|
||||||
<td>${fieldValid(c, "email", "E-Mail:")}</td>
|
<td>${fieldValid(c, "email", "E-Mail:")}</td>
|
||||||
<td>${textWidget(c, "email", reuseText, maxlength=300)}</td>
|
<td>${textWidget(c, "email", reuseText, maxlength=300)}</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
#if useCaptcha:
|
||||||
<tr>
|
<tr>
|
||||||
<td>${fieldValid(c, "antibot", "What is " & antibot(c) & "?")}</td>
|
<td>${fieldValid(c, "g-recaptcha-response", "Captcha:")}</td>
|
||||||
<td>${textWidget(c, "antibot", "", maxlength=4)}</td>
|
<td>${captcha.render(includeNoScript=true)}</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
#end if
|
||||||
</table>
|
</table>
|
||||||
#if c.errorMsg != "":
|
#if c.errorMsg != "":
|
||||||
<div style="float: left; width: 100%;">
|
<div style="float: left; width: 100%;">
|
||||||
|
|
|
||||||
4
forum.json.example
Normal file
4
forum.json.example
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
{
|
||||||
|
"recaptchaSecretKey": "",
|
||||||
|
"recaptchaSiteKey": ""
|
||||||
|
}
|
||||||
25
forum.nim
25
forum.nim
|
|
@ -8,8 +8,8 @@
|
||||||
|
|
||||||
import
|
import
|
||||||
os, strutils, times, md5, strtabs, cgi, math, db_sqlite,
|
os, strutils, times, md5, strtabs, cgi, math, db_sqlite,
|
||||||
captchas, scgi, jester, asyncdispatch, asyncnet, cache, sequtils,
|
scgi, jester, asyncdispatch, asyncnet, cache, sequtils,
|
||||||
parseutils, utils, random, rst, ranks
|
parseutils, utils, random, rst, ranks, recaptcha
|
||||||
|
|
||||||
when not defined(windows):
|
when not defined(windows):
|
||||||
import bcrypt # TODO
|
import bcrypt # TODO
|
||||||
|
|
@ -77,6 +77,8 @@ var
|
||||||
db: DbConn
|
db: DbConn
|
||||||
isFTSAvailable: bool
|
isFTSAvailable: bool
|
||||||
config: Config
|
config: Config
|
||||||
|
useCaptcha: bool
|
||||||
|
captcha: ReCaptcha
|
||||||
|
|
||||||
proc init(c: var TForumData) =
|
proc init(c: var TForumData) =
|
||||||
c.userPass = ""
|
c.userPass = ""
|
||||||
|
|
@ -314,8 +316,16 @@ proc register(c: var TForumData, name, pass, antibot,
|
||||||
return setError(c, "new_password", "Invalid password!")
|
return setError(c, "new_password", "Invalid password!")
|
||||||
|
|
||||||
# captcha validation:
|
# captcha validation:
|
||||||
if not isCaptchaCorrect(c, antibot):
|
if useCaptcha:
|
||||||
return setError(c, "antibot", "Answer to captcha incorrect!")
|
var captchaValid: bool = false
|
||||||
|
try:
|
||||||
|
captchaValid = waitFor captcha.verify(antibot)
|
||||||
|
except:
|
||||||
|
echo("[ERROR] Error checking captcha: " & getCurrentExceptionMsg())
|
||||||
|
captchaValid = false
|
||||||
|
|
||||||
|
if not captchaValid:
|
||||||
|
return setError(c, "antibot", "Answer to captcha incorrect!")
|
||||||
|
|
||||||
# email validation
|
# email validation
|
||||||
if not ('@' in email and '.' in email):
|
if not ('@' in email and '.' in email):
|
||||||
|
|
@ -1123,7 +1133,7 @@ routes:
|
||||||
|
|
||||||
post "/doregister":
|
post "/doregister":
|
||||||
createTFD()
|
createTFD()
|
||||||
if c.register(@"name", @"new_password", @"antibot", @"email"):
|
if c.register(@"name", @"new_password", @"g-recaptcha-response", @"email"):
|
||||||
resp genMain(c, "You are now registered. You must now confirm your" &
|
resp genMain(c, "You are now registered. You must now confirm your" &
|
||||||
" email address by clicking the link sent to " & @"email",
|
" email address by clicking the link sent to " & @"email",
|
||||||
"Registration successful - Nim Forum")
|
"Registration successful - Nim Forum")
|
||||||
|
|
@ -1353,6 +1363,11 @@ when isMainModule:
|
||||||
isFTSAvailable = db.getAllRows(sql("SELECT name FROM sqlite_master WHERE " &
|
isFTSAvailable = db.getAllRows(sql("SELECT name FROM sqlite_master WHERE " &
|
||||||
"type='table' AND name='post_fts'")).len == 1
|
"type='table' AND name='post_fts'")).len == 1
|
||||||
config = loadConfig()
|
config = loadConfig()
|
||||||
|
if len(config.recaptchaSecretKey) > 0 and len(config.recaptchaSiteKey) > 0:
|
||||||
|
useCaptcha = true
|
||||||
|
captcha = initReCaptcha(config.recaptchaSecretKey, config.recaptchaSiteKey)
|
||||||
|
else:
|
||||||
|
useCaptcha = false
|
||||||
var http = true
|
var http = true
|
||||||
if paramCount() > 0:
|
if paramCount() > 0:
|
||||||
if paramStr(1) == "scgi":
|
if paramStr(1) == "scgi":
|
||||||
|
|
|
||||||
|
|
@ -2,3 +2,5 @@
|
||||||
# we need the documentation generator of the compiler:
|
# we need the documentation generator of the compiler:
|
||||||
path="$lib/packages/docutils"
|
path="$lib/packages/docutils"
|
||||||
path="$nim"
|
path="$nim"
|
||||||
|
|
||||||
|
-d:ssl
|
||||||
|
|
@ -8,4 +8,4 @@ license = "MIT"
|
||||||
bin = "forum"
|
bin = "forum"
|
||||||
|
|
||||||
[Deps]
|
[Deps]
|
||||||
Requires: "nim >= 0.14.0, cairo#head, jester#head, bcrypt#head"
|
Requires: "nim >= 0.14.0, cairo#head, jester#head, bcrypt#head, recaptcha >= 1.0.0"
|
||||||
|
|
|
||||||
2
public/captchas/.gitignore
vendored
2
public/captchas/.gitignore
vendored
|
|
@ -1,2 +0,0 @@
|
||||||
*
|
|
||||||
!.gitignore
|
|
||||||
|
|
@ -22,6 +22,8 @@ type
|
||||||
smtpUser: string
|
smtpUser: string
|
||||||
smtpPassword: string
|
smtpPassword: string
|
||||||
mlistAddress: string
|
mlistAddress: string
|
||||||
|
recaptchaSecretKey*: string
|
||||||
|
recaptchaSiteKey*: string
|
||||||
|
|
||||||
var docConfig: StringTableRef
|
var docConfig: StringTableRef
|
||||||
|
|
||||||
|
|
@ -38,6 +40,8 @@ proc loadConfig*(filename = getCurrentDir() / "forum.json"): Config =
|
||||||
result.smtpUser = root{"smtpUser"}.getStr("")
|
result.smtpUser = root{"smtpUser"}.getStr("")
|
||||||
result.smtpPassword = root{"smtpPassword"}.getStr("")
|
result.smtpPassword = root{"smtpPassword"}.getStr("")
|
||||||
result.mlistAddress = root{"mlistAddress"}.getStr("")
|
result.mlistAddress = root{"mlistAddress"}.getStr("")
|
||||||
|
result.recaptchaSecretKey = root{"recaptchaSecretKey"}.getStr("")
|
||||||
|
result.recaptchaSiteKey = root{"recaptchaSiteKey"}.getStr("")
|
||||||
except:
|
except:
|
||||||
echo("[WARNING] Couldn't read config file: ", filename)
|
echo("[WARNING] Couldn't read config file: ", filename)
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue