Merge branch 'master' into add_categories

This commit is contained in:
Joey Yakimowich-Payne 2020-02-14 09:48:08 -07:00
commit fac828b1e9
13 changed files with 72 additions and 51 deletions

View file

@ -9,7 +9,7 @@ cache:
- "$HOME/.choosenim"
addons:
firefox: "60.0.1"
firefox: "73.0"
before_install:
- sudo apt-get -qq update
@ -26,13 +26,13 @@ before_install:
- sudo make -j5 install
- cd ..
- wget https://github.com/mozilla/geckodriver/releases/download/v0.20.1/geckodriver-v0.20.1-linux64.tar.gz
- wget https://github.com/mozilla/geckodriver/releases/download/v0.26.0/geckodriver-v0.26.0-linux64.tar.gz
- mkdir geckodriver
- tar -xzf geckodriver-v0.20.1-linux64.tar.gz -C geckodriver
- tar -xzf geckodriver-v0.26.0-linux64.tar.gz -C geckodriver
- export PATH=$PATH:$PWD/geckodriver
install:
- export CHOOSENIM_CHOOSE_VERSION="#f92d61b1f4e193bd"
- export CHOOSENIM_CHOOSE_VERSION="stable"
- |
curl https://nim-lang.org/choosenim/init.sh -sSf > init.sh
sh init.sh -y
@ -41,4 +41,5 @@ install:
script:
- export MOZ_HEADLESS=1
- nimble -y test
- nimble -y install
- nimble -y test

View file

@ -1,5 +1,5 @@
# Package
version = "2.1.0"
version = "2.0.2"
author = "Dominik Picheta"
description = "The Nim forum"
license = "MIT"
@ -12,16 +12,16 @@ skipExt = @["nim"]
# Dependencies
requires "nim >= 0.18.1"
requires "jester#22f8240"
requires "nim >= 1.0.6"
requires "jester#d8a03aa"
requires "bcrypt#head"
requires "hmac#9c61ebe2fd134cf97"
requires "recaptcha 1.0.2"
requires "recaptcha#d06488e"
requires "sass#649e0701fa5c"
requires "karax#c8c7b13"
requires "karax#f6bda9a"
requires "webdriver#20f3c1b"
requires "webdriver#c2fee57"
# Tasks
@ -36,7 +36,7 @@ task frontend, "Builds the necessary JS frontend (with CSS)":
exec "nimble c -r src/buildcss"
exec "nimble js -d:release src/frontend/forum.nim"
mkDir "public/js"
cpFile "src/frontend/nimcache/forum.js", "public/js/forum.js"
cpFile "src/frontend/forum.js", "public/js/forum.js"
task minify, "Minifies the JS using Google's closure compiler":
exec "closure-compiler public/js/forum.js --js_output_file public/js/forum.js.opt"

View file

