4 Commits
0.1.3 ... 0.1.4

Author SHA1 Message Date
9a21e6d20b fixed bugs 2026-02-23 19:31:40 +01:00
639aac68ca added version number to build 2026-02-23 16:11:23 +01:00
4d00936719 Fixed first issue, added release script 2026-02-23 15:19:15 +01:00
b03d9bf998 updated include to be more scoped 2026-02-23 14:08:18 +01:00
30 changed files with 220 additions and 82 deletions

View File

@@ -87,8 +87,13 @@ target_link_options(${TARGET_NAME} PRIVATE
$<$<CONFIG:Release>:-flto=auto>
)
if(NOT DEFINED APP_VERSION)
set(APP_VERSION "0.0.0")
endif()
target_compile_definitions(${TARGET_NAME} PRIVATE
APPLICATION_NAME="${TARGET_NAME}"
APP_VERSION="${APP_VERSION}"
SQLITE_THREADSAFE=1 # build sqlite with thread safty
ASIO_STANDALONE # use asio without boost
CROW_ENABLE_COMPRESSION # enable compression part of crow

View File

@@ -1,7 +1,7 @@
# Maintainer: Lukas Forsberg lukas96.forsberg@gmail.com
pkgname=shadowrun-server
pkgver=0.1.3
pkgver=0.1.4
pkgrel=1
arch=('x86_64')
depends=()
@@ -18,7 +18,8 @@ build() {
cmake -S "${srcdir}" \
-B build \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_INSTALL_PREFIX=/usr
-DCMAKE_INSTALL_PREFIX=/usr \
-DAPP_VERSION=${pkgver}
cmake --build build
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1 @@
import{l as o,a as r}from"../chunks/D_WAtfM3.js";export{o as load_css,r as start};

View File

@@ -1 +0,0 @@
import{l as o,a as r}from"../chunks/niSfElle.js";export{o as load_css,r as start};

View File

@@ -1 +1 @@
import{f as u,a as h}from"../chunks/K5GTgIDA.js";import{i as g}from"../chunks/DgU0EQmz.js";import{z as l,a8 as v,K as d,B as _,D as s,F as e,C as x}from"../chunks/DxMC-E2z.js";import{s as o}from"../chunks/V6M2jInR.js";import{s as $,p}from"../chunks/niSfElle.js";const k={get error(){return p.error},get status(){return p.status}};$.updated.check;const m=k;var b=u("<h1> </h1> <p> </p>",1);function F(i,f){l(f,!1),g();var t=b(),r=v(t),n=s(r,!0);e(r);var a=x(r,2),c=s(a,!0);e(a),d(()=>{o(n,m.status),o(c,m.error?.message)}),h(i,t),_()}export{F as component};
import{f as u,a as h}from"../chunks/K5GTgIDA.js";import{i as g}from"../chunks/DgU0EQmz.js";import{z as l,a8 as v,K as d,B as _,D as s,F as e,C as x}from"../chunks/DxMC-E2z.js";import{s as o}from"../chunks/V6M2jInR.js";import{s as $,p}from"../chunks/D_WAtfM3.js";const k={get error(){return p.error},get status(){return p.status}};$.updated.check;const m=k;var b=u("<h1> </h1> <p> </p>",1);function F(i,f){l(f,!1),g();var t=b(),r=v(t),n=s(r,!0);e(r);var a=x(r,2),c=s(a,!0);e(a),d(()=>{o(n,m.status),o(c,m.error?.message)}),h(i,t),_()}export{F as component};

View File

@@ -1 +1 @@
import{f as w,a as d}from"../chunks/K5GTgIDA.js";import{i as J}from"../chunks/DgU0EQmz.js";import{z as O,A as t,B as P,C as r,D as o,F as i,G as v,I as g,J as b,K as S}from"../chunks/DxMC-E2z.js";import{e as T,s as j}from"../chunks/V6M2jInR.js";import{i as z}from"../chunks/BJWcdj5l.js";import{r as h}from"../chunks/HgGInnYf.js";import{b as _}from"../chunks/Cp1RMksV.js";import{g as A}from"../chunks/niSfElle.js";var B=w('<p class="error svelte-1uha8ag"> </p>'),D=w('<form class="login svelte-1uha8ag"><h2>Login</h2> <label class="svelte-1uha8ag">User <input type="text" required/></label> <label class="svelte-1uha8ag">Password <input type="password" required/></label> <button>Login</button> <!></form>');function M(y,x){O(x,!1);let s=v(""),e=v({username:"",password:""});async function k(){try{const a=await fetch("/login",{method:"POST",headers:{"Content-Type":"application/json"},credentials:"include",body:JSON.stringify(t(e))});if(!a.ok){b(s,await a.text());return}A("/shadowrun")}catch(a){b(s,a.message)}}J();var n=D(),l=r(o(n),2),u=r(o(l));h(u),i(l);var p=r(l,2),f=r(o(p));h(f),i(p);var c=r(p,2),C=r(c,2);{var L=a=>{var m=B(),q=o(m,!0);i(m),S(()=>j(q,t(s))),d(a,m)};z(C,a=>{t(s)&&a(L)})}i(n),_(u,()=>t(e).username,a=>g(e,t(e).username=a)),_(f,()=>t(e).password,a=>g(e,t(e).password=a)),T("click",c,k),d(y,n),P()}export{M as component};
import{f as w,a as d}from"../chunks/K5GTgIDA.js";import{i as J}from"../chunks/DgU0EQmz.js";import{z as O,A as t,B as P,C as r,D as o,F as i,G as v,I as g,J as b,K as S}from"../chunks/DxMC-E2z.js";import{e as T,s as j}from"../chunks/V6M2jInR.js";import{i as z}from"../chunks/BJWcdj5l.js";import{r as h}from"../chunks/HgGInnYf.js";import{b as _}from"../chunks/Cp1RMksV.js";import{g as A}from"../chunks/D_WAtfM3.js";var B=w('<p class="error svelte-1uha8ag"> </p>'),D=w('<form class="login svelte-1uha8ag"><h2>Login</h2> <label class="svelte-1uha8ag">User <input type="text" required/></label> <label class="svelte-1uha8ag">Password <input type="password" required/></label> <button>Login</button> <!></form>');function M(y,x){O(x,!1);let s=v(""),e=v({username:"",password:""});async function k(){try{const a=await fetch("/login",{method:"POST",headers:{"Content-Type":"application/json"},credentials:"include",body:JSON.stringify(t(e))});if(!a.ok){b(s,await a.text());return}A("/shadowrun")}catch(a){b(s,a.message)}}J();var n=D(),l=r(o(n),2),u=r(o(l));h(u),i(l);var p=r(l,2),f=r(o(p));h(f),i(p);var c=r(p,2),C=r(c,2);{var L=a=>{var m=B(),q=o(m,!0);i(m),S(()=>j(q,t(s))),d(a,m)};z(C,a=>{t(s)&&a(L)})}i(n),_(u,()=>t(e).username,a=>g(e,t(e).username=a)),_(f,()=>t(e).password,a=>g(e,t(e).password=a)),T("click",c,k),d(y,n),P()}export{M as component};

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -1 +1 @@
{"version":"1771789536194"}
{"version":"1771871349245"}

View File

@@ -5,11 +5,11 @@
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="icon" type="image/x-icon" href="/favicon.ico" />
<link rel="modulepreload" href="./_app/immutable/entry/start.BnAWgAKt.js">
<link rel="modulepreload" href="./_app/immutable/chunks/niSfElle.js">
<link rel="modulepreload" href="./_app/immutable/entry/start.BWyMcWXp.js">
<link rel="modulepreload" href="./_app/immutable/chunks/D_WAtfM3.js">
<link rel="modulepreload" href="./_app/immutable/chunks/DxMC-E2z.js">
<link rel="modulepreload" href="./_app/immutable/chunks/CgHyU30y.js">
<link rel="modulepreload" href="./_app/immutable/entry/app.CJZl1xEf.js">
<link rel="modulepreload" href="./_app/immutable/entry/app.DShWGRS5.js">
<link rel="modulepreload" href="./_app/immutable/chunks/V6M2jInR.js">
<link rel="modulepreload" href="./_app/immutable/chunks/K5GTgIDA.js">
<link rel="modulepreload" href="./_app/immutable/chunks/BJWcdj5l.js">
@@ -20,15 +20,15 @@
<div style="display: contents">
<script>
{
__sveltekit_q0ydb3 = {
__sveltekit_1wppsc6 = {
base: new URL(".", location).pathname.slice(0, -1)
};
const element = document.currentScript.parentElement;
Promise.all([
import("./_app/immutable/entry/start.BnAWgAKt.js"),
import("./_app/immutable/entry/app.CJZl1xEf.js")
import("./_app/immutable/entry/start.BWyMcWXp.js"),
import("./_app/immutable/entry/app.DShWGRS5.js")
]).then(([kit, app]) => {
kit.start(app, element);
});

View File

@@ -1,5 +0,0 @@
{
"http_port" : 3011,
"db_path": "shadowrun.db",
"domain": "http://192.168.1.101:3011"
}

View File

@@ -5,11 +5,11 @@
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="icon" type="image/x-icon" href="/favicon.ico" />
<link rel="modulepreload" href="./_app/immutable/entry/start.BnAWgAKt.js">
<link rel="modulepreload" href="./_app/immutable/chunks/niSfElle.js">
<link rel="modulepreload" href="./_app/immutable/entry/start.BWyMcWXp.js">
<link rel="modulepreload" href="./_app/immutable/chunks/D_WAtfM3.js">
<link rel="modulepreload" href="./_app/immutable/chunks/DxMC-E2z.js">
<link rel="modulepreload" href="./_app/immutable/chunks/CgHyU30y.js">
<link rel="modulepreload" href="./_app/immutable/entry/app.CJZl1xEf.js">
<link rel="modulepreload" href="./_app/immutable/entry/app.DShWGRS5.js">
<link rel="modulepreload" href="./_app/immutable/chunks/V6M2jInR.js">
<link rel="modulepreload" href="./_app/immutable/chunks/K5GTgIDA.js">
<link rel="modulepreload" href="./_app/immutable/chunks/BJWcdj5l.js">
@@ -20,15 +20,15 @@
<div style="display: contents">
<script>
{
__sveltekit_q0ydb3 = {
__sveltekit_1wppsc6 = {
base: new URL(".", location).pathname.slice(0, -1)
};
const element = document.currentScript.parentElement;
Promise.all([
import("./_app/immutable/entry/start.BnAWgAKt.js"),
import("./_app/immutable/entry/app.CJZl1xEf.js")
import("./_app/immutable/entry/start.BWyMcWXp.js"),
import("./_app/immutable/entry/app.DShWGRS5.js")
]).then(([kit, app]) => {
kit.start(app, element);
});

View File

@@ -1,6 +1,5 @@
<script lang="ts">
import { onMount } from 'svelte';
//import { API_BASE } from '$lib/config';
import { Defaults } from './defaults.svelte';
import type { Skill, Connection} from './types.svelte';
import { autoGrow } from '$lib/common/autogrow';
@@ -24,8 +23,10 @@
characterData.NegativeQualities ??= [];
characterData.PysicalCondition ??= Defaults.PysicalCondition
characterData.StunCondition ??= Defaults.StunCondition
characterData.Inventory ??= {};
characterData.Inventory ??= [];
characterData.Notes ??= {};
characterData.KnowledgeSkills ??= [];
characterData.Specializations ??= [];
let selectedDate : any = null // YYYY-MM-DD format
const characterInfoTypes = {
@@ -211,6 +212,65 @@
</table>
<button on:click={() => add("Skills")}>+</button>
<h2>Specialization</h2>
<table>
<thead>
<tr>
<th>Name</th>
<th>Page</th>
<th></th>
<th></th>
</tr>
</thead>
<tbody>
{#each characterData.Specializations as proficiency, i}
<tr>
<td><textarea use:autoGrow class="input-height" rows="1" bind:value={characterData.Specializations[i].Name}></textarea></td>
<td><input type="number" min=1 max=354 bind:value={characterData.Specializations[i].Page} /></td>
<td><button on:click={() => viewPage(characterData.Specializations[i].Page)}>View</button></td>
<td><button class="red-button" on:click={() => remove("Specializations", i)}>X</button></td>
</tr>
{/each}
</tbody>
</table>
<button on:click={() => add("Specializations")}>+</button>
<h2>Knowledge Skills</h2>
<table>
<thead>
<tr>
<th>Name</th>
<th>Rating</th>
<th>Attribute</th>
<th>Dice</th>
<th>Page</th>
<th></th>
<th></th>
</tr>
</thead>
<tbody>
{#each characterData.KnowledgeSkills as skill, i}
<tr>
<td><textarea use:autoGrow class="input-height" rows="1" bind:value={characterData.KnowledgeSkills[i].Name}></textarea></td>
<td><input type="number" min=0 max=100 bind:value={characterData.KnowledgeSkills[i].Rating} /></td>
<td><select bind:value={characterData.KnowledgeSkills[i].Attribute}>
{#each Object.keys(Defaults.Attributes) as attr}
<option value={attr}>{attr}</option>
{/each}
</select></td>
<td><span>{skill.Rating + characterData.Attributes[skill.Attribute]}</span></td>
<td><input type="number" min=1 max=354 bind:value={characterData.KnowledgeSkills[i].Page} /></td>
<td><button on:click={() => viewPage(characterData.KnowledgeSkills[i].Page)}>View</button></td>
<td><button class="red-button" on:click={() => remove("KnowledgeSkills", i)}>X</button></td>
</tr>
{/each}
</tbody>
</table>
<button on:click={() => add("KnowledgeSkills")}>+</button>
<h2>Contacts</h2>
<table>
<thead>
@@ -262,8 +322,8 @@
<td><input type="number" min=0 max=100 bind:value={characterData.RangedWeapons[i].RC} /></td>
<td><input type="number" min=0 max=9999 bind:value={characterData.RangedWeapons[i].Ammo} /></td>
<td><textarea use:autoGrow class="input-height" style="width: 3em;" rows="1" bind:value={characterData.RangedWeapons[i].Availabiliy}></textarea></td>
<td><input type="number" min=1 max=354 bind:value={characterData.Connections[i].Page} /></td>
<td><button on:click={() => viewPage(characterData.Connections[i].Page)}>View</button></td>
<td><input type="number" min=1 max=354 bind:value={characterData.RangedWeapons[i].Page} /></td>
<td><button on:click={() => viewPage(characterData.RangedWeapons[i].Page)}>View</button></td>
<td><button class="red-button" on:click={() => remove("RangedWeapons", i)}>X</button></td>
</tr>
{/each}
@@ -297,8 +357,8 @@
<td><input type="number" min=0 max=999 bind:value={characterData.MeleeWeapons[i]["Strength Multiplier"]} /></td>
<td><span> {(weapon["Strength Multiplier"] * characterData.Attributes.Strength) + weapon.Damage }</span></td>
<td><input type="number" min=0 max=100 bind:value={characterData.MeleeWeapons[i].AP} /></td>
<td><input type="number" min=1 max=354 bind:value={characterData.Connections[i].Page} /></td>
<td><button on:click={() => viewPage(characterData.Connections[i].Page)}>View</button></td>
<td><input type="number" min=1 max=354 bind:value={characterData.MeleeWeapons[i].Page} /></td>
<td><button on:click={() => viewPage(characterData.MeleeWeapons[i].Page)}>View</button></td>
<td><button class="red-button" on:click={() => remove("MeleeWeapons", i)}>X</button></td>
</tr>
{/each}
@@ -339,11 +399,12 @@
<tr>
<th>Cyberware</th>
<th>Rating</th>
<th>Capacity</th>
<th>Essence</th>
<th>Notes</th>
<th>Page</th>
<th></th>
<th></th> <!-- for remove button -->
<th></th>
</tr>
</thead>
<tbody>
@@ -351,10 +412,11 @@
<tr>
<td><input placeholder="Cyberware" bind:value={characterData.Cyberware[i].Implant} /></td>
<td><input type="number" min=0 max=100 bind:value={characterData.Cyberware[i].Rating} /></td>
<td><input type="number" min=0 max=100 bind:value={characterData.Cyberware[i].Capacity} /></td>
<td><input type="number" min=0 max=100 bind:value={characterData.Cyberware[i].Essence} /></td>
<td><input placeholder="Notes" bind:value={characterData.Cyberware[i].Notes} /></td>
<td><input type="number" min=1 max=354 bind:value={characterData.Connections[i].Page} /></td>
<td><button on:click={() => viewPage(characterData.Connections[i].Page)}>View</button></td>
<td><input type="number" min=1 max=354 bind:value={characterData.Cyberware[i].Page} /></td>
<td><button on:click={() => viewPage(characterData.Cyberware[i].Page)}>View</button></td>
<td><button class="red-button" on:click={() => remove("Cyberware", i)}>X</button></td>
</tr>
{/each}
@@ -368,6 +430,7 @@
<tr>
<th>Bioware</th>
<th>Rating</th>
<th>Capacity</th>
<th>Essence</th>
<th>Notes</th>
<th>Page</th>
@@ -379,11 +442,12 @@
{#each characterData.Bioware as Bioware, i}
<tr>
<td><input placeholder="Bioware" bind:value={characterData.Bioware[i].Implant} /></td>
<td><input type="number" min="0" bind:value={characterData.Bioware[i].Rating} /></td>
<td><input type="number" min="0" bind:value={characterData.Bioware[i].Essence} /></td>
<td><input type="number" min=0 max=100 bind:value={characterData.Bioware[i].Rating} /></td>
<td><input type="number" min=0 max=100 bind:value={characterData.Bioware[i].Capacity} /></td>
<td><input type="number" min=0 max=100 bind:value={characterData.Bioware[i].Essence} /></td>
<td><input placeholder="Notes" bind:value={characterData.Bioware[i].Notes} /></td>
<td><input type="number" min=1 max=354 bind:value={characterData.Connections[i].Page} /></td>
<td><button on:click={() => viewPage(characterData.Connections[i].Page)}>View</button></td>
<td><input type="number" min=1 max=354 bind:value={characterData.Bioware[i].Page} /></td>
<td><button on:click={() => viewPage(characterData.Bioware[i].Page)}>View</button></td>
<td><button class="red-button" on:click={() => remove("Bioware", i)}>X</button></td>
</tr>
{/each}
@@ -423,7 +487,7 @@
<th>Quality</th>
<th>Page</th>
<th></th>
<th></th> <!-- for remove button -->
<th></th>
</tr>
</thead>
<tbody>
@@ -491,8 +555,8 @@
{#each characterData.Inventory as inventory, i}
<tr>
<td><input placeholder="Item" bind:value={characterData.Inventory[i].Item} /></td>
<td><input type="number" min=1 max=354 bind:value={characterData.NegativeQualities[i].Quantity} /></td>
<td><input placeholder="Notes" bind:value={characterData.NegativeQualities[i].Notes} /></td>
<td><input type="number" min=1 max=354 bind:value={characterData.Inventory[i].Quantity} /></td>
<td><input placeholder="Notes" bind:value={characterData.Inventory[i].Notes} /></td>
<td><input type="number" min=1 max=354 bind:value={characterData.Inventory[i].Page} /></td>
<td><button on:click={() => viewPage(characterData.Inventory[i].Page)}>View</button></td>
<td><button class="red-button" on:click={() => remove("Inventory", i)}>X</button></td>

View File

@@ -30,7 +30,13 @@ const Attributes = {
const Skill = {
Name: "",
Rating: 0,
Attribute: Object.keys(Attributes)[0]
Attribute: Object.keys(Attributes)[0],
Page: 1,
}
const Specialization = {
Name: "",
Page: 1,
}
const Connection = {
@@ -48,6 +54,7 @@ const RangedWeapon = {
RC: 0,
Ammo: 0,
Availabiliy: "",
Page: 1,
}
const MeleeWeapon = {
@@ -56,17 +63,21 @@ const MeleeWeapon = {
Damage: 1,
"Strength Multiplier" : 0.5,
AP: 0,
Page: 1,
};
const Implant = {
Implant: "",
Rating: 0,
Capacity: 0,
Essence: 0,
Notes: "",
Page: 1,
}
const Qualitiy = {
Qualitiy : ""
Qualitiy : "",
Page: 1,
}
const PysicalCondition = Array.from({ length: 6 }, () =>
@@ -78,20 +89,23 @@ const StunCondition = Array.from({ length: 4 }, () =>
const Armor = {
Armor: "",
Ballistic: 0,
Impact: 0
Impact: 0,
Page: 1,
}
const Inventory = {
Item: "",
Quantity: 1,
Notes: "",
Page: 1
Page: 1,
}
export const Defaults = {
Info: Info,
Attributes: Attributes,
Skills: Skill,
Specializations: Specialization,
KnowledgeSkills: Skill,
Connections: Connection,
RangedWeapons : RangedWeapon,
MeleeWeapons : MeleeWeapon,

29
release.sh Executable file
View File

@@ -0,0 +1,29 @@
# get the varaibles from PKGBUILD
source ./PKGBUILD
# assets to pack in the tar ball
ASSETS=(
"source/"
"modules/"
"assets/"
"frontend/build/"
"shadowrun-server.service"
"CMakeLists.txt"
"shadowrun-server.install"
)
# create the tar ball
tar czf ${pkgname}-${pkgver}.tar.gz "${ASSETS[@]}"
# create the package
makepkg -f
# create the release directory and store all files there
RELEASE_DIR="release-${pkgver}/"
mkdir -p ${RELEASE_DIR}
mv ${pkgname}-${pkgver}.tar.gz ${RELEASE_DIR}
mv ${pkgname}-${pkgver}-1-x86_64.pkg.tar.zst ${RELEASE_DIR}
mv ${pkgname}-debug-${pkgver}-1-x86_64.pkg.tar.zst ${RELEASE_DIR}
mv src/ ${RELEASE_DIR}
#scp ${RELEASE_DIR}${pkgname}-${pkgver}-1-x86_64.pkg.tar.zst lukas@192.168.1.101:/home/lukas/Drive/archrepo/x86_64/

26
source/Application.hpp Normal file
View File

@@ -0,0 +1,26 @@
#ifndef __APPVERSION_H__
#define __APPVERSION_H__
#include <string>
namespace Application {
#ifndef APP_VERSION
#define APP_VERSION "0.0.0"
#endif
#ifndef APPLICATION_NAME
#define APPLICATION_NAME "app"
#endif
inline std::string version(){
return std::string(APP_VERSION);
}
inline std::string name(){
return std::string(APPLICATION_NAME);
}
}
#endif // __APPVERSION_H__

View File

@@ -1,8 +1,8 @@
#include <fstream>
#include "json.hpp"
#include "json_settings.h"
#include "crow/logging.h"
#include "utils.hpp"
#include <iostream>
using namespace std;
using json = nlohmann::json;
@@ -19,7 +19,7 @@ Settings AppSettings::deafult(){
Settings AppSettings::load() {
ifstream file(settingsFile);
if (!file.is_open()) {
CROW_LOG_ERROR << "Failed to load settings file" << settingsFile << " Loading default settings";
std::cerr << "Failed to load settings file" << settingsFile << " Loading default settings" << std::endl;
return AppSettings::deafult();
}
@@ -29,14 +29,14 @@ Settings AppSettings::load() {
auto result = utils::parseJson(fileContents);
if(!result){
CROW_LOG_ERROR << "failed to parse settings file, Loading default settings";
std::cerr << "failed to parse settings file, Loading default settings" << std::endl;
return AppSettings::deafult();
}
try {
return result.value().get<Settings>();
} catch (...) {
CROW_LOG_ERROR << "failed to parse settings file, Loading default settings";
std::cerr << "failed to parse settings file, Loading default settings";
return AppSettings::deafult();
}
}

View File

@@ -3,7 +3,6 @@
#include "json.hpp"
#include <string>
namespace AppSettings {
static constexpr char settingsFile[] = "assets/settings.json";

View File

@@ -1,15 +1,13 @@
#include "login.hpp"
#include "crow/http_response.h"
#include "databasepool.h"
#include "SessionHandler.hpp"
#include <optional>
namespace login
{
SessionHandler sessionHandler;
std::string getSessionId(const crow::request& req) {
static std::string getSessionId(const crow::request& req) {
auto cookie_header = req.get_header_value("Cookie");
std::string prefix = "session_id=";
auto pos = cookie_header.find(prefix);
@@ -24,6 +22,15 @@ static crow::response redirectToLogin(){
return res;
}
static std::optional<std::string> loginUser(const std::string& username, const std::string& password)
{
auto user = getVerifiedUser(username, password);
if (user) {
return sessionHandler.createSession(user->id);
}
return {};
}
std::optional<crow::response> isLoggedIn(const crow::request& req) {
std::string sessionId = getSessionId(req);
if (sessionId.empty())
@@ -36,15 +43,6 @@ std::optional<crow::response> isLoggedIn(const crow::request& req) {
return {};
}
std::optional<std::string> loginUser(const std::string& username, const std::string& password)
{
auto user = getVerifiedUser(username, password);
if (user) {
return sessionHandler.createSession(user->id);
}
return {};
}
void initLogin(crow::App<crow::CORSHandler>& app){
createUser("lukas", "Trollar4928");

View File

@@ -3,7 +3,8 @@
#pragma once
#include <crow.h>
#include <crow/http_response.h>
#include <crow/app.h>
#include "crow/middlewares/cors.h"
namespace login {

View File

@@ -5,6 +5,7 @@
#include <vector>
#include "json.hpp"
#include "utils.hpp"
namespace login
{

View File

@@ -7,18 +7,21 @@
#include "ShadowrunApi.hpp"
#include "databasepool.h"
#include "crow/compression.h"
#include "Application.hpp"
using namespace std;
int main() {
std::cout << "Launching " << Application::name() << " version: " << Application::version() << std::endl;
AppSettings::Settings settings = AppSettings::load();
crow::App<crow::CORSHandler> app;
// init cors
auto& cors = app.get_middleware<crow::CORSHandler>();
cors.global()
.headers("Content-Type", "Authorization")
.methods("GET"_method, "POST"_method, "PUT"_method, "DELETE"_method, "OPTIONS"_method)
.headers("Content-Type", "Authorization")
.methods("GET"_method, "POST"_method, "PUT"_method, "DELETE"_method, "OPTIONS"_method)
.allow_credentials()
.origin(settings.domain)
.max_age(86400);
@@ -26,20 +29,20 @@ int main() {
// create global database
dbpool = std::make_unique<DatabasePool>(settings.db_path);
if (!dbpool->init(std::thread::hardware_concurrency())){
CROW_LOG_ERROR << "Failed to create database at : " << settings.db_path;
return 1;
std::cerr << "Failed to create database at : " << settings.db_path << std::endl;
std::exit(1);
}
auto opt_isPortOpen = utils::isLocalPortOpen(settings.http_port);
if (opt_isPortOpen.has_value()){
if (opt_isPortOpen.value()){
CROW_LOG_ERROR << "Local port : " << settings.http_port << " is already open";
return 1;
std::cerr << "Local port : " << settings.http_port << " is already open" << std::endl;
std::exit(1);
}
}
else {
CROW_LOG_ERROR << "failed to check if local port is open : " << opt_isPortOpen.error();
return 1;
std::cerr << "failed to check if local port is open : " << opt_isPortOpen.error() << std::endl;
std::exit(1);
}
// Root route

View File

@@ -3,6 +3,7 @@
#include "ShadowrunApi.hpp"
#include "ShadowrunDb.hpp"
#include "login.hpp"
#include "magic_enum.hpp"
#include <vector>
using namespace std;

View File

@@ -1,7 +1,7 @@
#ifndef __SHADOWRUNAPI_H__
#define __SHADOWRUNAPI_H__
#include "crow.h"
#include "crow/app.h"
#include "crow/middlewares/cors.h"
namespace shadowrun {

View File

@@ -1,6 +1,7 @@
#include "ShadowrunDb.hpp"
#include <optional>
#include "databasepool.h"
#include "magic_enum.hpp"
#include "utils.hpp"
#include "crow/logging.h"

View File

@@ -7,8 +7,6 @@
#include <optional>
#include "json.hpp"
#include "utils.hpp"
#include "sqlite_orm.h"
#include "magic_enum.hpp"
namespace shadowrun {
enum class Type {
@@ -25,6 +23,8 @@ namespace shadowrun {
NegativeQualities = 10,
Notes = 11,
Inventory = 12,
KnowledgeSkills = 13,
Specializations = 14,
};
struct ShadowrunCharacter {

View File

@@ -7,7 +7,7 @@
#include <filesystem>
#include <expected>
#include "json.hpp"
#include "crow.h"
#include "crow/http_response.h"
namespace utils {
// Svelte genereated files