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" - "$HOME/.choosenim"
addons: addons:
firefox: "60.0.1" firefox: "73.0"
before_install: before_install:
- sudo apt-get -qq update - sudo apt-get -qq update
@ -26,13 +26,13 @@ before_install:
- sudo make -j5 install - sudo make -j5 install
- cd .. - 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 - 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 - export PATH=$PATH:$PWD/geckodriver
install: install:
- export CHOOSENIM_CHOOSE_VERSION="#f92d61b1f4e193bd" - export CHOOSENIM_CHOOSE_VERSION="stable"
- | - |
curl https://nim-lang.org/choosenim/init.sh -sSf > init.sh curl https://nim-lang.org/choosenim/init.sh -sSf > init.sh
sh init.sh -y sh init.sh -y
@ -41,4 +41,5 @@ install:
script: script:
- export MOZ_HEADLESS=1 - export MOZ_HEADLESS=1
- nimble -y install
- nimble -y test - nimble -y test

View file

@ -1,5 +1,5 @@
# Package # Package
version = "2.1.0" version = "2.0.2"
author = "Dominik Picheta" author = "Dominik Picheta"
description = "The Nim forum" description = "The Nim forum"
license = "MIT" license = "MIT"
@ -12,16 +12,16 @@ skipExt = @["nim"]
# Dependencies # Dependencies
requires "nim >= 0.18.1" requires "nim >= 1.0.6"
requires "jester#22f8240" requires "jester#d8a03aa"
requires "bcrypt#head" requires "bcrypt#head"
requires "hmac#9c61ebe2fd134cf97" requires "hmac#9c61ebe2fd134cf97"
requires "recaptcha 1.0.2" requires "recaptcha#d06488e"
requires "sass#649e0701fa5c" requires "sass#649e0701fa5c"
requires "karax#c8c7b13" requires "karax#f6bda9a"
requires "webdriver#20f3c1b" requires "webdriver#c2fee57"
# Tasks # Tasks
@ -36,7 +36,7 @@ task frontend, "Builds the necessary JS frontend (with CSS)":
exec "nimble c -r src/buildcss" exec "nimble c -r src/buildcss"
exec "nimble js -d:release src/frontend/forum.nim" exec "nimble js -d:release src/frontend/forum.nim"
mkDir "public/js" 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": 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" 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 { .posts, .about {
@extend .grid-md; @extend .grid-md;
@extend .container; @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> 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 ### Supervisor

View file

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

View file

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

View file

@ -1,6 +1,6 @@
when defined(js): when defined(js):
import sugar, httpcore, options, json import sugar, httpcore, options, json
import dom except Event import dom except Event, KeyboardEvent
include karax/prelude include karax/prelude
import karax / [kajax, kdom] import karax / [kajax, kdom]

View file

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

View file

@ -1,6 +1,6 @@
when defined(js): when defined(js):
import sugar, httpcore, options, json import sugar, httpcore, options, json
import dom except Event import dom except Event, KeyboardEvent
include karax/prelude include karax/prelude
import karax / [kajax, kdom] import karax / [kajax, kdom]

View file

@ -10,11 +10,6 @@ let
import frontend/[karaxutils, error] import frontend/[karaxutils, error]
export parseInt 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 type
Config* = object Config* = object
smtpAddress*: string smtpAddress*: string
@ -56,7 +51,7 @@ proc loadConfig*(filename = getCurrentDir() / "forum.json"): Config =
smtpPassword: "", mlistAddress: "") smtpPassword: "", mlistAddress: "")
let root = parseFile(filename) let root = parseFile(filename)
result.smtpAddress = root{"smtpAddress"}.getStr("") result.smtpAddress = root{"smtpAddress"}.getStr("")
result.smtpPort = root{"smtpPort"}.getNum(25).int result.smtpPort = root{"smtpPort"}.getInt(25)
result.smtpUser = root{"smtpUser"}.getStr("") result.smtpUser = root{"smtpUser"}.getStr("")
result.smtpPassword = root{"smtpPassword"}.getStr("") result.smtpPassword = root{"smtpPassword"}.getStr("")
result.smtpFromAddr = root{"smtpFromAddr"}.getStr("") result.smtpFromAddr = root{"smtpFromAddr"}.getStr("")
@ -69,7 +64,7 @@ proc loadConfig*(filename = getCurrentDir() / "forum.json"): Config =
result.name = root["name"].getStr() result.name = root["name"].getStr()
result.title = root["title"].getStr() result.title = root["title"].getStr()
result.ga = root{"ga"}.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) = proc processGT(n: XmlNode, tag: string): (int, XmlNode, string) =
result = (0, newElement(tag), tag) result = (0, newElement(tag), tag)

View file

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

View file

@ -30,5 +30,18 @@ proc test*(session: Session, baseUrl: string) =
test "can register": test "can register":
with session: with session:
register("test", "test") 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()