.
This commit is contained in:
		
							parent
							
								
									746da62a26
								
							
						
					
					
						commit
						65774a6d04
					
				
							
								
								
									
										20
									
								
								lyb
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								lyb
									
									
									
									
									
										Normal file
									
								
							@ -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
									
								
								lybmods/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								lybmods/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
								
								
									
										22
									
								
								lybmods/lybcfg.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								lybmods/lybcfg.py
									
									
									
									
									
										Normal file
									
								
							@ -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'
 | 
			
		||||
							
								
								
									
										624
									
								
								lybmods/lybclasses.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										624
									
								
								lybmods/lybclasses.py
									
									
									
									
									
										Normal file
									
								
							@ -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
 | 
			
		||||
							
								
								
									
										244
									
								
								lybmods/lybctl.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										244
									
								
								lybmods/lybctl.py
									
									
									
									
									
										Normal file
									
								
							@ -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)
 | 
			
		||||
							
								
								
									
										235
									
								
								lybmods/lybedit.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										235
									
								
								lybmods/lybedit.py
									
									
									
									
									
										Normal file
									
								
							@ -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)
 | 
			
		||||
							
								
								
									
										138
									
								
								lybmods/lybformauth.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										138
									
								
								lybmods/lybformauth.py
									
									
									
									
									
										Normal file
									
								
							@ -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("/")
 | 
			
		||||
							
								
								
									
										1686
									
								
								lybmods/lybhtdata.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1686
									
								
								lybmods/lybhtdata.py
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										32
									
								
								lybmods/lybpqconn.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								lybmods/lybpqconn.py
									
									
									
									
									
										Normal file
									
								
							@ -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()
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										248
									
								
								lybmods/lybpqsession.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										248
									
								
								lybmods/lybpqsession.py
									
									
									
									
									
										Normal file
									
								
							@ -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,)
 | 
			
		||||
							
								
								
									
										151
									
								
								lybmods/lybrary.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										151
									
								
								lybmods/lybrary.py
									
									
									
									
									
										Normal file
									
								
							@ -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))
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    
 | 
			
		||||
							
								
								
									
										166
									
								
								lybmods/lybshared.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										166
									
								
								lybmods/lybshared.py
									
									
									
									
									
										Normal file
									
								
							@ -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)
 | 
			
		||||
                                                              )
 | 
			
		||||
							
								
								
									
										440
									
								
								lybmods/lybtools.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										440
									
								
								lybmods/lybtools.py
									
									
									
									
									
										Normal file
									
								
							@ -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…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user