tobe-test

1 parent 9fa85a52
...@@ -16,13 +16,12 @@ pyramid.debug_templates = true ...@@ -16,13 +16,12 @@ pyramid.debug_templates = true
default_locale_name = id default_locale_name = id
sqlalchemy.url = postgresql://aagusti:a@localhost:5432/demo2 sqlalchemy.url = postgresql://aagusti:a@localhost:5432/demo2
session.url = postgresql://aagusti:a@localhost:5432/demo2 session.url = postgresql://aagusti:a@localhost:5432/demo2
pyramid.includes = pyramid.includes =
pyramid_tm pyramid_tm
pyramid_beaker pyramid_beaker
pyramid_chameleon pyramid_chameleon
pyramid_debugtoolbar
pyramid_rpc.jsonrpc pyramid_rpc.jsonrpc
pyramid_debugtoolbar
session.type = ext:database session.type = ext:database
...@@ -73,7 +72,7 @@ login_captcha = 1 ...@@ -73,7 +72,7 @@ login_captcha = 1
; ;
;modules = ;modules =
menus = login:Login menus = login:Login
; pjdl:PJDL register:PJDL
; bphtb:BPHTB ; bphtb:BPHTB
; five:Five ; five:Five
;app_name = GAJI ASN ;app_name = GAJI ASN
...@@ -117,20 +116,19 @@ port = 6543 ...@@ -117,20 +116,19 @@ port = 6543
keys = root, opensipkd, sqlalchemy keys = root, opensipkd, sqlalchemy
[handlers] [handlers]
keys = console keys = console, filelog
#, filelog, tabel #, tabel
[formatters] [formatters]
keys = generic keys = generic
[logger_root] [logger_root]
level = WARN level = WARN
handlers = console handlers =
#, filelog, tabel #, tabel
[logger_opensipkd] [logger_opensipkd]
level = DEBUG level = DEBUG
handlers = handlers =console, filelog
qualname = opensipkd qualname = opensipkd
[logger_sqlalchemy] [logger_sqlalchemy]
...@@ -143,8 +141,9 @@ qualname = sqlalchemy.engine ...@@ -143,8 +141,9 @@ qualname = sqlalchemy.engine
[handler_filelog] [handler_filelog]
class = FileHandler class = FileHandler
args = ('log_file_location','a') ; args = ('log_file','a')
level = INFO args = ('/tmp/logs/opensipkd.log','a')
level = DEBUG
formatter = generic formatter = generic
......
...@@ -15,16 +15,14 @@ pyramid.debug_routematch = true ...@@ -15,16 +15,14 @@ pyramid.debug_routematch = true
pyramid.debug_templates = true pyramid.debug_templates = true
default_locale_name = id default_locale_name = id
sqlalchemy.url = postgresql://aagusti:a@localhost:5432/demo2 sqlalchemy.url = postgresql://aagusti:a@localhost:5432/demo2
session.url = postgresql://aagusti:a@localhost:5433/demo2 session.url = postgresql://aagusti:a@localhost:5432/demo2
temp_dir = C:\tmp
allow_register = true
pyramid.includes = pyramid.includes =
pyramid_tm pyramid_tm
pyramid_beaker pyramid_beaker
pyramid_chameleon pyramid_chameleon
pyramid_debugtoolbar
pyramid_rpc.jsonrpc pyramid_rpc.jsonrpc
pyramid_debugtoolbar
session.type = ext:database session.type = ext:database
session.secret = s0s3cr3ts session.secret = s0s3cr3ts
...@@ -37,6 +35,20 @@ timezone = Asia/Jakarta ...@@ -37,6 +35,20 @@ timezone = Asia/Jakarta
#localization = Indonesian_indonesia.1252 #localization = Indonesian_indonesia.1252
localization = English_Australia.1252 localization = English_Australia.1252
# Base Configuration
temp_files = C:\tmp
partner_doc = C:\\tmp\\docs\\partner\\
# Registrasi User
allow_register = 1
reg_form =
reg_idcard = 1
reg_captcha = 1
reg_verify = 1
;reg_form =
login_tpl =
login_captcha = 1
;login_tpl = opensipkd.samsat.jabar.views:templates/login.pt ;login_tpl = opensipkd.samsat.jabar.views:templates/login.pt
;static_files = %(here)s/../files ;static_files = %(here)s/../files
...@@ -60,7 +72,7 @@ localization = English_Australia.1252 ...@@ -60,7 +72,7 @@ localization = English_Australia.1252
; ;
;modules = ;modules =
menus = login:Login menus = login:Login
; pjdl:PJDL register:PJDL
; bphtb:BPHTB ; bphtb:BPHTB
; five:Five ; five:Five
;app_name = GAJI ASN ;app_name = GAJI ASN
...@@ -68,13 +80,7 @@ menus = login:Login ...@@ -68,13 +80,7 @@ menus = login:Login
;change_unit = False ;change_unit = False
;departemen_chg_id = 3 ;departemen_chg_id = 3
# Registrasi User
;captcha_files = /tmp/captcha
;reg_captcha = 0
;reg_idcard = 1
;reg_verify = 1
;reg_form =
;login_tpl =
# digunakan jika akan menggunakan form registrasi sendiri # digunakan jika akan menggunakan form registrasi sendiri
...@@ -110,20 +116,19 @@ port = 6543 ...@@ -110,20 +116,19 @@ port = 6543
keys = root, opensipkd, sqlalchemy keys = root, opensipkd, sqlalchemy
[handlers] [handlers]
keys = console keys = console, filelog
#, filelog, tabel #, tabel
[formatters] [formatters]
keys = generic keys = generic
[logger_root] [logger_root]
level = WARN level = WARN
handlers = console handlers =
#, filelog, tabel #, tabel
[logger_opensipkd] [logger_opensipkd]
level = DEBUG level = DEBUG
handlers = handlers =console, filelog
qualname = opensipkd qualname = opensipkd
[logger_sqlalchemy] [logger_sqlalchemy]
...@@ -136,8 +141,9 @@ qualname = sqlalchemy.engine ...@@ -136,8 +141,9 @@ qualname = sqlalchemy.engine
[handler_filelog] [handler_filelog]
class = FileHandler class = FileHandler
args = ('log_file_location','a') ; args = ('log_file','a')
level = INFO args = ('/tmp/logs/opensipkd.log','a')
level = DEBUG
formatter = generic formatter = generic
...@@ -163,7 +169,7 @@ script_location = ziggurat_foundations:migrations ...@@ -163,7 +169,7 @@ script_location = ziggurat_foundations:migrations
sqlalchemy.url = postgresql://aagusti:a@localhost:5432/demo2 sqlalchemy.url = postgresql://aagusti:a@localhost:5432/demo2
[alembic_base] [alembic_base]
script_location = opensipkd.base:alembic script_location = opensipkd.base.scripts:alembic
sqlalchemy.url = postgresql://aagusti:a@localhost:5432/demo2 sqlalchemy.url = postgresql://aagusti:a@localhost:5432/demo2
[pytest] [pytest]
......
...@@ -397,6 +397,7 @@ class BaseApp(): ...@@ -397,6 +397,7 @@ class BaseApp():
self.reg_form = "" self.reg_form = ""
self.reg_captcha = "" self.reg_captcha = ""
self.captcha_files = "" self.captcha_files = ""
self.login_captcha = 0
def static_view(self, config, settings=None): def static_view(self, config, settings=None):
self.partner_doc = get_params( self.partner_doc = get_params(
...@@ -421,10 +422,12 @@ class BaseApp(): ...@@ -421,10 +422,12 @@ class BaseApp():
self.captcha_files = os.path.join(self.temp_files, "captcha")+os.sep self.captcha_files = os.path.join(self.temp_files, "captcha")+os.sep
if not os.path.exists(self.captcha_files): if not os.path.exists(self.captcha_files):
os.makedirs(self.captcha_files) os.makedirs(self.captcha_files)
config.add_static_view( config.add_static_view(
'captcha', self.captcha_files, cache_max_age=0) 'captcha', self.captcha_files, cache_max_age=0)
self.login_tpl = get_params("login_tpl", "", settings=settings)
self.login_captcha = get_params("login_captcha", 0, settings=settings)
def add_menu(self, config, route_menus, parent=None, paket="opensipkd.base.views"): def add_menu(self, config, route_menus, parent=None, paket="opensipkd.base.views"):
route_names = [] route_names = []
...@@ -523,6 +526,7 @@ class BaseApp(): ...@@ -523,6 +526,7 @@ class BaseApp():
self.add_menu(config, new_routes, paket) self.add_menu(config, new_routes, paket)
def get_menus(self): def get_menus(self):
_logging.debug(f"Menus: {self.menus}")
return self.menus return self.menus
...@@ -543,6 +547,8 @@ def has_permission_(request, perm_names, context=None): ...@@ -543,6 +547,8 @@ def has_permission_(request, perm_names, context=None):
@subscriber(BeforeRender) @subscriber(BeforeRender)
def add_global(event): def add_global(event):
event['has_permission'] = has_permission_ event['has_permission'] = has_permission_
event['get_base_menus'] = BASE_CLASS.get_menus
# event['has_modules'] = has_modules_ # event['has_modules'] = has_modules_
# event['urlencode'] = urlencode # event['urlencode'] = urlencode
# event['quote_plus'] = quote_plus # event['quote_plus'] = quote_plus
......
...@@ -110,7 +110,7 @@ class DefaultModel(CommonModel): ...@@ -110,7 +110,7 @@ class DefaultModel(CommonModel):
return query return query
@classmethod @classmethod
def query_from(cls, db_session=DBSession, columns=None, filters=None): def query_from(cls, db_session=DBSession, columns=[], filters=None):
query = db_session.query().select_from(cls) query = db_session.query().select_from(cls)
for c in columns: for c in columns:
query = query.add_columns(c) query = query.add_columns(c)
......
...@@ -97,6 +97,13 @@ class Partner(Base, PartnerModel): ...@@ -97,6 +97,13 @@ class Partner(Base, PartnerModel):
row = cls.query().filter_by(mobile=ident).first() row = cls.query().filter_by(mobile=ident).first()
return row return row
@classmethod
def query_register(cls):
columns= [cls.kode, cls.nama, cls.mobile, cls.email, cls.status]
return cls.query_from(columns=columns)
class PartnerFiles(Base, StandarModel): class PartnerFiles(Base, StandarModel):
__tablename__ = 'partner_files' __tablename__ = 'partner_files'
......
kode,path,module,file_name,class_name,func_name,order_id,permission,parent_id/routes.kode,nama,status,type,app_id,is_menu,template,csrf, kode,path,module,file_name,class_name,func_name,order_id,permission,parent_id/routes.kode,nama,status,type,app_id,is_menu,template,csrf,
base-home,/,base,__init__,Home,view_home,1,,,Home,1,0,,1,home.pt,, base-home,/,base,__init__,Home,view_home,1,,,Home,1,0,,1,home.pt,,
base-login,/login,base,user_login,ViewLogin,view_login,1,,,Login,1,0,,1,,1, base-login,/login,base,user_login,ViewAuth,view_login,1,,,Login,1,0,,0,form6.pt,1,
base-logout,/logout,base,user_login,ViewLogout,view_logout,1,,,Logout,1,0,,1,logout.pt,, base-logout,/logout,base,user_login,ViewAuth,view_logout,1,,,Logout,1,0,,0,logout.pt,,
base-admin,,base,,,,,,,,,,,1,,, base-password-reset,/password/reset,base,user_login,ViewPassword,reset_password,,,,Reset Password,1,0,,0,form6.pt,,
base-password,/password,base,user_login,ViewPassword,change_password,1,view,,Change Password,1,0,,0,form8.pt,,
base-password-request,/password/{code}/request,base,user_login,ViewPassword,change_password_request,1,,,Change Password,1,0,,0,form8.pt,,
base-profile,/profile,base,register,,view_profile,,,,Profile,1,0,,0,form.pt,,
base-register,/register,base,register,,view_register,,,,Register,1,0,,0,form.pt,, base-register,/register,base,register,,view_register,,,,Register,1,0,,0,form.pt,,
base-user,/user,base,user,,view_list,,user-view,,User List,1,0,,1,form.pt,, base-recreate-api-key,/recreate-api-key,base,register,ViewPassword,recreate-api-key,,,,Get Api Key,1,0,,0,recreate-api-key.pt,,
base-user-act,/user/{act}/act,base,user,,,,user-view,,User Action,1,0,,,json,, base-admin,#,,,,,,view,,Administrator,1,0,,1,,,
base-user-add,/user/add,base,user,,,,user-edit,,User Add,1,0,,,form6.pt,, base-user,/user,base,user,,view_list,,user-view,base-admin,User,1,0,,1,form.pt,,
base-user-edit,/user/{id}/edit,base,user,,,,user-edit,,User Edit,1,0,,,form6.pt,, base-user-act,/user/{act}/act,base,user,,,,user-view,base-user,User Action,1,0,,,json,,
base-user-view,/user/{id}/view,base,user,,,,user-view,,User View,1,0,,,form6.pt,, base-user-add,/user/add,base,user,,,,user-edit,base-user,User Add,1,0,,,form6.pt,,
base-user-delete,/user/{id}/delete,base,user,,,,user-edit,,User Delete,1,0,,,form6.pt,, base-user-edit,/user/{id}/edit,base,user,,,,user-edit,base-user,User Edit,1,0,,,form6.pt,,
base-partner,/partner,base,partner,,view_list,,admin,,Partner,1,0,,1,form.pt,, base-user-view,/user/{id}/view,base,user,,,,user-view,base-user,User View,1,0,,,form6.pt,,
base-partner-act,/partner/{act}/act,base,partner,,,,admin,,Partner Action,1,0,,,json,, base-user-delete,/user/{id}/delete,base,user,,,,user-edit,base-user,User Delete,1,0,,,form6.pt,,
base-partner-add,/partner/add,base,partner,,,,admin,,Partner Add,1,0,,,form6.pt,, base-partner,/partner,base,partner,,view_list,,admin,base-admin,Partner,1,0,,1,form.pt,,
base-partner-edit,/partner/{id}/edit,base,partner,,,,admin,,Partner Edit,1,0,,,form6.pt,, base-partner-act,/partner/{act}/act,base,partner,,,,admin,base-partner,Partner Action,1,0,,,json,,
base-partner-view,/partner/{id}/view,base,partner,,,,admin,,Partner View,1,0,,,form6.pt,, base-partner-add,/partner/add,base,partner,,,,admin,base-partner,Partner Add,1,0,,,form6.pt,,
base-partner-delete,/partner/{id}/delete,base,partner,,,,admin,,Partner Delete,1,0,,,form6.pt,, base-partner-edit,/partner/{id}/edit,base,partner,,,,admin,base-partner,Partner Edit,1,0,,,form6.pt,,
base-partner-upload,/partner/upload,base,partner,,,,admin,,Partner Uload,1,0,,,form6.pt,, base-partner-view,/partner/{id}/view,base,partner,,,,admin,base-partner,Partner View,1,0,,,form6.pt,,
base-partner-delete,/partner/{id}/delete,base,partner,,,,admin,base-partner,Partner Delete,1,0,,,form6.pt,,
base-partner-upload,/partner/upload,base,partner,,,,admin,base-partner,Partner Uload,1,0,,,form6.pt,,
,,,,,,,,,,,,,,,, ,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,, ,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,, ,,,,,,,,,,,,,,,,
......
...@@ -49,7 +49,7 @@ def http_forbidden(request): ...@@ -49,7 +49,7 @@ def http_forbidden(request):
# next_url = get_urls( # next_url = get_urls(
# request.route_url( # request.route_url(
# 'login', _query={'next': request.url})) # 'login', _query={'next': request.url}))
next_url = request.route_url('login', _query={'next': request.url}) next_url = request.route_url('base-login', _query={'next': request.url})
return HTTPSeeOther(location=next_url) return HTTPSeeOther(location=next_url)
request.response.status = 403 request.response.status = 403
......
...@@ -556,16 +556,16 @@ class BaseView(object): ...@@ -556,16 +556,16 @@ class BaseView(object):
def get_bindings(self, row=None): def get_bindings(self, row=None):
return {"row": row} return {"row": row}
# def next_edit(self, form, **kwargs): def next_edit(self, form, **kwargs):
# """Digunakan untuk memproses button post yang lainnya """Digunakan untuk memproses button post yang lainnya
# Args: Args:
# form (_type_): _description_ form (_type_): _description_
# Returns: Returns:
# _type_: _description_ _type_: _description_
# """ """
# return self.route_list(**kwargs) return self.route_list(**kwargs)
def returned_form(self, form, table=None, **kwargs): def returned_form(self, form, table=None, **kwargs):
resources = form.get_widget_resources() resources = form.get_widget_resources()
...@@ -576,8 +576,6 @@ class BaseView(object): ...@@ -576,8 +576,6 @@ class BaseView(object):
resources["js"].extend(set(table["js"]) - set(resources["js"])) resources["js"].extend(set(table["js"]) - set(resources["js"]))
resources["css"].extend(set(table["css"]) - set(resources["css"])) resources["css"].extend(set(table["css"]) - set(resources["css"]))
table = table["form"] table = table["form"]
# resources["js"] = list(resources["js"])
# resources["css"] = list(resources["css"])
if is_object: if is_object:
return dict(form=form, return dict(form=form,
table=table and table.render() or None, table=table and table.render() or None,
...@@ -747,19 +745,19 @@ class BaseView(object): ...@@ -747,19 +745,19 @@ class BaseView(object):
""" """
return self.route_list(**kwargs) return self.route_list(**kwargs)
# def get_captcha_url(self): def get_captcha_url(self):
# return get_urls("/captcha/") + get_captcha(self.req) return self.req.static_url(BASE_CLASS.captcha_files)
# def update_value(self, value, cstruct): def update_value(self, value, cstruct):
# for k in cstruct: for k in cstruct:
# val = cstruct.get(k) val = cstruct.get(k)
# if type(val) is dict: if type(val) is dict:
# if k not in value: if k not in value:
# value[k] = {} value[k] = {}
# value[k] = self.update_value(value[k], val) value[k] = self.update_value(value[k], val)
# elif val: elif val:
# value[k] = cstruct.get(k) value[k] = cstruct.get(k)
# return value return value
def view_add(self, **kwargs): def view_add(self, **kwargs):
# bindings = self.get_bindings() # bindings = self.get_bindings()
...@@ -800,7 +798,7 @@ class BaseView(object): ...@@ -800,7 +798,7 @@ class BaseView(object):
return self.returned_form(form, table, **kwargs) return self.returned_form(form, table, **kwargs)
def save(self, values, user, row=None): def save(self, values, user, row=None):
log.info("Save") log.debug("Save")
log.debug(values) log.debug(values)
values.pop("id", None) values.pop("id", None)
self.ses["old_email"] = user and user.email or None self.ses["old_email"] = user and user.email or None
......
...@@ -134,10 +134,6 @@ class Views(BaseView): ...@@ -134,10 +134,6 @@ class Views(BaseView):
# } # }
# return super().view_list(new_buttons=new_buttons) # return super().view_list(new_buttons=new_buttons)
# # @view_config(route_name='partner-act', renderer='json',
# permission='user-view')
# def view_act(self):
# return super().view_act()
def next_act(self): def next_act(self):
request = self.req request = self.req
...@@ -203,26 +199,6 @@ class Views(BaseView): ...@@ -203,26 +199,6 @@ class Views(BaseView):
r.append(d) r.append(d)
return r return r
# @view_config(route_name='partner-add', renderer='templates/form.pt',
# permission='user-edit')
# def view_add(self):
# return super().view_add()
# @view_config(route_name='partner-edit', renderer='templates/form.pt',
# permission='user-edit')
# def view_edt(self):
# return super().view_edit()
# @view_config(route_name='partner-view', renderer='templates/form.pt',
# permission='user-edit')
# def view_view(self):
# return super().view_view()
# @view_config(route_name='partner-delete', renderer='templates/form.pt',
# permission='user-edit')
# def view_delete(self):
# return super().view_delete()
def form_validator(self, form, value): def form_validator(self, form, value):
def err_kode(): def err_kode():
raise colander.Invalid(form, raise colander.Invalid(form,
...@@ -254,12 +230,6 @@ class Views(BaseView): ...@@ -254,12 +230,6 @@ class Views(BaseView):
else: else:
value.pop("idcard") value.pop("idcard")
# value['is_vendor'] = 'is_vendor' in value and \
# value['is_vendor'] and 1 or 0
# value['is_customer'] = 'is_customer' in value and \
# value['is_customer'] and 1 or 0
# value["status"] = 'status' in value and value['status'] and 1 or 0
def get_bindings(self, row=None): def get_bindings(self, row=None):
result = super().get_bindings(row) result = super().get_bindings(row)
# provinsi_list = ResProvinsi.get_list() # provinsi_list = ResProvinsi.get_list()
...@@ -279,7 +249,7 @@ class Views(BaseView): ...@@ -279,7 +249,7 @@ class Views(BaseView):
return result return result
def save_request(self, values, row=None): # def save_request(self, values, row=None):
# if "idcard" in values and values["idcard"]: # if "idcard" in values and values["idcard"]:
# if str(self.req.POST['upload']) != "": # if str(self.req.POST['upload']) != "":
# folder = self.get_params("idcard_folder", '/tmp/idcard') # folder = self.get_params("idcard_folder", '/tmp/idcard')
...@@ -289,8 +259,8 @@ class Views(BaseView): ...@@ -289,8 +259,8 @@ class Views(BaseView):
# else: # else:
# del values["idcard"] # del values["idcard"]
row = super().save_request(values, row) # row = super().save_request(values, row)
return row # return row
def get_values(self, row, istime=False): def get_values(self, row, istime=False):
d = super().get_values(row, istime) d = super().get_values(row, istime)
...@@ -308,6 +278,8 @@ class Views(BaseView): ...@@ -308,6 +278,8 @@ class Views(BaseView):
def before_delete(self, row): def before_delete(self, row):
PartnerFiles.query().filter_by(partner_id=row.id).delete() PartnerFiles.query().filter_by(partner_id=row.id).delete()
def before_delete(self, row):
PartnerFiles.query().filter_by(partner_id=row.id).delete()
@colander.deferred @colander.deferred
def partner_widget(node, kw): def partner_widget(node, kw):
......
...@@ -30,10 +30,10 @@ import logging ...@@ -30,10 +30,10 @@ import logging
from datetime import datetime from datetime import datetime
import colander import colander
from deform import (widget, FileData, ValidationFailure) from deform import (widget, FileData, ValidationFailure, Button)
from opensipkd.base import BASE_CLASS from opensipkd.base import BASE_CLASS
from opensipkd.tools import Upload, mem_tmp_store, image_validator, date_from_str from opensipkd.tools import Upload, mem_tmp_store, image_validator, date_from_str
from opensipkd.tools.buttons import btn_cancel, btn_register, btn_save from opensipkd.tools.buttons import btn_cancel, btn_save
from pyramid.httpexceptions import HTTPFound, HTTPNotFound from pyramid.httpexceptions import HTTPFound, HTTPNotFound
from pyramid.i18n import TranslationStringFactory from pyramid.i18n import TranslationStringFactory
# from pyramid.security import forget # from pyramid.security import forget
...@@ -45,7 +45,7 @@ from opensipkd.base.views.user import email_validator, add_member_count ...@@ -45,7 +45,7 @@ from opensipkd.base.views.user import email_validator, add_member_count
from ..models import User, DBSession, Partner, Group, UserGroup from ..models import User, DBSession, Partner, Group, UserGroup
from ..widgets import widget_os from ..widgets import widget_os
# from .base_views import need_captcha, get_url_captcha # from .base_views import need_captcha, get_url_captcha
# from .user_login import regenerate_security_code, send_email_security_code from .user_login import regenerate_security_code, send_email_security_code
from ..views import BaseView from ..views import BaseView
# from .. import get_urls # from .. import get_urls
...@@ -90,7 +90,7 @@ class AddSchema(colander.Schema): ...@@ -90,7 +90,7 @@ class AddSchema(colander.Schema):
self["email"].missing = colander.drop self["email"].missing = colander.drop
self["email"].validator = None self["email"].validator = None
if is_id_card == '1' or is_id_card == "True" or is_id_card == "true": if is_id_card:
self["kode"] = colander.SchemaNode( self["kode"] = colander.SchemaNode(
colander.String(), colander.String(),
widget=widget.TextInputWidget(), widget=widget.TextInputWidget(),
...@@ -106,14 +106,12 @@ class AddSchema(colander.Schema): ...@@ -106,14 +106,12 @@ class AddSchema(colander.Schema):
if not request.user and BASE_CLASS.reg_captcha: if not request.user and BASE_CLASS.reg_captcha:
self["captcha"] = colander.SchemaNode( self["captcha"] = colander.SchemaNode(
colander.String(), colander.String(),
widget=widget_os.CaptchaWidget(request=request, widget=widget_os.CaptchaWidget(
url=request.static_url( request=request,
BASE_CLASS.captcha_files)), url=request.static_url(BASE_CLASS.captcha_files)),
oid="captcha", title=_("Captcha")) oid="captcha", title=_("Captcha"))
if request.user and request.user.id and not external_user: if request.user and request.user.id and not external_user:
# todo: external user tidak ada password
# validasi harusnya menggunakan authentikasi ke provider lagi
self["password"] = colander.SchemaNode( self["password"] = colander.SchemaNode(
colander.String(), colander.String(),
widget=widget.PasswordWidget(), widget=widget.PasswordWidget(),
...@@ -127,20 +125,20 @@ class EditSchema(AddSchema): ...@@ -127,20 +125,20 @@ class EditSchema(AddSchema):
del self["email"] del self["email"]
# def user_found(identity): def user_found(identity):
# return User.get_by_identity(identity) return User.get_by_identity(identity)
# def mobile_found_partner(mobile): # def mobile_found_partner(mobile):
# return Partner.query_mobile(mobile) # return Partner.query_mobile(mobile)
# def email_found_partner(email): def email_found_partner(email):
# return Partner.query_email(email).first() return Partner.query_email(email).first()
# def nik_found(nik): def nik_found(nik):
# return Partner.query_kode(nik).first() return Partner.query_kode(nik).first()
# def _show_error(request, msg): # def _show_error(request, msg):
...@@ -153,8 +151,7 @@ class EditSchema(AddSchema): ...@@ -153,8 +151,7 @@ class EditSchema(AddSchema):
# # def reg_buttons(): # # def reg_buttons():
# # btn_register = Button(name='save', css_class='btn-success', type="submit",
# # title="Register")
# # btn_cancel = Button(name='batal', css_class='btn-primary', type="submit") # # btn_cancel = Button(name='batal', css_class='btn-primary', type="submit")
# # return btn_cancel, btn_register # # return btn_cancel, btn_register
...@@ -163,137 +160,138 @@ class Views(BaseView): ...@@ -163,137 +160,138 @@ class Views(BaseView):
def __init__(self, request): def __init__(self, request):
super().__init__(request) super().__init__(request)
self.autocomplete = "off" self.autocomplete = "off"
btn_register = Button(name='save', css_class='btn-success', type="submit",
title="Register")
self.buttons = (btn_register, btn_cancel) self.buttons = (btn_register, btn_cancel)
self.add_schema = AddSchema self.add_schema = AddSchema
self.edit_schema = EditSchema self.edit_schema = EditSchema
self.table = Partner self.table = Partner
self.list_route = "home" self.list_route = "base-home"
def form_validator(self, form, value):
"""
Default "value"
user_name = mobile
kode = mobile
Validasi saat Register
1. Cek email pada Users jika ada dan Users.id beda reject
2. Cek email pada Partner jika ada dan Partner.id beda reject
3. Cek kode pada Partner jika ada dan Partner.id beda reject
4. Cek mobile pada Partner jika ada dan Users.id beda reject
"""
_logging.debug(value)
form_exc = colander.Invalid(form, '')
request = form.request
session = request.session
def raise_err(field, msg):
form_exc[field] = msg
raise form_exc
# def err_captcha():
# msg = 'Captcha berbeda'
# raise_err('captcha', msg)
def err_email():
msg = 'e-mail %s sudah ada yang menggunakan' % value['email']
raise_err('email', msg)
def err_user():
if 'user_name' in form:
msg = 'User name %s sudah ada yang menggunakan' % value[
'user_name']
raise_err('user_name', msg)
else:
msg = 'Email %s sudah ada yang menggunakan' % value['email']
raise_err('email', msg)
def err_nik():
if "kode" in form:
msg = 'NIK %s sudah ada yang menggunakan' % value['kode']
raise_err('kode', msg)
else:
msg = 'Mobile %s sudah ada yang menggunakan' % value['kode']
raise_err('mobile', msg)
def err_login():
msg = 'User atau Password tidak sesuai'
raise_err('password', msg)
# if not request.user and need_captcha():
# captcha = 'captcha' in value and value['captcha'].upper() or None
# ses_captcha = request.session.pop('captcha')
# if captcha != ses_captcha:
# err_captcha()
# def form_validator(self, form, value): user = request.user
# """ if "email" not in value and "id_info" in session:
# Default "value" value["email"] = session["id_info"]["email"]
# user_name = mobile
# kode = mobile if not user and (
# Validasi saat Register "user_name" not in value or not value["user_name"]):
# 1. Cek email pada Users jika ada dan Users.id beda reject value["user_name"] = value["email"]
# 2. Cek email pada Partner jika ada dan Partner.id beda reject
# 3. Cek kode pada Partner jika ada dan Partner.id beda reject if 'user_name' in value:
# 4. Cek mobile pada Partner jika ada dan Users.id beda reject user_name = value["user_name"]
# """ found = user_found(user_name)
# _logging.debug(value) if found and not user:
# form_exc = colander.Invalid(form, '') err_user()
# request = form.request
# session = request.session if found and user:
if user.id != found.id:
# def raise_err(field, msg): err_user()
# form_exc[field] = msg
# raise form_exc # Check Data Partner
if user:
# def err_captcha(): q = DBSession.query(Partner).filter_by(email=user.email)
# msg = 'Captcha berbeda' partner = q.first()
# raise_err('captcha', msg) else:
partner = None
# def err_email():
# msg = 'e-mail %s sudah ada yang menggunakan' % value['email'] if not user:
# raise_err('email', msg) email = value["email"]
found = user_found(email)
# def err_user(): if found and not user:
# if 'user_name' in form: err_email()
# msg = 'User name %s sudah ada yang menggunakan' % value[
# 'user_name'] if found and user:
# raise_err('user_name', msg) if user.id != found.id:
# else: err_email()
# msg = 'Email %s sudah ada yang menggunakan' % value['email']
# raise_err('email', msg) found = email_found_partner(email)
if partner:
# def err_nik(): if found and found.id != partner.id:
# if "kode" in form: err_email()
# msg = 'NIK %s sudah ada yang menggunakan' % value['kode'] elif found:
# raise_err('kode', msg) err_email()
# else: if "kode" not in value or not value["kode"]:
# msg = 'Mobile %s sudah ada yang menggunakan' % value['kode'] value["kode"] = value["mobile"]
# raise_err('mobile', msg)
if 'kode' in value:
# def err_login(): found_nik = nik_found(value['kode'])
# msg = 'User atau Password tidak sesuai' if partner:
# raise_err('password', msg) if found_nik and found_nik.id != partner.id:
err_nik()
# if not request.user and need_captcha(): elif found_nik:
# captcha = 'captcha' in value and value['captcha'].upper() or None err_nik()
# ses_captcha = request.session.pop('captcha')
# if captcha != ses_captcha: if 'password' in value:
# err_captcha() if not user or not UserService.check_password(
user, value['password']):
# user = request.user err_login()
# if "email" not in value and "id_info" in session:
# value["email"] = session["id_info"]["email"] if "idcard" in value and value["idcard"]:
idcard = value["idcard"]
# if not user and ( if "fp" in idcard and idcard["fp"] and idcard["fp"] != b'':
# "user_name" not in value or not value["user_name"]): path = BASE_CLASS.reg_id_card
# value["user_name"] = value["email"] _logging.debug(idcard["fp"])
upload = Upload(path)
# if 'user_name' in value: value["idcard"] = upload.save_fp(idcard)
# user_name = value["user_name"] else:
# found = user_found(user_name) value.pop("idcard")
# if found and not user: value["groups"] = "Guest"
# err_user()
# if found and user:
# if user.id != found.id:
# err_user()
# # Check Data Partner
# if user:
# q = DBSession.query(Partner).filter_by(email=user.email)
# partner = q.first()
# else:
# partner = None
# if not user:
# email = value["email"]
# found = user_found(email)
# if found and not user:
# err_email()
# if found and user:
# if user.id != found.id:
# err_email()
# found = email_found_partner(email)
# if partner:
# if found and found.id != partner.id:
# err_email()
# elif found:
# err_email()
# if "kode" not in value or not value["kode"]:
# value["kode"] = value["mobile"]
# if 'kode' in value:
# found_nik = nik_found(value['kode'])
# if partner:
# if found_nik and found_nik.id != partner.id:
# err_nik()
# elif found_nik:
# err_nik()
# if 'password' in value:
# if not user or not UserService.check_password(
# user, value['password']):
# err_login()
# if "idcard" in value and value["idcard"]:
# idcard = value["idcard"]
# if "fp" in idcard and idcard["fp"] and idcard["fp"] != b'':
# path = get_id_card_folder()
# _logging.debug(idcard["fp"])
# upload = Upload(path)
# value["idcard"] = upload.save_fp(idcard)
# else:
# value.pop("idcard")
# value["groups"] = "Guest"
def before_add(self): def before_add(self):
result = {} result = {}
...@@ -315,13 +313,13 @@ class Views(BaseView): ...@@ -315,13 +313,13 @@ class Views(BaseView):
# self.ses.delete() # self.ses.delete()
def view_register(self): def view_register(self):
if not BASE_CLASS.allow_register:
return HTTPNotFound()
self.bindings = dict(user=None)
request = self.req request = self.req
if not BASE_CLASS.allow_register:
return HTTPFound(location=request.route_url("base-home"))
if request.user: if request.user:
return HTTPFound(location=request.route_url("profile")) return HTTPFound(location=request.route_url("base-profile"))
self.bindings = dict(user=None)
if "g_state" in self.req.cookies: if "g_state" in self.req.cookies:
if "id_info" not in self.ses or not self.ses["id_info"]: if "id_info" not in self.ses or not self.ses["id_info"]:
return HTTPFound(location=self.req.route_url("login")) return HTTPFound(location=self.req.route_url("login"))
...@@ -329,92 +327,98 @@ class Views(BaseView): ...@@ -329,92 +327,98 @@ class Views(BaseView):
reg_form = BASE_CLASS.reg_form reg_form = BASE_CLASS.reg_form
if reg_form != "base-register": if reg_form != "base-register":
return HTTPFound(location=self.req.route_url(reg_form)) return HTTPFound(location=self.req.route_url(reg_form))
return super().view_add() return super().view_add()
# def query_id(self): def save_request(self, values, row=None):
# return DBSession.query(Partner). \ if not "email" in values or not values["email"]:
# filter(Partner.email == self.req.user.email) values["email"] = self.req.user and self.req.user.email or ""
if not row:
values["is_vendor"] = 0
values["is_customer"] = 1
row = super().save_request(values, row)
def after_save(self, values, row):
# User Baru
if not self.req.user:
#todo: simplikasi lagi disini
user = User()
user.email = row.email
user.user_name = row.email
user.registered_date = datetime.now()
self.db_session.add(user)
self.db_session.flush()
if 'groups' in values and values['groups']:
gr = Group.query_group_name(values['groups']).first()
ug = UserGroup()
ug.user_id = user.id
ug.group_id = gr.id
self.db_session.add(ug)
add_member_count(gr.id)
self.db_session.flush()
remain = regenerate_security_code(user)
send_email_security_code(
self.req, user, remain, 'Welcome new user', 'email-new-user',
'email-new-user.tpl')
ts = _(
'user-added',
default='${email} berhasil ditambahkan dan email untuk ubah '
'kata kunci sudah dikirim.',
mapping={"email": row.email})
self.ses.flash(ts)
return super().after_save(values, row)
return row
def query_id(self):
return DBSession.query(Partner). \
filter(Partner.email == self.req.user.email)
# def id_not_found(self, **kwargs): # def id_not_found(self, **kwargs):
# return # return
# def get_values(self, row, istime=False): def get_values(self, row, istime=False):
# d = super().get_values(row, istime) d = super().get_values(row, istime)
# partner = DBSession.query(Partner). \ partner = DBSession.query(Partner). \
# filter(Partner.email == self.req.user.email).first() filter(Partner.email == self.req.user.email).first()
# if partner: if partner:
# fields = ["nama", "alamat_1", "alamat_2", "mobile", "email", "kode", fields = ["nama", "alamat_1", "alamat_2", "mobile", "email", "kode",
# "idcard"] "idcard"]
# for f in fields: for f in fields:
# d[f] = hasattr(partner, f) and getattr(partner, f) or "" d[f] = hasattr(partner, f) and getattr(partner, f) or ""
# if "idcard" in d: if "idcard" in d:
# if d["idcard"]: if d["idcard"]:
# filename = d["idcard"] filename = d["idcard"]
# preview_url = "/".join( preview_url = "/".join(
# [self.req.static_url(get_id_card_folder('/')), [self.req.static_url(BASE_CLASS.reg_id_card),
# filename]) filename])
# d["idcard"] = {"uid": filename.split(".")[0], d["idcard"] = {"uid": filename.split(".")[0],
# "filename": filename, "filename": filename,
# "preview_url": preview_url "preview_url": preview_url
# } }
# else: else:
# d.pop("idcard") d.pop("idcard")
# else: else:
# d.pop("idcard") d.pop("idcard")
# return d return d
# # def before_add(self): # def before_add(self):
# @view_config(route_name='profile', renderer='templates/form.pt',
# permission='view')
def view_profile(self): def view_profile(self):
self.buttons = (btn_save, btn_cancel) self.buttons = (btn_save, btn_cancel)
reg_form = get_params("reg_form") reg_form =BASE_CLASS.reg_form
if reg_form: if reg_form and reg_form != "base-register":
return HTTPFound(location=get_urls(self.req.route_url(reg_form))) return HTTPFound(location=self.req.route_url(reg_form))
self.bindings = dict(user=self.req.user) self.bindings = dict(user=self.req.user)
resp = super(Registrasi, self).view_edit() partner = Partner.query_email(self.req.user.email).first()
if not resp: if not partner:
resp = super(Registrasi, self).view_add() resp = super().view_add()
else:
resp = super().view_edit()
return resp return resp
# def save_request(self, values, row=None):
# if not "email" in values or not values["email"]:
# values["email"] = self.req.user and self.req.user.email or ""
# if not row:
# values["is_vendor"] = 0
# values["is_customer"] = 1
# row = super().save_request(values, row)
# if not self.req.user: # User Baru
# user = User()
# user.email = row.email
# user.user_name = row.email
# user.registered_date = datetime.now()
# DBSession.add(user)
# DBSession.flush()
# if 'groups' in values and values['groups']:
# gr = Group.query_group_name(values['groups']).first()
# ug = UserGroup()
# ug.user_id = user.id
# ug.group_id = gr.id
# DBSession.add(ug)
# add_member_count(gr.id)
# DBSession.flush()
# remain = regenerate_security_code(user)
# send_email_security_code(
# self.req, user, remain, 'Welcome new user', 'email-new-user',
# 'email-new-user.tpl')
# ts = _(
# 'user-added',
# default='${email} berhasil ditambahkan dan email untuk ubah '
# 'kata kunci sudah dikirim.',
# mapping={"email": row.email})
# self.ses.flash(ts)
# return row
# def next_add(self, form, **kwargs): # def next_add(self, form, **kwargs):
# table = kwargs.get("table") # table = kwargs.get("table")
......
...@@ -125,12 +125,14 @@ ...@@ -125,12 +125,14 @@
</span> </span>
<i class="fa fa-angle-down"></i> </a> <i class="fa fa-angle-down"></i> </a>
<ul class="dropdown-menu pull-right"> <ul class="dropdown-menu pull-right">
<li><a style="text-transform:capitalize" href="{request.route_url('profile')}">Profile</a></li> <li><a style="text-transform:capitalize" href="${request.route_url('base-profile')}">Profile</a>
</li>
<li tal:condition="not request.user.external"> <li tal:condition="not request.user.external">
<a style="text-transform:capitalize" href="{request.route_url('password')}">Ubah <a style="text-transform:capitalize" href="${request.route_url('base-password')}">Ubah
password</a> password</a>
</li> </li>
<li><a style="text-transform:capitalize" href="${request.route_url('base-logout')}">Logout</a></li> <li><a style="text-transform:capitalize" href="${request.route_url('base-logout')}">Logout</a>
</li>
<li tal:condition="request.user.api_key"><a style="text-transform:capitalize" <li tal:condition="request.user.api_key"><a style="text-transform:capitalize"
href="${home}/recreate-api-key">API Key</a></li> href="${home}/recreate-api-key">API Key</a></li>
<!-- <li talcondition="'core' in request.modules and change_unit(request)"> <!-- <li talcondition="'core' in request.modules and change_unit(request)">
...@@ -150,92 +152,51 @@ ...@@ -150,92 +152,51 @@
<!-- Left panel : Navigation area --> <!-- Left panel : Navigation area -->
<!-- Note: This width of the aside area can be adjusted through LESS variables --> <!-- Note: This width of the aside area can be adjusted through LESS variables -->
<aside id="left-panel" style="padding-bottom:67px"> <aside id="left-panel" style="padding-bottom:67px">
Menu
<!-- NAVIGATION : This navigation is also responsive--> <!-- NAVIGATION : This navigation is also responsive-->
<nav style=""> <nav class="smart-menu" id="menu">
<!-- Modul Menu --> <!-- Modul Menu -->
<ul metal:define-slot="navs"></ul>
<!-- Admin Menu -->
<ul tal:condition="has_permission(request, user_path)" style="margin-top: 0; padding-top: 0;">
<li>
<a href="#"><i class="fa fa-lg fa-fw fa-shield"></i><span class="menu-item-parent">Admin</span></a>
<ul>
<li tal:condition="has_permission(request, ['user-view', 'user-edit'])"
tal:attributes="class route_name in user_path and 'active'">
<a href="${home}/user">User</a>
</li>
<li tal:condition="has_permission(request, ['user-view', 'user-edit'])"
tal:attributes="class route_name in user_area_path and 'active'">
<a href="${home}/user/area">User Area</a>
</li>
<li tal:condition="has_permission(request, ['user-view', 'user-edit'])"
tal:attributes="class route_name in user_dep_path and 'active'">
<a href="${home}/user/departemen">User Departemen</a>
</li>
<li tal:condition="has_permission(request, ['user-view', 'user-edit'])"
tal:attributes="class route_name in user_ext_path and 'active'">
<a href="${home}/user/ext">External User</a>
</li>
<li tal:condition="has_permission(request, ['user-view', 'user-edit'])"
tal:attributes="class route_name in group_path and 'active'">
<a href="${home}/group">Group</a>
</li>
<li tal:condition="has_permission(request, 'upload-logo')"
tal:attributes="class route_name in ['upload-logo'] and 'active'">
<a href="${home}/upload/logo">Upload Logo</a>
</li>
<li tal:condition="has_permission(request, 'parameter')"
tal:attributes="class route_name in param_path and 'active'">
<a href="${home}/parameter">Parameter</a>
</li>
<li tal:condition="has_permission(request, 'company')"
tal:attributes="class route_name in company_path and 'active'">
<a href="${home}/company">Pemerintah</a>
</li>
<li tal:condition="has_permission(request, 'eselon')"
tal:attributes="class route_name in eselon_path and 'active'">
<a href="${home}/eselon">Eselon</a>
</li>
<li tal:condition="has_permission(request, 'jabatan')"
tal:attributes="class route_name in jabatan_path and 'active'">
<a href="${home}/jabatan">Jabatan</a>
</li>
<li tal:condition="has_permission(request, 'departemen')" <ul metal:define-slot="navs"></ul>
tal:attributes="class route_name in dep_path and 'active'"> <ul style="margin-top: 0; padding-top: 0;">
<a href="${home}/departemen">Departemen</a> <li tal:repeat="menu get_base_menus()"
</li> tal:attributes="class route_name in menu['route_name'] and 'active'">
<li tal:condition="has_permission(request, 'partner')" <a tal:condition="python:not menu['children'] and has_permission(request, menu['permission'])"
tal:attributes="class route_name in partner_path and 'active'"> href="${home}${menu['path']}">
<a href="${home}/partner">Partner</a> <i tal:condition="menu['icon']" class="fa fa-lg fa-fw ${menu['icon']}"></i>
</li> <span>${menu['nama']}</span>
<li tal:condition="has_permission(request, 'partner-departemen')" </a>
tal:attributes="class route_name in part_dep_path and 'active'"> <a tal:condition="python:menu['children'] and has_permission(request, menu['permission'])" href="#">
<a href="${home}/partner/departemen">Partner Departemen</a> <i tal:condition="menu['icon']" class="fa fa-lg fa-fw ${menu['icon']}"></i>
</li> <span class="menu-item-parent">${menu['nama']}</span>
<li tal:condition="has_permission(request, 'provinsi')" </a>
tal:attributes="class route_name in provinsi_path and 'active'">
<a href="${home}/provinsi">Provinsi</a> <ul tal:condition="python:menu['children'] and has_permission(request, menu['permission'])">
</li> <li tal:repeat="submenu menu['children']"
<li tal:condition="has_permission(request, 'dati2')" tal:attributes="class route_name in submenu['route_name'] and 'active'">
tal:attributes="class route_name in dati2_path and 'active'"> <a tal:condition="python:not submenu['children'] and has_permission(request, submenu['permission'])"
<a href="${home}/dati2">Kabupaten/Kota</a> href="${home}${submenu['path']}">
</li> <i tal:condition="submenu['icon']" class="fa fa-lg fa-fw ${submenu['icon']}"></i>
<li tal:condition="has_permission(request, 'kecamatan')" <span>${submenu['nama']}</span>
tal:attributes="class route_name in kecamatan_path and 'active'"> </a>
<a href="${home}/kecamatan">Kecamatan</a>
</li> <a tal:condition="submenu['children']" href="#">
<li tal:condition="has_permission(request, 'desa')" <i tal:condition="submenu['icon']" class="fa fa-lg fa-fw ${submenu['icon']}"></i>
tal:attributes="class route_name in desa_path and 'active'"> <span class="menu-item-parent">${submenu['nama']}</span>
<a href="${home}/desa">Desa/Kelurahan</a> </a>
<ul tal:condition="submenu['children']">
<li tal:repeat="submenu2 submenu['children']"
tal:attributes="class route_name in submenu2['route_name'] and 'active'">
<a href="${home}${submenu2['path']}">${submenu2['nama']}</a>
</li> </li>
<li tal:condition="has_permission(request, 'log')" </ul>
tal:attributes="class route_name in ['log'] and 'active'">
<a href="${home}/log">Log</a>
</li> </li>
</ul> </ul>
</li> </li>
</ul> </ul>
</nav> </nav>
<span class="minifyme" data-action="minifyMenu"> <span class="minifyme" data-action="minifyMenu">
<i class="fa fa-arrow-circle-left hit"></i> <i class="fa fa-arrow-circle-left hit"></i>
......
...@@ -79,6 +79,7 @@ ...@@ -79,6 +79,7 @@
<b class="tooltip tooltip-top-right"><i class="fa fa-lock txt-color-teal"></i> ISI <b class="tooltip tooltip-top-right"><i class="fa fa-lock txt-color-teal"></i> ISI
DENGAN PASSWORD ANDA</b> </label> DENGAN PASSWORD ANDA</b> </label>
</section> </section>
<section> <section>
<div class="form-group"> <div class="form-group">
<label class=" checkbox checkbox-inline"> <label class=" checkbox checkbox-inline">
...@@ -87,16 +88,18 @@ ...@@ -87,16 +88,18 @@
<a href="${home}/reset-password" id="lupa" >Lupa Password?</a> <a href="${home}/reset-password" id="lupa" >Lupa Password?</a>
</div> </div>
</div> </div>
</section> </section>
<section tal:condition="'captcha' in form">
<div tal:define="field form['captcha']">
${structure:field.serialize()}
</div>
</section>
<section> <section tal:condition="'csrf_token' in form">
<div tal:condition="'csrf_token' in form">
<div tal:define="field form['csrf_token']" style="display: none;"> <div tal:define="field form['csrf_token']" style="display: none;">
${structure:field.serialize()} ${structure:field.serialize()}
</div> </div>
</div>
</section> </section>
</fieldset> </fieldset>
......
...@@ -23,7 +23,9 @@ import os ...@@ -23,7 +23,9 @@ import os
import re import re
from datetime import timedelta, datetime from datetime import timedelta, datetime
from importlib import import_module from importlib import import_module
from urllib import request
from bak.opensipkd.base.tools import buttons
import colander import colander
from deform import widget, Form, ValidationFailure, Button from deform import widget, Form, ValidationFailure, Button
from pyramid.csrf import new_csrf_token from pyramid.csrf import new_csrf_token
...@@ -36,7 +38,7 @@ from ziggurat_foundations.models.services.external_identity import \ ...@@ -36,7 +38,7 @@ from ziggurat_foundations.models.services.external_identity import \
ExternalIdentityService ExternalIdentityService
from ziggurat_foundations.models.services.user import UserService from ziggurat_foundations.models.services.user import UserService
from opensipkd.base import BASE_CLASS, DBSession, get_params from opensipkd.base import BASE_CLASS, DBSession, get_params, scripts
from . import one_hour, two_minutes from . import one_hour, two_minutes
from ..models.users import User, ExternalIdentity from ..models.users import User, ExternalIdentity
# , Partner # , Partner
...@@ -45,6 +47,8 @@ from opensipkd.tools.buttons import btn_cancel ...@@ -45,6 +47,8 @@ from opensipkd.tools.buttons import btn_cancel
# from .. import get_urls # from .. import get_urls
from .base_views import CSRFSchema, BaseView from .base_views import CSRFSchema, BaseView
from pyramid.i18n import TranslationStringFactory from pyramid.i18n import TranslationStringFactory
from ..widgets import widget_os
_ = TranslationStringFactory('login') _ = TranslationStringFactory('login')
log = __import__("logging").getLogger(__name__) log = __import__("logging").getLogger(__name__)
...@@ -60,14 +64,21 @@ class Login(CSRFSchema): ...@@ -60,14 +64,21 @@ class Login(CSRFSchema):
password = colander.SchemaNode( password = colander.SchemaNode(
colander.String(), widget=widget.PasswordWidget()) colander.String(), widget=widget.PasswordWidget())
# def after_bind(self, schema, kwargs): def after_bind(self, schema, kwargs):
# request = kwargs["request"] request = kwargs["request"]
# csrf_token = new_csrf_token(request) csrf_token = new_csrf_token(request)
# log.error(csrf_token) log.debug(csrf_token)
# self["csrf_token"] = colander.SchemaNode( self["csrf_token"] = colander.SchemaNode(
# colander.String(), widget=widget.HiddenWidget(), colander.String(), widget=widget.HiddenWidget(),
# default=csrf_token default=csrf_token
# ) )
if BASE_CLASS.login_captcha:
self["captcha"] = colander.SchemaNode(
colander.String(),
widget=widget_os.CaptchaWidget(
request=request,
url=request.static_url(BASE_CLASS.captcha_files)),
oid="captcha", title=_("Captcha"))
# http://deformdemo.repoze.org/interfield/ # http://deformdemo.repoze.org/interfield/
...@@ -172,27 +183,31 @@ def oauth2_login(request, params=None): ...@@ -172,27 +183,31 @@ def oauth2_login(request, params=None):
return user return user
class ViewLogin(BaseView): class ViewAuth(BaseView):
# @view_config(route_name='login', renderer='templates/form.pt', require_csrf=True)
def view_login(self): def view_login(self):
request = self.req request = self.req
request.session["login"] = True request.session["login"] = True
next_url = request.params.get('next', request.referrer) next_url = request.params.get('next', request.referrer)
login_tpl = get_params('login_tpl', 'templates/login.pt') login_tpl = BASE_CLASS.login_tpl
if not next_url: if not next_url:
# next_url = get_urls(request.route_url('home'))
next_url = request.home next_url = request.home
if request.authenticated_userid: # (request): if request.authenticated_userid: # (request):
request.session.flash('Anda sudah login', 'error') request.session.flash('Anda sudah login', 'error')
# return HTTPFound(location=get_urls(f"{request.route_url('home')}")) return HTTPFound(location=f"{request.home}")
return HTTPFound(location=f"{request.route_url('base-home')}")
schema = Login() schema = Login()
schema = schema.bind(request=self.req) schema = schema.bind(request=self.req)
form = Form(schema, buttons=('login',)) buttons = (Button('login', _('Login')),)
if BASE_CLASS.allow_register:
buttons += (Button('register', _('Register')),)
buttons += (Button('reset', _('Reset')), btn_cancel,)
form = Form(schema, buttons=buttons)
message = "" message = ""
if 'login' in request.POST: if 'cancel' in request.POST:
return HTTPFound(location=request.home)
elif 'login' in request.POST:
identity = request.POST.get('username') identity = request.POST.get('username')
user = schema.user = User.get_by_identity(identity) user = schema.user = User.get_by_identity(identity)
controls = request.POST.items() controls = request.POST.items()
...@@ -202,7 +217,7 @@ class ViewLogin(BaseView): ...@@ -202,7 +217,7 @@ class ViewLogin(BaseView):
msg = 'Login gagal' msg = 'Login gagal'
set_user_log(msg, request, log, identity) set_user_log(msg, request, log, identity)
request.session.flash(msg, 'error') request.session.flash(msg, 'error')
return HTTPFound(location=get_urls(request.route_url('login'))) return HTTPFound(location=request.route_url('base-login'))
values = dict(c) values = dict(c)
...@@ -222,21 +237,20 @@ class ViewLogin(BaseView): ...@@ -222,21 +237,20 @@ class ViewLogin(BaseView):
except Exception as e: except Exception as e:
log.warn(str(e)) log.warn(str(e))
request.session.flash(str(e), "error") request.session.flash(str(e), "error")
return HTTPFound(location=get_urls(request.route_url('login'))) return HTTPFound(location=request.route_url('base-login'))
else: else:
login = LoginUser(self.req) login = LoginUser(self.req)
if not login.login(values, user): if not login.login(values, user):
request.session.flash(login.message, "error") request.session.flash(login.message, "error")
next_url = get_urls( next_url = f"{request.route_url('base-login')}?next={next_url}"
f"{request.route_url('login')}?next={next_url}")
return HTTPFound(location=next_url) return HTTPFound(location=next_url)
return redirect_login(request, user) return redirect_login(request, user)
elif 'register' in request.POST: elif 'register' in request.POST:
# register_form = get_params("register_form", 'register')
return HTTPFound(location=request.route_url(BASE_CLASS.reg_form)) return HTTPFound(location=request.route_url(BASE_CLASS.reg_form))
elif 'reset' in request.POST:
return HTTPFound(location=request.route_url('base-password-reset'))
elif 'login failed' in request.session: elif 'login failed' in request.session:
r = dict(form=request.session['login failed']) r = dict(form=request.session['login failed'])
del request.session['login failed'] del request.session['login failed']
...@@ -252,13 +266,13 @@ class ViewLogin(BaseView): ...@@ -252,13 +266,13 @@ class ViewLogin(BaseView):
login_tpl, dict( login_tpl, dict(
form=form, form=form,
message=message, message=message,
url=get_urls(request.route_url('login')), url=request.route_url('base-login'),
next_url=next_url, next_url=next_url,
login=login, ), login=login, ),
request=request) request=request)
except Oauth2UserExc as e: except Oauth2UserExc as e:
request.session.flash(str(e), 'error') request.session.flash(str(e), 'error')
return HTTPFound(location=get_urls(request.route_url('login'))) return HTTPFound(location=request.route_url('base-login'))
if user and user.status == 1: if user and user.status == 1:
return redirect_login(request, user) return redirect_login(request, user)
# values = {"csrf_token": new_csrf_token(request)} # values = {"csrf_token": new_csrf_token(request)}
...@@ -269,17 +283,40 @@ class ViewLogin(BaseView): ...@@ -269,17 +283,40 @@ class ViewLogin(BaseView):
# url=get_urls(request.route_url('login')), # url=get_urls(request.route_url('login')),
# next_url=next_url, # next_url=next_url,
# login=login, ) # login=login, )
if login_tpl:
return render_to_response( return render_to_response(
renderer_name=login_tpl, renderer_name=login_tpl,
request=request, request=request,
value=dict(form=form, value=dict(form=form,
message=message, message=message,
# url=get_urls(request.route_url('login')),
url=request.route_url('base-login'), url=request.route_url('base-login'),
next_url=next_url, next_url=next_url,
login=login, ), login=login, ),
) )
return dict(form=form.render(),scripts="")
def view_logout(self):
request = self.req
if not request.user:
if "g_state" in request.cookies:
request.response.delete_cookie("g_state", '/')
form = self.get_form(LogoutSchema, buttons=(btn_cancel, btn_logout))
if 'cancel' in request.POST or "home" in request.POST:
return HTTPFound(location=request.home)
elif "logout" in request.POST:
form = self.get_form(LogoutSchema, buttons=(btn_home,))
set_user_log("Logout", request, log)
headers = forget(request)
request.session.delete()
request.response.headers.update(headers)
if "g_state" in request.cookies:
request.response.delete_cookie("g_state", '/')
form.set_appstruct({"message": "Sukses Logout"})
request.session["login"] = False
return dict(form=form.render())
def redirect_login(request, user): def redirect_login(request, user):
...@@ -291,8 +328,8 @@ def redirect_login(request, user): ...@@ -291,8 +328,8 @@ def redirect_login(request, user):
request.session.flash("Sukses Login") request.session.flash("Sukses Login")
next_url = request.params.get('next') next_url = request.params.get('next')
if not next_url and request.matched_route.name == 'login': if not next_url and request.matched_route.name == 'login':
url = get_params('modules_default', 'home') url = get_params('modules_default', 'base-home')
return HTTPFound(location=get_urls(request.route_url(url)), return HTTPFound(location=request.route_url(url),
headers=headers) headers=headers)
if not next_url: if not next_url:
next_url = request.home next_url = request.home
...@@ -312,88 +349,126 @@ btn_logout = Button("logout", css_class="btn-danger") ...@@ -312,88 +349,126 @@ btn_logout = Button("logout", css_class="btn-danger")
btn_home = Button("home", css_class="btn-success") btn_home = Button("home", css_class="btn-success")
class ViewLogout(BaseView): # class ViewLogout(BaseView):
# @view_config(route_name='logout', renderer="templates/logout.pt", require_csrf=False) # @view_config(route_name='logout', renderer="templates/logout.pt", require_csrf=False)
def view_logout(self):
class ViewPassword(BaseView):
def reset_password(self):
request = self.req request = self.req
if not request.user: if request.authenticated_userid:
if "g_state" in request.cookies: return HTTPFound(location=f"{request.home}")
request.response.delete_cookie("g_state", '/')
form = self.get_form(LogoutSchema, buttons=(btn_cancel, btn_logout)) resp = dict(title=_('Reset password'))
if 'cancel' in request.POST or "home" in request.POST: resp['scripts'] = ""
# log.info(get_urls(request.route_url('home'))) schema = ResetPassword(validator=reset_password_validator)
# return HTTPFound(location=get_urls(f"{request.route_url('home')}", )) btn_submit = Button('submit', _('Send password reset email'))
form = Form(schema, buttons=(btn_submit, btn_cancel))
if 'submit' in request.POST:
controls = request.POST.items()
identity = request.POST.get('email')
q = DBSession.query(User).filter_by(email=identity)
schema.user = user = q.first()
try:
c = form.validate(controls)
except ValidationFailure:
resp['form'] = form.render()
return resp
remain = regenerate_security_code(user)
set_user_log("Reset password to {}".format(user.email), request, log,
user.user_name)
send_email_security_code(
request, user, remain, 'Reset password', 'reset-password-body',
'reset-password-body.tpl')
self.ses.flash(
'Email reset password sudah dikirim ke {}'.format(user.email))
return HTTPFound(location=request.home) return HTTPFound(location=request.home)
elif 'cancel' in request.POST:
return HTTPFound(location=request.route_url('base-login'))
elif "logout" in request.POST: resp['form'] = form.render()
form = self.get_form(LogoutSchema, buttons=(btn_home,)) return resp
set_user_log("Logout", request, log)
headers = forget(request)
request.session.delete()
request.response.headers.update(headers)
if "g_state" in request.cookies:
request.response.delete_cookie("g_state", '/')
form.set_appstruct({"message": "Sukses Logout"})
request.session["login"] = False
return dict(form=form.render())
def change_password(self):
"""
Digunakan untuk change password
1. Jika sudah login maka redirect ke home
2. Jika form valid maka akan menyimpan password baru ke database
3. User di logout dan di redirect ke home
"""
request = self.req
class ChangePassword(colander.Schema): schema = ChangePassword(validator=change_password_validator)
new_password = colander.SchemaNode( btn_save = Button('save', _('Simpan'))
colander.String(), widget=widget.CheckedPasswordWidget()) btn_cancel = Button('cancel', _('Batalkan'))
# retype_password = colander.SchemaNode( buttons = (btn_save, btn_cancel)
# colander.String(), widget=widget.PasswordWidget()) form = Form(schema, buttons=buttons)
# password = colander.SchemaNode(colander.String(), if not request.POST:
# widget=widget.PasswordWidget(), return dict(form=form.render(), scripts="")
# title=_("Old Password"))
if 'save' not in request.POST:
return HTTPFound(location=request.route_url('base-login'))
def change_password_validator(form, value): items = request.POST.items()
pass try:
# exc = colander.Invalid(form, '') c = form.validate(items)
# user = form.request.user except ValidationFailure as e:
# if not UserService.check_password(user, value["password"]): return dict(form=e.render())
# exc["password"] = 'Login Failed'
# raise exc
# if value['new_password'] != value['retype_password']: user = request.user
# exc["new_password"] = 'Retype mismatch.' user.security_code = None
# exc["retype_password"] = 'Retype mismatch.' if not UserService.check_password(user, c['password']):
# raise exc request.session.flash('Password lama tidak sesuai', 'error')
return HTTPFound(location=request.route_url('base-password'))
UserService.set_password(user, c['new_password'])
self.db_session.add(user)
self.db_session.flush()
headers = forget(request)
request.session.flash('Password baru Anda sudah disimpan.')
set_user_log("Change Password", request, log)
return HTTPFound(location=f"{request.home}", headers=headers)
# @view_config(route_name='change-password', def change_password_request(self):
# renderer='templates/change-password.pt')
def view_change_password(request):
""" """
Digunakan untuk change password url dari email (register, reset password) Digunakan untuk change password url dari email (register, reset password)
1. Jika sudah login maka redirect ke home
2. Jika code tidak ada atau tidak valid maka akan redirect ke get code
2. Jika code valid maka akan menampilkan form untuk change password
3. Jika form valid maka akan menyimpan password baru ke database
""" """
request = self.req
if request.authenticated_userid: if request.authenticated_userid:
request.session.flash('Anda sudah login', 'error') request.session.flash('Anda sudah login', 'error')
return HTTPFound(location=get_urls(f"{request.route_url('home')}")) return HTTPFound(location=f"{request.home}")
code = request.matchdict['code']
q = DBSession.query(User).filter_by(security_code=code)
user = q.first()
now = create_now()
if not user or now - user.security_code_date > one_hour:
request.session.flash('Security code expired', 'error')
return HTTPFound(location=request.route_url('base-login'))
schema = ChangePassword(validator=change_password_validator) schema = ChangePasswordRequest(validator=change_password_validator)
btn_save = Button('save', _('Simpan')) btn_save = Button('save', _('Simpan'))
btn_cancel = Button('cancel', _('Batalkan')) btn_cancel = Button('cancel', _('Batalkan'))
buttons = (btn_save, btn_cancel) buttons = (btn_save, btn_cancel)
form = Form(schema, buttons=buttons) form = Form(schema, buttons=buttons)
if not request.POST: if not request.POST:
return dict(form=form.render()) return dict(form=form.render(), scripts="")
if 'save' not in request.POST: if 'save' not in request.POST:
return HTTPFound(location=get_urls(request.route_url('login'))) return HTTPFound(location=request.route_url('base-login'))
items = request.POST.items() items = request.POST.items()
try: try:
c = form.validate(items) c = form.validate(items)
except ValidationFailure as e: except ValidationFailure as e:
return dict(form=e.render()) return dict(form=e.render())
code = request.matchdict['code']
q = DBSession.query(User).filter_by(security_code=code)
user = q.first()
if not user or create_now() - user.security_code_date > one_hour:
request.session.flash('Security code expired', 'error')
return HTTPFound(location=get_urls(request.route_url('login')))
user.security_code = None user.security_code = None
UserService.set_password(user, c['new_password']) UserService.set_password(user, c['new_password'])
...@@ -401,7 +476,59 @@ def view_change_password(request): ...@@ -401,7 +476,59 @@ def view_change_password(request):
headers = get_login_headers(request, user) headers = get_login_headers(request, user)
request.session.flash('Password baru Anda sudah disimpan.') request.session.flash('Password baru Anda sudah disimpan.')
set_user_log("Change Password", request, log) set_user_log("Change Password", request, log)
return HTTPFound(location=get_urls(f"{request.route_url('home')}"), headers=headers) return HTTPFound(location=f"{request.home}", headers=headers)
# def view_recreate_api_key(self):
# request = self.req
# if not request.user.api_key:
# return HTTPNotFound()
# schema = APIKey()
# btn_submit = Button('recreate', _('Buat ulang'))
# btn_cancel = Button('cancel', _('Batalkan'))
# buttons = (btn_submit, btn_cancel)
# form = Form(schema, buttons=buttons)
# if not request.POST:
# d = dict(api_key=request.user.api_key)
# return dict(form=form.render(appstruct=d))
# if 'recreate' not in request.POST:
# return HTTPFound(location=f"{request.home}")
# request.user.api_key = api_key = generate_api_key()
# DBSession.add(request.user)
# msg = 'API Key Anda yang baru {}'.format(api_key)
# request.session.flash(msg)
# return HTTPFound(location=f"{request.home}")
class ChangePasswordRequest(colander.Schema):
new_password = colander.SchemaNode(
colander.String(), widget=widget.CheckedPasswordWidget())
class ChangePassword(ChangePasswordRequest):
new_password = colander.SchemaNode(
colander.String(), widget=widget.CheckedPasswordWidget())
password = colander.SchemaNode(colander.String(),
widget=widget.PasswordWidget(),
title=_("Old Password"))
def change_password_validator(form, value):
pass
# exc = colander.Invalid(form, '')
# user = form.request.user
# if not UserService.check_password(user, value["password"]):
# exc["password"] = 'Login Failed'
# raise exc
# if value['new_password'] != value['retype_password']:
# exc["new_password"] = 'Retype mismatch.'
# exc["retype_password"] = 'Retype mismatch.'
# raise exc
###################### ######################
...@@ -416,27 +543,7 @@ def generate_api_key(): ...@@ -416,27 +543,7 @@ def generate_api_key():
return UserService.generate_random_string(64) return UserService.generate_random_string(64)
# @view_config(
# route_name='recreate-api-key', renderer='templates/recreate-api-key.pt',
# permission='view')
def view_recreate_api_key(request):
if not request.user.api_key:
return HTTPNotFound()
schema = APIKey()
btn_submit = Button('recreate', _('Buat ulang'))
btn_cancel = Button('cancel', _('Batalkan'))
buttons = (btn_submit, btn_cancel)
form = Form(schema, buttons=buttons)
if not request.POST:
d = dict(api_key=request.user.api_key)
return dict(form=form.render(appstruct=d))
if 'recreate' not in request.POST:
return HTTPFound(location=get_urls(f"{request.route_url('home')}"))
request.user.api_key = api_key = generate_api_key()
DBSession.add(request.user)
msg = 'API Key Anda yang baru {}'.format(api_key)
request.session.flash(msg)
return HTTPFound(location=get_urls(f"{request.route_url('home')}"))
################## ##################
...@@ -473,7 +580,7 @@ def send_email_security_code( ...@@ -473,7 +580,7 @@ def send_email_security_code(
if 'mail.sender_name' not in settings or 'mail.username' not in settings: if 'mail.sender_name' not in settings or 'mail.username' not in settings:
return return
url = '{}/password/{}?password={}'.format( url = '{}/password/{}?password={}/request'.format(
request.home, user.security_code, password) request.home, user.security_code, password)
minutes = int(time_remain.seconds / 60) minutes = int(time_remain.seconds / 60)
...@@ -525,46 +632,16 @@ def regenerate_security_code(user, hour=1.0): ...@@ -525,46 +632,16 @@ def regenerate_security_code(user, hour=1.0):
age = security_code_age(user) age = security_code_age(user)
remain = hour - age remain = hour - age
if user.security_code and age < hour and remain > two_minutes: if user.security_code and age < hour and remain > two_minutes:
log.debug("Security code: %s", user.security_code)
return remain return remain
UserService.regenerate_security_code(user) UserService.regenerate_security_code(user)
user.security_code_date = create_now() user.security_code_date = create_now()
log.debug("Security code: %s", user.security_code)
DBSession.add(user) DBSession.add(user)
return hour return hour
# @view_config(route_name='reset-password',
# renderer='templates/reset-password.pt')
def view_reset_password(request):
if request.authenticated_userid:
return HTTPFound(location=get_urls(f"{request.route_url('home')}"))
resp = dict(title=_('Reset password'))
schema = ResetPassword(validator=reset_password_validator)
btn_submit = Button('submit', _('Send password reset email'))
form = Form(schema, buttons=(btn_submit,))
if 'submit' in request.POST:
controls = request.POST.items()
identity = request.POST.get('email')
q = DBSession.query(User).filter_by(email=identity)
schema.user = user = q.first()
try:
c = form.validate(controls)
except ValidationFailure:
resp['form'] = form.render()
return resp
remain = regenerate_security_code(user)
set_user_log("Reset password to {}".format(user.email), request, log,
user.user_name)
send_email_security_code(
request, user, remain, 'Reset password', 'reset-password-body',
'reset-password-body.tpl')
return HTTPFound(location=get_urls(request.route_url('reset-password-sent')))
resp['form'] = form.render()
return resp
# @view_config(
# route_name='reset-password-sent',
# renderer='templates/reset-password-sent.pt')
def view_reset_password_sent(request):
return dict(title=_('Reset password'))
<form
tal:define="style style|field.widget.style;
css_class css_class|string:${field.widget.css_class or field.css_class or ''};
item_template item_template|field.widget.readonly_item_template;
title title|field.title;
errormsg errormsg|field.errormsg;
description description|field.description;
buttons buttons|field.buttons;
use_ajax use_ajax|field.use_ajax;
ajax_options ajax_options|field.ajax_options;
formid formid|field.formid;
method method|field.method;"
tal:attributes="style style;
class css_class;"
id="${formid}"
method="${method}"
enctype="multipart/form-data"
accept-charset="utf-8"
i18n:domain="deform"
class="deform ${field.bootstrap_form_style | 'form-horizontal'}"
>
<fieldset class="deform-form-fieldset">
<div class="row">
<legend tal:condition="title">${title}</legend>
<p class="section first" tal:condition="description">
${description}
</p>
<div tal:repeat="child field"
tal:replace="structure child.render_template(item_template)"/>
</div>
<div class="row">
<div class="form-group deform-form-buttons">
<tal:loop tal:repeat="button buttons">
<button
tal:define="btn_disposition repeat.button.start and 'btn-primary' or 'btn-default';"
tal:attributes="disabled button.disabled if button.disabled else None;
attributes|button.attributes|{};"
id="${formid+button.name}"
name="${button.name}"
type="${button.type}"
class="btn ${button.css_class or btn_disposition}"
value="${button.value}"
tal:condition="button.type != 'link'">
<span tal:condition="button.icon" class="glyphicon glyphicon-${button.icon}"></span>
${button.title}
</button>
<a
tal:define="btn_disposition repeat.button.start and 'btn-primary' or 'btn-default';
btn_href button.value|''"
class="btn ${button.css_class or btn_disposition}"
id="${field.formid + button.name}"
href="${btn_href}"
tal:condition="button.type == 'link'">
<span tal:condition="button.icon" class="glyphicon glyphicon-${button.icon}"></span>
${button.title}
</a>
</tal:loop>
</div>
</div>
</fieldset>
</form>
...@@ -378,8 +378,6 @@ class CaptchaWidget(Widget): ...@@ -378,8 +378,6 @@ class CaptchaWidget(Widget):
kode_captcha, file_name = img_captcha(self.request) kode_captcha, file_name = img_captcha(self.request)
self.request.session["captcha"] = kode_captcha self.request.session["captcha"] = kode_captcha
cstruct = self.url+file_name cstruct = self.url+file_name
# if cstruct in (null, None):
# cstruct = ""
readonly = kw.get("readonly", self.readonly) readonly = kw.get("readonly", self.readonly)
template = readonly and self.readonly_template or self.template template = readonly and self.readonly_template or self.template
values = self.get_template_values(field, cstruct, kw) values = self.get_template_values(field, cstruct, kw)
...@@ -394,6 +392,8 @@ class CaptchaWidget(Widget): ...@@ -394,6 +392,8 @@ class CaptchaWidget(Widget):
pstruct = pstruct.strip() pstruct = pstruct.strip()
if not pstruct: if not pstruct:
return null return null
if pstruct != self.request.session["captcha"]:
raise Invalid(field.schema, "Captcha tidak sesuai")
return pstruct return pstruct
......
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!