Skip to main content

Overview

The Admin API provides endpoints for administrators to review proposals, manage the review queue, and manage users. All endpoints require the ADMIN role.
All admin endpoints require authentication with the ADMIN role. Access is enforced by the @PreAuthorize("hasRole('ADMIN')") annotation at the controller level.

Get Pending Proposals

curl -X GET https://api.example.com/api/admin/proposals \
  -H "Authorization: Bearer YOUR_TOKEN"
GET /api/admin/proposals
Authorization: Bearer YOUR_TOKEN
Retrieve all pending proposals for the admin’s department. The proposals returned depend on the administrator’s department:
  • YOUTH_UNION - PENDING_L1 proposals for Youth Union events
  • STUDENT_ASSOCIATION - PENDING_L1 proposals for Student Association events
  • FACULTY - All PENDING_L2 proposals
  • RECTOR - All PENDING_L3 proposals

Response

statusCode
integer
HTTP status code (200)
message
string
Success message indicating the department
data
array
Array of proposal objects (ProposalDTO)
{
  "statusCode": 200,
  "message": "Proposals for department YOUTH_UNION retrieved successfully",
  "data": [
    {
      "proposalID": 1,
      "title": "Spring Tech Conference 2024",
      "description": "A comprehensive tech conference",
      "proposedDate": "2024-05-15",
      "startTime": "09:00:00",
      "endTime": "17:00:00",
      "venue": "Main Auditorium",
      "capacity": 300,
      "organizationType": "YOUTH_UNION",
      "status": "PENDING_L1",
      "attachmentsJson": "[{\"name\":\"budget.pdf\"}]",
      "submittedAt": "2024-03-05T09:00:00",
      "reviewedAt": null,
      "reviewedByID": null,
      "rejectionReason": null,
      "organizerID": 12,
      "organizerName": "John Smith"
    }
  ],
  "timestamp": "2024-03-07T10:30:00"
}

Get Proposal by ID

curl -X GET https://api.example.com/api/admin/proposals/1 \
  -H "Authorization: Bearer YOUR_TOKEN"
GET /api/admin/proposals/{proposalID}
Authorization: Bearer YOUR_TOKEN
Retrieve detailed information about a specific proposal.

Path Parameters

proposalID
integer
required
ID of the proposal to retrieve

Response

{
  "statusCode": 200,
  "message": "Proposal retrieved successfully",
  "data": {
    "proposalID": 1,
    "title": "Spring Tech Conference 2024",
    "description": "A comprehensive tech conference featuring industry leaders and hands-on workshops",
    "proposedDate": "2024-05-15",
    "startTime": "09:00:00",
    "endTime": "17:00:00",
    "venue": "Main Auditorium",
    "capacity": 300,
    "organizationType": "YOUTH_UNION",
    "status": "PENDING_L1",
    "attachmentsJson": "[{\"name\":\"budget.pdf\",\"url\":\"https://...\"}]",
    "submittedAt": "2024-03-05T09:00:00",
    "reviewedAt": null,
    "reviewedByID": null,
    "rejectionReason": null,
    "organizerID": 12,
    "organizerName": "John Smith"
  },
  "timestamp": "2024-03-07T10:30:00"
}

Approve Proposal

curl -X PUT https://api.example.com/api/admin/proposals/1/approve \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "comment": "Excellent proposal. Budget is well-planned."
  }'
PUT /api/admin/proposals/{proposalID}/approve
Content-Type: application/json
Authorization: Bearer YOUR_TOKEN
Approve a proposal. Depending on the current status and organization type, this may:
  • Move to the next approval level (L1 → L2 → L3)
  • Create an event if all approvals are complete

Path Parameters

proposalID
integer
required
ID of the proposal to approve

Request Body

comment
string
Optional approval comment or feedback

Response

statusCode
integer
HTTP status code (200)
message
string
Success message: “Proposal approved successfully”
data
null
No data returned
{
  "statusCode": 200,
  "message": "Proposal approved successfully",
  "data": null,
  "timestamp": "2024-03-07T10:30:00"
}

Reject Proposal

curl -X PUT https://api.example.com/api/admin/proposals/1/reject \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "rejectionReason": "Budget exceeds available funding. Please revise and resubmit."
  }'
PUT /api/admin/proposals/{proposalID}/reject
Content-Type: application/json
Authorization: Bearer YOUR_TOKEN
Reject a proposal with a reason. The organizer can then revise and resubmit.

Path Parameters

proposalID
integer
required
ID of the proposal to reject

Request Body

rejectionReason
string
required
Reason for rejecting the proposal (required)

Response

{
  "statusCode": 200,
  "message": "Proposal has been rejected",
  "data": null,
  "timestamp": "2024-03-07T10:30:00"
}

Get Unified Review Queue

