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" ;
2020-03-25 22:37:56 +00:00
import { ObjectID } from "mongodb" ;
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 ,
2020-08-07 14:16:39 +00:00
nored ,
2020-03-18 10:00:57 +00:00
} = req . query ;
2020-08-07 14:16:39 +00:00
const sendError = ( type ) = > {
2020-03-18 10:00:57 +00:00
if ( redirect_uri === "$local" ) redirect_uri = "/code" ;
2020-08-07 14:16:39 +00:00
res . redirect (
( redirect_uri += ` ?error= ${ type } ${ state ? "&state=" + state : "" } ` )
) ;
2020-03-18 10:00:57 +00:00
} ;
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 ) {
2020-08-07 14:16:39 +00:00
for ( let perm of scopes . filter ( ( e ) = > e !== "read_user" ) ) {
2020-03-25 22:37:56 +00:00
let oid = undefined ;
try {
oid = new ObjectID ( perm ) ;
} catch ( err ) {
Logging . error ( err ) ;
continue ;
}
2020-03-18 10:00:57 +00:00
proms . push (
2020-08-07 14:16:39 +00:00
Permission . findById ( oid ) . then ( ( p ) = > {
2020-03-18 10:00:57 +00:00
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 ;
2020-08-07 14:16:39 +00:00
await Promise . all ( proms ) . catch ( ( e ) = > {
2020-03-18 10:00:57 +00:00
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 ,
2020-08-07 14:16:39 +00:00
user : req.user._id ,
2020-03-18 10:00:57 +00:00
} ) ;
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
2020-08-07 14:16:39 +00:00
. map ( ( perm ) = > permissions . find ( ( p ) = > p . _id . equals ( perm ) ) )
. filter ( ( e ) = > ! ! e ) ;
2020-03-18 10:00:57 +00:00
} 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 (
2020-08-07 14:16:39 +00:00
( e ) = > e . grant_type == "client"
2020-03-18 10:00:57 +00:00
) ;
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 ,
2020-08-07 14:16:39 +00:00
permissions . map ( ( perm ) = > {
2020-03-18 10:00:57 +00:00
return {
name : perm.name ,
description : perm.description ,
2020-08-07 14:16:39 +00:00
logo : client.logo ,
2020-03-18 10:00:57 +00:00
} ;
} )
)
) ;
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 ,
2020-08-07 14:16:39 +00:00
permissions : [ ] ,
2020-03-18 10:00:57 +00:00
} ) ;
grant . permissions . push (
2020-08-07 14:16:39 +00:00
. . . missing_permissions . map ( ( e ) = > e . _id )
2020-03-18 10:00:57 +00:00
) ;
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 ,
2020-08-07 14:16:39 +00:00
permissions : permissions.map ( ( p ) = > p . _id ) ,
validTill : moment ( ) . add ( 30 , "minutes" ) . toDate ( ) ,
code : randomBytes ( 16 ) . toString ( "hex" ) ,
2020-03-18 10:00:57 +00:00
} ) ;
await ClientCode . save ( code ) ;
let redir =
client . redirect_url === "$local" ? "/code" : client . redirect_url ;
2020-08-07 14:16:39 +00:00
let ruri =
redir + ` ?code= ${ code . code } ${ state ? "&state=" + state : "" } ` ;
2020-03-18 10:00:57 +00:00
if ( nored === "true" ) {
res . json ( {
2020-08-07 14:16:39 +00:00
redirect_uri : ruri ,
2020-03-18 10:00:57 +00:00
} ) ;
} 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 ;