misuzu/src/Users/UsersApiRoutes.php

155 lines
5.6 KiB
PHP

<?php
namespace Misuzu\Users;
use RuntimeException;
use Index\XArray;
use Index\Colour\{Colour,ColourRgb};
use Index\Http\{HttpRequest,HttpResponseBuilder};
use Index\Http\Routing\AccessControl\AccessControl;
use Index\Http\Routing\Processors\Before;
use Index\Http\Routing\Routes\ExactRoute;
use Index\Urls\UrlRegistry;
use Misuzu\{FieldTransformer,SiteInfo};
use Misuzu\Auth\AuthInfo;
use Misuzu\Routing\{HandlerRoles,RouteHandler,RouteHandlerCommon};
use Misuzu\Users\UserInfo;
use Misuzu\Users\Assets\UserAvatarAsset;
#[HandlerRoles('main')]
final class UsersApiRoutes implements RouteHandler {
use RouteHandlerCommon;
public function __construct(
private SiteInfo $siteInfo,
private UrlRegistry $urls,
private UsersContext $usersCtx,
private AuthInfo $authInfo,
) {}
/** @return FieldTransformer<UserInfo> */
public function createUserTransformer(): FieldTransformer {
$fields = [
'id' => [
'default' => true,
'transform' => fn($user) => $user->id,
],
];
$openid = $this->authInfo->hasScope('openid');
if(!$openid || $this->authInfo->hasScope('profile')) {
$fields['name'] = [
'default' => true,
'transform' => fn($user) => $user->name,
];
$fields['colour_raw'] = [
'default' => true,
'transform' => function($user) {
$colour = $this->usersCtx->getUserColour($user);
return $colour->inherits ? null : Colour::toRawRgb($colour);
},
'include' => fn() => true,
];
$fields['colour_css'] = [
'default' => true,
'transform' => function($user) {
$colour = $this->usersCtx->getUserColour($user);
return $colour->inherits ? (string)$colour : (string)ColourRgb::convert($colour);
},
];
$fields['country_code'] = [
'default' => true,
'transform' => fn($user) => $user->countryCode,
];
$fields['rank'] = [
'default' => true,
'transform' => fn($user) => (
$this->usersCtx->hasActiveBan($user)
? 0
: $this->usersCtx->getUserRank($user)
),
];
$fields['roles'] = [
'default' => true,
'transform' => fn($user) => (
$this->usersCtx->hasActiveBan($user)
? ['x-banned']
: XArray::select(
$this->usersCtx->roles->getRoles(
userInfo: $user,
hasString: true,
orderByRank: true
),
fn($roleInfo) => $roleInfo->string,
)
),
];
$fields['is_super'] = [
'default' => true,
'transform' => fn($user) => $user->super,
'include' => fn($value) => $value === true,
];
$fields['title'] = [
'default' => true,
'transform' => fn($user) => empty($user->title) ? null : $user->title,
];
$fields['created_at'] = [
'default' => true,
'transform' => fn($user) => $user->createdAt->toIso8601ZuluString(),
];
$fields['last_active_at'] = [
'default' => true,
'transform' => fn($user) => $user->lastActiveAt?->toIso8601ZuluString(),
];
$fields['profile_url'] = [
'default' => true,
'transform' => fn($user) => ($this->siteInfo->url . $this->urls->format('user-profile', ['user' => $user->id])),
];
$fields['avatar_url'] = [
'default' => true,
'transform' => fn($user) => ($this->siteInfo->url . $this->urls->format('user-avatar', ['user' => $user->id])),
];
$fields['is_deleted'] = [
'default' => true,
'transform' => fn($user) => $user->deleted,
'include' => fn($value) => $value === true,
];
}
if($this->authInfo->hasScope($openid ? 'email' : 'identify:email'))
$fields['email'] = [
'default' => true,
'transform' => fn($user) => $user->emailAddress,
];
return new FieldTransformer($fields);
}
/** @return int|mixed[] */
#[AccessControl]
#[ExactRoute('GET', '/api/v1/me')]
#[Before('authz:cookie', required: false)]
#[Before('authz:bearer', required: false)]
#[Before('authz:misuzu', required: false)]
public function getMe(HttpResponseBuilder $response, HttpRequest $request): int|array {
$response->setHeader('Cache-Control', 'no-store');
$openid = $this->authInfo->hasScope('openid');
if(!$openid
&& !$this->authInfo->hasScope('identify')
&& !$this->authInfo->hasScope('beans'))
return 403;
$transformer = $this->createUserTransformer();
if(!$transformer->filter($request))
return 400;
try {
$userInfo = $this->usersCtx->getUserInfo($this->authInfo->userId, UsersData::GET_USER_ID);
} catch(RuntimeException) {
return 404;
}
return $transformer->convert($userInfo);
}
}