Commit 3c3ed020 by aagusti

before csrf

2 parents 08fe1794 6bacab04
...@@ -40,7 +40,7 @@ from opensipkd.tools import ( ...@@ -40,7 +40,7 @@ from opensipkd.tools import (
from deform import ZPTRendererFactory, Form from deform import ZPTRendererFactory, Form
from pkg_resources import resource_filename from pkg_resources import resource_filename
from deform.widget import default_resource_registry
import os import os
from opensipkd.models.handlers import LogDBSession from opensipkd.models.handlers import LogDBSession
...@@ -423,6 +423,8 @@ partner_idcard_url = 'partner/idcard' ...@@ -423,6 +423,8 @@ partner_idcard_url = 'partner/idcard'
def main(global_config, **settings): def main(global_config, **settings):
""" This function returns a Pyramid WSGI application. """ This function returns a Pyramid WSGI application.
""" """
default_resource_registry.registry['jquery.maskMoney'] = {
None: {"js": "opensipkd.base:static/jquery/jquery.maskMoney.min.js"}}
engine = engine_from_config( engine = engine_from_config(
settings, 'sqlalchemy.', client_encoding='utf8') #, convert_unicode=True settings, 'sqlalchemy.', client_encoding='utf8') #, convert_unicode=True
......
...@@ -243,7 +243,9 @@ def reset_sequence_(cls, seq): ...@@ -243,7 +243,9 @@ def reset_sequence_(cls, seq):
q = DBSession.query(cls) q = DBSession.query(cls)
if not q.first(): if not q.first():
sql = "SELECT setval('{}', 1, false)".format(seq) sql = "SELECT setval('{}', 1, false)".format(seq)
DBSession.bind.execute(sql) # DBSession.bind.execute(sql)
#sqlalchemy 2
DBSession.execute(text(sql))
def reset_sequences(): def reset_sequences():
......
...@@ -63,6 +63,7 @@ class Home(BaseView): ...@@ -63,6 +63,7 @@ class Home(BaseView):
# session = request.session # session = request.session
modules = request.menus modules = request.menus
modules_default = get_params('modules_default') modules_default = get_params('modules_default')
submodules_default = get_params('submenus')
# request.session['modules'] = modules # request.session['modules'] = modules
# request.session['modules_default'] = modules_default # request.session['modules_default'] = modules_default
log.info(request.session.peek_flash()) log.info(request.session.peek_flash())
...@@ -78,10 +79,10 @@ class Home(BaseView): ...@@ -78,10 +79,10 @@ class Home(BaseView):
if home_tpl: if home_tpl:
return render_to_response( return render_to_response(
home_tpl, home_tpl,
dict(modules=modules, logo=logo), dict(modules=modules, logo=logo, submodules=[]),
request=request request=request
) )
return dict(modules=modules, logo=logo) return dict(modules=modules, logo=logo, submodules=[])
@view_config(context=HTTPForbidden, renderer='templates/403.pt') @view_config(context=HTTPForbidden, renderer='templates/403.pt')
...@@ -101,16 +102,16 @@ class Password(colander.Schema): ...@@ -101,16 +102,16 @@ class Password(colander.Schema):
old_password = colander.SchemaNode( old_password = colander.SchemaNode(
colander.String(), widget=widget.PasswordWidget()) colander.String(), widget=widget.PasswordWidget())
new_password = colander.SchemaNode( new_password = colander.SchemaNode(
colander.String(), widget=widget.PasswordWidget()) colander.String(), widget=widget.CheckedPasswordWidget())
retype_password = colander.SchemaNode( # retype_password = colander.SchemaNode(
colander.String(), widget=widget.PasswordWidget()) # colander.String(), widget=widget.PasswordWidget())
def password_validator(form, value): def password_validator(form, value):
if not UserService.check_password(form.request.user, value['old_password']): if not UserService.check_password(form.request.user, value['old_password']):
raise colander.Invalid(form, 'Invalid old password.') raise colander.Invalid(form, 'Invalid old password.')
if value['new_password'] != value['retype_password']: # if value['new_password'] != value['retype_password']:
raise colander.Invalid(form, 'Retype mismatch.') # raise colander.Invalid(form, 'Retype mismatch.')
@view_config( @view_config(
......
...@@ -398,7 +398,7 @@ class Registrasi(BaseView): ...@@ -398,7 +398,7 @@ class Registrasi(BaseView):
DBSession.flush() DBSession.flush()
remain = regenerate_security_code(user) remain = regenerate_security_code(user)
send_email_security_code( send_email_security_code(
self.req, row, remain, 'Welcome new user', 'email-new-user', self.req, user, remain, 'Welcome new user', 'email-new-user',
'email-new-user.tpl') 'email-new-user.tpl')
ts = _( ts = _(
'user-added', 'user-added',
...@@ -422,5 +422,5 @@ class Registrasi(BaseView): ...@@ -422,5 +422,5 @@ class Registrasi(BaseView):
js=resources["js"]) js=resources["js"])
values = dict(c) values = dict(c)
row = self.save_request(values) row = self.save_request(values)
self.after_add(row, values) self.after_add(row=row, values=values)
return self.route_list() return self.route_list()
...@@ -57,7 +57,7 @@ ...@@ -57,7 +57,7 @@
<img alt="" class="icon-modul" src="${home}/static/icon/${modul.replace('/','_')}.png"> <img alt="" class="icon-modul" src="${home}/static/icon/${modul.replace('/','_')}.png">
<span>${modules[modul]}</span> <span>${modules[modul]}</span>
</a> </a>
<a tal:condition="modul.find('://')>-1" target="_blank" <a tal:condition="modul.find('://')>-1"
href="${modul}" class="box"> href="${modul}" class="box">
<img alt="" class="icon-modul" <img alt="" class="icon-modul"
src="${home}/static/icon/${modul.replace('://','').replace('https','').replace('http','')}.png"> src="${home}/static/icon/${modul.replace('://','').replace('https','').replace('http','')}.png">
......
...@@ -317,30 +317,33 @@ class Logout(BaseView): ...@@ -317,30 +317,33 @@ class Logout(BaseView):
class ChangePassword(colander.Schema): class ChangePassword(colander.Schema):
new_password = colander.SchemaNode( new_password = colander.SchemaNode(
colander.String(), widget=widget.PasswordWidget()) colander.String(), widget=widget.CheckedPasswordWidget())
retype_password = colander.SchemaNode( # retype_password = colander.SchemaNode(
colander.String(), widget=widget.PasswordWidget()) # colander.String(), widget=widget.PasswordWidget())
password = colander.SchemaNode(colander.String(), # password = colander.SchemaNode(colander.String(),
widget=widget.PasswordWidget(), # widget=widget.PasswordWidget(),
title=_("Old Password")) # title=_("Old Password"))
def change_password_validator(form, value): def change_password_validator(form, value):
exc = colander.Invalid(form, '') exc = colander.Invalid(form, '')
user = form.request.user user = form.request.user
if not UserService.check_password(user, value["password"]): # if not UserService.check_password(user, value["password"]):
exc["password"] = 'Login Failed' # exc["password"] = 'Login Failed'
raise exc # raise exc
if value['new_password'] != value['retype_password']: # if value['new_password'] != value['retype_password']:
exc["new_password"] = 'Retype mismatch.' # exc["new_password"] = 'Retype mismatch.'
exc["retype_password"] = 'Retype mismatch.' # exc["retype_password"] = 'Retype mismatch.'
raise exc # raise exc
@view_config(route_name='change-password', @view_config(route_name='change-password',
renderer='templates/change-password.pt') renderer='templates/change-password.pt')
def view_change_password(request): def view_change_password(request):
"""
Digunakan untuk change password url dari email (register, reset password)
"""
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=get_urls(f"{request.route_url('home')}"))
......
...@@ -4,6 +4,7 @@ import logging ...@@ -4,6 +4,7 @@ import logging
from deform.widget import ( from deform.widget import (
SchemaType, SchemaType,
DateInputWidget as DeformDateInputWidget, DateInputWidget as DeformDateInputWidget,
DateInputWidget,
default_resources, ResourceRegistry, default_resource_registry, _StrippedString, Widget) default_resources, ResourceRegistry, default_resource_registry, _StrippedString, Widget)
from colander import null, Invalid, SchemaNode, Mapping from colander import null, Invalid, SchemaNode, Mapping
......
...@@ -5,9 +5,11 @@ from colander import SchemaNode, null, Mapping, Invalid #, string_types ...@@ -5,9 +5,11 @@ from colander import SchemaNode, null, Mapping, Invalid #, string_types
from deform.widget import Widget, _StrippedString, Select2Widget, default_resources, \ from deform.widget import Widget, _StrippedString, Select2Widget, default_resources, \
ResourceRegistry, default_resource_registry ResourceRegistry, default_resource_registry
from deform.widget import string_types from deform.widget import string_types
from deform.form import Button
from iso8601.iso8601 import ISO8601_REGEX from iso8601.iso8601 import ISO8601_REGEX
from deform.i18n import _ from deform.i18n import _
from colander import compat
from deform import widget
_logging = logging.getLogger(__name__) _logging = logging.getLogger(__name__)
...@@ -381,7 +383,7 @@ class MapWidget(Widget): ...@@ -381,7 +383,7 @@ class MapWidget(Widget):
{ {
"js": "opensipkd.base:static/js/gmap.js", "js": "opensipkd.base:static/js/gmap.js",
"css": "deform:static/select2/select2.css", "css": "deform:static/select2/select2.css",
},) },)
def __init__(self, **kw): def __init__(self, **kw):
super().__init__(**kw) super().__init__(**kw)
...@@ -692,3 +694,13 @@ class BootStrapDateTimeInputWidget(Widget): ...@@ -692,3 +694,13 @@ class BootStrapDateTimeInputWidget(Widget):
return result return result
class TextInputWidget(widget.TextInputWidget):
template = "textinput_btn"
button = None
def __init__(self, **kw):
super(TextInputWidget, self).__init__(**kw)
if isinstance(self.button, compat.string_types):
self.button = Button(self.button, type="button")
...@@ -4,9 +4,10 @@ ...@@ -4,9 +4,10 @@
css_class css_class|field.widget.css_class; css_class css_class|field.widget.css_class;
style style|field.widget.style"> style style|field.widget.style">
${field.start_mapping()} ${field.start_mapping()}
<div> <div class="input">
<input type="password" <input type="password"
name="${name}" name="${name}"
onkeyup="checkPasswordStrength();"
value="${field.widget.redisplay and cstruct or ''}" value="${field.widget.redisplay and cstruct or ''}"
tal:attributes="class string: form-control ${css_class or ''}; tal:attributes="class string: form-control ${css_class or ''};
style style; style style;
...@@ -14,10 +15,17 @@ ${field.start_mapping()} ...@@ -14,10 +15,17 @@ ${field.start_mapping()}
id="${oid}" id="${oid}"
i18n:attributes="placeholder" i18n:attributes="placeholder"
placeholder="Password"/> placeholder="Password"/>
<div class="checkbox">
<label>
<input type="checkbox" id="view${field.oid}">
<span>Show Password</span>
</label>
</div>
</div> </div>
<div> <div class="input">
<input type="password" <input type="password"
name="${name}-confirm" name="${name}-confirm"
onkeyup="checkPasswordStrength${oid}();"
value="${field.widget.redisplay and confirm or ''}" value="${field.widget.redisplay and confirm or ''}"
tal:attributes="class string: form-control ${css_class or ''}; tal:attributes="class string: form-control ${css_class or ''};
style style; style style;
...@@ -25,6 +33,70 @@ ${field.start_mapping()} ...@@ -25,6 +33,70 @@ ${field.start_mapping()}
id="${oid}-confirm" id="${oid}-confirm"
i18n:attributes="placeholder" i18n:attributes="placeholder"
placeholder="Confirm Password"/> placeholder="Confirm Password"/>
<div class="checkbox">
<label>
<input type="checkbox" id="view${field.oid}-confirm">
<span>Show Password</span>
</label>
</div>
<div id="${oid}-confirm-password-strength-status"></div>
</div> </div>
${field.end_mapping()} ${field.end_mapping()}
<style>
#password-strength-status {
padding: 5px 10px;
border-radius: 4px;
margin-top: 5px;
}
</style>
<script type="text/javascript">
$('#view${oid}').change(function(){
if ($(this).prop('checked')==true){
$('#${oid}').attr('type','text');
}
else {
$('#${oid}').attr('type','password');
}
});
$('#view${oid}-confirm').change(function(){
if ($(this).prop('checked')==true){
$('#${oid}-confirm').attr('type','text');
}
else {
$('#${oid}-confirm').attr('type','password');
}
});
function checkPasswordStrength${oid}() {
var number = /([0-9])/;
var alphabets = /([a-zA-Z])/;
var special_characters = /([~,!,@,#,$,%,^,&,*,-,_,+,=,?,>,<,\),\(,{,},\[,\]])/;
var passworda = $('#${oid}').val().trim();
var password = $('#${oid}-confirm').val().trim();
if (password.length <= 8) {
$('#${oid}-confirm-password-strength-status').removeClass();
$('#${oid}-confirm-password-strength-status').addClass('label label-danger');
$('#${oid}-confirm-password-strength-status').html("Weak (should be atleast 8 characters.)");
} else {
if (passworda != password){
$('#${oid}-confirm-password-strength-status').removeClass();
$('#${oid}-confirm-password-strength-status').addClass('label label-danger');
$('#${oid}-confirm-password-strength-status').html("Password do not match.");
}
else if (password.match(number) && password.match(alphabets) && password.match(special_characters)) {
$('#${oid}-confirm-password-strength-status').removeClass();
$('#${oid}-confirm-password-strength-status').addClass('label label-success');
$('#${oid}-confirm-password-strength-status').html("Strong");
}
else {
$('#${oid}-confirm-password-strength-status').removeClass();
$('#${oid}-confirm-password-strength-status').addClass('label label-warning');
$('#${oid}-confirm-password-strength-status').html("Medium (should include alphabets, numbers and special characters.)");
}
}
}
</script>
</div> </div>
<tal:block tal:define="oid oid|field.oid; <tal:block tal:define="oid oid|field.oid;
css_class css_class|field.widget.css_class; css_class css_class|field.widget.css_class;
style style|field.widget.style;"> style style|field.widget.style;
preview_url cstruct.get('preview_url')|cstruct.get('base64')|'';
ext str(cstruct.get('filename').split('.')[-1:][0]).lower()|[];
fname str(cstruct.get('filename'))|'';
delete cstruct.get('delete')|'';">
${field.start_mapping()} ${field.start_mapping()}
<img tal:define="preview_url cstruct.get('preview_url'); <tal:block tal:condition="preview_url and ext in ['jpg','jpeg','png','bmp','gif']">
filename cstruct.get('filename')" <img id="preview-${oid}" alt="" src="${structure: preview_url}" style="width:100px;height:auto;"
tal:condition="preview_url" src="${structure: preview_url}" onload="window.URL.revokeObjectURL(this.src)"></img>
></img> <br>
</tal:block>
<tal:block tal:condition="not preview_url or ext not in ['jpg','jpeg','png','bmp','gif']">
<img id="preview-${oid}" alt="" src="" style="width:100px;height:auto;"
onload="window.URL.revokeObjectURL(this.src)"></img>
<br>
</tal:block>
<a id="label-${oid}" tal:condition="preview_url" class="label label-default" href="${structure: preview_url}"
target="_blank"><i class="fa fa-search"></i> View</a>
<button id="labeldelete-${oid}" type="button" tal:condition="delete" class="label label-danger" href="#"
target="_blank"
onclick="var daft = document.getElementById('daftar_file_hapus').value.replace(/\[|\]/g,'').split(',');
daft.push('${fname}');
document.getElementById('daftar_file_hapus').value=daft;
document.getElementById('${oid}-close').click();">
<i class="fa fa-remove"></i> Delete</button>
<input type="file" name="upload" id="${oid}" <input type="file" name="upload" id="${oid}"
tal:attributes="style style; tal:attributes="style style;
accept accept|field.widget.accept; accept accept|field.widget.accept;
data-filename cstruct.get('filename'); data-filename fname;
attributes|field.widget.attributes|{};"/> attributes|field.widget.attributes|{};"
onchange="document.getElementById('preview-'+this.id).src = window.URL.createObjectURL(this.files[0]);
document.getElementById('labeldelete-'+this.id).remove();
document.getElementById('label-'+this.id).remove();"/>
<input tal:define="uid cstruct.get('uid')" <input tal:define="uid cstruct.get('uid')"
tal:condition="uid" tal:condition="uid"
type="hidden" name="uid" value="${uid}"/> type="hidden" name="uid" value="${uid}"/>
...@@ -19,5 +41,6 @@ ...@@ -19,5 +41,6 @@
deform.addCallback('${oid}', function (oid) { deform.addCallback('${oid}', function (oid) {
$('#' + oid).upload(); $('#' + oid).upload();
}); });
</script> </script>
</tal:block> </tal:block>
<input <tal:block tal:define="name name|field.name;
tal:define="autofocus autofocus|field.autofocus" oid oid|field.oid;">
<div class="input">
<input
type="password" type="password"
name="${name|field.name}" name="${name}"
onkeyup="checkPasswordStrength${oid}();"
value="${field.widget.redisplay and cstruct or ''}" value="${field.widget.redisplay and cstruct or ''}"
tal:attributes="style style|field.widget.style; tal:attributes="style style|field.widget.style;
class string: form-control ${css_class|field.widget.css_class or ''}; class string: form-control ${css_class|field.widget.css_class or ''};
autofocus autofocus;
attributes|field.widget.attributes|{};" attributes|field.widget.attributes|{};"
id="${oid|field.oid}"/> id="${oid}"/>
<div class="checkbox">
<label>
<input type="checkbox" id="view${oid}">
<span>Show Password</span>
</label>
</div>
<div id="${oid}-password-strength-status"></div>
</div>
<style>
#password-strength-status {
padding: 5px 10px;
border-radius: 4px;
margin-top: 5px;
}
</style>
<script type="text/javascript">
$('#view${oid}').change(function(){
if ($(this).prop('checked')==true){
$('#${oid}').attr('type','text');
}
else {
$('#${oid}').attr('type','password');
}
});
function checkPasswordStrength${oid}() {
var number = /([0-9])/;
var alphabets = /([a-zA-Z])/;
var special_characters = /([~,!,@,#,$,%,^,&,*,-,_,+,=,?,>,<,\),\(,{,},\[,\]])/;
var password = $('#${oid}').val().trim();
if (password.length <= 8) {
$('#${oid}-password-strength-status').removeClass();
$('#${oid}-password-strength-status').addClass('label label-danger');
$('#${oid}-password-strength-status').html("Weak (should be atleast 8 characters.)");
} else {
if (password.match(number) && password.match(alphabets) && password.match(special_characters)) {
$('#${oid}-password-strength-status').removeClass();
$('#${oid}-password-strength-status').addClass('label label-success');
$('#${oid}-password-strength-status').html("Strong");
}
else {
$('#${oid}-password-strength-status').removeClass();
$('#${oid}-password-strength-status').addClass('label label-warning');
$('#${oid}-password-strength-status').html("Medium (should include alphabets, numbers and special characters.)");
}
}
}
</script>
</tal:block>
<p tal:define="preview_url cstruct.get('preview_url')"> <p tal:define="preview_url cstruct.get('preview_url');
<a tal:condition="preview_url" href="${structure: preview_url}" ext str(cstruct.get('filename').split('.')[-1:][0]).lower()|[];">
target="_blank">Show</a> <tal:block tal:condition="preview_url and ext in ['jpg','jpeg','png','bmp','gif']">
<p tal:condition="not preview_url" id="${oid|field.oid}" <img src="${structure: preview_url}" style="width:100px;height:auto;"></img>
class="form-control-static deform-readonly-text" <br>
tal:content="cstruct.get('filename') or ''"></p> </tal:block>
<a class="label label-default" href="${structure: preview_url}"
target="_blank"><i class="fa fa-search"></i> View</a>
</p> </p>
...@@ -99,6 +99,7 @@ ...@@ -99,6 +99,7 @@
<input type="hidden" name="__end__" value="${field.name}:sequence"/> <input type="hidden" name="__end__" value="${field.name}:sequence"/>
<!-- /sequence --> <!-- /sequence -->
<input tal:define="templates subfields[0][1].widget.template|''" tal:condition="templates=='file_upload'" id="daftar_file_hapus" name="daftar_file_hapus" type="hidden">
</div> </div>
</div> </div>
......
...@@ -20,12 +20,12 @@ ...@@ -20,12 +20,12 @@
</div> </div>
<div class="col-xs-1" style="padding:0"> <div class="col-xs-1" style="padding:0">
<!-- sequence_item --> <!-- sequence_item -->
<span class="deform-order-button close glyphicon glyphicon-resize-vertical" <span class="deform-order-button close glyphicon glyphicon-resize-vertical ${field.widget.template=='file_upload' and 'hide' or ''}"
id="${oid}-order" id="${oid}-order"
tal:condition="not hidden" tal:condition="not hidden"
title="Reorder (via drag and drop)" title="Reorder (via drag and drop)"
i18n:attributes="title"></span> i18n:attributes="title"></span>
<a class="deform-close-button close" <a class="deform-close-button close ${field.widget.template=='file_upload' and 'hide' or ''}"
id="${oid}-close" id="${oid}-close"
tal:condition="not field.widget.hidden" tal:condition="not field.widget.hidden"
title="Remove" title="Remove"
......
<span tal:define="name name|field.name;
css_class css_class|field.widget.css_class;
oid oid|field.oid;
mask mask|field.widget.mask;
button button|field.widget.button;
mask_placeholder mask_placeholder|field.widget.mask_placeholder;
style style|field.widget.style;
" tal:omit-tag="">
<input type="text" tal:attributes="class string: form-control ${css_class or ''};
style style;
attributes|field.widget.attributes|{};" id="${oid}" name="${name}" value="${cstruct}"
tal:condition="not button" />
<div class="input-group" tal:condition="button">
<input type="text" name="${name}" value="${cstruct}" tal:attributes="class string: form-control ${css_class or ''};
style style;
attributes|field.widget.attributes|{};" id="${oid}" />
<span class="input-group-btn">
<button tal:define="btn_disposition 'btn-default';" tal:attributes="disabled button.disabled if button.disabled else None;
attributes|button.attributes|{};" id="${oid+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 'btn-default';
btn_href button.value|''" class="btn ${button.css_class or btn_disposition}" id="${oid + button.name}"
href="${btn_href}" tal:condition="button.type == 'link'">
<span tal:condition="button.icon" class="glyphicon glyphicon-${button.icon}"></span>
${button.title}
</a>
</span>
</div><!-- /input-group -->
<script tal:condition="mask" type="text/javascript">
deform.addCallback(
'${oid}',
function (oid) {
$("#" + oid).mask("${mask}",
{ placeholder: "${mask_placeholder}" });
});
</script>
</span>
\ No newline at end of file \ No newline at end of file
...@@ -10,8 +10,9 @@ with open(os.path.join(here, 'CHANGES.txt')) as f: ...@@ -10,8 +10,9 @@ with open(os.path.join(here, 'CHANGES.txt')) as f:
line = CHANGES.splitlines()[0] line = CHANGES.splitlines()[0]
version = line.split()[0] version = line.split()[0]
requires = [ requires = [
'sqlalchemy==1.4.50',
'wheel', 'wheel',
'colander', 'colander==1.8.3',
'pyramid', 'pyramid',
'pyramid_tm', 'pyramid_tm',
'SQLAlchemy', 'SQLAlchemy',
......
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!