def insert(userid, target_user, parentid, content, staffnotes): # Check invalid content if not content: raise WeasylError("commentInvalid") elif not target_user or not d.is_vouched_for(target_user): raise WeasylError("Unexpected") # Determine parent userid if parentid: parentuserid = d.engine.scalar( "SELECT userid FROM comments WHERE commentid = %(parent)s", parent=parentid, ) if parentuserid is None: raise WeasylError("shoutRecordMissing") else: parentuserid = None # Check permissions if userid not in staff.MODS: if ignoreuser.check(target_user, userid): raise WeasylError("pageOwnerIgnoredYou") elif ignoreuser.check(userid, target_user): raise WeasylError("youIgnoredPageOwner") elif ignoreuser.check(parentuserid, userid): raise WeasylError("replyRecipientIgnoredYou") elif ignoreuser.check(userid, parentuserid): raise WeasylError("youIgnoredReplyRecipient") _, is_banned, _ = d.get_login_settings(target_user) profile_config = d.get_config(target_user) if is_banned or "w" in profile_config or "x" in profile_config and not frienduser.check( userid, target_user): raise WeasylError("insufficientActionPermissions") # Create comment settings = 's' if staffnotes else '' co = d.meta.tables['comments'] db = d.connect() commentid = db.scalar(co.insert().values(userid=userid, target_user=target_user, parentid=parentid or None, content=content, unixtime=arrow.utcnow(), settings=settings).returning( co.c.commentid)) # Create notification if parentid and userid != parentuserid: if not staffnotes or parentuserid in staff.MODS: welcome.shoutreply_insert(userid, commentid, parentuserid, parentid, staffnotes) elif not staffnotes and target_user and userid != target_user: welcome.shout_insert(userid, commentid, otherid=target_user) d.metric('increment', 'shouts') return commentid
def select_profile(userid, viewer=None): query = d.engine.execute(""" SELECT pr.username, pr.full_name, pr.catchphrase, pr.created_at, pr.profile_text, pr.settings, pr.stream_url, pr.config, pr.stream_text, us.end_time FROM profile pr INNER JOIN login lo USING (userid) LEFT JOIN user_streams us USING (userid) WHERE userid = %(user)s """, user=userid).first() if not query: raise WeasylError('userRecordMissing') is_banned, is_suspended = d.get_login_settings(userid) streaming_status = "stopped" if query[6]: # profile.stream_url if 'l' in query[5]: streaming_status = "later" elif query[9] is not None and query[9] > d.get_time( ): # user_streams.end_time streaming_status = "started" return { "userid": userid, "user_media": media.get_user_media(userid), "username": query[0], "full_name": query[1], "catchphrase": query[2], "unixtime": query[3], "profile_text": query[4], "settings": query[5], "stream_url": query[6], "stream_text": query[8], "config": query[7], "show_favorites_bar": "u" not in query[7] and "v" not in query[7], "show_favorites_tab": userid == viewer or "v" not in query[7], "commish_slots": 0, "banned": is_banned, "suspended": is_suspended, "streaming_status": streaming_status, }
def authenticate_bcrypt(username, password, request, ip_address=None, user_agent=None): """ Return a result tuple of the form (userid, error); `error` is None if the login was successful. Pass None as the `request` to authenticate a user without creating a new session. :param username: The username of the user attempting authentication. :param password: The user's claimed password to check against the stored hash. :param request: The request, or None :param ip_address: The address requesting authentication. :param user_agent: The user agent string of the submitting client. Possible errors are: - "invalid" - "unexpected" - "banned" - "suspended" - "2fa" - Indicates the user has opted-in to 2FA. Additional authentication required. """ # Check that the user entered potentially valid values for `username` and # `password` before attempting to authenticate them if not username or not password: return 0, "invalid" # Select the authentication data necessary to check that the the user-entered # credentials are valid query = d.engine.execute( "SELECT ab.userid, ab.hashsum, lo.twofa_secret FROM authbcrypt ab" " RIGHT JOIN login lo USING (userid)" " WHERE lo.login_name = %(name)s", name=d.get_sysname(username), ).first() if not query: return 0, "invalid" USERID, HASHSUM, TWOFA = query HASHSUM = HASHSUM.encode('utf-8') _, IS_BANNED, IS_SUSPENDED = d.get_login_settings(USERID) d.metric('increment', 'attemptedlogins') if not bcrypt.checkpw(password.encode('utf-8'), HASHSUM): # Log the failed login attempt in a security log if the account the user # attempted to log into is a privileged account if USERID in staff.MODS: d.append_to_log('login.fail', userid=USERID, ip=d.get_address()) d.metric('increment', 'failedlogins') # Return a zero userid and an error code (indicating the entered password # was incorrect) return 0, "invalid" elif IS_BANNED: # Return the proper userid and an error code (indicating the user's account # has been banned) return USERID, "banned" elif IS_SUSPENDED: from weasyl import moderation suspension = moderation.get_suspension(USERID) if d.get_time() > suspension.release: d.execute("DELETE FROM suspension WHERE userid = %i", [USERID]) d._get_all_config.invalidate(USERID) else: # Return the proper userid and an error code (indicating the user's # account has been temporarily suspended) return USERID, "suspended" # Attempt to create a new session if this is a request to log in, then log the signin # if it succeeded. if request is not None: # If the user's record has ``login.twofa_secret`` set (not nulled), return that password authentication succeeded. if TWOFA: if not isinstance(request.weasyl_session, GuestSession): request.pg_connection.delete(request.weasyl_session) request.pg_connection.flush() request.weasyl_session = create_session(None) request.weasyl_session.additional_data = {} return USERID, "2fa" else: signin(request, USERID, ip_address=ip_address, user_agent=user_agent) # Either way, authentication succeeded, so return the userid and a status. return USERID, None