def configure():
     canonical_upstream = cfg("dispatch.sr.ht::gitlab", "canonical-upstream")
     upstreams = [k for k in cfgkeys("dispatch.sr.ht::gitlab") if k not in [
         "enabled", "canonical-upstream", canonical_upstream,
     ]]
     return render_template("gitlab/select-instance.html",
             canonical_upstream=canonical_upstream, upstreams=upstreams,
             instance_name=lambda inst: cfg("dispatch.sr.ht::gitlab",
                 inst).split(":")[0])
예제 #2
0
 def inject():
     git_user = cfg("man.sr.ht", "git-user")
     origin = urlparse(cfg("man.sr.ht", "origin"))
     return {
         "repo_uri":
         lambda user=None, wiki=None: ("{}@{}:{}".format(
             git_user.split(":")[0], origin.netloc, "~{}/{}".format(
                 user, wiki) if user and wiki else "root")),
     }
예제 #3
0
def _unsubscribe(dest, mail):
    sender = parseaddr(mail["From"])
    user = User.query.filter(User.email == sender[1]).one_or_none()
    if user:
        sub = Subscription.query.filter(
            Subscription.list_id == dest.id,
            Subscription.user_id == user.id).one_or_none()
    else:
        sub = Subscription.query.filter(
            Subscription.list_id == dest.id,
            Subscription.email == sender[1]).one_or_none()
    list_addr = dest.owner.canonical_name + "/" + dest.name
    message = None
    if sub is None:
        reply = MIMEText("""Hi {}!

We got your request to unsubscribe from {}, but we did not find a subscription
from your email. If you continue to receive undesirable emails from this list,
please reply to this email for support.""".format(sender[0] or sender[1],
                                                  list_addr))
    else:
        db.session.delete(sub)
        reply = MIMEText("""Hi {}!

You have been successfully unsubscribed from the {} mailing list. If you wish to
re-subscribe, send an email to:

{}+subscribe@{}

Feel free to reply to this email if you have any questions.""".format(
            sender[0] or sender[1], list_addr, list_addr,
            cfg("lists.sr.ht", "posting-domain")))
    reply["To"] = mail["From"]
    reply["From"] = "mailer@" + cfg("lists.sr.ht", "posting-domain")
    reply["In-Reply-To"] = mail["Message-ID"]
    reply["Subject"] = "Re: " + (mail.get("Subject")
                                 or "Your subscription request")
    reply["Reply-To"] = "{} <{}>".format(cfg("sr.ht", "owner-name"),
                                         cfg("sr.ht", "owner-email"))
    print(reply.as_string(unixfrom=True))
    smtp = smtplib.SMTP(smtp_host, smtp_port)
    smtp.ehlo()
    smtp.starttls()
    smtp.login(smtp_user, smtp_password)
    smtp.sendmail(smtp_user, [sender[1]], reply.as_string(unixfrom=True))
    smtp.quit()
    db.session.commit()
예제 #4
0
def _forward(dest, mail):
    domain = cfg("lists.sr.ht", "posting-domain")
    list_name = "{}/{}".format(dest.owner.canonical_name, dest.name)
    list_unsubscribe = list_name + "+unsubscribe@" + domain
    list_subscribe = list_name + "+subscribe@" + domain
    for overwrite in [
            "List-Unsubscribe", "List-Subscribe", "List-Archive", "List-Post",
            "List-ID", "Sender"
    ]:
        del mail[overwrite]

    mail["List-Unsubscribe"] = (
        "<mailto:{}?subject=unsubscribe>".format(list_unsubscribe))
    mail["List-Subscribe"] = (
        "<mailto:{}?subject=subscribe>".format(list_subscribe))
    mail["List-Archive"] = "<{}/{}>".format(cfg("lists.sr.ht", "origin"),
                                            list_name)
    mail["List-Post"] = "<mailto:{}@{}>".format(list_name, domain)
    mail["List-ID"] = "{} <{}@{}>".format(dest.name, list_name, domain)
    mail["Sender"] = "{} <{}@{}>".format(list_name, list_name, domain)

    # TODO: Encrypt emails
    smtp = smtplib.SMTP(smtp_host, smtp_port)
    smtp.ehlo()
    smtp.starttls()
    smtp.login(smtp_user, smtp_password)

    froms = mail.get_all('From', [])
    tos = mail.get_all('To', [])
    ccs = mail.get_all('Cc', [])
    recipients = set([a[1] for a in getaddresses(froms + tos + ccs)])

    for sub in dest.subscribers:
        to = sub.email
        if sub.user:
            to = sub.user.email
        if to in recipients:
            print(to + " is already copied, skipping")
            continue
        print("Forwarding message to " + to)
        smtp.sendmail(smtp_user, [to],
                      mail.as_string(unixfrom=True, maxheaderlen=998))
    smtp.quit()
