Skip to content

HYU-ICEWALL/CTF-Backend

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

CTF-Backend README

Schema

Account

const accountSchema = new Schema({
  id: { type: String, unique: true, required: true},
  password: { type: String, required: true},
  salt: { type: String, required: true},
  email: { type: String, unique: true, required: true},
  verified: { type: Boolean, required: true, default: false },
  authority: { type: Number, required: true, default: 0 },
  test: { type: Boolean, required: true, default: false },
});

module.exports = accountSchema;

Contest

const contestSchema = new Schema({
  name: { type: String, unique: true, required: true },
  description: { type: String },
  problems: { type: [String], required: true},  // problem name
  begin_at: { type: String, required: true },
  end_at: { type: String, required: true },
  participants: { type: [String], required: true }, // account id
  state: { type: String, required: true, default: '0' }, // 0 : upcoming, 1 : in progress, 2 : ended, 3 : suspended
  test: { type: Boolean, required: true, default: false },
});

Problem

const problemSchema = new Schema({
  name: { type: String, unique: true, required: true },
  description: { type: String },
  file: { type: String },
  flag: { type: String },
  url: {type: String},
  port: {type: String},
  score: { type: String, required: true },
  domain: { type: String, required: true }, // pwn, web, forensic, reverse, misc
  contest: { type: String }, // contest name
  test: { type: Boolean, required: true, default: false },
});

Profile

const profileSchema = new Schema({
  id: { type: String, unique: true, required: true },
  email: { type: String, unique: true, required: true},
  name: { type: String, required: true },
  organization: { type: String, required: true },
  department: { type: String, required: true },
  solved: { type: [Schema.ObjectId], default: [] },
  test: { type: Boolean, required: true, default: false },
});

/*
solved : [
    // problem names
]
*/

Scoreboard

const scoreboardSchema = new Schema({
  contest: { type: String, unique: true, required: true }, // contest name
  begin_at: { type: String, required: true },
  end_at: { type: String, required: true },
  sumbissions: { type: [Object], default: [] },
  test: { type: Boolean, required: true, default: false }
});

/*
submission : [
  {
    problem : problem name,
    score : problem score,
    account : account id,
    time : time (YYYY-MM-DD HH:MM:SS)
  }
]
*/

API Endpoints

Account

POST /api/account

  • 계정 생성 ν›„ ν”„λ‘œν•„ 생성을 ν•œλ‹€.

  • μ„Έμ…˜μ΄ 있으면 μ‹€νŒ¨ν•œλ‹€.

  • ID/Email 쀑볡 확인을 ν•œλ‹€.

  • Request Body

{
    "id": "exampleId",
    "password": "examplePassword",
    "email": "exampleEmail",
    "name": "exampleName",
    "organization": "exampleOrganization",
    "department": "exampleDepartment"
}
  • Response
{
    "code": 0,
    "data": {}
}

POST /api/account/login

  • 계정 λ‘œκ·ΈμΈμ„ ν•œλ‹€.

  • μ„Έμ…˜μ„ μƒμ„±ν•˜κ³  쿠킀에 μ €μž₯ν•œλ‹€.

  • μ„Έμ…˜μ—λŠ” ID와 Token이 μ €μž₯λœλ‹€.

  • Request Body

{
    "id": "exampleId",
    "password": "examplePassword"
}
  • Response
{
    "code": 0,
    "data": {}
}

GET /api/account/auth

  • μœ νš¨ν•œ μ„Έμ…˜μΈμ§€ ν™•μΈν•œλ‹€.

  • Response

{
    "code": 0,
    "data": {}
}

GET /api/account/logout

  • 계정 λ‘œκ·Έμ•„μ›ƒμ„ ν•œλ‹€.

  • μ„Έμ…˜μ„ μ œκ±°ν•˜κ³  μΏ ν‚€λ₯Ό μ œκ±°ν•œλ‹€.

  • Response

{
    "code": 0,
    "data": {}
}

GET /api/account/refresh

  • 계정 토큰을 κ°±μ‹ ν•œλ‹€.

  • Response

{
    "code": 0,
    "data": {}
}

PUT /api/account

  • μœ νš¨ν•œ μ„Έμ…˜μΈμ§€ ν™•μΈν•œλ‹€.

  • 계정 λΉ„λ°€λ²ˆν˜Έλ₯Ό λ³€κ²½ν•œλ‹€.

  • Request Body

{
    "id": "exampleId",
    "password": "examplePassword",
    "newPassword": "exampleNewPassword"
}
  • Response
{
    "code": 0,
    "data": {}
}

