Skip to content

Commit aa9db6c

Browse files
Initial Commit
0 parents  commit aa9db6c

32 files changed

+2138
-0
lines changed

LICENSE

+661
Large diffs are not rendered by default.

README.md

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
# StoryFontBackendNim
2+
A re-implementation of the storyfont backend in nim.
3+
The tech stack of this project is:
4+
- Application Server: prologue
5+
- ORM: norm
6+
- JWT-handling: jwt

config/config.nims

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
switch("path", "~/dev/nimstoryfont/../src")

nimstoryfont.nimble

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
# Package
2+
3+
version = "0.1.0"
4+
author = "PhilippMDoerner"
5+
description = "A new awesome nimble package"
6+
license = "GPL-3.0-or-later"
7+
srcDir = "src"
8+
bin = @["nimstoryfont"]
9+
10+
11+
# Dependencies
12+
13+
requires "nim >= 1.6.2"

src/applicationSettings.nim

+82
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
import prologue
2+
import times
3+
4+
#Custom Settings
5+
const database* = "db.sqlite3"
6+
const DEBUG*: bool = true
7+
const ACCESS_TOKEN_LIFETIME*: TimeInterval = hours(1) # 1h in seconds
8+
const REFRESH_TOKEN_LIFETIME*: TimeInterval = days(100) # 100 days in seconds
9+
10+
#Prologue Settings
11+
let coreSettings*: Settings = loadSettings("./settings.json")
12+
13+
const SECRET_KEY*: string = "MyBeautifulSecretKey"
14+
const AUTHORIZATION_HEADER*: string = "Authorization"
15+
16+
17+
#Constants
18+
const PRIMARY_DB_TIME_FORMAT* = "yyyy-MM-dd HH:mm:ss'.'ffffff" #Datetime format as Django stores it in DB
19+
const SECONDARY_DB_TIME_FORMAT* = "yyyy-MM-dd HH:mm:ss" # Datetime format as Django sometimes stores it in DB
20+
const OUTPUT_TIME_FORMAT* = "yyyy-MM-dd'T'HH:mm:ss'.'ffffff'Z'"
21+
22+
###TABLE NAMES
23+
#Auth
24+
const GROUP_TABLE* = "auth_group"
25+
const GROUP_PERMISSION_TABLE* = "auth_group_permission"
26+
const PERMISSION_TABLE* = "auth_permission"
27+
const USER_TABLE* = "auth_user"
28+
const USER_GROUP_TABLE* = "auth_user_groups"
29+
const USER_USERPERMISSIONS_TABLE* = "auth_user_user_permissions"
30+
31+
const TOKEN_TABLE* = "authtoken_token"
32+
const TOKEN_BLACKLIST_TABLE* = "token_blacklist_blacklistedtoken"
33+
const TOKEN_OUTSTANDING_TABLE* = "token_blacklist_outstandingtoken"
34+
35+
#Django
36+
const DJ_ADMIN_LOG_TABLE* = "django_admin_log"
37+
const DJ_CONTENT_TYPE_TABLE* = "django_content_type"
38+
const DJ_MIGRATION_TABLE* = "django_migrations"
39+
const DJ_SESSION_TABLE* = "django_session"
40+
41+
const DJ_GROUPOBJECTPERMISSION* = "guardian_groupobjectpermission"
42+
const DJ_USEROBJECTPERMISSION* = "guardian_userobjectpermission"
43+
44+
#Wikientries
45+
const CAMPAIGN_TABLE* = "wikientries_campaign"
46+
const CHARACTER_TABLE* = "wikientries_character"
47+
const CHARACTER_PLAYERCLASS_TABLE* = "wikientries_characterplayerclassconnection"
48+
const CREATURE_TABLE* = "wikientries_creature"
49+
const DIARYENTRY_TABLE* = "wikientries_diaryentry"
50+
const ENCOUNTER_TABLE* = "wikientries_encounter"
51+
const ENCOUNTER_CHARACTER_TABLE* = "wikientries_encounterconnection"
52+
const IMAGE_TABLE* = "wikientries_image"
53+
const ITEM_TABLE* = "wikientries_item"
54+
const LOCATION_TABLE* = "wikientries_location"
55+
const ORGANIZATION_TABLE* = "wikientries_organization"
56+
const PLAYERCLASS_TABLE* = "wikientries_playerclass"
57+
const QUEST_TABLE* = "wikientries_quest"
58+
const QUOTE_TABLE* = "wikientries_quote"
59+
const QUOTE_CHARACTER_TABLE* = "wikientries_quoteconnection"
60+
const RULES_TABLE* = "wikientries_rules"
61+
const SESSION_TABLE* = "wikientries_session"
62+
const SPELL_TABLE* = "wikientries_spell"
63+
const SPELL_PLAYERCLASS_TABLE* = "wikientries_spellclassconnection"
64+
65+
#Fileserver
66+
const SESSIONAUDIO_TABLE* = "fileserver_sessionaudio"
67+
const TIMESTAMP_TABLE* = "fileserver_sessionaudiotimestamp"
68+
69+
#Map
70+
const MAP_TABLE* = "map_map"
71+
const MARKER_TABLE* = "map_marker"
72+
const MARKERTYPE_TABLE* = "map_markertype"
73+
74+
#Search
75+
const SEARCH_TABLE* = "search_article_content"
76+
const EMPTY_SEARCH_RESPONSE_TABLE* = "wikientries_emptysearchresponse"
77+
78+
#Sqlite
79+
const SQLITE_SEQUENCE_TABLE* = "sqlite_sequence"
80+
81+
#Views
82+
const V_ALL_ARTICLES_TABLE* = "v_all_articles"
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
import prologue
2+
import json
3+
import ../../utils/errorResponses
4+
import myJwt
5+
import ../../utils/database
6+
import authenticationRepository
7+
import authenticationModels
8+
import ../../applicationSettings
9+
import jwt
10+
import nimSHA2
11+
12+
#proc createToken*(ctx: Context) {.async.} =
13+
14+
proc getRefreshToken(ctx: Context): Option[JWT] =
15+
let requestBody: string = ctx.request.body()
16+
let parsedRequestBody: JsonNode = parseJson(requestBody)
17+
let refreshTokenString: string = parsedRequestBody.fields["refresh"].getStr()
18+
19+
result = parseJWT(refreshTokenString)
20+
21+
22+
proc createNextToken(user: User, tokenType: JWTType): JWT =
23+
var newToken: JWT = user.createToken(JWTType.REFRESH)
24+
newToken.sign(applicationSettings.SECRET_KEY)
25+
result = newToken
26+
27+
28+
proc refreshTokens*(ctx: Context) {.async.} =
29+
let refreshTokenOption: Option[JWT] = getRefreshToken(ctx)
30+
if refreshTokenOption.isNone():
31+
resp get401UnauthorizedResponse(ctx)
32+
return
33+
34+
let refreshToken: JWT = refreshTokenOption.get()
35+
if not myJwt.isValidRefreshToken(refreshToken):
36+
resp get401UnauthorizedResponse(ctx)
37+
return
38+
39+
let tokenData: TokenData = extractTokenData(refreshToken)
40+
let user: User = getUserById(tokenData.userId)
41+
42+
let newAccessToken: JWT = createNextToken(user, JWTType.ACCESS)
43+
let newRefreshToken: JWT = createNextToken(user, JWTType.REFRESH)
44+
45+
resp jsonResponse(%*{"refresh": newRefreshToken, "access": newAccessToken})
46+
47+
48+
proc hasMatchingPassword(user: User, password: string): bool=
49+
let hashedPassword = computeSHA256(password, 18000).toHex()
50+
return true
51+
52+
53+
proc login*(ctx: Context) {.async.} =
54+
let requestBody: JsonNode = parseJson(ctx.request.body())
55+
let userName: string = requestBody.fields["username"].getStr()
56+
let user: User = getUserByName(userName)
57+
58+
let plainPassword: string = requestBody.fields["password"].getStr()
59+
if not user.hasMatchingPassword(plainPassword):
60+
resp get401UnauthorizedResponse(ctx)
61+
62+
let newAccessToken: JWT = createNextToken(user, JWTType.ACCESS)
63+
let newRefreshToken: JWT = createNextToken(user, JWTType.REFRESH)
64+
65+
resp jsonResponse(%*{"refresh": newRefreshToken, "access": newAccessToken})
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
import norm/[model, pragmas]
2+
import ../../utils/djangoDateTime/djangoDateTimeType
3+
import ../../applicationSettings
4+
import std/options
5+
6+
7+
type User* {.tableName: USER_TABLE.} = ref object of Model
8+
##[TableModel of the table of creatures ]##
9+
password*: string
10+
last_login*: Option[DjangoDateTime]
11+
is_superuser*: bool
12+
username*: string
13+
last_name*: string
14+
email*: string
15+
is_staff*: bool
16+
is_active*: bool
17+
date_joined*: DjangoDateTime
18+
first_name*: string
19+
20+
21+
type Group* {.tableName: GROUP_TABLE.} = ref object of Model
22+
name*: string
23+
24+
25+
type Permission* {.tableName: PERMISSION_TABLE.} = ref object of Model
26+
content_type_id*: int64
27+
codename*: string
28+
name*: string
29+
30+
31+
type GroupPermission* {.tableName: GROUP_PERMISSION_TABLE.} = ref object of Model
32+
group_id*: int64
33+
permission_id*: int64
34+
35+
36+
type UserGroup* {.tableName: USER_GROUP_TABLE.} = ref object of Model
37+
user_id*: int64
38+
group_id*: int64
39+
40+
41+
type UserPermission* {.tableName: USER_USERPERMISSIONS_TABLE.} = ref object of Model
42+
user_id*: int64
43+
permission_id*: int64
44+
45+
46+
proc newUser(
47+
password = "",
48+
lastLogin = none(DjangoDateTime),
49+
isSuperuser = false,
50+
username = "",
51+
firstName = "",
52+
lastName = "",
53+
email = "",
54+
isStaff = false,
55+
isActive = true,
56+
dateJoined = djangoDateTimeType.now()
57+
): User =
58+
result = User(
59+
password: password,
60+
last_login: lastLogin,
61+
is_superuser: isSuperuser,
62+
username: username,
63+
last_name: lastName,
64+
email: email,
65+
is_staff: isStaff,
66+
is_active: isActive,
67+
date_joined: dateJoined,
68+
first_name: firstName
69+
)
70+
71+
72+
proc newPermission(
73+
contentTypeId = -1,
74+
codename = "",
75+
name = ""
76+
): Permission =
77+
result = Permission(
78+
content_type_id: contentTypeId,
79+
codename: codename,
80+
name: name
81+
)
82+
83+
84+
proc newGroup(name = ""): Group =
85+
result = Group(name: name)
86+
87+
88+
proc newGroupPermission(groupId = -1, permissionId = -1): GroupPermission =
89+
result = GroupPermission(group_id: groupId, permission_id: permissionId)
90+
91+
92+
proc newUserGroup(userId = -1, groupId = -1): UserGroup =
93+
result = UserGroup(user_id: userId, group_id: groupId)
94+
95+
96+
proc newUserPermission(userId = -1, permissionId = -1): UserPermission =
97+
result = UserPermission(user_id: userId, permission_id: permissionId)
98+
99+
proc newTableModel*(T: typedesc[User]): User = newUser()
100+
101+
proc newModel*(T: typedesc[GroupPermission]): GroupPermission = newGroupPermission()
102+
proc newModel*(T: typedesc[UserPermission]): UserPermission = newUserPermission()
103+
proc newModel*(T: typedesc[User]): User = newUser()
104+
proc newModel*(T: typedesc[Group]): Group = newGroup()
105+
proc newModel*(T: typedesc[Permission]): Permission = newPermission()
106+
proc newModel*(T: typedesc[UserGroup]): UserGroup = newUserGroup()
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import ../base_generics/genericArticleRepository
2+
import authenticationModels
3+
4+
5+
proc getUserById*(userId: int64): User =
6+
result = getEntryById[User](userId)
7+
8+
9+
proc getUserByName*(userName: string): User =
10+
result = getEntryByField[User, string]("username", userName)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import prologue
2+
import authenticationControllers
3+
4+
proc addAuthenticationRoutes*(app: Prologue) =
5+
app.addRoute(
6+
re"/token/refresh",
7+
authenticationControllers.refreshTokens,
8+
httpMethod = HttpPost,
9+
)

0 commit comments

Comments
 (0)