예제 #5
0
def gitlab_redirect(upstream, return_to):
    gl_authorize_url = f"https://{upstream}/oauth/authorize"
    gl_client = cfg("dispatch.sr.ht::gitlab", upstream, default=None)
    if not gl_client:
        return redirect(url_for("gitlab_no_instance"))
    [instance_name, client_id, secret] = gl_client.split(":")
    parameters = {
        "client_id": client_id,
        "scope": "api",
        "state": return_to,
        "response_type": "code",
        "redirect_uri": _root + url_for("gitlab_callback", upstream=upstream),
    }
    return redirect("{}?{}".format(gl_authorize_url, urlencode(parameters)))
예제 #6
0
def invoice_POST(invoice_id):
    invoice = Invoice.query.filter(Invoice.id == invoice_id).one_or_none()
    if not invoice:
        abort(404)
    if (invoice.user_id != current_user.id 
            and current_user.user_type != UserType.admin):
        abort(401)
    valid = Validation(request)
    bill_to = valid.optional("address-to")
    if not bill_to:
        bill_to = "~" + invoice.user.username
    bill_from = [l for l in [
        cfg("meta.sr.ht::billing", "address-line1", default=None),
        cfg("meta.sr.ht::billing", "address-line2", default=None),
        cfg("meta.sr.ht::billing", "address-line3", default=None),
        cfg("meta.sr.ht::billing", "address-line4", default=None)
    ] if l]

    # Split bill_to to first row (rendered as heading) and others
    [bill_from_head, *bill_from_tail] = bill_from or [None]

    html = render_template("billing-invoice-pdf.html",
        invoice=invoice,
        amount=f"${invoice.cents / 100:.2f}",
        source=invoice.source,
        created=invoice.created.strftime("%Y-%m-%d"),
        valid_thru=invoice.valid_thru.strftime("%Y-%m-%d"),
        bill_to=bill_to,
        bill_from_head=bill_from_head,
        bill_from_tail=bill_from_tail)

    pdf = HTML(string=html).write_pdf()

    filename = f"invoice_{invoice.id}.pdf"
    headers = [('Content-Disposition', f'attachment; filename="{filename}"')]
    return Response(pdf, mimetype="application/pdf", headers=headers)
예제 #7
0
def svg_page(jobs):
    name = request.args.get("name", default=cfg("sr.ht", "site-name"))
    job = (get_jobs(jobs).filter(
        Job.status.in_(
            [JobStatus.success, JobStatus.failed, JobStatus.timeout])).first())
    if not job:
        badge = badge_unknown.replace("__NAME__", name)
    elif job.status == JobStatus.success:
        badge = badge_success.replace("__NAME__", name)
    else:
        badge = badge_failure.replace("__NAME__", name)
    return Response(badge,
                    mimetype="image/svg+xml",
                    headers={
                        "Cache-Control": "no-cache",
                        "ETag": hashlib.sha1(badge.encode()).hexdigest(),
                    })
예제 #8
0
    def __init__(self):
        super().__init__("meta.sr.ht",
                         __name__,
                         oauth_service=MetaOAuthService(),
                         oauth_provider=MetaOAuthProvider())

        from metasrht.blueprints.api import register_api
        from metasrht.blueprints.auth import auth
        from metasrht.blueprints.billing import billing
        from metasrht.blueprints.invites import invites
        from metasrht.blueprints.keys import keys
        from metasrht.blueprints.oauth_exchange import oauth_exchange
        from metasrht.blueprints.oauth_web import oauth_web
        from metasrht.blueprints.privacy import privacy
        from metasrht.blueprints.profile import profile
        from metasrht.blueprints.security import security

        self.register_blueprint(auth)
        self.register_blueprint(invites)
        self.register_blueprint(keys)
        self.register_blueprint(oauth_exchange)
        self.register_blueprint(oauth_web)
        self.register_blueprint(privacy)
        self.register_blueprint(profile)
        self.register_blueprint(security)
        register_api(self)

        if cfg("meta.sr.ht::billing", "enabled") == "yes":
            self.register_blueprint(billing)

        @self.context_processor
        def inject():
            return {'UserType': UserType}

        @self.login_manager.user_loader
        def load_user(username):
            # TODO: Session tokens
            return User.query.filter(User.username == username).first()
