Skip to content

Challenge Endpoints

tkaixiang edited this page Sep 16, 2021 · 7 revisions

GET /v1/challenge/list

Show all available challenges, sorted by category
Authenticated

Input

No input required

Output

// Type 0 or 1 users
{
	"success": true,
	"data": [
		{
			"_id": "CATEGORY_NAME",
			"challenges": [
				{
                                        "_id": "CHALLENGE_ID",
					"name": "CHALLENGE_NAME",
					"points": "int",
					"solved": "bool",
					"tags": [
						"CHALLENGE_TAGS"
					],
                    "requires": "required challenge to unlock this challenge"
				}
			]
		}
	]
}
// Type 2 users
{
	"success": true,
	"data": [
		{
			"_id": "CATEGORY_NAME",
			"challenges": [
				{
                                        "_id": "CHALLENGE_ID",
					"name": "CHALLENGE_NAME",
					"points": "int",
					"solved": "bool",
					"tags": [
						"CHALLENGE_TAGS"
					],
                    "requires": "required challenge to unlock this challenge",
                    "visibility": true
				}
			]
		}
	]
}
  • For admin users (type 2 users), hidden challenges are also returned along with a visibility property for each challenge

GET /v1/challenge/list/:category

Show all available challenges in a category
Authenticated

Input

GET /v1/challenge/list/CATEGORY_NAME
{
	"success": true,
	"challenges": [
		{
                        "_id": "CHALLENGE_ID",
			"name": "CHALLENGE_NAME",
			"points": "int",
			"solved": "bool",
            "tags": [],
            "requires": "required_challenge_to_solve"
		}
	]
}

Remarks

  • Only shows challenges with visibility: true

Errors

Error Definition
not-found No challenges were found (matching the criteria if specified)

GET /v1/challenge/list_categories

Show all available categories
Authenticated

Input

No input required

Output

{
	"success": true,
	"categories": [
		"NEW_CATEGORIES",
		"OTHER_NEW_CATEGORIES"
	]
}

Remarks

  • Only shows challenges with visibility: true

Errors

No special errors

GET /v1/challenge/list__all_categories

Show all categories including hidden ones
Authenticated // Permissions: 2

Input

No input required

Output

{
	"success": true,
	"categories": [
		"NEW_CATEGORIES",
		"OTHER_NEW_CATEGORIES"
	]
}

Remarks

  • Only shows challenges with visibility: true

Errors

No special errors

GET /v1/challenge/list_all

Show all challenges
Authenticated // Permissions: 2

Input

No input required

Output

{
	"success": true,
	"challenges": [
		{
                        "_id": "CHALLENGE_ID",
			"name": "CHALLENGE_NAME",
			"category": "CHALLENGE_CATEGORY",
			"points": "int",
			"solves": "array",
			"visibility": true,
            "requires": "chall"
		},
		{
                        "_id": "CHALLENGE_ID",
			"name": "CHALLENGE_NAME",
			"category": "CHALLENGE_CATEGORY",
			"points": "int",
			"solves": "array",
			"visibility": true,
            "requires": "chall"
		}
	]
}

Remarks

  • Shows all challenges, including those with visibility: false

Errors

No special errors

GET /v1/challenge/show/:chall

Get the details of a challenge
Authenticated

Input

GET: /v1/challenge/show/CHALLENGE_ID

Output

{
	"success": true,
	"challenge": {
		"name": "CHALLENGE_NAME",
		"category": "CHALLENGE_CATEGORY",
		"description": "CHALLENGE_DESCRIPTION (HTML)",
		"points": "int",
		"author": "CHALLENGE_AUTHOR",
		"created": "CREATION_TIMESTAMP",
		"solves": [
			"USERNAME_OF_SOLVER"
		],
		"max_attempts": "int (0 means unlimited)",
		"tags": [
			"CHALLENGE_TAG"
		],
		"hints": [
			{
				"bought": true,
				"hint": "HINT_CONTENTS" // hint 1
			},
			{
				"bought": false,
				"cost": "int" // hint 2
			}
		]
	}
}

Remarks

  • Only shows challenges with visibility: true (unless the user is a type 2 user)
  • The endpoint will not return any info if the user has yet to solve the required challenge
  • Hints: if the hint has been bought, the object will provide the hint directly. If not, the cost key will be an integer of the number of points needed

