diff --git a/source/api/base.ts b/source/api/base.ts index 56f7a07..a8a23e8 100644 --- a/source/api/base.ts +++ b/source/api/base.ts @@ -6,10 +6,10 @@ namespace _zeitbild.api * @todo zu plankton auslagern? */ type type_stuff = { - version: (null | string); - headers: Record; - path_parameters: Record; - query_parameters: Record; + version : (null | string); + headers : Record; + path_parameters : Record; + query_parameters : Record; }; @@ -24,10 +24,127 @@ namespace _zeitbild.api return {"key": key, "value": value}; } + + /** + */ + export async function user_from_web_auth( + stuff : {headers : Record;} + ) : Promise< + { + id : _zeitbild.type_user_id; + object : _zeitbild.type_user_object; + } + > + { + const authorization_string : string = ( + stuff.headers["Authorization"] + ?? + stuff.headers["authorization"] + ?? + null + ); + if (authorization_string === null) + { + return Promise.reject(new Error("authorization header missing")); + } + else + { + const parts : Array = authorization_string.split(" "); + const strategy : string = parts[0]; + const data_raw : string = parts.slice(1).join(" "); + switch (strategy) + { + default: + { + lib_plankton.log.notice( + "zeitbild.user_from_web_auth.unhandled_strategy", + { + "strategy": strategy, + } + ); + return Promise.reject(new Error("unhandled authorization strategy: " + strategy)); + break; + } + case "Basic": + { + const data_raw_decoded : string = lib_plankton.base64.decode(data_raw); + const parts_ : Array = data_raw_decoded.split(":"); + const username : string = parts_[0]; + const password_is : string = parts_.slice(1).join(":"); + const {"value": user_id, "error": error} = await lib_plankton.call.try_catch_wrap_async<_zeitbild.type_user_id>( + () => _zeitbild.service.user.identify(username) + ); + if ((error !== null) || (user_id === null)) + { + lib_plankton.log.notice( + "zeitbild.user_from_web_auth.unknown_user", + { + "username": username, + } + ); + return Promise.reject(); + } + else + { + const user_object : _zeitbild.type_user_object = await _zeitbild.service.user.get(user_id); + if (user_object.dav_token === null) + { + lib_plankton.log.notice( + "zeitbild.user_from_web_auth.dav_token_unset", + { + "user_id": user_id, + } + ); + return Promise.reject(new Error("DAV token unset")); + } + else + { + const password_shall : string = user_object.dav_token; + if (! (password_is === password_shall)) + { + lib_plankton.log.notice( + "zeitbild.user_from_web_auth.wrong_password", + { + "user_id": user_id, + "password_is": password_is, + } + ); + return Promise.reject(new Error("wrong password")); + } + else + { + return Promise.resolve({"id": user_id, "object": user_object}); + } + } + } + break; + } + } + } + } + /** */ - export const restriction_logged_in : lib_plankton.rest.type_restriction = ( + export const restriction_none : lib_plankton.rest_http.type_restriction = ( + (stuff) => Promise.resolve(true) + ); + + + /** + */ + export const restriction_web_auth : lib_plankton.rest_http.type_restriction = ( + stuff => ( + user_from_web_auth(stuff) + .then(() => Promise.resolve(true)) + .catch(() => Promise.resolve(false)) + ) + ); + + + /** + */ + export const restriction_logged_in : lib_plankton.rest_http.type_restriction = ( (stuff) => ( session_from_stuff(stuff) .then(() => Promise.resolve(true)) @@ -36,23 +153,16 @@ namespace _zeitbild.api ); - /** - */ - export const restriction_none : lib_plankton.rest.type_restriction = ( - (stuff) => Promise.resolve(true) - ); - - /** */ export function register( - rest_subject : lib_plankton.rest.type_rest, + rest_subject : lib_plankton.rest_http.type_rest, http_method : lib_plankton.http.enum_method, path : string, options : { - active ?: ((version : string) => boolean); - restriction ?: (null | lib_plankton.rest.type_restriction); - execution ?: lib_plankton.rest.type_execution; + active ?: ((version : (null | string)) => boolean); + restriction ?: (null | lib_plankton.rest_http.type_restriction); + execution ?: lib_plankton.rest_http.type_execution; title ?: (null | string); description ?: (null | string); query_parameters ?: ((version : (null | string)) => Array< @@ -62,12 +172,26 @@ namespace _zeitbild.api required : boolean; } >); - input_schema ?: ((version: (null | string)) => lib_plankton.rest.type_oas_schema); - output_schema ?: ((version: (null | string)) => lib_plankton.rest.type_oas_schema); - request_body_mimetype ?: string; - request_body_decode ?: ((http_request_body : Buffer, http_request_header_content_type : (null | string)) => any); + input_schema ?: ((version: (null | string)) => lib_plankton.rest_http.type_oas_schema); + output_schema ?: ((version: (null | string)) => lib_plankton.rest_http.type_oas_schema); + request_body_mimetype ?: ( + (version : (null | string)) + => + string + ); + request_body_decode ?: ( + (version : (null | string)) + => + (http_request_body : Buffer, http_request_header_content_type : (null | string)) + => + Promise + ); response_body_mimetype ?: string; - response_body_encode ?: ((output : any) => Buffer); + response_body_encode ?: ( + (output : any) + => + Promise + ); } = {} ) : void { @@ -76,11 +200,78 @@ namespace _zeitbild.api }, options ); - lib_plankton.rest.register( + lib_plankton.rest_http.register( rest_subject, http_method, (_zeitbild.conf.get().server.path_base + path), - options + { + "active": options.active, + /** + * @todo heed version + */ + "restriction": ( + ((options.restriction === undefined) || (options.restriction === null)) + ? + undefined + : + (version) => (options.restriction as lib_plankton.rest_http.type_restriction) + ), + /** + * @todo heed version + */ + "execution": ( + ((options.execution === undefined) || (options.execution === null)) + ? + undefined + : + (version) => (options.execution as lib_plankton.rest_http.type_execution) + ), + /** + * @todo heed version + */ + "title": ( + ((options.title === undefined) || (options.title === null)) + ? + (version) => null + : + (version) => (options.title as string) + ), + /** + * @todo heed version + */ + "description": ( + ((options.description === undefined) || (options.description === null)) + ? + (version) => null + : + (version) => (options.description as string) + ), + "query_parameters": options.query_parameters, + "input_schema": options.input_schema, + "output_schema": options.output_schema, + "request_body_mimetype": options.request_body_mimetype, + "request_body_decode": options.request_body_decode, + /** + * @todo heed version + */ + "response_body_mimetype": ( + ((options.response_body_mimetype === undefined) || (options.response_body_mimetype === null)) + ? + undefined + : + (version) => (options.response_body_mimetype as string) + ), + /** + * @todo heed version + */ + "response_body_encode": ( + ((options.response_body_encode === undefined) || (options.response_body_encode === null)) + ? + undefined + : + (version) => (options.response_body_encode as ((output : any) => Promise)) + ), + } ); }