.
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