Errors

Error Definition
notfound No challenge found
required-challenge-not-found The required challenge was not found. This likely means that the challenge that should be solved to unlock this challenge has been deleted/no longer exists
required-challenge-not-completed The user has yet to completed the required challenge to unlock this challenge

GET /v1/challenge/show/:chall/detailed

Get all the details of a challenge
Authenticated // Permissions: 2

Input

GET: /v1/challenge/show/CHALLENGE_ID/detailed

Output

{
	"success": true,
	"challenge": {
                "_id": "CHALLENGE_ID",
		"name": "CHALLENGE_NAME",
		"category": "CHALLENGE_CATEGORY",
		"description": "CHALLENGE_DESCRIPTION (HTML)",
		"points": "int",
		"author": "CHALLENGE_AUTHOR",
		"created": "CREATION_TIMESTAMP",
		"solves": [
			"USERNAME_OF_SOLVER"
		],
		"max_attempts": "int (0 means unlimited)",
		"used_attempts": "int",
		"tags": [
			"CHALLENGE_TAG"
		],
		"visibility": "bool",
		"flags": [
			"FLAG"
		],
		"hints": [
			{
				"hint": "HINT_CONTENTS",
				"cost": "int",
				"purchased": [
					"USERNAME"
				]
			},
			{
				"hint": "HINT_CONTENTS",
				"cost": "int",
				"purchased": [
					"USERNAME"
				]
			}
		],
                "dynamic": true // whether the challenge uses dynamic scoring
                "initial": 100 // initial score for dynamic challs
                "minSolves": 10 // number of solves for the challenge till it decays till the minimum score below
                "minimum": 50 // minimum score to decay to for dynamic challs                
	}
}

Errors

Error Definition
permissions The logged-in user does not have sufficient permissions to create a new challenge

POST /v1/challenge/hint

Buy a hint for a challenge
Authenticated

Input

{
	"id": "int",
	"chall": "CHALLENGE_ID"
}

Output

{
	"success": true,
	"hint": "HINT_CONTENT"
}

Remarks

  • The id field refers to the index of the hint (e.g. the 1st hint would be ID = 0)
  • The server will return the hint if it has already been bought, but will not deduct any points
  • Buying a hint triggers a websocket message broadcast to all live scoreboard clients

Errors

Error Definition
not-found The CHALLENGE_ID specified was invalid
out-of-range The id field is too large or too small (minimum is 0)
required-challenge-not-found The required challenge was not found. This likely means that the challenge that should be solved to unlock this challenge has been deleted/no longer exists
required-challenge-not-completed The user has yet to completed the required challenge to unlock this challenge

POST /v1/challenge/submit

Submit a flag for a challenge
Authenticated

Input

{
	"flag": "FLAG_TO_BE_SUBMITTED",
	"chall": "CHALLENGE_ID"
}

Output

{
	"success": true,
	"data": "correct/ding dong your flag is wrong"
}

Remarks

  • On a correct solve, this endpoint broadcasts a websocket msg to all connected clients to update the scoreboard

Errors

Error Definition
not-found The CHALLENGE_ID specified was invalid
submitted This challenge was already solved
exceeded The user has already exceeded the maximum number of attempts allowed
submission-disabled Challenge submission has been disabled by the admin and no new submissions are allowed
required-challenge-not-found The required challenge was not found. This likely means that the challenge that should be solved to unlock this challenge has been deleted/no longer exists
required-challenge-not-completed The user has yet to completed the required challenge to unlock this challenge

POST /v1/challenge/new

Create a new challenge
Authenticated // Permissions: 1

Input

{
	"name": "CHALLENGE_NAME",
	"category": "CATEGORY",
	"description": "CHALLENGE_DESCRIPTION (HTML)",
	"points": "POINTS (int)",
	"flags": [
		"FLAG"
	],
	"tags": [
		"TAG"
	],
	"hints": [
		{
			"hint": "HINT",
			"cost": "HINT_COST (int)"
		}
	],
	"max_attempts": "int",
	"visibility": "bool",
        "writeup": "writeup_link",
        "writeupComplete": true, //whether to show writeup only after challenge is solved
        "requires": "required challenge to unlock this challenge",
        "dynamic": true // whether the challenge uses dynamic scoring
        "initial": 100 // initial score for dynamic challs
        "minSolves": 10 // number of solves for the challenge till it decays till the minimum score below
        "minimum": 50 // minimum score to decay to for dynamic challs
}

