Adding Basic API Documentation

This commit is contained in:
Fabian Stamm
2019-03-14 18:10:39 -04:00
parent e09c6df9f6
commit 18ea5de8aa
21 changed files with 828 additions and 97 deletions

View File

@ -5,10 +5,91 @@ import TwoFactorRoute from "./twofactor";
import { GetToken, DeleteToken } from "./token";
const UserRoute: Router = Router();
/**
* @api {post} /user/register
* @apiName UserRegister
*
* @apiGroup user
* @apiPermission none
*
* @apiParam {String} mail EMail linked to this Account
* @apiParam {String} username The new Username
* @apiParam {String} password Password hashed and salted like specification
* @apiParam {String} salt The Salt used for password hashing
* @apiParam {String} regcode The regcode, that should be used
* @apiParam {String} gender Gender can be: "male", "female", "other", "none"
* @apiParam {String} name The real name of the User
*
* @apiSuccess {Boolean} success
*
* @apiErrorExample {Object} Error-Response:
{
error: [
{
message: "Some Error",
field: "username"
}
],
status: 400
}
*/
UserRoute.post("/register", Register);
/**
* @api {post} /user/login?type=:type
* @apiName UserLogin
*
* @apiParam {String} type Type could be either "username" or "password"
*
* @apiGroup user
* @apiPermission none
*
* @apiParam {String} username Username (either username or uid required)
* @apiParam {String} uid (either username or uid required)
* @apiParam {String} password Password hashed and salted like specification (only on type password)
*
* @apiSuccess {String} uid On type = "username"
* @apiSuccess {String} salt On type = "username"
*
* @apiSuccess {String} login On type = "password". Login Token
* @apiSuccess {String} special On type = "password". Special Token
* @apiSuccess {Object[]} tfa Will be set when TwoFactorAuthentication is required
* @apiSuccess {String} tfa.id The ID of the TFA Method
* @apiSuccess {String} tfa.name The name of the TFA Method
* @apiSuccess {String} tfa.type The type of the TFA Method
*/
UserRoute.post("/login", Login)
UserRoute.use("/twofactor", TwoFactorRoute);
/**
* @api {get} /user/token
* @apiName UserGetToken
*
* @apiGroup user
* @apiPermission user
*
* @apiSuccess {Object[]} token
* @apiSuccess {String} token.id The Token ID
* @apiSuccess {String} token.special Identifies Special Token
* @apiSuccess {String} token.ip IP the token was optained from
* @apiSuccess {String} token.browser The Browser the token was optained from (User Agent)
* @apiSuccess {Boolean} token.isthis Shows if it is token used by this session
*/
UserRoute.get("/token", GetToken);
UserRoute.delete("/token", DeleteToken);
/**
* @api {delete} /user/token/:id
* @apiParam {String} id The id of the token to be deleted
*
* @apiName UserDeleteToken
*
* @apiParam {String} type Type could be either "username" or "password"
*
* @apiGroup user
* @apiPermission user
*
* @apiSuccess {Boolean} success
*/
UserRoute.delete("/token/:id", DeleteToken);
export default UserRoute;

View File

@ -3,9 +3,7 @@ import User, { IUser } from "../../models/user";
import { randomBytes } from "crypto";
import moment = require("moment");
import LoginToken from "../../models/login_token";
import RequestError, { HttpStatusCode } from "../../helper/request_error";
import promiseMiddleware from "../../helper/promiseMiddleware";
import * as speakeasy from "speakeasy";
import TwoFactor from "../../models/twofactor";
const Login = promiseMiddleware(async (req: Request, res: Response) => {
@ -19,49 +17,49 @@ const Login = promiseMiddleware(async (req: Request, res: Response) => {
res.json({ salt: user.salt, uid: user.uid });
}
return;
}
} else if (type === "password") {
const sendToken = async (user: IUser, tfa?: any[]) => {
let ip = req.headers['x-forwarded-for'] || req.connection.remoteAddress
let client = {
ip: Array.isArray(ip) ? ip[0] : ip,
browser: req.headers["user-agent"]
}
const sendToken = async (user: IUser, tfa?: any[]) => {
let ip = req.headers['x-forwarded-for'] || req.connection.remoteAddress
let client = {
ip: Array.isArray(ip) ? ip[0] : ip,
browser: req.headers["user-agent"]
let token_str = randomBytes(16).toString("hex");
let tfa_exp = moment().add(5, "minutes").toDate()
let token_exp = moment().add(6, "months").toDate()
let token = LoginToken.new({
token: token_str,
valid: true,
validTill: tfa ? tfa_exp : token_exp,
user: user._id,
validated: tfa ? false : true,
...client
});
await LoginToken.save(token);
let special_str = randomBytes(24).toString("hex");
let special_exp = moment().add(30, "minutes").toDate()
let special = LoginToken.new({
token: special_str,
valid: true,
validTill: tfa ? tfa_exp : special_exp,
special: true,
user: user._id,
validated: tfa ? false : true,
...client
});
await LoginToken.save(special);
res.json({
login: { token: token_str, expires: token.validTill.toUTCString() },
special: { token: special_str, expires: special.validTill.toUTCString() },
tfa
});
}
let token_str = randomBytes(16).toString("hex");
let tfa_exp = moment().add(5, "minutes").toDate()
let token_exp = moment().add(6, "months").toDate()
let token = LoginToken.new({
token: token_str,
valid: true,
validTill: tfa ? tfa_exp : token_exp,
user: user._id,
validated: tfa ? false : true,
...client
});
await LoginToken.save(token);
let special_str = randomBytes(24).toString("hex");
let special_exp = moment().add(30, "minutes").toDate()
let special = LoginToken.new({
token: special_str,
valid: true,
validTill: tfa ? tfa_exp : special_exp,
special: true,
user: user._id,
validated: tfa ? false : true,
...client
});
await LoginToken.save(special);
res.json({
login: { token: token_str, expires: token.validTill.toUTCString() },
special: { token: special_str, expires: special.validTill.toUTCString() },
tfa
});
}
if (type === "password") {
let { username, password, uid } = req.body;
let user = await User.findOne(username ? { username: username.toLowerCase() } : { uid: uid })

View File

@ -6,7 +6,6 @@ import TwoFactor from "../../../models/twofactor";
import * as moment from "moment"
import RequestError, { HttpStatusCode } from "../../../helper/request_error";
const TwoFactorRouter = Router();
TwoFactorRouter.get("/", Stacker(GetUserMiddleware(true, true), async (req, res) => {