2018-11-06 19:48:50 +00:00
import Stacker from "../middlewares/stacker" ;
import { GetUserMiddleware } from "../middlewares/user" ;
import { Request , Response } from "express" ;
import Client from "../../models/client" ;
import Logging from "@hibas123/nodelogging" ;
import Permission , { IPermission } from "../../models/permissions" ;
import ClientCode from "../../models/client_code" ;
import moment = require ( "moment" ) ;
import { randomBytes } from "crypto" ;
2020-03-17 15:27:57 +00:00
// import { ObjectID } from "bson";
import Grant , { IGrant } from "../../models/grants" ;
import GetAuthPage from "../../views/authorize" ;
2018-11-06 19:48:50 +00:00
2020-03-17 15:27:57 +00:00
// const AuthRoute = Stacker(GetUserMiddleware(true), async (req: Request, res: Response) => {
// let { response_type, client_id, redirect_uri, scope, state, nored } = req.query;
// const sendError = (type) => {
// if (redirect_uri === "$local")
// redirect_uri = "/code";
// res.redirect(redirect_uri += `?error=${type}&state=${state}`);
// }
// /**
// * error
// REQUIRED. A single ASCII [USASCII] error code from the
// following:
// invalid_request
// The request is missing a required parameter, includes an
// invalid parameter value, includes a parameter more than
// once, or is otherwise malformed.
// unauthorized_client
// The client is not authorized to request an authorization
// code using this method.
// access_denied
// The resource owner or authorization server denied the
// request.
// */
// try {
// if (response_type !== "code") {
// return sendError("unsupported_response_type");
// } else {
// let client = await Client.findOne({ client_id: client_id })
// if (!client) {
// return sendError("unauthorized_client")
// }
// if (redirect_uri && client.redirect_url !== redirect_uri) {
// Logging.log(redirect_uri, client.redirect_url);
// return res.send("Invalid redirect_uri. Please check the integrity of the site requesting and contact the administrator of the page, you want to authorize!");
// }
// let permissions: IPermission[] = [];
// if (scope) {
// let perms = (<string>scope).split(";").filter(e => e !== "read_user").map(p => new ObjectID(p));
// permissions = await Permission.find({ _id: { $in: perms } })
// if (permissions.length != perms.length) {
// return sendError("invalid_scope");
// }
// }
// let code = ClientCode.new({
// user: req.user._id,
// client: client._id,
// permissions: permissions.map(p => p._id),
// validTill: moment().add(30, "minutes").toDate(),
// code: randomBytes(16).toString("hex")
// });
// await ClientCode.save(code);
// let redir = client.redirect_url === "$local" ? "/code" : client.redirect_url;
// let ruri = redir + `?code=${code.code}&state=${state}`;
// if (nored === "true") {
// res.json({
// redirect_uri: ruri
// })
// } else {
// res.redirect(ruri);
// }
// }
// } catch (err) {
// Logging.error(err);
// sendError("server_error")
// }
// })
2020-03-18 10:00:57 +00:00
const GetAuthRoute = ( view = false ) = >
Stacker ( GetUserMiddleware ( false ) , async ( req : Request , res : Response ) = > {
let {
response_type ,
client_id ,
redirect_uri ,
scope ,
state ,
nored
} = req . query ;
const sendError = type = > {
if ( redirect_uri === "$local" ) redirect_uri = "/code" ;
res . redirect ( ( redirect_uri += ` ?error= ${ type } &state= ${ state } ` ) ) ;
} ;
const scopes = scope . split ( ";" ) ;
Logging . debug ( "Scopes:" , scope ) ;
try {
if ( response_type !== "code" ) {
return sendError ( "unsupported_response_type" ) ;
} else {
let client = await Client . findOne ( { client_id : client_id } ) ;
if ( ! client ) {
return sendError ( "unauthorized_client" ) ;
}
2018-11-06 19:48:50 +00:00
2020-03-18 10:00:57 +00:00
if ( redirect_uri && client . redirect_url !== redirect_uri ) {
Logging . log ( redirect_uri , client . redirect_url ) ;
return res . send (
"Invalid redirect_uri. Please check the integrity of the site requesting and contact the administrator of the page, you want to authorize!"
2020-03-17 15:27:57 +00:00
) ;
}
2020-03-18 10:00:57 +00:00
let permissions : IPermission [ ] = [ ] ;
let proms : PromiseLike < void > [ ] = [ ] ;
if ( scopes ) {
for ( let perm of scopes . filter ( e = > e !== "read_user" ) ) {
proms . push (
Permission . findById ( perm ) . then ( p = > {
if ( ! p ) return Promise . reject ( new Error ( ) ) ;
permissions . push ( p ) ;
} )
) ;
}
}
2020-03-17 15:27:57 +00:00
2020-03-18 10:00:57 +00:00
let err = undefined ;
await Promise . all ( proms ) . catch ( e = > {
err = e ;
} ) ;
2020-03-17 15:27:57 +00:00
2020-03-18 10:00:57 +00:00
if ( err ) {
Logging . error ( err ) ;
return sendError ( "invalid_scope" ) ;
}
2020-03-17 15:27:57 +00:00
2020-03-18 10:00:57 +00:00
let grant : IGrant | undefined = await Grant . findOne ( {
client : client._id ,
user : req.user._id
} ) ;
2020-03-17 15:27:57 +00:00
2020-03-18 10:00:57 +00:00
Logging . debug ( "Grant" , grant , permissions ) ;
2020-03-17 15:27:57 +00:00
2020-03-18 10:00:57 +00:00
let missing_permissions : IPermission [ ] = [ ] ;
2020-03-17 15:27:57 +00:00
2020-03-18 10:00:57 +00:00
if ( grant ) {
missing_permissions = grant . permissions
. map ( perm = > permissions . find ( p = > p . _id . equals ( perm ) ) )
. filter ( e = > ! ! e ) ;
} else {
missing_permissions = permissions ;
}
2018-11-06 19:48:50 +00:00
2020-03-18 10:00:57 +00:00
let client_granted_perm = missing_permissions . filter (
e = > e . grant_type == "client"
) ;
if ( client_granted_perm . length > 0 ) {
return sendError ( "no_permission" ) ;
}
2020-03-17 15:27:57 +00:00
2020-03-18 10:00:57 +00:00
if ( ! grant && missing_permissions . length > 0 ) {
await new Promise < void > ( ( yes , no ) = >
GetUserMiddleware ( false , true ) ( req , res , ( err? : Error ) = >
err ? no ( err ) : yes ( )
)
) ; // Maybe unresolved when redirect is happening
if ( view ) {
res . send (
GetAuthPage (
req . __ ,
client . name ,
permissions . map ( perm = > {
return {
name : perm.name ,
description : perm.description ,
logo : client.logo
} ;
} )
)
) ;
return ;
2020-03-17 15:27:57 +00:00
} else {
2020-03-18 10:00:57 +00:00
if ( ( req . body . allow = "true" ) ) {
if ( ! grant )
grant = Grant . new ( {
client : client._id ,
user : req.user._id ,
permissions : [ ]
} ) ;
grant . permissions . push (
. . . missing_permissions . map ( e = > e . _id )
) ;
await Grant . save ( grant ) ;
} else {
return sendError ( "access_denied" ) ;
}
2020-03-17 15:27:57 +00:00
}
2018-11-06 19:48:50 +00:00
}
2020-03-18 10:00:57 +00:00
let code = ClientCode . new ( {
user : req.user._id ,
client : client._id ,
permissions : permissions.map ( p = > p . _id ) ,
validTill : moment ( )
. add ( 30 , "minutes" )
. toDate ( ) ,
code : randomBytes ( 16 ) . toString ( "hex" )
} ) ;
await ClientCode . save ( code ) ;
let redir =
client . redirect_url === "$local" ? "/code" : client . redirect_url ;
let ruri = redir + ` ?code= ${ code . code } &state= ${ state } ` ;
if ( nored === "true" ) {
res . json ( {
redirect_uri : ruri
} ) ;
} else {
res . redirect ( ruri ) ;
}
2018-11-06 19:48:50 +00:00
}
2020-03-18 10:00:57 +00:00
} catch ( err ) {
Logging . error ( err ) ;
sendError ( "server_error" ) ;
2018-11-06 19:48:50 +00:00
}
2020-03-18 10:00:57 +00:00
} ) ;
2020-03-17 15:27:57 +00:00
export default GetAuthRoute ;