Giter Site home page Giter Site logo

Comments (10)

fibis avatar fibis commented on May 2, 2024 2

To login into BookStack with a oauth2 provider is also one of my needs. +1

from bookstack.

ssddanbrown avatar ssddanbrown commented on May 2, 2024 1

Just setting up a local raspberry pi LDAP server now so I can get familiar with LDAP and implement it properly 😄

from bookstack.

mbugeia avatar mbugeia commented on May 2, 2024

+1 for LDAP
Bonus point, if you add reverse proxy auth compatibility via HTTP basic authentification (for SSO) I will probably make a Yunohost package.

from bookstack.

TJuberg avatar TJuberg commented on May 2, 2024

+1 for LDAP as well.

from bookstack.

ssddanbrown avatar ssddanbrown commented on May 2, 2024

As of release 0.7 (commit 148e172) LDAP user auth is now part of BookStack. It's only basic at the moment, and experimental since it has only been tested by me. Setup/Usage instructions are in the readme.

Since login is functional in some capacity I will close this issue. For any extra LDAP features or bugs new ,more focused, issues should be created.

from bookstack.

ssddanbrown avatar ssddanbrown commented on May 2, 2024

@MVprobr Thanks for letting me know. In regards to oAuth, What exactly is it that you want implemented in BookStack?

  • Some kind of generic oAuth implementation?
  • A specific oAuth provider to login with?
  • Do you want BookStack to act as a oAuth provider?

Sorry for the questions, I'm not too familiar with the actual use cases when it comes to oAuth.

from bookstack.

younes0 avatar younes0 commented on May 2, 2024

I need to setup a specific oauth2 provider in my case. This should be easy to implement.
I will also try to make the admin options for it.

from bookstack.

dealproc avatar dealproc commented on May 2, 2024

@younes0 did you ever get sorted with this? I'd like to experiment with it against identityserver4 and possibly use this system.

from bookstack.

younes0 avatar younes0 commented on May 2, 2024

@dealproc I've setup Socialite on my bookstack instance, and I handle user creation from my main app.

Socialite:

namespace BookStack\Providers;

use Illuminate\Support\Facades\Auth;
use Illuminate\Support\ServiceProvider;
use BookStack\User;
use BookStack\Icra\IcramProvider;


class AppServiceProvider extends ServiceProvider
{
    /**
     * Bootstrap any application services.
     *
     * @return void
     */
    public function boot()
    {
        // Custom validation methods
        \Validator::extend('is_image', function($attribute, $value, $parameters, $validator) {
            $imageMimes = ['image/png', 'image/bmp', 'image/gif', 'image/jpeg', 'image/jpg', 'image/tiff', 'image/webp'];
            return in_array($value->getMimeType(), $imageMimes);
        });

        $socialite = $this->app->make('Laravel\Socialite\Contracts\Factory');

        $socialite->extend('icram', function ($app) use ($socialite) {
            $config = $app['config']['services.icram'];
            return $socialite->buildProvider(IcramProvider::class, $config);
        });

    }
}

<?php

namespace BookStack\Icra;

use Laravel\Socialite\Two\AbstractProvider;
use Laravel\Socialite\Two\ProviderInterface;
use Laravel\Socialite\Two\User;

class IcramProvider extends AbstractProvider implements ProviderInterface
{
    /**
     * {@inheritdoc}
     */
    protected function getAuthUrl($state)
    {
        return $this->buildAuthUrlFromBase(env('ICRAM_URL').'/oauth/authorize', $state);
    }

    /**
     * {@inheritdoc}
     */
    protected function getTokenUrl()
    {
        return env('ICRAM_URL').'/oauth/token';
    }

    /**
     * {@inheritdoc}
     */
    public function getAccessToken($code)
    {
        $response = $this->getHttpClient()->post($this->getTokenUrl(), [
            'headers' => ['Authorization' => 'Basic ' . base64_encode($this->clientId . ':' . $this->clientSecret)],
            'body'    => $this->getTokenFields($code),
        ]);

        return $this->parseAccessToken($response->getBody());
    }

    /**
     * {@inheritdoc}
     */
    protected function getTokenFields($code)
    {
        return array_add(
            parent::getTokenFields($code), 'grant_type', 'authorization_code'
        );
    }