DELETE /api/account

  • μœ νš¨ν•œ μ„Έμ…˜μΈμ§€ ν™•μΈν•œλ‹€.

  • 계정과 ν”„λ‘œν•„μ„ μ‚­μ œν•œλ‹€.

  • Request Body

{
    "id": "exampleId",
    "password": "examplePassword"
}
  • Response
{
    "code": 0,
    "data": {}
}

Contest

GET /api/contest/recent

  • μ΅œκ·Όμ— μ§„ν–‰λœ contestλ₯Ό count만큼 κ°€μ Έμ˜¨λ‹€.

  • Parameters

{
    "count": 5
}
  • Response
{
    "code": 0,
    "data": {
        "recent" : [...],
        "upcoming" : [...],
        "inprogress" : [...],
        "ended" : [...]
    }
}

GET /api/contest

  • contest의 정보λ₯Ό κ°€μ Έμ˜¨λ‹€.

  • name이 있으면 ν•΄λ‹Ή 이름을 κ°€μ§„ contestλ₯Ό κ°€μ Έμ˜¨λ‹€.

  • name이 있고 μ„Έμ…˜μ΄ μœ νš¨ν•˜λ©° contest의 participants에 μ†ν•˜λ©΄ problemsλ‚˜ scoreboardsλ₯Ό κ°€μ Έμ˜¬ 수 μžˆλ‹€.

  • Parameters

{
    "name": "exampleContest",
    "problems": true,
    "scoreboards": true
}
  • Response
// no params
{
    "code": 0,
    "data": [
        // contests
    ]
}

// only name
{
    "code": 0,
    "data": {
        // contest info
    }
}

// problems or scoreboards
{
    "code": 0,
    "data": {
        // contest info
        "problems": [
            // problems
        ],
        "scoreboard": {
            // scoreboard
        }
    }
}

GET /api/contest/scoreboard

  • contest의 scoreboardλ₯Ό κ°€μ Έμ˜¨λ‹€.

  • μ„Έμ…˜μ΄ μœ νš¨ν•˜λ©° contest의 participants에 μ†ν•˜λ©΄ κ°€μ Έμ˜¬ 수 μžˆλ‹€.

  • Parameters

{
    "name": "exampleContest"
}
  • Response
{
    "code": 0,
    "data": { 
        "contest": "exampleContest",
        "begin_at": "YYYY-MM-DD HH:MM:SS",
        "end_at": "YYYY-MM-DD HH:MM:SS",
        "submissions": [
            {
                "accountId" : {
                    "total": 0,
                    "timestamp": [
                        {
                            "problem": "exampleProblem",
                            "score": 0,
                            "type": true,
                            "time": "YYYY-MM-DD HH:MM:SS"
                        },
                        ...
                    ]
                },
                ...
            }
        ]
    }
}

Problem

GET /api/problem

  • 문제 λͺ©λ‘μ„ κ°€μ Έμ˜¨λ‹€.

  • Parameters

{
    "name": "exampleName",
    "category": "exampleCategory",
    "contest": "exampleContest"
}
  • Response
{
    "code": 0,
    "data": [
        // problems
    ]
}

POST /api/problem/submit

  • μ„Έμ…˜μ΄ μœ νš¨ν•œμ§€ ν™•μΈν•œλ‹€

  • flagλ₯Ό ν™•μΈν•œλ‹€.

  • profile의 solved에 μΆ”κ°€ν•œλ‹€.

  • contest의 μ‹œκ°„μ΄ begin_atκ³Ό end_at 사이인지 ν™•μΈν•œλ‹€.

  • contest의 participants에 μ†ν•˜λŠ”μ§€ ν™•μΈν•œλ‹€.

  • contest의 scoreboard에 μΆ”κ°€ν•œλ‹€.

  • Request Body

{
    "name": "exampleProblem",
    "flag": "exampleFlag"
}
  • Response (Correct)
// solved
{
    "code": 0,
    "data": {
        "result": true
    }
}
// not solved
{
    "code": 0,
    "data": {
        "result": false
    }
}

Profile

GET /api/profile

Get the profile information of the account.

  • Request body
Field Type Description
id string Account id.
  • Response
{
    "code": 0,
    "data": {
        "id": "exampleId",
        "email": "exampleEmail",
        "name": "exampleName",
        "organization": "exampleOrganization",
        "department": "exampleDepartment"
    }
}

GET /api/profile

  • ν”„λ‘œν•„ 정보λ₯Ό κ°€μ Έμ˜¨λ‹€.

  • Parameters