Output

{
	"success": true
}

Remarks

  • File uploads have not been implemented
  • Validation: name, category, description, points, visibility, dynamic and at least one flags are required fields
  • Validation must be done on the client side as the server does not produce meaning output (integers are passed through parseInt)

Errors

Error Definition
permissions The logged-in user does not have sufficient permissions to create a new challenge
exists Another challenge already exists with this name
validation The input was malformed

POST /v1/challenge/edit

Edit a challenge
Authenticated // Permissions: 2

Input

{
        "id": "CHALLENGE_ID",
	"chall": "CHALLENGE_NAME",
	"name": "NEW_CHALLENGE_NAME",
	"category": "NEW_CATEGORIES",
	"description": "NEW_CHALLENGE_DESCRIPTION (HTML)",
	"points": "NEW_POINTS (int)",
	"flags": [
		"NEW_FLAG"
	],
	"tags": [
		"NEW_TAG"
	],
	"hints": [{
		"hint": "NEW_HINT",
		"cost": "NEW_HINT_COST (int)",
		"purchased": [
			"USERNAME (required, even if empty)"
		]
	}],
	"max_attempts": "int",
	"visibility": "bool",
        "writeup": "writeup_link",
        "writeupComplete": true, //See /new for info on this property,
        "requires": "required_challenge",
        "dynamic": true // whether the challenge uses dynamic scoring
        "initial": 100 // initial score for dynamic challs
        "minSolves": 10 // number of solves for the challenge till it decays till the minimum score below
        "minimum": 50 // minimum score to decay to for dynamic challs
}

Output

{
	"success": true
}

Remarks

  • All fields other than chall are optional.
  • All entries must be filled with the original data as well (Entries which are marked as '', an empty string, will be treated that the user wants to delete that entry)
    • e.g. to add a new flag, input ["old flag", "new flag"]
    • Deletes hint purchases without compensation if this is not done (but can also be used to award hints to users)
  • File uploads have not been implemented
  • Validation must be done on the client side as the server does not produce meaning output (integers are passed not through parseInt - perform on client side)

Errors

Error Definition
notfound The CHALLENGE_ID specified was not found
permissions The logged-in user does not have sufficient permissions to edit a challenge

POST /v1/challenge/edit/visibility

Edit the visibility of a list of challenges
Authenticated // Permissions: 2

Input

{
	"challenges": ["CHALLENGE_ID1", "CHALLENE_ID2"...]
}

Output

{
	"success": true
}

Errors

Error Definition
notfound The CHALLENGE_ID specified was invalid
permissions The logged-in user does not have sufficient permissions to edit a challenge
validation Check that the input is an array

POST /v1/challenge/edit/category

Edit a category's metadata
Authenticated // Permissions: 2

Input

{
	"category": "CATEGORY_NAME",
	"new_name": "NEW_CATEGORY_NAME (optional)",
	"visibility": "bool (optional)"
}

Output

{
	"success": true
}

Errors

Error Definition
notfound The CATEGORY_NAME specified was invalid
permissions The logged-in user does not have sufficient permissions to edit a challenge

POST /v1/challenge/delete

Delete a list of challenges
Authenticated // Permissions: 2

Input

{
	"chall": ["CHALLENGE_ID", "CHALLENGE_ID2"...]
}

Output

{
	"success": true
}

Remarks

  • Deletes transaction records for the challenges as well. Hence, any points earned from this challenge, and any hints taken from this challenge are refunded.

Errors

Error Definition
notfound One of the challenges was not found
permissions The logged-in user does not have sufficient permissions to edit a challenge

GET /v1/challenge/disableStates

Returns the states of the admin panel challenges settings

Authenticated // Permissions: 2

Input

None

Output

{
	"success": ,
    "states": []
}

Errors

Error Definition
permissions The logged-in user does not have sufficient permissions to edit a challenge
Clone this wiki locally