Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[PropelAuth] add custom user class and logout function #1323

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
151 changes: 151 additions & 0 deletions src/PropelAuth/Models/OrgMemberInfo.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
<?php

namespace SocialiteProviders\PropelAuth\Models;

use Illuminate\Support\Collection;
use JsonSerializable;

class OrgMemberInfo implements JsonSerializable
{
private const MULTI_ROLE = 'multi_role';
private const SINGLE_ROLE = "single_role_in_hierarchy";

private string $orgId;
private string $orgName;
private string $urlSafeOrgName;
private array $orgMetadata;
private string $userRole;
private array $inheritedUserRolesPlusCurrentRole;
private string $orgRoleStructure;
private array $additionalRoles;
private array $userPermissions;

public function __construct(
string $orgId,
string $orgName,
string $urlSafeOrgName,
array $orgMetadata,
string $userRole,
array $inheritedUserRolesPlusCurrentRole,
string $orgRoleStructure,
array $additionalRoles,
array $userPermissions
) {
$this->orgId = $orgId;
$this->orgName = $orgName;
$this->urlSafeOrgName = $urlSafeOrgName;
$this->orgMetadata = $orgMetadata;
$this->userRole = $userRole;
$this->inheritedUserRolesPlusCurrentRole = $inheritedUserRolesPlusCurrentRole;
$this->orgRoleStructure = $orgRoleStructure;
$this->additionalRoles = $additionalRoles;
$this->userPermissions = $userPermissions;
}

public function isRole(string $role): bool
{
return $role === $this->userRole ||
($this->orgRoleStructure === self::MULTI_ROLE &&
in_array($role, $this->additionalRoles, true));
}


public function isAtLeastRole(string $role): bool
{
if ($this->orgRoleStructure === self::MULTI_ROLE) {
return $role === $this->userRole || in_array($role, $this->additionalRoles, true);
} else {
return in_array($role, $this->inheritedUserRolesPlusCurrentRole, true);
}
}

public function hasPermission(string $permission): bool
{
return isset($this->userPermissions) && in_array($permission, $this->userPermissions);
}

public function hasAllPermissions(array $permissions): bool
{
if (!isset($this->userPermissions)) {
return false;
}

return Collection::make($permissions)
->every(fn($permission) => in_array($permission, $this->userPermissions));
}

public function getOrgId(): string
{
return $this->orgId;
}

public function getOrgName(): string
{
return $this->orgName;
}

public function getUrlSafeOrgName(): string
{
return $this->urlSafeOrgName;
}

public function getOrgMetadata(): ?array
{
return $this->orgMetadata;
}

public function getUserRole(): string
{
return $this->userRole;
}

public function getInheritedUserRolesPlusCurrentRole(): array
{
return $this->inheritedUserRolesPlusCurrentRole;
}

public function getOrgRoleStructure(): string
{
return $this->orgRoleStructure;
}

public function getAdditionalRoles(): array
{
return $this->additionalRoles;
}

public function getUserPermissions(): array
{
return $this->userPermissions;
}

public function jsonSerialize(): array
{
return [
'org_id' => $this->orgId,
'org_name' => $this->orgName,
'url_safe_org_name' => $this->urlSafeOrgName,
'org_metadata' => $this->orgMetadata,
'user_role' => $this->userRole,
'inherited_user_roles_plus_current_role' => $this->inheritedUserRolesPlusCurrentRole,
'org_role_structure' => $this->orgRoleStructure,
'additional_roles' => $this->additionalRoles,
'user_permissions' => $this->userPermissions,
];
}

public static function getOrgMemberInfoFromArray(array $data): self
{
return new self(
$data['org_id'],
$data['org_name'],
$data['url_safe_org_name'],
$data['org_metadata'],
$data['user_role'],
$data['inherited_user_roles_plus_current_role'],
$data['org_role_structure'],
$data['additional_roles'],
$data['user_permissions']
);
}
}
191 changes: 191 additions & 0 deletions src/PropelAuth/Models/PropelAuthUser.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,191 @@
<?php

namespace SocialiteProviders\PropelAuth\Models;

use SocialiteProviders\Manager\OAuth2\User as SocialiteUser;
use Illuminate\Support\Collection;

