예제 #1
0
def reset_password():
    """
    Ask for a reset password link by email.
    ---
    tags:
        - Accounts
    responses:
        200:
            description: fixme.
    """
    email = request.args.get("email", None)
    if not email:
        abort(400)

    user = User.query.filter(User.email == email).first()
    if not user:
        abort(404)

    # generate a reset link
    prt = PasswordResetToken()
    prt.token = generate_random_token()
    prt.expires_at = None
    prt.user_id = user.id

    db.session.add(prt)
    db.session.commit()
    add_user_log(user.id, user.id, "user", "info",
                 "Password reset token generated")

    # Send email
    token_link = f"https://{current_app.config['AP_DOMAIN']}/password-reset/{prt.token}"
    msg = Message(subject="Password reset",
                  recipients=[user.email],
                  sender=current_app.config["MAIL_DEFAULT_SENDER"])

    _config = Config.query.first()
    if not _config:
        print("ERROR: cannot get instance Config from database")
    instance = {"name": None, "url": None}
    if _config:
        instance["name"] = _config.app_name
    instance["url"] = current_app.config["REEL2BITS_URL"]
    msg.body = render_template("email/password_reset.txt",
                               token_link=token_link,
                               user=user,
                               instance=instance)
    msg.html = render_template("email/password_reset.html",
                               token_link=token_link,
                               user=user,
                               instance=instance)
    err = None
    mail = current_app.extensions.get("mail")
    if not mail:
        err = "mail extension is none"
    else:
        try:
            mail.send(msg)
        except ConnectionRefusedError as e:
            # TODO: do something about that maybe
            print(f"Error sending mail: {e}")
            err = e
        except smtplib.SMTPRecipientsRefused as e:
            print(f"Error sending mail: {e}")
            err = e
        except smtplib.SMTPException as e:
            print(f"Error sending mail: {e}")
            err = e
        if err:
            add_log(
                "global", "ERROR",
                f"Error sending email for password reset user {user.id}: {err}"
            )
            add_user_log(user.id, user.id, "user", "error",
                         "An error occured while sending email")

    return jsonify({"status": "ok"}), 204
예제 #2
0
def account_delete():
    """
    Delete account
    ---
    tags:
        - Accounts
    responses:
      200:
        description: Returns user username
    """
    current_user = current_token.user
    if not current_user:
        abort(400)

    # store a few infos
    username = current_user.name
    user_id = current_user.id
    email = current_user.email

    # Revoke Oauth2 credentials
    for oa2_token in OAuth2Token.query.filter(
            OAuth2Token.user_id == current_user.id).all():
        oa2_token.revoked = True

    # Drop password reset tokens
    for prt in PasswordResetToken.query.filter(
            PasswordResetToken.user_id == current_user.id).all():
        db.session.delete(prt)

    # set all activities as deleted
    activities = Activity.query.filter(
        Activity.actor == current_user.actor[0].id)
    for activity in activities.all():
        activity.meta_deleted = True

    # set actor as deleted and federate a Delete(Actor)
    current_user.actor[0].meta_deleted = True
    # Federate Delete(Actor)
    federate_delete_actor(current_user.actor[0])

    # drop all relations
    follows = Follower.query.filter(
        or_(Follower.actor_id == current_user.actor[0].id,
            Follower.target_id == current_user.actor[0].id))
    for follow_rel in follows.all():
        db.session.delete(follow_rel)

    # delete User
    db.session.delete(current_user)

    db.session.commit()  # crimes

    # send email that account have been deleted
    msg = Message(subject="Account successfully deleted",
                  recipients=[email],
                  sender=current_app.config["MAIL_DEFAULT_SENDER"])
    msg.body = render_template("email/account_deleted.txt", username=username)
    msg.html = render_template("email/account_deleted.html", username=username)
    err = None
    mail = current_app.extensions.get("mail")
    if not mail:
        err = "mail extension is none"
    else:
        try:
            mail.send(msg)
        except ConnectionRefusedError as e:
            # TODO: do something about that maybe
            print(f"Error sending mail: {e}")
            err = e
        except smtplib.SMTPRecipientsRefused as e:
            print(f"Error sending mail: {e}")
            err = e
        except smtplib.SMTPException as e:
            print(f"Error sending mail: {e}")
            err = e
    if err:
        add_log(
            "global", "ERROR",
            f"Error sending email for account deletion of {username} ({user_id}): {err}"
        )

    return jsonify({"username": username}), 200
예제 #3
0
def work_metadatas(sound_id, force=False):
    # force is unused for now
    sound = Sound.query.get(sound_id)
    if not sound:
        print("- Cant find sound ID %(id)s in database".format(id=sound_id))
        return

    add_user_log(
        sound.id,
        sound.user.id,
        "sounds",
        "info",
        "Metadatas gathering started for: {0} -- {1}".format(sound.id, sound.title),
    )

    _infos = sound.sound_infos.first()

    if not _infos:
        _infos = SoundInfo()
        _infos.sound_id = sound.id

    # Generate Basic infos

    fname = os.path.join(current_app.config["UPLOADED_SOUNDS_DEST"], sound.user.slug, sound.filename)
    basic_infos = None
    if not _infos.done_basic:
        basic_infos = get_basic_infos(fname)
        if type(basic_infos) != dict:
            # cannot process further
            print(f"- MIME: '{basic_infos}' is not supported")
            add_log("global", "ERROR", f"Unsupported audio format: {basic_infos}")
            return False

    if not _infos.done_basic or force:
        print("- WORKING BASIC on {0}, {1}".format(sound.id, sound.filename))
        print("- Our file got basic infos: {0}".format(basic_infos))
        _infos.duration = basic_infos["duration"]
        _infos.channels = basic_infos["channels"]
        _infos.rate = basic_infos["rate"]
        _infos.codec = basic_infos["codec"]
        _infos.format = basic_infos["format"]
        _infos.bitrate = basic_infos["bitrate"]
        _infos.bitrate_mode = basic_infos["bitrate_mode"]
        _infos.done_basic = True
        _infos.type = basic_infos["type"]
        _infos.type_human = basic_infos["type_human"]

    if not _infos.done_waveform or force:
        if sound.transcode_state == Sound.TRANSCODE_DONE:
            _f, _e = splitext(fname)
            fname_t = "{0}.mp3".format(_f)
            print("- WORKING ON TRANSCODED FOR WAVEFORM")
        else:
            fname_t = fname

        print("- GENERATING AUDIO DAT FILE")
        dat_file_name = generate_audio_dat_file(fname_t, _infos.duration)

        print("- WORKING WAVEFORM on {0}, {1}".format(sound.id, sound.filename))
        waveform_infos = get_waveform(dat_file_name, _infos.duration)
        print("- Our file got waveform infos: {0}".format(waveform_infos))
        _infos.waveform = waveform_infos
        if not waveform_infos:
            _infos.waveform_error = True
            add_user_log(
                sound.id,
                sound.user.id,
                "sounds",
                "info",
                "Got an error when generating waveform" " for: {0} -- {1}".format(sound.id, sound.title),
            )

        # Delete the temporary dat file
        os.unlink(dat_file_name)

        _infos.done_waveform = True

    db.session.add(_infos)
    db.session.commit()

    add_user_log(
        sound.id,
        sound.user.id,
        "sounds",
        "info",
        "Metadatas gathering finished for: {0} -- {1}".format(sound.id, sound.title),
    )
    return True
예제 #4
0
def upload_workflow(self, sound_id):
    print("UPLOAD WORKFLOW started")

    sound = Sound.query.get(sound_id)
    if not sound:
        print("- Cant find sound ID {id} in database".format(id=sound_id))
        return

    # First, if the sound isn't local, we need to fetch it
    if sound.activity and not sound.activity.local:
        fetch_remote_track(sound_id)
        fetch_remote_artwork(sound_id)
        if not sound.filename.startswith("remote_"):
            print("UPLOAD WORKFLOW had errors")
            add_log("global", "ERROR",
                    f"Error fetching remote track {sound.id}")
            return

    print("METADATAS started")
    metadatas = work_metadatas(sound_id)
    print("METADATAS finished")

    if not metadatas:
        # cannot process further
        sound.transcode_state = Sound.TRANSCODE_ERROR
        db.session.commit()
        print("UPLOAD WORKFLOW had errors")
        add_log("global", "ERROR", f"Error processing track {sound.id}")
        add_user_log(sound.id, sound.user_id, "sounds", "error",
                     "An error occured while processing your track")
        return

    if metadatas:
        print("TRANSCODE started")
        work_transcode(sound_id)
        print("TRANSCODE finished")

    # The rest only applies if the track is local
    if not sound.remote_uri:
        # Federate if public
        if not sound.private:
            print("UPLOAD WORKFLOW federating sound")
            # Federate only if sound is public
            sound.activity_id = federate_new_sound(sound)
            db.session.commit()

        track_url = f"https://{current_app.config['AP_DOMAIN']}/{sound.user.name}/track/{sound.slug}"

        msg = Message(
            subject="Song processing finished",
            recipients=[sound.user.email],
            sender=current_app.config["MAIL_DEFAULT_SENDER"],
        )

        _config = Config.query.first()
        if not _config:
            print("ERROR: cannot get instance Config from database")
        instance = {"name": None, "url": None}
        if _config:
            instance["name"] = _config.app_name
        instance["url"] = current_app.config["REEL2BITS_URL"]
        msg.body = render_template("email/song_processed.txt",
                                   sound=sound,
                                   track_url=track_url,
                                   instance=instance)
        msg.html = render_template("email/song_processed.html",
                                   sound=sound,
                                   track_url=track_url,
                                   instance=instance)
        err = None
        mail = current_app.extensions.get("mail")
        if not mail:
            err = "mail extension is none"
        else:
            try:
                mail.send(msg)
            except ConnectionRefusedError as e:
                # TODO: do something about that maybe
                print(f"Error sending mail: {e}")
                err = e
            except smtplib.SMTPRecipientsRefused as e:
                print(f"Error sending mail: {e}")
                err = e
            except smtplib.SMTPException as e:
                print(f"Error sending mail: {e}")
                err = e
        if err:
            add_log("global", "ERROR",
                    f"Error sending email for track {sound.id}: {err}")
            add_user_log(sound.id, sound.user.id, "sounds", "error",
                         "An error occured while sending email")

    print("UPLOAD WORKFLOW finished")
예제 #5
0
def upload_workflow(self, sound_id):
    print("UPLOAD WORKFLOW started")

    sound = Sound.query.get(sound_id)
    if not sound:
        print("- Cant find sound ID {id} in database".format(id=sound_id))
        return

    print("METADATAS started")
    metadatas = work_metadatas(sound_id)
    print("METADATAS finished")

    if not metadatas:
        # cannot process further
        sound.transcode_state = Sound.TRANSCODE_ERROR
        db.session.commit()
        print("UPLOAD WORKFLOW had errors")
        add_log("global", "ERROR", f"Error processing track {sound.id}")
        add_user_log(sound.id, sound.user.id, "sounds", "error",
                     "An error occured while processing your track")
        return

    if metadatas:
        print("TRANSCODE started")
        work_transcode(sound_id)
        print("TRANSCODE finished")

    # Federate if public
    if not sound.private:
        print("UPLOAD WORKFLOW federating sound")
        # Federate only if sound is public
        sound.activity_id = federate_new_sound(sound)
        db.session.commit()

    track_url = f"https://{current_app.config['AP_DOMAIN']}/{sound.user.name}/track/{sound.slug}"

    msg = Message(
        subject="Song processing finished",
        recipients=[sound.user.email],
        sender=current_app.config["MAIL_DEFAULT_SENDER"],
    )
    msg.body = render_template("email/song_processed.txt",
                               sound=sound,
                               track_url=track_url)
    msg.html = render_template("email/song_processed.html",
                               sound=sound,
                               track_url=track_url)
    err = None
    mail = current_app.extensions.get("mail")
    if not mail:
        err = "mail extension is none"
    else:
        try:
            mail.send(msg)
        except ConnectionRefusedError as e:
            # TODO: do something about that maybe
            print(f"Error sending mail: {e}")
            err = e
        except smtplib.SMTPRecipientsRefused as e:
            print(f"Error sending mail: {e}")
            err = e
        except smtplib.SMTPException as e:
            print(f"Error sending mail: {e}")
            err = e
    if err:
        add_log("global", "ERROR",
                f"Error sending email for track {sound.id}: {err}")
        add_user_log(sound.id, sound.user.id, "sounds", "error",
                     "An error occured while sending email")

    print("UPLOAD WORKFLOW finished")