def add_subscription_request(self, user): if self.check_subscriber(user): raise AlreadySubscribed if not self.get_profile('private'): self.add_subscriber(user) return True res = db.fetchone("SELECT user_id FROM users.blacklist WHERE " "user_id=%s AND to_user_id=%s;", [self.id, user.id]) if res: raise SubscribeError res = db.fetchone("SELECT user_id FROM users.whitelist WHERE " "user_id=%s AND to_user_id=%s;", [self.id, user.id]) if res: self.add_subscriber(user) return True try: db.perform("INSERT INTO subs.requests " "VALUES (%s, %s);", [user.id, self.id]) except IntegrityError: raise AlreadyRequested return False
def add_subscription_request(self, user): if self.check_subscriber(user): raise AlreadySubscribed if not self.get_profile('private'): self.add_subscriber(user) return True res = db.fetchone( "SELECT user_id FROM users.blacklist WHERE " "user_id=%s AND to_user_id=%s;", [self.id, user.id]) if res: raise SubscribeError res = db.fetchone( "SELECT user_id FROM users.whitelist WHERE " "user_id=%s AND to_user_id=%s;", [self.id, user.id]) if res: self.add_subscriber(user) return True try: db.perform("INSERT INTO subs.requests " "VALUES (%s, %s);", [user.id, self.id]) except IntegrityError: raise AlreadyRequested return False
def check_tag_blacklisted(self, tag, user=None): if user: res = db.fetchone("SELECT 1 FROM posts.tags_blacklist_user " "WHERE user_id=%s AND to_user_id=%s AND tag=%s;", [self.id, user.id, tag]) else: res = db.fetchone("SELECT 1 FROM posts.tags_blacklist_global " "WHERE user_id=%s AND tag=%s;", [self.id, tag]) return bool(res)
def check_tag_subscribed(self, tag, user=None): if user: res = db.fetchone("SELECT 1 FROM subs.tags_user " "WHERE user_id=%s AND to_user_id=%s AND tag=%s;", [self.id, user.id, tag]) else: res = db.fetchone("SELECT 1 FROM subs.tags_global " "WHERE user_id=%s AND tag=%s;", [self.id, tag]) return bool(res)
def check_subscribe_to_user_rec(self, login): user = User('login', login) if self == user or not user or not self.id: return False res = db.fetchone("SELECT user_id FROM subs.recommendations WHERE " "user_id=%s AND to_user_id=%s;", [self.id, user.id]) return bool(res)
def authenticate(self, login=None, password=None): if login is not None: res = db.fetchone("SELECT id, login FROM users.logins " "WHERE lower(login)=%s AND password=%s;", [login.lower(), self._passhash(password)]) if not res: self.id = None self.login = None raise NotAuthorized self.id = res['id'] self.login = res['login'] self._get_avatar() elif not self.id: raise NotAuthorized sess = Session() sess['id'] = self.id sess['login'] = self.login sess.save() add_session(self, sess.sessid) return sess.sessid
def comments_count(self): if self._comments_count is not None: return self._comments_count if not self.id: raise PostNotFound(None) redis = RedisPool(settings.storage_socket) cnt = redis.get('cmnt_cnt.%s' % unb26(self.id)) if cnt is not None: try: self._comments_count = int(cnt) except (TypeError, ValueError): self._comments_count = 0 return self._comments_count try: cnt = db.fetchone("SELECT count(comment_id)::int " "FROM posts.comments " "WHERE post_id=%s;", [unb26(self.id)])[0] except IndexError: cnt = 0 redis.set('cmnt_cnt.%s' % unb26(self.id), int(cnt)) try: self._comments_count = int(cnt) except (TypeError, ValueError): self._comments_count = 0 return self._comments_count
def check_bookmarked(self, user): if not self.id or not user.id: return False res = db.fetchone("SELECT user_id FROM posts.bookmarks " "WHERE user_id=%s AND post_id=%s AND comment_id=0;", [user.id, unb26(self.id)]) return bool(res)
def last_published(self, ts=None): if not self.id: return None redis = RedisPool(settings.storage_socket) key = "feed:last_published:%s" % self.id if ts is None: if not self.id: if not self._posts: return None ts = max([ p.created for p in self._posts ]) redis.set(key, ts.isoformat()) return ts ts = redis.get(key) if ts: return dateutil.parser.parse(ts) res = db.fetchone("SELECT max(created) FROM posts.posts " "WHERE author=%s;", [self.id]) if not res or not res[0]: return None redis.set(key, res[0].isoformat()) return res[0] redis.set(key, ts.isoformat())
def last_published(self, ts=None): if not self.id: return None redis = RedisPool(settings.storage_socket) key = "feed:last_published:%s" % self.id if ts is None: if not self.id: if not self._posts: return None ts = max([p.created for p in self._posts]) redis.set(key, ts.isoformat()) return ts ts = redis.get(key) if ts: return dateutil.parser.parse(ts) res = db.fetchone( "SELECT max(created) FROM posts.posts " "WHERE author=%s;", [self.id]) if not res or not res[0]: return None redis.set(key, res[0].isoformat()) return res[0] redis.set(key, ts.isoformat())
def check_blacklist(self, user): if self == user or not user or not self.id: return False res = db.fetchone( "SELECT user_id FROM users.blacklist " "WHERE user_id=%s AND to_user_id=%s;", [self.id, user.id]) return bool(res)
def get_active_account(self, type=None): if not self.id: return None data = self.redis.get('active.%d' % self.id) if data: data = json.loads(data) else: _type = type if type else 'xmpp' res = db.fetchone("SELECT type, address FROM users.accounts WHERE " "user_id=%s AND type=%s;", [self.id, _type]) if not res: self.redis.set('active.%d' % self.id, '{}') self.redis.expire('active.%d' % self.id, 60) return None self.redis.set('active.%d' % self.id, json.dumps({'type': _type, 'addr': res['address']})) data = {'type': res['type'], 'addr': res['address']} if not type: return data try: if data['type'] == type: return data['addr'] except KeyError: return None return None
def get(table, param): try: return self.profile[table][param] except KeyError: try: # FIXME: profile models db.perform("INSERT INTO %s (id) VALUES (%%s);" % \ table, [self.id]) except IntegrityError: pass res = cache_get('profile:%s:%s' % (table, self.id)) if res: self.profile[table] = res else: res = db.fetchone("SELECT * FROM %s WHERE id=%%s;" % \ table, [self.id]) log.debug('RES %s %s' % (table, res)) if res: self.profile[table] = dict(res) cache_store('profile:%s:%s' % (table, self.id), self.profile[table]) else: #try: # return cls._profile[param]['default'] #except KeyError: # return None return None # FIXME: remove recursive call try: return self.profile[table][param] except KeyError: cache_del('profile:%s:%s' % (table, self.id)) return get(table, param)
def get_active_account(self, type=None): if not self.id: return None data = self.redis.get('active.%d' % self.id) if data: data = json.loads(data) else: _type = type if type else 'xmpp' res = db.fetchone( "SELECT type, address FROM users.accounts WHERE " "user_id=%s AND type=%s;", [self.id, _type]) if not res: self.redis.set('active.%d' % self.id, '{}') self.redis.expire('active.%d' % self.id, 60) return None self.redis.set('active.%d' % self.id, json.dumps({ 'type': _type, 'addr': res['address'] })) data = {'type': res['type'], 'addr': res['address']} if not type: return data try: if data['type'] == type: return data['addr'] except KeyError: return None return None
def check_blacklist(self, user): if self == user or not user or not self.id: return False res = db.fetchone("SELECT user_id FROM users.blacklist " "WHERE user_id=%s AND to_user_id=%s;", [self.id, user.id]) return bool(res)
def check_rec_subscriber(self, user): if self == user or not user or not self.id: return False res = db.fetchone( "SELECT user_id FROM subs.recommendations WHERE " "user_id=%s AND to_user_id=%s;", [user.id, self.id]) return bool(res)
def updates_count(self): try: return db.fetchone( "SELECT count(post_id) FROM posts.updates " "WHERE post_id=%s;", [unb26(self.id)])[0] except IndexError: return 0
def check_subscriber(self, user): if not self.id or not user.id: return False res = db.fetchone("SELECT user_id FROM subs.posts " "WHERE user_id=%s AND post_id=%s;", [user.id, unb26(self.id)]) return bool(res)
def get_info(self, param=None): if not self.info: res = cache_get('userinfo:%s' % self.id) if res: for k in ('birthdate', 'created'): res[k] = dateutil.parser.parse(res[k]) if res[k] else None self.info = res else: res = db.fetchone( "SELECT name, email, xmpp, icq, skype, " "about, avatar, gender, " "birthdate, location, homepage, created " "FROM users.info WHERE id=%s;", [self.id]) if res: self.info = dict(res) res = dict(res) for k in ('birthdate', 'created'): res[k] = res[k].isoformat() if res[k] else None cache_store('userinfo:%s' % self.id, res) if not self.info: return None if param: try: return self.info[param] except KeyError: return None else: return self.info
def confirm_account(self, code): res = db.fetchone("SELECT id, user_id, type, address, code " "FROM users.accounts_unconfirmed " "WHERE code=%s;", [code.lower()]) if not res: return False if res['user_id'] != self.id or res['code'] != str(code).lower(): return False db.perform("DELETE FROM users.accounts_unconfirmed WHERE id=%s;", [res['id']]) try: db.perform("INSERT INTO users.accounts (user_id, type, address) " "VALUES (%s, %s, %s);", [self.id, res['type'], res['address']]) except IntegrityError: log.error("%s %s already exists" % (res['type'], res['address'])) return False cache_del("addr_id_login:%s" % res['address']) return True
def confirm_account(self, code): res = db.fetchone( "SELECT id, user_id, type, address, code " "FROM users.accounts_unconfirmed " "WHERE code=%s;", [code.lower()]) if not res: return False if res['user_id'] != self.id or res['code'] != str(code).lower(): return False db.perform("DELETE FROM users.accounts_unconfirmed WHERE id=%s;", [res['id']]) try: db.perform( "INSERT INTO users.accounts (user_id, type, address) " "VALUES (%s, %s, %s);", [self.id, res['type'], res['address']]) except IntegrityError: log.error("%s %s already exists" % (res['type'], res['address'])) return False cache_del("addr_id_login:%s" % res['address']) return True
def get_info(self, param=None): if not self.info: res = cache_get('userinfo:%s' % self.id) if res: for k in ('birthdate', 'created'): res[k] = dateutil.parser.parse(res[k]) if res[k] else None self.info = res else: res = db.fetchone("SELECT name, email, xmpp, icq, skype, " "about, avatar, gender, " "birthdate, location, homepage, created " "FROM users.info WHERE id=%s;", [self.id]) if res: self.info = dict(res) res = dict(res) for k in ('birthdate', 'created'): res[k] = res[k].isoformat() if res[k] else None cache_store('userinfo:%s' % self.id, res) if not self.info: return None if param: try: return self.info[param] except KeyError: return None else: return self.info
def authenticate(cls, login, password): res = db.fetchone("SELECT id FROM users.logins " "WHERE lower(login)=%s AND password=%s;", [login.lower(), cls._passhash(password)]) if res: return cls(res[0], login) raise NotAuthorized
def authenticate_ulogin(self, network, uid): res = db.fetchone("SELECT id FROM users.ulogin_accounts " "WHERE network=%s AND uid=%s;", [network, uid]) if not res: raise NotAuthorized User.__init__(self, int(res[0])) self.authenticate()
def check_post_subscribed(self, post): """Check for user subscription to post. Return True, if subscribed, otherwise False """ res = db.fetchone("SELECT user_id, post_id FROM subs.posts " "WHERE user_id=%s AND post_id=%s;", [self.id, unb26(post)]) return bool(res)
def check_post_subscribed(self, post): """Check for user subscription to post. Return True, if subscribed, otherwise False """ res = db.fetchone( "SELECT user_id, post_id FROM subs.posts " "WHERE user_id=%s AND post_id=%s;", [self.id, unb26(post)]) return bool(res)
def del_from_whitelist(self, user): res = db.fetchone("DELETE FROM users.whitelist WHERE " "user_id=%s AND to_user_id=%s RETURNING user_id;", [self.id, user.id]) if self.get_profile('private'): self.del_subscriber(user) return bool(res)
def __init__(self, post, id, to_comment_id=None, author=None, created=None, text=None, archive=False, files=None): if post and id: if isinstance(post, Post): self.post = post elif isinstance(post, (int, long)): self.post = Post.from_data(b26(post)) else: self.post = Post.from_data(post) self.id = int(id) res = db.fetchone( "SELECT c.author, u.login, i.name, i.avatar, " "c.to_comment_id, " "c.anon_login, " "c.created at time zone %s AS created, " "c.text, c.files, c.updated " "FROM posts.comments c " "JOIN users.logins u ON u.id=c.author " "JOIN users.info i ON u.id=i.id " "WHERE post_id=%s AND comment_id=%s;", [self.post.tz, unb26(self.post.id), self.id]) if not res: raise CommentNotFound(self.post.id, id) if author: self.author = author else: login = res['anon_login'] or res['login'] self.author = User.from_data(res['author'], login, info={ 'name': res['name'] or login, 'avatar': res['avatar'] }) self.to_comment_id = to_comment_id or res['to_comment_id'] self.created = created or res['created'] self.text = text or res['text'] self.recommendations = 0 self.recommended = False self.files = res['files'] self.updated = res['updated'] self.comments = [] self.archive = archive if isinstance(files, (list, tuple)): self.files = files
def domain(user): if not user.id: raise NotAuthorized res = db.fetchone("SELECT domain FROM users.domains WHERE id=%s;", [user.id]) #, _cache=600) if res: return res[0] else: return '%s.%s' % (user.login, settings.domain)
def check_password(self, password): res = db.fetchone("SELECT password FROM users.logins " "WHERE id=%s;", [self.id]) if not res: return False if res[0] != self._passhash(password): return False return True
def check_whitelist(self, user): if self.id == user.id or not self.id: return True if not user.id: return False res = db.fetchone("SELECT user_id FROM users.whitelist " "WHERE user_id=%s AND to_user_id=%s;", [self.id, user.id]) return bool(res)
def delete(self): res = db.fetchone("DELETE FROM posts.comments " "WHERE post_id=%s AND comment_id=%s " "RETURNING files;", [unb26(self.post.id), self.id]) if res and res['files']: for f in res['files']: remove_attach(f) redis = RedisPool(settings.storage_socket) redis.decr('cmnt_cnt.%s' % unb26(self.post.id))
def check_whitelist(self, user): if self.id == user.id or not self.id: return True if not user.id: return False res = db.fetchone( "SELECT user_id FROM users.whitelist " "WHERE user_id=%s AND to_user_id=%s;", [self.id, user.id]) return bool(res)
def delete_alias(self, alias): if not self.id: raise NotAuthorized res = db.fetchone("DELETE FROM users.user_aliases " "WHERE user_id=%s AND alias=%s " "RETURNING alias;", [self.id, alias.lower()]) if not res: return False cache_del('aliases:%s' % self.id) return True
def comments_count(self): c = cache_get('comments_count:%s' % self.id) if c: return c try: c = db.fetchone("SELECT count(id) FROM posts.comments " "WHERE author=%s;", [self.id])[0] cache_store('comments_count:%s' % self.id, c, 30) return c except IndexError: return 0
def domain_owner(domain): if domain == settings.domain: return User.from_data(None, None) if domain.endswith(settings.domain): return User("login", domain[0 : domain.find(settings.domain) - 1]) res = db.fetchone("SELECT id FROM users.domains WHERE domain=%s;", [domain]) # , _cache=600) if res: return User(res[0]) raise UserNotFound
def readers_count(self, cache=True): if not cache: c = cache_get('readers_count:%s' % self.id) if c: return c try: c = db.fetchone("SELECT count(user_id) FROM subs.users " "WHERE to_user_id=%s;", [self.id])[0] cache_store('readers_count:%s' % self.id, c) return c except IndexError: return 0
def delete_alias(self, alias): if not self.id: raise NotAuthorized res = db.fetchone( "DELETE FROM users.user_aliases " "WHERE user_id=%s AND alias=%s " "RETURNING alias;", [self.id, alias.lower()]) if not res: return False cache_del('aliases:%s' % self.id) return True
def add_to_whitelist(self, user): try: db.perform("INSERT INTO users.whitelist VALUES (%s, %s);", [self.id, user.id]) except IntegrityError: return False res = db.fetchone("DELETE FROM subs.requests WHERE " "user_id=%s AND to_user_id=%s " "RETURNING user_id;", [user.id, self.id]) if res: self.add_subscriber(user) return True
def domain_owner(domain): if domain == settings.domain: return User.from_data(None, None) if domain.endswith(settings.domain): return User('login', domain[0:domain.find(settings.domain) - 1]) res = db.fetchone("SELECT id FROM users.domains WHERE domain=%s;", [domain]) #, _cache=600) if res: return User(res[0]) raise UserNotFound
def add_account(self, type, address): if type in ACCOUNT_TYPES and not parse_email(address): raise ValueError(address) res = db.fetchone("SELECT id FROM users.accounts " "WHERE type=%s AND address=%s;", [type, address]) if res: return res = db.fetchone("SELECT id FROM users.accounts_unconfirmed " "WHERE type=%s AND address=%s;", [type, address]) if res: return code = '%s%s%s%s' % (settings.secret, datetime.now(), type, address) code = sha1(code).hexdigest().lower() self.accounts_add.append((type, address, code)) cache_del("addr_id_login:%s" % address) return code
def check_password_set(self): try: return self._password_set except AttributeError: pass if not self.id: self._password_set = False return self._password_set res = db.fetchone("SELECT password FROM users.logins WHERE id=%s;", [self.id]) if not res: self._password_set = False return self._password_set self._password_set = bool(res['password']) return self._password_set
def delete(self): files = [] for ff in db.fetchall("SELECT files FROM posts.comments " "WHERE post_id=%s;", [unb26(self.id)]): if ff and ff['files']: files.extend(ff['files']) for ff in db.fetchone("DELETE FROM posts.posts WHERE id=%s " "RETURNING files;", [unb26(self.id)]): if ff: files.extend(ff) redis = RedisPool(settings.storage_socket) redis.delete('cmnt_cnt.%s' % unb26(self.id)) for f in files: remove_attach(f)