    /**
     * {@inheritdoc}
     */
    protected function getUserByToken($token)
    {
        $response = $this->getHttpClient()->get(env('ICRAM_URL').'/api/me', [
            'headers' => [
                'Authorization' => 'Bearer ' . $token,
            ],
        ]);

        return json_decode($response->getBody(), true);
    }

    /**
     * {@inheritdoc}
     */
    protected function mapUserToObject(array $user)
    {
        return (new User)->setRaw($user)->map([
            'id'       => $user['id'],
            'nickname' => $user['username'],
            'name'     => $user['firstname'].' '.$user['lastname'],
            'avatar'   => null,
        ]);
    }

}

User Creation:

<?php

namespace Icram\Models;

use Yeb\Laravel\ExtendedModel;
use Carbon\Carbon;

class WikiUser extends ExtendedModel
{
    protected $connection = 'wiki';

    public static $unguarded = false;

    public $table = 'users';
    
    protected $guarded = [''];

    /**
     * Define the relationship with the user's roles.
     *
     * @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
     */
    public function roles()
    {
        return $this->belongsToMany(WikiRole::class, 'role_user', 'user_id', 'role_id');
    }

    public function getUser()
    {
        return User::where('email', $this->email)->first();
    }

    public static function firstOrCreateFromUser(User $user, $delete = true)
    {
        if ($model = $user->getWikiUser()) {
            if ($delete) {
                $model->delete();
            
            } else {
                return $model;
            }
        } 

        $model = static::create(static::getDefaults($user));

        // group
        $roleName = $user->is_admin ? 'admin' : 'viewer';
        $role = WikiRole::where('name', $roleName)->first();
        
        $model->roles()->attach($role);
        $model->save();
        
        $con = \DB::connection('wiki');

        // social account
        $con->table('social_accounts')->insert([
            'user_id'   => $model->id,
            'driver'    => 'icram',
            'driver_id' => $user->id,
            'avatar'    => '',
        ]);

        // image
        $imageId = $con->table('images')->insertGetId([
            'name'       => $user->id.'.jpg',
            'url'        => $user->photoUrl,
            'path'       => '/photos/'.$user->id.'.jpg',
            'type'       => 'jpeg',
            'created_at' => Carbon::now(),
            'updated_at' => Carbon::now(),
            'created_by' => $model->id,
            'updated_by' => $model->id,
        ]);

        $model->update(['image_id' => $imageId]);
        
        return $model;
    }

    public function syncInfos()
    {
        $this->update(static::getDefaults($this->getUser()));

        return $this;
    }

    static protected function getDefaults($user)
    {
        return [
            'name'             => $user->fullname, 
            'email'            => $user->email,
            'email_confirmed'  => true,
            'password'         => $user->password ?: str_random(),
            'external_auth_id' => '',
            'image_url'        => $user->photoUrl, 
        ];
    }
}

<?php

namespace Icram\Models;

use Yeb\Laravel\ExtendedModel;

class WikiRole extends ExtendedModel
{
    protected $connection = 'wiki';

    public static $unguarded = false;

    public $table = 'roles';
    
    protected $guarded = [''];

    /**
     * Define the relationship with the group's users.
     *
     * @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
     */
    public function users()
    {
        return $this->belongsToMany(WikiUser::class, 'role_user');
    }
}

// usage from main app
/*
 * Create/Update related when User is created/updated
 *
 * @return void
 */
public static function boot()
{
    parent::boot();

    // created
    static::created(function($model) {
        $model->profile()->create([]);
    });

    // updated
    static::updated(function($model) {
        // wiki
        $wikiUser = $model->getWikiUser();

        if ($wikiUser) {
            $wikiUser->syncInfos();
        
        } else if ($model->isComplete()) {
            WikiUser::firstOrCreateFromUser($model);
        }
    });

    // deleted
    static::deleting(function($model) {
           if ($wikiUser = WikiUser::where('email', $model->email)->first()) {
            $wikiUser->delete();
        }
    });
}

from bookstack.

dealproc avatar dealproc commented on May 2, 2024

I have no idea of how to make that dance. Will have to bookmark this and come back to it once i get a little read through and see if its possible. my hope was to have a user directed to this, and let them create their user within the system as a "user", and then assign them into what categories they'd need thereafter. I like the idea of this system as you're publishing eBooks per topic/product/whatever, which is what intrigued me about it.

from bookstack.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.