Scout APM is PHP application performance monitoring designed for developers. With tracing logic that ties issues back to the line of code causing them, you can pinpoint n+1 queries, memory leaks, and other abnormalities in real time so you can knock them out and get back to building a great product. Start your free 14-day trial today and get the performance insight you need in less than 4 minutes.

Selling digital products using Laravel part 3: Giving customers access to private repositories on Github

Original – by Freek Van der Herten – 3 minute read

Wouldn't it be great if we could automatically give customers access to the private repositories on GitHub for the products they bought? Let's take a look at how this is handled at spatie.be

Some of the products we sell, like Mailcoach, have source code that resides in a private repository.

screenshot

We automatically give our customers access to the repos containing the source code of bought products. This is quite nice because our more technical users can directly create issues and submit PRs. Even though it is a private repo, we still got some open source vibes there. For Mailcoach, there's a small friendly community helping each other and fixing things. Of course, because it's a paid product, my team members and I still do the bulk of the work.

Let's take a look at how that repository access is automatically granted. In the previous part, you might have noticed that RestoreRepositoryAccessAction being called in the GitHubSocialiteController. An action is a class that encapsulates logic that is being called from several places. We talk some more about actions in our Laravel Beyond CRUD course.

Let's take a look at the execute method of RestoreRepositoryAccessAction.

public function execute(User $user): void
{
    $user->purchases
        ->where('has_repository_access', false)
        ->filter(fn(Purchase $purchase) => $purchase->purchasable->repository_access)
        ->reject(fn(Purchase $purchase) => $purchase->license && $purchase->license->isExpired())
        ->each(function (Purchase $purchase) use ($user) {
            $this->gitHubApi->inviteToRepo(
                $user->github_username,
                $purchase->purchasable->repository_access
            );

            $purchase->update(['has_repository_access' => true]);
        });
}

This collection chain filters out the non-expired purchases (with a non-expired license) of the given user. If the user's purchasable has repository access, we'll use the GitHub API to invite that user to the repo. GitHub will mail the user an invite.

That GitHub class used in the code above is a simple wrapper class around the knplabs/github-api package.

If the license of a product that has a private repository expires, the repository access will be revoked. This is done in the RevokeRepositoryAccessForExpiredLicensesCommand, which is scheduled to run daily.

class RevokeRepositoryAccessForExpiredLicensesCommand extends Command
{
    public $signature = 'revoke-repository-access-for-expired-licenses';

    public function handle(GitHubApi $gitHubApi)
    {
        $this->info('Revoking access to repositories for expired licenses...');

        Purchase::query()
            ->whereHas('license', fn(Builder $query) => $query->whereExpired())
            ->where('has_repository_access', true)
            ->cursor()
            ->each(function (Purchase $purchase) use ($gitHubApi) {
                $gitHubApi->revokeAccessToRepo(
                    $purchase->user->github_username,
                    $purchase->purchasable->repository_access
                );

                $purchase->update(['has_repository_access' => false]);
            });

        $this->info('All done!');
    }
}

This series is continued in part 4: Making a sale using Paddle.

Stay up to date with all things Laravel, PHP, and JavaScript.

Follow me on Twitter. I regularly tweet out programming tips, and what I myself have learned in ongoing projects.

Every two weeks I send out a newsletter containing lots of interesting stuff for the modern PHP developer.

Expect quick tips & tricks, interesting tutorials, opinions and packages. Because I work with Laravel every day there is an emphasis on that framework.

Rest assured that I will only use your email address to send you the newsletter and will not use it for any other purposes.

Comments

Webmentions

Percy Astocaza retweeted on 20th October 2020
Percy Astocaza liked on 20th October 2020
Derick Alangi © liked on 20th October 2020
Paulund liked on 20th October 2020
Burhan liked on 20th October 2020
Istvan Szana liked on 20th October 2020
sandip liked on 20th October 2020
Rati Wannapanop liked on 20th October 2020
Beeen E nya tiga liked on 20th October 2020
Sam Snelling liked on 20th October 2020
Shane Oliver liked on 20th October 2020
merlot99 liked on 20th October 2020
Spatie retweeted on 20th October 2020
Zach Williams liked on 19th October 2020
Guus liked on 19th October 2020
Bert van Hoekelen liked on 19th October 2020
Placebo Domingo retweeted on 19th October 2020
Alejandro Pérez liked on 19th October 2020
Philipp Grimm liked on 19th October 2020
Alejandro Pérez replied on 19th October 2020
This is extremely valuable information!! The approach for handling access to private repos looks both simple and powerful. Thanks for sharing!
Toan Nguyen retweeted on 19th October 2020
Domingos Cruz liked on 19th October 2020
Niels liked on 19th October 2020
José Cage retweeted on 19th October 2020
leunggamciu retweeted on 19th October 2020
Kevin Ullyott liked on 19th October 2020
José Cage liked on 19th October 2020
Steve Bauman liked on 19th October 2020
Jesil Jose liked on 19th October 2020
imagdic liked on 19th October 2020
Michael Aguiar liked on 19th October 2020
Andrés Santibáñez retweeted on 19th October 2020
Andrés Santibáñez liked on 19th October 2020
Kamau Wanyee retweeted on 19th October 2020
Axel Pardemann retweeted on 19th October 2020
Jiří Žižka liked on 19th October 2020
Tipu Danny liked on 19th October 2020
jaccogardner7 liked on 19th October 2020
Axel Pardemann liked on 19th October 2020
Wade Striebel liked on 19th October 2020
江亞倫 liked on 19th October 2020
Momen Albelbeisi retweeted on 19th October 2020
ali ali liked on 19th October 2020
Christopher Pearse liked on 19th October 2020
Luiyi Nuñez 🇩🇴 liked on 19th October 2020
Rens Bultynck liked on 19th October 2020
Tom de Wit liked on 19th October 2020
Paulius Jasiulis retweeted on 19th October 2020
Bader retweeted on 19th October 2020
Paulius Jasiulis liked on 19th October 2020
Oung liked on 19th October 2020
Bader liked on 19th October 2020
Tauseef shah liked on 19th October 2020
ahgood liked on 19th October 2020
mohamed amine liked on 19th October 2020
Richard Radermacher liked on 19th October 2020
ArielMejiaDev retweeted on 19th October 2020
dSoto liked on 19th October 2020
ArielMejiaDev liked on 19th October 2020
Claudio Dekker liked on 19th October 2020
Daniel Lucas liked on 19th October 2020
Luigi Cruz liked on 19th October 2020
Miguel Piedrafita 🚀 liked on 19th October 2020
Robin Dirksen liked on 13th October 2020
Richard Radermacher liked on 13th October 2020