Skip to content

Commit 7af368d

Browse files
committed
fix: docs profile
1 parent f5d39eb commit 7af368d

File tree

4 files changed

+167
-126
lines changed

4 files changed

+167
-126
lines changed

docs-v3/content/auth/profile.md

Lines changed: 108 additions & 117 deletions
Original file line numberDiff line numberDiff line change
@@ -5,24 +5,24 @@ category: Auth
55
position: 1
66
---
77

8+
Laravel Restify provides a convenient profile endpoint that allows authenticated users to retrieve and update their profile information using the same repository system that powers the rest of your API.
9+
810
## Prerequisites
911

10-
Make sure you followed the [Authentication](/auth/authentication) guide first, as one common mistake is not adding this middleware:
12+
Make sure you followed the [Authentication](/auth/authentication) guide first, as you need the authentication middleware configured:
1113

1214
```php
1315
// config/restify.php
1416
'middleware' => [
15-
// ...
17+
// ...
1618
'auth:sanctum',
17-
// ...
19+
// ...
1820
]
1921
```
2022

2123
## Get profile
2224

23-
Before retrieving the user's profile, you need to log in and obtain an authentication token. You can refer to the [login documentation](/auth/authentication#login) for details on how to authenticate a user. Make sure to include `Bearer {$token}` in the `Authorization` header for subsequent API requests, either using Postman or cURL.
24-
25-
When retrieving the user's profile, it is serialized by using the `UserRepository`.
25+
The profile endpoint uses your `UserRepository` to serialize the authenticated user's data, giving you full control over what fields are exposed and how relationships are handled.
2626

2727
```http request
2828
GET: /api/restify/profile
@@ -72,28 +72,27 @@ public function fields(RestifyRequest $request): array
7272
}
7373
```
7474

75-
Since the profile is managed using the UserRepository, you can now benefit from the power of related entities. For example, if you want to return user roles:
75+
Since the profile uses the UserRepository, you can include related entities using Restify's relationship system. For example, to include user roles:
7676

7777
```php
78-
//UserRepository
78+
// UserRepository
79+
use Binaryk\LaravelRestify\Fields\BelongsToMany;
7980

80-
public static array $related = [
81-
'roles',
82-
];
81+
public static function related(): array
82+
{
83+
return [
84+
'roles' => BelongsToMany::make('roles', RoleRepository::class),
85+
];
86+
}
8387
```
8488

85-
Also, make sure the `User` model has this method that returns a relationship from another table, or you can simply return an array:
89+
Make sure your `User` model defines the proper Eloquent relationship:
8690

8791
```php
88-
//User.php
89-
90-
public function roles(): array
92+
// User.php
93+
public function roles(): BelongsToMany
9194
{
92-
// In a real project, here you will get this information from the database.
93-
return [
94-
'owner',
95-
'admin'
96-
];
95+
return $this->belongsToMany(Role::class);
9796
}
9897
```
9998

@@ -115,8 +114,20 @@ The result will look like this:
115114
},
116115
"relationships": {
117116
"roles": [
118-
"owner",
119-
"admin"
117+
{
118+
"id": "1",
119+
"type": "roles",
120+
"attributes": {
121+
"name": "owner"
122+
}
123+
},
124+
{
125+
"id": "2",
126+
"type": "roles",
127+
"attributes": {
128+
"name": "admin"
129+
}
130+
}
120131
]
121132
},
122133
"meta": {
@@ -128,89 +139,34 @@ The result will look like this:
128139
}
129140
```
130141

131-
### Without repository
132-
133-
In some cases, you might choose not to use the repository for profile serialization. To do this, you should add the `Binaryk\LaravelRestify\Repositories\UserProfile` trait to your `UserRepository`:
134-
135-
```php
136-
// UserProfile
137-
138-
use Binaryk\LaravelRestify\Repositories\UserProfile;
139-
140-
class UserRepository extends Repository
141-
{
142-
use UserProfile;
143-
144-
public static $model = 'App\\Models\\User';
145-
146-
//...
147-
}
148-
```
149-
150-
The profile will return the model directly:
151-
152-
### Relations
153-
<alert type="warning">
154-
Note that when you're not using the repository, the `?include` parameter will not work.
155-
</alert>
156-
157-
```http request
158-
/api/restify/profile
159-
```
160-
161-
You will get:
162-
163-
```json
164-
{
165-
"data": {
166-
"id": 7,
167-
"name": "Eduard",
168-
"email": "[email protected]",
169-
"email_verified_at": null,
170-
"created_at": "2020-12-24T08:49:30.000000Z",
171-
"updated_at": "2020-12-24T08:52:37.000000Z"
172-
}
173-
}
174-
```
175-
176-
### Conditionally use repository
142+
### Repository Control
177143

178-
In rare cases, you may want to use the repository only for non-admin users. Make sure to serialize specific fields for users:
144+
You can control whether the repository is used for profile serialization by implementing the `canUseForProfile` method:
179145

180146
```php
181-
use Binaryk\LaravelRestify\Fields\Field;
182147
use Binaryk\LaravelRestify\Http\Requests\RestifyRequest;
183-
use Binaryk\LaravelRestify\Repositories\UserProfile;
184148
use Illuminate\Http\Request;
185149