예제 #9
0
파일: auth.py 프로젝트: terorie/meta.sr.ht
def confirm_account(token):
    if current_user:
        return redirect(onboarding_redirect)
    user = User.query.filter(User.confirmation_hash == token).one_or_none()
    if not user:
        return render_template("already-confirmed.html",
                               redir=onboarding_redirect)
    if user.new_email:
        user.confirmation_hash = None
        audit_log("email updated",
                  "{} became {}".format(user.email, user.new_email))
        user.email = user.new_email
        user.new_email = None
        db.session.commit()
    elif user.user_type == UserType.unconfirmed:
        user.confirmation_hash = None
        user.user_type = UserType.active_non_paying
        audit_log("account created")
        db.session.commit()
        login_user(user, remember=True)
    if cfg("meta.sr.ht::billing", "enabled") == "yes":
        return redirect(url_for("billing.billing_initial_GET"))
    metrics.meta_confirmations.inc()
    return redirect(onboarding_redirect)
예제 #10
0
def gitlab_callback(upstream):
    code = request.args.get("code")
    state = request.args.get("state")
    gl_client = cfg("dispatch.sr.ht::gitlab", upstream, default=None)
    if not gl_client:
        abort(400)
    [instance_name, client_id, secret] = gl_client.split(":")

    resp = requests.post(f"https://{upstream}/oauth/token",
                         headers={"Accept": "application/json"},
                         data={
                             "grant_type":
                             "authorization_code",
                             "client_id":
                             client_id,
                             "client_secret":
                             secret,
                             "code":
                             code,
                             "redirect_uri":
                             _root +
                             url_for("gitlab_callback", upstream=upstream),
                         })
    if resp.status_code != 200:
        # TODO: Proper error page
        print(resp.text)
        return "An error occured"
    json = resp.json()
    access_token = json.get("access_token")
    auth = GitLabAuthorization()
    auth.user_id = current_user.id
    auth.oauth_token = access_token
    auth.upstream = upstream
    db.session.add(auth)
    db.session.commit()
    return redirect(state)
예제 #11
0
def privacy_GET():
    owner = {'name': cfg("sr.ht", "owner-name"),
             'email': cfg("sr.ht", "owner-email")}
    return render_template("privacy.html",
                           pgp_key_id=site_key_id, owner=owner)
예제 #12
0
import metasrht.webhooks
from metasrht.oauth import MetaOAuthService, MetaOAuthProvider
from metasrht.types import User, UserType
from prometheus_client import make_wsgi_app
from srht.config import cfg
from srht.database import DbSession
from srht.flask import SrhtFlask
from urllib.parse import quote_plus
from werkzeug.wsgi import DispatcherMiddleware

db = DbSession(cfg("meta.sr.ht", "connection-string"))
db.init()


class MetaApp(SrhtFlask):
    def __init__(self):
        super().__init__("meta.sr.ht",
                         __name__,
                         oauth_service=MetaOAuthService(),
                         oauth_provider=MetaOAuthProvider())

        from metasrht.blueprints.api import register_api
        from metasrht.blueprints.auth import auth
        from metasrht.blueprints.billing import billing
        from metasrht.blueprints.invites import invites
        from metasrht.blueprints.keys import keys
        from metasrht.blueprints.oauth_exchange import oauth_exchange
        from metasrht.blueprints.oauth_web import oauth_web
        from metasrht.blueprints.privacy import privacy
        from metasrht.blueprints.profile import profile
        from metasrht.blueprints.security import security
예제 #13
0
from listssrht.filters import diffstat, format_body, post_address
from listssrht.oauth import ListsOAuthService
from srht.config import cfg
from srht.database import DbSession
from srht.flask import SrhtFlask
from urllib.parse import quote

