123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123openLwt.InfixmoduleServer=Cohttp_lwt_unix.Servertypet={client_id:string;client_secret:string;scopes:stringlist;redirect_uri:string;}[@@derivingyojson]letv?(scopes=["read_user"])~client_id~client_secret~redirect_uri()={client_id;client_secret;scopes;redirect_uri}exceptionScopeOfStringofstringletscope_of_stringscope=matchGitlab.Scope.of_stringscopewith|Somes->s|None->raise@@ScopeOfString("Invalid option for scope_of_string :"^scope)letmake_login_urit~csrf=Gitlab.Token.create_url~client_id:t.client_id~redirect_uri:(Uri.of_stringt.redirect_uri)~state:csrf~scopes:(List.mapscope_of_stringt.scopes)()letget_access_tokentcode=Gitlab.Token.of_code~client_id:t.client_id~code~client_secret:t.client_secret~redirect_uri:t.redirect_uri()letget_usertoken=letopenGitlabinletopenMonadinletcmd=User.current_user~token()>|~funuser->Ok("gitlab:"^user.Gitlab_t.current_user_username)inruncmdletexample_config()=v~client_id:"..."~client_secret:"..."~redirect_uri:"..."()|>to_yojson|>Yojson.Safe.pretty_to_stringletconfiguration_howtoctx=Current_web.Context.respond_okctxTyxml.Html.[p[txt"GitLab single-sign-on has not been configured."];p[txt"Start the service with ";code[txt"--gitlab-oauth path.json"];txt", where the file contains:";];pre[txt(example_config())]]letlogint:Current_web.Resource.t=objectmethodget_rawsiterequest=Current_web.Context.of_request~siterequest>>=functx->matchtwith|None->configuration_howtoctx|Somet->leturi=Cohttp.Request.urirequestinmatchUri.get_query_paramuri"code",Uri.get_query_paramuri"state"with|None,_->Server.respond_error~status:`Bad_request~body:"Missing code"()|_,None->Server.respond_error~status:`Bad_request~body:"Missing state"()|Somecode,Somestate->ifstate<>Current_web.Context.csrfctxthen(Server.respond_error~status:`Bad_request~body:"Bad CSRF token"())else(get_access_tokentcode>>=function|None->Server.respond_error~status:`Internal_server_error~body:"Failed to get token"()|Sometoken->get_usertoken>>=function|Error(status,msg)->Log.warn(funf->f"Failed to get user details from GitLab: %s: %s"(Cohttp.Code.string_of_statusstatus)msg);Server.respond_error~status:`Internal_server_error~body:"Failed to get user details"()|Okuser->Log.info(funf->f"Successful login for %S"user);matchCurrent_web.User.vuserwith|Error(`Msgm)->Log.warn(funf->f"Failed to create user: %s"m);Server.respond_error~status:`Bad_request~body:"Bad user"()|Okuser->Current_web.Context.set_userctxuser)methodpost_raw___=Server.respond_error~status:`Bad_request~body:"Bad method"()methodnav_link=NoneendopenCmdlinerletoauth_config=Arg.value@@Arg.optArg.(somefile)None@@Arg.info~doc:"The JSON file containing the GitLab OAuth configuration"~docv:"PATH"["gitlab-oauth"]letmake_configpath=matchYojson.Safe.from_filepathwith|exceptionex->Fmt.failwith"Invalid JSON in %s:@,%a"pathFmt.exnex|json->json|>of_yojson|>function|Okx->x|Errormsg->Fmt.failwith"Invalid GitLab OAuth configuration: %s@.Expected: %s"msg(example_config())letcmdliner=Term.(const(Option.mapmake_config)$oauth_config)