186150
class UserRepository extends Repository
187151
{
188-
use UserProfile;
189-
190-
public static $model = 'App\\Models\\User';
191-
192-
public static function canUseForProfile(Request $request)
152+
public static function canUseForProfile(Request $request): bool
193153
{
194-
return $request->user()->isAdmin();
154+
return true; // Always use repository for profile serialization
195155
}
196156

197-
public function fields(RestifyRequest $request)
157+
public function fields(RestifyRequest $request): array
198158
{
199159
return [
200160
field('name')->rules('required'),
201-
202-
field('email')->rules('required')
203-
->storingRules('unique:users')->messages([
204-
'required' => 'This field is required.',
205-
]),
161+
field('email')->rules('required')->storingRules('unique:users'),
206162
];
207163
}
208164
}
209165
```
210166

211-
This instructs Restify to use the repository only for users who are admins of your application.
167+
This method determines whether the repository should be used for profile serialization. Returning `true` enables full repository functionality including field control, validation, and relationships.
212168

213-
## Update profile using repository
169+
## Update profile
214170

215171
By default, Restify will validate and fill only the fields defined in your `UserRepository` when updating the user's profile. Let's use the following repository fields as an example:
216172

@@ -279,36 +235,9 @@ Since the payload is valid now, Restify will update the user's profile (a name,
279235
}
280236
```
281237