db = DbSession(cfg("lists.sr.ht", "connection-string"))
db.init()

class ListsApp(SrhtFlask):
    def __init__(self):
        super().__init__("lists.sr.ht", __name__,
                oauth_service=ListsOAuthService())

        self.url_map.strict_slashes = False

        from listssrht.blueprints.archives import archives
        from listssrht.blueprints.user import user

        self.register_blueprint(archives)
        self.register_blueprint(user)

        @self.context_processor
        def inject():
            return {
                "diffstat": diffstat,
                "format_body": format_body,
                "post_address": post_address,
                "quote": quote,
            }
예제 #14
0
from github import Github
from flask import Blueprint, redirect, request, render_template, url_for, abort
from flask_login import current_user
from jinja2 import Markup
from uuid import UUID, uuid4
from srht.database import Base, db
from srht.config import cfg
from srht.flask import icon, csrf_bypass
from srht.validation import Validation
from dispatchsrht.tasks import TaskDef
from dispatchsrht.tasks.github.auth import GitHubAuthorization
from dispatchsrht.tasks.github.auth import githubloginrequired
from dispatchsrht.tasks.github.auth import submit_build
from dispatchsrht.types import Task

_root = cfg("dispatch.sr.ht", "origin")
_builds_sr_ht = cfg("builds.sr.ht", "origin", default=None)
_github_client_id = cfg("dispatch.sr.ht::github",
                        "oauth-client-id",
                        default=None)
_github_client_secret = cfg("dispatch.sr.ht::github",
                            "oauth-client-secret",
                            default=None)


class GitHubPRToBuild(TaskDef):
    name = "github_pr_to_build"
    enabled = bool(_github_client_id and _github_client_secret
                   and _builds_sr_ht)

    def description():
예제 #15
0
파일: public.py 프로젝트: terorie/scm.sr.ht
from flask import Blueprint, current_app, request
from flask import render_template, abort
from flask_login import current_user
import requests
from srht.config import cfg
from srht.flask import paginate_query
from srht.search import search
from scmsrht.repos.repository import RepoVisibility
from sqlalchemy import or_

public = Blueprint('public', __name__)

meta_uri = cfg("meta.sr.ht", "origin")

@public.route("/")
def index():
    if current_user:
        Repository = current_app.Repository
        repos = (Repository.query
                .filter(Repository.owner_id == current_user.id)
                .filter(Repository.visibility != RepoVisibility.autocreated)
                .order_by(Repository.updated.desc())
                .limit(10)).all()
        return render_template("dashboard.html", repos=repos)
    return render_template("index.html")

@public.route("/~<username>")
@public.route("/~<username>/")
def user_index(username):
    User = current_app.User
    user = User.query.filter(User.username == username).first()
예제 #16
0
from dispatchsrht.app import app
from srht.config import cfg, cfgi

import os

app.static_folder = os.path.join(os.getcwd(), "static")

if __name__ == '__main__':
    app.run(host=cfg("dispatch.sr.ht", "debug-host"),
            port=cfgi("dispatch.sr.ht", "debug-port"),
            debug=True)
예제 #17
0
from srht.config import cfg
from srht.database import db
from srht.flask import SrhtFlask
from srht.oauth import AbstractOAuthService
from todosrht import urls, filters
from todosrht.types import EventType
from todosrht.types import TicketAccess, TicketStatus, TicketResolution
from todosrht.types import User

client_id = cfg("todo.sr.ht", "oauth-client-id")
client_secret = cfg("todo.sr.ht", "oauth-client-secret")

class TodoOAuthService(AbstractOAuthService):
    def __init__(self):
        super().__init__(client_id, client_secret, user_class=User)

class TodoApp(SrhtFlask):
    def __init__(self):
        super().__init__("todo.sr.ht", __name__,
                oauth_service=TodoOAuthService())

        self.url_map.strict_slashes = False

        from todosrht.blueprints.html import html
        from todosrht.blueprints.tracker import tracker
        from todosrht.blueprints.ticket import ticket

        self.register_blueprint(html)
        self.register_blueprint(tracker)
        self.register_blueprint(ticket)
