def charactersbyuser(userid, form): if userid not in staff.MODS: raise WeasylError("Unexpected") query = d.execute(""" SELECT ch.charid, pr.username, ch.unixtime, ch.char_name, ch.age, ch.gender, ch.height, ch.weight, ch.species, ch.content, ch.rating, ch.settings, ch.page_views, pr.config FROM character ch INNER JOIN profile pr ON ch.userid = pr.userid INNER JOIN login ON ch.userid = login.userid WHERE login.login_name = '%s' """, [d.get_sysname(form.name)]) return [{ "contype": 20, "userid": userid, "charid": item[0], "username": item[1], "unixtime": item[2], "title": item[3], "rating": item[10], "settings": item[11], "sub_media": character.fake_media_items(item[0], userid, d.get_sysname(item[1]), item[11]), } for item in query]
def resolve(userid, otherid, othername, myself=True): """ Attempts to determine the userid of a specified user; resolves using otherid, othername, and userid (if myself is True), in that order. If no userid can be resolved, returns 0 instead. """ result = None if otherid: result = d.execute("SELECT userid FROM login WHERE userid = %i", [d.get_int(otherid)], ["element"]) if result: return result elif othername: result = d.execute("SELECT userid FROM login WHERE login_name = '%s'", [d.get_sysname(othername)], ["element"]) if result: return result result = d.execute("SELECT userid FROM useralias WHERE alias_name = '%s'", [d.get_sysname(othername)], ["element"]) if result: return result elif userid and myself: return userid return 0
def add_criterion(self, criterion): def add_nonempty(s, item): if item: s.add(item) find_modifier = _QUERY_FIND_MODIFIERS.get(criterion) if find_modifier: self.find = find_modifier return rating_modifier = _QUERY_RATING_MODIFIERS.get(criterion) if rating_modifier: self.ratings.add(rating_modifier) return if criterion.startswith(("user:"******"+user:"******":", 1)[1]) add_nonempty(self.required_user_includes, user) elif criterion.startswith("-user:"******":", 1)[1]) add_nonempty(self.required_user_excludes, user) elif criterion.startswith("+"): tag = d.get_search_tag(criterion[1:]) add_nonempty(self.required_includes, tag) elif criterion.startswith("-"): tag = d.get_search_tag(criterion[1:]) add_nonempty(self.required_excludes, tag) elif criterion.startswith("|"): tag = d.get_search_tag(criterion[1:]) add_nonempty(self.possible_includes, tag) else: tag = d.get_search_tag(criterion) add_nonempty(self.required_includes, tag)
def resolve(userid, otherid, othername, myself=True): """ Attempts to determine the userid of a specified user; resolves using otherid, othername, and userid (if myself is True), in that order. If no userid can be resolved, returns 0 instead. """ result = None if otherid: result = d.execute("SELECT userid FROM login WHERE userid = %i", [d.get_int(otherid)], ["element"]) if result: return result elif othername: result = d.execute("SELECT userid FROM login WHERE login_name = '%s'", [d.get_sysname(othername)], ["element"]) if result: return result result = d.execute( "SELECT userid FROM useralias WHERE alias_name = '%s'", [d.get_sysname(othername)], ["element"]) if result: return result elif userid and myself: return userid return 0
def control_streaming_post_(request): form = request.web_input(target="", set_stream="", stream_length="", stream_url="", stream_text="") if form.target and request.userid not in staff.MODS: raise WeasylError('InsufficientPermissions') if form.target: target = int(form.target) else: target = request.userid stream_length = define.clamp(define.get_int(form.stream_length), 0, 360) p = orm.Profile() p.stream_text = form.stream_text p.stream_url = define.text_fix_url(form.stream_url.strip()) set_stream = form.set_stream profile.edit_streaming_settings(request.userid, target, p, set_stream=set_stream, stream_length=stream_length) if form.target: target_username = define.get_sysname(define.get_display_name(target)) raise HTTPSeeOther(location="/modcontrol/manageuser?name=" + target_username) else: raise HTTPSeeOther(location="/control")
def frienduser_(request): if not define.is_vouched_for(request.userid): raise WeasylError("vouchRequired") form = request.web_input(userid="") otherid = define.get_int(form.userid) if request.userid == otherid: raise WeasylError('cannotSelfFriend') if form.action == "sendfriendrequest": if not frienduser.check(request.userid, otherid) and not frienduser.already_pending( request.userid, otherid): frienduser.request(request.userid, otherid) elif form.action == "withdrawfriendrequest": if frienduser.already_pending(request.userid, otherid): frienduser.remove_request(request.userid, otherid) elif form.action == "unfriend": frienduser.remove(request.userid, otherid) if form.feature == "pending": raise HTTPSeeOther(location="/manage/friends?feature=pending") else: # typical value will be user raise HTTPSeeOther( location="/~%s" % (define.get_sysname(define.get_display_name(otherid))))
def submissionsbyuser(userid, form): if userid not in staff.MODS: raise WeasylError("Unexpected") query = d.execute( """ SELECT su.submitid, su.title, su.rating, su.unixtime, su.userid, pr.username, su.settings FROM submission su INNER JOIN profile pr USING (userid) WHERE su.userid = (SELECT userid FROM login WHERE login_name = '%s') ORDER BY su.submitid DESC """, [d.get_sysname(form.name)]) ret = [{ "contype": 10, "submitid": i[0], "title": i[1], "rating": i[2], "unixtime": i[3], "userid": i[4], "username": i[5], "settings": i[6], } for i in query] media.populate_with_submission_media(ret) return ret
def control_streaming_post_(request): form = request.web_input(target="", set_stream="", stream_length="", stream_url="", stream_text="") if form.target and request.userid not in staff.MODS: return Response(define.errorpage(request.userid, errorcode.permission)) if form.target: target = int(form.target) else: target = request.userid stream_length = define.clamp(define.get_int(form.stream_length), 0, 360) p = orm.Profile() p.stream_text = form.stream_text p.stream_url = define.text_fix_url(form.stream_url.strip()) set_stream = form.set_stream profile.edit_streaming_settings(request.userid, target, p, set_stream=set_stream, stream_length=stream_length) if form.target: target_username = define.get_sysname(define.get_display_name(target)) raise HTTPSeeOther(location="/modcontrol/manageuser?name=" + target_username) else: raise HTTPSeeOther(location="/control")
def tidy_submission(submission): submission['posted_at'] = d.iso8601(submission.pop('unixtime')) submission['sub_media'] = api.tidy_all_media(submission['sub_media']) if 'user_media' in submission: submission['owner_media'] = api.tidy_all_media( submission.pop('user_media')) submission.pop('userid', None) subtype = submission.pop('subtype', None) if subtype: submission['subtype'] = m.CATEGORY_PARSABLE_MAP[subtype // 1000 * 1000] contype = submission.pop('contype', None) if contype: submission['type'] = m.CONTYPE_PARSABLE_MAP[contype] submission['rating'] = ratings.CODE_TO_NAME[submission['rating']] submission['owner'] = submission.pop('username') submission['owner_login'] = d.get_sysname(submission['owner']) submission['media'] = submission.pop('sub_media') submitid = 0 if 'submitid' in submission: submitid = submission['submitid'] if 'charid' in submission: submitid = submission['charid'] if submitid > 0: if submission['type'] == "usercollect": linktype = "submission" else: linktype = submission['type'] submission['link'] = d.absolutify_url( "/%s/%d/%s" % (linktype, submitid, slug_for(submission['title'])))
def tidy_submission(submission): submission['posted_at'] = d.iso8601(submission.pop('unixtime')) submission['sub_media'] = api.tidy_all_media(submission['sub_media']) if 'user_media' in submission: submission['owner_media'] = api.tidy_all_media(submission.pop('user_media')) submission.pop('userid', None) subtype = submission.pop('subtype', None) if subtype: submission['subtype'] = m.CATEGORY_PARSABLE_MAP[subtype // 1000 * 1000] contype = submission.pop('contype', None) if contype: submission['type'] = m.CONTYPE_PARSABLE_MAP[contype] submission['rating'] = ratings.CODE_TO_NAME[submission['rating']] submission['owner'] = submission.pop('username') submission['owner_login'] = d.get_sysname(submission['owner']) submission['media'] = submission.pop('sub_media') submitid = 0 if 'submitid' in submission: submitid = submission['submitid'] if 'charid' in submission: submitid = submission['charid'] if submitid > 0: if submission['type'] == "usercollect": linktype = "submission" else: linktype = submission['type'] submission['link'] = d.absolutify_url( "/%s/%d/%s" % (linktype, submitid, slug_for(submission['title']))) return submission
def select_view_api(userid, journalid, anyway=False, increment_views=False): rating = d.get_rating(userid) journal = _select_journal_and_check( userid, journalid, rating=rating, ignore=anyway, anyway=anyway, increment_views=increment_views) return { 'journalid': journalid, 'title': journal['title'], 'owner': journal['username'], 'owner_login': d.get_sysname(journal['username']), 'owner_media': api.tidy_all_media( media.get_user_media(journal['userid'])), 'content': text.markdown(journal['content']), 'tags': searchtag.select(journalid=journalid), 'link': d.absolutify_url('/journal/%d/%s' % (journalid, text.slug_for(journal['title']))), 'type': 'journal', 'rating': ratings.CODE_TO_NAME[journal['rating']], 'views': journal['page_views'], 'favorites': favorite.count(journalid, 'journal'), 'comments': comment.count(journalid, 'journal'), 'favorited': favorite.check(userid, journalid=journalid), 'friends_only': 'f' in journal['settings'], 'posted_at': d.iso8601(journal['unixtime']), }
def api_user_gallery_(request): userid = profile.resolve_by_login(d.get_sysname(request.matchdict['login'])) if not userid: raise WeasylError('userRecordMissing') form = request.web_input(since=None, count=0, folderid=0, backid=0, nextid=0) since = None try: if form.since: since = d.parse_iso8601(form.since) count = int(form.count) folderid = int(form.folderid) backid = int(form.backid) nextid = int(form.nextid) except ValueError: raise HTTPUnprocessableEntity(json=_ERROR_UNEXPECTED) else: count = min(count or 100, 100) submissions = submission.select_list( request.userid, d.get_rating(request.userid), count + 1, otherid=userid, folderid=folderid, backid=backid, nextid=nextid) backid, nextid = d.paginate(submissions, backid, nextid, count, 'submitid') ret = [] for sub in submissions: if since is not None and since >= sub['unixtime']: break tidy_submission(sub) ret.append(sub) return { 'backid': backid, 'nextid': nextid, 'submissions': ret, }
def _fake_media_items(i): if i.contype == _CONTYPE_CHAR: return character.fake_media_items(i.id, i.userid, d.get_sysname(i.username), i.settings) else: return None
def vouch_(request): if not define.is_vouched_for(request.userid): raise WeasylError("vouchRequired") targetid = int(request.POST['targetid']) updated = define.engine.execute( "UPDATE login SET voucher = %(voucher)s WHERE userid = %(target)s AND voucher IS NULL RETURNING email", voucher=request.userid, target=targetid, ).first() target_username = define.get_display_name(targetid) if updated is not None: define._get_all_config.invalidate(targetid) emailer.send(updated.email, "Weasyl Account Verified", define.render("email/verified.html", [target_username])) if target_username is None: assert updated is None raise WeasylError("Unexpected") raise HTTPSeeOther(location=request.route_path( 'profile_tilde', name=define.get_sysname(target_username)))
def frienduser_(request): form = request.web_input(userid="") otherid = define.get_int(form.userid) if request.userid == otherid: return Response( define.errorpage(request.userid, "You cannot friend yourself.")) if form.action == "sendfriendrequest": if not frienduser.check(request.userid, otherid) and not frienduser.already_pending( request.userid, otherid): frienduser.request(request.userid, otherid) elif form.action == "withdrawfriendrequest": if frienduser.already_pending(request.userid, otherid): frienduser.remove_request(request.userid, otherid) elif form.action == "unfriend": frienduser.remove(request.userid, otherid) if form.feature == "pending": raise HTTPSeeOther(location="/manage/friends?feature=pending") else: # typical value will be user raise HTTPSeeOther( location="/~%s" % (define.get_sysname(define.get_display_name(otherid))))
def select_view(userid, charid, rating, ignore=True, anyway=None): query = _select_character_and_check( userid, charid, rating=rating, ignore=ignore, anyway=anyway == 'anyway') login = define.get_sysname(query['username']) return { 'charid': charid, 'userid': query['userid'], 'username': query['username'], 'user_media': media.get_user_media(query['userid']), 'mine': userid == query['userid'], 'unixtime': query['unixtime'], 'title': query['char_name'], 'age': query['age'], 'gender': query['gender'], 'height': query['height'], 'weight': query['weight'], 'species': query['species'], 'content': query['content'], 'rating': query['rating'], 'settings': query['settings'], 'reported': report.check(charid=charid), 'favorited': favorite.check(userid, charid=charid), 'page_views': query['page_views'], 'friends_only': 'f' in query['settings'], 'hidden_submission': 'h' in query['settings'], 'fave_count': favorite.count(charid, 'character'), 'comments': comment.select(userid, charid=charid), 'sub_media': fake_media_items( charid, query['userid'], login, query['settings']), 'tags': searchtag.select(charid=charid), }
def select_view(userid, charid, rating, ignore=True, anyway=None): query = _select_character_and_check( userid, charid, rating=rating, ignore=ignore, anyway=anyway == "true") login = define.get_sysname(query['username']) return { 'charid': charid, 'userid': query['userid'], 'username': query['username'], 'user_media': media.get_user_media(query['userid']), 'mine': userid == query['userid'], 'unixtime': query['unixtime'], 'title': query['char_name'], 'age': query['age'], 'gender': query['gender'], 'height': query['height'], 'weight': query['weight'], 'species': query['species'], 'content': query['content'], 'rating': query['rating'], 'settings': query['settings'], 'reported': report.check(charid=charid), 'favorited': favorite.check(userid, charid=charid), 'page_views': query['page_views'], 'friends_only': 'f' in query['settings'], 'hidden_submission': 'h' in query['settings'], 'fave_count': favorite.count(charid, 'character'), 'comments': comment.select(userid, charid=charid), 'sub_media': fake_media_items( charid, query['userid'], login, query['settings']), 'tags': searchtag.select(charid=charid), }
def request(form): token = security.generate_key(100) email = emailer.normalize_address(form.email) username = d.get_sysname(form.username) # Determine the user associated with `username`; if the user is not found, # raise an exception user = d.engine.execute( "SELECT userid, email FROM login WHERE login_name = %(username)s", username=username).first() if not user: raise WeasylError("loginRecordMissing") # Check the user's email address against the provided e-mail address, # raising an exception if there is a mismatch if email != emailer.normalize_address(user.email): raise WeasylError("emailInvalid") # Insert a record into the forgotpassword table for the user, # or update an existing one now = d.get_time() address = d.get_address() d.engine.execute(""" INSERT INTO forgotpassword (userid, token, set_time, address) VALUES (%(id)s, %(token)s, %(time)s, %(address)s) ON CONFLICT (userid) DO UPDATE SET token = %(token)s, set_time = %(time)s, address = %(address)s """, id=user.userid, token=token, time=now, address=address) # Generate and send an email to the user containing a password reset link emailer.append([email], None, "Weasyl Password Recovery", d.render("email/reset_password.html", [token]))
def create(form): # Normalize form data username = d.plaintext(form.username[:_USERNAME]) sysname = d.get_sysname(username) email = emailer.normalize_address(form.email) emailcheck = emailer.normalize_address(form.emailcheck) password = form.password passcheck = form.passcheck if form.day and form.month and form.year: try: birthday = arrow.Arrow(int(form.year), int(form.month), int(form.day)) except ValueError: raise WeasylError("birthdayInvalid") else: birthday = None # Check mismatched form data if password != passcheck: raise WeasylError("passwordMismatch") if email != emailcheck: raise WeasylError("emailMismatch") # Check invalid form data if birthday is None or d.age_in_years(birthday) < 13: raise WeasylError("birthdayInvalid") if not password_secure(password): raise WeasylError("passwordInsecure") if not email: raise WeasylError("emailInvalid") if not sysname or ";" in username: raise WeasylError("usernameInvalid") if sysname in ["admin", "administrator", "mod", "moderator", "weasyl", "weasyladmin", "weasylmod", "staff", "security"]: raise WeasylError("usernameInvalid") if email_exists(email): raise WeasylError("emailExists") if username_exists(sysname): raise WeasylError("usernameExists") # Create pending account token = security.generate_key(40) d.engine.execute(d.meta.tables["logincreate"].insert(), { "token": token, "username": username, "login_name": sysname, "hashpass": passhash(password), "email": email, "birthday": birthday, "unixtime": arrow.now(), }) # Queue verification email emailer.append([email], None, "Weasyl Account Creation", d.render( "email/verify_account.html", [token, sysname])) d.metric('increment', 'createdusers')
def select_list(userid, form): # Find the unique violation types and the number of reporters. This will be # joined against the Report model to get the violations/reporters for each # selected report. subq = ( ReportComment.dbsession.query( ReportComment.reportid, sa.func.count(), sa.type_coerce( sa.func.array_agg(ReportComment.violation.distinct()), ARRAY(sa.Integer, as_tuple=True)).label('violations')) .filter(ReportComment.violation != 0) .group_by(ReportComment.reportid) .subquery()) # Find reports, joining against the aforementioned subquery, and eager-load # the reports' owners. q = ( Report.dbsession.query(Report, subq) .options(joinedload(Report.owner)) .join(subq, Report.reportid == subq.c.reportid) .reset_joinpoint()) # For each type of report, eagerly load the content reported and the # content's owner. Also, keep track of the Login model aliases used for each # report type so they can be filtered against later. login_aliases = [] for column_name in _report_types: login_alias = aliased(Login) login_aliases.append(login_alias) q = ( q .outerjoin(getattr(Report, column_name)) .outerjoin(login_alias) .options(contains_eager(column_name + '.owner', alias=login_alias)) .reset_joinpoint()) # Filter by report status. form.status can also be 'all', in which case no # filter is applied. if form.status == 'closed': q = q.filter_by(is_closed=True) elif form.status == 'open': q = q.filter_by(is_closed=False) # If filtering by the report's content's owner, iterate over the previously # collected Login model aliases to compare against Login.login_name. if form.submitter: submitter = d.get_sysname(form.submitter) q = q.filter(sa.or_(l.login_name == submitter for l in login_aliases)) # If filtering by violation type, see if the violation is in the array # aggregate of unique violations for this report. if form.violation and form.violation != '-1': q = q.filter(sa.literal(int(form.violation)) == sa.func.any(subq.c.violations)) q = q.order_by(Report.opened_at.desc()) return [(report, report_count, map(_convert_violation, violations)) for report, _, report_count, violations in q.all()]
def submissions_(request): name = request.matchdict.get('name', request.params.get('name', '')) userid = define.get_int(request.params.get('userid')) rating = define.get_rating(request.userid) otherid = profile.resolve(request.userid, userid, name) folderid = define.get_int(request.params.get('folderid')) or None backid = request.params.get('backid') nextid = request.params.get('nextid') if not otherid: raise WeasylError("userRecordMissing") elif not request.userid and "h" in define.get_config(otherid): raise WeasylError('noGuests') userprofile = profile.select_profile(otherid, viewer=request.userid) has_fullname = userprofile[ 'full_name'] is not None and userprofile['full_name'].strip() != '' page_title = u"%s's submissions" % (userprofile['full_name'] if has_fullname else userprofile['username'], ) page = define.common_page_start(request.userid, title=page_title) url_format = "/submissions/{username}?%s{folderquery}".format( username=define.get_sysname(userprofile['username']), folderquery="&folderid=%d" % folderid if folderid else "") result = pagination.PaginatedResult(submission.select_list, submission.select_count, 'submitid', url_format, request.userid, rating, limit=60, otherid=otherid, folderid=folderid, backid=define.get_int(backid), nextid=define.get_int(nextid), profile_page_filter=not folderid) page.append( define.render( 'user/submissions.html', [ # Profile information userprofile, # User information profile.select_userinfo(otherid, config=userprofile['config']), # Relationship profile.select_relation(request.userid, otherid), # Recent submissions result, # Folders folder.select_list(otherid), # Current folder folderid, ])) return Response(define.common_page_end(request.userid, page))
def _fake_media_items(i): if i.contype == _CONTYPE_CHAR: return character.fake_media_items( i.id, i.userid, d.get_sysname(i.username), i.settings) else: return None
def submission_(request): username = request.matchdict.get('name') submitid = request.matchdict.get('submitid') form = request.web_input(submitid="", ignore="", anyway="") rating = define.get_rating(request.userid) submitid = define.get_int(submitid) if submitid else define.get_int(form.submitid) extras = { "pdf": True, } if define.user_is_twitterbot(): extras['twitter_card'] = submission.twitter_card(submitid) try: item = submission.select_view( request.userid, submitid, rating, ignore=define.text_bool(form.ignore, True), anyway=form.anyway ) except WeasylError as we: we.errorpage_kwargs = extras if 'twitter_card' in extras: extras['options'] = ['nocache'] if we.value in ("UserIgnored", "TagBlocked"): extras['links'] = [ ("View Submission", "?ignore=false"), ("Return to the Home Page", "/index"), ] raise login = define.get_sysname(item['username']) canonical_path = request.route_path('submission_detail_profile', name=login, submitid=submitid, slug=slug_for(item['title'])) if request.GET.get('anyway'): canonical_path += '?anyway=true' if login != username: raise httpexceptions.HTTPMovedPermanently(location=canonical_path) extras["canonical_url"] = canonical_path extras["title"] = item["title"] page = define.common_page_start(request.userid, **extras) page.append(define.render('detail/submission.html', [ # Myself profile.select_myself(request.userid), # Submission detail item, # Subtypes macro.MACRO_SUBCAT_LIST, # Violations [i for i in macro.MACRO_REPORT_VIOLATION if 2000 <= i[0] < 3000], ])) return Response(define.common_page_end(request.userid, page))
def prepare(info): dinfo = dict(info) dinfo['localmin'] = convert_currency(info.pricemin, info.pricesettings, currency) dinfo['localmax'] = convert_currency(info.pricemax, info.pricesettings, currency) if tags: terms = ["user:"******"|" + tag for tag in tags] dinfo['searchquery'] = "q=" + urllib.quote(u" ".join(terms).encode("utf-8")) else: dinfo['searchquery'] = "" return dinfo
def GET(self, a="", b=None): if b is None: username, submitid = None, a else: username, submitid = a, b now = time.time() form = web.input(submitid="", ignore="", anyway="") rating = define.get_rating(self.user_id) submitid = define.get_int(submitid) if submitid else define.get_int(form.submitid) extras = { "pdf": True, } if define.user_is_twitterbot(): extras['twitter_card'] = submission.twitter_card(submitid) try: item = submission.select_view( self.user_id, submitid, rating, ignore=define.text_bool(form.ignore, True), anyway=form.anyway ) except WeasylError as we: we.errorpage_kwargs = extras if 'twitter_card' in extras: extras['options'] = ['nocache'] if we.value in ("UserIgnored", "TagBlocked"): extras['links'] = [ ("View Submission", "?ignore=false"), ("Return to the Home Page", "/index"), ] raise login = define.get_sysname(item['username']) if username is not None and login != username: raise web.seeother('/~%s/post/%s/%s' % (login, submitid, slug_for(item["title"]))) extras["canonical_url"] = "/submission/%d/%s" % (submitid, slug_for(item["title"])) extras["title"] = item["title"] page = define.common_page_start(self.user_id, options=["mediaplayer"], **extras) page.append(define.render('detail/submission.html', [ # Myself profile.select_myself(self.user_id), # Submission detail item, # Subtypes macro.MACRO_SUBCAT_LIST, # Violations [i for i in macro.MACRO_REPORT_VIOLATION if 2000 <= i[0] < 3000], ])) return define.common_page_end(self.user_id, page, now=now)
def api_useravatar_(request): form = request.web_input(username="") userid = profile.resolve_by_login(d.get_sysname(form.username)) if userid: media_items = media.get_user_media(userid) return { "avatar": d.absolutify_url(media_items['avatar'][0]['display_url']), } raise WeasylError('userRecordMissing')
def ignoreuser_(request): form = request.web_input(userid="") otherid = define.get_int(form.userid) if form.action == "ignore": ignoreuser.insert(request.userid, [otherid]) elif form.action == "unignore": ignoreuser.remove(request.userid, [otherid]) raise HTTPSeeOther(location="/~%s" % (define.get_sysname(define.get_display_name(otherid))))
def POST(self): form = web.input(userid="") otherid = define.get_int(form.userid) if form.action == "ignore": if not ignoreuser.check(self.user_id, otherid): ignoreuser.insert(self.user_id, otherid) elif form.action == "unignore": ignoreuser.remove(self.user_id, otherid) raise web.seeother("/~%s" % (define.get_sysname(define.get_display_name(otherid))))
def ignoreuser_(request): form = request.web_input(userid="") otherid = define.get_int(form.userid) if form.action == "ignore": if not ignoreuser.check(request.userid, otherid): ignoreuser.insert(request.userid, otherid) elif form.action == "unignore": ignoreuser.remove(request.userid, otherid) raise HTTPSeeOther(location="/~%s" % (define.get_sysname(define.get_display_name(otherid))))
def select_char(userid, rating, limit, otherid=None, backid=None, nextid=None, config=None): if config is None: config = d.get_config(userid) query = [] statement = [""" SELECT ch.charid, ch.char_name, ch.rating, fa.unixtime, ch.userid, pr.username, ch.settings FROM favorite fa INNER JOIN character ch ON fa.targetid = ch.charid INNER JOIN profile pr ON ch.userid = pr.userid WHERE fa.type = 'f' AND ch.settings !~ 'h' """] if userid: # filter own content in SFW mode if d.is_sfw_mode(): statement.append(" AND (ch.rating <= %i)" % (rating,)) else: statement.append(" AND (ch.userid = %i OR ch.rating <= %i)" % (userid, rating)) statement.append(m.MACRO_FRIENDUSER_CHARACTER % (userid, userid, userid)) statement.append(m.MACRO_IGNOREUSER % (userid, "ch")) statement.append(m.MACRO_BLOCKTAG_CHAR % (userid, userid)) else: statement.append(" AND ch.rating <= %i AND ch.settings !~ 'f'" % (rating,)) if otherid: statement.append(" AND fa.userid = %i" % (otherid,)) if backid: statement.append(" AND fa.unixtime > " "(SELECT unixtime FROM favorite WHERE (userid, targetid, type) = (%i, %i, 'f'))" % (otherid, backid)) elif nextid: statement.append(" AND fa.unixtime < " "(SELECT unixtime FROM favorite WHERE (userid, targetid, type) = (%i, %i, 'f'))" % (otherid, nextid)) statement.append(" ORDER BY fa.unixtime%s LIMIT %i" % ("" if backid else " DESC", limit)) from weasyl import character query = [{ "contype": 20, "charid": i[0], "title": i[1], "rating": i[2], "unixtime": i[3], "userid": i[4], "username": i[5], "sub_media": character.fake_media_items(i[0], i[4], d.get_sysname(i[5]), i[6]), } for i in d.execute("".join(statement))] return query[::-1] if backid else query
def get_account_verification_token(email=None, username=None): email = email and emailer.normalize_address(email) username = username and d.get_sysname(username) logincreate = d.meta.tables['logincreate'] statement = select([logincreate.c.token]) if email: statement = statement.where(logincreate.c.email.ilike(email)) else: statement = statement.where(logincreate.c.login_name == username) return d.engine.scalar(statement)
def verify(token, ip_address=None): lo = d.meta.tables["login"] lc = d.meta.tables["logincreate"] query = d.engine.execute(lc.select().where(lc.c.token == token)).first() # Did the token match a pending login create record? if not query: raise WeasylError("logincreateRecordMissing") elif query.invalid: # If the record is explicitly marked as invalid, treat the record as if it doesn't exist. raise WeasylError("logincreateRecordMissing") db = d.connect() with db.begin(): # Create login record userid = db.scalar( lo.insert().returning(lo.c.userid), { "login_name": d.get_sysname(query.username), "last_login": arrow.now(), "email": query.email, "ip_address_at_signup": ip_address, }) # Create profile records db.execute(d.meta.tables["authbcrypt"].insert(), { "userid": userid, "hashsum": query.hashpass, }) db.execute( d.meta.tables["profile"].insert(), { "userid": userid, "username": query.username, "full_name": query.username, "unixtime": arrow.now(), "config": "kscftj", }) db.execute(d.meta.tables["userinfo"].insert(), { "userid": userid, "birthday": query.birthday, }) db.execute(d.meta.tables["userstats"].insert(), { "userid": userid, }) db.execute(d.meta.tables["welcomecount"].insert(), { "userid": userid, }) # Update logincreate records db.execute(lc.delete().where(lc.c.token == token)) d.metric('increment', 'verifiedusers')
def followuser_(request): form = request.web_input(userid="") otherid = define.get_int(form.userid) if request.userid == otherid: return Response(define.errorpage(request.userid, "You cannot follow yourself.")) if form.action == "follow": if not followuser.check(request.userid, otherid): followuser.insert(request.userid, otherid) elif form.action == "unfollow": followuser.remove(request.userid, otherid) raise HTTPSeeOther(location="/~%s" % (define.get_sysname(define.get_display_name(otherid))))
def prepare(info): dinfo = dict(info) dinfo['localmin'] = convert_currency(info.pricemin, info.pricesettings, currency) dinfo['localmax'] = convert_currency(info.pricemax, info.pricesettings, currency) if tags: terms = ["user:"******"|" + tag for tag in tags] dinfo['searchquery'] = "q=" + urllib.quote( u" ".join(terms).encode("utf-8")) else: dinfo['searchquery'] = "" return dinfo
def followuser_(request): form = request.web_input(userid="") otherid = define.get_int(form.userid) if request.userid == otherid: raise WeasylError("cannotSelfFollow") if form.action == "follow": followuser.insert(request.userid, otherid) elif form.action == "unfollow": followuser.remove(request.userid, otherid) raise HTTPSeeOther(location="/~%s" % (define.get_sysname(define.get_display_name(otherid))))
def select(**kwargs): search = kwargs['search'] results, next_count, back_count = _find_without_media(**kwargs) if search.find == 'submit': media.populate_with_submission_media(results) elif search.find == 'char': for r in results: r['sub_media'] = character.fake_media_items( r['charid'], r['userid'], d.get_sysname(r['username']), r['settings']) elif search.find == 'journal': media.populate_with_user_media(results) return results, next_count, back_count
def journalsbyuser(userid, form): if userid not in staff.MODS: raise WeasylError("Unexpected") results = d.engine.execute(""" SELECT journalid, title, journal.settings, journal.unixtime, rating, profile.username, 30 contype FROM journal JOIN profile USING (userid) JOIN login USING (userid) WHERE login_name = %(sysname)s """, sysname=d.get_sysname(form.name)).fetchall() return map(dict, results)
def POST(self): form = web.input(userid="") otherid = define.get_int(form.userid) if self.user_id == otherid: return define.errorpage(self.user_id, "You cannot follow yourself.") if form.action == "follow": if not followuser.check(self.user_id, otherid): followuser.insert(self.user_id, otherid) elif form.action == "unfollow": followuser.remove(self.user_id, otherid) raise web.seeother("/~%s" % (define.get_sysname(define.get_display_name(otherid))))
def verify(token, ip_address=None): lo = d.meta.tables["login"] lc = d.meta.tables["logincreate"] query = d.engine.execute(lc.select().where(lc.c.token == token)).first() # Did the token match a pending login create record? if not query: raise WeasylError("logincreateRecordMissing") elif query.invalid: # If the record is explicitly marked as invalid, treat the record as if it doesn't exist. raise WeasylError("logincreateRecordMissing") db = d.connect() with db.begin(): # Create login record userid = db.scalar(lo.insert().returning(lo.c.userid), { "login_name": d.get_sysname(query.username), "last_login": arrow.now(), "email": query.email, "ip_address_at_signup": ip_address, }) # Create profile records db.execute(d.meta.tables["authbcrypt"].insert(), { "userid": userid, "hashsum": query.hashpass, }) db.execute(d.meta.tables["profile"].insert(), { "userid": userid, "username": query.username, "full_name": query.username, "unixtime": arrow.now(), "config": "kscftj", }) db.execute(d.meta.tables["userinfo"].insert(), { "userid": userid, "birthday": query.birthday, }) db.execute(d.meta.tables["userstats"].insert(), { "userid": userid, }) db.execute(d.meta.tables["welcomecount"].insert(), { "userid": userid, }) # Update logincreate records db.execute(lc.delete().where(lc.c.token == token)) d.metric('increment', 'verifiedusers')
def reset(form): from weasyl import login # Raise an exception if `password` does not enter `passcheck` (indicating # that the user mistyped one of the fields) or if `password` does not meet # the system's password security requirements if form.password != form.passcheck: raise WeasylError("passwordMismatch") elif not login.password_secure(form.password): raise WeasylError("passwordInsecure") # Select the user information and record data from the forgotpassword table # pertaining to `token`, requiring that the link associated with the record # be visited no more than five minutes prior; if the forgotpassword record is # not found or does not meet this requirement, raise an exception query = d.engine.execute(""" SELECT lo.userid, lo.login_name, lo.email, fp.link_time, fp.address FROM login lo INNER JOIN userinfo ui USING (userid) INNER JOIN forgotpassword fp USING (userid) WHERE fp.token = %(token)s AND fp.link_time > %(cutoff)s """, token=form.token, cutoff=d.get_time() - 300).first() if not query: raise WeasylError("forgotpasswordRecordMissing") USERID, USERNAME, EMAIL, LINKTIME, ADDRESS = query # Check `username` and `email` against known correct values and raise an # exception if there is a mismatch if emailer.normalize_address( form.email) != emailer.normalize_address(EMAIL): raise WeasylError("emailIncorrect") elif d.get_sysname(form.username) != USERNAME: raise WeasylError("usernameIncorrect") elif d.get_address() != ADDRESS: raise WeasylError("addressInvalid") # Update the authbcrypt table with a new password hash d.engine.execute( 'INSERT INTO authbcrypt (userid, hashsum) VALUES (%(user)s, %(hash)s) ' 'ON CONFLICT (userid) DO UPDATE SET hashsum = %(hash)s', user=USERID, hash=login.passhash(form.password)) d.engine.execute("DELETE FROM forgotpassword WHERE token = %(token)s", token=form.token)
def followuser_(request): form = request.web_input(userid="") otherid = define.get_int(form.userid) if request.userid == otherid: return Response( define.errorpage(request.userid, "You cannot follow yourself.")) if form.action == "follow": if not followuser.check(request.userid, otherid): followuser.insert(request.userid, otherid) elif form.action == "unfollow": followuser.remove(request.userid, otherid) raise HTTPSeeOther(location="/~%s" % (define.get_sysname(define.get_display_name(otherid))))
def reset(form): import login # Raise an exception if `password` does not enter `passcheck` (indicating # that the user mistyped one of the fields) or if `password` does not meet # the system's password security requirements if form.password != form.passcheck: raise WeasylError("passwordMismatch") elif not login.password_secure(form.password): raise WeasylError("passwordInsecure") # Select the user information and record data from the forgotpassword table # pertaining to `token`, requiring that the link associated with the record # be visited no more than five minutes prior; if the forgotpassword record is # not found or does not meet this requirement, raise an exception query = d.execute(""" SELECT lo.userid, lo.login_name, lo.email, fp.link_time, fp.address FROM login lo INNER JOIN userinfo ui USING (userid) INNER JOIN forgotpassword fp USING (userid) WHERE fp.token = '%s' AND fp.link_time > %i """, [form.token, d.get_time() - 300], options="single") if not query: raise WeasylError("forgotpasswordRecordMissing") USERID, USERNAME, EMAIL, LINKTIME, ADDRESS = query # Check `username` and `email` against known correct values and raise an # exception if there is a mismatch if emailer.normalize_address(form.email) != emailer.normalize_address(EMAIL): raise WeasylError("emailIncorrect") elif d.get_sysname(form.username) != USERNAME: raise WeasylError("usernameIncorrect") elif d.get_address() != ADDRESS: raise WeasylError("addressInvalid") # Update the authbcrypt table with a new password hash """ TODO TEMPORARY """ try: d.execute("INSERT INTO authbcrypt VALUES (%i, '')", [USERID]) except: pass d.execute("UPDATE authbcrypt SET hashsum = '%s' WHERE userid = %i", [login.passhash(form.password), USERID]) d.execute("DELETE FROM forgotpassword WHERE token = '%s'", [form.token])
def verify(token): lo = d.meta.tables["login"] lc = d.meta.tables["logincreate"] query = d.engine.execute(lc.select().where(lc.c.token == token)).first() if not query: raise WeasylError("logincreateRecordMissing") db = d.connect() with db.begin(): # Create login record userid = db.execute( lo.insert().returning(lo.c.userid), { "login_name": d.get_sysname(query.username), "last_login": arrow.now(), "email": query.email, }).scalar() # Create profile records db.execute(d.meta.tables["authbcrypt"].insert(), { "userid": userid, "hashsum": query.hashpass, }) db.execute( d.meta.tables["profile"].insert(), { "userid": userid, "username": query.username, "full_name": query.username, "unixtime": arrow.now(), "config": "kscftj", }) db.execute(d.meta.tables["userinfo"].insert(), { "userid": userid, "birthday": query.birthday, }) db.execute(d.meta.tables["userstats"].insert(), { "userid": userid, }) db.execute(d.meta.tables["welcomecount"].insert(), { "userid": userid, }) # Update logincreate records db.execute(lc.delete().where(lc.c.token == token)) d.metric('increment', 'verifiedusers')
def request(form): token = security.generate_key(100) email = emailer.normalize_address(form.email) username = d.get_sysname(form.username) # Determine the user associated with `username`; if the user is not found, # raise an exception user = d.engine.execute( "SELECT userid, email FROM login WHERE login_name = %(username)s", username=username).first() if not user: raise WeasylError("loginRecordMissing") # Check the user's email address against the provided e-mail address, # raising an exception if there is a mismatch if email != emailer.normalize_address(user.email): raise WeasylError("emailInvalid") # Insert a record into the forgotpassword table for the user, # or update an existing one now = d.get_time() address = d.get_address() try: d.engine.execute( "INSERT INTO forgotpassword (userid, token, set_time, address)" " VALUES (%(id)s, %(token)s, %(time)s, %(address)s)", id=user.userid, token=token, time=now, address=address) except IntegrityError: # An IntegrityError will probably indicate that a password reset request # already exists and that the existing row should be updated. If the update # doesn't find anything, though, the original error should be re-raised. result = d.engine.execute(""" UPDATE forgotpassword SET token = %(token)s, set_time = %(time)s, address = %(address)s WHERE userid = %(id)s """, id=user.userid, token=token, time=now, address=address) if result.rowcount != 1: raise # Generate and send an email to the user containing a password reset link emailer.append([email], None, "Weasyl Password Recovery", d.render("email/reset_password.html", [token]))
def GET(self, name=""): form = web.input(userid="", name="", backid=None, nextid=None, folderid=None) form.name = name if name else form.name form.userid = define.get_int(form.userid) config = define.get_config(self.user_id) rating = define.get_rating(self.user_id) otherid = profile.resolve(self.user_id, form.userid, form.name) folderid = define.get_int(form.folderid) or None if not otherid: raise WeasylError("userRecordMissing") elif not self.user_id and "h" in define.get_config(otherid): return define.errorpage(self.user_id, errorcode.no_guest_access) userprofile = profile.select_profile(otherid, images=True, viewer=self.user_id) has_fullname = userprofile['full_name'] is not None and userprofile['full_name'].strip() != '' page_title = u"%s's submissions" % (userprofile['full_name'] if has_fullname else userprofile['username'],) page = define.common_page_start(self.user_id, title=page_title) url_format = "/submissions/{username}?%s{folderquery}".format( username=define.get_sysname(userprofile['username']), folderquery="&folderid=%d" % folderid if folderid else "") result = pagination.PaginatedResult( submission.select_list, submission.select_count, 'submitid', url_format, self.user_id, rating, 60, otherid=otherid, folderid=folderid, backid=define.get_int(form.backid), nextid=define.get_int(form.nextid), config=config, profile_page_filter=not folderid) page.append(define.render(template.user_submissions, [ # Profile information userprofile, # User information profile.select_userinfo(otherid, config=userprofile['config']), # Relationship profile.select_relation(self.user_id, otherid), # Recent submissions result, # Folders folder.select_list(otherid, "sidebar/all"), # Current folder folderid, ])) return define.common_page_end(self.user_id, page)
def verify(token): lo = d.meta.tables["login"] lc = d.meta.tables["logincreate"] query = d.engine.execute(lc.select().where(lc.c.token == token)).first() if not query: raise WeasylError("logincreateRecordMissing") db = d.connect() with db.begin(): # Create login record userid = db.scalar(lo.insert().returning(lo.c.userid), { "login_name": d.get_sysname(query.username), "last_login": arrow.now(), "email": query.email, }) # Create profile records db.execute(d.meta.tables["authbcrypt"].insert(), { "userid": userid, "hashsum": query.hashpass, }) db.execute(d.meta.tables["profile"].insert(), { "userid": userid, "username": query.username, "full_name": query.username, "unixtime": arrow.now(), "config": "kscftj", }) db.execute(d.meta.tables["userinfo"].insert(), { "userid": userid, "birthday": query.birthday, }) db.execute(d.meta.tables["userstats"].insert(), { "userid": userid, }) db.execute(d.meta.tables["welcomecount"].insert(), { "userid": userid, }) # Update logincreate records db.execute(lc.delete().where(lc.c.token == token)) d.metric('increment', 'verifiedusers')
def POST(self): form = web.input(userid="") otherid = define.get_int(form.userid) if self.user_id == otherid: return define.errorpage(self.user_id, "You cannot friend yourself.") if form.action == "sendfriendrequest": if not frienduser.check(self.user_id, otherid) and not frienduser.already_pending(self.user_id, otherid): frienduser.request(self.user_id, otherid) elif form.action == "withdrawfriendrequest": if frienduser.already_pending(self.user_id, otherid): frienduser.remove_request(self.user_id, otherid) elif form.action == "unfriend": frienduser.remove(self.user_id, otherid) if form.feature == "pending": raise web.seeother("/manage/friends?feature=pending") else: # typical value will be user raise web.seeother("/~%s" % (define.get_sysname(define.get_display_name(otherid))))
def frienduser_(request): form = request.web_input(userid="") otherid = define.get_int(form.userid) if request.userid == otherid: return Response(define.errorpage(request.userid, "You cannot friend yourself.")) if form.action == "sendfriendrequest": if not frienduser.check(request.userid, otherid) and not frienduser.already_pending(request.userid, otherid): frienduser.request(request.userid, otherid) elif form.action == "withdrawfriendrequest": if frienduser.already_pending(request.userid, otherid): frienduser.remove_request(request.userid, otherid) elif form.action == "unfriend": frienduser.remove(request.userid, otherid) if form.feature == "pending": raise HTTPSeeOther(location="/manage/friends?feature=pending") else: # typical value will be user raise HTTPSeeOther(location="/~%s" % (define.get_sysname(define.get_display_name(otherid))))
def manageuser(userid, form): if userid not in staff.MODS: raise WeasylError("Unexpected") query = d.execute( "SELECT userid, username, config, profile_text, catchphrase FROM profile" " WHERE userid = (SELECT userid FROM login WHERE login_name = '%s')", [d.get_sysname(form.name)], ["single"]) if not query: raise WeasylError("noUser") return { "userid": query[0], "username": query[1], "config": query[2], "profile_text": query[3], "catchphrase": query[4], "user_media": media.get_user_media(query[0]), "staff_notes": shout.count(query[0], staffnotes=True), }
def select_list(userid, rating, limit, otherid=None, backid=None, nextid=None, options=[], config=None): statement = ["SELECT ch.charid, ch.char_name, ch.rating, ch.unixtime, ch.userid, pr.username, ch.settings "] statement.extend(select_query(userid, rating, otherid, backid, nextid, options, config)) statement.append(" ORDER BY ch.charid%s LIMIT %i" % ("" if backid else " DESC", limit)) query = [] for i in define.execute("".join(statement)): query.append({ "contype": 20, "charid": i[0], "title": i[1], "rating": i[2], "unixtime": i[3], "userid": i[4], "username": i[5], "sub_media": fake_media_items(i[0], i[4], define.get_sysname(i[5]), i[6]), }) return query[::-1] if backid else query