@ -269,6 +269,13 @@ $threads-meta-color: #545d70;
}
// Hide all the avatars but the first on small screens.
@media screen and (max-width: 600px) {
#threads-list a:not(:first-child) > .avatar {
display: none;
}
}
.posts, .about {
@extend .grid-md;
@extend .container;

View file

@ -100,7 +100,7 @@ You should then create a symlink to this file inside ``/etc/nginx/sites-enabled/
ln -s /etc/nginx/sites-available/<forum.hostname.com> /etc/nginx/sites-enabled/<forum.hostname.com>
```
Then restart nginx by running ``sudo systemctl restart nginx``.
Then reload nginx configuration by running ``sudo nginx -s reload``.
### Supervisor
@ -168,4 +168,4 @@ You should see something like this:
## Conclusion
That should be all you need to get started. Your forum should now be accessible
via your hostname, assuming that it points to your VPS' IP address.
via your hostname, assuming that it points to your VPS' IP address.

View file

@ -457,13 +457,21 @@ proc executeReply(c: TForumData, threadId: int, content: string,
if isLocked == "1":
raise newForumError("Cannot reply to a locked thread.")
let retID = insertID(
db,
crud(crCreate, "post", "author", "ip", "content", "thread", "replyingTo"),
c.userId, c.req.ip, content, $threadId,
if replyingTo.isSome(): $replyingTo.get()
else: ""
)
var retID: int64
if replyingTo.isSome():
retID = insertID(
db,
crud(crCreate, "post", "author", "ip", "content", "thread", "replyingTo"),
c.userId, c.req.ip, content, $threadId, $replyingTo.get()
)
else:
retID = insertID(
db,
crud(crCreate, "post", "author", "ip", "content", "thread"),
c.userId, c.req.ip, content, $threadId
)
discard tryExec(
db,
crud(crCreate, "post_fts", "id", "content"),
@ -621,7 +629,7 @@ proc executeRegister(c: TForumData, name, pass, antibot, userIp,
raise newForumError("Invalid username", @["username"])
if getValue(
db,
sql"select name from person where name = ? and isDeleted = 0",
sql"select name from person where name = ? collate nocase and isDeleted = 0",
name
).len > 0:
raise newForumError("Username already exists", @["username"])
@ -1123,7 +1131,8 @@ routes:
except EParseError:
let err = PostError(
errorFields: @[],
message: getCurrentExceptionMsg()
message: "Message needs to be valid RST! Error: " &
getCurrentExceptionMsg()
)
resp Http400, $(%err), "application/json"

View file

@ -90,4 +90,4 @@ when defined(js):
state.error = some(PostError(
errorFields: @[],
message: "Unknown error occurred."
))
))

View file

@ -25,7 +25,7 @@ proc getInt64*(s: string, default = 0): int64 =
when defined(js):
include karax/prelude
import karax / [kdom]
import karax / [kdom, kajax]
from dom import nil
@ -87,16 +87,10 @@ when defined(js):
navigateTo(url)
type
FormData* = ref object
proc newFormData*(): FormData
{.importcpp: "new FormData()", constructor.}
proc newFormData*(form: dom.Element): FormData
{.importcpp: "new FormData(@)", constructor.}
proc get*(form: FormData, key: cstring): cstring
{.importcpp: "#.get(@)".}
proc append*(form: FormData, key, val: cstring)
{.importcpp: "#.append(@)".}
proc renderProfileUrl*(username: string): string =
makeUri(fmt"/profile/{username}")
@ -120,4 +114,4 @@ when defined(js):
inc(i) # Skip =
i += query.parseUntil(val, '&', i)
inc(i) # Skip &
result[$decodeUri(key)] = $decodeUri(val)
result[$decodeUri(key)] = $decodeUri(val)

View file

@ -1,6 +1,6 @@
when defined(js):
import sugar, httpcore, options, json
import dom except Event
import dom except Event, KeyboardEvent
include karax/prelude
import karax / [kajax, kdom]
@ -93,4 +93,4 @@ when defined(js):
(state.onSignUp(); state.shown = false)):
text "Create account"
render(state.resetPasswordModal, recaptchaSiteKey)
render(state.resetPasswordModal, recaptchaSiteKey)

View file

@ -26,7 +26,7 @@ when defined(js):
proc performScroll() =
let replyBox = dom.document.getElementById("reply-box")
replyBox.scrollIntoView(false)
replyBox.scrollIntoView()
proc show*(state: ReplyBox) =
# Scroll to the reply box.

View file

@ -1,6 +1,6 @@
when defined(js):
import sugar, httpcore, options, json
import dom except Event
import dom except Event, KeyboardEvent
include karax/prelude
import karax / [kajax, kdom]
@ -152,4 +152,4 @@ when defined(js):
),
`type`="button",
onClick=(ev: Event, n: VNode) => onClick(ev, n, state)):
text "Reset password"
text "Reset password"

View file

@ -10,11 +10,6 @@ let
import frontend/[karaxutils, error]
export parseInt
proc `%`*[T](opt: Option[T]): JsonNode =
## Generic constructor for JSON data. Creates a new ``JNull JsonNode``
## if ``opt`` is empty, otherwise it delegates to the underlying value.
if opt.isSome: %opt.get else: newJNull()
type
Config* = object
smtpAddress*: string
@ -56,7 +51,7 @@ proc loadConfig*(filename = getCurrentDir() / "forum.json"): Config =
smtpPassword: "", mlistAddress: "")
let root = parseFile(filename)
result.smtpAddress = root{"smtpAddress"}.getStr("")
result.smtpPort = root{"smtpPort"}.getNum(25).int
result.smtpPort = root{"smtpPort"}.getInt(25)
result.smtpUser = root{"smtpUser"}.getStr("")
result.smtpPassword = root{"smtpPassword"}.getStr("")
result.smtpFromAddr = root{"smtpFromAddr"}.getStr("")
@ -69,7 +64,7 @@ proc loadConfig*(filename = getCurrentDir() / "forum.json"): Config =
result.name = root["name"].getStr()
result.title = root["title"].getStr()
result.ga = root{"ga"}.getStr()
result.port = root{"port"}.getNum(5000).int
result.port = root{"port"}.getInt(5000)
proc processGT(n: XmlNode, tag: string): (int, XmlNode, string) =
result = (0, newElement(tag), tag)

View file

@ -115,7 +115,7 @@ proc login*(session: Session, user, password: string) =
checkText "#profile-btn #profile-name", user
click "#profile-btn"
proc register*(session: Session, user, password: string) =
proc register*(session: Session, user, password: string, verify = true) =
with session:
click "#signup-btn"
@ -130,11 +130,13 @@ proc register*(session: Session, user, password: string) =
click "#signup-modal .create-account-btn"
wait()
# Verify that the user menu has been initialised properly.
click "#profile-btn"
checkText "#profile-btn #profile-name", user
# close menu
click "#profile-btn"
if verify:
with session:
# Verify that the user menu has been initialised properly.
click "#profile-btn"
checkText "#profile-btn #profile-name", user
# close menu
click "#profile-btn"
proc createThread*(session: Session, title, content: string) =
with session:

View file

@ -30,5 +30,18 @@ proc test*(session: Session, baseUrl: string) =
test "can register":
with session:
register("test", "test")
logout()
session.logout()
test "can't register same username with different case":
with session:
register "test1", "test1", verify = false
logout()
navigate baseUrl
wait()
register "TEst1", "test1", verify = false
ensureExists "#signup-form .has-error"
navigate baseUrl
wait()