예제 #18
0
from flask import Blueprint, Response, render_template, request, redirect
from flask_login import current_user
from metasrht.audit import audit_log
from metasrht.types import User, PGPKey
from metasrht.email import send_email
from srht.config import cfg
from srht.database import db
from srht.flask import loginrequired
from srht.validation import Validation

privacy = Blueprint('privacy', __name__)

site_key = cfg("mail", "pgp-pubkey", None)
site_key_id = cfg("mail", "pgp-key-id", None)

@privacy.route("/privacy")
@loginrequired
def privacy_GET():
    owner = {'name': cfg("sr.ht", "owner-name"),
             'email': cfg("sr.ht", "owner-email")}
    return render_template("privacy.html",
                           pgp_key_id=site_key_id, owner=owner)

@privacy.route("/privacy/pubkey")
def privacy_pubkey_GET():
    if site_key:
        with open(site_key, "r") as f:
            pubkey = f.read()
    else:
        pubkey = ''
    return Response(pubkey, mimetype="text/plain")
예제 #19
0
from todosrht.types import Event, EventType, EventNotification
from todosrht.types import Tracker, Ticket, TicketStatus, TicketAccess
from todosrht.types import Label, TicketLabel
from todosrht.urls import tracker_url
from srht.config import cfg
from srht.database import db
from srht.flask import paginate_query, loginrequired
from srht.validation import Validation
from datetime import datetime
from sqlalchemy.orm import subqueryload

tracker = Blueprint("tracker", __name__)

name_re = re.compile(r"^([a-z][a-z0-9_.-]*?)+$")

smtp_user = cfg("mail", "smtp-user", default=None)
smtp_from = cfg("mail", "smtp-from", default=None)
notify_from = cfg("todo.sr.ht", "notify-from", default=smtp_from)


@tracker.route("/tracker/create")
@loginrequired
def create_GET():
    return render_template("tracker-create.html")


@tracker.route("/tracker/create", methods=["POST"])
@loginrequired
def create_POST():
    valid = Validation(request)
    name = valid.require("tracker_name", friendly_name="Name")
예제 #20
0
from srht.config import cfg, cfgi
from srht.database import DbSession, db
if not hasattr(db, "session"):
    db = DbSession(cfg("lists.sr.ht", "connection-string"))
    import listssrht.types
    db.init()
from listssrht.types import Email, List, User, Subscription, ListAccess

import email
import email.utils
import io
import json
import smtplib
from celery import Celery
from datetime import datetime
from email import policy
from email.mime.text import MIMEText
from email.utils import parseaddr, getaddresses
from unidiff import PatchSet

dispatch = Celery("lists.sr.ht", broker=cfg("lists.sr.ht", "redis"))

smtp_host = cfg("mail", "smtp-host", default=None)
smtp_port = cfgi("mail", "smtp-port", default=None)
smtp_user = cfg("mail", "smtp-user", default=None)
smtp_password = cfg("mail", "smtp-password", default=None)


def _forward(dest, mail):
    domain = cfg("lists.sr.ht", "posting-domain")
    list_name = "{}/{}".format(dest.owner.canonical_name, dest.name)
예제 #21
0
파일: email.py 프로젝트: terorie/todo.sr.ht
import os
from srht.email import send_email, lookup_key
import html.parser
import pystache
from srht.config import cfg, cfgi
from flask_login import current_user

origin = cfg("todo.sr.ht", "origin")


def notify(sub, template, subject, headers, **kwargs):
    encrypt_key = None
    if sub.email:
        to = sub.email
    elif sub.user:
        to = sub.user.email
        encrypt_key = lookup_key(sub.user.username, sub.user.oauth_token)
    else:
        return  # TODO
    with open(os.path.join(os.path.dirname(__file__), "emails",
                           template)) as f:
        body = html.unescape(
            pystache.render(f.read(), {
                'user': current_user,
                'root': origin,
                **kwargs
            }))
    send_email(body, to, subject, encrypt_key=encrypt_key, **headers)
예제 #22
0
from srht.config import cfg
from srht.oauth import AbstractOAuthService
from listssrht.types import User

client_id = cfg("lists.sr.ht", "oauth-client-id")
client_secret = cfg("lists.sr.ht", "oauth-client-secret")


class ListsOAuthService(AbstractOAuthService):
    def __init__(self):
        super().__init__(client_id, client_secret, user_class=User)
