Commit 1f158947 by aagusti

api

1 parent 1c9f3ec4
...@@ -66,29 +66,30 @@ titles = {} ...@@ -66,29 +66,30 @@ titles = {}
# http://stackoverflow.com/questions/9845669/pyramid-inverse-to-add-notfound-viewappend-slash-true # http://stackoverflow.com/questions/9845669/pyramid-inverse-to-add-notfound-viewappend-slash-true
class RemoveSlashNotFoundViewFactory(object): # class RemoveSlashNotFoundViewFactory(object):
def __init__(self, notfound_view=None): # diganti menggunakan @view_config(context=HTTPNotFound, renderer='templates/404.pt') pada base.views
if notfound_view is None: # def __init__(self, notfound_view=None):
notfound_view = default_exceptionresponse_view # if notfound_view is None:
self.notfound_view = notfound_view # notfound_view = default_exceptionresponse_view
# self.notfound_view = notfound_view
def __call__(self, context, request): #
if not isinstance(context, Exception): # def __call__(self, context, request):
# backwards compat for an append_notslash_view registered via # if not isinstance(context, Exception):
# config.set_notfound_view instead of as a proper exception view # # backwards compat for an append_notslash_view registered via
context = getattr(request, 'exception', None) or context # # config.set_notfound_view instead of as a proper exception view
path_req = request.path # context = getattr(request, 'exception', None) or context
registry = request.registry # path_req = request.path
mapper = registry.queryUtility(IRoutesMapper) # registry = request.registry
if mapper is not None and path_req.endswith('/'): # mapper = registry.queryUtility(IRoutesMapper)
noslash_path = path_req.rstrip('/') # if mapper is not None and path_req.endswith('/'):
for route in mapper.get_routes(): # noslash_path = path_req.rstrip('/')
if route.match(noslash_path) is not None: # for route in mapper.get_routes():
qs = request.query_string # if route.match(noslash_path) is not None:
if qs: # qs = request.query_string
noslash_path += '?' + qs # if qs:
return HTTPFound(location=noslash_path) # noslash_path += '?' + qs
return self.notfound_view(context, request) # return HTTPFound(location=noslash_path)
# return self.notfound_view(context, request)
# https://groups.google.com/forum/#!topic/pylons-discuss/QIj4G82j04c # https://groups.google.com/forum/#!topic/pylons-discuss/QIj4G82j04c
...@@ -312,11 +313,11 @@ def json_rpc(): ...@@ -312,11 +313,11 @@ def json_rpc():
return json_r return json_r
class MyAuthenticationPolicy(AuthTktAuthenticationPolicy): # class MyAuthenticationPolicy(AuthTktAuthenticationPolicy):
def authenticated_userid(self, request): # def authenticated_userid(self, request):
user = request.user # user = request.user
if user is not None: # if user is not None:
return user.id # return user.id
def get_host(request): def get_host(request):
...@@ -371,35 +372,21 @@ def main(global_config, **settings): ...@@ -371,35 +372,21 @@ def main(global_config, **settings):
config = Configurator(settings=settings, config = Configurator(settings=settings,
root_factory='opensipkd.base.models.RootFactory', root_factory='opensipkd.base.models.RootFactory',
session_factory=session_factory) session_factory=session_factory)
from .models import RootFactory
modules = get_modules(settings) modules = get_modules(settings)
# print(modules)
from importlib import import_module from importlib import import_module
for module in modules: for module in modules:
# compatibility
if module == 'admin': if module == 'admin':
continue continue
module = module.replace('/', '.') module = module.replace('/', '.')
mfile = module mfile = module
print(">>Load Module:", mfile)
m = import_module(mfile) m = import_module(mfile)
cfg = m.main(config, **settings) cfg = m.main(config, **settings)
if cfg: if cfg:
config = cfg config = cfg
# todo apakah config bisa dikirim ke module?
# contoh:
# config = m.config(config)
# dipindahkan ke config pyramid.include
# config.include('pyramid_beaker')
# config.include('pyramid_chameleon')
# authn_policy = AuthTktAuthenticationPolicy(
# 'sosecret', callback=group_finder, hashalg='sha512')
#
# authz_policy = ACLAuthorizationPolicy()
config.set_security_policy(MySecurityPolicy(settings["session.secret"])) config.set_security_policy(MySecurityPolicy(settings["session.secret"]))
# config.set_authentication_policy(authn_policy)
# config.set_security_policy(authz_policy)
# config.set_authorization_policy(authz_policy)
config.add_request_method(get_user, 'user', reify=True) config.add_request_method(get_user, 'user', reify=True)
config.add_request_method(get_title, 'title', reify=True) config.add_request_method(get_title, 'title', reify=True)
config.add_request_method(get_company, 'company', reify=True) config.add_request_method(get_company, 'company', reify=True)
...@@ -421,70 +408,19 @@ def main(global_config, **settings): ...@@ -421,70 +408,19 @@ def main(global_config, **settings):
config.add_request_method(allow_register, 'allow_register', reify=True) config.add_request_method(allow_register, 'allow_register', reify=True)
config.add_request_method(disable_responsive, 'disable_responsive', reify=True) config.add_request_method(disable_responsive, 'disable_responsive', reify=True)
config.add_request_method(get_params, 'get_params', reify=True) config.add_request_method(get_params, 'get_params', reify=True)
# config.add_notfound_view(RemoveSlashNotFoundViewFactory())
config.add_static_view('static', 'opensipkd.base:static', cache_max_age=3600) config.add_static_view('static', 'opensipkd.base:static', cache_max_age=3600)
config.add_static_view('deform_static', 'deform:static') config.add_static_view('deform_static', 'deform:static')
# config.add_view('.views.api.echoGateway')
# config.add_static_view('files', get_params('static_files'))
# Captcha
captcha_files = get_params('captcha_files', settings=settings,alternate="/tmp/captcha") captcha_files = get_params('captcha_files', settings=settings, alternate="/tmp/captcha")
if not os.path.exists(captcha_files): if not os.path.exists(captcha_files):
os.makedirs(captcha_files) os.makedirs(captcha_files)
config.add_static_view('captcha', captcha_files)
# config.add_static_view('tts', path=get_params('tts_files'))
config.add_static_view('captcha', captcha_files)
config.add_renderer('csv', 'opensipkd.tools.CSVRenderer') config.add_renderer('csv', 'opensipkd.tools.CSVRenderer')
config.add_renderer('json', json_renderer()) config.add_renderer('json', json_renderer())
# dipindahkan ke config pyramid.include
# config.include('pyramid_rpc.jsonrpc')
config.add_renderer('json_rpc', json_rpc()) config.add_renderer('json_rpc', json_rpc())
# q = DBSession.query(Route)
# for route in q:
# if route.type == 0:
# config.add_route(route.kode, route.path)
# if route.nama:
# titles[route.kode] = route.nama
# elif route.type == 1:
# config.add_jsonrpc_endpoint(route.kode, route.path,
# default_renderer="json_rpc")
set_routes(config) set_routes(config)
###########################################
# MAP
# todo apabila config bosa di get dari module maka baris ini bisa hilang
# Sudah solve menggunakan includeme
###########################################
# if 'opensipkd.map.base' in modules:
# import papyrus
# from papyrus.renderers import GeoJSON, XSD
#
# config.add_request_method(get_gmap_key, 'gmap_key', reify=True)
# config.add_request_method(get_bing_key, 'bing_key', reify=True)
# config.add_request_method(get_extent, 'extent', reify=True)
#
# config.include(papyrus.includeme)
# config.add_renderer('geojson', GeoJSON())
# config.add_renderer('xsd', XSD())
# config.add_static_view('static_map', 'opensipkd.map.base:static', cache_max_age=3600)
# if 'opensipkd.map.aset' in modules:
# config.add_static_view('static_map_aset', 'opensipkd.map.aset:static', cache_max_age=3600)
#
# # if 'opensipkd.map.pbb' in modules:
# # config.add_static_view('static_map_pbb', 'opensipkd.map.pbb:static', cache_max_age=3600)
#
# if 'opensipkd.pasar.web' in modules:
# config.add_static_view('static_pasar', 'opensipkd.pasar.web:static', cache_max_age=3600)
#
# if 'opensipkd.pbb.master' in modules:
# config.add_static_view('static_pbb', 'opensipkd.pbb.master:static', cache_max_age=3600)
# if 'opensipkd.pos.pbb' in modules:
# config.add_static_view('static_pospbb', 'opensipkd.pos.pbb:static', cache_max_age=3600)
config.registry['mailer'] = mailer_factory_from_settings(settings) config.registry['mailer'] = mailer_factory_from_settings(settings)
# config.include()
config.scan() config.scan()
for m in modules: for m in modules:
config.scan(m) config.scan(m)
......
"""penambahan user device expired
Revision ID: 8e7057155823
Revises: 86c1b4a1da16
Create Date: 2022-07-08 14:58:39.378811
"""
# revision identifiers, used by Alembic.
revision = '8e7057155823'
down_revision = '86c1b4a1da16'
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('user_device', 'expired'):
op.add_column('user_device', sa.Column('expired', sa.DateTime(timezone=True)))
op.alter_column('user_device', sa.Column('expired', sa.DateTime(timezone=True)))
if not helpers.table_has_column('routes', 'create_uid'):
op.add_column('routes', sa.Column('create_uid', sa.Integer, default=0))
if not helpers.table_has_column('routes', 'update_uid'):
op.add_column('routes', sa.Column('update_uid', sa.Integer, default=0))
def downgrade():
pass
...@@ -38,8 +38,9 @@ class UserDeviceModel(Base, KodeModel): ...@@ -38,8 +38,9 @@ class UserDeviceModel(Base, KodeModel):
kode = Column(String(256)) kode = Column(String(256))
token = Column(String(256)) token = Column(String(256))
logged_in = Column(Integer) logged_in = Column(Integer)
las_login_date = Column(DateTime) las_login_date = Column(DateTime(timezone=True))
expired = Column(DateTime(timezone=True))
user = relationship(User, backref=backref("devices"))
class ResCompany(Base, NamaModel): class ResCompany(Base, NamaModel):
__tablename__ = 'company' __tablename__ = 'company'
......
...@@ -258,14 +258,16 @@ def alembic_run(ini_file, name=None): ...@@ -258,14 +258,16 @@ def alembic_run(ini_file, name=None):
if subprocess.call(command) != 0: if subprocess.call(command) != 0:
sys.exit() sys.exit()
def alembic_run(ini_file, name='alembic_base'):
def base_alembic_run(ini_file, name=None):
bin_path = os.path.split(sys.executable)[0] bin_path = os.path.split(sys.executable)[0]
alembic_bin = os.path.join(bin_path, 'alembic') alembic_bin = os.path.join(bin_path, 'alembic')
command = (alembic_bin, '-c', ini_file, '-n', 'alembic_base', 'upgrade', 'head') command = (alembic_bin, '-c', ini_file, '-n', name, 'upgrade', 'head')
if subprocess.call(command) != 0: if subprocess.call(command) != 0:
sys.exit() sys.exit()
def base_alembic_run(ini_file):
alembic_run(ini_file)
def main(argv=sys.argv): def main(argv=sys.argv):
if len(argv) < 2: if len(argv) < 2:
......
import logging import logging
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 .models import (
User, User,
UserGroup, UserGroup,
...@@ -35,6 +40,7 @@ def get_user(request): ...@@ -35,6 +40,7 @@ def get_user(request):
q = DBSession.query(User).filter_by(id=user_id) q = DBSession.query(User).filter_by(id=user_id)
return q.first() return q.first()
# def get_user(request): # def get_user(request):
# user_id = request.unauthenticated_userid # user_id = request.unauthenticated_userid
# if user_id is not None: # if user_id is not None:
...@@ -45,21 +51,18 @@ def get_user(request): ...@@ -45,21 +51,18 @@ def get_user(request):
from pyramid.authentication import AuthTktCookieHelper from pyramid.authentication import AuthTktCookieHelper
from pyramid.authorization import ACLHelper, Authenticated, Everyone from pyramid.authorization import ACLHelper, Authenticated, Everyone
class MySecurityPolicy: class MySecurityPolicy:
def __init__(self, secret): def __init__(self, secret):
self.helper = AuthTktCookieHelper(secret) self.helper = AuthTktCookieHelper(secret)
def identity(self, request): def identity(self, request):
# define our simple identity as None or a dict with userid and principals keys
identity = self.helper.identify(request) identity = self.helper.identify(request)
if identity is None: if identity is None:
return None return None
userid = identity['userid'] # identical to the deprecated request.unauthenticated_userid
# verify the userid, just like we did before with groupfinder userid = identity['userid']
principals = group_finder(userid, request) principals = group_finder(userid, request)
# assuming the userid is valid, return a map with userid and principals
if principals is not None: if principals is not None:
return { return {
'userid': userid, 'userid': userid,
...@@ -67,18 +70,14 @@ class MySecurityPolicy: ...@@ -67,18 +70,14 @@ class MySecurityPolicy:
} }
def authenticated_userid(self, request): def authenticated_userid(self, request):
# defer to the identity logic to determine if the user id logged in
# and return None if they are not
identity = request.identity identity = request.identity
if identity is not None: if identity is not None:
return identity['userid'] return identity['userid']
def permits(self, request, context, permission): def permits(self, request, context, permission):
# use the identity to build a list of principals, and pass them
# to the ACLHelper to determine allowed/denied
identity = request.identity identity = request.identity
principals = set([Everyone]) principals = set([Everyone])
if identity is not None: if identity is not None:
principals.add(Authenticated) principals.add(Authenticated)
principals.add(identity['userid']) principals.add(identity['userid'])
...@@ -90,4 +89,3 @@ class MySecurityPolicy: ...@@ -90,4 +89,3 @@ class MySecurityPolicy:
def forget(self, request, **kw): def forget(self, request, **kw):
return self.helper.forget(request, **kw) return self.helper.forget(request, **kw)
from .. import log import logging
log=logging.getLogger(__name__)
log.warning("opensipkd.base.tools depreciated use opensipkd.tools") log.warning("opensipkd.base.tools depreciated use opensipkd.tools")
from opensipkd.tools import * from opensipkd.tools import *
import json import json
from datetime import timedelta, timezone, tzinfo
import requests import requests
from opensipkd.tools import ( from opensipkd.tools import (
get_random_number, devel, get_random_string, get_settings) get_random_number, devel, get_random_string, get_settings, DefaultTimeZone, get_params, get_timezone)
from opensipkd.tools.api import * from opensipkd.tools.api import *
from .. import log
from ..models import (DBSession, User, GroupPermission, UserDeviceModel) from ..models import (DBSession, User, GroupPermission, UserDeviceModel)
import logging
lima_menit = 300 log = logging.getLogger(__name__)
lima_menit = 300
#
def auth_from_rpc(request): def auth_from_rpc(request):
return auth_from(request) return auth_from(request)
def rpc_auth(request):
return auth_from(request)
def auth_from(request, field=None): def auth_from(request, field=None):
global lima_menit global lima_menit
...@@ -43,27 +50,44 @@ def auth_from(request, field=None): ...@@ -43,27 +50,44 @@ def auth_from(request, field=None):
return user return user
# def auth_from_token(request):
def auth_from_token(request): # return auth_from(request, "security_code")
return auth_from(request, "security_code") #
def renew_token(user_device): # def renew_token(user_device, logout=False):
user_device.token = get_random_string(32) # now = datetime.now(tz=get_timezone())
DBSession.add(user_device) # tte = timedelta(minutes=10)
DBSession.flush() # if not user_device.expired or not user_device.token or \
return user_device # now - user_device.expired > tte:
# user_device.expired = now
def get_user_device(request, user): # user_device.token = get_random_string(128)
# if logout:
# user_device.token=""
# DBSession.add(user_device)
# DBSession.flush()
# return user_device
# def token_auth(request, logout=False):
# if not request.environ["HTTP_TOKEN"]:
# raise JsonRpcInvalidLoginError
# user_device = UserDeviceModel.query() \
# .filter_by(kode=request.environ["HTTP_USER_AGENT"],
# token=request.environ["HTTP_TOKEN"]).first()
# if not user_device:
# raise JsonRpcInvalidLoginError
#
# return renew_token(user_device, logout=logout)
def get_user_device(request, user_id):
user_device = UserDeviceModel.query() \ user_device = UserDeviceModel.query() \
.filter_by(user_id=user.id, .filter_by(user_id=user_id,
kode=request.environ["HTTP_USER_AGENT"]).first() kode=request.environ["HTTP_USER_AGENT"]).first()
if not user_device: if not user_device:
user_device = UserDeviceModel() user_device = UserDeviceModel()
user_device.user_id = user.id user_device.user_id = user_id
user_device.kode = request.environ["HTTP_USER_AGENT"] user_device.kode = request.environ["HTTP_USER_AGENT"]
user_device.token = get_random_string(32) # user_device = renew_token(user_device)
DBSession.add(user_device)
DBSession.flush()
return user_device return user_device
...@@ -82,6 +106,7 @@ def validate_time(request): ...@@ -82,6 +106,7 @@ def validate_time(request):
return time_stamp return time_stamp
def auth_device(request): def auth_device(request):
env = request.environ env = request.environ
log.info(env) log.info(env)
......
...@@ -4,15 +4,20 @@ from datetime import timedelta ...@@ -4,15 +4,20 @@ from datetime import timedelta
import colander import colander
from deform import ( from deform import (
Form, ValidationFailure, widget, Button, ) Form, ValidationFailure, widget, Button, )
from opensipkd.tools.api import JsonRpcInvalidLoginError
from pyramid.httpexceptions import ( from pyramid.httpexceptions import (
HTTPFound, HTTPForbidden, HTTPNotFound, HTTPInternalServerError, HTTPFound, HTTPForbidden, HTTPNotFound, HTTPInternalServerError,
HTTPSeeOther) HTTPSeeOther)
from pyramid.i18n import TranslationStringFactory from pyramid.i18n import TranslationStringFactory
from pyramid.interfaces import IRoutesMapper from pyramid.interfaces import IRoutesMapper
from pyramid.renderers import render_to_response
from pyramid.response import Response from pyramid.response import Response
from pyramid.security import remember
from pyramid.view import view_config from pyramid.view import view_config
from opensipkd.base import get_params from opensipkd.base import get_params
from opensipkd.base.tools.api import rpc_auth
from .base_views import BaseView from .base_views import BaseView
from ..models import ( from ..models import (
DBSession, UserService, ) DBSession, UserService, )
...@@ -74,18 +79,11 @@ class Home(BaseView): ...@@ -74,18 +79,11 @@ class Home(BaseView):
@view_config(context=HTTPForbidden, renderer='templates/403.pt') @view_config(context=HTTPForbidden, renderer='templates/403.pt')
def http_forbidden(request): def http_forbidden(request):
# if request.authenticated_userid: # (request):
# request.session.flash('Hak Akses Terbatas', 'error')
# return HTTPFound(location=request.route_url('home'))
# return HTTPFound(location=request.route_url('login'))
if not request.is_authenticated: if not request.is_authenticated:
next_url = request.route_url('login', _query={'next': request.url}) next_url = request.route_url('login', _query={'next': request.url})
# next_url = f'{get_params("_host").strip()}/{next_url}'
# log.info(next_url)
return HTTPSeeOther(location=next_url) return HTTPSeeOther(location=next_url)
request.response.status = 403
request.response.status = 403
return {"url": request.url} return {"url": request.url}
......
...@@ -6,35 +6,7 @@ from ziggurat_foundations.models.services.user import UserService ...@@ -6,35 +6,7 @@ from ziggurat_foundations.models.services.user import UserService
from ..models import Partner, User from ..models import Partner, User
def get_profile_(user):
partner = Partner.query().filter_by(email=user.email).first()
if not partner:
raise JsonRpcInvalidDataError
result = dict(user_name=user.user_name,
nik=partner.kode,
email=partner.email,
mobile=partner.mobile,
nama=partner.nama, )
return dict(data=result)
@jsonrpc_method(method='get_profile', endpoint='rpc-user')
def get_profile(request, data):
"""
Digunakan untuk memperoleh profile user yang sedang login
parameter
@param request: Request
@param data: Dict(user_name=user_name/email, password=password)
@return:
"""
user = request.user
print("User", user)
data = type(data) == list and data[0] or data
user = User.get_by_identity(data["user_name"])
if not user or not UserService.check_password(user, data['password']):
raise JsonRpcInvalidLoginError
return get_profile_(user)
# services = { # services = {
......
...@@ -12,12 +12,13 @@ class NamaSchema(colander.Schema): ...@@ -12,12 +12,13 @@ class NamaSchema(colander.Schema):
validator=colander.Length(max=32), validator=colander.Length(max=32),
oid="kode", oid="kode",
title="Kode", title="Kode",
width="100pt") width="100pt")
nama = colander.SchemaNode( nama = colander.SchemaNode(
colander.String(), colander.String(),
validator=colander.Length(max=64), validator=colander.Length(max=64),
oid="nama") oid="nama")
class PartnerSchema(NamaSchema): class PartnerSchema(NamaSchema):
alamat_1 = colander.SchemaNode( alamat_1 = colander.SchemaNode(
colander.String(), colander.String(),
......
<html metal:use-macro="load: ./base3.1.pt"> <html metal:use-macro="load: ./base.pt">
<js metal:fill-slot="js_files"> <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/jquery.dataTables.min.js"></script>
<script src="${home}/static/v3/js/plugin/datatables/dataTables.colVis.min.js"></script> <script src="${home}/static/v3/js/plugin/datatables/dataTables.colVis.min.js"></script>
<script src="${home}/static/v3/js/plugin/datatables/dataTables.tableTools.min.js"></script> <script src="${home}/static/v3/js/plugin/datatables/dataTables.tableTools.min.js"></script>
<script src="${home}/static/v3/js/plugin/datatables/dataTables.bootstrap.min.js"></script> <script src="${home}/static/v3/js/plugin/datatables/dataTables.bootstrap.min.js"></script>
<script src="${home}/static/v3/js/plugin/datatable-responsive/datatables.responsive.min.js"></script> <script src="${home}/static/v3/js/plugin/datatable-responsive/datatables.responsive.min.js"></script>
</js> </js>
</html> </html>
\ No newline at end of file \ No newline at end of file
...@@ -94,8 +94,8 @@ class Views(BaseView): ...@@ -94,8 +94,8 @@ class Views(BaseView):
base_path=base_path) base_path=base_path)
filename = os.path.basename(filename) filename = os.path.basename(filename)
resp = pdf_response(self.req, pdf, filename) resp = pdf_response(self.req, pdf, filename)
if resp.content_length<10: if resp.content_length < 10:
resp.content_length=len(resp.body) resp.content_length = len(resp.body)
return resp return resp
return super(Views, self).view_act() return super(Views, self).view_act()
...@@ -238,21 +238,22 @@ class EmailValidator(colander.Email, Validator): ...@@ -238,21 +238,22 @@ class EmailValidator(colander.Email, Validator):
Validator.__init__(self, user) Validator.__init__(self, user)
def __call__(self, node, value): def __call__(self, node, value):
def email_found():
data = dict(email=email, uid=found.id)
ts = _(
'email-already-used',
default='Email ${email} already used by user ID ${uid}',
mapping=data)
raise colander.Invalid(node, ts)
if self.match_object.match(value) is None: if self.match_object.match(value) is None:
raise colander.Invalid(node, _('Invalid email format')) raise colander.Invalid(node, _('Invalid email format'))
email = value.lower() email = value.lower()
if self.user and self.user.email == email:
return
q = DBSession.query(User).filter_by(email=email) q = DBSession.query(User).filter_by(email=email)
found = q.first() found = q.first()
if not found: if found and (not self.user or self.user.email!=found.email):
return email_found()
data = dict(email=email, uid=found.id)
ts = _(
'email-already-used',
default='Email ${email} already used by user ID ${uid}',
mapping=data)
raise colander.Invalid(node, ts)
REGEX_ONLY_CONTAIN = re.compile('([A-Za-z0-9-]*)') REGEX_ONLY_CONTAIN = re.compile('([A-Za-z0-9-]*)')
......
...@@ -29,13 +29,14 @@ from pyramid.httpexceptions import HTTPFound, HTTPNotFound ...@@ -29,13 +29,14 @@ from pyramid.httpexceptions import HTTPFound, HTTPNotFound
from pyramid.renderers import render_to_response from pyramid.renderers import render_to_response
from pyramid.security import remember, forget from pyramid.security import remember, forget
from pyramid.view import view_config from pyramid.view import view_config
from ziggurat_foundations.models.services.external_identity import ExternalIdentityService from ziggurat_foundations.models.services.external_identity import \
ExternalIdentityService
from ziggurat_foundations.models.services.user import UserService from ziggurat_foundations.models.services.user import UserService
from opensipkd.base import DBSession, get_params from opensipkd.base import DBSession, get_params
from opensipkd.base.models import User, ExternalIdentity from opensipkd.base.models import User, ExternalIdentity
from opensipkd.tools import create_now, set_user_log, get_settings from opensipkd.tools import create_now, set_user_log, get_settings
from opensipkd.base.views import _, one_hour, two_minutes from opensipkd.base.views import _, one_hour, two_minutes, BaseView
from pyramid_mailer.message import Message from pyramid_mailer.message import Message
log = __import__("logging").getLogger(__name__) log = __import__("logging").getLogger(__name__)
...@@ -60,121 +61,120 @@ def get_login_headers(request, user): ...@@ -60,121 +61,120 @@ def get_login_headers(request, user):
return headers return headers
@view_config(route_name='login', renderer='templates/login.pt') class Views(BaseView):
def view_login(request): @view_config(route_name='login', renderer='templates/login.pt')
request.session["login"]=True def view_login(self):
next_url = request.params.get('next', request.referrer) request = self.req
login_tpl = get_params('login_tpl', 'templates/login.pt') request.session["login"] = True
if not next_url: next_url = request.params.get('next', request.referrer)
next_url = request.route_url('home') # get_params('_host')+ login_tpl = get_params('login_tpl', 'templates/login.pt')
if not next_url:
if request.authenticated_userid: # (request): next_url = request.route_url('home')
request.session.flash('Anda sudah login', 'error')
return HTTPFound(location=f"{request.route_url('home')}") if request.authenticated_userid: # (request):
request.session.flash('Anda sudah login', 'error')
schema = Login(validator=login_validator) return HTTPFound(location=f"{request.route_url('home')}")
form = Form(schema, buttons=('login',))
message = "" schema = Login(validator=login_validator)
if 'login' in request.POST: form = Form(schema, buttons=('login',))
identity = request.POST.get('username') message = ""
user = schema.user = User.get_by_identity(identity) if 'login' in request.POST:
controls = request.POST.items() identity = request.POST.get('username')
try: user = schema.user = User.get_by_identity(identity)
c = form.validate(controls) controls = request.POST.items()
except ValidationFailure as e:
msg = 'Login gagal'
set_user_log(msg, request, log, identity)
request.session.flash(msg, 'error')
return HTTPFound(location=request.route_url('login'))
values = dict(c)
# start cek external module
pckgs = get_params('external-uim')
if user:
external_user = DBSession.query(ExternalIdentity) \
.filter_by(local_user_id=user.id,
external_user_name=identity).first()
pckgs = external_user and pckgs or None
if pckgs:
# user_name = user and user.user_name or ""
m = import_module(pckgs)
try: try:
user = m.login(identity, values['password'], user) c = form.validate(controls)
except Exception as e: except ValidationFailure as e:
log.warn(str(e)) msg = 'Login gagal'
request.session.flash(str(e), "error")
return HTTPFound(location=request.route_url('login'))
else:
if not user or not UserService.check_password(user, values['password']):
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')
next_url = f"{request.route_url('login')}?next={next_url}" return HTTPFound(location=request.route_url('login'))
return HTTPFound(location=next_url)
return redirect_login(request, user)
elif 'register' in request.POST: values = dict(c)
register_form = get_params("register_form", 'register') # start cek external module
return HTTPFound(location=request.route_url(register_form)) pckgs = get_params('external-uim')
if user:
external_user = DBSession.query(ExternalIdentity) \
.filter_by(local_user_id=user.id,
external_user_name=identity).first()
pckgs = external_user and pckgs or None
if pckgs:
# user_name = user and user.user_name or ""
m = import_module(pckgs)
try:
user = m.login(identity, values['password'], user)
except Exception as e:
log.warn(str(e))
request.session.flash(str(e), "error")
return HTTPFound(location=request.route_url('login'))
else:
if not user or not UserService.check_password(user, values[
'password']):
msg = "Login Gagal"
set_user_log(msg, request, log, identity)
request.session.flash(msg, "error")
next_url = f"{request.route_url('login')}?next={next_url}"
return HTTPFound(location=next_url)
elif 'login failed' in request.session: return redirect_login(request, user)
r = dict(form=request.session['login failed'])
del request.session['login failed']
return r
elif "provider_name" in request.params and request.params["provider_name"]: elif 'register' in request.POST:
provider_name = request.params["provider_name"]
if provider_name == "google":
from .base_google import googlesignin
try:
id_info = googlesignin(request)
except Exception as e:
login = ""
request.session.flash(str(e), "error")
return render_to_response(login_tpl,
dict(form=form.render(),
message=message,
url=request.route_url('login'),
next_url=next_url,
login=login, ),
request=request)
request.session["id_info"] = id_info
else:
id_info = None
user = id_info and ExternalIdentityService. \
user_by_external_id_and_provider(id_info['sub'], id_info['iss'])
if id_info and not user:
request.session.flash('Silahkan Melakukan Registrasi')
register_form = get_params("register_form", 'register') register_form = get_params("register_form", 'register')
return HTTPFound(location=request.route_url(register_form)) return HTTPFound(location=request.route_url(register_form))
if user and user.status == 1: elif 'login failed' in request.session:
return redirect_login(request, user) r = dict(form=request.session['login failed'])
else: del request.session['login failed']
message = "User anda masih menunggu verifikasi atau lagi di blokir" return r
request.session.flash(message, "error")
# if "g_state" in request.cookies: elif "provider_name" in request.params and request.params[
# requests.post("https://accounts.google.com/o/oauth2/revoke?token=" + ACCESS_TOKEN); "provider_name"]:
# headers = forget(request) provider_name = request.params["provider_name"]
# request.session.delete() if provider_name == "google":
# request.session["start"]="login" from .base_google import googlesignin
login="" try:
return render_to_response(login_tpl, id_info = googlesignin(request)
dict(form=form.render(), except Exception as e:
message=message, login = ""
url=request.route_url('login'), request.session.flash(str(e), "error")
next_url=next_url, return render_to_response(login_tpl,
login=login, ), dict(form=form.render(),
request=request) message=message,
url=request.route_url(
# return dict( 'login'),
# ) next_url=next_url,
login=login, ),
request=request)
request.session["id_info"] = id_info
else:
id_info = None
user = id_info and ExternalIdentityService. \
user_by_external_id_and_provider(id_info['sub'], id_info['iss'])
if id_info and not user:
request.session.flash('Silahkan Melakukan Registrasi')
register_form = get_params("register_form", 'register')
return HTTPFound(location=request.route_url(register_form))
if user and user.status == 1:
return redirect_login(request, user)
else:
message = "User anda masih menunggu verifikasi atau lagi di blokir"
request.session.flash(message, "error")
login = ""
return render_to_response(
renderer_name=login_tpl,
request=request,
value=dict(form=form.render(),
message=message,
url=request.route_url('login'),
next_url=next_url,
login=login, ),
)
def redirect_login(request, user): def redirect_login(request, user):
...@@ -200,7 +200,12 @@ def view_logout(request): ...@@ -200,7 +200,12 @@ def view_logout(request):
request.session.delete() request.session.delete()
if "g_state" in request.cookies: if "g_state" in request.cookies:
del request.cookies["g_state"] del request.cookies["g_state"]
return HTTPFound(location=f"{request.route_url('home')}", # if "g_state" in request.cookies:
# requests.post("https://accounts.google.com/o/oauth2/revoke?token=" + ACCESS_TOKEN);
# headers = forget(request)
# request.session.delete()
# request.session["start"]="login"
return HTTPFound(location=request.route_url('home'),
headers=headers) headers=headers)
return dict() return dict()
...@@ -210,14 +215,25 @@ class ChangePassword(colander.Schema): ...@@ -210,14 +215,25 @@ class ChangePassword(colander.Schema):
colander.String(), widget=widget.PasswordWidget()) colander.String(), widget=widget.PasswordWidget())
retype_password = colander.SchemaNode( retype_password = colander.SchemaNode(
colander.String(), widget=widget.PasswordWidget()) colander.String(), widget=widget.PasswordWidget())
password = colander.SchemaNode(colander.String(),
title=_("Old Password"))
def change_password_validator(form, value): def change_password_validator(form, value):
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']: if value['new_password'] != value['retype_password']:
raise colander.Invalid(form, 'Retype mismatch.') exc["new_password"] = 'Retype mismatch.'
exc["retype_password"] = 'Retype mismatch.'
raise exc
@view_config(route_name='change-password', renderer='templates/change-password.pt') @view_config(route_name='change-password',
renderer='templates/change-password.pt')
def view_change_password(request): def view_change_password(request):
if request.authenticated_userid: if request.authenticated_userid:
request.session.flash('Anda sudah login', 'error') request.session.flash('Anda sudah login', 'error')
...@@ -265,7 +281,8 @@ def generate_api_key(): ...@@ -265,7 +281,8 @@ def generate_api_key():
@view_config( @view_config(
route_name='recreate-api-key', renderer='templates/recreate-api-key.pt', permission='view') route_name='recreate-api-key', renderer='templates/recreate-api-key.pt',
permission='view')
def view_recreate_api_key(request): def view_recreate_api_key(request):
if not request.user.api_key: if not request.user.api_key:
return HTTPNotFound() return HTTPNotFound()
...@@ -374,7 +391,8 @@ def regenerate_security_code(user): ...@@ -374,7 +391,8 @@ def regenerate_security_code(user):
return one_hour return one_hour
@view_config(route_name='reset-password', renderer='templates/reset-password.pt') @view_config(route_name='reset-password',
renderer='templates/reset-password.pt')
def view_reset_password(request): def view_reset_password(request):
if request.authenticated_userid: if request.authenticated_userid:
return HTTPFound(location=f"{request.route_url('home')}") return HTTPFound(location=f"{request.route_url('home')}")
...@@ -394,7 +412,8 @@ def view_reset_password(request): ...@@ -394,7 +412,8 @@ def view_reset_password(request):
resp['form'] = form.render() resp['form'] = form.render()
return resp return resp
remain = regenerate_security_code(user) remain = regenerate_security_code(user)
set_user_log("Reset password to {}".format(user.email), request, log, user.user_name) set_user_log("Reset password to {}".format(user.email), request, log,
user.user_name)
send_email_security_code( send_email_security_code(
request, user, remain, 'Reset password', 'reset-password-body', request, user, remain, 'Reset password', 'reset-password-body',
'reset-password-body.tpl') 'reset-password-body.tpl')
...@@ -404,6 +423,7 @@ def view_reset_password(request): ...@@ -404,6 +423,7 @@ def view_reset_password(request):
@view_config( @view_config(
route_name='reset-password-sent', renderer='templates/reset-password-sent.pt') route_name='reset-password-sent',
renderer='templates/reset-password-sent.pt')
def view_reset_password_sent(request): def view_reset_password_sent(request):
return dict(title=_('Reset password')) return dict(title=_('Reset password'))
import re
from datetime import datetime from datetime import datetime
from email.utils import parseaddr
import transaction import colander
################## from deform import Form, ValidationFailure
# RPC USER from opensipkd.base.tools.api import (
################## get_user_device)
from opensipkd.base.views.partner_base import NamaSchema
from opensipkd.jsonrpc_auth import JsonRpcInvalidLogin
from opensipkd.tools import create_now
from opensipkd.tools.api import (
JsonRpcInvalidLoginError, JsonRpcInvalidDataError,
JsonRpcUserNotFoundError)
from pyramid.i18n import TranslationStringFactory
from pyramid.security import remember, forget
from pyramid_rpc.jsonrpc import jsonrpc_method from pyramid_rpc.jsonrpc import jsonrpc_method
from opensipkd.tools.api import ( from .user import EmailValidator as EmailValidatorBase
JsonRpcInvalidLoginError, JsonRpcInvalidNikError, JsonRpcInvalidMobileError,
JsonRpcInvalidEmailError, JsonRpcUserFoundError, JsonRpcEmailFoundError,
JsonRpcNikFoundError, JsonRpcRegisterFailError, JsonRpcInvalidDataError,
JsonRpcUserNotFoundError, JsonRpcProfileFailError, JsonRpcMobileFoundError)
from .base_google import googlesignin
from .user import add_member_count
from .user import save_user
from .user_group import save as save_groups from .user_group import save as save_groups
from .. import get_params, log from .user_login import (ChangePassword, change_password_validator,
regenerate_security_code, send_email_security_code)
from ..models import DBSession, UserService, Departemen from ..models import DBSession, UserService, Departemen
from ..models import (User, Partner, Group, UserGroup, PartnerDepartemen) from ..models import (User, Partner, Group, UserGroup, PartnerDepartemen)
from opensipkd.tools import create_now, get_settings
from opensipkd.tools.api import custom_error
from opensipkd.base.tools.api import (
auth_from_rpc, check_token_rpc, update_token)
#todo save_partner
# from ..views.partner import save as save_partner
def insert_user(request, values): _ = TranslationStringFactory('user')
q = DBSession.query(Group).filter(Group.group_name.ilike('web service'))
ws_group = q.first()
user = User()
user.email = values['email'].lower()
user.user_name = values['user_name'].lower()
user.password = values['password']
user.status = 1
DBSession.add(user)
DBSession.flush()
ug = UserGroup(user_id=user.id, group_id=ws_group.id)
DBSession.add(ug)
add_member_count(ws_group.id)
return user
def get_user(data): def get_user(data):
user = 'user_name' in data and User.get_by_identity(data['user_name']) or None user = 'user_name' in data and User.get_by_identity(
data['user_name']) or None
if not user: if not user:
user = 'email' in data and User.get_by_identity(data['email']) or None user = 'email' in data and User.get_by_identity(data['email']) or None
if not user:
log.info("Get User Rpc Not Found")
raise JsonRpcUserNotFoundError
return user return user
def get_user_token(row):
user = 'token' in row and User.get_by_token(row['token']).first()
return user
# def validasi_nik(nik):
# return partner.query().filter_by(kode=nik).first()
def validasi_email(value):
name, email = parseaddr(value)
if not email or email.find('@') < 0:
return
return True
def validasi_user(data, row=None):
user = User.get_by_identity(data['user_name'])
if (not row and user) or (row and user and row.id != user.id):
log.info("Validasi User Found")
raise JsonRpcUserFoundError
user = User.get_by_identity(data['email'])
if (not row and user) or (row and user and row.id != user.id):
log.info("Validasi Email Found")
raise JsonRpcEmailFoundError
def validasi_partner(data, row=None):
# Cek di partner
partner = Partner.query_email(data['email']).first()
if (not row and partner) or (row and partner and row.id != partner.id):
log.info("Validasi Email Found")
raise JsonRpcEmailFoundError
partner = Partner.query_kode(data['nik']).first()
if (not row and partner) or (row and partner and row.id != partner.id):
log.info("Validasi NIK Found")
raise JsonRpcNikFoundError
partner = Partner.query().filter_by(mobile=data['mobile']).first()
if (not row and partner) or (row and partner and row.id != partner.id):
log.info("Validasi Mobile Found")
raise JsonRpcMobileFoundError
def validasi_data(dat):
nik = ""
if 'nik' in dat:
nik = re.sub('\D', '', dat['nik'])
if len(nik) != 16:
log.info("Validasi NIK Error")
raise JsonRpcInvalidNikError
mobile = re.sub('\D', '', dat['mobile'])
if len(mobile) < 9:
log.info("Validasi Mobile Error")
raise JsonRpcInvalidMobileError
email = dat['email']
if not validasi_email(email):
log.info("Validasi Email")
raise JsonRpcInvalidEmailError
dat['nik'] = nik and nik or mobile
dat['mobile'] = mobile
dat['email'] = email
return dat
def register_user_(data, user, groups=None):
is_list = isinstance(data, list)
if is_list:
data_list = data
else:
data_list = [data]
result = []
for data in data_list:
if not ('user_name' in data and 'password' in data and 'email' in data
and 'nama' in data and 'mobile' in data):
raise JsonRpcInvalidDataError
data = validasi_data(data)
validasi_user(data)
data['status'] = 1
row = save_user(data, user=user)
if not row:
raise JsonRpcRegisterFailError
# proses ke tabel partner
kode = 'nik' in data and data['nik'] or ""
if not kode:
kode = 'kode' in data and data['kode'] or ""
if not kode:
kode = 'email' in data and data['email'] or ""
data['kode'] = kode
data['user_id'] = row.id
data['is_customer'] = 1
user = row if not user else user
validasi_partner(data)
partner = save_partner(data, user)
if not partner:
transaction.abort()
raise JsonRpcRegisterFailError
##Untuk SIMKEL##
settings = get_settings()
default_group = get_params("default_group")
if default_group:
groups = settings['default_group'].split(',')
for group in groups:
group_data = Group.query_group_name(group).first()
if not group_data:
raise custom_error(-1, "Group Not Found.")
data['group_id'] = group_data.id
data['user_id'] = row.id
save_groups(data, None)
if not groups:
raise Exception("Groups Kosong")
ret_groups = []
if groups:
for group in groups.split(','):
group_data = Group.query_group_name(group).first()
if not group_data:
print(group)
raise Exception("Groups Data Kosong")
if group_data:
data['group_id'] = group_data.id
data['user_id'] = row.id
row = save_groups(data, None)
ret_groups.append(dict(group_name=group))
del data['group_id']
# del data['user_id']
data['groups']=ret_groups
result.append(data)
if not is_list:
result = result[0]
return result
# url /rpc/user , permission='web-service'
@jsonrpc_method(method='register', endpoint='rpc-user')
def register_user(request, data, groups=''):
# Digunakan untuk registrasi user via aplikasi lain
# parameter user_name, password, email, nama, mobile, nik
user = auth_from_rpc(request)
result = register_user_(data, user, groups)
return dict(message="Sukses Register User", data=result)
# 3 , permission='web-service'
def login_(request, data): def login_(request, data):
is_list = type(data) is list user = get_user(data)
data = is_list and data[0] or data if not user:
row = get_user(data)
if not row:
if 'external' in data: if 'external' in data:
from .base_google import googlesignin from .base_google import googlesignin
row = googlesignin(request) user = googlesignin(request)
if not row: if not user:
result = dict(next="complete_user", result = dict(next="complete_user",
message="Silahkan Melakukan Registrasi") message="Silahkan Melakukan Registrasi")
raise JsonRpcInvalidLoginError(data=result) raise JsonRpcInvalidLoginError(data=result)
raise JsonRpcInvalidLoginError else:
raise JsonRpcInvalidLoginError
if not UserService.check_password(row, data['password']):
raise JsonRpcInvalidLoginError
row.last_login_date = create_now()
DBSession.add(row)
DBSession.flush()
partner = Partner.query().filter_by(user_id=row.id).first()
if not partner and row.id > 1:
raise JsonRpcInvalidDataError(message="Silahkan melengkapi Registrasi")
result = None
if row.id == 1:
is_pegawai = 1
else: else:
is_pegawai = partner and not partner.is_customer and not partner.is_vendor and 1 or 0 if not UserService.check_password(user, data['password']):
raise JsonRpcInvalidLoginError
##RETURNING GROUP## user.last_login_date = create_now()
DBSession.add(user)
DBSession.flush()
headers = remember(request, user.id)
request.headers.update(headers)
response = request.response
response.headers.update(headers)
groups = DBSession.query(Group). \ groups = DBSession.query(Group). \
join(UserGroup, UserGroup.group_id == Group.id). \ join(UserGroup, UserGroup.group_id == Group.id). \
filter(UserGroup.user_id == row.id).all() filter(UserGroup.user_id == user.id).all()
group_data = [] group_data = []
for group in groups: for group in groups:
group = group.to_dict() group = group.to_dict()
group_data.append(dict(group_name=group['group_name'])) group_data.append(dict(group_name=group['group_name']))
now = datetime.now().date() now = datetime.now()
partner_dep = Departemen.query() \ partner = Partner.query().filter_by(email=user.email).first()
.join(PartnerDepartemen, Departemen.id == PartnerDepartemen.departemen_id) \ departemen = None
.join(Partner, Partner.id == PartnerDepartemen.partner_id) \ if partner:
.filter(Partner.email == row.email, partner_dep = Departemen.query() \
PartnerDepartemen.mulai <= now, .join(PartnerDepartemen,
PartnerDepartemen.selesai >= now).first() Departemen.id == PartnerDepartemen.departemen_id) \
if partner_dep: .join(Partner, Partner.id == PartnerDepartemen.partner_id) \
departemen = dict(id=partner_dep.id, .filter(Partner.email == user.email,
kode=partner_dep.kode, PartnerDepartemen.mulai <= now,
nama=partner_dep.nama) PartnerDepartemen.selesai >= now).first()
else: if partner_dep:
departemen = None departemen = dict(id=partner_dep.id,
kode=partner_dep.kode,
result = dict(user_name=row.user_name, nama=partner_dep.nama)
token=row.security_code,
nik=partner and partner.kode or '', return dict(id=user.id,
nama=partner and partner.nama or '', user_name=user.user_name,
is_pegawai=is_pegawai, nik=partner and partner.kode or '',
group=group_data, nama=partner and partner.nama or '',
departemens=departemen) group=group_data,
result = is_list and [result] or result departemens=departemen)
return dict(data=result)
@jsonrpc_method(method='login', endpoint='rpc-user') @jsonrpc_method(method='login', endpoint='rpc-user')
def login(request, data): def login(request, data):
# Digunakan untuk login dari aplikasi lain """
# parameter user_name/email, user_password Digunakan untuk login pada aplikasi lain
ws_user = auth_from_rpc(request) :param request:
return login_(request, data) :param data:
{
user_name:
password:
device_id:
# , permission='web-service' }
def set_profile_(request, data): :return:{
"user_name": user_name,
"token": token,
"nik": nik,
"nama": nik,
"group": [group],
"departemens": departemen
}
"""
is_list = type(data) is list is_list = type(data) is list
data = is_list and data[0] or data data = is_list and data[0] or data
if not ('user_name' in data and 'password' in data and 'email' in data resp = login_(request, data)
and 'nama' in data and 'mobile' in data and 'nik' in data): resp["token"] = get_user_device(request, resp["id"]).token
raise JsonRpcInvalidDataError result = is_list and [resp] or resp
return result
data = validasi_data(data)
if 'external' in data:
user = googlesignin(request)
if not user:
raise JsonRpcInvalidLoginError
@jsonrpc_method(method='logout', endpoint='rpc-user', permission="view")
def logout(request, data):
"""
Digunakan untuk login pada aplikasi lain
:param request:
:param data:
{
}
:return:{
}
"""
# token_auth(request, logout=True)
headers = forget(request)
request.session.delete()
request.response.headers.update(headers)
return dict(data="")
def get_profile_(user):
partner = Partner.query().filter_by(email=user.email).first()
if not partner:
return dict(user_name=user.user_name,
nik="",
email="",
mobile="",
nama="", )
return dict(user_name=user.user_name,
nik=partner.kode,
email=partner.email,
mobile=partner.mobile,
nama=partner.nama, )
@jsonrpc_method(method='get-profile', endpoint='rpc-user', permission="view")
@jsonrpc_method(method='get_profile', endpoint='rpc-user', permission="view")
def get_profile(request, data):
"""
Digunakan untuk memperoleh profile user yang sedang login
parameter
@param request: Request
@param data: Dict(password=password)
@return:
"""
user = request.user
is_list = type(data) == list
data = is_list and data[0] or data
print(data)
if not user or not UserService.check_password(user, data['password']):
raise JsonRpcInvalidLoginError
resp = get_profile_(user)
resp = is_list and [resp] or resp
return resp
class EmailValidator(EmailValidatorBase):
def __call__(self, node, value):
def email_found_partner():
data = dict(email=email, uid=found.id)
ts = _(
'email-already-used',
default='Email ${email} already used by partner ID ${uid}',
mapping=data)
raise colander.Invalid(node, ts)
super().__call__(node, value)
email = value.lower()
q = DBSession.query(Partner).filter_by(email=email)
found = q.first()
if found and (not self.user or self.user.email != found.email):
email_found_partner()
@colander.deferred
def email_validator(node, kw):
return EmailValidator(kw['user'])
class PartnerSchema(NamaSchema):
email = colander.SchemaNode(
colander.String(),
validator=email_validator
)
mobile = colander.SchemaNode(
colander.String()
)
def form_validator(form, values):
exc = colander.Invalid(form, "")
user = form.request.user
if user:
values["update_uid"] = user.id
values["updated"] = datetime.now()
else: else:
user = get_user(data) values["create_uid"] = user.id
if not UserService.check_password(user, data['password']): values["created"] = datetime.now()
raise JsonRpcInvalidLoginError
# if not user or UserService.check_password(user, data['password']): values["is_customer"] = "is_customer" in values and values[
# raise JsonRpcInvalidLoginError "is_customer"] or 1
values["is_vendor"] = "is_vendor" in values and values["is_vendor"] or 0
mobile = values["mobile"]
partner = Partner.query().filter_by(mobile=mobile).first()
if partner:
if not user or user and user.email != partner.email:
exc["mobile"] = "No Handphone sudah ada yang menggunakan"
raise exc
validasi_user(data, user)
partner = Partner.query().filter_by(user_id=user.id).first()
validasi_partner(data, partner)
if 'new_password' in data: def set_profile_(request, data):
data['password'] = data['new_password'] schema = PartnerSchema(validator=form_validator)
schema = schema.bind(request=request, user=request.user)
schema.request = request
form = Form(schema)
data["kode"] = data["nik"]
controls = ((k, v) for k, v in data.items())
try:
controls = form.validate(controls)
except ValidationFailure as e:
print(e.error, type(e.error))
raise JsonRpcInvalidDataError(data=e.error.asdict())
values = dict(controls)
partner = Partner.query().filter_by(email=values["email"]).first()
if not partner:
partner = Partner()
partner.from_dict(values)
DBSession.add(partner)
DBSession.flush()
return values
row = save_user(data, user, user)
if not row:
raise JsonRpcProfileFailError
partner = save_partner(data, user, partner) @jsonrpc_method(method='set-profile', endpoint='rpc-user', permission="view")
if not partner: @jsonrpc_method(method='set_profile', endpoint='rpc-user', permission="view")
transaction.abort() def set_profile(request, data):
raise JsonRpcProfileFailError """
Digunakan untuk menyimpan profile
:param request:
:param data:Dict(
nik="",
email="",
mobile="",
nama="",
)
:return:
"""
is_list = type(data) is list
data = is_list and data[0] or data
user = request.user
if not UserService.check_password(user, data['password']):
raise JsonRpcInvalidLoginError
result = data old_email = user.email
result = is_list and [result] or result values = set_profile_(request, data)
return dict(message='Sukses Ubah', data=result) user.from_dict(values)
if old_email != data["email"]:
remain = regenerate_security_code(user)
send_email_security_code(
request, user, remain, 'Change email', 'change-email-body',
'change-email-body.tpl')
user.status = 0
headers = forget(request)
request.session.delete()
request.response.headers.update(headers)
return dict(message=f"Silahkan buka email {old_email}")
return dict(message="Sukses Ubah Profile")
@jsonrpc_method(method='set_profile', endpoint='rpc-user')
def set_profile(request, data): @jsonrpc_method(method='register', endpoint='rpc-user')
# Digunakan untuk menyimpan profile kepada aplikasi lain def register_user(request, data):
# parameter user_name / password """
return set_profile_(request, data) Digunakan untuk registrasi user dan profile
:param request:
:param data:Dict(
user_name="",
nik="",
email="",
mobile="",
nama="",
)
:return:
"""
is_list = type(data) is list
data = is_list and data[0] or data
values = set_profile_(request, data)
user = User()
user.from_dict(values)
DBSession.add(user)
DBSession.flush()
groups = data["groups"]
for g in groups:
d = Group.query_group_name(g).first()
data['group_id'] = d.id
data['user_id'] = user.id
save_groups(data, None)
remain = regenerate_security_code(user)
send_email_security_code(
request, 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=data)
return dict(message=ts)
def get_password_(request, data): def get_password_(request, data):
...@@ -340,35 +330,59 @@ def get_password_(request, data): ...@@ -340,35 +330,59 @@ def get_password_(request, data):
if not user: if not user:
raise JsonRpcUserNotFoundError raise JsonRpcUserNotFoundError
from opensipkd.base.views.user_login import (
regenerate_security_code, send_email_security_code)
remain = regenerate_security_code(user) remain = regenerate_security_code(user)
send_email_security_code( send_email_security_code(
request, user, remain, 'Reset password', 'reset-password-body', request, user, remain, 'Reset password', 'reset-password-body',
'reset-password-body.tpl') 'reset-password-body.tpl')
return dict(data=dict(message='Email reset password sudah terkirim ke %s' % identity)) return dict(data=dict(
message='Email reset password sudah terkirim ke %s' % identity))
@jsonrpc_method(method='get-password', endpoint='rpc-user')
@jsonrpc_method(method='get_password', endpoint='rpc-user') @jsonrpc_method(method='get_password', endpoint='rpc-user')
def get_password(request, data): def get_password(request, data):
auth_from_rpc(request)
return get_password_(request, data) return get_password_(request, data)
def set_password_(token, data): def set_password_(user, data):
user = check_token_rpc(token) schema = ChangePassword(validator=change_password_validator)
if not UserService.check_password(user, data["password"]): form = Form(schema)
raise JsonRpcInvalidLoginError items = ((k, v) for k, v in data.items())
try:
c = form.validate(items)
except ValidationFailure as e:
raise JsonRpcInvalidLogin(data=e.error.asdict())
UserService.set_password(user, c['new_password'])
DBSession.add(user)
DBSession.flush()
if "new_password" in data and data["new_password"]: if "new_password" in data and data["new_password"]:
UserService.set_password(User, data["new_password"]) UserService.set_password(User, data["new_password"])
result = dict(message="Sukses Ubah Password") result = dict(message="Sukses Ubah Password")
result.update(update_token(user))
return result return result
@jsonrpc_method(method='set_password', endpoint='rpc-user') @jsonrpc_method(method='set-password', endpoint='rpc-user', permission="view")
def set_password(request, token, data): @jsonrpc_method(method='set_password', endpoint='rpc-user', permission="view")
auth_from_rpc(request) def set_password(request, data):
return set_password_(token, data) """
Digunakan untuk mengubah password
:param request:
:param data: {
"password": old_password,
"new_password": new_password,
"retype_password": conf_password,
}
:return:
success: {"result": {}}
error: {"error": {}}
"""
user = request.user
is_list = type(data) is list
data = is_list and data[0] or data
resp = set_password_(user, data)
headers = forget(request)
request.session.delete()
request.response.headers.update(headers)
return resp
import logging import logging
import venusian from pyramid.httpexceptions import HTTPForbidden
from pyramid.httpexceptions import HTTPFound from pyramid.httpexceptions import HTTPNotFound
from pyramid.renderers import null_renderer
from pyramid.security import NO_PERMISSION_REQUIRED from pyramid.security import NO_PERMISSION_REQUIRED
from pyramid_rpc.jsonrpc import jsonrpc_method as json_rpc_base, MethodPredicate, BatchedRequestPredicate, \ from pyramid_rpc.jsonrpc import (JsonRpcError, JsonRpcMethodNotFound, JsonRpcParamsInvalid,
EndpointPredicate, jsonrpc_renderer, DEFAULT_RENDERER, add_jsonrpc_endpoint, add_jsonrpc_method, JsonRpcError, \ JsonRpcInternalError, make_error_response, MethodPredicate, BatchedRequestPredicate,
exception_view, JsonRpcRequestInvalid, parse_request_GET, parse_request_POST jsonrpc_renderer, add_jsonrpc_method,
DEFAULT_RENDERER,
from opensipkd.base.tools.api import auth_from_rpc batched_request_view, Endpoint, EndpointPredicate)
from opensipkd.base.views.user_login import get_login_headers from pyramid_rpc.mapper import ViewMapperArgsInvalid, MapplyViewMapper
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
def setup_request(endpoint, request):
""" Parse a JSON-RPC request body.""" class JsonRpcRequestForbidden(JsonRpcError):
if request.method == 'GET': code = -32604
parse_request_GET(request) message = 'request forbidden'
elif request.method == 'POST':
parse_request_POST(request)
class JsonRpcInvalidLogin(JsonRpcError):
code = -32605
message = "Invalid User/Password"
#
# class EndpointPredicate(BaseEndpointPredicate):
# def __call__(self, info, request):
# if self.val:
# # find the endpoint info
# key = info['route'].name
# endpoint = request.registry.jsonrpc_endpoints[key]
#
# # potentially setup either rpc v1 or v2 from the parsed body
# setup_request(endpoint, request)
#
# # update request with endpoint information
# request.rpc_endpoint = endpoint
#
# # Always return True so that even if it isn't a valid RPC it
# # will fall through to the notfound_view which will still
# # return a valid JSON-RPC response.
# return True
# def setup_request(endpoint, request):
# """ Parse a JSON-RPC request body."""
# if request.method == 'GET':
# parse_request_GET(request)
# elif request.method == 'POST':
# parse_request_POST(request)
# else:
# log.debug('unsupported request method "%s"', request.method)
# raise JsonRpcRequestInvalid
#
# if hasattr(request, 'batched_rpc_requests'):
# log.debug('handling batched rpc request')
# # the checks below will look at the subrequests
# return
#
# if request.rpc_version != '2.0':
# log.debug('id:%s invalid rpc version %s',
# request.rpc_id, request.rpc_version)
# raise JsonRpcRequestInvalid
#
# if request.rpc_method is None:
# log.debug('id:%s invalid rpc method', request.rpc_id)
# raise JsonRpcRequestInvalid
# env = request.environ
# if 'HTTP_TOKEN' in env:
# try:
# user_device = token_auth(request)
# user = user_device.user
# headers = remember(request, user.id)
# request.headers["Cookie"] = dict(headers)["Set-Cookie"]
# request.headers["token"]=user_device.token
# log.debug(request.headers["Cookie"])
# except JsonRpcInvalidLoginError as e:
# raise JsonRpcInvalidLogin
#
# elif ('HTTP_USERID' in env and 'HTTP_SIGNATURE' in env and
# 'HTTP_KEY' in env):
# try:
# user = rpc_auth(request)
# headers = remember(request, user.id)
# request.headers["Cookie"] = dict(headers)["Set-Cookie"]
# log.debug(request.headers["Cookie"])
# except JsonRpcInvalidLoginError as e:
# raise JsonRpcInvalidLogin
# log.debug('handling id:%s method:%s',
# request.rpc_id, request.rpc_method)
def exception_view(exc, request):
rpc_id = getattr(request, 'rpc_id', None)
if isinstance(exc, JsonRpcError):
fault = exc
log.debug('json-rpc error rpc_id:%s "%s"',
rpc_id, exc.message)
elif isinstance(exc, HTTPNotFound):
fault = JsonRpcMethodNotFound()
log.debug('json-rpc method not found rpc_id:%s "%s"',
rpc_id, request.rpc_method)
elif isinstance(exc, HTTPForbidden):
fault = JsonRpcRequestForbidden()
log.debug('json-rpc method forbidden rpc_id:%s "%s"',
rpc_id, request.rpc_method)
elif isinstance(exc, ViewMapperArgsInvalid):
fault = JsonRpcParamsInvalid()
log.debug('json-rpc invalid method params')
else: else:
log.debug('unsupported request method "%s"', request.method) fault = JsonRpcInternalError()
raise JsonRpcRequestInvalid log.exception('json-rpc exception rpc_id:%s "%s"', rpc_id, exc)
if hasattr(request, 'batched_rpc_requests'): return make_error_response(request, fault, rpc_id)
log.debug('handling batched rpc request')
# the checks below will look at the subrequests
return def add_jsonrpc_endpoint(config, name, *args, **kw):
"""Add an endpoint for handling JSON-RPC.
if request.rpc_version != '2.0':
log.debug('id:%s invalid rpc version %s', ``name``
request.rpc_id, request.rpc_version)
raise JsonRpcRequestInvalid The name of the endpoint.
if request.rpc_method is None: ``default_mapper``
log.debug('id:%s invalid rpc method', request.rpc_id)
raise JsonRpcRequestInvalid A default view mapper that will be passed as the ``mapper``
argument to each of the endpoint's methods.
log.debug('handling id:%s method:%s',
request.rpc_id, request.rpc_method) ``default_renderer``
class MethodPredicate(object): A default renderer that will be passed as the ``renderer``
def __init__(self, val, config): argument to each of the endpoint's methods. This should be the
self.method = val string name of the renderer, registered via
:meth:`pyramid.config.Configurator.add_renderer`.
def text(self):
return 'jsonrpc method = %s' % self.method A JSON-RPC method also accepts all of the arguments supplied to
:meth:`pyramid.config.Configurator.add_route`.
phash = text
"""
def __call__(self, context, request): default_mapper = kw.pop('default_mapper', MapplyViewMapper)
user = auth_from_rpc(request) default_renderer = kw.pop('default_renderer', DEFAULT_RENDERER)
headers = get_login_headers(request, user)
response = HTTPFound(location=request.route_url('home'), headers=headers) endpoint = Endpoint(
# response = request.response name,
request.response.set_cookie('userid', value=str(user.id), max_age=31536000) # max_age = year default_mapper=default_mapper,
return getattr(request, 'rpc_method', None) == self.method default_renderer=default_renderer,
)
config.registry.jsonrpc_endpoints[name] = endpoint
kw['jsonrpc_endpoint'] = True
config.add_route(name, *args, **kw)
kw = {}
kw['jsonrpc_batched'] = True
kw['renderer'] = null_renderer
config.add_view(batched_request_view, route_name=name,
permission=NO_PERMISSION_REQUIRED, **kw)
config.add_view(exception_view, route_name=name, context=Exception,
permission=NO_PERMISSION_REQUIRED)
def includeme(config): def includeme(config):
""" Set up standard configurator registrations. Use via: """ Set up standard configurator registrations. Use via:
......
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!