Fixes for 0.12.0 (tables.[]), and added -d:dev.

This commit is contained in:
Dominik Picheta 2015-11-07 00:21:31 +00:00
commit a5963c9164
4 changed files with 22 additions and 14 deletions

View file

@ -4,7 +4,7 @@ This is Nim's forum. Available at http://forum.nim-lang.org.
## Building ## Building
You can use ``nimble`` (available [here](https://github.com/nim-lang/nimble) You can use ``nimble`` (available [here](https://github.com/nim-lang/nimble)
to get all the necessary to get all the necessary
[dependencies](https://github.com/nim-lang/nimforum/blob/master/nimforum.nimble#L11). [dependencies](https://github.com/nim-lang/nimforum/blob/master/nimforum.nimble#L11).
@ -55,6 +55,10 @@ Requires: "nimrod >= 0.10.3, cairo#head, jester#head, bcrypt >= 0.2.1"
**Important: You need to compile and run `createdb` to generate the initial database **Important: You need to compile and run `createdb` to generate the initial database
before you can run `forum` the first time**! before you can run `forum` the first time**!
**Note: If you do not have a mail server set up locally, you can specify
``-d:dev`` during compilation to prevent nimforum from attempting to send
emails and to automatically activate user accounts**
This is as simple as: This is as simple as:
``` ```

View file

@ -8,10 +8,10 @@
import strutils, db_sqlite import strutils, db_sqlite
var db = open(connection="nimforum.db", user="postgres", password="", var db = open(connection="nimforum.db", user="postgres", password="",
database="nimforum") database="nimforum")
const const
TUserName = "varchar(20)" TUserName = "varchar(20)"
TPassword = "varchar(32)" TPassword = "varchar(32)"
TEmail = "varchar(30)" TEmail = "varchar(30)"
@ -63,7 +63,7 @@ create table if not exists post(
content varchar(1000) not null, content varchar(1000) not null,
thread integer not null, thread integer not null,
creation timestamp not null default (DATETIME('now')), creation timestamp not null default (DATETIME('now')),
foreign key (thread) references thread(id), foreign key (thread) references thread(id),
foreign key (author) references person(id) foreign key (author) references person(id)
);""", []): );""", []):

View file

@ -105,18 +105,18 @@ const
proc TextWidget(c: TForumData, name, defaultText: string, proc TextWidget(c: TForumData, name, defaultText: string,
maxlength = 30, size = -1): string = maxlength = 30, size = -1): string =
let x = if defaultText != reuseText: defaultText let x = if defaultText != reuseText: defaultText
else: xmlEncode(c.req.params[name]) else: xmlEncode(c.req.params.getOrDefault(name))
return """<input type="text" name="$1" maxlength="$2" value="$3" $4/>""" % [ return """<input type="text" name="$1" maxlength="$2" value="$3" $4/>""" % [
name, $maxlength, x, if size != -1: "size=\"" & $size & "\"" else: ""] name, $maxlength, x, if size != -1: "size=\"" & $size & "\"" else: ""]
proc HiddenField(c: TForumData, name, defaultText: string): string = proc HiddenField(c: TForumData, name, defaultText: string): string =
let x = if defaultText != reuseText: defaultText let x = if defaultText != reuseText: defaultText
else: xmlEncode(c.req.params[name]) else: xmlEncode(c.req.params.getOrDefault(name))
return """<input type="hidden" name="$1" value="$2"/>""" % [name, x] return """<input type="hidden" name="$1" value="$2"/>""" % [name, x]
proc TextAreaWidget(c: TForumData, name, defaultText: string): string = proc TextAreaWidget(c: TForumData, name, defaultText: string): string =
let x = if defaultText != reuseText: defaultText let x = if defaultText != reuseText: defaultText
else: xmlEncode(c.req.params[name]) else: xmlEncode(c.req.params.getOrDefault(name))
return """<textarea name="$1">$2</textarea>""" % [ return """<textarea name="$1">$2</textarea>""" % [
name, x] name, x]
@ -333,16 +333,17 @@ proc register(c: var TForumData, name, pass, antibot,
# TODO: This is a workaround for 'var T' not being usable in async procs. # TODO: This is a workaround for 'var T' not being usable in async procs.
while not emailSentFut.finished: while not emailSentFut.finished:
poll() poll()
if emailSentFut.failed: when not defined(dev):
echo("[WARNING] Couldn't send activation email: ", emailSentFut.error.msg) if emailSentFut.failed:
return setError(c, "email", "Couldn't send activation email") echo("[WARNING] Couldn't send activation email: ", emailSentFut.error.msg)
return setError(c, "email", "Couldn't send activation email")
# add account to person table # add account to person table
exec(db, exec(db,
sql("INSERT INTO person(name, password, email, salt, status, lastOnline, " & sql("INSERT INTO person(name, password, email, salt, status, lastOnline, " &
"ban) VALUES (?, ?, ?, ?, 'user', DATETIME('now'), ?)"), name, "ban) VALUES (?, ?, ?, ?, 'user', DATETIME('now'), ?)"), name,
password, email, salt, password, email, salt,
banReasonEmailUnconfirmed) when defined(dev): "" else: banReasonEmailUnconfirmed)
return true return true
@ -409,10 +410,10 @@ proc incrementViews(c: var TForumData) =
exec(db, query, $c.threadId) exec(db, query, $c.threadId)
proc isPreview(c: TForumData): bool = proc isPreview(c: TForumData): bool =
result = c.req.params["previewBtn"].len > 0 # TODO: Could be wrong? result = c.req.params.hasKey("previewBtn")
proc isDelete(c: TForumData): bool = proc isDelete(c: TForumData): bool =
result = c.req.params["delete"].len > 0 result = c.req.params.hasKey("delete")
proc rstToHtml(content: string): string = proc rstToHtml(content: string): string =
result = rstgen.rstToHtml(content, {roSupportSmilies, roSupportMarkdown}, result = rstgen.rstToHtml(content, {roSupportSmilies, roSupportMarkdown},
@ -582,6 +583,8 @@ proc login(c: var TForumData, name, pass: string): bool =
of "": discard of "": discard
of banReasonDeactivated: of banReasonDeactivated:
return c.setError("name", "Your account has been deactivated.") return c.setError("name", "Your account has been deactivated.")
of banReasonEmailUnconfirmed:
return c.setError("name", "You need to confirm your email first.")
else: else:
return c.setError("name", "You have been banned: " & row[6]) return c.setError("name", "You have been banned: " & row[6])
c.userid = row[0] c.userid = row[0]
@ -624,7 +627,7 @@ proc setPassword(c: var TForumData, nick, pass: string): bool =
proc hasReplyBtn(c: var TForumData): bool = proc hasReplyBtn(c: var TForumData): bool =
result = c.req.pathInfo != "/donewthread" and c.req.pathInfo != "/doreply" result = c.req.pathInfo != "/donewthread" and c.req.pathInfo != "/doreply"
result = result and c.req.params["action"] != "reply" result = result and c.req.params.getOrDefault("action") != "reply"
# If the user is not logged in and there are no page numbers then we shouldn't # If the user is not logged in and there are no page numbers then we shouldn't
# generate the div. # generate the div.
let pages = ceil(c.totalPosts / PostsPerPage).int let pages = ceil(c.totalPosts / PostsPerPage).int

View file

@ -23,6 +23,7 @@ proc loadConfig*(filename = getCurrentDir() / "forum.json"): Config =
echo("[WARNING] Couldn't read config file: ./forum.json") echo("[WARNING] Couldn't read config file: ./forum.json")
proc sendMail(config: Config, subject, message, recipient: string, from_addr = "forum@nim-lang.org", otherHeaders:seq[(string, string)] = @[]) {.async.} = proc sendMail(config: Config, subject, message, recipient: string, from_addr = "forum@nim-lang.org", otherHeaders:seq[(string, string)] = @[]) {.async.} =
when defined(dev): return
var client = newAsyncSmtp(config.smtpAddress, Port(config.smtpPort)) var client = newAsyncSmtp(config.smtpAddress, Port(config.smtpPort))
await client.connect() await client.connect()
if config.smtpUser.len > 0: if config.smtpUser.len > 0: