pixelfed/pixelfed

View on GitHub
resources/assets/components/remote-auth/StartComponent.vue

Summary

Maintainability
Test Coverage
<template>
<div class="container remote-auth-start">
    <div class="row mt-5 justify-content-center">
        <div class="col-12 col-md-5">
            <div class="card shadow-none border" style="border-radius: 20px;">
                <div v-if="!loaded" class="card-body d-flex justify-content-center flex-column" style="min-height: 662px;">
                    <p class="lead text-center font-weight-bold mb-0">Sign-in with Mastodon</p>
                    <div class="w-100">
                        <hr>
                    </div>
                    <div class="d-flex justify-content-center align-items-center flex-grow-1">
                        <b-spinner />
                    </div>
                </div>

                <div v-else class="card-body" style="min-height: 662px;">
                    <p class="lead text-center font-weight-bold">Sign-in with Mastodon</p>
                    <hr>
                    <p class="small text-center mb-3">Select your Mastodon server:</p>
                    <button
                        v-for="domain in domains"
                        type="button"
                        class="server-btn"
                        @click="handleRedirect(domain)">
                        <span class="font-weight-bold">{{ domain }}</span>
                    </button>
                    <hr v-if="!config.default_only && !config.custom_only">
                    <p v-if="!config.default_only && !config.custom_only" class="text-center">
                        <button type="button" class="other-server-btn" @click="handleOther()">Sign-in with a different server</button>
                    </p>
                    <div class="w-100">
                        <hr>
                        <p class="text-center mb-0">
                            <a class="font-weight-bold" href="/login">Go back to login</a>
                        </p>
                    </div>
                </div>
            </div>
        </div>
    </div>
</div>
</template>

<script type="text/javascript">
    export default {
        props: {
            config: {
                type: Object
            }
        },

        data() {
            return {
                loaded: false,
                domains: []
            }
        },

        mounted() {
            this.fetchDomains();
        },

        methods: {
            fetchDomains() {
                axios.post('/auth/raw/mastodon/domains')
                .then(res => {
                    this.domains = res.data;
                })
                .finally(() => {
                    setTimeout(() => {
                        this.loaded = true;
                    }, 500);
                })
            },

            handleRedirect(domain) {
                axios.post('/auth/raw/mastodon/redirect', { domain: domain })
                .then(res => {
                    if(!res || !res.data.hasOwnProperty('ready')) {
                        return;
                    }

                    if(res.data.hasOwnProperty('action') && res.data.action === 'incompatible_domain') {
                        swal('Oops!', 'This server is not compatible, please choose another or try again later!', 'error');
                        return;
                    }

                    if(res.data.hasOwnProperty('action') && res.data.action === 'blocked_domain') {
                        swal('Server Blocked', 'This server is blocked by admins and cannot be used, please try another server!', 'error');
                        return;
                    }

                    if(res.data.ready) {
                        window.location.href = '/auth/raw/mastodon/preflight?d=' + domain + '&dsh=' + res.data.dsh;
                    }
                })
            },

            handleOther() {
                swal({
                  text: 'Enter your mastodon domain (without https://)',
                  content: "input",
                  button: {
                    text: "Next",
                    closeModal: false,
                  },
                })
                .then(domain => {
                  if (!domain || domain.length < 2 || domain.indexOf('.') == -1) {
                    swal('Oops!', "Please enter a valid domain!", 'error');
                    return;
                  };

                  if(domain.startsWith('http')) {
                    swal('Oops!', "The domain you enter should not start with http(s://)\nUse the domain format, like mastodon.social", 'error');
                    return;
                  }

                  return this.handleRedirect(domain);
                })
            }
        }
    }
</script>

<style lang="scss">
    @use '../../../../node_modules/bootstrap/scss/bootstrap';

    .remote-auth-start {
        .server-btn {
            @extend .btn;
            @extend .btn-primary;
            @extend .btn-block;
            @extend .rounded-pill;
            @extend .font-weight-light;

            background: linear-gradient(#6364FF, #563ACC);
        }

        .other-server-btn {
            @extend .btn;
            @extend .btn-dark;
            @extend .btn-block;
            @extend .rounded-pill;
            @extend .font-weight-light;
        }
    }
</style>