from alembic import op
import sqlalchemy as sa
import sqlalchemy_utils as sau
from enum import Enum
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker, Session as BaseSession, relationship
from srht.config import cfg
import requests
try:
    from tqdm import tqdm
except ImportError:
    def tqdm(iterable):
        yield from iterable

metasrht = cfg("meta.sr.ht", "origin")

Session = sessionmaker()
Base = declarative_base()

class UserType(Enum):
    unconfirmed = "unconfirmed"
    active_non_paying = "active_non_paying"
    active_free = "active_free"
    active_paying = "active_paying"
    active_delinquent = "active_delinquent"
    admin = "admin"

class User(Base):
    __tablename__ = 'user'
    id = sa.Column(sa.Integer, primary_key=True)
예제 #24
0
meta_scopes = {
    'profile': 'profile information',
    'audit': 'audit log',
    'keys': 'SSH and PGP keys',
}

meta_access = {
    'profile': 'read',
    'audit': 'read',
    'keys': 'read',
}

meta_aliases = {"meta.sr.ht": None}
for key in cfgkeys("meta.sr.ht::aliases"):
    meta_aliases[key] = cfg("meta.sr.ht::aliases", key)


class MetaOAuthProvider(AbstractOAuthProvider):
    def get_alias(self, client_id):
        return meta_aliases.get(client_id)

    def resolve_scope(self, scope):
        if scope.client_id:
            client = (OAuthClient.query.filter(
                OAuthClient.client_id == scope.client_id)).one_or_none()
            if not client:
                raise Exception('Unknown client ID {}'.format(scope.client_id))
            scope.client = client
        else:
            scope.client = None
예제 #25
0
import subprocess
from srht.database import db
from srht.config import cfg
from mansrht.types import Wiki
import shutil
import re
import os

repos_path = cfg("man.sr.ht", "repo-path")


def validate_name(valid, owner, wiki_name):
    if not valid.ok:
        return None
    valid.expect(re.match(r'^[a-z._-][a-z0-9._-]*$', wiki_name),
                 "Name must match [a-z._-][a-z0-9._-]*",
                 field="name")
    existing = (Wiki.query.filter(Wiki.owner_id == owner.id).filter(
        Wiki.name.ilike(wiki_name)).first())
    valid.expect(not existing, "This name is already in use.", field="name")
    return None


def create_wiki(valid, owner):
    wiki_name = valid.require("name", friendly_name="Name")
    if not valid.ok:
        return None

    wiki = Wiki()
    wiki.name = wiki_name
    wiki.owner_id = owner.id
예제 #26
0
import os
import srht.email
import html.parser
import pystache
from srht.config import cfg, cfgi
from flask_login import current_user

origin = cfg("meta.sr.ht", "origin")
owner_name = cfg("sr.ht", "owner-name")
site_name = cfg("sr.ht", "site-name")

def send_email(template, *args, encrypt_key=None, headers={}, **kwargs):
    with open(os.path.join(os.path.dirname(__file__), "emails", template)) as f:
        body = html.parser.HTMLParser().unescape(\
            pystache.render(f.read(), {
                'owner-name': owner_name,
                'site-name': site_name,
                'user': current_user,
                'root': origin,
                **kwargs
            }))
    srht.email.send_email(body, *args, encrypt_key=encrypt_key, **headers)
