diff --git a/html/src/main.js b/html/src/main.js
index a9b7baa..12cb5f6 100755
--- a/html/src/main.js
+++ b/html/src/main.js
@@ -41,4 +41,6 @@ window.addListener('popupError', (data)=>{
window.addListener('popupColor', (data)=>{
window.utils.addPopup(data.data.color, data.data.isDark, data.data.title, data.data.msg)
-})
\ No newline at end of file
+})
+
+window.main()
\ No newline at end of file
diff --git a/html/src/packets.js b/html/src/packets.js
index de4782a..d9335e9 100755
--- a/html/src/packets.js
+++ b/html/src/packets.js
@@ -14,6 +14,7 @@ function getErrorDesc(error){
utils.setCookie('session', '')
return 'Some part of the login request is invalid, please try again'
case 'prelogin':
+ window.location.pathname = '/'
return 'You are already logged in'
}
return error
@@ -32,6 +33,8 @@ function processData(data){
utils.iconauth()
}
break
+ case 'redir':
+ window.location.pathname = data.location
case 'data':
console.log(data.data)
break
diff --git a/html/src/style.css b/html/src/style.css
index a96af1b..f57e778 100755
--- a/html/src/style.css
+++ b/html/src/style.css
@@ -56,6 +56,21 @@ body {
font-family: var(--font);
}
+.half-left {
+ position: relative;
+ display: inline-block;
+ width: 45%;
+ margin-right: calc(4%);
+}
+
+.half-right {
+ position: relative;
+ display: inline-block;
+ width: 44%;
+ margin-left: 4%;
+}
+
+
.navbar {
position: fixed;
top:0;
@@ -202,7 +217,7 @@ li::marker {
width: var(--popupBoxWidth);
height: calc(100% - var(--topnavheight) - 10px);
- pointer-events:none;
+ pointer-events: none;
bottom: 0;
right: 20px;
overflow: auto;
@@ -225,7 +240,7 @@ li::marker {
padding: 0;
background-color: inherit;
- pointer-events:all;
+ pointer-events: all;
left: 0;
margin: 0;
@@ -254,10 +269,11 @@ li::marker {
opacity: 1;
}
-.popupBox article a {
+dialog article a {
cursor: pointer;
}
+
.popupBox article p {
font-size: 15px;
}
diff --git a/html/src/utils.js b/html/src/utils.js
index 07e15ba..6dc1bb0 100755
--- a/html/src/utils.js
+++ b/html/src/utils.js
@@ -1,3 +1,5 @@
+export const getEl = (id)=>{return document.getElementById(id)}
+
export const setCookie = (name, value, hours = 1, path = '/') => {
const expires = new Date(Date.now() + hours * 6e4).toUTCString()
document.cookie = `${name}=${encodeURIComponent(value)}; path=${path}; SameSite=None; secure=True; session=True`
@@ -64,6 +66,21 @@ export function iconauth() {
// }
+export function modal(elem, identifier, bgcolor, header, textColor, title, innerHTML) {
+ elem.innerHTML += `
+
+
+
+ ${innerHTML}
+
+
+ `
+}
+
export function addPopup(bgcolor, isDark, title, content) {
const elem = document.getElementById('popupBox')
let header
@@ -75,18 +92,8 @@ export function addPopup(bgcolor, isDark, title, content) {
header = 'rgba(0,0,0,0.2)'
textColor = 'text-black'
}
- elem.innerHTML += `
-
-
-
- ${content}
-
-
- `
+ modal(elem, "document.getElementById('popupBox')", bgcolor, header, textColor, title, `
${content}
`)
+
}
export function popupInfo(title, text){
@@ -105,12 +112,27 @@ export function popupError(title, text){
addPopup('#500000', true, title, text)
}
+export function confirmBox(bgcolor, isDark, title, yesFunc, noFunc) {
+ const elem = document.body
+ let header
+ let textColor
+ if(isDark){
+ header = 'rgba(255,255,255,0.05)'
+ textColor = 'text-white'
+ }else{
+ header = 'rgba(0,0,0,0.2)'
+ textColor = 'text-black'
+ }
+ modal(elem, 'document.body', bgcolor, header, textColor, title, `
+ Yes
+ No `)
+}
export function getUnixTime() {
return (+ new Date())
}
-function formatTime(Millis){
+export function formatTime(Millis){
const date = new Date(Millis)
if(date.getDate() != (new Date()).getDate()){
diff --git a/main.py b/main.py
index 6a682db..eb8ddaa 100755
--- a/main.py
+++ b/main.py
@@ -16,13 +16,13 @@ def main():
if input("No credentials file was found, \nwould you like to create one? (Y/n): ").lower() in ["yes", "y", ""]:
utils.writeFile('data/creds.json', utils.genDefaultAccounts())
- if webserv.secure and ( not utils.pathExists('data/selfsign.crt') or not utils.pathExists('data/selfsign.key') ):
+ if webserv.secure and ( not utils.pathExists('data/ssl.crt') or not utils.pathExists('data/ssl.key') ):
if input("No ssl key/cert was found, \nwould you like to create them? (Y/n): ").lower() in ["yes", "y", ""]:
- if not utils.pathExists('data/selfsign.key'):
+ if not utils.pathExists('data/ssl.key'):
utils.genKey(utils.getRoot('data/'))
- if not utils.pathExists('data/selfsign.crt'):
+ if not utils.pathExists('data/ssl.crt'):
utils.genCert(utils.getRoot('data/'))
moduleMaster.addModules(webserv)
diff --git a/modules/chat/chat.html b/modules/chat/chat.html
new file mode 100644
index 0000000..411c45c
--- /dev/null
+++ b/modules/chat/chat.html
@@ -0,0 +1,33 @@
+
+
+
+
+
+
+This is an example chat module
+
+
\ No newline at end of file
diff --git a/modules/chat/main.py b/modules/chat/main.py
new file mode 100644
index 0000000..b27a687
--- /dev/null
+++ b/modules/chat/main.py
@@ -0,0 +1,12 @@
+mm = None
+
+def test(ac, data):
+ mm.sendPopupColor(ac.rawClient, 'test!', 'test!', '#600060', True)
+
+def init(moduleMaster):
+ global mm
+ mm = moduleMaster
+ mm.addAuthEventListener('exampleTest', test)
+
+def main():
+ pass
\ No newline at end of file
diff --git a/modules/chat/module.json b/modules/chat/module.json
new file mode 100644
index 0000000..881a6d3
--- /dev/null
+++ b/modules/chat/module.json
@@ -0,0 +1,20 @@
+{
+ "name": "chat",
+ "creators": ["ASTATIN3"],
+ "version": "1.0",
+ "entrypoint": "modules/chat/main.py",
+ "tabs": [
+ {
+ "name": "chat",
+ "defaultPage": "chat",
+ "pages": [
+ {
+ "type": "page",
+ "name": "chat",
+ "requiredPermGroup": "",
+ "location": "modules/chat/chat.html"
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file
diff --git a/modules/example/example.html b/modules/example/example.html
new file mode 100644
index 0000000..f23c222
--- /dev/null
+++ b/modules/example/example.html
@@ -0,0 +1,11 @@
+This is a very simple example module!
+test!
+
\ No newline at end of file
diff --git a/modules/example/main.py b/modules/example/main.py
new file mode 100644
index 0000000..b27a687
--- /dev/null
+++ b/modules/example/main.py
@@ -0,0 +1,12 @@
+mm = None
+
+def test(ac, data):
+ mm.sendPopupColor(ac.rawClient, 'test!', 'test!', '#600060', True)
+
+def init(moduleMaster):
+ global mm
+ mm = moduleMaster
+ mm.addAuthEventListener('exampleTest', test)
+
+def main():
+ pass
\ No newline at end of file
diff --git a/modules/example/module.json b/modules/example/module.json
new file mode 100644
index 0000000..3d21a3e
--- /dev/null
+++ b/modules/example/module.json
@@ -0,0 +1,20 @@
+{
+ "name": "example",
+ "creators": ["ASTATIN3"],
+ "version": "1.0",
+ "entrypoint": "modules/example/main.py",
+ "tabs": [
+ {
+ "name": "example",
+ "defaultPage": "example",
+ "pages": [
+ {
+ "type": "page",
+ "name": "example",
+ "requiredPermGroup": "",
+ "location": "modules/example/example.html"
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file
diff --git a/modules/main/Dashboard-copy.html b/modules/main/Dashboard-copy.html
deleted file mode 100644
index caa5726..0000000
--- a/modules/main/Dashboard-copy.html
+++ /dev/null
@@ -1 +0,0 @@
-Test123123!
\ No newline at end of file
diff --git a/modules/main/adminSettings.html b/modules/main/adminSettings.html
new file mode 100644
index 0000000..1f00026
--- /dev/null
+++ b/modules/main/adminSettings.html
@@ -0,0 +1,11 @@
+Test!
+test!
+
\ No newline at end of file
diff --git a/modules/main/main.py b/modules/main/main.py
index fa1eb15..b1cc43a 100644
--- a/modules/main/main.py
+++ b/modules/main/main.py
@@ -1,14 +1,43 @@
-from modules.main import test as test
-
mm = None
-def test1(ac, data):
- mm.sendPopupColor(ac.rawClient, 'test!', 'test!', '#600060', True)
+def logout(ac, data):
+ ac.send('redir', {
+ "location": "/"
+ })
+ mm.authServer.unauth(ac)
+
+def loadSessions(ac):
+ obj = []
+ for client in mm.authServer.clients:
+ if client.user != ac.user:
+ continue
+ obj.append({
+ 'username': client.username,
+ 'address': client.rawClient.address,
+ 'currentPage': client.currentPage,
+ 'clientid': client.rawClient.clientid,
+ 'timeout': client.timeout
+ })
+ # obj.append(client.session)
+ ac.send('sessions', obj)
+
+def unauth(ac, data):
+ removeClient = mm.getAuthClientByID(data['data'])
+ if removeClient == None:
+ return
+ if removeClient.user == ac.user:
+ removeClient.send('redir', {
+ "location": "/"
+ })
+ mm.unauth(removeClient)
+ loadSessions(ac)
def init(moduleMaster):
global mm
mm = moduleMaster
- mm.addAuthEventListener('test1', test1)
+ mm.addAuthEventListener('logout', logout)
+ mm.addAuthEventListener('unauth', unauth)
+ mm.addPageEventListener('/main/User', loadSessions)
def main():
pass
\ No newline at end of file
diff --git a/modules/main/module.json b/modules/main/module.json
index b6f540c..18ac352 100644
--- a/modules/main/module.json
+++ b/modules/main/module.json
@@ -11,27 +11,30 @@
{
"type": "page",
"name": "dashboard",
+ "requiredPermGroup": "",
"location": "modules/main/Dashboard.html"
},
{
"type": "folder",
- "name": "folder 1",
+ "name": "Settings",
"pages": [
{
"type": "page",
- "name": "dashboardcopy",
- "location": "modules/main/Dashboard-copy.html"
+ "name": "User",
+ "requiredPermGroup": "",
+ "location": "modules/main/userSettings.html"
},
{
- "type": "folder",
- "name": "folder 2",
- "pages": [
- {
- "type": "page",
- "name": "dashboardcopy",
- "location": "modules/main/Dashboard-copy.html"
- }
- ]
+ "type": "page",
+ "name": "Program",
+ "requiredPermGroup": "Admin",
+ "location": "modules/main/programSettings.html"
+ },
+ {
+ "type": "page",
+ "name": "Admin",
+ "requiredPermGroup": "Admin",
+ "location": "modules/main/adminSettings.html"
}
]
}
diff --git a/modules/main/programSettings.html b/modules/main/programSettings.html
new file mode 100644
index 0000000..1f00026
--- /dev/null
+++ b/modules/main/programSettings.html
@@ -0,0 +1,11 @@
+Test!
+test!
+
\ No newline at end of file
diff --git a/modules/main/test.py b/modules/main/test.py
deleted file mode 100644
index bdcaa13..0000000
--- a/modules/main/test.py
+++ /dev/null
@@ -1,2 +0,0 @@
-def test():
- return "testsjdhgkjrhsgkhjertestsjdhgkjrhsgkhjertestsjdhgkjrhsgkhjer"
\ No newline at end of file
diff --git a/modules/main/userSettings.html b/modules/main/userSettings.html
new file mode 100644
index 0000000..3985015
--- /dev/null
+++ b/modules/main/userSettings.html
@@ -0,0 +1,86 @@
+
+ User Settings
+ Sessions
+
+
+
+ Username
+ Address
+ Path
+ Expires
+ Remove
+
+
+
+
+ Change Password
+ Logout
+
+
+
\ No newline at end of file
diff --git a/src/auth.py b/src/auth.py
index c508127..6c705ad 100755
--- a/src/auth.py
+++ b/src/auth.py
@@ -18,14 +18,16 @@ class authClient:
def __init__(self):
self.username = None
self.session = utils.randID(32)
- self.userData = None
+ self.currentPage = "/login"
+ self.user = None
self.timeout = utils.getUnixTime() + (60 * 60 * 1000)
self.loginTime = utils.getUnixTime()
self.lastReauth = utils.getUnixTime()
self.rawClient = None
- def send(type, data):
+
+ def send(self, type, data):
self.rawClient.send(type, data)
class authServer:
@@ -37,6 +39,8 @@ class authServer:
self.webserv = webserv
+ self.pageListeners = []
+
self.reloadUsers()
self.rawServer = webserv.rawServer
self.initRawServer()
@@ -67,13 +71,14 @@ class authServer:
ac = authClient()
ac.username = validAcc.username
- ac.userData = validAcc
+ ac.user = validAcc
ac.rawClient = c
self.clients.append(ac)
c.send('loginSuccess', {
'username': ac.username,
+ 'permGroups': ac.user.permGroups,
'session': ac.session,
'redir': f'/{self.webserv.defaultTab}/{self.webserv.defaultPage}',
'timeout': ac.timeout
@@ -87,6 +92,8 @@ class authServer:
def validAc(self, ac):
if ac == None:
return False
+ if not (ac in self.clients):
+ return False
if ac.rawClient.address != request.remote_addr:
return False
if utils.getUnixTime() > ac.timeout:
@@ -106,10 +113,16 @@ class authServer:
ac.rawClient = c
ac.lastReauth = utils.getUnixTime()
- c.send('reauth', {
- 'username': ac.username
+ ac.send('reauth', {
+ 'username': ac.username,
+ 'permGroups': ac.user.permGroups,
+ 'timeout': ac.timeout
})
+ for pageListener in self.pageListeners:
+ if pageListener['page'] == ac.currentPage:
+ pageListener['func'](ac)
+
def cookieLogin(self, request):
session = request.cookies.get('session')
if session == None:
@@ -117,8 +130,37 @@ class authServer:
ac = utils.getatribinarr(self.clients, 'session', session)
- return self.validAc(ac)
+ if not self.validAc(ac):
+ return False
+ ac.currentPage = request.path
+
+ return True
+
+ def validPermGroup(self, group, request):
+ session = request.cookies.get('session')
+ if session == None:
+ return False, None
+
+ ac = utils.getatribinarr(self.clients, 'session', session)
+
+ if not self.validAc(ac):
+ return False, None
+ if (group != "") and not (group in ac.user.permGroups):
+ return False, None
+ return True, ac.user.permGroups
+
+ # def validPermGroupfromSession(self, group, request):
+
+
+ # def logout(self, ac):
+ # if not self.validAc(ac):
+ # return False
+ # self.clients.remove(ac)
+ # return True
+
+ def unauth(self, ac):
+ self.clients.remove(ac)
def initRawServer(self):
self.rawServer.addEventListener('login', self.login)
diff --git a/src/modules.py b/src/modules.py
index ece8362..4cc97cb 100644
--- a/src/modules.py
+++ b/src/modules.py
@@ -1,6 +1,7 @@
import json
import importlib
import sys
+import multiprocessing as mupr
import src.web as web
import src.utils as utils
@@ -9,6 +10,7 @@ class module():
def __init__(self):
self.name = None
self.module = None
+ self.proc = None
self.rootdir = None
self.tabs = []
@@ -19,10 +21,15 @@ class module():
self.module = module
def init(self, moduleMaster):
- self.module.init(moduleMaster)
+ self.module.init(moduleMaster)
+ self.proc = mupr.Process(target=self.module.main)
def run(self):
- self.module.main()
+ self.proc.start()
+
+ def stop(self):
+ self.proc.stop()
+
class moduleMaster():
@@ -33,6 +40,9 @@ class moduleMaster():
self.app = None
self.rawServer = None
self.authServer = None
+ self.defaultPage = ""
+ self.vars = {}
+
# self.addRawEventListener('test1', test1)
def addModules(self, webserv):
@@ -67,6 +77,7 @@ class moduleMaster():
else:
mpage = web.webpage()
mpage.name = obj['name']
+ mpage.requiredPermGroup = obj['requiredPermGroup']
mpage.location = obj['location']
tmpPages.append(mpage)
return tmpPages
@@ -83,8 +94,8 @@ class moduleMaster():
m.add()
self.modules.append(m)
- for tab in webserv.webtabs:
- tab.addHtml()
+ # for tab in webserv.webtabs:
+ # tab.compileHtml('User')
@@ -94,6 +105,8 @@ class moduleMaster():
self.rawServer = webserv.rawServer
self.authServer = webserv.authServer
+ self.defaultPage = f'/{webserv.defaultTab}/{webserv.defaultPage}'
+
for module in self.modules:
module.init(self)
@@ -101,6 +114,11 @@ class moduleMaster():
for module in self.modules:
module.run()
+ def runModules(self):
+ for module in self.modules:
+ module.run()
+
+
@@ -139,6 +157,25 @@ class moduleMaster():
return None
return utils.getatribinarr(self.authServer.clients, 'rawClient', c)
+ def addPageEventListener(self, page, func):
+ self.authServer.pageListeners.append({
+ 'page': page,
+ 'func': func
+ })
+
+
+
+ def getVar(self, varName):
+ return self.vars[varname]
+
+ def setVar(self, varName, val):
+ self.vars[varName] = val
+
+
+ def unauth(self, ac):
+ self.authServer.unauth(ac)
+
+
def sendPopupInfo(self, c, title, msg):
c.send('popupInfo', {
'title': title,
diff --git a/src/utils.py b/src/utils.py
index 5350188..c459e21 100755
--- a/src/utils.py
+++ b/src/utils.py
@@ -99,10 +99,10 @@ def genDefaultAccounts():
], sort_keys=True, indent=2)
def genKey(path):
- subprocess.run(['openssl', 'genrsa', '-out', f'{path}selfsign.key', '2048'])
+ subprocess.run(['openssl', 'genrsa', '-out', f'{path}ssl.key', '2048'])
def genCert(path):
- writeFile(f'{path}/selfsign.cnf',
+ writeFile(f'{path}/ssl.cnf',
"""[req]
default_bits = 2048
prompt = no
@@ -117,8 +117,8 @@ OU = www.ca.local
CN = Self-Signed Root CA
""")
- subprocess.run(['openssl', 'req', '-new', '-key', f'{path}selfsign.key', '-out', f'{path}selfsign.csr', '-config', f'{path}selfsign.cnf'])
- subprocess.run(['openssl', 'x509', '-req', '-days', '36500', '-in', f'{path}selfsign.csr', '-signkey', f'{path}selfsign.key', '-out', f'{path}selfsign.crt'])
+ subprocess.run(['openssl', 'req', '-new', '-key', f'{path}ssl.key', '-out', f'{path}ssl.csr', '-config', f'{path}ssl.cnf'])
+ subprocess.run(['openssl', 'x509', '-req', '-days', '36500', '-in', f'{path}ssl.csr', '-signkey', f'{path}ssl.key', '-out', f'{path}ssl.crt'])
- delFile(f'{path}selfsign.cnf')
- delFile(f'{path}selfsign.csr')
\ No newline at end of file
+ delFile(f'{path}ssl.cnf')
+ delFile(f'{path}ssl.csr')
\ No newline at end of file
diff --git a/src/web.py b/src/web.py
index 7542ac6..74e7c59 100755
--- a/src/web.py
+++ b/src/web.py
@@ -23,24 +23,12 @@ class webtab():
self.defaultPage = ''
self.html = ''
- def recursiveAdder(self, objs):
+ def compileHtml(self, permGroups):
html = ''
- for obj in objs:
- if isinstance(obj, webpagefolder):
- html += '' +\
- obj.name +\
- ' \n' +\
- self.recursiveAdder(obj.pages) +\
- ' \n'
- else:
- html += f'' +\
- obj.name +\
- ' \n'
+ for page in self.pages:
+ html += page.compileHtml(self.name, permGroups)
return html
- def addHtml(self):
- self.html = self.recursiveAdder(self.pages)
-
def addPage(self, page):
self.pages.append(page)
@@ -48,11 +36,28 @@ class webpagefolder():
def __init__(self):
self.name = None
self.pages = []
+
+ def compileHtml(self, tabname, permGroups):
+ html = '' + self.name + ' '
+ for page in self.pages:
+ html += page.compileHtml(tabname, permGroups)
+ html += ' '
+ return html
class webpage():
def __init__(self):
self.name = None
+ self.requiredPermGroup = ''
self.location = None
+
+ def compileHtml(self, tabname, permGroups):
+ html = '' +\
+ self.name
+ else:
+ html += f'>{self.name}'
+ return html + ' '
@app.route('/')
def index():
@@ -74,16 +79,16 @@ def loginPage():
.replace('', app.webserv.title)
.replace('', '/login'))
-def recursivePageLocationFinder(pagename, objs):
+def recursivePageFinder(pagename, objs):
returnVal = None
for obj in objs:
if isinstance(obj, webpagefolder):
- tmp = recursivePageLocationFinder(pagename, obj.pages)
+ tmp = recursivePageFinder(pagename, obj.pages)
if tmp != None:
returnVal = tmp
else:
if obj.name == pagename:
- returnVal = obj.location
+ returnVal = obj
return returnVal
@app.route('//')
@@ -96,16 +101,23 @@ def page(tabname, pagename):
try:
tab = utils.getatribinarr(app.webserv.webtabs, 'name', tabname)
- pageloc = recursivePageLocationFinder(pagename, tab.pages)
+ page = recursivePageFinder(pagename, tab.pages)
+
+ # print(page.requiredPermGroup)
+
+ isValid, permGroups = app.webserv.authServer.validPermGroup(page.requiredPermGroup, request)
+
+ if not isValid:
+ return redirect(f'/{tab.name}/{tab.defaultPage}', code=302)
return make_response(open(utils.getRoot('html/nav.html'), 'r').read()
- .replace('', open(utils.getRoot(pageloc), 'r').read())
+ .replace('', open(utils.getRoot(page.location), 'r').read())
.replace('', app.webserv.tabHtml)
- .replace('', tab.html)
+ .replace('', tab.compileHtml(permGroups))
.replace('', app.webserv.title)
.replace('', f'/{app.webserv.defaultTab}/{app.webserv.defaultPage}'))
except:
- return redirect("/login", code=302)
+ return redirect("/", code=302)
@app.route('/src/')
def src(file):
@@ -138,7 +150,7 @@ class webserv():
if self.secure:
dataroot = utils.getRoot("data/")
- sslcontext = (f'{dataroot}selfsign.crt', f'{dataroot}selfsign.key')
+ sslcontext = (f'{dataroot}ssl.crt', f'{dataroot}ssl.key')
else:
sslcontext = None
@@ -146,14 +158,11 @@ class webserv():
return f'{name} '
for tab in self.webtabs:
- self.tabHtml += tabHtml(f'/{tab.name}/{tab.defaultPage}', tab.name)
if tab.name == self.defaultTab:
+ self.tabHtml = tabHtml(f'/{tab.name}/{tab.defaultPage}', tab.name) + self.tabHtml
self.defaultPage = tab.defaultPage
-
- def testfunc1(ac, data):
- print(ac)
- print(data)
-
+ else:
+ self.tabHtml += tabHtml(f'/{tab.name}/{tab.defaultPage}', tab.name)
app.webserv = self
self.app = app