Commit ca297443 by Owo Sugiana

Kali pertama

0 parents
dist
*egg-info
*.pyc
0.2 31-1-2019
-------------
- Penambahan field users.api_key.
- Pembersihan file yang tak perlu.
0.1.1 17-12-2018
----------------
- Form edit user bisa ubah password karena user non-manusia (host to host)
tidak punya email.
- .gitignore ditambah .DS_Store.
0.1 12-12-2018
--------------
- get_login_headers() menyimpan user.id pada cookie ketimbang user.user_email.
Akhirnya ini berdampak pada group_finder().
- RootFactory yang lebih efisien yaitu cukup berisi daftar hak akses, tidak
perlu melibatkan request.
- groups.py kini menyertakan hak akses dengan memanfaatkan tabel
groups_permissions bawaan ziggurat. Sebagai pendukung dibuatlah tabel
permissions yang berisi daftar hak akses sebagaimana yang tertera pada
function argument permission di setiap view function.
- Hak akses yang lebih ringkas dimana user.py dan groups.py menggunakan
satu hak akses saja yang bernama user-edit yang bermakna bisa SELECT, INSERT,
UPDATE, dan DELETE tabel users dan tabel groups. Jika nanti ada kebutuhan
grup yang hanya bisa SELECT maka bisa dibuat hak akses bernama user-view.
- initializedb.py saat INSERT data kini menggunakan format csv saja
dengan menggunakan dua fungsi:
- restore_csv() yang akan INSERT data hanya jika tabelnya masih kosong. Ini
cocok untuk tabel users.
- append_csv() yang akan INSERT data jika key pada tabel tidak ditemukan.
- Jika field pada csv merupakan foreign key maka nama field ditulis dengan
susunan nama-field-tabel-csv/nama-tabel-foreign.nama-field-foreign, contoh:
pemda_id/va_pemda.kode.
- Tabel user_ws diganti dengan field users.api_key.
- Admin bisa membuatkan API Key saat membuat user baru atau saat sedang edit.
- User bisa membuat ulang API Key jika memang terisi.
- Ada prosedur lupa password.
0.0.1 21-10-2017
----------------
- Penambahan Field type pada route default 0
- alter table routes add type not null default 0
- Field ini digunakan untuk menentukan jenis-renderer
- 0 Route Standar
- 1 Route JSON_RPC
0.0 24-9-2017 aa.gusti
----------------------
- Penambahan tabel parameters
0.0
---
- Initial version
include *.txt *.rst
recursive-include opensipkd *.py *.ico *.png *.css *.gif *.jpg *.pt *.txt *.js *.html
Pustaka Utama Aplikasi openSIPKD
================================
Ini berisi class dan fungsi yang dibutuhkan untuk membuat aplikasi web. Web
framework menggunakan Pyramid dan manajemen user menggunakan Ziggurat
Foundations.
File mode changed
from sqlalchemy.orm import (
sessionmaker,
scoped_session,
)
from sqlalchemy.ext.declarative import declarative_base
from zope.sqlalchemy import ZopeTransactionExtension
ZTE = ZopeTransactionExtension()
DBSession = scoped_session(sessionmaker(extension=ZTE))
Base = declarative_base()
class CommonModel(object):
def to_dict(self):
values = {}
for column in self.__table__.columns:
values[column.name] = getattr(self, column.name)
return values
def to_dict_without_none(self):
values = {}
for column in self.__table__.columns:
val = getattr(self, column.name)
if val is not None:
values[column.name] = val
return values
from pyramid.security import (
Allow,
Authenticated,
ALL_PERMISSIONS,
)
from sqlalchemy import (
Column,
String,
PrimaryKeyConstraint,
)
import ziggurat_foundations.models
from ziggurat_foundations.models.base import BaseModel
from ziggurat_foundations.models.external_identity import ExternalIdentityMixin
from ziggurat_foundations.models.group import GroupMixin
from ziggurat_foundations.models.group_permission import GroupPermissionMixin
from ziggurat_foundations.models.group_resource_permission import GroupResourcePermissionMixin
from ziggurat_foundations.models.resource import ResourceMixin
from ziggurat_foundations.models.user import UserMixin
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 import ziggurat_model_init
from . import (
Base,
DBSession,
CommonModel,
)
# this is needed for scoped session approach like in pylons 1.0
ziggurat_foundations.models.DBSession = DBSession
# optional for folks who pass request.db to model methods
# Base is sqlalchemy's Base = declarative_base() from your project
class Group(GroupMixin, Base, CommonModel):
pass
class GroupPermission(GroupPermissionMixin, Base):
pass
class UserGroup(UserGroupMixin, Base):
pass
class GroupResourcePermission(GroupResourcePermissionMixin, Base):
__table_args__ = (
PrimaryKeyConstraint(
"group_id",
"resource_id",
"perm_name"),)
class Resource(ResourceMixin, Base):
# ... your own properties....
# example implementation of ACLS for pyramid application
@property
def __acl__(self):
acls = []
if self.owner_user_id:
acls.extend([(Allow, self.owner_user_id, ALL_PERMISSIONS,), ])
if self.owner_group_id:
acls.extend([(Allow, "group:%s" % self.owner_group_id,
ALL_PERMISSIONS,), ])
return acls
class UserPermission(UserPermissionMixin, Base):
pass
class UserResourcePermission(UserResourcePermissionMixin, Base):
pass
class User(UserMixin, Base, CommonModel):
api_key = Column(String(256))
class ExternalIdentity(ExternalIdentityMixin, Base):
pass
# you can define multiple resource derived models to build a complex
# application like CMS, forum or other permission based solution
#class Entry(Resource):
# """
# Resource of `entry` type
# """
# __tablename__ = 'entries'
# __mapper_args__ = {'polymorphic_identity': 'entry'}
# resource_id = sa.Column(sa.Integer(),
# sa.ForeignKey('resources.resource_id',
# onupdate='CASCADE',
# ondelete='CASCADE', ),
# primary_key=True, )
# ... your own properties....
# some_property = sa.Column(sa.UnicodeText())
class RootFactory:
def __init__(self, request):
self.__acl__ = [
(Allow, Authenticated, 'view'),
(Allow, 'group:1', ALL_PERMISSIONS),
]
for gp in DBSession.query(GroupPermission):
acl_name = 'group:{}'.format(gp.group_id)
self.__acl__.append((Allow, acl_name, gp.perm_name))
#ziggurat_model_init(User, Group, UserGroup, GroupPermission, passwordmanager=None)
ziggurat_model_init(User, Group, UserGroup, GroupPermission, UserPermission,
UserResourcePermission, GroupResourcePermission, Resource,
ExternalIdentity, passwordmanager=None)
from ziggurat_foundations.models.services.user import UserService
from opensipkd.jsonrpc.exc import JsonRpcInvalidLogin
from opensipkd.jsonrpc.auth import Auth as BaseAuth
class Auth(BaseAuth):
def __init__(self, request):
BaseAuth.__init__(self, request.environ)
self.validate_signature()
def validate_signature(self):
user = UserService.get(self.env['HTTP_USERID'])
if not (user and user.api_key):
raise JsonRpcInvalidLogin()
BaseAuth.validate_signature(self, user.api_key)
return user
def generate_api_key():
return UserService.generate_random_string(64)
from .models import DBSession
from .models.ziggurat import (
User,
UserGroup,
)
def group_finder(login, request):
q = DBSession.query(User).filter_by(id=login)
u = q.first()
if not u or not u.status:
return # None means logout
r = []
q = DBSession.query(UserGroup).filter_by(user_id=u.id)
for ug in q:
acl_name = 'group:{gid}'.format(gid=ug.group_id)
r.append(acl_name)
return r
def get_user(request):
uid = request.authenticated_userid
if uid:
q = DBSession.query(User).filter_by(id=uid)
return q.first()
# items = request.POST.items()
def to_dict(items):
d = dict()
values = None
for item in items:
print(item)
key, value = item
if key == '__start__':
fieldname = value
values = []
elif key == '__end__':
d[fieldname] = values
values = None
elif isinstance(values, list):
values.append(value)
else:
d[key] = value
return d
import csv
class Restore:
def __init__(self, db_session, table, filename):
self.db_session = db_session
self.table = table
self.filename = filename
def open_file(self):
return open(self.filename)
def run(self):
q = self.db_session.query(self.table)
if q.first():
return
with self.open_file() as f:
reader = csv.DictReader(f)
for cf in reader:
row = self.table()
for fieldname in cf:
val = cf[fieldname]
if not val:
continue
setattr(row, fieldname, val)
self.db_session.add(row)
return True
class Append(Restore):
def __init__(self, db_session, table, filename, keys):
Restore.__init__(self, db_session, table, filename)
self.keys = keys
self.run()
def run(self):
with self.open_file() as f:
reader = csv.DictReader(f)
filter_ = dict()
for cf in reader:
for key in self.keys:
filter_[key] = cf[key]
q = self.db_session.query(self.table).filter_by(**filter_)
found = q.first()
if found:
continue
row = self.table()
for fieldname in cf:
val = cf[fieldname]
if not val:
continue
setattr(row, fieldname, val)
self.db_session.add(row)
from random import choice
from string import digits
def get_random_number(width):
return [''.join(choice(digits) for _ in range(width))]
from pyramid.threadlocal import get_current_registry
from pyramid.events import (
subscriber,
BeforeRender,
)
from pyramid.i18n import default_locale_negotiator
LOCALE_NAMES = {
'en': 'English',
'id': 'Indonesia',
}
LOCALE_IDS = list(LOCALE_NAMES.keys())
def get_settings():
return get_current_registry().settings
def get_locale_should_be(request):
if 'HTTP_ACCEPT_LANGUAGE' not in request.environ:
return 'id'
# id-ID,id;q=0.9,en-US;q=0.8,en;q=0.7
vals = request.environ['HTTP_ACCEPT_LANGUAGE'].split(',')
for val in vals:
for locale_id in LOCALE_IDS:
if val.find(locale_id) == 0:
return locale_id
def get_locale_name(request):
return default_locale_negotiator(request) or \
get_locale_should_be(request)
def get_locale_title(name):
if name in LOCALE_NAMES:
return LOCALE_NAMES[name]
return name
def get_locale_title_(request):
name = get_locale_name(request)
return get_locale_title(name)
@subscriber(BeforeRender)
def add_global(event):
event['locale_name'] = get_locale_title_
event['locale_should_be'] = get_locale_should_be
import calendar
from datetime import (
date,
datetime,
)
import pytz
from .this_framework import get_settings
def get_timezone():
settings = get_settings()
return pytz.timezone(settings['timezone'])
def create_datetime(year, month, day, hour=0, minute=7, second=0,
microsecond=0):
tz = get_timezone()
return datetime(year, month, day, hour, minute, second,
microsecond, tzinfo=tz)
def create_date(year, month, day):
return create_datetime(year, month, day)
def as_timezone(tz_date):
localtz = get_timezone()
if not tz_date.tzinfo:
tz_date = create_datetime(tz_date.year, tz_date.month, tz_date.day,
tz_date.hour, tz_date.minute, tz_date.second,
tz_date.microsecond)
return tz_date.astimezone(localtz)
def create_now():
tz = get_timezone()
return datetime.now(tz)
def date_from_str(value):
separator = None
value = value.split()[0] # dd-mm-yyyy HH:MM:SS
for s in ['-', '/']:
if value.find(s) > -1:
separator = s
break
if separator:
t = map(lambda x: int(x), value.split(separator))
y, m, d = t[2], t[1], t[0]
if d > 999: # yyyy-mm-dd
y, d = d, y
else:
y, m, d = int(value[:4]), int(value[4:6]), int(value[6:])
return date(y, m, d)
def dmy(tgl):
return tgl.strftime('%d-%m-%Y')
def dmyhms(t):
return t.strftime('%d-%m-%Y %H:%M:%S')
def next_month(year, month):
if month == 12:
month = 1
year += 1
else:
month += 1
return year, month
def best_date(year, month, day):
try:
return date(year, month, day)
except ValueError:
last_day = calendar.monthrange(year, month)[1]
return date(year, month, last_day)
def next_month_day(year, month, day):
year, month = next_month(year, month)
return best_date(year, month, day)
import os
import sys
import subprocess
from setuptools import (
setup,
find_packages,
)
here = os.path.abspath(os.path.dirname(__file__))
with open(os.path.join(here, 'README.rst')) as f:
README = f.read()
with open(os.path.join(here, 'CHANGES.txt')) as f:
CHANGES = f.read()
line = CHANGES.splitlines()[0]
version = line.split()[0]
requires=[
'pytz',
'sqlalchemy',
'ziggurat_foundations',
'psycopg2-binary',
'pyramid',
]
customs_require=[
'http://repo.opensipkd.com/pip/opensipkd-jsonrpc-0.1.tar.gz',
]
packages=[
'opensipkd.base',
'opensipkd.base.tools',
'opensipkd.base.models',
'opensipkd.base.rpc',
]
def run(cmd):
if subprocess.call(cmd) != 0:
sys.exit()
def pip_install(package, upgrade=False):
cmd = [pip, 'install']
if upgrade:
cmd += ['--upgrade']
if sys.argv[2:]:
option = sys.argv[2] # Bisa untuk proxy
cmd += [option]
cmd += [package]
run(cmd)
if sys.argv[1:] and sys.argv[1] == 'develop-use-pip':
bin_ = os.path.split(sys.executable)[0]
pip = os.path.join(bin_, 'pip')
pip_install('pip', True)
pip_install('setuptools', True)
requires_ = requires + customs_require
for package in requires_:
if sys.argv[2:]:
cmd = [pip, 'install', sys.argv[2], package]
else:
cmd = [pip, 'install', package]
run(cmd)
cmd = [sys.executable, sys.argv[0], 'develop']
subprocess.call(cmd)
sys.exit()
setup(
name='opensipkd-base',
version=version,
description='Basis Aplikasi openSIPKD',
long_description=README + '\n\n' + CHANGES,
classifiers=[
"Programming Language :: Python",
"Framework :: Pylons",
"Topic :: Internet :: WWW/HTTP",
"Topic :: Internet :: WWW/HTTP :: WSGI :: Application",
],
keywords='web pyramid pylons',
packages=packages,
zip_safe=False,
install_requires=requires,
)
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!