def remove(userid, submitid=None, charid=None, journalid=None): def remove_transaction(db): delete_result = db.execute( "DELETE FROM favorite WHERE (userid, targetid, type) = (%(user)s, %(target)s, %(type)s)", user=userid, target=d.get_targetid(submitid, charid, journalid), type="s" if submitid else "f" if charid else "j", ) if delete_result.rowcount == 0: return if submitid: db.execute( "UPDATE submission SET favorites = favorites - 1 WHERE submitid = %(target)s", target=submitid, ) welcome.favorite_remove(db, userid, submitid=submitid, charid=charid, journalid=journalid) d.serializable_retry(remove_transaction)
def change_username(acting_user, target_user, bypass_limit, new_username): new_username = clean_display_name(new_username) new_sysname = d.get_sysname(new_username) old_username = d.get_display_name(target_user) old_sysname = d.get_sysname(old_username) if new_username == old_username: return cosmetic = new_sysname == old_sysname def change_username_transaction(db): if not cosmetic and not bypass_limit: seconds = db.scalar( "SELECT extract(epoch from now() - replaced_at)::int8" " FROM username_history" " WHERE userid = %(target)s" " AND NOT cosmetic" " ORDER BY historyid DESC LIMIT 1", target=target_user, ) if seconds is not None: days = seconds // (3600 * 24) if days < 30: raise WeasylError("usernameChangedTooRecently") if not cosmetic: release_username( db, acting_user=acting_user, target_user=target_user, ) conflict = db.scalar( "SELECT EXISTS (SELECT FROM login WHERE login_name = %(new_sysname)s AND userid != %(target)s)" " OR EXISTS (SELECT FROM useralias WHERE alias_name = %(new_sysname)s)" " OR EXISTS (SELECT FROM logincreate WHERE login_name = %(new_sysname)s)" " OR EXISTS (SELECT FROM username_history WHERE active AND login_name = %(new_sysname)s)", target=target_user, new_sysname=new_sysname, ) if conflict: raise WeasylError("usernameExists") db.execute( "INSERT INTO username_history (userid, username, login_name, replaced_at, replaced_by, active, cosmetic)" " VALUES (%(target)s, %(old_username)s, %(old_sysname)s, now(), %(target)s, NOT %(cosmetic)s, %(cosmetic)s)", target=target_user, old_username=old_username, old_sysname=old_sysname, cosmetic=cosmetic, ) if not cosmetic: result = db.execute( "UPDATE login SET login_name = %(new_sysname)s WHERE userid = %(target)s AND login_name = %(old_sysname)s", target=target_user, old_sysname=old_sysname, new_sysname=new_sysname, ) if result.rowcount != 1: raise WeasylError("Unexpected") db.execute( "UPDATE profile SET username = %(new_username)s WHERE userid = %(target)s", target=target_user, new_username=new_username, ) d.serializable_retry(change_username_transaction) d._get_display_name.invalidate(target_user)
def insert(userid, submitid=None, charid=None, journalid=None): if submitid: content_table, id_field, target = "submission", "submitid", submitid elif charid: content_table, id_field, target = "character", "charid", charid else: content_table, id_field, target = "journal", "journalid", journalid query = d.engine.execute( "SELECT userid, settings FROM %s WHERE %s = %i" % (content_table, id_field, target), ).first() if not query: raise WeasylError("TargetRecordMissing") elif userid == query[0]: raise WeasylError("CannotSelfFavorite") elif "f" in query[1] and not frienduser.check(userid, query[0]): raise WeasylError("FriendsOnly") elif ignoreuser.check(userid, query[0]): raise WeasylError("YouIgnored") elif ignoreuser.check(query[0], userid): raise WeasylError("contentOwnerIgnoredYou") notified = [] def insert_transaction(db): insert_result = db.execute( 'INSERT INTO favorite (userid, targetid, type, unixtime) ' 'VALUES (%(user)s, %(target)s, %(type)s, %(now)s) ' 'ON CONFLICT DO NOTHING', user=userid, target=d.get_targetid(submitid, charid, journalid), type='s' if submitid else 'f' if charid else 'j', now=d.get_time()) if insert_result.rowcount == 0: return if submitid: db.execute( "UPDATE submission SET favorites = favorites + 1" " WHERE submitid = %(target)s", target=submitid, ) if not notified: # create a list of users to notify notified_ = collection.find_owners(submitid) # conditions under which "other" should be notified def can_notify(other): other_jsonb = d.get_profile_settings(other) allow_notify = other_jsonb.allow_collection_notifs return allow_notify and not ignoreuser.check(other, userid) notified.extend(u for u in notified_ if can_notify(u)) # always notify for own content notified.append(query[0]) for other in notified: welcome.favorite_insert(db, userid, submitid=submitid, charid=charid, journalid=journalid, otherid=other) d.serializable_retry(insert_transaction)