diff --git a/README.md b/README.md
index 5da3520..1df440e 100644
--- a/README.md
+++ b/README.md
@@ -4,7 +4,7 @@ This is Nim's forum. Available at http://forum.nim-lang.org.
## 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
[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
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:
```
diff --git a/createdb.nim b/createdb.nim
index 815b7a8..2d34099 100644
--- a/createdb.nim
+++ b/createdb.nim
@@ -8,10 +8,10 @@
import strutils, db_sqlite
-var db = open(connection="nimforum.db", user="postgres", password="",
+var db = open(connection="nimforum.db", user="postgres", password="",
database="nimforum")
-const
+const
TUserName = "varchar(20)"
TPassword = "varchar(32)"
TEmail = "varchar(30)"
@@ -63,7 +63,7 @@ create table if not exists post(
content varchar(1000) not null,
thread integer not null,
creation timestamp not null default (DATETIME('now')),
-
+
foreign key (thread) references thread(id),
foreign key (author) references person(id)
);""", []):
diff --git a/forum.nim b/forum.nim
index e657a93..ba25752 100644
--- a/forum.nim
+++ b/forum.nim
@@ -105,18 +105,18 @@ const
proc TextWidget(c: TForumData, name, defaultText: string,
maxlength = 30, size = -1): string =
let x = if defaultText != reuseText: defaultText
- else: xmlEncode(c.req.params[name])
+ else: xmlEncode(c.req.params.getOrDefault(name))
return """""" % [
name, $maxlength, x, if size != -1: "size=\"" & $size & "\"" else: ""]
proc HiddenField(c: TForumData, name, defaultText: string): string =
let x = if defaultText != reuseText: defaultText
- else: xmlEncode(c.req.params[name])
+ else: xmlEncode(c.req.params.getOrDefault(name))
return """""" % [name, x]
proc TextAreaWidget(c: TForumData, name, defaultText: string): string =
let x = if defaultText != reuseText: defaultText
- else: xmlEncode(c.req.params[name])
+ else: xmlEncode(c.req.params.getOrDefault(name))
return """""" % [
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.
while not emailSentFut.finished:
poll()
- if emailSentFut.failed:
- echo("[WARNING] Couldn't send activation email: ", emailSentFut.error.msg)
- return setError(c, "email", "Couldn't send activation email")
+ when not defined(dev):
+ if emailSentFut.failed:
+ echo("[WARNING] Couldn't send activation email: ", emailSentFut.error.msg)
+ return setError(c, "email", "Couldn't send activation email")
# add account to person table
exec(db,
sql("INSERT INTO person(name, password, email, salt, status, lastOnline, " &
"ban) VALUES (?, ?, ?, ?, 'user', DATETIME('now'), ?)"), name,
password, email, salt,
- banReasonEmailUnconfirmed)
+ when defined(dev): "" else: banReasonEmailUnconfirmed)
return true
@@ -409,10 +410,10 @@ proc incrementViews(c: var TForumData) =
exec(db, query, $c.threadId)
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 =
- result = c.req.params["delete"].len > 0
+ result = c.req.params.hasKey("delete")
proc rstToHtml(content: string): string =
result = rstgen.rstToHtml(content, {roSupportSmilies, roSupportMarkdown},
@@ -582,6 +583,8 @@ proc login(c: var TForumData, name, pass: string): bool =
of "": discard
of banReasonDeactivated:
return c.setError("name", "Your account has been deactivated.")
+ of banReasonEmailUnconfirmed:
+ return c.setError("name", "You need to confirm your email first.")
else:
return c.setError("name", "You have been banned: " & row[6])
c.userid = row[0]
@@ -624,7 +627,7 @@ proc setPassword(c: var TForumData, nick, pass: string): bool =
proc hasReplyBtn(c: var TForumData): bool =
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
# generate the div.
let pages = ceil(c.totalPosts / PostsPerPage).int
diff --git a/utils.nim b/utils.nim
index 9819f66..ceb8dc2 100644
--- a/utils.nim
+++ b/utils.nim
@@ -23,6 +23,7 @@ proc loadConfig*(filename = getCurrentDir() / "forum.json"): Config =
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.} =
+ when defined(dev): return
var client = newAsyncSmtp(config.smtpAddress, Port(config.smtpPort))
await client.connect()
if config.smtpUser.len > 0: