io.kamax.mxisd.controller.identity.v1.SessionRestController.java Source code

Java tutorial

Introduction

Here is the source code for io.kamax.mxisd.controller.identity.v1.SessionRestController.java

Source

/*
 * mxisd - Matrix Identity Server Daemon
 * Copyright (C) 2017 Maxime Dor
 *
 * https://max.kamax.io/
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * This program 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 Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

package io.kamax.mxisd.controller.identity.v1;

import com.google.gson.Gson;
import com.google.gson.JsonObject;
import io.kamax.matrix.ThreePid;
import io.kamax.matrix.ThreePidMedium;
import io.kamax.mxisd.config.ServerConfig;
import io.kamax.mxisd.config.ViewConfig;
import io.kamax.mxisd.controller.identity.v1.io.SessionEmailTokenRequestJson;
import io.kamax.mxisd.controller.identity.v1.io.SessionPhoneTokenRequestJson;
import io.kamax.mxisd.controller.identity.v1.io.SuccessStatusJson;
import io.kamax.mxisd.exception.BadRequestException;
import io.kamax.mxisd.exception.SessionNotValidatedException;
import io.kamax.mxisd.invitation.InvitationManager;
import io.kamax.mxisd.lookup.ThreePidValidation;
import io.kamax.mxisd.session.SessionMananger;
import io.kamax.mxisd.session.ValidationResult;
import io.kamax.mxisd.util.GsonParser;
import org.apache.http.HttpStatus;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

import static org.springframework.web.bind.annotation.RequestMethod.POST;

@RestController
@CrossOrigin
@RequestMapping(path = IdentityAPIv1.BASE, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
public class SessionRestController {

    private Logger log = LoggerFactory.getLogger(SessionRestController.class);

    private class Sid { // FIXME replace with RequestTokenResponse

        private String sid;

        public Sid(String sid) {
            setSid(sid);
        }

        String getSid() {
            return sid;
        }

        void setSid(String sid) {
            this.sid = sid;
        }
    }

    @Autowired
    private ServerConfig srvCfg;

    @Autowired
    private SessionMananger mgr;

    @Autowired
    private InvitationManager invMgr;

    @Autowired
    private ViewConfig viewCfg;

    private Gson gson = new Gson();
    private GsonParser parser = new GsonParser(gson);

    @RequestMapping(value = "/validate/{medium}/requestToken")
    String init(HttpServletRequest request, HttpServletResponse response, @PathVariable String medium)
            throws IOException {
        log.info("Request {}: {}", request.getMethod(), request.getRequestURL(), request.getQueryString());
        if (ThreePidMedium.Email.is(medium)) {
            SessionEmailTokenRequestJson req = parser.parse(request, SessionEmailTokenRequestJson.class);
            return gson.toJson(
                    new Sid(mgr.create(request.getRemoteHost(), new ThreePid(req.getMedium(), req.getValue()),
                            req.getSecret(), req.getAttempt(), req.getNextLink())));
        }

        if (ThreePidMedium.PhoneNumber.is(medium)) {
            SessionPhoneTokenRequestJson req = parser.parse(request, SessionPhoneTokenRequestJson.class);
            ThreePid threepid = new ThreePid(req.getMedium(), req.getValue());

            String sessionId = mgr.create(request.getRemoteHost(), threepid, req.getSecret(), req.getAttempt(),
                    req.getNextLink());

            JsonObject res = new JsonObject();
            res.addProperty("sid", sessionId);
            res.addProperty(threepid.getMedium(), threepid.getAddress());
            return gson.toJson(res);
        }

        JsonObject obj = new JsonObject();
        obj.addProperty("errcode", "M_INVALID_3PID_TYPE");
        obj.addProperty("error", medium + " is not supported as a 3PID type");
        response.setStatus(HttpStatus.SC_BAD_REQUEST);
        return gson.toJson(obj);
    }

    @RequestMapping(value = "/validate/{medium}/submitToken", method = POST)
    public String validate(HttpServletRequest request, HttpServletResponse response, @RequestParam String sid,
            @RequestParam("client_secret") String secret, @RequestParam String token, Model model) {
        log.info("Requested: {}", request.getRequestURL());

        ValidationResult r = mgr.validate(sid, secret, token);
        log.info("Session {} was validated", sid);

        return gson.toJson(new SuccessStatusJson(true));
    }

    @RequestMapping(value = "/3pid/getValidated3pid")
    String check(HttpServletRequest request, HttpServletResponse response, @RequestParam String sid,
            @RequestParam("client_secret") String secret) {
        log.info("Requested: {}", request.getRequestURL(), request.getQueryString());

        try {
            ThreePidValidation pid = mgr.getValidated(sid, secret);

            JsonObject obj = new JsonObject();
            obj.addProperty("medium", pid.getMedium());
            obj.addProperty("address", pid.getAddress());
            obj.addProperty("validated_at", pid.getValidation().toEpochMilli());

            return gson.toJson(obj);
        } catch (SessionNotValidatedException e) {
            log.info("Session {} was requested but has not yet been validated", sid);
            throw e;
        }
    }

    @RequestMapping(value = "/3pid/bind")
    String bind(HttpServletRequest request, HttpServletResponse response, @RequestParam String sid,
            @RequestParam("client_secret") String secret, @RequestParam String mxid) {
        log.info("Requested: {}", request.getRequestURL(), request.getQueryString());
        try {
            mgr.bind(sid, secret, mxid);
            return "{}";
        } catch (BadRequestException e) {
            log.info("requested session was not validated");

            JsonObject obj = new JsonObject();
            obj.addProperty("errcode", "M_SESSION_NOT_VALIDATED");
            obj.addProperty("error", e.getMessage());
            response.setStatus(HttpStatus.SC_BAD_REQUEST);
            return gson.toJson(obj);
        } finally {
            // If a user registers, there is no standard login event. Instead, this is the only way to trigger
            // resolution at an appropriate time. Meh at synapse/Riot!
            invMgr.lookupMappingsForInvites();
        }
    }

}