001/* 002 * This file is part of the Keycloak Moodle authenticator 003 * Copyright (C) 2024 Michael N. Lipp 004 * 005 * This program is free software; you can redistribute it and/or modify it 006 * under the terms of the GNU Lesser General Public License as published 007 * by the Free Software Foundation; either version 3 of the License, or 008 * (at your option) any later version. 009 * 010 * This program is distributed in the hope that it will be useful, but 011 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 012 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 013 * License for more details. 014 * 015 * You should have received a copy of the GNU Lesser General Public License along 016 * with this program; if not, see <http://www.gnu.org/licenses/>. 017 */ 018 019package org.jdrupes.keycloak.moodleauth.moodle; 020 021import java.io.IOException; 022import java.net.URI; 023import java.net.URISyntaxException; 024import java.util.Collections; 025import java.util.Map; 026import java.util.logging.Logger; 027import org.jdrupes.keycloak.moodleauth.moodle.actions.MoodleGetSiteInfo; 028import org.jdrupes.keycloak.moodleauth.moodle.actions.MoodleUserByName; 029import org.jdrupes.keycloak.moodleauth.moodle.model.MoodleSiteInfo; 030import org.jdrupes.keycloak.moodleauth.moodle.model.MoodleTokens; 031import org.jdrupes.keycloak.moodleauth.moodle.model.MoodleUser; 032import org.jdrupes.keycloak.moodleauth.moodle.service.MoodleAuthFailedException; 033import org.jdrupes.keycloak.moodleauth.moodle.service.MoodleClient; 034import org.jdrupes.keycloak.moodleauth.moodle.service.MoodleService; 035import org.jdrupes.keycloak.moodleauth.moodle.service.Password; 036 037/** 038 * Represents an open connection to a moodle instance. 039 */ 040public class MoodleServiceProvider implements MoodleService { 041 042 @SuppressWarnings({ "PMD.FieldNamingConventions", 043 "PMD.UnusedPrivateField", "unused" }) 044 private static final Logger logger 045 = Logger.getLogger(MoodleServiceProvider.class.getName()); 046 047 @Override 048 @SuppressWarnings({ "PMD.AvoidCatchingGenericException", 049 "PMD.EmptyCatchBlock" }) 050 public MoodleClient connect(String website, String username, 051 Password password) throws IOException, MoodleAuthFailedException { 052 // Request token 053 try { 054 String site = website; 055 if (!site.contains("://")) { 056 site = "https://" + site; 057 } 058 URI siteUri = new URI("https", "localhost", null, null, null) 059 .resolve(site); 060 if ("".equals(siteUri.getPath())) { 061 siteUri = siteUri.resolve(new URI(null, null, "/", null, null)); 062 } 063 URI tokenUri = siteUri 064 .resolve(new URI(null, null, "login/token.php", null, null)); 065 var restClient = new RestClient(tokenUri); 066 var tokens = restClient.invoke(MoodleTokens.class, 067 Map.of("username", username, 068 "password", new String(password.password()), 069 "service", "moodle_mobile_app"), 070 Collections.emptyMap()); 071 if (tokens.getErrorcode() != null) { 072 try { 073 restClient.close(); 074 } catch (Exception e) { 075 // Was just trying to be nice 076 } 077 throw new MoodleAuthFailedException(tokens.getError()); 078 } 079 URI serviceUri = siteUri.resolve( 080 new URI(null, null, "webservice/rest/server.php", null, null)); 081 restClient.setUri(serviceUri); 082 restClient.setDefaultParams(Map.of("wstoken", tokens.getToken(), 083 "moodlewsrestformat", "json")); 084 MoodleUser muser 085 = new MoodleUserByName(restClient).invoke(username); 086 MoodleSiteInfo siteInfo 087 = new MoodleGetSiteInfo(restClient).invoke(); 088 return new MoodleClientConnection(siteUri, restClient, muser, 089 siteInfo); 090 } catch (URISyntaxException e) { 091 throw new IllegalArgumentException(e); 092 } 093 } 094}