celery_tasks.py
Python script, ASCII text executable
1import common 2import time 3import os 4import config 5import email_send 6import shutil 7from celery import shared_task 8from app import db, _ 9from smtplib import SMTP 10from celery.utils.log import get_task_logger 11 12 13@shared_task(ignore_result=False) 14def send_notification(user_notification_id): 15from models import UserNotification 16user_notification = db.session.get(UserNotification, user_notification_id) 17user = user_notification.user 18notification = user_notification.notification 19 20if user.email: 21with (SMTP(config.MAIL_SERVER) as mail): 22if notification.data.get("type") == "welcome": 23message = email_send.make_multipart_message( 24"Welcome, {username}".format(username=user.username), 25config.NOTIFICATION_EMAIL, 26user.email, 27"welcome", 28username=user.username) 29 30mail.sendmail(config.NOTIFICATION_EMAIL, user.email, message) 31 32return 0 # notification sent successfully 33 34 35@shared_task(ignore_result=False) 36def merge_heads(head_route, head_branch, base_route, base_branch, simulate=True): 37from models import Repo 38server_repo_location = os.path.join(config.REPOS_PATH, base_route.lstrip("/")) 39if not os.path.isdir(server_repo_location): 40raise FileNotFoundError(f"Repo {server_repo_location} not found, cannot merge.") 41 42if base_route == head_route: 43common.git_command(server_repo_location, b"", "checkout", f"{base_branch}") 44if simulate: 45out, err, merge_exit = common.git_command(server_repo_location, b"", "merge", "--no-commit", "--no-ff", f"heads/{head_branch}", 46return_err=True, return_exit=True) 47 48# Undo the merge. 49common.git_command(server_repo_location, b"", "merge", "--abort") 50else: 51out, err, merge_exit = common.git_command(server_repo_location, b"", "merge", f"heads/{head_branch}", 52return_err=True, return_exit=True) 53 54return "merge_simulator" if simulate else "merge", out, err, head_route, head_branch, base_route, base_branch, merge_exit 55 56# Otherwise, we need to fetch the head repo. 57remote_url = os.path.join(config.BASE_DOMAIN, "git", base_route.lstrip("/")) 58 59out, err = b"", b"" 60part_out, part_err = common.git_command(server_repo_location, b"", "remote", "add", "NEW", remote_url, return_err=True) 61out += part_out 62err += part_err 63part_out, part_err = common.git_command(server_repo_location, b"", "remote", "update", return_err=True) 64out += part_out 65err += part_err 66part_out, part_err = common.git_command(server_repo_location, b"", "checkout", f"{base_branch}", return_err=True) 67out += part_out 68err += part_err 69if simulate: 70part_out, part_err, merge_exit = common.git_command(server_repo_location, b"", "merge", "--allow-unrelated-histories", 71"--no-commit", "--no-ff", f"NEW/{head_branch}", return_err=True, return_exit=True) 72else: 73part_out, part_err, merge_exit = common.git_command(server_repo_location, b"", "merge", "--allow-unrelated-histories", 74f"NEW/{head_branch}", return_err=True, return_exit=True) 75 76diff, diff_exit = common.git_command(server_repo_location, b"", "diff", "--check", return_exit=True) 77 78out += part_out 79err += part_err 80part_out, part_err = common.git_command(server_repo_location, b"", "remote", "rm", "NEW", return_err=True) 81out += part_out 82err += part_err 83if simulate: 84# Undo the merge. 85common.git_command(server_repo_location, b"", "merge", "--abort") 86 87return "merge_simulator" if simulate else "merge", out, err, head_route, head_branch, base_route, base_branch, merge_exit 88 89 90@shared_task(ignore_result=False) 91def copy_site(route): 92from models import Repo 93repo = db.session.get(Repo, route) 94server_repo_location = os.path.join(config.REPOS_PATH, route.lstrip("/")) 95subdomain = repo.owner.username 96subpath = repo.name if repo.has_site != 2 else "" 97site_location = os.path.join(config.SITE_PATH, subdomain, subpath) 98# Get the branch to be used for the site; if it somehow doesn't exist, use the default branch. 99branch = repo.site_branch or repo.default_branch 100# Make a shallow clone of the repo; this prevents getting the full git database when it's not needed. 101if os.path.isdir(site_location): 102# Delete the old site. 103shutil.rmtree(site_location) 104 105common.git_command(config.SITE_PATH, b"", "clone", "--depth=1", f"--branch={branch}", os.path.join(os.getcwd(), server_repo_location), os.path.join(subdomain, subpath)) 106 107 108@shared_task(ignore_result=False) 109def delete_site(route): 110from models import Repo 111repo = db.session.get(Repo, route) 112subdomain = repo.owner.username 113subpath = repo.name if repo.has_site != 2 else "." 114site_location = os.path.join(config.SITE_PATH, subdomain, subpath) 115if os.path.isdir(site_location): 116shutil.rmtree(site_location) 117 118# Redo the primary site. 119primary_site = Repo.query.filter_by(owner=repo.owner, has_site=2).first() 120if primary_site: 121copy_site(primary_site.route) 122 123 124@shared_task(ignore_result=False) 125def request_email_change(username, email): 126from models import User, EmailChangeRequest 127user = db.session.get(User, username) 128 129request = EmailChangeRequest(user, email) 130 131db.session.add(request) 132db.session.commit() 133 134message = email_send.make_multipart_message( 135"Email change request for {username}".format(username=username), 136config.NOTIFICATION_EMAIL, 137email, 138"email-change", 139username=username, 140code=request.code, 141new_email=email, 142url="https://" if config.suggest_https else "http://" + config.BASE_DOMAIN + "/settings/confirm-email/" + request.code 143) 144