Users microservice for MUI Toolpad Extended TUNI
npm install @mui-toolpad-extended-tuni/usersUsers microservice extension for MUI Toolpad Extended TUNI. This package provides user management functionality, user authentication, user settings, and user-related components.
``bash`
npm install @mui-toolpad-extended-tuni/users @mui-toolpad-extended-tuni/main @mui-toolpad-extended-tuni/core
Important: You must also install @mui-toolpad-extended-tuni/main and @mui-toolpad-extended-tuni/core as they are required peer dependencies.
This package requires the following peer dependencies to be installed:
: ^3.4.0 - MUST be installed separately: ^3.2.0 - MUST be installed separately (also required by main)
- react-dom@^19.0.0
- react-router-dom@^7.0.0
- @mui/material@^7.0.0
- @mui/icons-material@^7.0.0
- @emotion/react@^11.0.0
- @emotion/styled@^11.0.0
- axios@^1.7.0
- zustand@^4.5.0$3
`bash
npm install @mui-toolpad-extended-tuni/users @mui-toolpad-extended-tuni/main @mui-toolpad-extended-tuni/core \
react react-dom react-router-dom \
@mui/material @mui/icons-material \
@emotion/react @emotion/styled \
axios zustand
`API Configuration
This package uses configurable API endpoints. Each microservice accepts its own
apiEndpoints prop, allowing you to configure endpoints independently for only the services you use.$3
If no
apiEndpoints prop is provided, the package uses these default endpoints:-
getCurrent: "api/users/current/" - GET current authenticated user
- get: "api/users/" - GET list of users
- post: "api/users/" - POST create new user
- put: "api/users/:id/" - PUT update user (use :id placeholder)
- delete: "api/users/:id/" - DELETE user (use :id placeholder)
- logout: "/auth/lti_logout/" - POST logout user$3
Configure endpoints directly on the
UserMicroservice component:`tsx
import { UserMicroservice } from '@mui-toolpad-extended-tuni/users';
import type { UsersApiEndpoints } from '@mui-toolpad-extended-tuni/users';const usersEndpoints: UsersApiEndpoints = {
getCurrent: "https://api.example.com/v1/users/me",
get: "https://api.example.com/v1/users",
post: "https://api.example.com/v1/users",
put: "https://api.example.com/v1/users/:id",
delete: "https://api.example.com/v1/users/:id",
logout: "https://api.example.com/v1/auth/logout",
};
`Note: You can use either full URLs or relative paths. Placeholders like
:id will be replaced with actual values at runtime.Partial Configuration: You can configure only the endpoints you need to customize. Unspecified endpoints will use defaults:
`tsx
getCurrent: "api/v2/users/me", // Only override getCurrent endpoint
// Other endpoints use defaults
}} />
`Usage
$3
The users microservice automatically configures the UserBus when imported:
`tsx
import { BrowserRouter } from 'react-router-dom';
import { ToolpadProvider, Microservices } from 'mui-toolpad-extended-tuni';
import { UserMicroservice } from '@mui-toolpad-extended-tuni/users';function App() {
return (
{/ Other microservices /}
);
}
`$3
`tsx
import { useUserStore } from '@mui-toolpad-extended-tuni/users';function MyComponent() {
const { user, users, getUser, getUsers, updateUser } = useUserStore();
useEffect(() => {
getUser();
getUsers();
}, [getUser, getUsers]);
return (
{user && Welcome, {user.name}}
);
}
`$3
`tsx
import { UserSettings } from '@mui-toolpad-extended-tuni/users';function SettingsPage() {
return ;
}
`$3
`tsx
import { UserManager } from '@mui-toolpad-extended-tuni/users';function App() {
return (
<>
{/ Rest of your app /}
>
);
}
`API Endpoints
This package makes the following API calls. All endpoints are configurable via
apiConfig.$3
Retrieves the currently authenticated user.
Request: No body required (uses session/cookies for authentication)
Response:
200 OK
`json
{
"id": "user-123",
"name": "John Doe",
"email": "john.doe@example.com",
"gender": "male",
"image": {
"large": "https://example.com/images/user-large.jpg",
"medium": "https://example.com/images/user-medium.jpg",
"thumbnail": "https://example.com/images/user-thumbnail.jpg"
},
"department": "Computer Science",
"platform_roles": ["user", "creator"],
"privacy_settings": {
"allow_analytics": true,
"allow_personalization": true,
"allow_communications": true,
"allow_third_party_sharing": false
},
"gdpr_consent": {
"accepted": true,
"accepted_date": "2024-01-15T10:00:00Z",
"last_updated": "2024-01-15T10:00:00Z"
},
"data_retention": {
"delete_account_after_inactivity": 365,
"delete_data_after_account_deletion": 30
},
"preferences": {
"navigation_type": "direct",
"visible_course_lists": {
"is_student": true,
"is_student_old": true,
"is_teacher": false,
"is_teacher_old": false,
"available": true
},
"last_visited_courses": ["COMP.CS.100:compcs100-fall-2024"],
"visible_navigation": ["Courses", "Calendar"]
}
}
`Response Type:
UserData$3
Retrieves a list of users. Optionally filtered by course.
Request Parameters (query string):
-
course_id (optional) - Filter users by course IDExample:
GET /api/users/?course_id=course-123Response:
200 OK
`json
[
{
"id": "user-123",
"name": "John Doe",
"email": "john.doe@example.com",
// ... same structure as getCurrent
},
{
"id": "user-456",
"name": "Jane Smith",
"email": "jane.smith@example.com",
// ...
}
]
`Response Type:
UserData[]$3
Creates a new user.
Request Body:
Partial (snake_case)
`json
{
"name": "John Doe",
"email": "john.doe@example.com",
"gender": "male",
"department": "Computer Science",
"platform_roles": ["user"],
"privacy_settings": {
"allow_analytics": true,
"allow_personalization": true,
"allow_communications": true,
"allow_third_party_sharing": false
},
"gdpr_consent": {
"accepted": true,
"last_updated": "2024-01-15T10:00:00Z"
},
"data_retention": {
"delete_account_after_inactivity": 365,
"delete_data_after_account_deletion": 30
},
"preferences": {
"navigation_type": "direct",
"visible_course_lists": {
"is_student": true,
"is_student_old": true,
"is_teacher": false,
"is_teacher_old": false,
"available": true
},
"last_visited_courses": [],
"visible_navigation": ["Courses"]
}
}
`Response:
201 Created
`json
{
"id": "user-123",
"name": "John Doe",
// ... full UserData object with generated ID
}
`Response Type:
UserDataNote: The request body should be in snake_case format. The package automatically converts from camelCase.
$3
Updates an existing user.
Request Parameters:
-
:id (path parameter) - User IDRequest Body:
UserData (snake_case, must include id)
`json
{
"id": "user-123",
"name": "Updated Name",
"email": "updated.email@example.com",
// ... all UserData fields
}
`Response:
200 OK
`json
{
"id": "user-123",
"name": "Updated Name",
// ... updated UserData object
}
`Response Type:
UserData$3
Deletes a user.
Request Parameters:
-
:id (path parameter) - User IDResponse:
200 OK or 204 No ContentResponse Type:
void$3
Logs out the current user (LTI logout).
Request: No body required
Response:
200 OK or 204 No ContentResponse Type:
voidData Types
$3
Complete user object returned by API.
`typescript
interface UserData {
id: userId; // Unique user ID (string)
name: string; // User's full name
email: string; // User's email address
gender?: gender; // "male" | "female" | "other" (optional)
image?: { // User profile images (optional)
large: string; // Large image URL
medium: string; // Medium image URL
thumbnail: string; // Thumbnail image URL
};
department?: string; // User's department (optional)
platformRoles: PlatformRole[]; // Array of platform roles
privacySettings: { // Privacy preferences
allowAnalytics: boolean;
allowPersonalization: boolean;
allowCommunications: boolean;
allowThirdPartySharing: boolean;
};
gdprConsent: { // GDPR consent information
accepted: boolean;
acceptedDate?: string; // ISO date string (optional)
lastUpdated: string; // ISO date string
};
dataRetention: { // Data retention settings
deleteAccountAfterInactivity?: number; // Days (optional)
deleteDataAfterAccountDeletion?: number; // Days (optional)
};
preferences: { // User preferences
navigationType: navigationTypes; // "direct" | "instances"
visibleCourseLists: {
isStudent: boolean;
isStudentOld: boolean;
isTeacher: boolean;
isTeacherOld: boolean;
available: boolean;
};
lastVisitedCourses: string[]; // Array of "code:instance" strings
visibleNavigation: string[]; // Array of visible navigation items
};
}
`$3
`typescript
type userId = string;
type navigationTypes = "direct" | "instances";
type gender = "male" | "female" | "other";
type PlatformRole = "admin" | "developer" | "moderator" | "creator" | "user" | "guest";
`$3
Important: The backend API expects and returns data in snake_case format (e.g.,
platform_roles, privacy_settings). This package automatically converts between camelCase (used in TypeScript) and snake_case (used in API requests/responses).Example conversion:
- TypeScript:
platformRoles → API: platform_roles
- TypeScript: privacySettings → API: privacy_settings
- TypeScript: lastVisitedCourses → API: last_visited_coursesExports
$3
- UserMicroservice - Main microservice component
- UserManager - User manager component (syncs navigation filters)
- UserSettings - User settings form component
- UserEventPublisher - Publishes user events to EventBus$3
- useUserStore - Zustand store for user management$3
- getCurrentUser() - Fetch current authenticated user
- getUsers(courseId?: string) - Fetch list of users (optionally filtered by course)
- createUser(userData: Partial - Create new user
- updateUser(userData: UserData) - Update existing user
- deleteUser(userId: string) - Delete user
- logoutUser() - Logout current user$3
- useUsersApiConfig() - Hook to access users API endpoint configuration$3
- configureUserBus - Configures UserBus with store methods (called automatically)$3
- UserData - Complete user data type
- UsersApiEndpoints - API endpoint configuration type
- PlatformRole - Platform role type
- navigationTypes - Navigation types
- gender - Gender type
- userId` - User ID type- User management and CRUD operations
- User authentication and session handling
- User preferences management
- User settings UI
- UserBus integration (automatic configuration)
- User event publishing
- Course user management
- GDPR consent handling
- Data retention settings
This package automatically configures the UserBus from the main package when imported. The UserBus provides a centralized way for other microservices to interact with user data without direct dependencies.
MIT