Commit 278b71c4 by taufikyu

Merge branch 'latest' of https://git.opensipkd.com/aa.gusti/opensipkd-base into latest

2 parents bfe5ab1f 32befca7
...@@ -250,7 +250,7 @@ def is_devel(request): ...@@ -250,7 +250,7 @@ def is_devel(request):
def google_signin_client_ids(request): def google_signin_client_ids(request):
ids = get_params('google-signin-client-id', '') ids = get_params('google-signin-client-id', '')
if ids: if ids:
return ids.split(',') return ids.split('\n')
else: else:
return [] return []
......
import logging
from google.auth.transport import requests from google.auth.transport import requests
from google.oauth2 import id_token from google.oauth2 import id_token
from opensipkd.base import get_params from opensipkd.base import get_params
...@@ -7,6 +9,8 @@ from opensipkd.models import User ...@@ -7,6 +9,8 @@ from opensipkd.models import User
from opensipkd.tools import get_settings from opensipkd.tools import get_settings
import json import json
_logging = logging.getLogger(__name__)
def validate_user(request, idinfo): def validate_user(request, idinfo):
""" """
...@@ -49,7 +53,7 @@ def google_oauth2(request): ...@@ -49,7 +53,7 @@ def google_oauth2(request):
@view_config(route_name='googlesignin', renderer='json') @view_config(route_name='googlesignin', renderer='json')
def googlesignin(request): def googlesignin(request, data=None):
# (Receive token by HTTPS POST) # (Receive token by HTTPS POST)
# ... # ...
CLIENT_IDS = request.google_signin_client_ids CLIENT_IDS = request.google_signin_client_ids
...@@ -59,15 +63,30 @@ def googlesignin(request): ...@@ -59,15 +63,30 @@ def googlesignin(request):
# idinfo = id_token.verify_oauth2_token(token, requests.Request(), CLIENT_ID) # idinfo = id_token.verify_oauth2_token(token, requests.Request(), CLIENT_ID)
# Or, if multiple clients access the backend server: # Or, if multiple clients access the backend server:
gtoken = json.loads(request.params['id_token']) id_token = "id_token" in request.params and request.params[
'id_token'] or ""
gtoken = None
if id_token:
gtoken = json.loads(id_token)
else:
if data and "id_token" in data:
gtoken = data["id_token"]
_logging.debug(gtoken)
if not gtoken:
raise Exception("Gtoken not found")
# idinfo = id_token.verify_oauth2_token(gtoken, requests.Request()) # idinfo = id_token.verify_oauth2_token(gtoken, requests.Request())
# test # test
import jwt import jwt
idinfo = jwt.decode(gtoken["credential"], options={"verify_signature": False}) # KEY, algorithms=["RS256"]) # idinfo = jwt.decode(gtoken["credential"], options={
"verify_signature": False}) # KEY, algorithms=["RS256"]) #
_logging.debug(CLIENT_IDS)
_logging.debug(idinfo)
if idinfo['aud'] not in CLIENT_IDS or idinfo['azp'] not in CLIENT_IDS: if idinfo['aud'] not in CLIENT_IDS or idinfo['azp'] not in CLIENT_IDS:
raise ValueError('Could not verify audience.') raise ValueError('Could not verify audience.')
if idinfo['iss'] not in ['accounts.google.com', 'https://accounts.google.com']: if idinfo['iss'] not in ['accounts.google.com',
'https://accounts.google.com']:
raise ValueError('Wrong issuer.') raise ValueError('Wrong issuer.')
return idinfo return idinfo
...@@ -383,12 +383,26 @@ class BaseView(object): ...@@ -383,12 +383,26 @@ class BaseView(object):
if self.req.POST: if self.req.POST:
if 'save' in self.req.POST: if 'save' in self.req.POST:
controls = self.req.POST.items() controls = self.req.POST.items()
log.debug(self.req.POST.items())
log.debug(dict(self.req.POST.items()))
try: try:
c = form.validate(controls) c = form.validate(controls)
except ValidationFailure as e: except ValidationFailure as e:
# value = self.validation_failure(e.cstruct) # value = self.validation_failure(e.cstruct)
# value.update(self.before_add()) # value.update(self.before_add())
# form.render(appstruct=value) # form.render(appstruct=value)
# log.debug(e.cstruct)
# log.debug(e.field)
# efield = e.field
for f in e.field.children:
if isinstance(f.typ, colander.Date):
e.cstruct[f.name] = date_from_str(e.cstruct[f.name])
# for k, v in e.cstruct.items():
# log.debug(hasattr(e.field, k))
# if isinstance(f, colander.Date):
# e.cstruct[f] = date_from_str(e.cstruct[f])
return dict(form=form.render(e.cstruct), return dict(form=form.render(e.cstruct),
table=table and table.render() or None, table=table and table.render() or None,
scripts=self.form_scripts, css=resources["css"], scripts=self.form_scripts, css=resources["css"],
...@@ -409,6 +423,9 @@ class BaseView(object): ...@@ -409,6 +423,9 @@ class BaseView(object):
js=resources["js"]) js=resources["js"])
def save(self, values, user, row=None): def save(self, values, user, row=None):
log.debug("Save")
log.debug(values)
values.pop("id", None)
self.ses["old_email"] = user and user.email or None self.ses["old_email"] = user and user.email or None
if not row: if not row:
row = self.table() row = self.table()
...@@ -470,7 +487,13 @@ class BaseView(object): ...@@ -470,7 +487,13 @@ class BaseView(object):
resources = form.get_widget_resources() resources = form.get_widget_resources()
if request.POST: if request.POST:
if 'save' in request.POST: if 'save' in request.POST:
log.debug("Save Edit")
log.debug(dict(request.POST.items()))
log.debug(request.POST)
controls = request.POST.items() controls = request.POST.items()
log.debug(controls)
# log.debug(dict(controls))
# log.debug(list(controls))
try: try:
controls = form.validate(controls) controls = form.validate(controls)
except ValidationFailure as e: except ValidationFailure as e:
......
...@@ -119,8 +119,7 @@ class ViewDati2(BaseView): ...@@ -119,8 +119,7 @@ class ViewDati2(BaseView):
def list_join(self, query): def list_join(self, query):
return query.join(ResProvinsi, ResProvinsi.id == ResDati2.provinsi_id) return query.join(ResProvinsi, ResProvinsi.id == ResDati2.provinsi_id)
@view_config(route_name='dati2-act', renderer='json', @view_config(route_name='dati2-act', renderer='json')
permission='view')
def view_act(self): def view_act(self):
return super().view_act() return super().view_act()
......
...@@ -163,11 +163,16 @@ class ViewMenus(BaseView): ...@@ -163,11 +163,16 @@ class ViewMenus(BaseView):
self.update_children(child.children) self.update_children(child.children)
def save_request(self, values, row=None): # save(self, row, values): def save_request(self, values, row=None): # save(self, row, values):
for k, v in values.items(): # for k, v in values.items():
if not v: # if not v:
setattr(row, k, None) # setattr(row, k, None)
row = super().save_request(values, row) # row = super().save_request(values, row)
return row for k, v in self.req.GET.items():
if k not in values:
if v:
values[k] = v
values["status"] = "status" in values and values["status"] or 0
return self.save(values, self.req.user, row)
@view_config(route_name='menu', @view_config(route_name='menu',
renderer='templates/table.pt', renderer='templates/table.pt',
......
...@@ -26,6 +26,8 @@ Link dalam module registrasi: ...@@ -26,6 +26,8 @@ Link dalam module registrasi:
4. Form edit registrasi http://server/register/{uid}/edit 4. Form edit registrasi http://server/register/{uid}/edit
5. Form Upload template 5. Form Upload template
""" """
import base64
import logging
from datetime import datetime from datetime import datetime
import colander import colander
...@@ -48,6 +50,8 @@ from ..views import BaseView ...@@ -48,6 +50,8 @@ from ..views import BaseView
_ = TranslationStringFactory('user') _ = TranslationStringFactory('user')
_logging = logging.getLogger(__name__)
class AddSchema(colander.Schema): class AddSchema(colander.Schema):
nama = colander.SchemaNode( nama = colander.SchemaNode(
...@@ -173,6 +177,7 @@ class Registrasi(BaseView): ...@@ -173,6 +177,7 @@ class Registrasi(BaseView):
3. Cek kode pada Partner jika ada dan Partner.id beda reject 3. Cek kode pada Partner jika ada dan Partner.id beda reject
4. Cek mobile pada Partner jika ada dan Users.id beda reject 4. Cek mobile pada Partner jika ada dan Users.id beda reject
""" """
_logging.debug(value)
form_exc = colander.Invalid(form, '') form_exc = colander.Invalid(form, '')
request = form.request request = form.request
session = request.session session = request.session
...@@ -218,7 +223,7 @@ class Registrasi(BaseView): ...@@ -218,7 +223,7 @@ class Registrasi(BaseView):
err_captcha() err_captcha()
user = request.user user = request.user
if not "email" in value and "id_info" in session: if "email" not in value and "id_info" in session:
value["email"] = session["id_info"]["email"] value["email"] = session["id_info"]["email"]
if not user and ( if not user and (
...@@ -274,6 +279,16 @@ class Registrasi(BaseView): ...@@ -274,6 +279,16 @@ class Registrasi(BaseView):
if not user or not UserService.check_password( if not user or not UserService.check_password(
user, value['password']): user, value['password']):
err_login() err_login()
if "idcard" in value and value["idcard"]:
idcard = value["idcard"]
path = get_id_card_folder()
if "fp" in idcard and idcard["fp"] and idcard["fp"] != b'':
_logging.debug(idcard["fp"])
upload = Upload(path)
value["idcard"] = upload.save_fp(idcard)
else:
value.pop("idcard")
def before_add(self): def before_add(self):
result = {} result = {}
...@@ -328,7 +343,8 @@ class Registrasi(BaseView): ...@@ -328,7 +343,8 @@ class Registrasi(BaseView):
if d["idcard"]: if d["idcard"]:
filename = d["idcard"] filename = d["idcard"]
preview_url = "/".join( preview_url = "/".join(
[self.req.static_url(get_id_card_folder('/')), filename]) [self.req.static_url(get_id_card_folder('/')),
filename])
d["idcard"] = {"uid": filename.split(".")[0], d["idcard"] = {"uid": filename.split(".")[0],
"filename": filename, "filename": filename,
"preview_url": preview_url "preview_url": preview_url
...@@ -360,13 +376,6 @@ class Registrasi(BaseView): ...@@ -360,13 +376,6 @@ class Registrasi(BaseView):
if not "email" in values or not values["email"]: if not "email" in values or not values["email"]:
values["email"] = self.req.user and self.req.user.email or "" values["email"] = self.req.user and self.req.user.email or ""
if "idcard" in values and values["idcard"]:
if self.req.POST['upload'] != b'':
path = get_id_card_folder()
upload = Upload(path)
values["idcard"] = upload.save(self.req, 'upload')
else:
values.pop("idcard")
if not row: if not row:
values["is_vendor"] = 0 values["is_vendor"] = 0
values["is_customer"] = 1 values["is_customer"] = 1
......
...@@ -20,6 +20,7 @@ Perubahan Mendasar dari fungsi login adalah: ...@@ -20,6 +20,7 @@ Perubahan Mendasar dari fungsi login adalah:
result object dari fungsi tersebut harus berupa class User() result object dari fungsi tersebut harus berupa class User()
""" """
import os import os
import re
from datetime import timedelta, datetime from datetime import timedelta, datetime
from importlib import import_module from importlib import import_module
...@@ -87,14 +88,78 @@ class LoginUser(object): ...@@ -87,14 +88,78 @@ class LoginUser(object):
self.message = "Login Gagal" self.message = "Login Gagal"
set_user_log(self.message, self.request, log, values["username"]) set_user_log(self.message, self.request, log, values["username"])
return return
# generate security_code dan simpan dalam session # generate security_code dan simpan dalam session
regenerate_security_code(self.user, 0.03) # berlaku selama 1.8 menit regenerate_security_code(self.user, 0.03) # berlaku selama 1.8 menit
# dicek pada module security get_user # dicek pada module security get_user
self.request.session["token"]=self.user.security_code self.request.session["token"] = self.user.security_code
return True return True
class Oauth2ParseExc(Exception):
"""Error parsing"""
class Oauth2UserExc(Exception):
"""Error User Found"""
def oauth2_login(request, params=None):
provider_name = params and params["provider_name"] \
or request.params["provider_name"]
if provider_name == "google":
from .base_google import googlesignin
try:
id_info = googlesignin(request, params)
except Exception as e:
raise Oauth2ParseExc(str(e))
request.session["id_info"] = id_info
else:
id_info = None
iss = id_info and re.sub(r'https?://', '', id_info['iss']) or None
user = id_info and ExternalIdentityService. \
user_by_external_id_and_provider(id_info['sub'], iss)
log.debug("Users : %s", user)
log.debug("IdInfo : %s", id_info)
if id_info and not user:
values = {'email': id_info['email'],
"user_name": id_info["email"],
"status": 1,
"registered_date": datetime.now()}
user = User.get_by_identity(values.get("email"))
partner = Partner.query_email(values.get("email")).first()
log.debug("User : %s", user)
log.debug("Partner : %s", partner)
if user or partner:
raise Oauth2UserExc("Email sudah terdaftar silahkan login standard")
user = User()
user.from_dict(values)
DBSession.add(user)
DBSession.flush()
DBSession.refresh(user)
values = {'external_id': id_info['sub'],
'external_user_name': id_info["name"],
'external_email': id_info["email"],
'provider_name': iss,
"local_user_id": user.id,
"status": 1}
external = ExternalIdentity()
external.from_dict(values)
DBSession.add(external)
DBSession.flush()
if user and user.status != 1:
raise Oauth2UserExc(
"User anda masih menunggu verifikasi atau lagi di blokir")
# # todo: what is this????
# # values['access_token']
# # values['alt_token']
# # values['token_secret']
return user
class ViewLogin(BaseView): class ViewLogin(BaseView):
@view_config(route_name='login', renderer='templates/form.pt') @view_config(route_name='login', renderer='templates/form.pt')
def view_login(self): def view_login(self):
...@@ -162,74 +227,24 @@ class ViewLogin(BaseView): ...@@ -162,74 +227,24 @@ class ViewLogin(BaseView):
elif "provider_name" in request.params and \ elif "provider_name" in request.params and \
request.params["provider_name"]: request.params["provider_name"]:
provider_name = request.params["provider_name"] try:
if provider_name == "google": user = oauth2_login(request)
from .base_google import googlesignin except Oauth2ParseExc as e:
try: login = ""
id_info = googlesignin(request) request.session.flash(str(e), "error")
except Exception as e: return render_to_response(
login = "" login_tpl, dict(
request.session.flash(str(e), "error") form=form.render(),
return render_to_response( message=message,
login_tpl, dict( url=request.route_url('login'),
form=form.render(), next_url=next_url,
message=message, login=login, ),
url=request.route_url('login'), request=request)
next_url=next_url, except Oauth2UserExc as e:
login=login, ), request.session.flash(str(e), 'error')
request=request) return HTTPFound(location=request.route_url('login'))
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'])
log.debug("Users : %s", user)
log.debug("IdInfo : %s", id_info)
if id_info and not user:
# Proses Register user
# Cek Data di user dan partner
# Jika sudah ada user login klasik pake user password
# Simpan ke table user dan external identity
values = {'email': id_info['email'],
"user_name": id_info["email"],
"status": 1,
"registered_date": datetime.now()}
user = User.get_by_identity(values.get("email"))
partner = Partner.query_email(values.get("email")).first()
log.debug("User : %s", user)
log.debug("Partner : %s", partner)
if user or partner:
request.session.flash(
"Email sudah terdaftar silahkan login standard",
'error')
return HTTPFound(location=request.route_url('login'))
user = User()
user.from_dict(values)
DBSession.add(user)
DBSession.flush()
DBSession.refresh(user)
values = {'external_id': id_info['sub'],
'external_user_name': id_info["name"],
'external_email': id_info["email"],
'provider_name': id_info["iss"],
"local_user_id": user.id,
"status": 1}
external = ExternalIdentity()
external.from_dict(values)
DBSession.add(external)
DBSession.flush()
# # todo: what is this????
# # values['access_token']
# # values['alt_token']
# # values['token_secret']
if user and user.status == 1: if user and user.status == 1:
return redirect_login(request, user) return redirect_login(request, user)
else:
message = "User anda masih menunggu verifikasi atau lagi di blokir"
request.session.flash(message, "error")
login = "" login = ""
if login_tpl == 'templates/login.pt': if login_tpl == 'templates/login.pt':
......
import json import json
import logging
from deform.widget import ( from deform.widget import (
SchemaType, SchemaType,
...@@ -56,6 +57,7 @@ class DateInputWidget(DeformDateInputWidget): ...@@ -56,6 +57,7 @@ class DateInputWidget(DeformDateInputWidget):
return field.renderer(template, **values) return field.renderer(template, **values)
def deserialize(self, field, pstruct): def deserialize(self, field, pstruct):
logging.debug(f"widget: {field} {pstruct}")
if pstruct in ("", null): if pstruct in ("", null):
return null return null
try: try:
......
<tal:block tal:define="oid oid|field.oid; <tal:block tal:define="oid oid|field.oid;
css_class css_class|field.widget.css_class; css_class css_class|field.widget.css_class;
style style|field.widget.style;"> style style|field.widget.style;">
${field.start_mapping()} ${field.start_mapping()}
<img tal:define="preview_url cstruct.get('preview_url');
filename cstruct.get('filename')"
tal:condition="preview_url" src="${structure: preview_url}"
></img>
<input type="file" name="upload" id="${oid}" <input type="file" name="upload" id="${oid}"
tal:attributes="style style; tal:attributes="style style;
accept accept|field.widget.accept; accept accept|field.widget.accept;
...@@ -10,11 +14,6 @@ ${field.start_mapping()} ...@@ -10,11 +14,6 @@ ${field.start_mapping()}
<input tal:define="uid cstruct.get('uid')" <input tal:define="uid cstruct.get('uid')"
tal:condition="uid" tal:condition="uid"
type="hidden" name="uid" value="${uid}"/> type="hidden" name="uid" value="${uid}"/>
<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()} ${field.end_mapping()}
<script type="text/javascript"> <script type="text/javascript">
deform.addCallback('${oid}', function (oid) { deform.addCallback('${oid}', function (oid) {
......
...@@ -18,7 +18,7 @@ ...@@ -18,7 +18,7 @@
data data|field.data; data data|field.data;
allow_edit allow_edit|field.allow_edit; allow_edit allow_edit|field.allow_edit;
allow_delete allow_delete|field.allow_delete; allow_delete allow_delete|field.allow_delete;
allow_view allow_delete|field.allow_view; allow_view allow_view|field.allow_view;
" "
tal:attributes="style style; class css_class; attributes|field.widget.attributes|{};" tal:attributes="style style; class css_class; attributes|field.widget.attributes|{};"
i18n:domain="detable" i18n:domain="detable"
......
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!