master
parent
746da62a26
commit
65774a6d04
|
@ -0,0 +1,20 @@
|
|||
#!/usr/bin/env python3
|
||||
from lybmods import lybrary, lybpqconn, lybpqsession
|
||||
from lybmods.lybformauth import check_auth
|
||||
from lybmods import lybcfg
|
||||
from cherrypy.process.plugins import Daemonizer, DropPrivileges, PIDFile
|
||||
from pwd import getpwnam
|
||||
import cherrypy
|
||||
cherrypy.log.screen = None
|
||||
lybpqconn.create_schema()
|
||||
cherrypy.lib.sessions.PgsqlSession = lybpqsession.PgsqlSession
|
||||
cherrypy.tools.auth = cherrypy.Tool('before_handler', check_auth)
|
||||
cherrypy.config.update({
|
||||
'server.socket_port': lybcfg.webport,
|
||||
'server.socket_host': '0.0.0.0',
|
||||
})
|
||||
|
||||
DropPrivileges(cherrypy.engine, umask=0o640, uid=getpwnam(lybcfg.user).pw_uid, gid=getpwnam(lybcfg.user).pw_gid).subscribe()
|
||||
PIDFile(cherrypy.engine, lybcfg.pid).subscribe()
|
||||
Daemonizer(cherrypy.engine).subscribe()
|
||||
cherrypy.quickstart(lybrary.Root())
|
|
@ -0,0 +1,22 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
pid = '/var/www/vhosts/ukamnya.ru/tmp/lyb2.pid'
|
||||
user = 'lyb2'
|
||||
dbhost = '91.224.22.151'
|
||||
webport = 80
|
||||
dbname = 'inposya5_lyb2'
|
||||
dbuser = 'lyb2'
|
||||
dbpass = '1lyb20qwe'
|
||||
sess_table_name = 'session'
|
||||
sess_data_table_name = 'session_data'
|
||||
cat_table_name = 'category'
|
||||
doc_table_name = 'document'
|
||||
bin_table_name = 'binaries'
|
||||
docbin_table_name = 'docbinref'
|
||||
catdoc_table_name = 'catdocref'
|
||||
pwd_table_name = 'auth_passwd'
|
||||
grp_table_name = 'auth_group'
|
||||
mbrsh_table_name = 'auth_membership'
|
||||
grpcat_access_table = 'grpcat_access'
|
||||
grpdoc_access_table = 'grpdoc_access'
|
||||
pwdcat_access_table = 'pwdcat_access'
|
||||
pwddoc_access_table = 'pwddoc_access'
|
|
@ -0,0 +1,624 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
import cherrypy
|
||||
import lybmods.lybcfg as lybcfg
|
||||
import lybmods.lybtools as lybtools
|
||||
from hashlib import sha1
|
||||
class Doc:
|
||||
def __init__(self, did):
|
||||
self.sess = cherrypy.session
|
||||
self.db = self.sess.db
|
||||
self.cursor = self.db.cursor()
|
||||
self.id = did
|
||||
@property
|
||||
def text(self):
|
||||
self.cursor.execute('SELECT body FROM %s WHERE id = %%s;' % lybcfg.doc_table_name, (self.id,))
|
||||
return self.cursor.fetchone()[0]
|
||||
@property
|
||||
def bins(self):
|
||||
"""D.keys() -> list of D's keys."""
|
||||
k = []
|
||||
self.cursor.execute('''SELECT b.hash FROM {bin} AS b, (SELECT binid FROM {docbin}
|
||||
WHERE docid = %s) AS d WHERE b.id = d.binid;'''.format(bin = lybcfg.bin_table_name,
|
||||
docbin = lybcfg.docbin_table_name),
|
||||
(self.id,))
|
||||
res = self.cursor.fetchall()
|
||||
for i in res:
|
||||
k.append(i[0])
|
||||
return k
|
||||
@property
|
||||
def mtime(self):
|
||||
self.cursor.execute('SELECT mtime FROM %s WHERE id = %%s;' % lybcfg.doc_table_name, (self.id,))
|
||||
return self.cursor.fetchone()[0]
|
||||
@property
|
||||
def muser(self):
|
||||
self.cursor.execute('SELECT muser FROM %s WHERE id = %%s;' % lybcfg.doc_table_name, (self.id,))
|
||||
return Usr(self.cursor.fetchone()[0])
|
||||
@property
|
||||
def name(self):
|
||||
self.cursor.execute('SELECT name FROM %s WHERE id = %%s;' % lybcfg.doc_table_name, (self.id,))
|
||||
return self.cursor.fetchone()[0]
|
||||
def setname(self, name):
|
||||
muser = cherrypy.session.get(lybtools.SESSION_KEY, None)
|
||||
self.cursor.execute('''UPDATE {doc} SET name = %s, muser = %s WHERE id = %s;'''.format(doc = lybcfg.doc_table_name), (name, muser, self.id))
|
||||
self.db.commit()
|
||||
return True
|
||||
def setcatid(self, catid):
|
||||
muser = cherrypy.session.get(lybtools.SESSION_KEY, None)
|
||||
self.cursor.execute('''UPDATE {doc} SET catid = %s, muser = %s WHERE id = %s;'''.format(doc = lybcfg.doc_table_name), (catid, muser, self.id))
|
||||
self.db.commit()
|
||||
return True
|
||||
@property
|
||||
def cat(self):
|
||||
self.cursor.execute('SELECT catid FROM %s WHERE id = %%s;' % lybcfg.doc_table_name, (self.id,))
|
||||
catid = self.cursor.fetchone()
|
||||
if catid: return Cat(catid[0])
|
||||
else: return None
|
||||
@property
|
||||
def path(self):
|
||||
def np(p, cid):
|
||||
p.append(cid)
|
||||
if cid > 0:
|
||||
p = np(p, Cat(cid).parent.id)
|
||||
return p
|
||||
p = []
|
||||
p = np(p, self.cat.id)
|
||||
p.reverse()
|
||||
return p
|
||||
@property
|
||||
def users(self):
|
||||
"""D.keys() -> list of D's keys."""
|
||||
n = []
|
||||
self.cursor.execute('''SELECT b.username FROM {pwd} AS b, (SELECT pid FROM {pwddoc_access}
|
||||
WHERE docid = %s) AS d WHERE b.id = d.pid;'''.format(pwd = lybcfg.pwd_table_name,
|
||||
pwddoc_access = lybcfg.pwddoc_access_table),
|
||||
(self.id,))
|
||||
res = self.cursor.fetchall()
|
||||
for i in res:
|
||||
n.append(i[0])
|
||||
return n
|
||||
@property
|
||||
def groups(self):
|
||||
"""D.keys() -> list of D's keys."""
|
||||
n = []
|
||||
self.cursor.execute('''SELECT b.name FROM {grp} AS b, (SELECT gid FROM {grpdoc_access}
|
||||
WHERE docid = %s) AS d WHERE b.id = d.gid;'''.format(grp = lybcfg.grp_table_name,
|
||||
grpdoc_access = lybcfg.grpdoc_access_table),
|
||||
(self.id,))
|
||||
res = self.cursor.fetchall()
|
||||
for i in res:
|
||||
n.append(i[0])
|
||||
return n
|
||||
def __getitem__(self, key):
|
||||
self.cursor.execute("""\
|
||||
SELECT b.type, b.body FROM {bin} AS b, (SELECT binid FROM {docbin} WHERE docid = %s) AS d
|
||||
WHERE b.id = d.binid AND hash = %s;""".format(bin = lybcfg.bin_table_name,
|
||||
docbin = lybcfg.docbin_table_name), (self.id, key))
|
||||
try:
|
||||
res = self.cursor.fetchone()
|
||||
(ctype, body) = res
|
||||
return {'type': ctype, 'body': body.tobytes()}
|
||||
except:
|
||||
raise KeyError(key)
|
||||
|
||||
def __setitem__(self, key, value):
|
||||
self.cursor.execute('SELECT id FROM %s WHERE hash = %%s;' % lybcfg.bin_table_name, (key, ))
|
||||
binid = self.cursor.fetchone()
|
||||
if binid:
|
||||
binid = binid[0]
|
||||
self.cursor.execute('SELECT COUNT(*) FROM %s WHERE binid = %%s AND docid = %%s;' % lybcfg.docbin_table_name, (binid, self.id))
|
||||
count = self.cursor.fetchone()[0]
|
||||
if count:
|
||||
return
|
||||
else:
|
||||
self.cursor.execute('INSERT INTO %s (hash, type, body) VALUES (%%s, %%s, %%s) RETURNING id;' % lybcfg.bin_table_name,
|
||||
(key, value['type'], value['body']))
|
||||
binid = self.cursor.fetchone()[0]
|
||||
self.cursor.execute('INSERT INTO %s (binid, docid) VALUES (%%s, %%s);' % lybcfg.docbin_table_name, (binid, self.id))
|
||||
self.db.commit()
|
||||
def __delitem__(self, key):
|
||||
self.cursor.execute('DELETE FROM {docbin} WHERE binid = (SELECT id FROM {bin} WHERE hash = %s) AND docid = %s;'.format(docbin = lybcfg.docbin_table_name,
|
||||
bin = lybcfg.bin_table_name), (key, self.id))
|
||||
self.db.commit()
|
||||
def pop(self, key, default = None):
|
||||
"""Remove the specified key and return the corresponding value.
|
||||
If key is not found, default is returned if given,
|
||||
otherwise KeyError is raised.
|
||||
"""
|
||||
try:
|
||||
val = self[key]
|
||||
except:
|
||||
if not default:
|
||||
raise KeyError(key)
|
||||
else:
|
||||
val = default
|
||||
return val
|
||||
del self[key]
|
||||
return val
|
||||
|
||||
def __contains__(self, key):
|
||||
self.cursor.execute('SELECT count(*) FROM {docbin} WHERE binid = (SELECT id FROM {bin} WHERE hash = %s) AND docid = %s;'.format(bin = lybcfg.bin_table_name,
|
||||
docbin = lybcfg.docbin_table_name),
|
||||
(key, self.id))
|
||||
return bool(self.cursor.fetchone()[0])
|
||||
|
||||
if hasattr({}, 'has_key'):
|
||||
def has_key(self, key):
|
||||
"""D.has_key(k) -> True if D has a key k, else False."""
|
||||
return self.__contains__(key)
|
||||
|
||||
def get(self, key, default=None):
|
||||
"""D.get(k[,d]) -> D[k] if k in D, else d. d defaults to None."""
|
||||
try:
|
||||
val = self[key]
|
||||
return val
|
||||
except:
|
||||
return default
|
||||
|
||||
def update(self, d):
|
||||
"""D.update(E) -> None. Update D from E: for k in E: D[k] = E[k]."""
|
||||
for k in d:
|
||||
self[k] = d[k]
|
||||
|
||||
def setdefault(self, key, default=None):
|
||||
"""D.setdefault(k[,d]) -> D.get(k,d), also set D[k]=d if k not in D."""
|
||||
try:
|
||||
val = self[key]
|
||||
except:
|
||||
self[key] = val = default
|
||||
return val
|
||||
|
||||
def clear(self):
|
||||
"""D.clear() -> None. Remove all items from D."""
|
||||
self.cursor.execute('DELETE FROM {docbin} WHERE docid = %s;'.format(docbin = lybcfg.docbin_table_name), (self.id,))
|
||||
self.db.commit()
|
||||
|
||||
def keys(self):
|
||||
"""D.keys() -> list of D's keys."""
|
||||
k = []
|
||||
self.cursor.execute('SELECT hash FROM {bin} WHERE id = (SELECT binid FROM {docbin} WHERE docid = %s);'.format(bin = lybcfg.bin_table_name,
|
||||
docbin = lybcfg.docbin_table_name),
|
||||
(self.id,))
|
||||
res = self.cursor.fetchall()
|
||||
for i in res:
|
||||
k.append(i[0])
|
||||
return k
|
||||
|
||||
def items(self):
|
||||
"""D.items() -> list of D's (key, value) pairs, as 2-tuples."""
|
||||
i = []
|
||||
self.cursor.execute('SELECT hash, type, body FROM {bin} WHERE id = (SELECT binid FROM {docbin} WHERE docid = %s);'.format(bin = lybcfg.bin_table_name,
|
||||
docbin = lybcfg.docbin_table_name),
|
||||
(self.id,))
|
||||
res = self.cursor.fetchall()
|
||||
for k, t, v in res:
|
||||
i.append((k, {'type': t, 'body': str(v)}))
|
||||
return i
|
||||
|
||||
def values(self):
|
||||
"""D.values() -> list of D's values."""
|
||||
v = []
|
||||
self.cursor.execute('SELECT body FROM {bin} WHERE id = (SELECT binid FROM {docbin} WHERE docid = %s);'.format(bin = lybcfg.bin_table_name,
|
||||
docbin = lybcfg.docbin_table_name),
|
||||
(self.id,))
|
||||
res = self.cursor.fetchall()
|
||||
for i in res:
|
||||
v.append(str(i[0]))
|
||||
return v
|
||||
|
||||
def __del__(self):
|
||||
self.db.commit()
|
||||
self.cursor.close()
|
||||
self.cursor = None
|
||||
self.db = None
|
||||
def __repr__(self):
|
||||
return '<DocObject %r>' % (self.id,)
|
||||
|
||||
class Cat:
|
||||
def __init__(self, cid = 0):
|
||||
self.sess = cherrypy.session
|
||||
self.db = self.sess.db
|
||||
self.cursor = self.db.cursor()
|
||||
self.id = cid
|
||||
|
||||
def search(self, query):
|
||||
if self.id == 0:
|
||||
self.cursor.execute("""SELECT tab.id FROM (SELECT ts_rank_cd(fts_index, q) as rank, id
|
||||
FROM %s, plainto_tsquery(%%s) q
|
||||
WHERE q @@ fts_index ORDER BY rank DESC) AS tab;""" % lybcfg.doc_table_name, (query, ))
|
||||
else:
|
||||
self.cursor.execute("""SELECT tab.id FROM (SELECT ts_rank_cd(fts_index, q) AS rank, id
|
||||
FROM %s, plainto_tsquery(%%s) q
|
||||
WHERE q @@ fts_index AND catid = %%s ORDER BY rank DESC) AS tab;""" % lybcfg.doc_table_name, (query, self.id))
|
||||
return [x[0] for x in self.cursor.fetchall()]
|
||||
@property
|
||||
def name(self):
|
||||
if self.id == 0:
|
||||
return 'Корневой'
|
||||
self.cursor.execute('SELECT name FROM %s WHERE id = %%s;' % lybcfg.cat_table_name, (self.id,))
|
||||
return self.cursor.fetchone()[0]
|
||||
def setname(self, name):
|
||||
if self.id == 0:
|
||||
return False
|
||||
self.cursor.execute('UPDATE %s SET name = %%s WHERE id = %%s;' % lybcfg.cat_table_name, (name, self.id))
|
||||
self.db.commit()
|
||||
return True
|
||||
@property
|
||||
def parent(self):
|
||||
if self.id == 0: return Cat(0)
|
||||
self.cursor.execute('SELECT parent FROM %s WHERE id = %%s;' % lybcfg.cat_table_name, (self.id,))
|
||||
parid = self.cursor.fetchone()[0]
|
||||
return Cat(parid)
|
||||
@property
|
||||
def path(self):
|
||||
def np(p, cid):
|
||||
p.append(cid)
|
||||
if cid > 0:
|
||||
p = np(p, Cat(cid).parent.id)
|
||||
return p
|
||||
p = []
|
||||
if self.id == 0: return []
|
||||
p = np(p, self.parent.id)
|
||||
p.reverse()
|
||||
return p
|
||||
def setparentid(self, parid):
|
||||
if self.id == 0:
|
||||
return False
|
||||
self.cursor.execute('UPDATE %s SET parent = %%s WHERE id = %%s;' % lybcfg.cat_table_name, (parid, self.id))
|
||||
self.db.commit()
|
||||
return True
|
||||
@property
|
||||
def categories(self):
|
||||
v = []
|
||||
self.cursor.execute('SELECT id FROM {cat} WHERE parent = %s ORDER BY name ASC;'.format(cat = lybcfg.cat_table_name), (self.id,))
|
||||
res = self.cursor.fetchall()
|
||||
for i in res:
|
||||
v.append(Cat(i[0]))
|
||||
return v
|
||||
def delete(self):
|
||||
self.cursor.execute('DELETE FROM {cat} WHERE id = %s;'.format(cat = lybcfg.cat_table_name), (self.id,))
|
||||
self.db.commit()
|
||||
@property
|
||||
def documents(self):
|
||||
v = []
|
||||
self.cursor.execute('SELECT id FROM %s WHERE catid = %%s ORDER BY name;' % lybcfg.doc_table_name, (self.id,))
|
||||
res = self.cursor.fetchall()
|
||||
for i in res:
|
||||
v.append(Doc(i[0]))
|
||||
return v
|
||||
@property
|
||||
def catcount(self):
|
||||
self.cursor.execute('SELECT count(*) FROM %s WHERE parent = %%s;' % lybcfg.cat_table_name, (self.id,))
|
||||
return self.cursor.fetchone()[0]
|
||||
@property
|
||||
def doccount(self):
|
||||
self.cursor.execute('SELECT count(*) FROM %s WHERE catid = %%s;' % lybcfg.doc_table_name, (self.id,))
|
||||
return self.cursor.fetchone()[0]
|
||||
def docidbyname(self, name):
|
||||
self.cursor.execute('SELECT id FROM %s WHERE catid = %%s AND name = %%s' % lybcfg.doc_table_name, (self.id, name))
|
||||
res = self.cursor.fetchone()
|
||||
if res:
|
||||
return res[0]
|
||||
else:
|
||||
return None
|
||||
def __getitem__(self, did):
|
||||
self.cursor.execute('SELECT id FROM %s WHERE catid = %%s AND id = %%s;' % lybcfg.doc_table_name, (self.id, did))
|
||||
docid = self.cursor.fetchone()
|
||||
if docid:
|
||||
return Doc(docid[0])
|
||||
else:
|
||||
raise KeyError(did)
|
||||
def __setitem__(self, did, value):
|
||||
muser = cherrypy.session.get(lybtools.SESSION_KEY, None)
|
||||
self.cursor.execute('SELECT id FROM %s WHERE id = %%s AND catid = %%s;' % lybcfg.doc_table_name, (did, self.id))
|
||||
docid = self.cursor.fetchone()
|
||||
if docid:
|
||||
self.cursor.execute('UPDATE %s SET name = %%s, body = %%s, muser = %%s, mtime = now() WHERE id = %%s;' % lybcfg.doc_table_name, (value['name'],
|
||||
value['body'],
|
||||
muser,
|
||||
docid[0]))
|
||||
else:
|
||||
raise KeyError(did)
|
||||
self.db.commit()
|
||||
def insert(self, value):
|
||||
muser = cherrypy.session.get(lybtools.SESSION_KEY, None)
|
||||
self.cursor.execute('INSERT INTO %s (name, catid, muser, body) VALUES (%%s, %%s, %%s, %%s) RETURNING id;' % lybcfg.doc_table_name,
|
||||
(value['name'], self.id, muser, value['body']))
|
||||
did = self.cursor.fetchone()[0]
|
||||
self.db.commit()
|
||||
return did
|
||||
def __delitem__(self, did):
|
||||
muser = cherrypy.session.get(lybtools.SESSION_KEY, None)
|
||||
self.cursor.execute('DELETE FROM %s WHERE catid = %%s AND id = %%s;' % lybcfg.doc_table_name, (self.id, did))
|
||||
self.db.commit()
|
||||
def pop(self, key, default = None):
|
||||
"""Remove the specified key and return the corresponding value.
|
||||
If key is not found, default is returned if given,
|
||||
otherwise KeyError is raised.
|
||||
"""
|
||||
try:
|
||||
val = self[key]
|
||||
except:
|
||||
if not default:
|
||||
raise KeyError(key)
|
||||
else:
|
||||
val = default
|
||||
return val
|
||||
del self[key]
|
||||
return val
|
||||
|
||||
def __contains__(self, did):
|
||||
self.cursor.execute('SELECT count(*) FROM %s WHERE catid = %%s AND id = %%s;' % lybcfg.doc_table_name, (self.id, did))
|
||||
return bool(self.cursor.fetchone()[0])
|
||||
|
||||
if hasattr({}, 'has_key'):
|
||||
def has_key(self, key):
|
||||
"""D.has_key(k) -> True if D has a key k, else False."""
|
||||
return self.__contains__(key)
|
||||
|
||||
def get(self, key, default=None):
|
||||
"""D.get(k[,d]) -> D[k] if k in D, else d. d defaults to None."""
|
||||
try:
|
||||
val = self[key]
|
||||
return val
|
||||
except:
|
||||
return default
|
||||
|
||||
def update(self, d):
|
||||
"""D.update(E) -> None. Update D from E: for k in E: D[k] = E[k]."""
|
||||
for k in d:
|
||||
self[k] = d[k]
|
||||
|
||||
def setdefault(self, key, default=None):
|
||||
"""D.setdefault(k[,d]) -> D.get(k,d), also set D[k]=d if k not in D."""
|
||||
try:
|
||||
val = self[key]
|
||||
except:
|
||||
self[key] = val = default
|
||||
return val
|
||||
|
||||
def clear(self):
|
||||
"""D.clear() -> None. Remove all items from D."""
|
||||
self.cursor.execute('DELETE FROM %s WHERE catid = %%s;' % lybcfg.doc_table_name, (self.id,))
|
||||
self.db.commit()
|
||||
|
||||
def keys(self):
|
||||
"""D.keys() -> list of D's keys."""
|
||||
k = []
|
||||
self.cursor.execute('SELECT id FROM %s WHERE catid = %%s;' % lybcfg.doc_table_name, (self.id,))
|
||||
res = self.cursor.fetchall()
|
||||
for i in res:
|
||||
k.append(i[0])
|
||||
return k
|
||||
|
||||
def items(self):
|
||||
"""D.items() -> list of D's (key, value) pairs, as 2-tuples."""
|
||||
i = []
|
||||
self.cursor.execute('SELECT id FROM %s WHERE catid = %%s;' % lybcfg.doc_table_name, (self.id,))
|
||||
res = self.cursor.fetchall()
|
||||
for did in res:
|
||||
i.append((did, Doc(did)))
|
||||
return tuple(i)
|
||||
|
||||
def values(self):
|
||||
"""D.values() -> list of D's values."""
|
||||
v = []
|
||||
self.cursor.execute('SELECT id FROM %s WHERE catid = %%s;' % lybcfg.doc_table_name, (self.id,))
|
||||
res = self.cursor.fetchall()
|
||||
for i in res:
|
||||
v.append(Doc(i))
|
||||
return v
|
||||
def newcat(self, name):
|
||||
self.cursor.execute('SELECT count(*) FROM %s WHERE name = %%s AND parent = %%s;' % lybcfg.cat_table_name, (name, self.id))
|
||||
exist = self.cursor.fetchone()[0]
|
||||
if exist:
|
||||
return False
|
||||
else:
|
||||
self.cursor.execute('INSERT INTO %s (name, parent) VALUES (%%s, %%s);' % lybcfg.cat_table_name, (name, self.id))
|
||||
self.db.commit()
|
||||
return True
|
||||
|
||||
def __del__(self):
|
||||
self.db.commit()
|
||||
self.cursor.close()
|
||||
self.cursor = None
|
||||
self.db = None
|
||||
|
||||
def __repr__(self):
|
||||
return '<CatObject %r>' % (self.id,)
|
||||
|
||||
class Usr:
|
||||
def __init__(self, name):
|
||||
self.sess = cherrypy.session
|
||||
self.db = self.sess.db
|
||||
self.cursor = self.db.cursor()
|
||||
self.name = name
|
||||
def new(self, password, dname = None):
|
||||
dname = True and dname or self.name
|
||||
p = sha1(self.name.encode("utf-8"))
|
||||
p.update(password.encode("utf-8"))
|
||||
try:
|
||||
self.cursor.execute('INSERT INTO %s (username, dname, password) VALUES (%%s, %%s, %%s);' % lybcfg.pwd_table_name,
|
||||
(self.name, dname, p.hexdigest()))
|
||||
except:
|
||||
self.db.commit()
|
||||
return False
|
||||
self.db.commit()
|
||||
return True
|
||||
def delete(self):
|
||||
self.cursor.execute('DELETE FROM %s WHERE username = %%s;' % lybcfg.pwd_table_name, (self.name,))
|
||||
self.db.commit()
|
||||
@property
|
||||
def uid(self):
|
||||
self.cursor.execute('SELECT id FROM %s WHERE username = %%s' % lybcfg.pwd_table_name, (self.name,))
|
||||
uid = self.cursor.fetchone()
|
||||
if uid:
|
||||
return uid[0]
|
||||
else:
|
||||
raise KeyError(self.name)
|
||||
@property
|
||||
def groups(self):
|
||||
v = []
|
||||
self.cursor.execute("""SELECT name FROM {grp}
|
||||
WHERE id = (SELECT gid FROM {mbrsh} WHERE uid = %s)
|
||||
ORDER BY dname ASC;""".format(grp = lybcfg.grp_table_name, mbrsh = lybcfg.mbrsh_table_name), (self.uid,))
|
||||
res = self.cursor.fetchall()
|
||||
for i in res:
|
||||
v.append(Grp(i[0]))
|
||||
return v
|
||||
@property
|
||||
def fgroups(self):
|
||||
v = []
|
||||
self.cursor.execute("""SELECT name FROM {grp}
|
||||
WHERE id NOT IN (SELECT gid FROM {mbrsh} WHERE uid = %s)
|
||||
ORDER BY dname ASC;""".format(grp = lybcfg.grp_table_name, mbrsh = lybcfg.mbrsh_table_name), (self.uid,))
|
||||
res = self.cursor.fetchall()
|
||||
for i in res:
|
||||
v.append(Grp(i[0]))
|
||||
return v
|
||||
def setpwd(self, pwd):
|
||||
p = sha1(self.name.encode("utf-8"))
|
||||
p.update(pwd.encode("utf-8"))
|
||||
self.cursor.execute('UPDATE %s SET password = %%s WHERE id = %%s;' % lybcfg.pwd_table_name, (p.hexdigest(), self.uid))
|
||||
self.db.commit()
|
||||
def setname(self, name):
|
||||
try:
|
||||
self.cursor.execute('UPDATE %s SET username = %%s WHERE username = %%s;' % lybcfg.pwd_table_name,
|
||||
(name, self.name))
|
||||
except:
|
||||
self.db.commit()
|
||||
return False
|
||||
self.db.commit()
|
||||
self.name = name
|
||||
return True
|
||||
def setdname(self, dname):
|
||||
self.cursor.execute('UPDATE %s SET dname = %%s WHERE username = %%s;' % lybcfg.pwd_table_name,
|
||||
(dname, self.name))
|
||||
self.db.commit()
|
||||
return True
|
||||
@property
|
||||
def dname(self):
|
||||
self.cursor.execute('SELECT dname FROM %s WHERE username = %%s' % lybcfg.pwd_table_name, (self.name,))
|
||||
dn = self.cursor.fetchone()
|
||||
if dn:
|
||||
return dn[0]
|
||||
else:
|
||||
raise KeyError(self.name)
|
||||
|
||||
class Grp:
|
||||
def __init__(self, name):
|
||||
self.sess = cherrypy.session
|
||||
self.db = self.sess.db
|
||||
self.cursor = self.db.cursor()
|
||||
self.name = name
|
||||
def new(self, dname = None):
|
||||
dname = True and dname or self.name
|
||||
try:
|
||||
self.cursor.execute('INSERT INTO %s (name, dname) VALUES (%%s, %%s);' % lybcfg.grp_table_name,
|
||||
(self.name, dname))
|
||||
|
||||
except:
|
||||
self.db.commit()
|
||||
return False
|
||||
self.db.commit()
|
||||
return True
|
||||
def delete(self):
|
||||
self.cursor.execute('DELETE FROM %s WHERE name = %%s;' % lybcfg.grp_table_name, (self.name,))
|
||||
self.db.commit()
|
||||
def setname(self, name):
|
||||
try:
|
||||
self.cursor.execute('UPDATE %s SET name = %%s WHERE name = %%s;' % lybcfg.grp_table_name,
|
||||
(name, self.name))
|
||||
except:
|
||||
self.db.commit()
|
||||
return False
|
||||
self.db.commit()
|
||||
self.name = name
|
||||
return True
|
||||
def setdname(self, dname):
|
||||
self.cursor.execute('UPDATE %s SET dname = %%s WHERE name = %%s;' % lybcfg.grp_table_name,
|
||||
(dname, self.name))
|
||||
self.db.commit()
|
||||
return True
|
||||
@property
|
||||
def gid(self):
|
||||
self.cursor.execute('SELECT id FROM %s WHERE name = %%s' % lybcfg.grp_table_name, (self.name,))
|
||||
gid = self.cursor.fetchone()
|
||||
if gid:
|
||||
return gid[0]
|
||||
else:
|
||||
raise KeyError(self.name)
|
||||
@property
|
||||
def members(self):
|
||||
v = []
|
||||
self.cursor.execute("""SELECT username FROM {pwd}
|
||||
WHERE id IN (SELECT uid FROM {mbrsh} WHERE gid = %s)
|
||||
ORDER BY dname ASC;""".format(pwd = lybcfg.pwd_table_name, mbrsh = lybcfg.mbrsh_table_name), (self.gid,))
|
||||
res = self.cursor.fetchall()
|
||||
for i in res:
|
||||
v.append(Usr(i[0]))
|
||||
return v
|
||||
@property
|
||||
def notmembers(self):
|
||||
v = []
|
||||
self.cursor.execute("""SELECT username FROM {pwd}
|
||||
WHERE id NOT IN (SELECT uid FROM {mbrsh} WHERE gid = %s)
|
||||
ORDER BY dname ASC;""".format(pwd = lybcfg.pwd_table_name, mbrsh = lybcfg.mbrsh_table_name), (self.gid,))
|
||||
res = self.cursor.fetchall()
|
||||
for i in res:
|
||||
v.append(Usr(i[0]))
|
||||
return v
|
||||
@property
|
||||
def dname(self):
|
||||
self.cursor.execute('SELECT dname FROM %s WHERE name = %%s' % lybcfg.grp_table_name, (self.name,))
|
||||
dn = self.cursor.fetchone()
|
||||
if dn:
|
||||
return dn[0]
|
||||
else:
|
||||
raise KeyError(self.name)
|
||||
def delmember(self, name):
|
||||
self.cursor.execute("""DELETE FROM {mbrsh}
|
||||
WHERE uid = (SELECT id FROM {pwd} WHERE username = %s)
|
||||
AND gid = %s;""".format(pwd = lybcfg.pwd_table_name, mbrsh = lybcfg.mbrsh_table_name), (name, self.gid))
|
||||
self.db.commit()
|
||||
def addmember(self, name):
|
||||
self.cursor.execute("""SELECT count(*) FROM {mbrsh}
|
||||
WHERE uid = (SELECT id FROM {pwd} WHERE username = %s)
|
||||
AND gid = %s;""".format(pwd = lybcfg.pwd_table_name, mbrsh = lybcfg.mbrsh_table_name), (name, self.gid))
|
||||
count = self.cursor.fetchone()[0]
|
||||
if count:
|
||||
return False
|
||||
else:
|
||||
self.cursor.execute("""INSERT INTO {mbrsh}
|
||||
(uid, gid)
|
||||
VALUES ((SELECT id FROM {pwd} WHERE username = %s), %s);""".format(mbrsh = lybcfg.mbrsh_table_name, pwd = lybcfg.pwd_table_name),
|
||||
(name, self.gid))
|
||||
self.db.commit()
|
||||
return True
|
||||
|
||||
class Users:
|
||||
def __init__(self):
|
||||
self.sess = cherrypy.session
|
||||
self.db = self.sess.db
|
||||
self.cursor = self.db.cursor()
|
||||
@property
|
||||
def list(self):
|
||||
v = []
|
||||
self.cursor.execute('SELECT username FROM %s ORDER BY dname;' % lybcfg.pwd_table_name)
|
||||
res = self.cursor.fetchall()
|
||||
for i in res:
|
||||
v.append(Usr(i[0]))
|
||||
return v
|
||||
|
||||
class Groups:
|
||||
def __init__(self):
|
||||
self.sess = cherrypy.session
|
||||
self.db = self.sess.db
|
||||
self.cursor = self.db.cursor()
|
||||
@property
|
||||
def list(self):
|
||||
v = []
|
||||
self.cursor.execute('SELECT name FROM %s ORDER BY dname;' % lybcfg.grp_table_name)
|
||||
res = self.cursor.fetchall()
|
||||
for i in res:
|
||||
v.append(Grp(i[0]))
|
||||
return v
|
|
@ -0,0 +1,244 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
import cherrypy
|
||||
from lybmods.lybformauth import member_of, name_is, require
|
||||
from lybmods.lybclasses import Users, Groups, Usr, Grp
|
||||
import lybmods.lybtools as lybtools
|
||||
import lybmods.lybhtdata as lybhtdata
|
||||
class Ctl:
|
||||
_cp_config = {
|
||||
'auth.require': []
|
||||
}
|
||||
def __init__(self, root):
|
||||
self.root = root
|
||||
@cherrypy.expose
|
||||
def index(self):
|
||||
raise cherrypy.HTTPRedirect("/")
|
||||
@cherrypy.expose
|
||||
def user(self, name = None, err = ''):
|
||||
name = True and name or cherrypy.session.get(lybtools.SESSION_KEY, None)
|
||||
html = ''
|
||||
usr = Usr(name)
|
||||
dname = usr.dname
|
||||
grps = usr.groups
|
||||
if len(grps):
|
||||
html += '<tr><td><b>Пользователь "' + dname + '[' + name + ']" находится в следующих группах:</b></td></tr>'
|
||||
for grp in grps:
|
||||
if member_of('admins')():
|
||||
html += '<tr><form action="/ctl/grpfromusr"><td></td><td><a href="/ctl/group?name=' + grp.name + '">' + grp.dname + '[' + grp.name + ']</a></td><input type="hidden" name="uname" value="' + name + '"><input type="hidden" name="gname" value="' + grp.name + '"><td><input type="submit" value="Удалить из этой группы"></td></form></tr>\n'
|
||||
else:
|
||||
html += '<tr><td>' + grp.dname + '[' + grp.name + ']</td></tr>\n'
|
||||
else: html += '<tr><td><b>Пользователь "' + dname + '[' + name + ']" не находится ни в каких группах</b></td></tr>'
|
||||
if member_of('admins')():
|
||||
l = '<select name="gname">\n{lbody}</select>\n'
|
||||
lo = '<option value={gname}>{dname}[{gname}]</option>\n'
|
||||
lopts = ''
|
||||
fg = usr.fgroups
|
||||
if len(fg):
|
||||
for g in usr.fgroups:
|
||||
lopts += lo.format(gname = g.name, dname = g.dname)
|
||||
sel = l.format(lbody = lopts)
|
||||
html += '<tr>\n<form action="/ctl/grptousr">\n<td>Добавить пользователя в группу: <input type="hidden" name="uname" value="' + name + '">\n{sel}<input type="submit" value="Добавить">\n</td>\n</form>\n</tr>\n'.format(sel = sel)
|
||||
if member_of('admins')() or name_is(name)():
|
||||
html += '<tr><form action="/ctl/setpwd"><input type="hidden" name="name" value="' + name + '"><td>Новый пароль<input type="password" name="password"><input type="submit" value="Установить"></td></form></tr>'
|
||||
return self.root.buildhtml('Панель управления[Пользователь "' + name + '"]' + err, lybhtdata.user_body.format(name = name, groups = html))
|
||||
@cherrypy.expose
|
||||
def setpwd(self, name = None, password = ''):
|
||||
if password == '': return self.user(name = name, err = '!!!Пароль не может быть пустым!!!')
|
||||
name = True and name or cherrypy.session.get(lybtools.SESSION_KEY, None)
|
||||
if not member_of('admins')() and not name_is(name)(): raise cherrypy.HTTPRedirect("/denied")
|
||||
usr = Usr(name)
|
||||
usr.setpwd(password)
|
||||
return self.user(name, '<Пароль установлен>')
|
||||
@cherrypy.expose
|
||||
@require(member_of('admins'))
|
||||
def useredit(self, submit = None, name = None, err = ''):
|
||||
if submit and name:
|
||||
usr = Usr(name)
|
||||
dname = usr.dname
|
||||
if submit == 'Переименовать':
|
||||
html = '<div align="center"><form action="/ctl/renameuser" method="post"><input type="hidden" name="name" value=' + name + '>\nНовое имя пользователя\n<input type="text" name="newname" value="' + name + '">\nНовое отображаемое имя<input type="text" name="newdname" value="' + dname + '"><input type="submit" value="Готово"></form></div><div align="center"><a href="/ctl/users"><i>← Обратно к списку пользователей</i></a></div>'
|
||||
title, document = ('Панель управления[Переименовать пользователя "' + name + '"]', html)
|
||||
elif submit == 'Удалить':
|
||||
html = '<div align="center"><form action="/ctl/deleteuser" method="post"><input type="hidden" name="name" value="' + name + '">Действительно удалить пользователея "' + name + '"?<br><input type="submit" value="Удалить"></form><div align="center"><a href="/ctl/users"><i>← Обратно к списку пользователей</i></a></div>'
|
||||
title, document = ('Панель управления[Удалить пользователя "' + name + '"]', html)
|
||||
return self.root.buildhtml(title + err, document)
|
||||
@cherrypy.expose
|
||||
@require(member_of('admins'))
|
||||
def renameuser(self, name = None, newname = '', newdname = ''):
|
||||
if newname == '': return self.useredit('Переименовать', name, '!!!Имя пользователя не может быть пустым!!!')
|
||||
if newdname == '': newdname = newname
|
||||
name = True and name or cherrypy.session.get(lybtools.SESSION_KEY, None)
|
||||
usr = Usr(name)
|
||||
dname = usr.dname
|
||||
if name == newname and dname == newdname: return self.useredit('Переименовать', name, '!!!Данные не изменены!!!')
|
||||
if name != newname:
|
||||
if not usr.setname(newname):return self.useredit('Переименовать', name, '!!!Ошибка. Возможно пользователь с таким именем уже существует!!!')
|
||||
if dname != newdname:
|
||||
usr.setdname(newdname)
|
||||
return self.users()
|
||||
@cherrypy.expose
|
||||
@require(member_of('admins'))
|
||||
def deleteuser(self, name = None):
|
||||
if not name: return
|
||||
if name_is(name)(): return self.useredit('Удалить', name, '!!!Нельзя удалить своего же пользователея!!!')
|
||||
usr = Usr(name)
|
||||
if 'admins' in usr.groups and len(Grp('admins').members) == 1:
|
||||
return self.useredit('Удалить', name, '!!!Нельзя удалить единственного администратора!!!')
|
||||
try:
|
||||
usr.delete()
|
||||
except:
|
||||
pass
|
||||
return self.users()
|
||||
@cherrypy.expose
|
||||
@require(member_of('admins'))
|
||||
def users(self):
|
||||
usrs = Users()
|
||||
html = '<div align="center">\n<table>\n'
|
||||
html += '<tr><td><b><u>Отображаемое имя|</u></b></td><td><b><u>|Имя пользователя</u></b></td>\n'
|
||||
for user in usrs.list:
|
||||
name = user.name
|
||||
dname = user.dname
|
||||
rec = '<td><a href="/ctl/user?name=' + name + '">' + dname + '</a></td><td><a href="/ctl/user?name=' + name + '">[' + name + ']</a></td>\n'
|
||||
html += '<tr><form action="/ctl/useredit" method="post">\n{rec}<input type="hidden" name="name" value="'.format(rec = rec) + name + '">\n<td><input type="submit" name="submit" value="Переименовать"></td>\n<td><input type="submit" name="submit" value="Удалить"></td>\n</form></tr>\n'
|
||||
html += '</table>\n</div>\n'
|
||||
html += '<div align="right">\n<form action="/ctl/newuser" method="post">\n<input type="submit" value="Создать пользователя">\n</form>\n</div>\n'
|
||||
return self.root.buildhtml('Панель управления[Пользователи]', html)
|
||||
@cherrypy.expose
|
||||
@require(member_of('admins'))
|
||||
def groups(self):
|
||||
grps = Groups()
|
||||
html = '<div align="center">\n<table>\n'
|
||||
html += '<tr><td><b><u>Отображаемое имя|</u></b></td><td><b><u>|Имя группы</u></b></td>\n'
|
||||
for grp in grps.list:
|
||||
name = grp.name
|
||||
dname = grp.dname
|
||||
rec = '<td><a href="/ctl/group?name=' + name + '">' + dname + '</a></td><td><a href="/ctl/group?name=' + name + '">[' + name + ']</a></td>\n'
|
||||
if name == 'admins' or name == 'editors': html += '<tr>%s</tr>' % rec
|
||||
else: html += '<tr><form action="/ctl/groupedit" method="post">\n{rec}<input type="hidden" name="name" value="'.format(rec = rec) + name + '">\n<td><input type="submit" name="submit" value="Переименовать"></td>\n<td><input type="submit" name="submit" value="Удалить"></td>\n</form></tr>\n'
|
||||
html += '</table>\n</div>\n'
|
||||
html += '<div align="right">\n<form action="/ctl/newgroup" method="post">\n<input type="submit" value="Создать группу">\n</form>\n</div>\n'
|
||||
return self.root.buildhtml('Панель управления[Группы]', html)
|
||||
@cherrypy.expose
|
||||
@require(member_of('admins'))
|
||||
def newuser(self, err = ''):
|
||||
html = '<div align="left">\n<table>\n'
|
||||
html += '<tr><form action="/ctl/createuser" method="post">\n<td>Имя пользователя<input type="input" name="name"></td>\n<td>Отображаемое имя<input type="input" name="dname"></td>\n<td>Пароль<input type="password" name="password"></td>\n<td><input type="submit" value="Создать"></td>\n</form></tr>\n'
|
||||
html += '</table>\n</div>\n'
|
||||
html += '<div align="right"><a href="/ctl/users">\n<i>← Обратно в список пользователей</i>\n</a>\n</div>\n'
|
||||
return self.root.buildhtml('Панель управления[Пользователи]' + err, html)
|
||||
@cherrypy.expose
|
||||
@require(member_of('admins'))
|
||||
def newgroup(self, err = ''):
|
||||
html = '<div align="left">\n<table>\n'
|
||||
html += '<tr><form action="/ctl/creategroup" method="post">\n<td>Имя группы<input type="input" name="name"></td>\n<td>Отображаемое имя<input type="input" name="dname"></td>\n<td><input type="submit" value="Создать"></td>\n</form></tr>\n'
|
||||
html += '</table>\n</div>\n'
|
||||
html += '<div align="right"><a href="/ctl/groups">\n<i>← Обратно в список групп</i>\n</a>\n</div>\n'
|
||||
return self.root.buildhtml('Панель управления[Группы]' + err, html)
|
||||
@cherrypy.expose
|
||||
@require(member_of('admins'))
|
||||
def createuser(self, name = '', dname = '', password = ''):
|
||||
if name == '' or password == '': return self.newuser(err = '!!!Имя пользователя или пароль не могут быть пустыми!!!')
|
||||
if dname == '': dname = name
|
||||
usr = Usr(name)
|
||||
if usr.new(password, dname): return self.user(name)
|
||||
else: return self.newuser(err = '!!!Ошибка. Возможно пользователь с таким именем уже существует!!!')
|
||||
@cherrypy.expose
|
||||
@require(member_of('admins'))
|
||||
def creategroup(self, name = '', dname = ''):
|
||||
if name == '': return self.newuser(err = '!!!Имя группы не может быть пустыми!!!')
|
||||
if dname == '': dname = name
|
||||
grp = Grp(name)
|
||||
if grp.new(dname): return self.group(name)
|
||||
else: return self.newgroup(err = '!!!Ошибка. Возможно группа с таким именем уже существует!!!')
|
||||
@cherrypy.expose
|
||||
@require(member_of('admins'))
|
||||
def group(self, name = None, err = ''):
|
||||
if not name: return
|
||||
html = ''
|
||||
grp = Grp(name)
|
||||
dname = grp.dname
|
||||
members = grp.members
|
||||
if len(members):
|
||||
html += '<tr><td><b>В группе "' + dname + '[' + name + ']" находятся следующие пользователи:</b></td></tr>'
|
||||
for member in members:
|
||||
html += '<tr><form action="/ctl/usrfromgrp"><td></td><td><a href="/ctl/user?name=' + member.name + '">' + member.dname + '[' + member.name + ']</a></td><input type="hidden" name="uname" value="' + member.name + '"><input type="hidden" name="gname" value="' + name + '"><td><input type="submit" value="Удалить из группы"></td></form></tr>\n'
|
||||
else: html += '<tr><td><b>В группе "' + dname + '[' + name + ']" нет ни одного пользователя</b></td></tr>'
|
||||
l = '<select name="uname">\n{lbody}</select>\n'
|
||||
lo = '<option value={uname}>{udname}[{uname}]</option>\n'
|
||||
lopts = ''
|
||||
nm = grp.notmembers
|
||||
if len(nm):
|
||||
for u in nm:
|
||||
lopts += lo.format(uname = u.name, udname = u.dname)
|
||||
sel = l.format(lbody = lopts)
|
||||
html += '<tr>\n<form action="/ctl/usrtogrp">\n<td>Добавить в эту группу пользователя: <input type="hidden" name="gname" value="' + name + '">\n{sel}<input type="submit" value="Добавить">\n</td>\n</form>\n</tr>\n'.format(sel = sel)
|
||||
return self.root.buildhtml('Панель управления[Группа "' + name + '"]' + err, lybhtdata.group_body.format(name = name, groups = html))
|
||||
@cherrypy.expose
|
||||
@require(member_of('admins'))
|
||||
def groupedit(self, submit = None, name = None, err = ''):
|
||||
if submit and name:
|
||||
grp = Grp(name)
|
||||
dname = grp.dname
|
||||
if submit == 'Переименовать':
|
||||
html = '<div align="center"><form action="/ctl/renamegroup" method="post"><input type="hidden" name="name" value=' + name + '>\nНовое имя группы\n<input type="text" name="newname" value="' + name + '">\nНовое отображаемое имя<input type="text" name="newdname" value="' + dname + '"><input type="submit" value="Готово"></form></div><div align="center"><a href="/ctl/groups"><i>← Обратно к списку групп</i></a></div>'
|
||||
title, document = ('Панель управления[Переименовать группу "' + name + '"]' + err, html)
|
||||
elif submit == 'Удалить':
|
||||
html = '<div align="center"><form action="/ctl/deletegroup" method="post"><input type="hidden" name="name" value="' + name + '">Действительно удалить группу "' + name + '"?<br><input type="submit" value="Удалить"></form><div align="center"><a href="/ctl/groups"><i>← Обратно к списку групп</i></a></div>'
|
||||
title, document = ('Панель управления[Удалить группу "' + name + '"]', html)
|
||||
return self.root.buildhtml(title + err, document)
|
||||
@cherrypy.expose
|
||||
@require(member_of('admins'))
|
||||
def renamegroup(self, name = None, newname = '', newdname = ''):
|
||||
if newname == '': return self.groupedit('Переименовать', name, '!!!Имя группы не может быть пустым!!!')
|
||||
if not name or name =='' or name == 'admins' or name == 'editors': return
|
||||
if newdname == '': newdname = newname
|
||||
grp = Grp(name)
|
||||
dname = grp.dname
|
||||
if name == newname and dname == newdname: return self.groupedit('Переименовать', name, '!!!Данные не изменены!!!')
|
||||
if name != newname:
|
||||
if not grp.setname(newname): return self.groupedit('Переименовать', name, '!!!Ошибка. Возможно группа с таким именем уже существует!!!')
|
||||
if dname != newdname:
|
||||
grp.setdname(newdname)
|
||||
return self.group()
|
||||
@cherrypy.expose
|
||||
@require(member_of('admins'))
|
||||
def deletegroup(self, name = None):
|
||||
if not name or name =='' or name == 'admins' or name == 'editors': return
|
||||
grp = Grp(name)
|
||||
try:
|
||||
grp.delete()
|
||||
except:
|
||||
pass
|
||||
return self.groups()
|
||||
@cherrypy.expose
|
||||
@require(member_of('admins'))
|
||||
def grpfromusr(self, uname = '', gname = ''):
|
||||
if uname == '' or gname == '': return
|
||||
grp = Grp(gname)
|
||||
if gname == 'admins' and len(Grp('admins').members) == 1:
|
||||
return self.user(uname, '!!!Нельзя удалить единственного пользователя из группы администраторов!!!')
|
||||
grp.delmember(uname)
|
||||
return self.user(uname)
|
||||
@cherrypy.expose
|
||||
@require(member_of('admins'))
|
||||
def usrfromgrp(self, uname = '', gname = ''):
|
||||
if uname == '' or gname == '': return
|
||||
grp = Grp(gname)
|
||||
if gname == 'admins' and len(Grp('admins').members) == 1:
|
||||
return self.group(gname, '!!!Нельзя удалить единственного пользователя из группы администраторов!!!')
|
||||
grp.delmember(uname)
|
||||
return self.group(gname)
|
||||
@cherrypy.expose
|
||||
@require(member_of('admins'))
|
||||
def grptousr(self, uname ='', gname = ''):
|
||||
if uname == '' or gname == '': return
|
||||
grp = Grp(gname)
|
||||
if not grp.addmember(uname): return self.user(uname, '!!!Пользователь уже в группе "' + grp.dname + '[' + gname + ']"!!!')
|
||||
return self.user(uname)
|
||||
@cherrypy.expose
|
||||
@require(member_of('admins'))
|
||||
def usrtogrp(self, uname ='', gname = ''):
|
||||
if uname == '' or gname == '': return
|
||||
grp = Grp(gname)
|
||||
if not grp.addmember(uname): return self.group(gname, '!!!Пользователь "' + Usr(uname).dname + '[' + uname + ']"уже в этой группе!!!')
|
||||
return self.group(uname)
|
|
@ -0,0 +1,235 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from lybmods.lybformauth import member_of, any_of
|
||||
from urllib.request import FancyURLopener
|
||||
from lybmods.lybclasses import Cat
|
||||
from random import random
|
||||
from lybmods import lybshared
|
||||
import lybmods.lybhtdata as lybhtdata
|
||||
import cherrypy
|
||||
import lybmods.lybtools as lybtools
|
||||
|
||||
class URLOpener(FancyURLopener):
|
||||
version = 'Mozilla/5.0 (X11; Linux x86_64; rv:10.0.6) Gecko/20100101 Firefox/10.0.6 Iceweasel/10.0.6'
|
||||
|
||||
class Edit:
|
||||
'''Управление хранилищем'''
|
||||
_cp_config = {
|
||||
'auth.require': [any_of(member_of('admins'),member_of('editors'))]
|
||||
}
|
||||
|
||||
def __init__(self, root):
|
||||
self.root = root
|
||||
@cherrypy.expose
|
||||
def index(self):
|
||||
cherrypy.HTTPRedirect("/")
|
||||
@cherrypy.expose
|
||||
def nejs(self):
|
||||
return lybhtdata.ne_js()
|
||||
|
||||
@cherrypy.expose
|
||||
def negif(self):
|
||||
response = cherrypy.response
|
||||
response.headers['Content-Type'] = 'image/gif'
|
||||
return lybhtdata.ne_gif()
|
||||
@cherrypy.expose
|
||||
def upl(self, catid = 0):
|
||||
catid = int(catid)
|
||||
cat = Cat(catid)
|
||||
catname = cat.name
|
||||
return self.root.buildhtml('Архив [Загрузка документа в архив]', lybhtdata.form_upload.format(catid = catid, catname = catname) + '<a href="/category?catid=' + str(catid) + '">\n<i>← Обратно в раздел "' + catname + '"</i>\n</a>\n')
|
||||
@cherrypy.expose
|
||||
def upload(self, catid = 0, filein=''):
|
||||
if catid: catid = int(catid)
|
||||
url = filein
|
||||
try:
|
||||
res = URLOpener().open(url)
|
||||
except:
|
||||
cat = Cat(catid)
|
||||
catname = cat.name
|
||||
return self.root.buildhtml('Архив [Загрузка документа в архив]', lybhtdata.form_upload.format(catid = catid, catname = catname) + '<div class="document" style="color: red; ">Ошибка загрузки документа</div><div><a href="/category?catid=' + str(catid) + '">\n<i>← Обратно в раздел "' + catname + '"</i>\n</a>\n</div>')
|
||||
return self.root.buildhtml('Архив [Обработка файла закончена]', self.fileproc(catid, res.url, lybtools.ctype(res.headers['Content-Type']), res.read()))
|
||||
@cherrypy.expose
|
||||
def tmpstore(self, lybsrcobj=None):
|
||||
sess = cherrypy.session
|
||||
|
||||
cherrypy.response.headers["Content-Type"] = sess[lybsrcobj]['type']
|
||||
res = sess[lybsrcobj]['body']
|
||||
try:
|
||||
return res
|
||||
except:
|
||||
pass
|
||||
def fileproc(self, catid, url, ctype, htfile):
|
||||
if ctype == 'text/html':
|
||||
return self.html(catid, url, htfile)
|
||||
if ctype == 'text/plain':
|
||||
htxt = self.txt(htfile)
|
||||
return self.html(catid, url, htxt)
|
||||
|
||||
def txt(self, text):
|
||||
text = "".join(lybtools.edit_esc.get(c,c) for c in text)
|
||||
return text.replace('\n', '<br />\n')
|
||||
def html(self, catid, url, htfile, md = None, sub = False, ins = False):
|
||||
return lybshared.html(self, catid, url, htfile, md, sub, ins)
|
||||
def ne(self, catid, url = None, html = None, md = None, docname = "Новый документ"):
|
||||
return lybshared.ne(self, catid, url, html, md, docname)
|
||||
@cherrypy.expose
|
||||
def newcat(self, catid = 0, catname = None):
|
||||
catid = int(catid)
|
||||
category = Cat(catid)
|
||||
if not catname or catname == '':
|
||||
return self.root.buildhtml('Архив[Ошибка создания раздела]', '<p>Имя раздела не должно быть пустым</p>\n<div align="center"><a href="/category?catid=' + str(category.id) + '">\n<i>← Обратно в раздел "' + category.name + '"</i>\n</a>\n</div>')
|
||||
catname = catname.strip()
|
||||
if category.newcat(catname):
|
||||
return self.root.category(catid = catid)
|
||||
else:
|
||||
return self.root.buildhtml('Архив[Ошибка создания раздела]', '<p>Ошибка создания раздела "' + catname + '"</p>\n<div align="center"><a href="/category?catid=' + str(category.id) + '">\n<i>← Обратно в раздел "' + category.name + '"</i>\n</a>\n</div>')
|
||||
@cherrypy.expose
|
||||
def catrename(self, catid = None, catname = None):
|
||||
if catid: catid = int(catid)
|
||||
if not catname: return self.catedit(submit = 'Переименовать', catid = catid, err = '!!!Пустое имя раздела!!!')
|
||||
catname = catname.strip()
|
||||
cat = Cat(catid)
|
||||
parent = cat.parent
|
||||
for subc in parent.categories:
|
||||
if subc.name == catname: return self.catedit(submit = 'Переименовать', catid = catid, err = '!!!В разделе "' + parent.name + '" есть подраздел с именем "' + catname + '"!!!')
|
||||
if catname == cat.name:
|
||||
return self.catedit(submit = 'Переименовать', catid = catid, err = '!!!Исходное имя равно новому!!!')
|
||||
cat.setname(catname)
|
||||
return self.root.category(catid = parent.id)
|
||||
@cherrypy.expose
|
||||
def catdelete(self, catid = None):
|
||||
if catid: catid = int(catid)
|
||||
cat = Cat(catid)
|
||||
parent = cat.parent
|
||||
cat.delete()
|
||||
return self.root.category(catid = parent.id)
|
||||
@cherrypy.expose
|
||||
def catmove(self, catid = None, toid = None):
|
||||
if not catid: return
|
||||
if not toid: return self.catedit(submit = 'Перенести', catid = catid, err = '!!!Не выбран раздел!!!')
|
||||
catid = int(catid)
|
||||
toid = int(toid)
|
||||
cat = Cat(catid)
|
||||
tocat = Cat(toid)
|
||||
if catid == toid: return self.catedit(submit = 'Перенести', catid = catid, err = '!!!Нельзя перенести себя в себя!!!')
|
||||
if toid == cat.parent.id: return self.catedit(submit = 'Перенести', catid = catid, err = '!!!Раздел уже в этом месте!!!')
|
||||
if cat.name in [x.name for x in tocat.categories]: return self.catedit(submit = 'Перенести', catid = catid, err = '!!!В разделе "' + cat.parent.name + '" уже есть подраздел с таким именем!!!')
|
||||
cat.setparentid(toid)
|
||||
return self.root.category(catid = cat.parent.id)
|
||||
@cherrypy.expose
|
||||
def catedit(self, submit = None, catid = None, err = ''):
|
||||
if submit and catid:
|
||||
catid = int(catid)
|
||||
cat = Cat(catid)
|
||||
catname = cat.name
|
||||
parent = cat.parent
|
||||
if submit == 'Переименовать':
|
||||
html = '<div align="center"><form action="/edit/catrename" method="post"><input type="hidden" name="catid" value=' + str(catid) + '>Сменить имя раздела "' + catname + '" на <input type="text" name="catname" value="' + catname + '"><input type="submit" value="Готово"></form></div><div align="center"><a href="/category?catid=' + str(parent.id) + '"><i>← Обратно в раздел "' + parent.name + '"</i></a></div>'
|
||||
title, document = ('Архив[Переименовать раздел "' + catname + '"]' + err, html)
|
||||
elif submit == 'Перенести':
|
||||
l = '<select name="toid">\n{lbody}</select>\n'
|
||||
lo = '<option value={id}>{name}</option>\n'
|
||||
lopts = ''
|
||||
def lgen(lopts, mod = '', cid = 0):
|
||||
c = Cat(cid)
|
||||
lopts += lo.format(id = cid, name = mod + c.name)
|
||||
for subcat in c.categories:
|
||||
if subcat.id == catid: continue
|
||||
lopts = lgen(lopts, mod = mod + '...', cid = subcat.id)
|
||||
return lopts
|
||||
lopts = lgen(lopts)
|
||||
sel = l.format(lbody = lopts)
|
||||
html = '<div align="center"><form action="/edit/catmove" method="post"><input type="hidden" name="catid" value=' + str(catid) + '>Переместить раздел "' + catname + '" в\n{sel}<input type="submit" value="Готово"></form></div><div align="center"><a href="/category?catid='.format(sel = sel) + str(parent.id) + '"><i>← Обратно в раздел "' + parent.name + '"</i></a></div>'
|
||||
title, document = ('Архив[Переместить раздел "' + catname + '"]' + err, html)
|
||||
elif submit == 'Удалить':
|
||||
html = '<div align="center"><form action="/edit/catdelete" method="post"><input type="hidden" name="catid" value="' + str(catid) + '">Действительно удалить раздел "' + catname + '"?<br>Все хранящиеся в нём подразделы и документы будут перенесены в родительский раздел.<br><input type="submit" value="Удалить"></form><div align="center"><a href="/category?catid=' + str(parent.id) + '"><i>← Обратно в раздел "' + parent.name + '"</i></a></div>'
|
||||
title, document = ('Архив[Удалить раздел "' + catname + '"]', html)
|
||||
return self.root.buildhtml(title, document)
|
||||
@cherrypy.expose
|
||||
def insert_doc(self, catid = 0, url = None, html = None, doc_name = '', md = None):
|
||||
return lybshared.insert_doc(self, catid, url, html, doc_name, md)
|
||||
@cherrypy.expose
|
||||
def docedit(self, catid = None, doc = None, submit = None, err = ''):
|
||||
if catid: catid = int(catid)
|
||||
if doc: doc = int(doc)
|
||||
if not doc or not submit: return
|
||||
cat = Cat(catid)
|
||||
doco = cat[doc]
|
||||
catname = cat.name
|
||||
docname = doco.name
|
||||
if submit == 'Редактировать':
|
||||
return self.root.buildhtml('Архив[Редактирование документа "' + docname + '"]', self.html(catid, '/', self.root.get_doc(doc=doc, catid=catid, plain=True), md = str(doc)))
|
||||
if submit == 'Переименовать':
|
||||
html = '<div align="center">\n<form action="/edit/docrename" method="post">\n<input type="hidden" name="catid" value=' + str(catid) + '>\n<input type="hidden" name="doc" value=' + str(doc) + '>\nСменить имя документа "' + docname + '" на <input type="text" name="doc_name" value="' + docname + '">\n<input type="submit" value="Готово">\n</form>\n</div>\n<div align="center">\n<a href="/category?catid=' + str(catid) + '">\n<i>← Обратно в раздел "' + catname + '"</i>\n</a>\n</div>'
|
||||
title, document = ('Архив[Переименовать документ "' + doco.name + '"]' + err, html)
|
||||
elif submit == 'Удалить':
|
||||
shtml = '<div align="center">\nУдалить документ "' + docname + '"?\n<form action="/edit/docdelete" method="post">\n<input type="hidden" name="catid" value=' + str(catid) + '>\n<input type="hidden" name="doc" value="' + str(doc) + '">\n<input type="submit" value="Удалить документ">\n</form>\n<br>\n<a href="/category?catid=' + str(catid) + '">\n<i>← Обратно в раздел "' + catname + '"</i>\n</a>\n</div>'
|
||||
title, document = ('Архив[Удалить Документ "' + doco.name + '"]' + err, shtml)
|
||||
elif submit == 'Перенести':
|
||||
if len(Cat(0).categories) == 0:
|
||||
shtml = '<div align="center">Других разделов нет\n<br><a href="/category?catid=' + str(catid) + '"><i>← Обратно в раздел "' + catname + '"</i></a></div>'
|
||||
else:
|
||||
l = '<select name="toid">\n{lbody}</select>\n'
|
||||
lo = '<option value={id}>{name}</option>\n'
|
||||
lopts = ''
|
||||
def lgen(lopts, mod = '', cid = 0):
|
||||
c = Cat(cid)
|
||||
lopts += lo.format(id = cid, name = mod + c.name)
|
||||
for subcat in c.categories:
|
||||
lopts = lgen(lopts, mod = mod + '...', cid = subcat.id)
|
||||
return lopts
|
||||
lopts = lgen(lopts)
|
||||
sel = l.format(lbody = lopts)
|
||||
shtml = '<div align="center">Перенести документ "' + docname + '"<form action="/edit/docmove" method="post">\n<input type="hidden" name="catid" value=' + str(catid) + '><input type="hidden" name="doc" value="' + str(doc) + '">в категорию ' + sel + ' ?<br><br><input type="submit" value="Перенести"></form>\n<br><a href="/category?catid=' + str(catid) + '"><i>← Обратно в раздел "' + catname + '"</i></a></div>'
|
||||
title, document = ('Архив[Перенос документов]' + err, shtml)
|
||||
return self.root.buildhtml(title, document)
|
||||
@cherrypy.expose
|
||||
def docdelete(self, catid = None, doc = None):
|
||||
if not catid or not doc: return
|
||||
catid = int(catid)
|
||||
doc = int(doc)
|
||||
cat = Cat(catid)
|
||||
try:
|
||||
del cat[doc]
|
||||
except:
|
||||
doco = cat[doc]
|
||||
docname = doco.name
|
||||
return self.root.buildhtml('Архив[Документ "' + docname + '" не удалён]', '<div align="center">Документ "' + docname + '" не удалён.<br><a href="/category?catid=' + str(catid) + '"><i>← Обратно в раздел "' + cat.name + '"</i></a></div>')
|
||||
return self.root.category(catid = catid)
|
||||
@cherrypy.expose
|
||||
def docrename(self, catid = None, doc = None, doc_name = None):
|
||||
if catid: catid = int(catid)
|
||||
if not doc_name or not doc: return self.docedit(submit = 'Переименовать', catid = catid, doc = doc, err = '!!!Пустое имя документа!!!')
|
||||
doc = int(doc)
|
||||
doc_name = doc_name.strip()
|
||||
cat = Cat(catid)
|
||||
doco = cat[doc]
|
||||
if doc_name == doco.name:
|
||||
return self.docedit(submit = 'Переименовать', catid = catid, doc = doc, err = '!!!Исходное имя равно новому!!!')
|
||||
for docs in cat.documents:
|
||||
if docs.name == doc_name: return self.docedit(submit = 'Переименовать', catid = catid, doc = doc, err = '!!!В разделе "' + cat.name + '" есть документ с именем "' + doc_name + '"!!!')
|
||||
doco.setname(doc_name)
|
||||
return self.root.category(catid = catid)
|
||||
@cherrypy.expose
|
||||
def newdoc(self, catid = 0):
|
||||
url = 'http://new.doc/' + (str(random() * int(random() * 10)) + str(random() * int(random() * 10)) + str(random() * int(random() * 10))).replace('.', '')
|
||||
return self.root.buildhtml('Архив[Новый документ]', self.fileproc(catid, url, 'text/html', '<body><br></body>'))
|
||||
@cherrypy.expose
|
||||
def docmove(self, catid = None, doc = None, toid = None):
|
||||
if not catid or not doc: return
|
||||
if not toid: return self.docedit(submit = 'Перенести', catid = catid, doc = doc, err = '!!!Не выбран раздел!!!')
|
||||
catid = int(catid)
|
||||
doc = int(doc)
|
||||
toid = int(toid)
|
||||
cat = Cat(catid)
|
||||
tocat = Cat(toid)
|
||||
doco = cat[doc]
|
||||
catname = cat.name
|
||||
tocatname = tocat.name
|
||||
docname = doco.name
|
||||
if catid == toid: return self.docedit(submit = 'Перенести', catid = catid, doc = doc, err = '!!!Документ "' + docname + '" уже в разделе "' + catname + '"!!!')
|
||||
if toid == catid: return self.docedit(submit = 'Перенести', catid = catid, doc = doc, err = '!!!Раздел уже в этом месте!!!')
|
||||
if doc in list(tocat.keys()): return self.docedit(submit = 'Перенести', catid = catid, doc = doc, err = '!!!В разделе "' + tocatname + '" уже есть документ с таким содержимым!!!')
|
||||
if tocat.docidbyname(doco.name): return self.docedit(submit = 'Перенести', catid = catid, doc = doc, err = '!!!В разделе "' + tocatname + '" уже есть документ с именем"' + docname + '"!!!')
|
||||
doco.setcatid(toid)
|
||||
return self.root.category(catid = catid)
|
|
@ -0,0 +1,138 @@
|
|||
import cherrypy
|
||||
import hashlib
|
||||
import urllib.parse
|
||||
import lybmods.lybtools as lybtools
|
||||
import lybmods.lybpqconn as lybpqconn
|
||||
from lybmods.lybclasses import Grp
|
||||
|
||||
def check_credentials(username, password):
|
||||
"""Проверяет имя пользователи и пароль.
|
||||
Возвращает None при успехе иначе строку с описанием ошибки"""
|
||||
cur = lybpqconn.conn.cursor()
|
||||
newhash = hashlib.sha1()
|
||||
newhash.update(username.encode("utf-8"))
|
||||
newhash.update(password.encode("utf-8"))
|
||||
cur.execute(lybtools.qChkUserAndPwd, (username, newhash.hexdigest()))
|
||||
res = cur.fetchone()[0]
|
||||
if res > 0:
|
||||
return None
|
||||
else:
|
||||
return "Incorrect username or password."
|
||||
|
||||
def check_auth(*args, **kwargs):
|
||||
"""A tool that looks in config for 'auth.require'. If found and it
|
||||
is not None, a login is required and the entry is evaluated as alist of
|
||||
conditions that the user must fulfill"""
|
||||
conditions = cherrypy.request.config.get('auth.require', None)
|
||||
# format GET params
|
||||
get_parmas = urllib.parse.quote(cherrypy.request.request_line.split()[1])
|
||||
if conditions is not None:
|
||||
username = cherrypy.session.get(lybtools.SESSION_KEY)
|
||||
if username:
|
||||
cherrypy.request.login = username
|
||||
for condition in conditions:
|
||||
# A condition is just a callable that returns true orfalse
|
||||
if not condition():
|
||||
# Send old page as from_page parameter
|
||||
raise cherrypy.HTTPRedirect("/denied")
|
||||
else:
|
||||
# Send old page as from_page parameter
|
||||
raise cherrypy.HTTPRedirect("/loginpage?from_page=%s" % get_parmas)
|
||||
|
||||
#cherrypy.lybtools.auth = cherrypy.Tool('before_handler', check_auth)
|
||||
|
||||
def require(*conditions):
|
||||
"""A decorator that appends conditions to the auth.require config
|
||||
variable."""
|
||||
def decorate(f):
|
||||
if not hasattr(f, '_cp_config'):
|
||||
f._cp_config = dict()
|
||||
if 'auth.require' not in f._cp_config:
|
||||
f._cp_config['auth.require'] = []
|
||||
f._cp_config['auth.require'].extend(conditions)
|
||||
return f
|
||||
return decorate
|
||||
|
||||
|
||||
# Conditions are callables that return True
|
||||
# if the user fulfills the conditions they define, False otherwise
|
||||
#
|
||||
# They can access the current username as cherrypy.request.login
|
||||
#
|
||||
# Define those at will however suits the application.
|
||||
|
||||
def member_of(groupname):
|
||||
def check():
|
||||
username = cherrypy.session.get(lybtools.SESSION_KEY, None)
|
||||
try:
|
||||
if username and username in [x.name for x in Grp(groupname).members]:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
except KeyError:
|
||||
return False
|
||||
return check
|
||||
|
||||
def name_is(reqd_username):
|
||||
return lambda: reqd_username == cherrypy.session.get(lybtools.SESSION_KEY, None)
|
||||
|
||||
# These might be handy
|
||||
|
||||
def any_of(*conditions):
|
||||
"""Returns True if any of the conditions match"""
|
||||
def check():
|
||||
for c in conditions:
|
||||
if c():
|
||||
return True
|
||||
return False
|
||||
return check
|
||||
|
||||
# By default all conditions are required, but this might still be
|
||||
# needed if you want to use it inside of an any_of(...) condition
|
||||
def all_of(*conditions):
|
||||
"""Returns True if all of the conditions match"""
|
||||
def check():
|
||||
for c in conditions:
|
||||
if not c():
|
||||
return False
|
||||
return True
|
||||
return check
|
||||
|
||||
|
||||
# Controller to provide login and logout actions
|
||||
|
||||
class AuthController(object):
|
||||
|
||||
def on_login(self, username):
|
||||
"""Called on successful login"""
|
||||
|
||||
def on_logout(self, username):
|
||||
"""Called on logout"""
|
||||
|
||||
@cherrypy.expose
|
||||
def login(self, username=None, password=None, from_page="/"):
|
||||
if username is None or password is None:
|
||||
raise cherrypy.HTTPRedirect("/")
|
||||
|
||||
error_msg = check_credentials(username, password)
|
||||
if error_msg:
|
||||
raise cherrypy.HTTPRedirect("/loginpage?from_page=" + from_page)
|
||||
else:
|
||||
cherrypy.session.regenerate()
|
||||
cherrypy.session[lybtools.SESSION_KEY] = cherrypy.request.login = username
|
||||
self.on_login(username)
|
||||
raise cherrypy.HTTPRedirect(from_page or "/")
|
||||
|
||||
@cherrypy.expose
|
||||
def logout(self, from_page="/"):
|
||||
sess = cherrypy.session
|
||||
username = sess.get(lybtools.SESSION_KEY, None)
|
||||
# for key in sess.keys():
|
||||
# del sess[key]
|
||||
# sess[lybtools.SESSION_KEY] = None
|
||||
sess.regenerate()
|
||||
sess.delete()
|
||||
if username:
|
||||
cherrypy.request.login = None
|
||||
self.on_logout(username)
|
||||
raise cherrypy.HTTPRedirect("/")
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,32 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
import psycopg2
|
||||
import psycopg2.extensions
|
||||
import lybmods.lybcfg as lybcfg
|
||||
import lybmods.lybtools as lybtools
|
||||
|
||||
psycopg2.extensions.register_type(psycopg2.extensions.UNICODE)
|
||||
psycopg2.extensions.register_type(psycopg2.extensions.UNICODEARRAY)
|
||||
conn = psycopg2.connect(database=lybcfg.dbname, user=lybcfg.dbuser, password=lybcfg.dbpass, host=lybcfg.dbhost)
|
||||
conn.set_isolation_level(psycopg2.extensions.ISOLATION_LEVEL_AUTOCOMMIT)
|
||||
|
||||
def create_schema():
|
||||
cur = conn.cursor()
|
||||
d = {
|
||||
lybcfg.pwd_table_name: lybtools.AUTH_SCHEMA,
|
||||
lybcfg.sess_table_name: lybtools.SESS_SCHEMA,
|
||||
lybcfg.cat_table_name: lybtools.CAT_SCHEMA,
|
||||
lybcfg.doc_table_name: lybtools.DOC_SCHEMA,
|
||||
lybcfg.bin_table_name: lybtools.BIN_SCHEMA,
|
||||
lybcfg.docbin_table_name: lybtools.DOCBIN_SCHEMA,
|
||||
lybcfg.grpcat_access_table: lybtools.GRPCAT_ACCESS_SCHEMA,
|
||||
lybcfg.grpdoc_access_table: lybtools.GRPDOC_ACCESS_SCHEMA,
|
||||
lybcfg.pwdcat_access_table: lybtools.PWDCAT_ACCESS_SCHEMA,
|
||||
lybcfg.pwddoc_access_table: lybtools.PWDDOC_ACCESS_SCHEMA
|
||||
}
|
||||
for k in d.keys():
|
||||
try:
|
||||
cur.execute('SELECT COUNT(*) FROM %s' % k)
|
||||
except:
|
||||
cur.execute(d[k])
|
||||
conn.commit()
|
||||
|
|
@ -0,0 +1,248 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
import cherrypy
|
||||
import logging
|
||||
import threading
|
||||
import psycopg2
|
||||
import lybmods.lybcfg as lybcfg
|
||||
import pickle as pickle
|
||||
import lybmods.lybtools as lybtools
|
||||
psycopg2.extensions.register_type(psycopg2.extensions.UNICODE)
|
||||
psycopg2.extensions.register_type(psycopg2.extensions.UNICODEARRAY)
|
||||
|
||||
logger = logging.getLogger('Session')
|
||||
|
||||
class PgsqlSession(cherrypy.lib.sessions.Session):
|
||||
sess_table_name = lybcfg.sess_table_name
|
||||
sess_data_table_name = lybcfg.sess_data_table_name
|
||||
connect_arguments = "dbname={0} user={1} password={2} host={3}".format(lybcfg.dbname, lybcfg.dbuser, lybcfg.dbpass, lybcfg.dbhost)
|
||||
|
||||
missing = False
|
||||
"True if the session requested by the client did not exist."
|
||||
|
||||
_database = None
|
||||
|
||||
def __init__(self, sid=None, **kwargs):
|
||||
logger.debug('Initializing PgsqlSession with %r' % kwargs)
|
||||
for k, v in list(kwargs.items()):
|
||||
setattr(PgsqlSession, k, v)
|
||||
self.db = self.get_db()
|
||||
self.cursor = self.db.cursor()
|
||||
super(PgsqlSession, self).__init__(sid, **kwargs)
|
||||
|
||||
@classmethod
|
||||
def get_db(cls):
|
||||
##
|
||||
## Use thread-local connections
|
||||
local = threading.local()
|
||||
if hasattr(local, 'db'):
|
||||
return local.db
|
||||
else:
|
||||
logger.debug("Connecting to %r" % cls.connect_arguments)
|
||||
db = psycopg2.connect(cls.connect_arguments)
|
||||
local.db = db
|
||||
|
||||
return db
|
||||
|
||||
def load(self):
|
||||
"""Copy stored session data into this session instance."""
|
||||
exptime = self._load()
|
||||
# data is either None or a tuple (session_data, expiration_time)
|
||||
if exptime is None or exptime < self.now().utcnow():
|
||||
if self.debug:
|
||||
cherrypy.log('Expired session, flushing data', 'TOOLS.SESSIONS')
|
||||
self.regenerate()
|
||||
self.loaded = True
|
||||
|
||||
# Stick the clean_thread in the class, not the instance.
|
||||
# The instances are created and destroyed per-request.
|
||||
cls = self.__class__
|
||||
if self.clean_freq and not cls.clean_thread:
|
||||
# clean_up is in instancemethod and not a classmethod,
|
||||
# so that tool config can be accessed inside the method.
|
||||
t = cherrypy.process.plugins.Monitor(
|
||||
cherrypy.engine, self.clean_up, self.clean_freq * 60,
|
||||
name='Session cleanup')
|
||||
t.subscribe()
|
||||
cls.clean_thread = t
|
||||
t.start()
|
||||
|
||||
def _load(self):
|
||||
logger.debug('_load %r' % self)
|
||||
# Select session data from table
|
||||
self.cursor.execute('select expiration_time from %s '
|
||||
'where id = %%s' % PgsqlSession.sess_table_name, (self.id,))
|
||||
row = self.cursor.fetchone()
|
||||
if row:
|
||||
expiration_time = row[0].utcfromtimestamp(row[0].timestamp())
|
||||
return expiration_time
|
||||
else:
|
||||
return None
|
||||
|
||||
def _save(self, expiration_time):
|
||||
logger.debug('_save %r' % self)
|
||||
self.cursor.execute('select count(*) from %s where id = %%s and expiration_time > now()' % PgsqlSession.sess_table_name, (self.id,))
|
||||
(count,) = self.cursor.fetchone()
|
||||
if count:
|
||||
self.cursor.execute('update %s set expiration_time = %%s where id = %%s' % PgsqlSession.sess_table_name,
|
||||
(expiration_time, self.id))
|
||||
else:
|
||||
self.cursor.execute('insert into %s (expiration_time, id) values (%%s, %%s)' % PgsqlSession.sess_table_name,
|
||||
(expiration_time, self.id))
|
||||
self.db.commit()
|
||||
|
||||
def acquire_lock(self):
|
||||
logger.debug('acquire_lock %r' % self)
|
||||
self.locked = True
|
||||
self.cursor.execute('select id from %s where id = %%s for update' % PgsqlSession.sess_table_name,
|
||||
(self.id,))
|
||||
self.db.commit()
|
||||
|
||||
def release_lock(self):
|
||||
logger.debug('release_lock %r' % self)
|
||||
self.locked = False
|
||||
self.db.commit()
|
||||
|
||||
def clean_up(self):
|
||||
logger.debug('clean_up %r' % self)
|
||||
|
||||
self.cursor.execute('DELETE FROM %s WHERE expiration_time < now()' % PgsqlSession.sess_table_name)
|
||||
self.db.commit()
|
||||
|
||||
def _delete(self):
|
||||
logger.debug('_delete %r' % self)
|
||||
self.cursor.execute('DELETE FROM %s WHERE id=%%s' % PgsqlSession.sess_table_name, (self.id,))
|
||||
self.db.commit()
|
||||
|
||||
|
||||
def _exists(self):
|
||||
# Select session data from table
|
||||
self.cursor.execute('select count(*) from %s '
|
||||
'where id = %%s and expiration_time > now()' % PgsqlSession.sess_table_name, (self.id,))
|
||||
(count,) = self.cursor.fetchone()
|
||||
logger.debug('_exists %r (%r)' % (self, bool(count)))
|
||||
return bool(count)
|
||||
|
||||
def __getitem__(self, key):
|
||||
if not self.loaded: self.load()
|
||||
self.cursor.execute('SELECT value FROM %s WHERE key=%%s AND sid=%%s;' % PgsqlSession.sess_data_table_name, (key, self.id))
|
||||
try:
|
||||
res = self.cursor.fetchall()[0][0]
|
||||
val = pickle.loads(res)
|
||||
return val
|
||||
except:
|
||||
raise KeyError(key)
|
||||
|
||||
def __setitem__(self, key, value):
|
||||
if not self.loaded: self.load()
|
||||
self.cursor.execute('SELECT count(*) FROM %s WHERE key = %%s AND sid = %%s;' % PgsqlSession.sess_data_table_name, (key, self.id))
|
||||
count = self.cursor.fetchone()[0]
|
||||
if count:
|
||||
self.cursor.execute('UPDATE %s SET value = %%s WHERE key = %%s AND sid = %%s;' % PgsqlSession.sess_data_table_name,
|
||||
(pickle.dumps(value), key, self.id))
|
||||
else:
|
||||
self.cursor.execute('INSERT INTO %s (value, key, sid) VALUES (%%s, %%s, %%s);' % PgsqlSession.sess_data_table_name,
|
||||
(pickle.dumps(value), key, self.id))
|
||||
self.db.commit()
|
||||
def __delitem__(self, key):
|
||||
if not self.loaded: self.load()
|
||||
self.cursor.execute('DELETE FROM %s WHERE key = %%s AND sid = %%s;' % PgsqlSession.sess_data_table_name, (key, self.id))
|
||||
self.db.commit()
|
||||
def pop(self, key, default=None):
|
||||
"""Remove the specified key and return the corresponding value.
|
||||
If key is not found, default is returned if given,
|
||||
otherwise KeyError is raised.
|
||||
"""
|
||||
if not self.loaded: self.load()
|
||||
try:
|
||||
val = self[key]
|
||||
except:
|
||||
if default is None:
|
||||
raise KeyError(key)
|
||||
else:
|
||||
val = default
|
||||
return val
|
||||
del self[key]
|
||||
return val
|
||||
|
||||
def __contains__(self, key):
|
||||
if not self.loaded: self.load()
|
||||
self.cursor.execute('SELECT count(*) FROM %s WHERE key = %%s AND sid = %%s;' % PgsqlSession.sess_data_table_name, (key, self.id))
|
||||
return bool(self.cursor.fetchone()[0])
|
||||
|
||||
if hasattr({}, 'has_key'):
|
||||
def has_key(self, key):
|
||||
"""D.has_key(k) -> True if D has a key k, else False."""
|
||||
if not self.loaded: self.load()
|
||||
return self.__contains__(key)
|
||||
|
||||
def get(self, key, default=None):
|
||||
"""D.get(k[,d]) -> D[k] if k in D, else d. d defaults to None."""
|
||||
if not self.loaded: self.load()
|
||||
try:
|
||||
val = self[key]
|
||||
return val
|
||||
except:
|
||||
return default
|
||||
|
||||
def update(self, d):
|
||||
"""D.update(E) -> None. Update D from E: for k in E: D[k] = E[k]."""
|
||||
if not self.loaded: self.load()
|
||||
for k in d:
|
||||
self[k] = d[k]
|
||||
|
||||
def setdefault(self, key, default=None):
|
||||
"""D.setdefault(k[,d]) -> D.get(k,d), also set D[k]=d if k not in D."""
|
||||
if not self.loaded: self.load()
|
||||
try:
|
||||
val = self[key]
|
||||
except:
|
||||
self[key] = val = default
|
||||
return val
|
||||
|
||||
def clear(self):
|
||||
"""D.clear() -> None. Remove all items from D."""
|
||||
if not self.loaded: self.load()
|
||||
self.cursor.execute('DELETE FROM %s WHERE sid=%%s AND key != %%s;' % PgsqlSession.sess_data_table_name, (self.id, lybtools.SESSION_KEY))
|
||||
self.db.commit()
|
||||
|
||||
def keys(self):
|
||||
"""D.keys() -> list of D's keys."""
|
||||
if not self.loaded: self.load()
|
||||
k = []
|
||||
self.cursor.execute('SELECT key FROM %s WHERE sid = %%s;' % PgsqlSession.sess_data_table_name, (self.id,))
|
||||
res = self.cursor.fetchall()
|
||||
if res != []:
|
||||
for i in res:
|
||||
k.append(i[0])
|
||||
return k
|
||||
|
||||
def items(self):
|
||||
"""D.items() -> list of D's (key, value) pairs, as 2-tuples."""
|
||||
if not self.loaded: self.load()
|
||||
i = []
|
||||
self.cursor.execute('SELECT key, value FROM %s WHERE sid = %%s;' % PgsqlSession.sess_data_table_name, (self.id,))
|
||||
res = self.cursor.fetchall()
|
||||
if res != []:
|
||||
for k, v in res:
|
||||
i.append({k, pickle.loads(v)})
|
||||
return i
|
||||
|
||||
def values(self):
|
||||
"""D.values() -> list of D's values."""
|
||||
if not self.loaded: self.load()
|
||||
v = []
|
||||
self.cursor.execute('SELECT value FROM %s WHERE sid = %%s;' % PgsqlSession.sess_data_table_name, (self.id,))
|
||||
res = self.cursor.fetchall()
|
||||
if res != []:
|
||||
for i in res:
|
||||
v.append(pickle.loads(i[0]))
|
||||
return v
|
||||
|
||||
def __del__(self):
|
||||
logger.debug('__del__ %r' % self)
|
||||
self.db.commit()
|
||||
self.db.close()
|
||||
self.db = None
|
||||
|
||||
def __repr__(self):
|
||||
return '<PgsqlSession %r>' % (self.id,)
|
|
@ -0,0 +1,151 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from time import tzname
|
||||
from lybmods.lybformauth import AuthController, member_of, any_of
|
||||
from lybmods.lybclasses import Doc, Cat
|
||||
import cherrypy
|
||||
from lybmods import lybtools
|
||||
from lybmods import lybhtdata
|
||||
from lybmods import lybedit
|
||||
from lybmods import lybctl
|
||||
|
||||
class Root:
|
||||
|
||||
_cp_config = {
|
||||
'tools.sessions.on': True,
|
||||
'tools.sessions.storage_type' : 'pgsql',
|
||||
'tools.sessions.name' : 'PGSQLSes',
|
||||
'tools.sessions.timeout': 120,
|
||||
'tools.auth.on': True
|
||||
}
|
||||
auth = AuthController()
|
||||
mdict = lybtools.mdict
|
||||
from_page = '/'
|
||||
def __init__(self):
|
||||
self.edit = lybedit.Edit(self)
|
||||
self.ctl = lybctl.Ctl(self)
|
||||
@cherrypy.expose
|
||||
def index(self):
|
||||
self.from_page = '/'
|
||||
return self.buildhtml('Архив', lybhtdata.index_html)
|
||||
@cherrypy.expose
|
||||
def css(self):
|
||||
return lybhtdata.style
|
||||
@cherrypy.expose
|
||||
def poisk(self, search = None, catid = 0):
|
||||
if not search or search == '':
|
||||
cherrypy.HTTPRedirect("/")
|
||||
search.replace('<', '').replace('>', '').replace(';', '').replace(',', '')
|
||||
html_cont = '<div align="left">\n<table>\n{html}\n</table></div>'
|
||||
html = ''
|
||||
cat = Cat(0)
|
||||
res = cat.search(search)
|
||||
html += '<tr><td><h1>Найдено ' + str(len(res)) + ' документов</h1></td></tr>'
|
||||
for did in res:
|
||||
doc = Doc(did)
|
||||
catid = doc.cat.id
|
||||
html += '<tr><td><a href="/get_doc?catid=' + str(catid) + '&doc=' + str(did) + '">' + doc.name + '</a></td>\n<td>(' + self.path(did, doc = True) + ')</td></tr>\n'
|
||||
return self.buildhtml('Архив[Запрос: ' + search + ']', html_cont.format(html=html))
|
||||
|
||||
@cherrypy.expose
|
||||
def loginpage(self, from_page='/'):
|
||||
self.from_page = from_page.replace('<', '').replace('>', '').replace(';', '').replace(',', '')
|
||||
username = cherrypy.session.get(lybtools.SESSION_KEY, None)
|
||||
if username:
|
||||
raise cherrypy.HTTPRedirect("/")
|
||||
else:
|
||||
return self.buildhtml('Архив [Получение доступа]', lybhtdata.login_body)
|
||||
@cherrypy.expose
|
||||
def denied(self):
|
||||
return self.buildhtml('Архив [Доступ закрыт]', lybhtdata.access_denied_body)
|
||||
def path(self, oid, doc = False, lcat = False):
|
||||
if doc:
|
||||
p = Doc(oid).path
|
||||
else:
|
||||
p = Cat(oid).path
|
||||
html = ''
|
||||
for i in p:
|
||||
name = Cat(i).name
|
||||
if len(name) > 15: name = name[:15] + '...'
|
||||
if i > 0: q = '»'
|
||||
else: q = ''
|
||||
html += q + '<a href="/category?catid=' + str(i) + '" title="' + Cat(i).name + '"><small><i><b>[' + name + ']</b></i></small></a>'
|
||||
if p == []: q = ''
|
||||
else: q = '»'
|
||||
if not doc and not lcat: html += q + '<small><i><b>' + Cat(oid).name + '</b></i></small>'
|
||||
if lcat: html += q + '<a href="/category?catid=' + str(oid) + '"><small><i><b>[' + Cat(oid).name + ']</b></i></small></a>'
|
||||
return html
|
||||
@cherrypy.expose
|
||||
def category(self, catid = 0):
|
||||
catid = int(catid)
|
||||
category = Cat(catid)
|
||||
html = '<div align="left">' + self.path(catid) + '</div><div align="center">\n<table>\n'
|
||||
if category.catcount: html += '<tr><td><h2>Подразделы:</h2></td>\n'
|
||||
for cat in category.categories:
|
||||
rec = '<td><b>[<a href="/category?catid=' + str(cat.id) + '" title="Подразделов: ' + str(cat.catcount) + '/Документов: ' + str(cat.doccount) + '">' + cat.name + '</a>]</b></td>\n'
|
||||
if any_of(member_of('admins'), member_of('editors'))():
|
||||
html += '<tr><form action="/edit/catedit" method="post">\n{rec}<input type="hidden" name="catid" value="'.format(rec = rec) + str(cat.id) + '">\n<td><input type="submit" name="submit" value="Переименовать"></td>\n<td><input type="submit" name="submit" value="Перенести"></td>\n<td><input type="submit" name="submit" value="Удалить"></td>\n</form></tr>\n'
|
||||
else:
|
||||
html += '<tr>{rec}</tr>'.format(rec = rec)
|
||||
if category.catcount and category.doccount: html += '<tr><td>***</td><td>***</td><td>***</td><td>***</td></tr>\n'
|
||||
if category.doccount: html += '<tr><td><h2>Документы:</h2></td>\n'
|
||||
for doc in category.documents:
|
||||
did = doc.id
|
||||
rec = '<td><a href="/get_doc?catid=' + str(catid) + '&doc=' + str(did) + '">' + doc.name + '</a></td>\n'
|
||||
if any_of(member_of('admins'), member_of('editors'))():
|
||||
html += '<tr><form action="/edit/docedit" method="post">\n{rec}<input type="hidden" name="catid" value="'.format(rec = rec) + str(catid) + '">\n<input type="hidden" name="doc" value="' + str(did) + '">\n<td><input type="submit" name="submit" value="Переименовать"></td>\n<td><input type="submit" name="submit" value="Редактировать"></td>\n<td><input type="submit" name="submit" value="Перенести"></td>\n<td><input type="submit" name="submit" value="Удалить"></td>\n</form></tr>\n'
|
||||
else:
|
||||
html += '<tr>{rec}</tr>'.format(rec = rec)
|
||||
html += '</table>\n</div>\n'
|
||||
if any_of(member_of('admins'), member_of('editors'))():
|
||||
html += '<div align="right">\n<form action="/edit/newdoc" method="post">\n<input type="hidden" name="catid" value="' + str(catid) + '">\n<input type="submit" value="Новый документ">\n</form>\n</div>\n'
|
||||
html += '<div align="right">\n<form action="/edit/upl" method="post">\n<input type="hidden" name="catid" value="' + str(catid) + '">\n<input type="submit" value="Загрузить документ">\n</form>\n</div>\n'
|
||||
html += '<div align="right">\n<form action="/edit/newcat" method="post">\nНовый раздел\n<input type="hidden" name="catid" value=' + str(catid) + '>\n<input type="text" name="catname">\n<input type="submit" value="Создать">\n</form>\n</div>\n'
|
||||
if catid != 0:
|
||||
parent = Cat(catid).parent
|
||||
html += '<div align="center"><a href="/category?catid=' + str(parent.id) + '"><i>← Обратно в раздел "' + parent.name + '"</i></a></div>\n'
|
||||
title = 'Архив[Раздел: ' + category.name + ']'
|
||||
return self.buildhtml(title, html)
|
||||
@cherrypy.expose
|
||||
def get_doc(self, catid = 0, doc = None, plain = False):
|
||||
catid = int(catid)
|
||||
cat = Cat(catid)
|
||||
if not doc: return
|
||||
doc = int(doc)
|
||||
doco = cat[doc]
|
||||
txt = doco.text
|
||||
muser = doco.muser
|
||||
mtime = doco.mtime.strftime('%d.%m.%Y %H:%M:%S') + ' /' + tzname[0] + '/'
|
||||
if plain:
|
||||
return txt
|
||||
else:
|
||||
doct = '<div align="left">' + self.path(doco.id, doc = True) + '</div><div align="right"><a href="/category?catid=' + str(catid) + '">\n<i>← Обратно в раздел "' + cat.name + '"</i>\n</a>\n</div>\n' + txt
|
||||
if any_of(member_of('admins'), member_of('editors'))():
|
||||
doct += '<div align="right"><form action="/edit/docedit" method="post">\n<input type="hidden" name="catid" value="' + str(catid) + '">\n<input type="hidden" name="doc" value="' + str(doc) + '">\n<input type="submit" name="submit" value="Переименовать">\n<input type="submit" name="submit" value="Редактировать">\n<input type="submit" name="submit" value="Перенести">\n<input type="submit" name="submit" value="Удалить">\n</form></div>\n'
|
||||
doct += '<div align="right">\nОтредактировано пользователем: <a href="/ctl/user?name=' + muser.name + '"><b>' + muser.dname + '[' + muser.name + ']</b></a>.</div>\n<div align="right">Дата редактирования: ' + mtime + '\n</div>\n'
|
||||
doct += '<br><div align="right"><a href="/category?catid=' + str(catid) + '">\n<i>← Обратно в раздел "' + cat.name + '"</i>\n</a>\n</div>\n'
|
||||
return self.buildhtml('Архив[' + doco.name + ']', doct)
|
||||
@cherrypy.expose
|
||||
def getobj(self, lybsrcobj = None):
|
||||
obj = lybtools.getbin(cherrypy.session, lybsrcobj)
|
||||
cherrypy.response.headers["Content-Type"] = obj['type']
|
||||
return obj['body']
|
||||
@cherrypy.expose
|
||||
def menu_img(self):
|
||||
cherrypy.response.headers["Content-Type"] = 'image/png'
|
||||
return lybhtdata.m_i()
|
||||
def menupanel(self, mdict):
|
||||
menu = lybtools.menu_gen(mdict)
|
||||
menu += lybhtdata.form_minisearch
|
||||
username = cherrypy.session.get(lybtools.SESSION_KEY, None)
|
||||
if username:
|
||||
menu += lybhtdata.form_user.format(username=username)
|
||||
else:
|
||||
menu += lybhtdata.form_auth.format(from_page=self.from_page)
|
||||
return menu
|
||||
|
||||
def buildhtml(self, title, doc):
|
||||
return lybhtdata.html.format(title=title, style='/css',
|
||||
body=lybhtdata.body.format(menu = self.menupanel(self.mdict), document = doc))
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,166 @@
|
|||
'''Этот модуль предназначен для конвертации в C-код и последующей компиляции в исполняюмую библиотеку. Здесь находятся тяжёлые функции.'''
|
||||
|
||||
import cherrypy
|
||||
from lxml import etree
|
||||
from lybmods import lybtools
|
||||
from urllib.request import FancyURLopener
|
||||
from urllib.parse import urlencode
|
||||
from urllib.parse import urljoin, parse_qs, urlsplit
|
||||
from lybmods.lybclasses import Cat
|
||||
from lybmods import lybhtdata
|
||||
from base64 import decodestring
|
||||
import re
|
||||
import hashlib
|
||||
|
||||
|
||||
class URLOpener(FancyURLopener):
|
||||
version = 'Mozilla/5.0 (X11; Linux x86_64; rv:10.0.6) Gecko/20100101 Firefox/10.0.6 Iceweasel/10.0.6'
|
||||
|
||||
def html(self, catid, url, htfile, md = None, sub = False, ins = False):
|
||||
htfile = lybtools.htfile_tounicode(htfile)
|
||||
body = etree.ElementTree(etree.HTML(htfile).xpath('//body')[0])
|
||||
sessdata = cherrypy.session
|
||||
strip_tags = ["script", "link"]
|
||||
etree.strip_elements(body, *strip_tags, with_tail=False)
|
||||
chg_tags = ["body", "a", "form", "input", "noscript"]
|
||||
etree.strip_tags(body, *chg_tags)
|
||||
etree.strip_tags(body, etree.Comment)
|
||||
#safe_tags = ['img']
|
||||
for elem in body.xpath('//*'):
|
||||
if elem.tag == 'body': elem.tag = 'old-body'
|
||||
attr = elem.attrib
|
||||
if elem.tag in chg_tags:
|
||||
etree.strip_attributes(elem, *attr)
|
||||
if "class" in attr:
|
||||
etree.strip_attributes(elem, "class")
|
||||
if "id" in attr:
|
||||
etree.strip_attributes(elem, "id")
|
||||
if "onclick" in attr:
|
||||
etree.strip_attributes(elem, "onclick")
|
||||
if "style" in attr:
|
||||
attr['style'] = re.sub('url\(.+\)', 'url()', attr['style'])
|
||||
#if elem.tag not in safe_tags and (elem.text is None or elem.text.strip() == '') and elem.getchildren() == []:
|
||||
# elem.getparent().remove(elem)
|
||||
# continue
|
||||
if "src" in attr:
|
||||
m = re.search('data:(\S+);base64,(.+)', attr['src'])
|
||||
if not m:
|
||||
srcurl = urljoin(url, attr['src'])
|
||||
srcobjquery = urlsplit(srcurl)[3]
|
||||
srcqdict = parse_qs(srcobjquery)
|
||||
if 'lybsrcobj' in list(srcqdict.keys()):
|
||||
ohash = srcqdict['lybsrcobj'][0]
|
||||
srcquerydata = {'lybsrcobj': ohash}
|
||||
srcquery = urlencode(srcquerydata)
|
||||
# if ins:
|
||||
page = '/getobj?'
|
||||
# else:
|
||||
# page = '/edit/tmpstore?'
|
||||
# if ohash not in sessdata:
|
||||
# if md:
|
||||
# cat = Cat(int(catid))
|
||||
# doco = cat[int(md)]
|
||||
# sessdata[ohash] = doco[ohash]
|
||||
elem.set('src', page + srcquery)
|
||||
continue
|
||||
try:
|
||||
srcu = URLOpener().open(srcurl)
|
||||
except:
|
||||
continue
|
||||
if srcu.code >= 400:
|
||||
continue
|
||||
srcdata = srcu.read()
|
||||
cont_type = srcu.headers['Content-Type']
|
||||
srcftype = cont_type and lybtools.ctype(srcu.headers['Content-Type']) or 'none'
|
||||
else:
|
||||
srcdata = decodestring(m.group(2).encode('utf-8'))
|
||||
srcftype = m.group(1)
|
||||
srchashname = hashlib.sha1(srcdata).hexdigest()
|
||||
if srcftype == 'text/html':
|
||||
if elem.tag == 'img': continue
|
||||
srcdata = self.html(catid, srcu.url, srcdata, sub = True)
|
||||
if srchashname not in sessdata:
|
||||
sessdata[srchashname] = {'body': srcdata, 'type': srcftype}
|
||||
srcquerydata = {'lybsrcobj': srchashname}
|
||||
srcquery = urlencode(srcquerydata)
|
||||
if ins:
|
||||
page = '/getobj?'
|
||||
else:
|
||||
page = '/edit/tmpstore?'
|
||||
elem.set('src', page + srcquery)
|
||||
etree.strip_tags(body, 'old-body')
|
||||
ht_ml = etree.tounicode(body, method='html', pretty_print = True)
|
||||
if not sub and not ins:
|
||||
return self.ne(catid, url=url, html=ht_ml, md=md)
|
||||
else:
|
||||
return ht_ml
|
||||
|
||||
def insert_doc(self, catid = 0, url = None, html = None, doc_name = '', md = None):
|
||||
catid = int(catid)
|
||||
doc_name = doc_name.strip()
|
||||
cat = Cat(catid)
|
||||
catname = cat.name
|
||||
if md:
|
||||
md = int(md)
|
||||
modify_doc = '<input type="hidden" name="md" value="' + str(md) + '">'
|
||||
else:
|
||||
modify_doc = ''
|
||||
|
||||
html = self.html(catid, '/', html, ins = True)
|
||||
if doc_name == '':
|
||||
return self.root.buildhtml('Архив [Укажи имя документа]', lybhtdata.nicedit_html1 + lybhtdata.nicedit_html2.format(docname=doc_name,
|
||||
url=url,
|
||||
modify_doc=modify_doc,
|
||||
textarea=lybhtdata.nicedit_textarea.format(input_html=html), catid=catid,
|
||||
catname = catname))
|
||||
did = cat.docidbyname(doc_name)
|
||||
if did and did != md:
|
||||
return self.root.buildhtml('Архив [Документ с таким именем в разделе "' + cat.name + '" существует]', lybhtdata.nicedit_html1 + lybhtdata.nicedit_html2.format(docname=doc_name,
|
||||
url=url,
|
||||
modify_doc=modify_doc,
|
||||
textarea=lybhtdata.nicedit_textarea.format(input_html=html), catid=catid,
|
||||
catname = catname))
|
||||
if md:
|
||||
cat[md] = { 'name': doc_name, 'body': html}
|
||||
did = md
|
||||
else:
|
||||
did = cat.insert({ 'name': doc_name, 'body': html})
|
||||
xdata = etree.HTML(html)
|
||||
if md:
|
||||
new_bin_list = [ parse_qs(urlsplit(x)[3])['lybsrcobj'][0] for x in xdata.xpath('//@src') if 'lybsrcobj' in parse_qs(urlsplit(x)[3])]
|
||||
old_bin_list = cat[did].bins
|
||||
list_to_del = list(set(old_bin_list) - set(new_bin_list))
|
||||
for bhash in list_to_del:
|
||||
del cat[did][bhash]
|
||||
for src in xdata.xpath('//@src'):
|
||||
srcquery = urlsplit(src)[3]
|
||||
try:
|
||||
src_obj = parse_qs(srcquery)['lybsrcobj'][0]
|
||||
except:
|
||||
continue
|
||||
try:
|
||||
obj = cherrypy.session[src_obj]
|
||||
except KeyError:
|
||||
continue
|
||||
cat[did][src_obj] = obj
|
||||
cherrypy.session.clear()
|
||||
args = {'doc':did, 'catid':catid}
|
||||
return self.root.get_doc(**args)
|
||||
|
||||
def ne(self, catid, url = None, html = None, md = None, docname = "Новый документ"):
|
||||
html = lybhtdata.nicedit_textarea.format(input_html=html)
|
||||
xhtml = etree.HTML(html).xpath('//textarea[@id=\'nicedit-js-area\']')[0]
|
||||
if md:
|
||||
docname = Cat(int(catid))[int(md)].name
|
||||
modify_doc = '<input type="hidden" name="md" value="' + md + '">'
|
||||
else:
|
||||
modify_doc = ''
|
||||
return self.root.path(int(catid), lcat = True) + '<br><br>' + lybhtdata.nicedit_html1 + lybhtdata.nicedit_html2.format(url=url,
|
||||
catid=catid,
|
||||
catname = Cat(int(catid)).name,
|
||||
docname = docname,
|
||||
modify_doc=modify_doc,
|
||||
textarea=etree.tounicode(xhtml,
|
||||
method="html",
|
||||
pretty_print=True)
|
||||
)
|
|
@ -0,0 +1,440 @@
|
|||
import lybmods.lybhtdata as lybhtdata
|
||||
from base64 import b64encode, b64decode, encodestring, decodestring, urlsafe_b64encode, urlsafe_b64decode
|
||||
import lybmods.lybcfg as lybcfg
|
||||
from lxml import etree
|
||||
from chardet import detect
|
||||
|
||||
SESSION_KEY = '_cp_username'
|
||||
mdict = {
|
||||
'Меню':[
|
||||
[
|
||||
'Хранилище',
|
||||
'/category',
|
||||
None
|
||||
],
|
||||
[
|
||||
'Панель управления',
|
||||
'#',
|
||||
{
|
||||
'Пользователи':'/ctl/users',
|
||||
'Группы': '/ctl/groups'
|
||||
}
|
||||
]
|
||||
]
|
||||
}
|
||||
edit_esc = {
|
||||
"&": "&amp;",
|
||||
'"': "&quot;",
|
||||
"'": "&apos;",
|
||||
">": "&gt;",
|
||||
"<": "&lt;",
|
||||
}
|
||||
def menu_gen(mdict):
|
||||
m = ''
|
||||
sm = ''
|
||||
smi = ''
|
||||
for menu in list(mdict.keys()):
|
||||
if type(mdict[menu]) is list:
|
||||
for submenu in mdict[menu]:
|
||||
if type(submenu[2]) is dict:
|
||||
for item in list(submenu[2].keys()):
|
||||
smi = smi + lybhtdata.submenuitem.format(name = item, url = submenu[2][item])
|
||||
sm = sm + lybhtdata.submenu.format(name = submenu[0], url = submenu[1],
|
||||
submenuitem = lybhtdata.submenuitem_container.format(submenuitem = smi))
|
||||
smi = ''
|
||||
else:
|
||||
sm = sm + lybhtdata.submenuitem.format(name = submenu[0], url = submenu[1],
|
||||
submenuitem = '')
|
||||
m = m + lybhtdata.menu.format(name = menu, submenu = sm)
|
||||
sm = ''
|
||||
else:
|
||||
m = m + lybhtdata.menu.format(name = menu, submenu = '')
|
||||
return lybhtdata.menu_container.format(menu = m)
|
||||
|
||||
def b64dec(self, data, ascii=False):
|
||||
if ascii:
|
||||
return urlsafe_b64decode(data)
|
||||
else:
|
||||
return b64decode(data)
|
||||
def b64enc(data, ascii=False):
|
||||
if ascii:
|
||||
return urlsafe_b64encode(data)
|
||||
else:
|
||||
return b64encode(data)
|
||||
def b64decstr(data):
|
||||
return decodestring(data)
|
||||
def b64encstr(data):
|
||||
return encodestring(data)
|
||||
|
||||
def ctype(c_t):
|
||||
t = c_t.split(';')
|
||||
return t[0]
|
||||
|
||||
def htfile_tounicode(htfile):
|
||||
if type(htfile) is str:
|
||||
return htfile
|
||||
ct = etree.HTML(htfile).xpath('//meta/@http-equiv')
|
||||
enc = detect(htfile)['encoding']
|
||||
if ct != []:
|
||||
c_t = ct[0].getparent().attrib['content']
|
||||
if 'charset' in c_t:
|
||||
enc = c_t.split('charset')[1].strip().split('=')[1].strip().split(' ')[0]
|
||||
return str(htfile, enc, 'ignore')
|
||||
|
||||
def getbin(sess, hhash):
|
||||
cur = sess.db.cursor()
|
||||
cur.execute('SELECT type, body FROM %s WHERE hash = %%s;' % lybcfg.bin_table_name, (hhash,))
|
||||
res = cur.fetchone()
|
||||
return {'type': res[0], 'body': res[1].tobytes()}
|
||||
|
||||
qChkUserAndPwd = """\
|
||||
SELECT COUNT(*) FROM auth_passwd
|
||||
WHERE username=%s AND password=%s;"""
|
||||
qChkUserInGroup = """\
|
||||
SELECT COUNT(*) FROM auth_membership AS m
|
||||
WHERE m.uid=(
|
||||
SELECT id FROM auth_passwd AS p
|
||||
WHERE p.username=%s
|
||||
)
|
||||
AND m.gid=(
|
||||
SELECT id FROM auth_group AS g
|
||||
WHERE g.name=%s
|
||||
);"""
|
||||
SESS_SCHEMA = """\
|
||||
CREATE TABLE {sess} (
|
||||
id VARCHAR(40),
|
||||
expiration_time TIMESTAMP,
|
||||
CONSTRAINT {sess}_pkey PRIMARY KEY (id)
|
||||
);
|
||||
CREATE TABLE {sessdata} (
|
||||
sid VARCHAR(40),
|
||||
key VARCHAR,
|
||||
value BYTEA
|
||||
);
|
||||
CREATE INDEX {sessdata}_idx on {sessdata} USING btree(sid);
|
||||
CREATE OR REPLACE FUNCTION del_{sessdata}() RETURNS trigger AS
|
||||
'
|
||||
BEGIN
|
||||
DELETE FROM {sessdata} where sid=old.id;
|
||||
RETURN old;
|
||||
END
|
||||
'
|
||||
LANGUAGE plpgsql;
|
||||
CREATE TRIGGER on_{sess}_del
|
||||
AFTER DELETE
|
||||
ON {sess} FOR EACH ROW
|
||||
EXECUTE PROCEDURE del_{sessdata}();
|
||||
""".format(sess = lybcfg.sess_table_name, sessdata = lybcfg.sess_data_table_name)
|
||||
|
||||
AUTH_SCHEMA = """\
|
||||
CREATE TABLE {grp} (
|
||||
id serial NOT NULL,
|
||||
name varchar(40) NOT NULL UNIQUE,
|
||||
dname varchar(40) NOT NULL,
|
||||
CONSTRAINT group_pkey PRIMARY KEY (id)
|
||||
);
|
||||
CREATE TABLE {pwd} (
|
||||
id serial NOT NULL,
|
||||
username varchar(40) NOT NULL UNIQUE,
|
||||
dname varchar(40) NOT NULL,
|
||||
password varchar(40) NOT NULL,
|
||||
CONSTRAINT passwd_pkey PRIMARY KEY (id)
|
||||
);
|
||||
CREATE TABLE {mbrsh} (
|
||||
id serial NOT NULL,
|
||||
uid integer,
|
||||
gid integer,
|
||||
CONSTRAINT membership_pkey PRIMARY KEY (id)
|
||||
);
|
||||
CREATE OR REPLACE FUNCTION del_uid() RETURNS trigger AS
|
||||
'
|
||||
BEGIN
|
||||
DELETE FROM {mbrsh} where uid=old.id;
|
||||
RETURN old;
|
||||
END
|
||||
'
|
||||
LANGUAGE plpgsql;
|
||||
CREATE TRIGGER on_{pwd}_del
|
||||
AFTER DELETE
|
||||
ON {pwd} FOR EACH ROW
|
||||
EXECUTE PROCEDURE del_uid();
|
||||
CREATE OR REPLACE FUNCTION del_gid() RETURNS trigger AS
|
||||
'
|
||||
BEGIN
|
||||
DELETE FROM {mbrsh} where gid=old.id;
|
||||
RETURN old;
|
||||
END
|
||||
'
|
||||
LANGUAGE plpgsql;
|
||||
CREATE TRIGGER on_{grp}_del
|
||||
AFTER DELETE
|
||||
ON {grp} FOR EACH ROW
|
||||
EXECUTE PROCEDURE del_uid();
|
||||
INSERT INTO {pwd}
|
||||
(username, dname, password)
|
||||
VALUES ('admin', 'Администратор', 'dd94709528bb1c83d08f3088d4043f4742891f4f');
|
||||
INSERT INTO {grp}
|
||||
(name, dname)
|
||||
VALUES ('admins', 'Администраторы');
|
||||
INSERT INTO {grp}
|
||||
(name, dname)
|
||||
VALUES ('editors', 'Редакторы');
|
||||
INSERT INTO {mbrsh}
|
||||
(uid, gid)
|
||||
VALUES ((SELECT id FROM {pwd} WHERE username = 'admin'), (SELECT id FROM {grp} WHERE name = 'admins'));
|
||||
""".format(grp = lybcfg.grp_table_name, pwd = lybcfg.pwd_table_name, mbrsh = lybcfg.mbrsh_table_name)
|
||||
|
||||
CAT_SCHEMA = """\
|
||||
CREATE TABLE {cat} (
|
||||
id bigserial NOT NULL,
|
||||
name varchar(512) NOT NULL,
|
||||
parent bigint,
|
||||
CONSTRAINT {cat}_pkey PRIMARY KEY (id)
|
||||
);
|
||||
CREATE OR REPLACE FUNCTION update_{cat}_in_{doc}() RETURNS trigger AS
|
||||
'
|
||||
BEGIN
|
||||
UPDATE {doc} SET catid = old.parent WHERE catid = old.id;
|
||||
UPDATE {cat} SET parent = old.parent WHERE parent = old.id;
|
||||
RETURN old;
|
||||
END
|
||||
'
|
||||
LANGUAGE plpgsql;
|
||||
CREATE TRIGGER on_{cat}_del
|
||||
AFTER DELETE
|
||||
ON {cat} FOR EACH ROW
|
||||
EXECUTE PROCEDURE update_{cat}_in_{doc}();
|
||||
CREATE INDEX name_idx ON {cat} USING gin(to_tsvector('russian', name));
|
||||
""".format(cat = lybcfg.cat_table_name, doc = lybcfg.doc_table_name)
|
||||
DOC_SCHEMA = """\
|
||||
CREATE TABLE {doc} (
|
||||
id bigserial NOT NULL,
|
||||
name varchar(512) NOT NULL,
|
||||
catid bigint NOT NULL,
|
||||
muser varchar(40) NOT NULL,
|
||||
mtime timestamp without time zone DEFAULT now() NOT NULL,
|
||||
body text,
|
||||
fts_index tsvector,
|
||||
CONSTRAINT {doc}_pkey PRIMARY KEY (id)
|
||||
);
|
||||
CREATE INDEX fts_idx on {doc} USING gin(fts_index);
|
||||
|
||||
CREATE OR REPLACE FUNCTION del_{docbin}() RETURNS trigger AS
|
||||
'
|
||||
BEGIN
|
||||
DELETE FROM {docbin} WHERE docid=old.id;
|
||||
RETURN old;
|
||||
END
|
||||
'
|
||||
LANGUAGE plpgsql;
|
||||
CREATE TRIGGER on_{doc}_del
|
||||
AFTER DELETE
|
||||
ON {doc} FOR EACH ROW
|
||||
EXECUTE PROCEDURE del_{docbin}();
|
||||
CREATE FUNCTION update_fts_index() RETURNS trigger AS $$
|
||||
BEGIN
|
||||
new.fts_index :=
|
||||
setweight(to_tsvector('pg_catalog.russian', coalesce(new.name,'')), 'A') ||
|
||||
setweight(to_tsvector('pg_catalog.russian', coalesce(new.body,'')), 'B');
|
||||
RETURN new;
|
||||
END
|
||||
$$ LANGUAGE plpgsql;
|
||||
CREATE TRIGGER fts_index_update
|
||||
BEFORE INSERT OR UPDATE
|
||||
ON {doc} FOR EACH ROW
|
||||
EXECUTE PROCEDURE update_fts_index();
|
||||
""".format(doc = lybcfg.doc_table_name, docbin = lybcfg.docbin_table_name)
|
||||
#CATDOC_SCHEMA = """\
|
||||
#CREATE TABLE {catdoc} (
|
||||
# id serial NOT NULL,
|
||||
# docid bigint NOT NULL,
|
||||
# catid bigint NOT NULL,
|
||||
# CONSTRAINT {catdoc}_pkey PRIMARY KEY (id)
|
||||
# );
|
||||
#CREATE OR REPLACE FUNCTION del_orphaned_{doc}() RETURNS trigger AS
|
||||
#'
|
||||
#BEGIN
|
||||
# PERFORM * FROM {catdoc} WHERE docid = old.docid;
|
||||
# IF NOT FOUND THEN
|
||||
# DELETE FROM {doc} where id=old.docid;
|
||||
# RETURN old;
|
||||
# END IF;
|
||||
# RETURN old;
|
||||
#END
|
||||
#'
|
||||
#LANGUAGE plpgsql;
|
||||
#CREATE TRIGGER on_{catdoc}_del
|
||||
# AFTER DELETE
|
||||
# ON {catdoc} FOR EACH ROW
|
||||
# EXECUTE PROCEDURE del_orphaned_{doc}();
|
||||
#""".format(catdoc = lybcfg.catdoc_table_name, doc = lybcfg.doc_table_name)
|
||||
BIN_SCHEMA = """\
|
||||
CREATE TABLE {bin} (
|
||||
id bigserial NOT NULL,
|
||||
hash varchar(40) NOT NULL,
|
||||
type varchar(40) NOT NULL,
|
||||
body bytea,
|
||||
CONSTRAINT {bin}_pkey PRIMARY KEY (id, hash)
|
||||
);
|
||||
""".format(bin = lybcfg.bin_table_name)
|
||||
DOCBIN_SCHEMA = """\
|
||||
CREATE TABLE {docbin} (
|
||||
id bigserial NOT NULL,
|
||||
binid bigint NOT NULL,
|
||||
docid bigint NOT NULL,
|
||||
CONSTRAINT {docbin}_pkey PRIMARY KEY (id)
|
||||
);
|
||||
CREATE OR REPLACE FUNCTION del_orphaned_{bin}() RETURNS trigger AS
|
||||
'
|
||||
BEGIN
|
||||
PERFORM * FROM {docbin} WHERE binid = old.binid;
|
||||
IF NOT FOUND THEN
|
||||
DELETE FROM {bin} where id=old.binid;
|
||||
RETURN old;
|
||||
END IF;
|
||||
RETURN old;
|
||||
END
|
||||
'
|
||||
LANGUAGE plpgsql;
|
||||
CREATE TRIGGER on_{docbin}_del
|
||||
AFTER DELETE
|
||||
ON {docbin} FOR EACH ROW
|
||||
EXECUTE PROCEDURE del_orphaned_{bin}();
|
||||
""".format(docbin = lybcfg.docbin_table_name, bin = lybcfg.bin_table_name)
|
||||
GRPCAT_ACCESS_SCHEMA = """\
|
||||
CREATE TABLE {grpcat_access} (
|
||||
id bigserial NOT NULL,
|
||||
gid bigint NOT NULL,
|
||||
catid bigint NOT NULL,
|
||||
attr varchar(2),
|
||||
CONSTRAINT {grpcat_access}_pkey PRIMARY KEY (id)
|
||||
);
|
||||
CREATE INDEX {grpcat_access}_idx on {grpcat_access} USING btree(gid, catid);
|
||||
CREATE OR REPLACE FUNCTION del_orphaned_{grpcat_access}_on_del_{cat}() RETURNS trigger AS
|
||||
'
|
||||
BEGIN
|
||||
DELETE FROM {grpcat_access} WHERE catid=old.id;
|
||||
RETURN old;
|
||||
END
|
||||
'
|
||||
LANGUAGE plpgsql;
|
||||
CREATE TRIGGER del_orphaned_{grpcat_access}_on_del_{cat}
|
||||
AFTER DELETE
|
||||
ON {cat} FOR EACH ROW
|
||||
EXECUTE PROCEDURE del_orphaned_{grpcat_access}_on_del_{cat}();
|
||||
CREATE OR REPLACE FUNCTION del_orphaned_{grpcat_access}_on_del_{grp}() RETURNS trigger AS
|
||||
'
|
||||
BEGIN
|
||||
DELETE FROM {grpcat_access} WHERE gid=old.id;
|
||||
RETURN old;
|
||||
END
|
||||
'
|
||||
LANGUAGE plpgsql;
|
||||
CREATE TRIGGER del_orphaned_{grpcat_access}_on_del_{grp}
|
||||
AFTER DELETE
|
||||
ON {grp} FOR EACH ROW
|
||||
EXECUTE PROCEDURE del_orphaned_{grpcat_access}_on_del_{grp}();
|
||||
""".format(grpcat_access = lybcfg.grpcat_access_table, cat = lybcfg.cat_table_name, grp = lybcfg.grp_table_name)
|
||||
GRPDOC_ACCESS_SCHEMA = """\
|
||||
CREATE TABLE {grpdoc_access} (
|
||||
id bigserial NOT NULL,
|
||||
gid bigint NOT NULL,
|
||||
docid bigint NOT NULL,
|
||||
attr varchar(2),
|
||||
CONSTRAINT {grpdoc_access}_pkey PRIMARY KEY (id)
|
||||
);
|
||||
CREATE INDEX {grpdoc_access}_idx on {grpdoc_access} USING btree(gid, docid);
|
||||
CREATE OR REPLACE FUNCTION del_orphaned_{grpdoc_access}_on_del_{doc}() RETURNS trigger AS
|
||||
'
|
||||
BEGIN
|
||||
DELETE FROM {grpdoc_access} WHERE docid=old.id;
|
||||
RETURN old;
|
||||
END
|
||||
'
|
||||
LANGUAGE plpgsql;
|
||||
CREATE TRIGGER del_orphaned_{grpdoc_access}_on_del_{doc}
|
||||
AFTER DELETE
|
||||
ON {doc} FOR EACH ROW
|
||||
EXECUTE PROCEDURE del_orphaned_{grpdoc_access}_on_del_{doc}();
|
||||
CREATE OR REPLACE FUNCTION del_orphaned_{grpdoc_access}_on_del_{grp}() RETURNS trigger AS
|
||||
'
|
||||
BEGIN
|
||||
DELETE FROM {grpdoc_access} WHERE gid=old.id;
|
||||
RETURN old;
|
||||
END
|
||||
'
|
||||
LANGUAGE plpgsql;
|
||||
CREATE TRIGGER del_orphaned_{grpdoc_access}_on_del_{grp}
|
||||
AFTER DELETE
|
||||
ON {grp} FOR EACH ROW
|
||||
EXECUTE PROCEDURE del_orphaned_{grpdoc_access}_on_del_{grp}();
|
||||
""".format(grpdoc_access = lybcfg.grpdoc_access_table, doc = lybcfg.doc_table_name, grp = lybcfg.grp_table_name)
|
||||
|
||||
PWDCAT_ACCESS_SCHEMA = """\
|
||||
CREATE TABLE {pwdcat_access} (
|
||||
id bigserial NOT NULL,
|
||||
pid bigint NOT NULL,
|
||||
catid bigint NOT NULL,
|
||||
attr varchar(2),
|
||||
CONSTRAINT {pwdcat_access}_pkey PRIMARY KEY (id)
|
||||
);
|
||||
CREATE INDEX {pwdcat_access}_idx on {pwdcat_access} USING btree(pid, catid);
|
||||
CREATE OR REPLACE FUNCTION del_orphaned_{pwdcat_access}_on_del_{cat}() RETURNS trigger AS
|
||||
'
|
||||
BEGIN
|
||||
DELETE FROM {pwdcat_access} WHERE catid=old.id;
|
||||
RETURN old;
|
||||
END
|
||||
'
|
||||
LANGUAGE plpgsql;
|
||||
CREATE TRIGGER del_orphaned_{pwdcat_access}_on_del_{cat}
|
||||
AFTER DELETE
|
||||
ON {cat} FOR EACH ROW
|
||||
EXECUTE PROCEDURE del_orphaned_{pwdcat_access}_on_del_{cat}();
|
||||
CREATE OR REPLACE FUNCTION del_orphaned_{pwdcat_access}_on_del_{pwd}() RETURNS trigger AS
|
||||
'
|
||||
BEGIN
|
||||
DELETE FROM {pwdcat_access} WHERE pid=old.id;
|
||||
RETURN old;
|
||||
END
|
||||
'
|
||||
LANGUAGE plpgsql;
|
||||
CREATE TRIGGER del_orphaned_{pwdcat_access}_on_del_{pwd}
|
||||
AFTER DELETE
|
||||
ON {pwd} FOR EACH ROW
|
||||
EXECUTE PROCEDURE del_orphaned_{pwdcat_access}_on_del_{pwd}();
|
||||
""".format(pwdcat_access = lybcfg.pwdcat_access_table, cat = lybcfg.cat_table_name, pwd = lybcfg.pwd_table_name)
|
||||
PWDDOC_ACCESS_SCHEMA = """\
|
||||
CREATE TABLE {pwddoc_access} (
|
||||
id bigserial NOT NULL,
|
||||
pid bigint NOT NULL,
|
||||
docid bigint NOT NULL,
|
||||
attr varchar(2),
|
||||
CONSTRAINT {pwddoc_access}_pkey PRIMARY KEY (id)
|
||||
);
|
||||
CREATE INDEX {pwddoc_access}_idx on {pwddoc_access} USING btree(pid, docid);
|
||||
CREATE OR REPLACE FUNCTION del_orphaned_{pwddoc_access}_on_del_{doc}() RETURNS trigger AS
|
||||
'
|
||||
BEGIN
|
||||
DELETE FROM {pwddoc_access} WHERE docid=old.id;
|
||||
RETURN old;
|
||||
END
|
||||
'
|
||||
LANGUAGE plpgsql;
|
||||
CREATE TRIGGER del_orphaned_{pwddoc_access}_on_del_{doc}
|
||||
AFTER DELETE
|
||||
ON {doc} FOR EACH ROW
|
||||
EXECUTE PROCEDURE del_orphaned_{pwddoc_access}_on_del_{doc}();
|
||||
CREATE OR REPLACE FUNCTION del_orphaned_{pwddoc_access}_on_del_{pwd}() RETURNS trigger AS
|
||||
'
|
||||
BEGIN
|
||||
DELETE FROM {pwddoc_access} WHERE pid=old.id;
|
||||
RETURN old;
|
||||
END
|
||||
'
|
||||
LANGUAGE plpgsql;
|
||||
CREATE TRIGGER del_orphaned_{pwddoc_access}_on_del_{pwd}
|
||||
AFTER DELETE
|
||||
ON {pwd} FOR EACH ROW
|
||||
EXECUTE PROCEDURE del_orphaned_{pwddoc_access}_on_del_{pwd}();
|
||||
""".format(pwddoc_access = lybcfg.pwddoc_access_table, doc = lybcfg.doc_table_name, pwd = lybcfg.pwd_table_name)
|
Loading…
Reference in New Issue