class PropelAuthUser extends SocialiteUser
{

public static function getPropelAuthUser(SocialiteUser $socialiteUser): self
{
$instance = new static();
$instance->setRaw($socialiteUser->getRaw());

$instance->token = $socialiteUser->token;
$instance->refreshToken = $socialiteUser->refreshToken;
$instance->expiresIn = $socialiteUser->expiresIn;

return $instance;
}

// Getters

public function getUserId(): string
{
return $this->getRaw()['user_id'];
}

public function getEmail(): string
{
return $this->getRaw()['email'];
}

public function getFirstName(): ?string
{
return $this->getRaw()['first_name'];
}

public function getLastName(): ?string
{
return $this->getRaw()['last_name'];
}

public function getUsername(): ?string
{
return $this->getRaw()['username'] ?? null;
}

public function getPictureUrl(): ?string
{
return $this->getRaw()['picture_url'] ?? null;
}

public function getMetadata(): ?array
{
return $this->getUserProperty('metadata');
}

public function getLegacyUserId(): ?string
{
return $this->getRaw()['legacy_user_id'] ?? null;
}

public function getCanCreateOrgs(): bool
{
return $this->getRaw()['can_create_orgs'];
}

public function getCreatedAt(): int
{
return $this->getRaw()['created_at'];
}

public function getLastActiveAt(): int
{
return $this->getRaw()['last_active_at'];
}

public function getIsEmailConfirmed(): bool
{
return $this->getRaw()['email_confirmed'];
}

public function getIsEnabled(): bool
{
return $this->getRaw()['enabled'];
}

public function getHasPassword(): bool
{
return $this->getRaw()['has_password'];
}

public function getIsLocked(): bool
{
return $this->getRaw()['locked'];
}

public function getIsMfaEnabled(): bool
{
return $this->getRaw()['mfa_enabled'];
}

public function getIsUpdatePasswordRequired(): bool
{
return $this->getRaw()['update_password_required'];
}

public function getUserProperty(string $propertyName): mixed
{
return $this->getRaw()['properties'][$propertyName] ?? null;
}

public function getProperties(): array
{
return $this->getRaw()['properties'] ?? [];
}

public function getActiveOrg(): ?OrgMemberInfo
{
$orgMemberInfo = $this->getRaw()['org_member_info'] ?? null;

if (!$orgMemberInfo) {
return null;
}

return OrgMemberInfo::getOrgMemberInfoFromArray($orgMemberInfo);
}

public function getActiveOrgId(): ?string
{
return $this->getRaw()['org_member_info'] ?? [] ['org_id'] ?? null;
}

public function getAccessToken(): string
{
return $this->token;
}

public function getRefreshToken(): string
{
return $this->refreshToken;
}

public function getTokenExpiresIn(): int
{
return $this->expiresIn;
}

// Org Functions

public function isRoleInOrg(string $orgId, string $role): bool
{
$org = $this->getOrg($orgId);
return $org ? $org->isRole($role) : false;
}

public function isAtLeastRoleInOrg(string $orgId, string $role): bool
{
$org = $this->getOrg($orgId);
return $org ? $org->isAtLeastRole($role) : false;
}

public function hasPermissionInOrg(string $orgId, string $permission): bool
{
$org = $this->getOrg($orgId);
return $org ? $org->hasPermission($permission) : false;
}

public function hasAllPermissionsInOrg(string $orgId, array $permissions): bool
{
$org = $this->getOrg($orgId);
return $org ? $org->hasAllPermissions($permissions) : false;
}

public function getOrgs(): Collection
{
$orgInfo = $this->getRaw()['org_id_to_org_info'] ?? [];
$orgMemberInfoCollection = Collection::make($orgInfo)
->map(fn ($orgData, $orgId) => OrgMemberInfo::getOrgMemberInfoFromArray(array_merge($orgData, ['org_id' => $orgId])));

return $orgMemberInfoCollection;
}

public function getOrg(string $orgId): ?OrgMemberInfo
{
return $this->getOrgs()->get($orgId);
}

}
12 changes: 12 additions & 0 deletions src/PropelAuth/Provider.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
use InvalidArgumentException;
use SocialiteProviders\Manager\OAuth2\AbstractProvider;
use SocialiteProviders\Manager\OAuth2\User;
use Illuminate\Support\Facades\Http;

class Provider extends AbstractProvider
{
Expand Down Expand Up @@ -36,6 +37,17 @@ protected function getBaseUrl(): string
return rtrim($baseUrl, '/');
}

public function logout($refreshToken): bool
{
$response = Http::withHeaders([
'Content-Type' => 'application/json',
])->post(env('PROPELAUTH_AUTH_URL') . '/api/backend/v1/logout', [
'refresh_token' => $refreshToken,
]);

return !$response->failed();
}

public static function additionalConfigKeys(): array
{
return ['auth_url'];
Expand Down
2 changes: 2 additions & 0 deletions src/PropelAuth/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ composer require socialiteproviders/propelauth

## Installation & Basic Usage

**For a full guide on how to integrate PropelAuth and Laravel, see our [docs here](/guides-and-examples/guides/laravel-authentication).**

Please see the [Base Installation Guide](https://socialiteproviders.com/usage/), then follow the [docs here](https://docs.propelauth.com/overview/authentication/oauth2) on how to setup an OAuth provider in PropelAuth.

### Add configuration to `config/services.php`
Expand Down
Loading