{
    "id": "exampleId",
    "name": "exampleName",
    "organization": "exampleOrganization",
    "department": "exampleDepartment"
}
  • Response
{
    "code": 0,
    "data": [
        // profiles
    ]
}

PUT /api/profile

  • μœ νš¨ν•œ μ„Έμ…˜μΈμ§€ ν™•μΈν•œλ‹€.

  • ν”„λ‘œν•„μ„ μˆ˜μ •ν•œλ‹€.

  • Request body

{
    "name": "exampleName",
    "organization": "exampleOrganization",
    "department": "exampleDepartment"
}
  • Response
{
    "code": 0,
    "data": {}
}

GET /api/profile/solved

  • ν”„λ‘œν•„μ˜ solvedλ₯Ό κ°€μ Έμ˜¨λ‹€.

  • Parameters

{
    "id": "exampleId"
}
  • Response
{
    "code": 0,
    "data": [
        // solved
    ]
}

Error Codes

  • 0 : Success

Database

Mongoose (mongodb.js)

  • 1000 : MongoDB Insert Error
  • 1010 : MongoDB Find Error
  • 1020 : MongoDB Update Error
  • 1030 : MongoDB Delete Error

Manager

AccountManager (account.js)

  • 2000 : Failed to create account
  • 2010 : Failed to find account
  • 2020 : Failed to find account by id
  • 2030 : Failed to find account by password
    • 2031 : Account not found
    • 2032 : Password incorrect
  • 2040 : Failed to delete account
  • 2050 : Failed to change password
    • 2051 : Account not found
    • 2052 : Password incorrect

ContestManager (contest.js)

  • 2100 : Failed to create contest
  • 2110 : Failed to find contest
  • 2120 : Failed to delete contest
  • 2130 : Failed to update contest
  • 2140 : Failed to update problems in contest
  • 2150 : Failed to update participants in contest

ProblemManager (problem.js)

  • 2200 : Failed to create problem
  • 2210 : Failed to find problem
  • 2220 : Failed to delete problem
  • 2230 : Failed to update problem

ProfileManager (profile.js)

  • 2300 : Failed to create profile
  • 2310 : Failed to find profile
  • 2320 : Failed to delete profile
  • 2330 : Failed to update profile
  • 2340 : Failed to update solved in profile

ScoreboardManager (scoreboard.js)

  • 2400 : Failed to create scoreboard
  • 2410 : Failed to find scoreboard
  • 2420 : Failed to delete scoreboard
  • 2430 : Failed to update scoreboard
  • 2440 : Failed to update submissions in scoreboard
  • 2450 : Failed to find processed scoreboard
    • 2451 : Scoreboard not found
  • 2460 : Failed to process submissions in scoreboard

SessionManager (session.js)

  • 2500 : Session check failed
  • 2501 : Session not found
  • 2502 : Session data not found

Router

/api/account

  • POST /api/account

    • 100 : Account registration failed
    • 101 : Session already exists
    • 102 : Invalid parameters
    • 103 : ID already exists
    • 104 : Email already exists
  • POST /api/account/login

    • 110 : Account login failed
    • 111 : Invalid parameters
    • 112 : Session save failed
  • GET /api/account/auth

    • 120 : Session check failed
  • GET /api/account/logout

    • 130 : Account logout failed
    • 131 : Session destroy failed
  • GET /api/account/refresh

    • 140 : Account refresh failed
    • 141 : Session refresh failed
  • DELETE /api/account

    • 150 : Account deletion failed
    • 151 : Invalid parameters
    • 152 : Not allowed
    • 153 : Session destroy failed
  • PUT /api/account

    • 160 : Account password change failed
    • 161 : Invalid parameters
    • 162 : Password incorrect
    • 163 : Session destroy failed

/api/contest

  • GET /api/contest/recent

    • 200 : Contest find failed
  • GET /api/contest

    • 210 : Contest find failed
    • 211 : Contest not found
    • 212 : Not in contest participants
  • GET /api/contest/scoreboard

    • 220 : Contest find failed
    • 221 : Invalid parameters
    • 222 : Contest not found
    • 223 : Not in contest participants

/api/problem

  • GET /api/problem

    • 300 : Problem find failed
  • POST /api/problem/submit

    • 310 : Problem flag check failed
    • 311 : Invalid parameters
    • 312 : Problem not found
    • 313 : Contest not found

/api/profile

  • GET /api/profile

    • 400 : Profile find failed
  • PUT /api/profile

    • 410 : Profile update failed
    • 411 : Invalid parameters
  • GET /api/profile/solved

    • 420 : Profile solved find failed
    • 421 : Invalid parameters
    • 422 : Profile not found

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Contributors 3

  •  
  •  
  •