Introduces /api/feedback endpoint (to replace Meteor /feedback)
This commit is contained in:
parent
759bf882c7
commit
a21dcb5818
@ -0,0 +1,44 @@
|
|||||||
|
package org.bigbluebutton.api.model.request;
|
||||||
|
|
||||||
|
import org.bigbluebutton.api.model.constraint.UserSessionConstraint;
|
||||||
|
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public class Feedback extends RequestWithSession<Feedback.Params> {
|
||||||
|
|
||||||
|
public enum Params implements RequestParameters {
|
||||||
|
SESSION_TOKEN("sessionToken");
|
||||||
|
|
||||||
|
private final String value;
|
||||||
|
|
||||||
|
Params(String value) { this.value = value; }
|
||||||
|
|
||||||
|
public String getValue() { return value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
@UserSessionConstraint
|
||||||
|
private String sessionToken;
|
||||||
|
|
||||||
|
public Feedback(HttpServletRequest servletRequest) {
|
||||||
|
super(servletRequest);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getSessionToken() {
|
||||||
|
return sessionToken;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSessionToken(String sessionToken) {
|
||||||
|
this.sessionToken = sessionToken;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void populateFromParamsMap(Map<String, String[]> params) {
|
||||||
|
if(params.containsKey(Feedback.Params.SESSION_TOKEN.getValue())) setSessionToken(params.get(Feedback.Params.SESSION_TOKEN.getValue())[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void convertParamsFromString() {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -44,6 +44,7 @@ public class ValidationService {
|
|||||||
SIGN_OUT("signOut", RequestType.GET),
|
SIGN_OUT("signOut", RequestType.GET),
|
||||||
LEARNING_DASHBOARD("learningDashboard", RequestType.GET),
|
LEARNING_DASHBOARD("learningDashboard", RequestType.GET),
|
||||||
GET_JOIN_URL("getJoinUrl", RequestType.GET),
|
GET_JOIN_URL("getJoinUrl", RequestType.GET),
|
||||||
|
FEEDBACK("feedback", RequestType.GET),
|
||||||
INSERT_DOCUMENT("insertDocument", RequestType.GET),
|
INSERT_DOCUMENT("insertDocument", RequestType.GET),
|
||||||
SEND_CHAT_MESSAGE("sendChatMessage", RequestType.GET);
|
SEND_CHAT_MESSAGE("sendChatMessage", RequestType.GET);
|
||||||
|
|
||||||
@ -130,6 +131,7 @@ public class ValidationService {
|
|||||||
case SIGN_OUT -> new SignOut(servletRequest);
|
case SIGN_OUT -> new SignOut(servletRequest);
|
||||||
case LEARNING_DASHBOARD -> new LearningDashboard(servletRequest);
|
case LEARNING_DASHBOARD -> new LearningDashboard(servletRequest);
|
||||||
case GET_JOIN_URL -> new GetJoinUrl(servletRequest);
|
case GET_JOIN_URL -> new GetJoinUrl(servletRequest);
|
||||||
|
case FEEDBACK -> new Feedback(servletRequest);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -227,7 +227,16 @@ const MeetingEnded: React.FC<MeetingEndedProps> = ({
|
|||||||
comment,
|
comment,
|
||||||
isModerator,
|
isModerator,
|
||||||
};
|
};
|
||||||
const url = './feedback';
|
|
||||||
|
const pathMatch = window.location.pathname.match('^(.*)/html5client/join$');
|
||||||
|
if (pathMatch == null) {
|
||||||
|
throw new Error('Failed to match BBB client URI');
|
||||||
|
}
|
||||||
|
const serverPathPrefix = pathMatch[1];
|
||||||
|
|
||||||
|
const sessionToken = sessionStorage.getItem('sessionToken');
|
||||||
|
|
||||||
|
const url = `https://${window.location.hostname}${serverPathPrefix}/bigbluebutton/api/feedback?sessionToken=${sessionToken}`;
|
||||||
const options = {
|
const options = {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
body: JSON.stringify(message),
|
body: JSON.stringify(message),
|
||||||
@ -351,7 +360,7 @@ const MeetingEnded: React.FC<MeetingEndedProps> = ({
|
|||||||
) : null}
|
) : null}
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}, []);
|
}, [askForFeedbackOnLogout, dispatched, selectedStars]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
// Sets Loading to falsed and removes loading splash screen
|
// Sets Loading to falsed and removes loading splash screen
|
||||||
|
@ -56,7 +56,7 @@ public:
|
|||||||
customStyleUrl: null
|
customStyleUrl: null
|
||||||
darkTheme:
|
darkTheme:
|
||||||
enabled: true
|
enabled: true
|
||||||
askForFeedbackOnLogout: false
|
askForFeedbackOnLogout: true
|
||||||
# the default logoutUrl matches window.location.origin i.e. bigbluebutton.org for demo.bigbluebutton.org
|
# the default logoutUrl matches window.location.origin i.e. bigbluebutton.org for demo.bigbluebutton.org
|
||||||
# in some cases we want only custom logoutUrl to be used when provided on meeting create. Default value: true
|
# in some cases we want only custom logoutUrl to be used when provided on meeting create. Default value: true
|
||||||
askForConfirmationOnLeave: true
|
askForConfirmationOnLeave: true
|
||||||
|
@ -111,6 +111,10 @@ class UrlMappings {
|
|||||||
action = [GET: 'getJoinUrl', POST: 'getJoinUrl']
|
action = [GET: 'getJoinUrl', POST: 'getJoinUrl']
|
||||||
}
|
}
|
||||||
|
|
||||||
|
"/bigbluebutton/api/feedback"(controller: "api") {
|
||||||
|
action = [POST: 'feedback']
|
||||||
|
}
|
||||||
|
|
||||||
"/bigbluebutton/api/learningDashboard"(controller: "api") {
|
"/bigbluebutton/api/learningDashboard"(controller: "api") {
|
||||||
action = [GET: 'learningDashboard', POST: 'learningDashboard']
|
action = [GET: 'learningDashboard', POST: 'learningDashboard']
|
||||||
}
|
}
|
||||||
|
@ -19,6 +19,7 @@
|
|||||||
package org.bigbluebutton.web.controllers
|
package org.bigbluebutton.web.controllers
|
||||||
|
|
||||||
import com.google.gson.Gson
|
import com.google.gson.Gson
|
||||||
|
import com.google.gson.JsonObject
|
||||||
import grails.web.context.ServletContextHolder
|
import grails.web.context.ServletContextHolder
|
||||||
import groovy.json.JsonBuilder
|
import groovy.json.JsonBuilder
|
||||||
import groovy.xml.MarkupBuilder
|
import groovy.xml.MarkupBuilder
|
||||||
@ -31,6 +32,7 @@ import org.bigbluebutton.api.*
|
|||||||
import org.bigbluebutton.api.domain.GuestPolicy
|
import org.bigbluebutton.api.domain.GuestPolicy
|
||||||
import org.bigbluebutton.api.domain.Meeting
|
import org.bigbluebutton.api.domain.Meeting
|
||||||
import org.bigbluebutton.api.domain.UserSession
|
import org.bigbluebutton.api.domain.UserSession
|
||||||
|
import org.bigbluebutton.api.domain.UserSessionBasicData
|
||||||
import org.bigbluebutton.api.service.ValidationService
|
import org.bigbluebutton.api.service.ValidationService
|
||||||
import org.bigbluebutton.api.service.ServiceUtils
|
import org.bigbluebutton.api.service.ServiceUtils
|
||||||
import org.bigbluebutton.api.util.ParamsUtil
|
import org.bigbluebutton.api.util.ParamsUtil
|
||||||
@ -1217,6 +1219,79 @@ class ApiController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def feedback = {
|
||||||
|
String API_CALL = 'feedback'
|
||||||
|
log.debug CONTROLLER_NAME + "#${API_CALL}"
|
||||||
|
|
||||||
|
if (!params.sessionToken) {
|
||||||
|
invalid("missingSession", "Invalid session token")
|
||||||
|
}
|
||||||
|
|
||||||
|
String requestBody = request.inputStream == null ? null : request.inputStream.text
|
||||||
|
Gson gson = new Gson()
|
||||||
|
JsonObject body = gson.fromJson(requestBody, JsonObject.class)
|
||||||
|
|
||||||
|
if (!body
|
||||||
|
|| !body.has("userName")
|
||||||
|
|| !body.has("authToken")
|
||||||
|
|| !body.has("comment")
|
||||||
|
|| !body.has("rating")) {
|
||||||
|
invalid("missingParameters", "One or more required parameters are missing")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
String userName = "[unconfirmed] " + body.get("userName").getAsString()
|
||||||
|
String meetingId = ""
|
||||||
|
String userId = ""
|
||||||
|
String authToken = body.get("authToken").getAsString()
|
||||||
|
String comment = body.get("comment").getAsString()
|
||||||
|
int rating = body.get("rating").getAsInt()
|
||||||
|
|
||||||
|
String sessionToken = sanitizeSessionToken(params.sessionToken)
|
||||||
|
UserSession userSession = meetingService.getUserSessionWithSessionToken(sessionToken)
|
||||||
|
|
||||||
|
if(userSession) {
|
||||||
|
userName = userSession.fullname
|
||||||
|
userId = userSession.internalUserId
|
||||||
|
meetingId = userSession.meetingID
|
||||||
|
} else {
|
||||||
|
//Usually the session was already removed when the user send the feedback
|
||||||
|
UserSessionBasicData removedUserSession = meetingService.getRemovedUserSessionWithSessionToken(sessionToken)
|
||||||
|
if(removedUserSession) {
|
||||||
|
userId = removedUserSession.userId
|
||||||
|
meetingId = removedUserSession.meetingId
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(userId == "") {
|
||||||
|
invalid("invalidSession", "Invalid Session")
|
||||||
|
}
|
||||||
|
|
||||||
|
response.contentType = 'application/json'
|
||||||
|
response.setStatus(200)
|
||||||
|
withFormat {
|
||||||
|
json {
|
||||||
|
def builder = new JsonBuilder()
|
||||||
|
builder {
|
||||||
|
"status" "ok"
|
||||||
|
}
|
||||||
|
render(contentType: "application/json", text: builder.toPrettyString())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
def feedback = [
|
||||||
|
meetingId: meetingId,
|
||||||
|
userId: userId,
|
||||||
|
authToken: authToken,
|
||||||
|
userName: userName,
|
||||||
|
comment: comment,
|
||||||
|
rating: rating
|
||||||
|
]
|
||||||
|
|
||||||
|
log.info("FEEDBACK LOG: ${feedback}")
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/***********************************************
|
/***********************************************
|
||||||
* LEARNING DASHBOARD DATA
|
* LEARNING DASHBOARD DATA
|
||||||
***********************************************/
|
***********************************************/
|
||||||
|
Loading…
Reference in New Issue
Block a user