/* This file is part of »zeitbild«. Copyright 2025 'kcf' »zeitbild« is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. »zeitbild« is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with »zeitbild«. If not, see . */ namespace _zeitbild.api { /** */ function get_group_name( group_name_raw : string ) : string { return lib_plankton.string.coin( "auto-{{name_raw}}", { "name_raw": group_name_raw, } ); } /** */ function get_group_label( group_name_raw : string ) : string { return lib_plankton.string.coin( "{{name_raw}}", { "name_raw": group_name_raw, } ); } /** */ export function register_session_oidc( rest_subject : lib_plankton.rest_http.type_rest ) : void { register< null, string >( rest_subject, lib_plankton.http.enum_method.get, "/session/oidc", { "description": "verarbeitet einen OIDC login callback", "query_parameters": () => ([ { "name": "code", "required": true, "description": null, }, { "name": "iss", "required": true, "description": null, }, { "name": "scope", "required": true, "description": null, }, { "name": "state", "required": true, "description": null, }, ]), "input_schema": () => ({ "type": "null", }), "output_schema": () => ({ "nullable": false, "type": "string", }), "response_body_mimetype": "text/html", "response_body_encode": (output => Buffer.from(output)), "restriction": restriction_none, "execution": async (stuff) => { const data : { token : string; userinfo : { name : (null | string); email : (null | string); groups : (null | Array); }; redirect_uri_template : string; } = await _zeitbild.auth.oidc_handle_authorization_callback( (stuff.headers["Cookie"] ?? stuff.headers["cookie"] ?? null), stuff.query_parameters ); if (data.userinfo.name === null) { return Promise.reject( new Error( "IDP did not return user name" ) ); } else { try { // groups const group_ids : Array<_zeitbild.type_group_id> = await Promise.all<_zeitbild.type_group_id>( (data.userinfo.groups ?? []) .map( async (group_name_raw) => { const group_name : string = get_group_name(group_name_raw); let group_id : (null | _zeitbild.type_group_id) = await (() => { try { return _zeitbild.repository.group.identify(group_name); } catch (error) { return Promise.resolve(null); } }) (); if (group_id === null) { group_id = await _zeitbild.service.group.add( { "name": group_name, "label": get_group_label(group_name_raw), } ); return group_id; } else { await _zeitbild.service.group.change( group_id, { "name": group_name, "label": get_group_label(group_name_raw), } ); return group_id; } } ) ); await _zeitbild.service.user.add( { "name": data.userinfo.name, "groups": group_ids, "email_address": data.userinfo.email, "dav_token": null, } ); lib_plankton.log.info( "user_provisioned", { "name": data.userinfo.name, } ); } catch (error) { // do nothing } const session_key : string = await lib_plankton.session.begin( data.userinfo.name, { "data": { "oidc_token": data.token, } } ); return Promise.resolve( { "status_code": 200, "data": lib_plankton.string.coin( "", { "url": lib_plankton.string.coin( data.redirect_uri_template, { "session_key": session_key, } ), } ), } ); } }, } ); } }