Compare commits
10 Commits
8d7eefb2e2
...
c03332884f
Author | SHA1 | Date | |
---|---|---|---|
c03332884f | |||
ba4ec31a04 | |||
b09fe65c32 | |||
83ba6ca330 | |||
fdb8d7a777 | |||
6696fcf8af | |||
480a275246 | |||
56586d1d5d | |||
14e42bc0d4 | |||
0edb5cabb5 |
1
app/.gitignore
vendored
1
app/.gitignore
vendored
@ -5,3 +5,4 @@ venv/
|
|||||||
env/
|
env/
|
||||||
.beaker/data/*
|
.beaker/data/*
|
||||||
!.beaker/data/.noremove
|
!.beaker/data/.noremove
|
||||||
|
nohup.out
|
||||||
|
@ -1,24 +1,18 @@
|
|||||||
from bottle import Bottle, get, static_file
|
from core import template
|
||||||
|
|
||||||
page = {
|
page = {
|
||||||
'public' :'pages/public',
|
'public' :'pages/public',
|
||||||
'email' :'pages/email'
|
'email' :'pages/email'
|
||||||
}
|
}
|
||||||
|
|
||||||
app = Bottle()
|
static = [
|
||||||
|
{
|
||||||
# Default staticdir
|
"route" :"/css/<filepath:re:.*\.(css|sass|css.map)>",
|
||||||
|
"root" :"./static/css"
|
||||||
@app.get("/css/<filepath:re:.*\.(css|sass|css.map)>")
|
},
|
||||||
def static(filepath):
|
{
|
||||||
return static_file(filepath, root="./static/css")
|
"route" :"/js/<filepath:re:.*\.(js)>",
|
||||||
|
"root" :"./static/js"
|
||||||
@app.get("/js/<filepath:re:.*\.(js)>")
|
}
|
||||||
def static(filepath):
|
]
|
||||||
return static_file(filepath, root="./static/js")
|
template.add(static, "templates")
|
||||||
|
|
||||||
# Template staticdir: plain
|
|
||||||
|
|
||||||
@app.get("/templates/plain/css/<filepath:re:.*\.(css|sass|css.map)>")
|
|
||||||
def static(filepath):
|
|
||||||
return static_file(filepath, root="./templates/plain/static/css")
|
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
title = "Authsquare"
|
title = "Authsquare"
|
||||||
header = f"Welcome to {title}"
|
header = f"Welcome to {title}"
|
||||||
copyright = "Copyright (C) 2024 Dita Aji Pratama"
|
copyright = "Copyright (C) 2024 Dita Aji Pratama"
|
||||||
|
|
||||||
production = False
|
production = False
|
||||||
su_mode = True
|
forbidden_registration = ['su', 'admin']
|
||||||
|
|
||||||
auth_key = 'your_key'
|
auth_key = 'your_key'
|
||||||
|
|
||||||
ssh = {
|
ssh = {
|
||||||
"key":{
|
"key":{
|
||||||
@ -49,7 +49,7 @@ def verification_url(token):
|
|||||||
return url
|
return url
|
||||||
|
|
||||||
def change_forgot_url(token):
|
def change_forgot_url(token):
|
||||||
url = f"{baseurl}/portal/change/forgot?token={token}"
|
url = f"{baseurl}/reset?token={token}"
|
||||||
return url
|
return url
|
||||||
|
|
||||||
menu = {
|
menu = {
|
||||||
|
7
app/core/staticdir.py
Normal file
7
app/core/staticdir.py
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
from bottle import Bottle, static_file
|
||||||
|
from config import directory
|
||||||
|
|
||||||
|
app = Bottle()
|
||||||
|
|
||||||
|
for item in directory.static:
|
||||||
|
app.route(item['route'], "GET", lambda filepath, root=item['root']: static_file(filepath, root=root) )
|
8
app/core/template.py
Normal file
8
app/core/template.py
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
import os
|
||||||
|
|
||||||
|
def add(dirconfig, template_directory):
|
||||||
|
template_list = [d for d in os.listdir(template_directory) if os.path.isdir(os.path.join(template_directory, d))]
|
||||||
|
for template_name in template_list:
|
||||||
|
template_module = __import__(f"{template_directory}.{template_name}.main", fromlist=["static"])
|
||||||
|
for static in getattr(template_module, "static", []):
|
||||||
|
dirconfig.append(static)
|
@ -5,19 +5,18 @@
|
|||||||
# This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
# This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||||
# You should have received a copy of the GNU General Public License along with this program. If not, see https://www.gnu.org/licenses/.
|
# You should have received a copy of the GNU General Public License along with this program. If not, see https://www.gnu.org/licenses/.
|
||||||
|
|
||||||
import sys
|
|
||||||
from bottle import Bottle, run
|
from bottle import Bottle, run
|
||||||
from beaker.middleware import SessionMiddleware
|
from beaker.middleware import SessionMiddleware
|
||||||
|
|
||||||
import handler
|
import handler
|
||||||
|
|
||||||
|
from core import staticdir
|
||||||
from config import server
|
from config import server
|
||||||
from config import directory
|
|
||||||
|
|
||||||
app = Bottle()
|
app = Bottle()
|
||||||
|
|
||||||
app.merge(handler.app)
|
app.merge(handler.app)
|
||||||
app.merge(directory.app)
|
app.merge(staticdir.app)
|
||||||
|
|
||||||
app = SessionMiddleware(app, server.session_opts)
|
app = SessionMiddleware(app, server.session_opts)
|
||||||
|
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
# This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
# This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||||
# You should have received a copy of the GNU General Public License along with this program. If not, see https://www.gnu.org/licenses/.
|
# You should have received a copy of the GNU General Public License along with this program. If not, see https://www.gnu.org/licenses/.
|
||||||
|
|
||||||
from bottle import Bottle, route, request, response
|
from bottle import Bottle, route, request, response, redirect
|
||||||
import json
|
import json
|
||||||
|
|
||||||
from config import directory
|
from config import directory
|
||||||
@ -18,6 +18,8 @@ import modules.public.register as public_register
|
|||||||
import modules.public.notme as public_notme
|
import modules.public.notme as public_notme
|
||||||
import modules.public.verify as public_verify
|
import modules.public.verify as public_verify
|
||||||
import modules.public.login as public_login
|
import modules.public.login as public_login
|
||||||
|
import modules.public.forgot as public_forgot
|
||||||
|
import modules.public.reset as public_reset
|
||||||
|
|
||||||
import modules.api.auth as api_auth
|
import modules.api.auth as api_auth
|
||||||
|
|
||||||
@ -69,6 +71,44 @@ def index():
|
|||||||
}
|
}
|
||||||
return public_login.login().html(params)
|
return public_login.login().html(params)
|
||||||
|
|
||||||
|
@app.route('/forgot')
|
||||||
|
def index():
|
||||||
|
params = {
|
||||||
|
"mako" : {
|
||||||
|
"website" : template_public.main(directory.page["public"], "forgot")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return public_forgot.forgot().html(params)
|
||||||
|
|
||||||
|
@app.route('/reset', method='GET')
|
||||||
|
def index():
|
||||||
|
params = {
|
||||||
|
"mako" : {
|
||||||
|
"website" : template_public.main(directory.page["public"], "reset")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return public_reset.reset().html(params)
|
||||||
|
|
||||||
|
@app.route('/logout')
|
||||||
|
def index():
|
||||||
|
beaker_session = request.environ.get('beaker.session')
|
||||||
|
if "token" in beaker_session:
|
||||||
|
params = {
|
||||||
|
"jwt" : beaker_session["token"],
|
||||||
|
"type" : "out"
|
||||||
|
}
|
||||||
|
response_session = api_auth.auth().session(params)
|
||||||
|
response_logout = api_auth.auth().logout(params)
|
||||||
|
if response_session['status'] == 'success' and response_logout['status'] == 'success' :
|
||||||
|
redirect('/?message=logout success')
|
||||||
|
else:
|
||||||
|
print('logout failed')
|
||||||
|
print(f"response session: {response_session['status']}")
|
||||||
|
print(f"response logout: {response_logout['status']}")
|
||||||
|
redirect('/?message=logout failed')
|
||||||
|
else:
|
||||||
|
redirect('/')
|
||||||
|
|
||||||
@app.route('/api/auth/registration/register/<roles>', method='POST')
|
@app.route('/api/auth/registration/register/<roles>', method='POST')
|
||||||
def index(roles):
|
def index(roles):
|
||||||
try:
|
try:
|
||||||
@ -144,3 +184,34 @@ def index(type):
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(str(e))
|
print(str(e))
|
||||||
return json.dumps({}, indent = 2).encode()
|
return json.dumps({}, indent = 2).encode()
|
||||||
|
|
||||||
|
@app.route('/api/auth/logout', method='POST')
|
||||||
|
def index():
|
||||||
|
try:
|
||||||
|
params = request.json
|
||||||
|
response.content_type = 'application/json'
|
||||||
|
return json.dumps(api_auth.auth().logout(params), indent = 2).encode()
|
||||||
|
except Exception as e:
|
||||||
|
print(str(e))
|
||||||
|
return json.dumps({}, indent = 2).encode()
|
||||||
|
|
||||||
|
@app.route('/api/auth/password/forgot/<type>', method='POST')
|
||||||
|
def index(type):
|
||||||
|
try:
|
||||||
|
params = request.json
|
||||||
|
params["type"] = type
|
||||||
|
if type == "send":
|
||||||
|
params["mako"] = {
|
||||||
|
"email" : template_email.main(directory.page["email"], "reset")
|
||||||
|
}
|
||||||
|
elif type == "change":
|
||||||
|
params["mako"] = {
|
||||||
|
"email" : template_email.main(directory.page["email"], "message")
|
||||||
|
}
|
||||||
|
else:
|
||||||
|
pass
|
||||||
|
response.content_type = 'application/json'
|
||||||
|
return json.dumps(api_auth.auth().forgot(params), indent = 2).encode()
|
||||||
|
except Exception as e:
|
||||||
|
print(str(e))
|
||||||
|
return json.dumps({}, indent = 2).encode()
|
||||||
|
@ -4,3 +4,7 @@ pip install bottle # Micro Framework
|
|||||||
pip install gunicorn # WSGI Server Backend
|
pip install gunicorn # WSGI Server Backend
|
||||||
pip install beaker # Session & caching library
|
pip install beaker # Session & caching library
|
||||||
pip install mako # Template library
|
pip install mako # Template library
|
||||||
|
pip install mysql-connector # Database
|
||||||
|
|
||||||
|
pip install bcrypt
|
||||||
|
pip install pyjwt[crypto]
|
||||||
|
@ -53,9 +53,9 @@ class auth:
|
|||||||
response["data" ] = {
|
response["data" ] = {
|
||||||
"recaptcha":captcha_r
|
"recaptcha":captcha_r
|
||||||
}
|
}
|
||||||
elif globalvar.su_mode == False and roles == 'su':
|
elif roles in globalvar.forbidden_registration:
|
||||||
response["status" ] = "failed"
|
response["status" ] = "failed"
|
||||||
response["desc" ] = "Forbidden to become super user"
|
response["desc" ] = f"Forbidden to become {roles}"
|
||||||
response["data" ] = {
|
response["data" ] = {
|
||||||
"recaptcha":captcha_r
|
"recaptcha":captcha_r
|
||||||
}
|
}
|
||||||
@ -471,14 +471,16 @@ class auth:
|
|||||||
type = params["type" ] # POST: send / change
|
type = params["type" ] # POST: send / change
|
||||||
self.cursor.execute("BEGIN;")
|
self.cursor.execute("BEGIN;")
|
||||||
try:
|
try:
|
||||||
|
loggorilla.fyinf(APIADDR, f"type: {type}")
|
||||||
if type == "send":
|
if type == "send":
|
||||||
loggorilla.prcss(APIADDR, "Define parameters inside decision")
|
loggorilla.prcss(APIADDR, "Define parameters inside decision")
|
||||||
email = params["email"].lower()
|
email = params["email"].lower()
|
||||||
loggorilla.prcss(APIADDR, "Get dependency data")
|
loggorilla.prcss(APIADDR, "Get dependency data")
|
||||||
self.cursor.execute(f"SELECT COUNT(*) AS `count`, auth_profile.token, auth_profile.email FROM auth_profile_verification INNER JOIN auth_profile ON auth_profile.id = auth_profile_verification.auth_profile WHERE auth_profile.email = %s AND auth_profile_verification.type = 'email' AND auth_profile_verification.verified = 1 ; ", (email,) )
|
self.cursor.execute(f"SELECT COUNT(*) AS `count`, auth_profile.token, auth_profile.email FROM auth_profile_verification INNER JOIN auth_profile ON auth_profile.id = auth_profile_verification.auth_profile WHERE auth_profile.email = %s AND auth_profile_verification.type = 'email' AND auth_profile_verification.verified = 1 ; ", (email,) )
|
||||||
result_verified = self.cursor.fetchone()
|
result_verified = self.cursor.fetchone()
|
||||||
token = result_verified["token"].decode()
|
|
||||||
if result_verified["count"] >= 1:
|
if result_verified["count"] >= 1:
|
||||||
|
loggorilla.prcss(APIADDR, "Get token")
|
||||||
|
token = result_verified["token"].decode()
|
||||||
loggorilla.prcss(APIADDR, "Generate URL")
|
loggorilla.prcss(APIADDR, "Generate URL")
|
||||||
# TODO: set expired time
|
# TODO: set expired time
|
||||||
expired = datetime.datetime.now() + datetime.timedelta(minutes=30) # Can be hours or minutes
|
expired = datetime.datetime.now() + datetime.timedelta(minutes=30) # Can be hours or minutes
|
||||||
@ -493,14 +495,13 @@ class auth:
|
|||||||
loggorilla.prcss(APIADDR, "Sending email")
|
loggorilla.prcss(APIADDR, "Sending email")
|
||||||
self.smtpconfig['subject' ] = f"{globalvar.title} forgot password"
|
self.smtpconfig['subject' ] = f"{globalvar.title} forgot password"
|
||||||
self.smtpconfig['to' ] = email
|
self.smtpconfig['to' ] = email
|
||||||
self.smtpconfig['text' ] = f"Please visit this link to change password: {change_forgot_url}. Avoid the link if you are not request this."
|
self.smtpconfig['text' ] = f"Please visit this link to reset password: {change_forgot_url}. Avoid the link if you are not request this."
|
||||||
self.smtpconfig['html' ] = Template(params["mako"]["email"]['template']).render(
|
self.smtpconfig['html' ] = Template(params["mako"]["email"]['index']).render(
|
||||||
title = globalvar.title,
|
title = globalvar.title,
|
||||||
heading = self.smtpconfig['subject'],
|
header = globalvar.title,
|
||||||
image = "https://colorlib.com/etc/email-template/10/images/email.png",
|
copyright = globalvar.copyright,
|
||||||
unsubscribe = "#",
|
container = Template(params["mako"]["email"]['container']).render(
|
||||||
container = Template(params["mako"]["email"]['container']).render(
|
reset = change_forgot_url
|
||||||
change = change_forgot_url
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
sendwave.smtp(self.smtpconfig)
|
sendwave.smtp(self.smtpconfig)
|
||||||
@ -544,12 +545,11 @@ class auth:
|
|||||||
self.smtpconfig['subject' ] = f"{globalvar.title} password change success"
|
self.smtpconfig['subject' ] = f"{globalvar.title} password change success"
|
||||||
self.smtpconfig['to' ] = email
|
self.smtpconfig['to' ] = email
|
||||||
self.smtpconfig['text' ] = f"You had change your password."
|
self.smtpconfig['text' ] = f"You had change your password."
|
||||||
self.smtpconfig['html' ] = Template(params["mako"]["email"]['template']).render(
|
self.smtpconfig['html' ] = Template(params["mako"]["email"]['index']).render(
|
||||||
title = globalvar.title,
|
title = globalvar.title,
|
||||||
heading = self.smtpconfig['subject'],
|
header = globalvar.title,
|
||||||
image = "https://colorlib.com/etc/email-template/10/images/email.png",
|
copyright = globalvar.copyright,
|
||||||
unsubscribe = "#",
|
container = Template(params["mako"]["email"]['container']).render(
|
||||||
container = Template(params["mako"]["email"]['container']).render(
|
|
||||||
message = f"You had change your password."
|
message = f"You had change your password."
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
30
app/modules/public/forgot.py
Normal file
30
app/modules/public/forgot.py
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
from mako.template import Template
|
||||||
|
from config import globalvar
|
||||||
|
from bottle import request
|
||||||
|
|
||||||
|
class forgot:
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def html(self, params):
|
||||||
|
active_page = "Forgot"
|
||||||
|
user_roles = [0]
|
||||||
|
beaker_session = request.environ.get('beaker.session')
|
||||||
|
jwt = beaker_session["token"] if "token" in beaker_session else None
|
||||||
|
if jwt is not None:
|
||||||
|
return redirect('/')
|
||||||
|
else:
|
||||||
|
return Template(params["mako"]["website"]['index']).render(
|
||||||
|
title = globalvar.title,
|
||||||
|
header = globalvar.header,
|
||||||
|
navbar = Template(params["mako"]["website"]['navbar']).render(
|
||||||
|
menu = globalvar.menu['public']['navbar'],
|
||||||
|
user_roles = user_roles,
|
||||||
|
active_page = active_page
|
||||||
|
),
|
||||||
|
footer = Template(params["mako"]["website"]['footer']).render(
|
||||||
|
copyright = globalvar.copyright,
|
||||||
|
),
|
||||||
|
container = Template(params["mako"]["website"]['container']).render()
|
||||||
|
)
|
@ -1,30 +1,49 @@
|
|||||||
import mysql.connector as mariadb
|
import mysql.connector as mariadb
|
||||||
from mako.template import Template
|
from mako.template import Template
|
||||||
from config import globalvar, database
|
from config import globalvar, database
|
||||||
|
from bottle import request
|
||||||
|
|
||||||
|
import procedure.session as procedure_session
|
||||||
|
|
||||||
class home:
|
class home:
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.db_main = mariadb.connect(**database.db_main)
|
self.db_main = mariadb.connect(**database.db_main)
|
||||||
self.cursor = self.db_main.cursor(dictionary=True)
|
self.cursor = self.db_main.cursor(dictionary=True)
|
||||||
self.user_roles = [0] # Cari user roles disini
|
self.user = {
|
||||||
|
"data":{
|
||||||
|
"profile":{
|
||||||
|
"username":None,
|
||||||
|
"email":None,
|
||||||
|
"phone":None,
|
||||||
|
"roles":[0]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
def html(self, params):
|
def html(self, params):
|
||||||
|
active_page = "Home"
|
||||||
active_page = "Home"
|
allowed_roles = [0,1,2,3]
|
||||||
|
beaker_session = request.environ.get('beaker.session')
|
||||||
return Template(params["mako"]["website"]['index']).render(
|
jwt = beaker_session["token"] if "token" in beaker_session else None
|
||||||
title = globalvar.title,
|
self.user = procedure_session.session().user(jwt, allowed_roles) if jwt is not None else self.user
|
||||||
header = globalvar.header,
|
user = self.user['data']
|
||||||
navbar = Template(params["mako"]["website"]['navbar']).render(
|
if 'valid' in user and user['valid']['status'] == 0:
|
||||||
menu = globalvar.menu['public']['navbar'],
|
return redirect('/logout')
|
||||||
user_roles = self.user_roles,
|
else:
|
||||||
active_page = active_page
|
return Template(params["mako"]["website"]['index']).render(
|
||||||
),
|
title = globalvar.title,
|
||||||
footer = Template(params["mako"]["website"]['footer']).render(
|
header = globalvar.header,
|
||||||
copyright = globalvar.copyright,
|
navbar = Template(params["mako"]["website"]['navbar']).render(
|
||||||
),
|
menu = globalvar.menu['public']['navbar'],
|
||||||
container = Template(params["mako"]["website"]['container']).render(
|
user_roles = user['profile']['roles'],
|
||||||
greeting = f"Welcome to your new web application! This placeholder page is here to let you know that your web framework is successfully set up and ready to go. Now, it's time to start building your project. Dive into the documentation to explore the features and capabilities at your disposal."
|
active_page = active_page
|
||||||
|
),
|
||||||
|
footer = Template(params["mako"]["website"]['footer']).render(
|
||||||
|
copyright = globalvar.copyright,
|
||||||
|
),
|
||||||
|
container = Template(params["mako"]["website"]['container']).render(
|
||||||
|
greeting = f"Welcome to your new web application! This placeholder page is here to let you know that your web framework is successfully set up and ready to go. Now, it's time to start building your project. Dive into the documentation to explore the features and capabilities at your disposal.",
|
||||||
|
user = user
|
||||||
|
)
|
||||||
)
|
)
|
||||||
)
|
|
||||||
|
@ -1,26 +1,30 @@
|
|||||||
import mysql.connector as mariadb
|
|
||||||
from mako.template import Template
|
from mako.template import Template
|
||||||
from config import globalvar, database
|
from config import globalvar
|
||||||
|
from bottle import request
|
||||||
|
|
||||||
class login:
|
class login:
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.db_main = mariadb.connect(**database.db_main)
|
pass
|
||||||
self.cursor = self.db_main.cursor(dictionary=True)
|
|
||||||
self.user_roles = [0] # Cari user roles disini
|
|
||||||
|
|
||||||
def html(self, params):
|
def html(self, params):
|
||||||
active_page = "Login"
|
active_page = "Login"
|
||||||
return Template(params["mako"]["website"]['index']).render(
|
user_roles = [0]
|
||||||
title = globalvar.title,
|
beaker_session = request.environ.get('beaker.session')
|
||||||
header = globalvar.header,
|
jwt = beaker_session["token"] if "token" in beaker_session else None
|
||||||
navbar = Template(params["mako"]["website"]['navbar']).render(
|
if jwt is not None:
|
||||||
menu = globalvar.menu['public']['navbar'],
|
return redirect('/')
|
||||||
user_roles = self.user_roles,
|
else:
|
||||||
active_page = active_page
|
return Template(params["mako"]["website"]['index']).render(
|
||||||
),
|
title = globalvar.title,
|
||||||
footer = Template(params["mako"]["website"]['footer']).render(
|
header = globalvar.header,
|
||||||
copyright = globalvar.copyright,
|
navbar = Template(params["mako"]["website"]['navbar']).render(
|
||||||
),
|
menu = globalvar.menu['public']['navbar'],
|
||||||
container = Template(params["mako"]["website"]['container']).render()
|
user_roles = user_roles,
|
||||||
)
|
active_page = active_page
|
||||||
|
),
|
||||||
|
footer = Template(params["mako"]["website"]['footer']).render(
|
||||||
|
copyright = globalvar.copyright,
|
||||||
|
),
|
||||||
|
container = Template(params["mako"]["website"]['container']).render()
|
||||||
|
)
|
||||||
|
@ -1,28 +1,45 @@
|
|||||||
import mysql.connector as mariadb
|
|
||||||
from mako.template import Template
|
from mako.template import Template
|
||||||
from config import globalvar, database
|
from config import globalvar
|
||||||
|
from bottle import request
|
||||||
|
|
||||||
|
import procedure.session as procedure_session
|
||||||
|
|
||||||
class notme:
|
class notme:
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.db_main = mariadb.connect(**database.db_main)
|
self.user = {
|
||||||
self.cursor = self.db_main.cursor(dictionary=True)
|
"data":{
|
||||||
self.user_roles = [0] # Cari user roles disini
|
"profile":{
|
||||||
|
"username":None,
|
||||||
|
"email":None,
|
||||||
|
"phone":None,
|
||||||
|
"roles":[0]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
def html(self, params):
|
def html(self, params):
|
||||||
active_page = None
|
active_page = None
|
||||||
return Template(params["mako"]["website"]['index']).render(
|
allowed_roles = [0,1,2,3]
|
||||||
title = globalvar.title,
|
beaker_session = request.environ.get('beaker.session')
|
||||||
header = globalvar.header,
|
jwt = beaker_session["token"] if "token" in beaker_session else None
|
||||||
navbar = Template(params["mako"]["website"]['navbar']).render(
|
self.user = procedure_session.session().user(jwt, allowed_roles) if jwt is not None else self.user
|
||||||
menu = globalvar.menu['public']['navbar'],
|
user = self.user['data']
|
||||||
user_roles = self.user_roles,
|
if 'valid' in user and user['valid']['status'] == 0:
|
||||||
active_page = active_page
|
return redirect('/logout')
|
||||||
),
|
else:
|
||||||
footer = Template(params["mako"]["website"]['footer']).render(
|
return Template(params["mako"]["website"]['index']).render(
|
||||||
copyright = globalvar.copyright,
|
title = globalvar.title,
|
||||||
),
|
header = globalvar.header,
|
||||||
container = Template(params["mako"]["website"]['container']).render(
|
navbar = Template(params["mako"]["website"]['navbar']).render(
|
||||||
title = globalvar.title
|
menu = globalvar.menu['public']['navbar'],
|
||||||
|
user_roles = user['profile']['roles'],
|
||||||
|
active_page = active_page
|
||||||
|
),
|
||||||
|
footer = Template(params["mako"]["website"]['footer']).render(
|
||||||
|
copyright = globalvar.copyright,
|
||||||
|
),
|
||||||
|
container = Template(params["mako"]["website"]['container']).render(
|
||||||
|
title = globalvar.title
|
||||||
|
)
|
||||||
)
|
)
|
||||||
)
|
|
||||||
|
@ -1,34 +1,36 @@
|
|||||||
import mysql.connector as mariadb
|
|
||||||
from mako.template import Template
|
from mako.template import Template
|
||||||
from config import globalvar, database
|
from config import globalvar
|
||||||
|
from bottle import request
|
||||||
|
|
||||||
class register:
|
class register:
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.db_main = mariadb.connect(**database.db_main)
|
pass
|
||||||
self.cursor = self.db_main.cursor(dictionary=True)
|
|
||||||
self.user_roles = [0] # Cari user roles disini
|
|
||||||
|
|
||||||
def html(self, params):
|
def html(self, params):
|
||||||
|
roles = params["roles"]
|
||||||
roles = params["roles"]
|
active_page = "Register"
|
||||||
active_page = "Register"
|
user_roles = [0]
|
||||||
|
beaker_session = request.environ.get('beaker.session')
|
||||||
return Template(params["mako"]["website"]['index']).render(
|
jwt = beaker_session["token"] if "token" in beaker_session else None
|
||||||
title = globalvar.title,
|
if jwt is not None:
|
||||||
header = globalvar.header,
|
return redirect('/')
|
||||||
navbar = Template(params["mako"]["website"]['navbar']).render(
|
else:
|
||||||
menu = globalvar.menu['public']['navbar'],
|
return Template(params["mako"]["website"]['index']).render(
|
||||||
user_roles = self.user_roles,
|
title = globalvar.title,
|
||||||
active_page = active_page
|
header = globalvar.header,
|
||||||
),
|
navbar = Template(params["mako"]["website"]['navbar']).render(
|
||||||
footer = Template(params["mako"]["website"]['footer']).render(
|
menu = globalvar.menu['public']['navbar'],
|
||||||
copyright = globalvar.copyright,
|
user_roles = user_roles,
|
||||||
),
|
active_page = active_page
|
||||||
container = Template(params["mako"]["website"]['container']).render(
|
),
|
||||||
title = globalvar.title,
|
footer = Template(params["mako"]["website"]['footer']).render(
|
||||||
reCAPTCHA_client = globalvar.reCAPTCHA['client'],
|
copyright = globalvar.copyright,
|
||||||
roles = roles,
|
),
|
||||||
production = globalvar.production
|
container = Template(params["mako"]["website"]['container']).render(
|
||||||
|
title = globalvar.title,
|
||||||
|
reCAPTCHA_client = globalvar.reCAPTCHA['client'],
|
||||||
|
roles = roles,
|
||||||
|
production = globalvar.production
|
||||||
|
)
|
||||||
)
|
)
|
||||||
)
|
|
||||||
|
30
app/modules/public/reset.py
Normal file
30
app/modules/public/reset.py
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
from mako.template import Template
|
||||||
|
from config import globalvar
|
||||||
|
from bottle import request
|
||||||
|
|
||||||
|
class reset:
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def html(self, params):
|
||||||
|
active_page = "Reset"
|
||||||
|
user_roles = [0]
|
||||||
|
beaker_session = request.environ.get('beaker.session')
|
||||||
|
jwt = beaker_session["token"] if "token" in beaker_session else None
|
||||||
|
if jwt is not None:
|
||||||
|
return redirect('/')
|
||||||
|
else:
|
||||||
|
return Template(params["mako"]["website"]['index']).render(
|
||||||
|
title = globalvar.title,
|
||||||
|
header = globalvar.header,
|
||||||
|
navbar = Template(params["mako"]["website"]['navbar']).render(
|
||||||
|
menu = globalvar.menu['public']['navbar'],
|
||||||
|
user_roles = user_roles,
|
||||||
|
active_page = active_page
|
||||||
|
),
|
||||||
|
footer = Template(params["mako"]["website"]['footer']).render(
|
||||||
|
copyright = globalvar.copyright,
|
||||||
|
),
|
||||||
|
container = Template(params["mako"]["website"]['container']).render()
|
||||||
|
)
|
@ -1,26 +1,43 @@
|
|||||||
import mysql.connector as mariadb
|
|
||||||
from mako.template import Template
|
from mako.template import Template
|
||||||
from config import globalvar, database
|
from config import globalvar
|
||||||
|
from bottle import request
|
||||||
|
|
||||||
|
import procedure.session as procedure_session
|
||||||
|
|
||||||
class verify:
|
class verify:
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.db_main = mariadb.connect(**database.db_main)
|
self.user = {
|
||||||
self.cursor = self.db_main.cursor(dictionary=True)
|
"data":{
|
||||||
self.user_roles = [0] # Cari user roles disini
|
"profile":{
|
||||||
|
"username":None,
|
||||||
|
"email":None,
|
||||||
|
"phone":None,
|
||||||
|
"roles":[0]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
def html(self, params):
|
def html(self, params):
|
||||||
active_page = None
|
active_page = None
|
||||||
return Template(params["mako"]["website"]['index']).render(
|
allowed_roles = [0,1,2,3]
|
||||||
title = globalvar.title,
|
beaker_session = request.environ.get('beaker.session')
|
||||||
header = globalvar.header,
|
jwt = beaker_session["token"] if "token" in beaker_session else None
|
||||||
navbar = Template(params["mako"]["website"]['navbar']).render(
|
self.user = procedure_session.session().user(jwt, allowed_roles) if jwt is not None else self.user
|
||||||
menu = globalvar.menu['public']['navbar'],
|
user = self.user['data']
|
||||||
user_roles = self.user_roles,
|
if 'valid' in user and user['valid']['status'] == 0:
|
||||||
active_page = active_page
|
return redirect('/logout')
|
||||||
),
|
else:
|
||||||
footer = Template(params["mako"]["website"]['footer']).render(
|
return Template(params["mako"]["website"]['index']).render(
|
||||||
copyright = globalvar.copyright,
|
title = globalvar.title,
|
||||||
),
|
header = globalvar.header,
|
||||||
container = Template(params["mako"]["website"]['container']).render()
|
navbar = Template(params["mako"]["website"]['navbar']).render(
|
||||||
)
|
menu = globalvar.menu['public']['navbar'],
|
||||||
|
user_roles = user['profile']['roles'],
|
||||||
|
active_page = active_page
|
||||||
|
),
|
||||||
|
footer = Template(params["mako"]["website"]['footer']).render(
|
||||||
|
copyright = globalvar.copyright,
|
||||||
|
),
|
||||||
|
container = Template(params["mako"]["website"]['container']).render()
|
||||||
|
)
|
||||||
|
6
app/pages/email/reset.html
Normal file
6
app/pages/email/reset.html
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
<h2>Forgot Password</h2>
|
||||||
|
|
||||||
|
<p>Please visit this link below to reset password. <b>Avoid the link if you are not request this.</b> </p>
|
||||||
|
<a href="${reset}" class="button">
|
||||||
|
Reset password
|
||||||
|
</a>
|
15
app/pages/public/forgot.html
Normal file
15
app/pages/public/forgot.html
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
<h1>Forgot Password</h1>
|
||||||
|
|
||||||
|
<script type="text/javascript" src="/js/carrack.js"></script>
|
||||||
|
|
||||||
|
<!-- FORM -->
|
||||||
|
<input required type="email" id="form-email" placeholder="Email"> <br>
|
||||||
|
|
||||||
|
<button onclick="onSubmit()">Submit</button>
|
||||||
|
|
||||||
|
<!-- RESPONSE -->
|
||||||
|
<div id="alert-response" role="alert">
|
||||||
|
<b id="alert-status">Loading...</b> <span id="alert-desc">Please wait...</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script type="text/javascript" src="/js/auth/forgot.js"></script>
|
@ -1 +1,7 @@
|
|||||||
<p>${greeting}</p>
|
<p>${greeting}</p>
|
||||||
|
<p>
|
||||||
|
<b>Username:</b> ${user['profile']['username']} <br>
|
||||||
|
<b>Email:</b> ${user['profile']['email']} <br>
|
||||||
|
<b>Phone:</b> ${user['profile']['phone']} <br>
|
||||||
|
<b>Roles:</b> ${str(user['profile']['roles'])} <br>
|
||||||
|
</p>
|
||||||
|
@ -4,7 +4,9 @@
|
|||||||
|
|
||||||
<input required type="text" id="form-username" placeholder="Username" > <br>
|
<input required type="text" id="form-username" placeholder="Username" > <br>
|
||||||
<input required type="password" id="form-password" placeholder="Password" > <br>
|
<input required type="password" id="form-password" placeholder="Password" > <br>
|
||||||
<button type="button" onclick="onSubmit()">Login</button>
|
<button type="button" onclick="onSubmit()">Login</button> <br>
|
||||||
|
|
||||||
|
<a href="/forgot">Forgot password</a>
|
||||||
|
|
||||||
<div id="alert-response" role="alert">
|
<div id="alert-response" role="alert">
|
||||||
<b id="alert-status">Loading...</b> <span id="alert-desc">Please wait...</span>
|
<b id="alert-status">Loading...</b> <span id="alert-desc">Please wait...</span>
|
||||||
|
16
app/pages/public/reset.html
Normal file
16
app/pages/public/reset.html
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
<h1>Reset Password</h1>
|
||||||
|
|
||||||
|
<script type="text/javascript" src="/js/carrack.js"></script>
|
||||||
|
|
||||||
|
<!-- FORM -->
|
||||||
|
<div id="form">
|
||||||
|
<input required type="password" id="form-password" placeholder="New Password"> <br>
|
||||||
|
<button onclick="onSubmit()">Submit</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- RESPONSE -->
|
||||||
|
<div id="alert-response" role="alert">
|
||||||
|
<b id="alert-status">Loading...</b> <span id="alert-desc">Please wait...</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script type="text/javascript" src="/js/auth/reset.js"></script>
|
100
app/procedure/session.py
Normal file
100
app/procedure/session.py
Normal file
@ -0,0 +1,100 @@
|
|||||||
|
import mysql.connector as mariadb
|
||||||
|
|
||||||
|
import datetime
|
||||||
|
|
||||||
|
import config.database as database
|
||||||
|
import config.globalvar as globalvar
|
||||||
|
|
||||||
|
import scripts.loggorilla as loggorilla
|
||||||
|
import scripts.tokenguard as tokenguard
|
||||||
|
|
||||||
|
class session():
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
self.db_main = mariadb.connect(**database.db_main)
|
||||||
|
self.cursor = self.db_main.cursor(dictionary=True)
|
||||||
|
|
||||||
|
def user(self, jwt, allowed_roles):
|
||||||
|
APIADDR = "procedure.validation"
|
||||||
|
response = {}
|
||||||
|
try:
|
||||||
|
loggorilla.prcss(APIADDR, "Define parameters")
|
||||||
|
payload = tokenguard.decode(jwt, globalvar.ssh['key']['public'])
|
||||||
|
|
||||||
|
loggorilla.prcss(APIADDR, "Get dependency data")
|
||||||
|
self.cursor.execute(f"SELECT * FROM auth_session WHERE id = %s ; ", (payload["session"]["id"],) )
|
||||||
|
r_session = self.cursor.fetchone()
|
||||||
|
self.cursor.execute(f"SELECT COUNT(*) AS `count`, auth_profile.* FROM auth_profile_verification LEFT JOIN auth_profile ON auth_profile.id = auth_profile_verification.auth_profile WHERE auth_profile.token = %s AND auth_profile_verification.type = 'email' AND auth_profile_verification.verified = 1 ; ", (r_session['token'],) )
|
||||||
|
r_profile = self.cursor.fetchone()
|
||||||
|
self.cursor.execute(f"SELECT auth_roles FROM auth_profile_roles WHERE auth_profile = %s ; ", (r_profile['id'],) )
|
||||||
|
r_roles = self.cursor.fetchall()
|
||||||
|
|
||||||
|
r_profile['roles'] = [0]
|
||||||
|
for row in r_roles:
|
||||||
|
r_profile['roles'].remove(0)
|
||||||
|
r_profile['roles'].append(row['auth_roles'])
|
||||||
|
|
||||||
|
loggorilla.prcss(APIADDR, "Validation")
|
||||||
|
if datetime.datetime.now() > r_session['end']:
|
||||||
|
loggorilla.prcss(APIADDR, "Deleting")
|
||||||
|
self.cursor.execute("DELETE FROM auth_session WHERE id = %s ; ", (r_session['id'],) )
|
||||||
|
loggorilla.prcss(APIADDR, "Giving response")
|
||||||
|
loggorilla.accss(APIADDR, "Expired. Your session removed." )
|
||||||
|
response["status" ] = "failed"
|
||||||
|
response["desc" ] = "Expired. Your session removed."
|
||||||
|
response["data" ] = {
|
||||||
|
"valid" :{
|
||||||
|
"status" : 0,
|
||||||
|
"desc" : "expired"
|
||||||
|
},
|
||||||
|
"session" : r_session,
|
||||||
|
"profile" : r_profile
|
||||||
|
}
|
||||||
|
elif r_profile["count"] == 0:
|
||||||
|
loggorilla.prcss(APIADDR, "Giving response")
|
||||||
|
loggorilla.accss(APIADDR, "No active account for this" )
|
||||||
|
response["status" ] = "failed"
|
||||||
|
response["desc" ] = "No active account for this"
|
||||||
|
response["data" ] = {
|
||||||
|
"message" : "Please contact us if you still had a problem",
|
||||||
|
"valid" :{
|
||||||
|
"status" : 0,
|
||||||
|
"desc" : "forbidden"
|
||||||
|
},
|
||||||
|
"session" : r_session,
|
||||||
|
"profile" : r_profile
|
||||||
|
}
|
||||||
|
elif any(role in allowed_roles for role in r_profile['roles']):
|
||||||
|
loggorilla.prcss(APIADDR, "Giving response")
|
||||||
|
response["status" ] = "success"
|
||||||
|
response["desc" ] = "User roles authorized"
|
||||||
|
response["data" ] = {
|
||||||
|
"valid" :{
|
||||||
|
"status" : 1,
|
||||||
|
"desc" : "authorized"
|
||||||
|
},
|
||||||
|
"session" : r_session,
|
||||||
|
"profile" : r_profile
|
||||||
|
}
|
||||||
|
else:
|
||||||
|
loggorilla.prcss(APIADDR, "Giving response")
|
||||||
|
loggorilla.accss(APIADDR, "User roles unauthorized" )
|
||||||
|
response["status" ] = "failed"
|
||||||
|
response["desc" ] = "User roles unauthorized"
|
||||||
|
response["data" ] = {
|
||||||
|
"valid" :{
|
||||||
|
"status" : 0,
|
||||||
|
"desc" : "unauthorized"
|
||||||
|
},
|
||||||
|
"session" : r_session,
|
||||||
|
"profile" : r_profile
|
||||||
|
}
|
||||||
|
except Exception as e:
|
||||||
|
loggorilla.error(APIADDR, str(e) )
|
||||||
|
response["status" ] = "failed"
|
||||||
|
response["desc" ] = "Internal Server Error. Please contact us if you still have an error. for detail"
|
||||||
|
finally:
|
||||||
|
self.cursor.close()
|
||||||
|
self.db_main.close()
|
||||||
|
|
||||||
|
return response
|
42
app/static/js/auth/forgot.js
Normal file
42
app/static/js/auth/forgot.js
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
function flushResponse() {
|
||||||
|
document.getElementById("alert-response" ).style.display = 'none';
|
||||||
|
document.getElementById("alert-response" ).classList.remove('alert-success' );
|
||||||
|
document.getElementById("alert-response" ).classList.remove('alert-danger' );
|
||||||
|
document.getElementById("alert-response" ).classList.remove('alert-primary' );
|
||||||
|
}
|
||||||
|
|
||||||
|
function loadingResponse() {
|
||||||
|
flushResponse();
|
||||||
|
document.getElementById("alert-status" ).innerHTML = "Loading...";
|
||||||
|
document.getElementById("alert-desc" ).innerHTML = "Please wait...";
|
||||||
|
document.getElementById("alert-response").classList.add('alert-primary');
|
||||||
|
document.getElementById("alert-response").style.display = 'block';
|
||||||
|
}
|
||||||
|
|
||||||
|
function responseAlert(response) {
|
||||||
|
flushResponse();
|
||||||
|
const obj = JSON.parse(response);
|
||||||
|
if (obj.status == "success" ) document.getElementById("alert-response").classList.add('alert-success' );
|
||||||
|
if (obj.status == "failed" ) document.getElementById("alert-response").classList.add('alert-danger' );
|
||||||
|
document.getElementById("alert-status" ).innerHTML = obj.status;
|
||||||
|
document.getElementById("alert-desc" ).innerHTML = obj.desc;
|
||||||
|
document.getElementById("alert-response").style.display = 'block';
|
||||||
|
}
|
||||||
|
|
||||||
|
function onSubmit() {
|
||||||
|
loadingResponse();
|
||||||
|
var email = document.getElementById("form-email" ).value;
|
||||||
|
var url = "/api/auth/password/forgot/send";
|
||||||
|
var payload = {
|
||||||
|
"email" : email
|
||||||
|
};
|
||||||
|
sendHttpRequest(url, "POST", payload, function (error, response) {
|
||||||
|
if (error) console.error("Error:", error);
|
||||||
|
else {
|
||||||
|
console.log("JSON Response:", response);
|
||||||
|
responseAlert(response);
|
||||||
|
}
|
||||||
|
}, "application/json");
|
||||||
|
}
|
||||||
|
|
||||||
|
flushResponse();
|
49
app/static/js/auth/reset.js
Normal file
49
app/static/js/auth/reset.js
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
function flushResponse() {
|
||||||
|
document.getElementById("alert-response" ).style.display = 'none';
|
||||||
|
document.getElementById("alert-response" ).classList.remove('alert-success' );
|
||||||
|
document.getElementById("alert-response" ).classList.remove('alert-danger' );
|
||||||
|
document.getElementById("alert-response" ).classList.remove('alert-primary' );
|
||||||
|
}
|
||||||
|
|
||||||
|
function loadingResponse() {
|
||||||
|
flushResponse();
|
||||||
|
document.getElementById("alert-status" ).innerHTML = "Loading...";
|
||||||
|
document.getElementById("alert-desc" ).innerHTML = "Please wait...";
|
||||||
|
document.getElementById("alert-response").classList.add('alert-primary');
|
||||||
|
document.getElementById("alert-response").style.display = 'block';
|
||||||
|
}
|
||||||
|
|
||||||
|
function responseAlert(response) {
|
||||||
|
flushResponse();
|
||||||
|
const obj = JSON.parse(response);
|
||||||
|
if (obj.status == "success" ) {
|
||||||
|
document.getElementById("form").style.display = 'none';
|
||||||
|
document.getElementById("alert-response").classList.add('alert-success' );
|
||||||
|
}
|
||||||
|
if (obj.status == "failed" ) document.getElementById("alert-response").classList.add('alert-danger' );
|
||||||
|
document.getElementById("alert-status" ).innerHTML = obj.status;
|
||||||
|
document.getElementById("alert-desc" ).innerHTML = obj.desc;
|
||||||
|
document.getElementById("alert-response").style.display = 'block';
|
||||||
|
}
|
||||||
|
|
||||||
|
function onSubmit() {
|
||||||
|
loadingResponse();
|
||||||
|
const queryString = window.location.search;
|
||||||
|
const urlParams = new URLSearchParams(queryString);
|
||||||
|
const token = urlParams.get('token')
|
||||||
|
var password = document.getElementById("form-password").value;
|
||||||
|
var url = "/api/auth/password/forgot/change";
|
||||||
|
var payload = {
|
||||||
|
"token" : token,
|
||||||
|
"password" : password
|
||||||
|
};
|
||||||
|
sendHttpRequest(url, "POST", payload, function (error, response) {
|
||||||
|
if (error) console.error("Error:", error);
|
||||||
|
else {
|
||||||
|
console.log("JSON Response:", response);
|
||||||
|
responseAlert(response);
|
||||||
|
}
|
||||||
|
}, "application/json");
|
||||||
|
}
|
||||||
|
|
||||||
|
flushResponse();
|
@ -7,6 +7,13 @@
|
|||||||
|
|
||||||
from core import html
|
from core import html
|
||||||
|
|
||||||
|
static = [
|
||||||
|
{
|
||||||
|
"route" : "/templates/plain/css/<filepath:re:.*\.(css|sass|css.map)>",
|
||||||
|
"root" : "./templates/plain/static/css"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
def main(dir, page):
|
def main(dir, page):
|
||||||
html_template = html.main.get_html("templates/plain/html")
|
html_template = html.main.get_html("templates/plain/html")
|
||||||
html_page = html.main.get_html(dir)
|
html_page = html.main.get_html(dir)
|
||||||
|
Loading…
Reference in New Issue
Block a user