예제 #27
0
def _subscribe(dest, mail):
    sender = parseaddr(mail["From"])
    user = User.query.filter(User.email == sender[1]).one_or_none()
    if user:
        perms = dest.account_permissions
        sub = Subscription.query.filter(
            Subscription.list_id == dest.id,
            Subscription.user_id == user.id).one_or_none()
    else:
        perms = dest.nonsubscriber_permissions
        sub = Subscription.query.filter(
            Subscription.list_id == dest.id,
            Subscription.email == sender[1]).one_or_none()

    list_addr = dest.owner.canonical_name + "/" + dest.name
    message = None

    # TODO: User-specific/email-specific overrides
    if ListAccess.browse not in perms:
        reply = MIMEText("""Hi {}!

We got your request to subscribe to {}, but unfortunately subscriptions to this
list are restricted. Your request has been disregarded.{}
        """.format(sender[0] or sender[1], list_addr,
                   ("""

However, you are permitted to post mail to this list at this address:

{}@{}""".format(list_addr, cfg("lists.sr.ht", "posting-domain"))
                    if ListAccess.post in perms else "")))
    elif sub is None:
        reply = MIMEText("""Hi {}!

Your subscription to {} is confirmed! To unsubscribe in the future, send an
email to this address:

{}+unsubscribe@{}

Feel free to reply to this email if you have any questions.""".format(
            sender[0] or sender[1], list_addr, list_addr,
            cfg("lists.sr.ht", "posting-domain")))
        sub = Subscription()
        sub.user_id = user.id if user else None
        sub.list_id = dest.id
        sub.email = sender[1] if not user else None
        db.session.add(sub)
    else:
        reply = MIMEText("""Hi {}!

We got an email asking to subscribe you to the {} mailing list. However, it
looks like you're already subscribed. To unsubscribe, send an email to:

{}+unsubscribe@{}

Feel free to reply to this email if you have any questions.""".format(
            sender[0] or sender[1], list_addr, list_addr,
            cfg("lists.sr.ht", "posting-domain")))
    reply["To"] = mail["From"]
    reply["From"] = "mailer@" + cfg("lists.sr.ht", "posting-domain")
    reply["In-Reply-To"] = mail["Message-ID"]
    reply["Subject"] = "Re: " + (mail.get("Subject")
                                 or "Your subscription request")
    reply["Reply-To"] = "{} <{}>".format(cfg("sr.ht", "owner-name"),
                                         cfg("sr.ht", "owner-email"))
    print(reply.as_string(unixfrom=True))
    smtp = smtplib.SMTP(smtp_host, smtp_port)
    smtp.ehlo()
    smtp.starttls()
    smtp.login(smtp_user, smtp_password)
    smtp.sendmail(smtp_user, [sender[1]], reply.as_string(unixfrom=True))
    smtp.quit()
    db.session.commit()
예제 #28
0
from todosrht.app import app
from srht.config import cfg, cfgi

import os

app.static_folder = os.path.join(os.getcwd(), "static")

if __name__ == '__main__':
    app.run(host=cfg("todo.sr.ht", "debug-host"),
            port=cfgi("todo.sr.ht", "debug-port"),
            debug=True)
예제 #29
0
from flask import Blueprint, render_template, request
from flask_login import current_user
from metasrht.types import User, UserAuthFactor, FactorType
from metasrht.email import send_email
from metasrht.audit import audit_log
from metasrht.webhooks import UserWebhook
from srht.config import cfg
from srht.database import db
from srht.flask import loginrequired
from srht.validation import Validation, valid_url

profile = Blueprint('profile', __name__)

site_name = cfg("sr.ht", "site-name")


@profile.route("/profile")
@loginrequired
def profile_GET():
    return render_template("profile.html")


@profile.route("/profile", methods=["POST"])
@loginrequired
def profile_POST():
    valid = Validation(request)

    user = User.query.filter(User.id == current_user.id).one()

    email = valid.optional("email", user.email)
    email = email.strip()
예제 #30
0
import sqlalchemy_utils as sau
from dispatchsrht.tasks.gitlab.common import GitLabAuthorization
from dispatchsrht.tasks.gitlab.common import gitlabloginrequired
from dispatchsrht.tasks.gitlab.common import submit_gitlab_build
from dispatchsrht.tasks import TaskDef
from dispatchsrht.types import Task
from flask import Blueprint, redirect, render_template, request, url_for
from jinja2 import Markup
from srht.config import cfg, cfgb, cfgkeys
from srht.database import Base, db
from srht.flask import icon, csrf_bypass
from srht.oauth import current_user, loginrequired
from srht.validation import Validation
from uuid import UUID, uuid4

_root = cfg("dispatch.sr.ht", "origin")
_builds_sr_ht = cfg("builds.sr.ht", "origin", default=None)
_gitlab_enabled = cfgb("dispatch.sr.ht::gitlab", "enabled", default=False)

if _gitlab_enabled:
    from gitlab import Gitlab


class GitLabMRToBuild(TaskDef):
    name = "gitlab_mr_to_build"
    enabled = bool(_gitlab_enabled and _builds_sr_ht)

    def description():
        return (icon("gitlab") + Markup(" GitLab merge requests ") +
                icon("caret-right") + Markup(" builds.sr.ht jobs"))