curl -X GET https://api.example.com/api/admin/queue \
  -H "Authorization: Bearer YOUR_TOKEN"
GET /api/admin/queue
Authorization: Bearer YOUR_TOKEN
Get a unified review queue containing both new proposals and event modification requests, sorted by submission date (newest first).

Response

statusCode
integer
HTTP status code (200)
message
string
Success message: “Unified review queue retrieved successfully”
data
array
Array of review queue items
data[].id
integer
ID of the proposal or update request
data[].eventID
integer
Event ID (only for MODIFICATION type)
data[].title
string
Title of the proposal or event update
data[].reviewType
string
Type of review: NEW_PROPOSAL or MODIFICATION
data[].submittedAt
string
ISO 8601 timestamp when submitted
{
  "statusCode": 200,
  "message": "Unified review queue retrieved successfully",
  "data": [
    {
      "id": 5,
      "eventID": null,
      "title": "Spring Tech Conference 2024",
      "reviewType": "NEW_PROPOSAL",
      "submittedAt": "2024-03-07T09:00:00"
    },
    {
      "id": 2,
      "eventID": 10,
      "title": "Career Fair 2024",
      "reviewType": "MODIFICATION",
      "submittedAt": "2024-03-06T14:30:00"
    },
    {
      "id": 3,
      "eventID": null,
      "title": "Alumni Networking Night",
      "reviewType": "NEW_PROPOSAL",
      "submittedAt": "2024-03-05T11:15:00"
    }
  ],
  "timestamp": "2024-03-07T10:30:00"
}

User Management

List Users

curl -X GET 'https://api.example.com/api/admin/users?page=0&size=10&role=STUDENT&search=john' \
  -H "Authorization: Bearer YOUR_TOKEN"
GET /api/admin/users?page=0&size=10&role=STUDENT&accountStatus=ACTIVE&search=john
Authorization: Bearer YOUR_TOKEN
Retrieve a paginated list of users with optional filtering.

Query Parameters

page
integer
default:"0"
Page number (zero-based)
size
integer
default:"10"
Number of users per page
role
string
Filter by role: STUDENT, ORGANIZER, EVENT_ORGANIZER, ADMIN
accountStatus
string
Filter by account status: ACTIVE, SUSPENDED, PENDING_VERIFICATION
Search by name or email

Response

{
  "statusCode": 200,
  "message": "User list fetched",
  "data": {
    "content": [
      {
        "userID": 1,
        "email": "[email protected]",
        "firstName": "John",
        "lastName": "Doe",
        "role": "STUDENT",
        "accountStatus": "ACTIVE",
        "createdAt": "2024-01-15T10:00:00",
        "lastLogin": "2024-03-07T08:30:00"
      }
    ],
    "totalElements": 150,
    "totalPages": 15,
    "size": 10,
    "number": 0
  },
  "timestamp": "2024-03-07T10:30:00"
}

Update User Status

curl -X PUT 'https://api.example.com/api/admin/users/5/status?status=SUSPENDED' \
  -H "Authorization: Bearer YOUR_TOKEN"
PUT /api/admin/users/{userID}/status?status=SUSPENDED
Authorization: Bearer YOUR_TOKEN
Update a user’s account status.

Path Parameters

userID
integer
required
ID of the user to update

Query Parameters

status
string
required
New status: ACTIVE, SUSPENDED, PENDING_VERIFICATION

Response

{
  "statusCode": 200,
  "message": "Account status updated to SUSPENDED",
  "data": null,
  "timestamp": "2024-03-07T10:30:00"
}

Update User Role

curl -X PUT 'https://api.example.com/api/admin/users/5/role?role=ORGANIZER' \
  -H "Authorization: Bearer YOUR_TOKEN"
PUT /api/admin/users/{userID}/role?role=ORGANIZER
Authorization: Bearer YOUR_TOKEN
Update a user’s role in the system.

Path Parameters

userID
integer
required
ID of the user to update

Query Parameters

role
string
required
New role: STUDENT, ORGANIZER, EVENT_ORGANIZER, ADMIN

Response

{
  "statusCode": 200,
  "message": "User role updated to ORGANIZER",
  "data": null,
  "timestamp": "2024-03-07T10:30:00"
}

Department-Based Access Control

From AdminController.java:123-129:
private AdminDepartment resolveAdminDepartment(CustomUserDetails userDetails) {
    Administrator admin = extractAdmin(userDetails);
    if (admin.getDepartment() == null) {
        throw new ForbiddenException("Administrator has no department assigned.");
    }
    return admin.getDepartment();
}
Admins only see proposals and requests relevant to their department:
  • YOUTH_UNION - Youth Union proposals at L1
  • STUDENT_ASSOCIATION - Student Association proposals at L1
  • FACULTY - All proposals at L2 (faculty level)
  • RECTOR - All proposals at L3 (rector level)

Build docs developers (and LLMs) love