282-
### Update without repository
283-
284-
If you [don't use the repository](#without-repository) for the user's profile, Restify will only update the `fillable` user attributes that are present in the request payload: `$request->only($user->getFillable())`.
285-
286-
```http request
287-
PUT: /api/restify/profile
288-
```
289-
290-
Payload:
291-
292-
````json
293-
{
294-
"name": "Eduard Lupacescu"
295-
}
296-
````
297-
298-
The response will be the updated user:
238+
### File uploads
299239

300-
```json
301-
{
302-
"data": {
303-
"id": 7,
304-
"name": "Eduard",
305-
"email": "[email protected]",
306-
"email_verified_at": null,
307-
"created_at": "2020-12-24T08:49:30.000000Z",
308-
"updated_at": "2020-12-24T09:34:48.000000Z"
309-
}
310-
}
311-
```
240+
For file uploads (like user avatars), you must use a POST request instead of PUT or PATCH:
312241

313242
## User avatar
314243

@@ -341,22 +270,84 @@ public function fields(RestifyRequest $request)
341270

342271
You can use the Restify's profile update and give the avatar as an image.
343272

344-
### Post request
273+
### Upload request
345274

346275
<alert type="warning">
347-
You cannot upload a file using PUT or PATCH verbs, so you should use a POST request instead.
276+
You cannot upload a file using PUT or PATCH verbs, so you must use a POST request instead.
348277
</alert>
349278

350279
```http request
351280
POST: /api/restify/profile
352281
```
353282

354-
The payload should be a form-data, with an image under the `avatar` key:
283+
The payload should be form-data, with an image under the `avatar` key:
355284

356285
```json
357286
{
358287
"avatar": "binary image in form data request"
359288
}
360289
```
361290

291+
The response will be the updated profile with the new avatar URL:
292+
293+
```json
294+
{
295+
"id": "7",
296+
"type": "users",
297+
"attributes": {
298+
"name": "Eduard",
299+
"email": "[email protected]",
300+
"avatar": "/storage/avatars/avatar.jpg"
301+
},
302+
"meta": {
303+
"authorizedToShow": true,
304+
"authorizedToStore": true,
305+
"authorizedToUpdate": true,
306+
"authorizedToDelete": true
307+
}
308+
}
309+
```
310+
362311
If you need to customize the path or disk for the storage file, check the [image field](/api/fields#file-fields) documentation.
312+
313+
## MCP Integration
314+
315+
AI agents can access the user profile using the MCP server's profile tool. When you include the `HasMcpTools` trait in your `UserRepository`, it automatically exposes a `users-profile-tool` that AI agents can use to retrieve the current authenticated user's profile including relationships.
316+
317+
```php
318+
use Binaryk\LaravelRestify\MCP\Concerns\HasMcpTools;
319+
320+
#[Model(User::class)]
321+
class UserRepository extends Repository
322+
{
323+
use HasMcpTools;
324+
325+
public static function canUseForProfile(Request $request): bool
326+
{
327+
return true;
328+
}
329+
330+
public static function related(): array
331+
{
332+
return [
333+
'roles' => BelongsToMany::make('roles', RoleRepository::class),
334+
];
335+
}
336+
}
337+
```
338+
339+
The AI agent can then use this tool to access profile information:
340+
341+
```json
342+
{
343+
"method": "tools/call",
344+
"params": {
345+
"name": "users-profile-tool",
346+
"arguments": {
347+
"include": "roles"
348+
}
349+
}
350+
}
351+
```
352+
353+
This provides AI agents with the same authentication and authorization controls as regular API access, ensuring secure profile data access.

docs-v3/pages/index.vue

Lines changed: 52 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -171,8 +171,11 @@
171171
</section>
172172

173173
<!-- Architecture Flow Diagram -->
174-
<section class="py-20 bg-gray-50/50 dark:bg-gray-800/20 relative">
175-
<div class="mx-auto px-4">
174+
<section class="py-20 relative overflow-hidden">
175+
<!-- Animated neon border -->
176+
<div class="absolute inset-4 rounded-3xl neon-border-animated"></div>
177+
178+
<div class="mx-auto px-4 relative z-10">
176179
<h2 class="text-4xl font-bold text-center text-gray-900 dark:text-white mb-20">
177180
How It Works
178181
</h2>
@@ -519,4 +522,51 @@ useHead({
519522
.animate-scroll:hover {
520523
animation-play-state: paused;
521524
}
525+
526+
@keyframes neonBorder {
527+
0% {
528+
background: conic-gradient(from 0deg, transparent, transparent, #3b82f6, #60a5fa, #3b82f6, transparent, transparent);
529+
}
530+
25% {
531+
background: conic-gradient(from 90deg, transparent, transparent, #3b82f6, #60a5fa, #3b82f6, transparent, transparent);
532+
}
533+
50% {
534+
background: conic-gradient(from 180deg, transparent, transparent, #3b82f6, #60a5fa, #3b82f6, transparent, transparent);
535+
}
536+
75% {
537+
background: conic-gradient(from 270deg, transparent, transparent, #3b82f6, #60a5fa, #3b82f6, transparent, transparent);
538+
}
539+
100% {
540+
background: conic-gradient(from 360deg, transparent, transparent, #3b82f6, #60a5fa, #3b82f6, transparent, transparent);
541+
}
542+
}
543+
544+
.neon-border-animated {
545+
background: conic-gradient(from 0deg, transparent, transparent, #3b82f6, #60a5fa, #3b82f6, transparent, transparent);
546+
animation: neonBorder 8s linear infinite;
547+
padding: 3px;
548+
}
549+
550+
.neon-border-animated::before {
551+
content: '';
552+
position: absolute;
553+
inset: 3px;
554+
border-radius: inherit;
555+
background: rgba(249, 250, 251, 0.8);
556+
}
557+
558+
.dark .neon-border-animated::before {
559+
background: rgba(17, 24, 39, 0.8);
560+
}
561+
562+
.neon-border-animated::after {
563+
content: '';
564+
position: absolute;
565+
inset: 3px;
566+
border-radius: inherit;
567+
background: inherit;
568+
filter: blur(8px);
569+
opacity: 0.5;
570+
z-index: -1;
571+
}
522572
</style>

0 commit comments

Comments
 (0)