Commit 2d066240 by aagusti

Perbaikan BaseView

1 parent 1f158947
Showing 62 changed files with 413 additions and 269 deletions
......@@ -28,7 +28,7 @@ from .security import (
group_finder,
get_user, MySecurityPolicy,
)
from .models import (
from opensipkd.models import (
DBSession,
Base,
init_model,
......@@ -50,7 +50,7 @@ from pkg_resources import resource_filename
import os
from .models.handlers import LogDBSession
from opensipkd.models.handlers import LogDBSession
log = logging.getLogger(__name__)
......@@ -350,7 +350,7 @@ def set_routes(config, app_id=None):
config.add_jsonrpc_endpoint(route.kode, route.path,
default_renderer="json_rpc")
partner_idcard_folder = 'partner/idcard'
def main(global_config, **settings):
""" This function returns a Pyramid WSGI application.
"""
......@@ -370,9 +370,9 @@ def main(global_config, **settings):
settings['timezone'] = DefaultTimeZone
config = Configurator(settings=settings,
root_factory='opensipkd.base.models.RootFactory',
root_factory='opensipkd.models.RootFactory',
session_factory=session_factory)
from .models import RootFactory
from opensipkd.models import RootFactory
modules = get_modules(settings)
from importlib import import_module
for module in modules:
......@@ -409,6 +409,9 @@ def main(global_config, **settings):
config.add_request_method(disable_responsive, 'disable_responsive', reify=True)
config.add_request_method(get_params, 'get_params', reify=True)
config.add_static_view('static', 'opensipkd.base:static', cache_max_age=3600)
config.add_static_view(partner_idcard_folder,
get_params("partner_idcard_folder", '/tmp/idcard'),
cache_max_age=3600)
config.add_static_view('deform_static', 'deform:static')
captcha_files = get_params('captcha_files', settings=settings, alternate="/tmp/captcha")
......
......@@ -7,7 +7,7 @@ from pyramid.paster import (
setup_logging,
)
from sqlalchemy import engine_from_config
from opensipkd.base.models.meta import Base
from opensipkd.models.meta import Base
config = context.config
......
"""tambah idcard
Revision ID: 91f07d138fe9
Revises: 8e7057155823
Create Date: 2022-07-11 18:29:13.867835
"""
# revision identifiers, used by Alembic.
revision = '91f07d138fe9'
down_revision = '8e7057155823'
branch_labels = None
depends_on = None
from alembic import op
import sqlalchemy as sa
def upgrade():
context = op.get_context()
helpers = context.opts['helpers']
if not helpers.table_has_column('partner', 'idcard'):
op.add_column('partner',
sa.Column('idcard', sa.String(256)))
def downgrade():
pass
......@@ -2,7 +2,7 @@ import logging
import traceback
from datetime import datetime
from hashlib import md5
from opensipkd.base.models.handlers import (
from opensipkd.models.handlers import (
Log,
LogDBSession,
)
......
from sqlalchemy import event
from .base import *
from .common import *
from .users import *
from .wilayah import *
from .partner import *
from .departemen import *
from .pegawai import *
# from .meta import *
# from .targets import *
# from .wilayah import *
def has_permission(action):
pass
@event.listens_for(User, 'before_delete', has_permission('delete'))
def receive_before_delete(mapper, connection, target):
"listen for the 'before_delete' event"
# ... (event handling logic) ...
pass
ALL_TABLES = {}
for sub_class in Base.__subclasses__():
if hasattr(sub_class, "__tablename__"):
tablename = sub_class.__tablename__
if tablename not in ALL_TABLES:
ALL_TABLES.update({tablename: sub_class})
def query_table(table_name, fields=None, domain=None):
cls = ALL_TABLES[table_name]
if fields:
query = DBSession.query().select_from(cls)
# for field in fields:
query = query.add_columns(*[getattr(cls, c) for c in fields])
else:
query = DBSession.query(cls)
if domain:
filter_expressions = []
for d in domain:
field = getattr(cls, d[0])
operator = d[1]
value = d[2]
filter_expressions.append(field.op(operator)(value))
query = query.filter(
*[
e for i, e in enumerate(filter_expressions)
if e is not None]
)
return query
log = __import__("logging").getLogger(__name__)
log.warning('Use opensipkd.models')
from opensipkd.models import *
......@@ -6,7 +6,7 @@ from pyramid.paster import (
get_appsettings,
setup_logging,
)
from ..models import (
from opensipkd.models import (
DBSession,
Route,
)
......
......@@ -7,7 +7,7 @@ from sqlalchemy import (
)
from sqlalchemy.schema import PrimaryKeyConstraint
from sqlalchemy.sql.expression import text
from ..models import (
from opensipkd.models import (
Base,
BaseModel,
CommonModel,
......
......@@ -13,7 +13,7 @@ from sqlalchemy import (
exc,
)
from sqlalchemy.orm import sessionmaker
from ..models.handlers import (
from opensipkd.models.handlers import (
Log,
LogDBSession,
)
......
......@@ -11,8 +11,8 @@ from sqlalchemy.schema import CreateSchema
from ziggurat_foundations.models.services.user import UserService
from pyramid.paster import (get_appsettings, setup_logging, )
from ..models.handlers import LogDBSession
from ..models import (
from opensipkd.models.handlers import LogDBSession
from opensipkd.models import (
init_model, DBSession, Base, Group, UserGroup, Permission, GroupPermission,
User, Route, Eselon, Jabatan, ResProvinsi, ResDati2, ResKecamatan, ResDesa)
......
......@@ -4,7 +4,7 @@ from opensipkd.base.tools.api import rpc_auth
from opensipkd.tools.api import JsonRpcInvalidLoginError
from pyramid.renderers import render_to_response
from .models import (
from opensipkd.models import (
User,
UserGroup,
DBSession,
......
......@@ -5,7 +5,7 @@ import requests
from opensipkd.tools import (
get_random_number, devel, get_random_string, get_settings, DefaultTimeZone, get_params, get_timezone)
from opensipkd.tools.api import *
from ..models import (DBSession, User, GroupPermission, UserDeviceModel)
from opensipkd.models import (DBSession, User, GroupPermission, UserDeviceModel)
import logging
log = logging.getLogger(__name__)
......@@ -91,20 +91,6 @@ def get_user_device(request, user_id):
return user_device
def validate_time(request):
global lima_menit
env = request.environ
time_stamp = int(env['HTTP_KEY'])
now = get_seconds()
settings = get_settings()
if 'diff_server_time' in settings and settings["diff_server_time"]:
lima_menit = int(settings["diff_server_time"])
if not request.devel and abs(now - time_stamp) > lima_menit:
log.info(f"req time {time_stamp} server time {now}")
raise JsonRpcInvalidTimeError
return time_stamp
def auth_device(request):
......@@ -135,10 +121,6 @@ def auth_device(request):
return user
def get_jsonrpc(method, params):
return dict(jsonrpc='2.0', method=method, params=params,
id=int(get_random_number(6)))
def check_token(token, perm_name=None):
user = User.get_by_token(token).first()
......@@ -171,44 +153,3 @@ def update_token(user):
DBSession.flush()
return dict(token=user.security_code)
def get_mandatory(data, values):
for value in values:
if value not in data or not data[value]:
raise JsonRpcInvalidDataError(message="{} Not Found".format(value))
def send_rpc(auth, message):
"""
Digunakan untuk mengirim data dengan methode JSONRPC 2.0 with os-auth
:param auth: Dict
{"user": user,
"url": url,
"key": key,
"method": method,
"timeout": optional,
}
:param message: Dict
:return: Dict
"""
userid = auth['user']
password = auth['key']
url = auth['url']
headers = json_rpc_header(userid, password)
params = dict(data=message)
data = get_jsonrpc(auth["method"], params)
timeout = 'timeout' in auth and int(auth['timeout']) or 5
log.info("URL:{} timeout:{} detik".format(url, timeout))
log.warning("REQUEST {}".format(data))
try:
results = requests.post(url, json=data, headers=headers, timeout=timeout) # data=jsondata,
except Exception as e:
log.warning(str(e))
return
if results.status_code != 200:
log.info(results)
log.info(results.text)
return
rows = results.text and json.loads(results.text) or None
log.info("RESPONSE {}".format(rows))
return rows
from sqlalchemy import func
from opensipkd.base.models import Parameter
from opensipkd.models import Parameter
def column_concat(cols=None):
......
......@@ -19,7 +19,7 @@ from opensipkd.base import get_params
from opensipkd.base.tools.api import rpc_auth
from .base_views import BaseView
from ..models import (
from opensipkd.models import (
DBSession, UserService, )
from .common import DataTables, ColumnDT
......
......@@ -3,7 +3,7 @@ from pyramid_rpc.jsonrpc import jsonrpc_method
from opensipkd.tools.api import JsonRpcInvalidDataError, JsonRpcInvalidLoginError
from ziggurat_foundations.models.services.user import UserService
from ..models import Partner, User
from opensipkd.models import Partner, User
......
......@@ -3,7 +3,7 @@ from google.oauth2 import id_token
from opensipkd.base import get_params
from pyramid.view import (view_config, )
from ..models import User
from opensipkd.models import User
from opensipkd.tools import get_settings
import json
......
......@@ -17,7 +17,7 @@ from email.utils import parseaddr
from opensipkd.tools.buttons import btn_save, btn_cancel, btn_close, btn_delete, btn_view, btn_add, btn_edit, btn_csv, \
btn_pdf
from ..models import User
from opensipkd.models import User
from ...detable import DeTable
......@@ -145,13 +145,21 @@ class BaseView(object):
def form_validator(self, form, value):
pass
def get_params(self, params):
return get_params(params)
def get_params(self, params, default=None):
return get_params(params, default)
def get_form(self, class_form, row=None, buttons=(btn_save, btn_cancel), **bindings):
def get_form(self, class_form, row=None, buttons=(btn_save, btn_cancel), **kwargs):
buttons = self.buttons and self.buttons or buttons
bindings = self.bindings and self.bindings or bindings
if "bindings" in kwargs and kwargs["bindings"]:
bindings = kwargs["bindings"]
else:
bindings = self.bindings
if "validator" in kwargs and kwargs["validator"]:
schema = class_form(validator=kwargs["validator"])
else:
schema = class_form(validator=self.form_validator)
schema = schema.bind(request=self.req, **bindings)
schema.request = self.req
if row:
......@@ -186,7 +194,7 @@ class BaseView(object):
if not row:
return self.id_not_found()
bindings = self.get_bindings(row)
form = self.get_form(self.edit_schema, buttons=(btn_close,), **bindings)
form = self.get_form(self.edit_schema, buttons=(btn_close,), bindings=bindings)
if request.POST:
return self.route_list()
......@@ -208,7 +216,7 @@ class BaseView(object):
return
def next_act(self):
return
raise NotImplementedError
def list_join(self, query):
return query
......@@ -230,16 +238,16 @@ class BaseView(object):
query = DBSession.query().select_from(self.table)
query = self.list_join(query)
if self.req.user.company_id and hasattr(self.table, "company_id"):
if self.req.user and self.req.user.company_id and hasattr(self.table, "company_id"):
query = query.filter(self.table.company_id == self.req.user.company_id)
row_table = DataTables(self.req.GET, query, columns)
return row_table.output_result()
else:
self.next_act()
return self.next_act()
def view_add(self):
bindings = self.get_bindings()
form = self.get_form(self.add_schema, **bindings)
form = self.get_form(self.add_schema, bindings=bindings)
table = self.get_item_table()
resources = form.get_widget_resources()
if self.req.POST:
......@@ -248,22 +256,27 @@ class BaseView(object):
try:
controls = form.validate(controls)
except ValidationFailure as e:
value = self.validation_failure(e.cstruct)
value.update(self.before_add())
form.render(appstruct=value)
return dict(form=form.render(), table=table and table.render() or None,
scripts=self.form_scripts, css=resources["css"], js=resources["js"])
# value = self.validation_failure(e.cstruct)
# value.update(self.before_add())
# form.render(appstruct=value)
return dict(form=form.render(e.cstruct),
table=table and table.render() or None,
scripts=self.form_scripts, css=resources["css"],
js=resources["js"])
values = dict(controls)
row = self.save_request(values)
self.after_add(row, values)
if "cancel" in self.req.POST or 'batal' in self.req.POST:
elif "cancel" in self.req.POST or 'batal' in self.req.POST:
self.cancel_act()
else:
return self.next_add(form)
return self.route_list()
values = self.before_add()
form.set_appstruct(values)
return dict(form=form.render(), table=table and table.render() or None,
scripts=self.form_scripts, css=resources["css"], js=resources["js"])
scripts=self.form_scripts, css=resources["css"],
js=resources["js"])
def before_save(self, row, values):
return row
......@@ -290,8 +303,7 @@ class BaseView(object):
return row
def save_request(self, values, row=None):
params = self.req.params
for k, v in params.items():
for k, v in self.req.GET.items():
if k not in values:
if v:
values[k] = v
......@@ -384,6 +396,14 @@ class BaseView(object):
return query.filter(self.table.company_id == self.req.user.company_id)
return query
def next_add(self, form):
"""
Digunakan untuk memverifikasi button yang lainnya
:param form: Object Form
:return:
"""
return self.route_list()
@colander.deferred
def deferred_status(node, kw):
......@@ -402,15 +422,6 @@ class Store(dict):
return ""
store = Store()
reg_exts = ['.png', '.jpg', '.pdf', '.jpeg']
def image_validator(node, value):
ext = get_ext(value["filename"])
if ext not in reg_exts:
raise colander.Invalid(node, f'Extension harus salahsatu dari {reg_exts}')
username_re = re.compile('^[a-z0-9_]{6,16}$', re.IGNORECASE)
......
......@@ -2,9 +2,9 @@ import colander
from deform import (widget, )
from pyramid.view import (view_config, )
from opensipkd.base.models import ResProvinsi, ResDati2, ResDesa, User
from opensipkd.models import ResProvinsi, ResDati2, ResDesa, User
from .partner_base import PartnerSchema, NamaSchema
from ..models import DBSession, ResCompany, ResKecamatan, Partner
from opensipkd.models import DBSession, ResCompany, ResKecamatan, Partner
from ..views import BaseView
SESS_ADD_FAILED = 'Tambah pemda gagal'
......@@ -40,7 +40,7 @@ class ListSchema(NamaSchema):
class ViewCompany(BaseView):
def __init__(self, request):
super(ViewCompany, self).__init__(request)
super().__init__(request)
self.list_route = 'company'
self.add_schema = AddSchema
self.edit_schema = EditSchema
......@@ -91,6 +91,7 @@ class ViewCompany(BaseView):
partner_id = value.get('partner_id')
if 'email' in value and value["email"]:
found = Partner.query_email(value.get('email')).first()
if found:
if found and found.id != partner_id:
......@@ -101,6 +102,9 @@ class ViewCompany(BaseView):
found = User.get_by_identity(value.get('email'))
if found:
err_user()
value["status"]="status" in value and value["status"] and 1 or 0
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
def get_bindings(self, row=None):
provinsi_list = ResProvinsi.get_list()
......@@ -162,14 +166,21 @@ class ViewCompany(BaseView):
part = None
if "id" in values:
del values["id"]
from .partner import save as partner_save
part = partner_save(values, self.req.user, part)
if not part:
part = Partner()
part.from_dict(values)
DBSession.add(part)
DBSession.flush()
if part:
values["partner_id"] = part.id
if "id" in self.req.matchdict:
values["id"] = self.req.matchdict["id"]
row = self.save(values, self.req.user, row)
if not part.company_id:
part.company_id = row.id
DBSession.add(part)
DBSession.flush()
return row
......@@ -4,7 +4,7 @@ from pyramid.view import (view_config, )
from . import widget_os
from .provinsi import provinsi_widget
from ..models import DBSession, ResDati2, kategori_dati2, ResProvinsi
from opensipkd.models import DBSession, ResDati2, kategori_dati2, ResProvinsi
from ..views import BaseView
SESS_ADD_FAILED = 'Tambah dati2 gagal'
......
......@@ -12,7 +12,7 @@ from sqlalchemy.orm import aliased
from .company import company_widget
from .upload import AddSchema as UploadSchema
from ..models import DBSession, Departemen, Partner, PartnerDepartemen
from opensipkd.models import DBSession, Departemen, Partner, PartnerDepartemen
from ..views import ColumnDT, DataTables, BaseView
SESS_ADD_FAILED = 'Tambah departemen gagal'
......
......@@ -14,7 +14,7 @@ from pyramid.view import (
view_config,
)
from ..models import Departemen
from opensipkd.models import Departemen
from ..views import BaseView
SESS_ADD_FAILED = 'Tambah departemen gagal'
......
......@@ -12,8 +12,8 @@ from opensipkd.tools.report import (
pdf_response,
csv_response,
)
from ..models import DBSession
from ..models import (
from opensipkd.models import DBSession
from opensipkd.models import (
Departemen,
)
from ..views import (BaseView, )
......
......@@ -5,7 +5,7 @@ from pyramid.view import (view_config, )
from .dati2 import dati2_widget
from .kecamatan import kecamatan_widget
from .provinsi import provinsi_widget
from ..models import DBSession, ResDesa, kategori_desa, ResKecamatan, ResProvinsi, ResDati2
from opensipkd.models import DBSession, ResDesa, kategori_desa, ResKecamatan, ResProvinsi, ResDati2
from ..views import BaseView
SESS_ADD_FAILED = 'Tambah desa gagal'
......@@ -22,13 +22,25 @@ def desa_widget(node, kw):
class AddSchema(colander.Schema):
provinsi_id = colander.SchemaNode(colander.String(),
widget=provinsi_widget,
validator=colander.Length(max=32), oid="kode")
validator=colander.Length(max=32),
oid="provinsi_id",
slave="dati2_id",
slave_url="/dati2/select/act?provinsi_id=",
title="Provinsi",
)
dati2_id = colander.SchemaNode(colander.String(),
widget=dati2_widget,
validator=colander.Length(max=32), oid="kode")
validator=colander.Length(max=32),
oid="dati2_id",
slave="kecamatan_id",
slave_url="/kecamatan/select/act?dati2_id=",
title="Kabupaten/Kota",
)
kecamatan_id = colander.SchemaNode(colander.String(),
widget=kecamatan_widget,
validator=colander.Length(max=32), oid="kode")
validator=colander.Length(max=32),
oid="kecamatan_id",
title="Kecamatan")
kode = colander.SchemaNode(colander.String(),
validator=colander.Length(max=32), oid="kode")
kategori = colander.SchemaNode(colander.String(),
......
......@@ -7,7 +7,7 @@ from pyramid.view import (
)
from .partner_base import NamaSchema
from ..models import (
from opensipkd.models import (
DBSession,
Eselon
)
......
......@@ -4,7 +4,7 @@ from pyramid.i18n import TranslationStringFactory
from pyramid.view import view_config
from . import BaseView
from ..models import (
from opensipkd.models import (
DBSession,
Group,
Permission,
......
......@@ -5,7 +5,7 @@ from opensipkd.tools.buttons import btn_view, btn_add, btn_edit, btn_delete, btn
from opensipkd.tools.report import csv_response, open_rml_pdf, open_rml_row, pdf_response
from pyramid.view import (view_config, )
from .partner_base import NamaSchema
from ..models import (
from opensipkd.models import (
DBSession,
Jabatan,
Eselon, Departemen
......
......@@ -11,8 +11,8 @@ from pyramid.view import (
view_config,
)
from ..models import DBSession
from ..models import (
from opensipkd.models import DBSession
from opensipkd.models import (
Jabatan,
Departemen,
)
......
import json
import colander
from deform import (widget, Form, )
from opensipkd.tools.buttons import btn_close, btn_cancel, btn_save, btn_add, btn_edit, btn_delete
from deform import (widget, )
from opensipkd.base.views.provinsi import provinsi_widget
from opensipkd.models import DBSession, ResKecamatan, ResDati2, ResProvinsi
from pyramid.view import (view_config, )
from . import widget_os
from .dati2 import dati2_widget
from ..models import DBSession, ResKecamatan, ResDati2, ResProvinsi
from ..views import ColumnDT, DataTables, BaseView
from ...detable import DeTable
from ..views import BaseView
SESS_ADD_FAILED = 'Tambah kecamatan gagal'
SESS_EDIT_FAILED = 'Edit kecamatan gagal'
......@@ -29,10 +26,22 @@ def kecamatan_widget(node, kw):
class AddSchema(colander.Schema):
dati2_id = colander.SchemaNode(colander.String(),
provinsi_id = colander.SchemaNode(
colander.String(),
widget=provinsi_widget,
validator=colander.Length(max=32),
oid="provinsi_id",
slave="dati2_id",
slave_url="/dati2/select/act?provinsi_id=",
title="Provinsi",
)
dati2_id = colander.SchemaNode(
colander.String(),
widget=dati2_widget,
validator=colander.Length(max=32), oid="kode")
kode = colander.SchemaNode(colander.String(),
validator=colander.Length(max=32),
oid="dati2_id")
kode = colander.SchemaNode(
colander.String(),
validator=colander.Length(max=32), oid="kode")
nama = colander.SchemaNode(colander.String(), oid="nama")
......@@ -43,7 +52,8 @@ class EditSchema(AddSchema):
class ListSchema(colander.Schema):
id = colander.SchemaNode(colander.Integer(), searchable=False, orderable=False, visible=False)
id = colander.SchemaNode(colander.Integer(), searchable=False,
orderable=False, visible=False)
kode = colander.SchemaNode(colander.String(), width='100pt', title="Kode")
nama = colander.SchemaNode(colander.String(), title="Nama")
kabupaten = colander.SchemaNode(colander.String(), field=ResDati2.nama)
......
......@@ -8,7 +8,7 @@ from pyramid.httpexceptions import HTTPFound
from pyramid.view import view_config
from opensipkd.base import DBSession
from opensipkd.base.models.handlers import Log
from opensipkd.models.handlers import Log
from opensipkd.base.views import BaseView, DataTables
......
......@@ -3,7 +3,7 @@ from deform import (widget, )
from pyramid.view import (view_config, )
from . import BaseView
from ..models import (
from opensipkd.models import (
DBSession,
Parameter)
......
import os
import colander
from deform import (
widget,
......@@ -6,13 +8,16 @@ from pyramid.view import (
view_config,
)
from opensipkd.base.models import (
from opensipkd.models import (
ResProvinsi, ResDati2, ResKecamatan, ResDesa)
from opensipkd.base.models.common import ResCompany
from opensipkd.models.common import ResCompany
from opensipkd.tools import Upload, img_exts
from .company import company_widget
from .partner_base import PartnerSchema, NamaSchema
from ..models import DBSession
from ..models import Partner
from opensipkd.models import DBSession, Partner
from .. import partner_idcard_folder
from ..views import BaseView
SESS_ADD_FAILED = 'Tambah partner gagal'
......@@ -54,6 +59,9 @@ class ListSchema(NamaSchema):
missing=colander.drop,
widget=widget.HiddenWidget(),
)
email = colander.SchemaNode(
colander.String(),
oid="email")
status = colander.SchemaNode(
colander.Boolean(),
oid="status")
......@@ -147,22 +155,22 @@ class ViewPartner(BaseView):
r.append(d)
return r
@view_config(route_name='partner-add', renderer='templates/form_input.pt',
@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_input.pt',
@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_input.pt',
@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_input.pt',
@view_config(route_name='partner-delete', renderer='templates/form.pt',
permission='user-edit')
def view_delete(self):
return super().view_delete()
......@@ -179,6 +187,7 @@ class ViewPartner(BaseView):
row = q.first()
else:
row = None
q = Partner.query_kode(value['kode'])
found = q.first()
if row:
......@@ -203,6 +212,26 @@ class ViewPartner(BaseView):
company_list=ResCompany.get_list()
)
def save_request(self, values, row=None):
if "idcard" in values and values["idcard"]:
folder = self.get_params("idcard_folder", '/tmp/idcard')
upload = Upload(folder)
file_name = upload.save(self.req, 'upload', img_exts)
values["idcard"] = file_name
row = super().save_request(values, row)
return row
def get_values(self, row, istime=False):
d = super().get_values(row, istime)
if "idcard" in d and d["idcard"]:
filename = d["idcard"]
preview_url = "/".join(
[self.home, partner_idcard_folder, filename])
d["idcard"] = {"uid": filename.split(".")[0],
"filename": filename,
"preview_url": preview_url
}
return d
@colander.deferred
def partner_widget(node, kw):
......
import colander
from deform import FileData, widget
from opensipkd.base.views.dati2 import dati2_widget
from opensipkd.base.views.desa import desa_widget
from opensipkd.base.views.kecamatan import kecamatan_widget
from opensipkd.base.views.provinsi import provinsi_widget
from opensipkd.tools import mem_tmp_store
class NamaSchema(colander.Schema):
kode = colander.SchemaNode(
......@@ -20,6 +23,12 @@ class NamaSchema(colander.Schema):
class PartnerSchema(NamaSchema):
idcard = colander.SchemaNode(
FileData(),
widget=widget.FileUploadWidget(mem_tmp_store),
missing=colander.drop,
title="ID Card"
)
alamat_1 = colander.SchemaNode(
colander.String(),
missing=colander.drop,
......
......@@ -5,8 +5,8 @@ from pyramid.view import (
view_config,
)
from ..models import DBSession
from ..models import (Partner, Departemen,
from opensipkd.models import DBSession
from opensipkd.models import (Partner, Departemen,
)
from opensipkd.tools.report import (
open_rml_row,
......
......@@ -2,7 +2,7 @@ import colander
from deform import (widget, )
from pyramid.view import (view_config, )
from ..models import Permission
from opensipkd.models import Permission
from ..views import BaseView
SESS_ADD_FAILED = 'Tambah permission gagal'
......
......@@ -6,9 +6,9 @@ from pyramid.view import (view_config, )
from sqlalchemy import or_
from sqlalchemy.orm import aliased
from ..models import DBSession as PartnerDBSession, DBSession, ResCompany
from ..models import Departemen, Jabatan
from ..models import Partner, PartnerDepartemen
from opensipkd.models import DBSession as PartnerDBSession, DBSession, ResCompany
from opensipkd.models import Departemen, Jabatan
from opensipkd.models import Partner, PartnerDepartemen
from opensipkd.tools import dmy, date_from_str
from opensipkd.tools.buttons import btn_cancel, btn_save, btn_delete, btn_close
from ..views import ColumnDT, DataTables, BaseView
......
......@@ -5,8 +5,8 @@ from pyramid.view import (
view_config,
)
from ..models import DBSession as PartnerDBSession
from ..models import (
from opensipkd.models import DBSession as PartnerDBSession
from opensipkd.models import (
Departemen,
Jabatan,
Partner,
......
......@@ -3,7 +3,7 @@ from deform import (widget, )
from pyramid.view import (view_config, )
from . import widget_os
from ..models import DBSession, ResProvinsi, kategori_provinsi
from opensipkd.models import DBSession, ResProvinsi, kategori_provinsi
from ..views import BaseView
SESS_ADD_FAILED = 'Tambah provinsi gagal'
......
......@@ -30,7 +30,7 @@ import os
import colander
from deform import (widget, Button, FileData)
from opensipkd.tools import Upload
from opensipkd.tools import Upload, mem_tmp_store, image_validator
from pyramid.httpexceptions import HTTPFound
from pyramid.i18n import TranslationStringFactory
from pyramid.security import forget
......@@ -40,9 +40,9 @@ from ziggurat_foundations.models.services.user import UserService
from opensipkd.base import get_params
from opensipkd.base.views.user import email_validator, add_member_count
from . import widget_os
from .base_views import store, image_validator, need_captcha, need_verify, get_url_captcha
from .base_views import need_captcha, need_verify, get_url_captcha
from .user_login import regenerate_security_code, get_login_headers, send_email_security_code, send_email_pending
from ..models import User, DBSession, Partner, Group, UserGroup, ExternalIdentity
from opensipkd.models import User, DBSession, Partner, Group, UserGroup, ExternalIdentity
from ..views import BaseView
_ = TranslationStringFactory('user')
......@@ -88,9 +88,9 @@ class AddSchema(colander.Schema):
title=_("ID Number"),
# missing=colander.drop,
oid="kode")
self["doc_id_card"] = colander.SchemaNode(
self["idcard"] = colander.SchemaNode(
FileData(),
widget=widget.FileUploadWidget(store),
widget=widget.FileUploadWidget(mem_tmp_store),
title=_("ID Card"),
validator=image_validator)
if not request.user and need_captcha():
......@@ -178,8 +178,14 @@ class Registrasi(BaseView):
raise exc
def err_user():
if 'user_name' in form:
raise colander.Invalid(
form['user_name'], 'User name %s sudah ada yang menggunakan' % value['user_name'])
else:
raise colander.Invalid(
form['email'], 'User name %s sudah ada yang menggunakan' % value['email'])
def err_nik():
if "kode" in form:
......@@ -198,11 +204,13 @@ class Registrasi(BaseView):
ses_captcha = request.session.pop('captcha')
if captcha != ses_captcha:
err_captcha()
is_logged = form.request.user
if not "email" in value and "id_info" in session:
value["email"] = session["id_info"]["email"]
if "user_name" not in value or not value["user_name"]:
value["user_name"] = value["email"]
if 'user_name' in value:
user_name = value["user_name"]
user = user_found(user_name)
......@@ -212,8 +220,7 @@ class Registrasi(BaseView):
if user and is_logged:
if user.id != is_logged.id:
err_user()
if "user_name" not in value or not value["user_name"]:
value["user_name"] = value["mobile"]
email = value["email"]
user = user_found(email)
......@@ -263,19 +270,6 @@ class Registrasi(BaseView):
result.update(dict(captcha=get_url_captcha(self.req)))
return result
def before_save(self, row, values):
if "doc_id_card" not in values or not values["doc_id_card"]:
return row
path = get_params('reg_folder', '/tmp/registrasi')
if not os.path.exists(path):
os.makedirs(path)
upload = Upload(path)
values["doc_id_card"] = upload.save(self.req, 'upload')
row.doc_id_card = values["doc_id_card"]
return row
def after_save(self, row, values):
if not self.req.user: # User Baru
if 'groups' in values and values['groups']:
......@@ -355,7 +349,7 @@ class Registrasi(BaseView):
forget(self.req)
self.ses.delete()
@view_config(route_name='register', renderer='templates/form_input.pt')
@view_config(route_name='register', renderer='templates/form.pt')
def view_register(self):
if "g_state" in self.req.cookies:
if "id_info" not in self.ses or not self.ses["id_info"]:
......@@ -390,7 +384,7 @@ class Registrasi(BaseView):
form.set_appstruct(values)
return form
@view_config(route_name='profile', renderer='templates/form_input.pt',
@view_config(route_name='profile', renderer='templates/form.pt',
permission='view')
def view_profile(self):
reg_form = get_params("reg_form")
......@@ -398,3 +392,11 @@ class Registrasi(BaseView):
return HTTPFound(location=self.req.route_url(reg_form))
self.bindings = dict(user=self.req.user)
return super(Registrasi, self).view_edit()
def save_request(self, values, row=None):
if "idcard" in values and values["idcard"]:
path = get_params('idcard_folder', '/tmp/idcard')
upload = Upload(path)
values["idcard"] = upload.save(self.req, 'upload')
row = super().save_request(values, row)
return row
\ No newline at end of file
......@@ -14,7 +14,7 @@
# # from . import get_login_headers
# # from .register import mobile_found_partner, save_partner, nik_found
# from .user_group import save as save_groups
# from ..models import DBSession, Partner, Group, ExternalIdentity, User, ExternalIdentityService
# from opensipkd.models import DBSession, Partner, Group, ExternalIdentity, User, ExternalIdentityService
# from opensipkd.tools import get_settings
# from opensipkd.tools.captcha import get_captcha
# from ..views import BaseView
......
......@@ -4,7 +4,7 @@ from opensipkd.tools.buttons import btn_view, btn_edit, btn_delete
from pyramid.view import view_config
from . import BaseView
from ..models import (DBSession, Route, )
from opensipkd.models import (DBSession, Route, )
class EditSchema(colander.Schema):
......
<html metal:use-macro="load: ./base.pt">
<html metal:use-macro="load: ./base3.1.pt">
<js metal:fill-slot="js_files">
<script src="${home}/static/v3/js/plugin/datatables/jquery.dataTables.min.js"></script>
<script src="${home}/static/v3/js/plugin/datatables/dataTables.colVis.min.js"></script>
......
......@@ -7,8 +7,8 @@
group_path ['group', 'group-add', 'group-edit', 'group-view', 'group-delete'];
param_path ['parameter', 'parameter-add', 'parameter-edit', 'parameter-view', 'parameter-delete'];
dep_path ['departemen', 'departemen-add', 'departemen-edit', 'departemen-view', 'departemen-delete'];
partner_path ['partner', 'partner-add', 'partner-edt', 'partner-view', 'partner-del'];
company_path ['company', 'company-add', 'company-edt', 'company-view', 'company-del'];
partner_path ['partner', 'partner-add', 'partner-edit', 'partner-view', 'partner-delete'];
company_path ['company', 'company-add', 'company-edit', 'company-view', 'company-delete'];
part_dep_path ['partner-departemen', 'partner-departemen-add', 'partner-departemen-edit', 'partner-departemen-view', 'partner-departemen-delete'];
jabatan_path ['jabatan', 'jabatan-add', 'jabatan-edit', 'jabatan-view', 'jabatan-delete'];
eselon_path ['eselon', 'eselon-add', 'eselon-edit', 'eselon-view', 'eselon-delete'];
......
......@@ -14,7 +14,7 @@ from . import BaseView
from .company import company_widget
from .user_login import (
regenerate_security_code, send_email_security_code, generate_api_key, )
from ..models import (DBSession, User, Group, UserGroup, ResCompany, )
from opensipkd.models import (DBSession, User, Group, UserGroup, ResCompany, )
_ = TranslationStringFactory('user')
......
......@@ -14,8 +14,8 @@
# )
# from sqlalchemy.orm import aliased
#
# from ..models import DBSession
# from ..models import DepartemenUser, User, Departemen
# from opensipkd.models import DBSession
# from opensipkd.models import DepartemenUser, User, Departemen
# from ..views import ColumnDT, DataTables, BaseView
#
# SESS_ADD_FAILED = 'Tambah departemen gagal'
......
......@@ -6,7 +6,7 @@ from pyramid.i18n import TranslationStringFactory
from pyramid.view import view_config
from . import BaseView
from ..models import (DBSession, User, ExternalIdentity)
from opensipkd.models import (DBSession, User, ExternalIdentity)
_ = TranslationStringFactory('user')
......
......@@ -12,7 +12,7 @@ from deform import (
widget,
ValidationFailure,
)
from ..models import (
from opensipkd.models import (
DBSession,
User,
Group,
......
......@@ -34,7 +34,7 @@ from ziggurat_foundations.models.services.external_identity import \
from ziggurat_foundations.models.services.user import UserService
from opensipkd.base import DBSession, get_params
from opensipkd.base.models import User, ExternalIdentity
from opensipkd.models import User, ExternalIdentity
from opensipkd.tools import create_now, set_user_log, get_settings
from opensipkd.base.views import _, one_hour, two_minutes, BaseView
from pyramid_mailer.message import Message
......@@ -323,7 +323,8 @@ def reset_password_validator(form, value):
def security_code_age(user):
return create_now() - user.security_code_date
now = create_now()
return now - user.security_code_date
def send_email_security_code(
......
......@@ -18,8 +18,8 @@ from .user import EmailValidator as EmailValidatorBase
from .user_group import save as save_groups
from .user_login import (ChangePassword, change_password_validator,
regenerate_security_code, send_email_security_code)
from ..models import DBSession, UserService, Departemen
from ..models import (User, Partner, Group, UserGroup, PartnerDepartemen)
from opensipkd.models import DBSession, UserService, Departemen
from opensipkd.models import (User, Partner, Group, UserGroup, PartnerDepartemen)
_ = TranslationStringFactory('user')
......@@ -93,18 +93,19 @@ def login(request, data):
:param request:
:param data:
{
user_name:
password:
device_id:
"user_name": "user_name",
"password": "password"
}
:return:{
"user_name": user_name,
"token": token,
:return:
result: "data":
{
"user_name": "user_name",
"nik": nik,
"nama": nik,
"group": [group],
"departemens": departemen
"departemens": [departemen]
}
error:"error":{}
"""
is_list = type(data) is list
data = is_list and data[0] or data
......@@ -125,7 +126,6 @@ def logout(request, data):
:return:{
}
"""
# token_auth(request, logout=True)
headers = forget(request)
request.session.delete()
request.response.headers.update(headers)
......@@ -155,7 +155,7 @@ def get_profile(request, data):
Digunakan untuk memperoleh profile user yang sedang login
parameter
@param request: Request
@param data: Dict(password=password)
@param data: {"password": password}
@return:
"""
user = request.user
......@@ -257,6 +257,8 @@ def set_profile(request, data):
email="",
mobile="",
nama="",
alamat_1="",
alamat_2=""
)
:return:
"""
......@@ -288,13 +290,14 @@ def register_user(request, data):
"""
Digunakan untuk registrasi user dan profile
:param request:
:param data:Dict(
user_name="",
nik="",
email="",
mobile="",
nama="",
)
:param data:{
"user_name"="",
"email"="",
"mobile"="",
"nama"="",
"alamat_1"="",
"alamat_2"=""
}
:return:
"""
is_list = type(data) is list
......@@ -341,6 +344,16 @@ def get_password_(request, data):
@jsonrpc_method(method='get-password', endpoint='rpc-user')
@jsonrpc_method(method='get_password', endpoint='rpc-user')
def get_password(request, data):
"""
Digunakan untuk request password
:param request:
:param data: {
"email": email
}
:return:
success: {"result": {}}
error: {"error": {}}
"""
return get_password_(request, data)
......
from deform.widget import *
import json
from deform.widget import (
SchemaType,
DateInputWidget as DeformDateInputWidget)
from colander import null, Invalid
class _FieldStorage(SchemaType):
def deserialize(self, node, cstruct):
......@@ -9,3 +13,53 @@ class _FieldStorage(SchemaType):
if not hasattr(cstruct, 'file'):
raise Invalid(node, "%s is not a FieldStorage instance" % cstruct)
return cstruct
class DateInputWidget(DeformDateInputWidget):
"""
Renders a date picker widget.
The default rendering is as a native HTML5 date input widget,
falling back to pickadate (https://github.com/amsul/pickadate.js.)
Most useful when the schema node is a ``colander.Date`` object.
**Attributes/Arguments**
options
Dictionary of options for configuring the widget (eg: date format)
template
The template name used to render the widget. Default:
``dateinput``.
readonly_template
The template name used to render the widget in read-only mode.
Default: ``readonly/textinput``.
"""
default_options = (
("format", "yyyy-mm-dd"),
("selectMonths", True),
("selectYears", True),
("formatSubmit", "yyyy-mm-dd"),
)
def serialize(self, field, cstruct, **kw):
if cstruct in (null, None):
cstruct = ""
readonly = kw.get("readonly", self.readonly)
template = readonly and self.readonly_template or self.template
options = dict(
kw.get("options") or self.options or self.default_options
)
kw.setdefault("options_json", json.dumps(options))
values = self.get_template_values(field, cstruct, kw)
return field.renderer(template, **values)
def deserialize(self, field, pstruct):
if pstruct in ("", null):
return null
try:
validated = self._pstruct_schema.deserialize(pstruct)
except Invalid as exc:
raise Invalid(field.schema, "Invalid pstruct: %s" % exc)
return validated["date_submit"] or validated["date"]
<tal:block tal:define="oid oid|field.oid;
css_class css_class|field.widget.css_class;
style style|field.widget.style;">
${field.start_mapping()}
${field.start_mapping()}
<input type="file" name="upload" id="${oid}"
tal:attributes="style style;
accept accept|field.widget.accept;
......@@ -10,6 +10,11 @@
<input tal:define="uid cstruct.get('uid')"
tal:condition="uid"
type="hidden" name="uid" value="${uid}"/>
<a tal:define="preview_url cstruct.get('preview_url');
filename cstruct.get('filename')"
tal:condition="preview_url" href="${structure: preview_url}"
target="_blank">Show</a>
${field.end_mapping()}
<script type="text/javascript">
deform.addCallback('${oid}', function (oid) {
......
<p id="${oid|field.oid}" class="form-control-static deform-readonly-text"
tal:content="cstruct.get('filename') or ''">
<p tal:define="preview_url cstruct.get('preview_url')">
<a tal:condition="preview_url" href="${structure: preview_url}"
target="_blank">Show</a>
<p tal:condition="not preview_url" id="${oid|field.oid}"
class="form-control-static deform-readonly-text"
tal:content="cstruct.get('filename') or ''"></p>
</p>
from sqlalchemy import event
from .base import *
from .common import *
from .users import *
from .wilayah import *
from .partner import *
from .departemen import *
from .pegawai import *
# from .meta import *
# from .targets import *
# from .wilayah import *
def has_permission(action):
pass
@event.listens_for(User, 'before_delete', has_permission('delete'))
def receive_before_delete(mapper, connection, target):
"listen for the 'before_delete' event"
# ... (event handling logic) ...
pass
ALL_TABLES = {}
for sub_class in Base.__subclasses__():
if hasattr(sub_class, "__tablename__"):
tablename = sub_class.__tablename__
if tablename not in ALL_TABLES:
ALL_TABLES.update({tablename: sub_class})
def query_table(table_name, fields=None, domain=None):
cls = ALL_TABLES[table_name]
if fields:
query = DBSession.query().select_from(cls)
# for field in fields:
query = query.add_columns(*[getattr(cls, c) for c in fields])
else:
query = DBSession.query(cls)
if domain:
filter_expressions = []
for d in domain:
field = getattr(cls, d[0])
operator = d[1]
value = d[2]
filter_expressions.append(field.op(operator)(value))
query = query.filter(
*[
e for i, e in enumerate(filter_expressions)
if e is not None]
)
return query
from sqlalchemy import (Column, Integer, String, DateTime, func, )
from sqlalchemy.orm import (scoped_session, sessionmaker, )
from opensipkd.base import Base
from opensipkd.base.models import CommonModel
from opensipkd.models import CommonModel
factory = sessionmaker(autoflush=True, autocommit=True)
LogDBSession = scoped_session(factory)
......
......@@ -6,12 +6,13 @@ from sqlalchemy import (
DateTime, ForeignKey
)
from opensipkd.base.models.common import NamaModel
from .common import NamaModel
from .wilayah import ResProvinsi, ResDesa, ResKecamatan, ResDati2
from .meta import (Base)
class PartnerModel(NamaModel):
idcard = Column(String(256))
status = Column(Integer, default=1)
alamat_1 = Column(String(128))
alamat_2 = Column(String(128))
......
......@@ -13,7 +13,7 @@ from sqlalchemy.orm import (
backref
)
from opensipkd.base.models import Partner
from opensipkd.models import Partner
from ..models import DBSession, Base
from ..models import (DefaultModel, NamaModel, TABLE_ARGS,
User, Departemen)
......
from datetime import datetime
import pytz
from ziggurat_foundations import ziggurat_model_init
import sqlalchemy as sa
......@@ -18,7 +20,7 @@ from ziggurat_foundations.models.user_group import UserGroupMixin
from ziggurat_foundations.models.user_permission import UserPermissionMixin
from ziggurat_foundations.models.user_resource_permission import UserResourcePermissionMixin
from ziggurat_foundations.models.services.external_identity import ExternalIdentityService
from opensipkd.tools import as_timezone
from opensipkd.tools import as_timezone, get_timezone
from .base import CommonModel, DBSession, DefaultModel
from .meta import Base
......@@ -71,6 +73,10 @@ class User(UserMixin, BaseModel, CommonModel, Base):
registered_date = Column(DateTime(timezone=True),
nullable=False,
default=datetime.utcnow)
security_code_date = Column(DateTime(timezone=True),
default=datetime(2000, 1, 1, tzinfo=pytz.timezone('Asia/Jakarta')),
server_default="2000-01-01 01:01+7",
)
api_key = Column(String(256))
partner_id = Column(Integer) #, ForeignKey(Partner.id))
company_id = Column(Integer) #, ForeignKey(Partner.id))
......
from sqlalchemy.orm import relationship, backref
from opensipkd.base.models import TABLE_ARGS
from opensipkd.models import TABLE_ARGS
from sqlalchemy import (
Column,
ForeignKey,
......
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!