Skip to content

Commit 853ddf0

Browse files
Merge branch 'release-5.19'
2 parents 9e00e9c + 7dd57a6 commit 853ddf0

38 files changed

Lines changed: 802 additions & 499 deletions

package-lock.json

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "wise",
3-
"version": "5.18.4",
3+
"version": "5.19.0",
44
"description": "Web-based Inquiry Science Environment",
55
"main": "app.js",
66
"browserslist": [

pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@
3434
<artifactId>wise</artifactId>
3535
<packaging>war</packaging>
3636
<name>Web-based Inquiry Science Environment</name>
37-
<version>5.18.4</version>
37+
<version>5.19.0</version>
3838
<url>http://wise5.org</url>
3939
<licenses>
4040
<license>
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
package org.wise.portal.presentation.web.controllers;
2+
3+
import java.io.UnsupportedEncodingException;
4+
import java.net.URLEncoder;
5+
import java.security.InvalidKeyException;
6+
import java.security.NoSuchAlgorithmException;
7+
import java.util.Properties;
8+
9+
import javax.crypto.Mac;
10+
import javax.crypto.spec.SecretKeySpec;
11+
12+
import org.springframework.beans.factory.annotation.Autowired;
13+
import org.springframework.security.core.Authentication;
14+
import org.springframework.stereotype.Controller;
15+
import org.springframework.web.bind.annotation.GetMapping;
16+
import org.springframework.web.bind.annotation.RequestParam;
17+
import org.springframework.web.servlet.view.RedirectView;
18+
import org.wise.portal.domain.authentication.MutableUserDetails;
19+
import org.wise.portal.domain.user.User;
20+
import org.wise.portal.presentation.util.http.Base64;
21+
import org.wise.portal.service.user.UserService;
22+
23+
@Controller
24+
public class DiscourseSSOController {
25+
26+
@Autowired
27+
Properties appProperties;
28+
29+
@Autowired
30+
UserService userService;
31+
32+
@GetMapping("/sso/discourse")
33+
protected RedirectView discourseSSOLogin(@RequestParam("sso") String base64EncodedSSO,
34+
@RequestParam("sig") String sigParam, Authentication auth) throws Exception {
35+
String secretKey = appProperties.getProperty("discourse_sso_secret_key");
36+
String discourseURL = appProperties.getProperty("discourse_url");
37+
if (secretKey == null || secretKey.isEmpty() || discourseURL == null || discourseURL.isEmpty()) {
38+
return null;
39+
}
40+
String base64DecodedSSO = new String(Base64.decode(base64EncodedSSO), "UTF-8");
41+
if (!base64DecodedSSO.startsWith("nonce=")) {
42+
return null;
43+
}
44+
String nonce = base64DecodedSSO.substring(6);
45+
String algorithm = "HmacSHA256";
46+
String hMACSHA256Message = hmacDigest(base64EncodedSSO, secretKey, algorithm);
47+
if (!hMACSHA256Message.equals(sigParam)) {
48+
return null;
49+
}
50+
User user = userService.retrieveUserByUsername(auth.getName());
51+
return new RedirectView(
52+
generateDiscourseSSOLoginURL(secretKey, discourseURL, nonce, algorithm, user));
53+
}
54+
55+
private String generateDiscourseSSOLoginURL(String secretKey, String discourseURL, String nonce,
56+
String algorithm, User user) throws UnsupportedEncodingException {
57+
String wiseUserId = URLEncoder.encode(user.getId().toString(), "UTF-8");
58+
MutableUserDetails userDetails = user.getUserDetails();
59+
String username = URLEncoder.encode(userDetails.getUsername(), "UTF-8");
60+
String name =
61+
URLEncoder.encode(userDetails.getFirstname() + " " + userDetails.getLastname(), "UTF-8");
62+
String email = URLEncoder.encode(userDetails.getEmailAddress(), "UTF-8");
63+
String payLoadString = "nonce=" + nonce + "&name=" + name + "&username=" + username +
64+
"&email=" + email + "&external_id=" + wiseUserId;
65+
String payLoadStringBase64Encoded = Base64.encodeBytes(payLoadString.getBytes());
66+
String payLoadStringBase64EncodedURLEncoded =
67+
URLEncoder.encode(payLoadStringBase64Encoded, "UTF-8");
68+
String payLoadStringBase64EncodedHMACSHA256Signed =
69+
hmacDigest(payLoadStringBase64Encoded, secretKey, algorithm);
70+
String discourseSSOLoginURL = discourseURL + "/session/sso_login" +
71+
"?sso=" + payLoadStringBase64EncodedURLEncoded +
72+
"&sig=" + payLoadStringBase64EncodedHMACSHA256Signed;
73+
return discourseSSOLoginURL;
74+
}
75+
76+
public static String hmacDigest(String msg, String secretKey, String algorithm) {
77+
String digest = null;
78+
try {
79+
SecretKeySpec key = new SecretKeySpec((secretKey).getBytes("UTF-8"), algorithm);
80+
Mac mac = Mac.getInstance(algorithm);
81+
mac.init(key);
82+
byte[] bytes = mac.doFinal(msg.getBytes("ASCII"));
83+
StringBuffer hash = new StringBuffer();
84+
for (int i = 0; i < bytes.length; i++) {
85+
String hex = Integer.toHexString(0xFF & bytes[i]);
86+
if (hex.length() == 1) {
87+
hash.append('0');
88+
}
89+
hash.append(hex);
90+
}
91+
digest = hash.toString();
92+
} catch (UnsupportedEncodingException e) {
93+
} catch (InvalidKeyException e) {
94+
} catch (NoSuchAlgorithmException e) {
95+
}
96+
return digest;
97+
}
98+
}

src/main/java/org/wise/portal/presentation/web/controllers/user/UserAPIController.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,7 @@ protected HashMap<String, Object> getConfig(HttpServletRequest request) {
135135
config.put("recaptchaPublicKey", appProperties.get("recaptcha_public_key"));
136136
config.put("wiseHostname", appProperties.get("wise.hostname"));
137137
config.put("wise4Hostname", appProperties.get("wise4.hostname"));
138+
config.put("discourseURL", appProperties.getOrDefault("discourse_url", null));
138139
return config;
139140
}
140141

src/main/java/org/wise/portal/service/vle/wise5/VLEService.java

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -122,12 +122,7 @@ Annotation saveAnnotation(Integer id, Integer runId, Integer periodId, Integer f
122122
String localNotebookItemId, Integer notebookItemId, String type, String data,
123123
String clientSaveTime) throws ObjectNotFoundException;
124124

125-
/**
126-
* @return StudentsAssets from data store
127-
*/
128-
List<StudentAsset> getStudentAssets(Integer id, Integer runId, Integer periodId,
129-
Integer workgroupId, String nodeId, String componentId, String componentType,
130-
Boolean isReferenced) throws ObjectNotFoundException;
125+
List<StudentAsset> getWorkgroupAssets(Long workgroupId) throws ObjectNotFoundException;
131126

132127
/**
133128
* Saves StudentAssets in the data store

src/main/java/org/wise/portal/service/vle/wise5/impl/VLEServiceImpl.java

Lines changed: 4 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -620,35 +620,10 @@ public Annotation saveAnnotation(Integer id, Integer runId, Integer periodId,
620620
}
621621

622622
@Override
623-
public List<StudentAsset> getStudentAssets(Integer id, Integer runId, Integer periodId,
624-
Integer workgroupId, String nodeId, String componentId, String componentType,
625-
Boolean isReferenced) {
626-
Run run = null;
627-
if (runId != null) {
628-
try {
629-
run = runService.retrieveById(new Long(runId));
630-
} catch (ObjectNotFoundException e) {
631-
e.printStackTrace();
632-
}
633-
}
634-
Group period = null;
635-
if (periodId != null) {
636-
try {
637-
period = groupService.retrieveById(new Long(periodId));
638-
} catch (ObjectNotFoundException e) {
639-
e.printStackTrace();
640-
}
641-
}
642-
Workgroup workgroup = null;
643-
if (workgroupId != null) {
644-
try {
645-
workgroup = workgroupService.retrieveById(new Long(workgroupId));
646-
} catch (ObjectNotFoundException e) {
647-
e.printStackTrace();
648-
}
649-
}
650-
return studentAssetDao.getStudentAssetListByParams(id, run, period, workgroup, nodeId,
651-
componentId, componentType, isReferenced);
623+
public List<StudentAsset> getWorkgroupAssets(Long workgroupId) throws ObjectNotFoundException {
624+
Workgroup workgroup = workgroupService.retrieveById(workgroupId);
625+
return studentAssetDao.getStudentAssetListByParams(null, null, null, workgroup, null,
626+
null, null, null);
652627
}
653628

654629
@Override
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package org.wise.portal.service.work;
2+
3+
import com.fasterxml.jackson.databind.module.SimpleModule;
4+
5+
import org.springframework.beans.factory.annotation.Autowired;
6+
import org.springframework.stereotype.Service;
7+
import org.wise.vle.domain.achievement.Achievement;
8+
import org.wise.vle.domain.achievement.AchievementSerializer;
9+
10+
@Service
11+
public class AchievementJsonModule extends SimpleModule {
12+
13+
private static final long serialVersionUID = 1L;
14+
15+
public AchievementJsonModule() {}
16+
17+
@Autowired
18+
public AchievementJsonModule(AchievementSerializer serializer) {
19+
this.addSerializer(Achievement.class, serializer);
20+
}
21+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package org.wise.portal.service.work;
2+
3+
import com.fasterxml.jackson.databind.module.SimpleModule;
4+
5+
import org.springframework.beans.factory.annotation.Autowired;
6+
import org.springframework.stereotype.Service;
7+
import org.wise.vle.domain.work.StudentAsset;
8+
import org.wise.vle.domain.work.StudentAssetSerializer;
9+
10+
@Service
11+
public class StudentAssetJsonModule extends SimpleModule {
12+
13+
private static final long serialVersionUID = 1L;
14+
15+
public StudentAssetJsonModule() {}
16+
17+
@Autowired
18+
public StudentAssetJsonModule(StudentAssetSerializer serializer) {
19+
this.addSerializer(StudentAsset.class, serializer);
20+
}
21+
}

src/main/java/org/wise/portal/spring/impl/WebSecurityConfig.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@ protected void configure(HttpSecurity http) throws Exception {
9494
.antMatchers("/student/**").hasAnyRole("STUDENT")
9595
.antMatchers("/studentStatus").hasAnyRole("TEACHER,STUDENT")
9696
.antMatchers("/teacher/**").hasAnyRole("TEACHER")
97+
.antMatchers("/sso/discourse").hasAnyRole("TEACHER,STUDENT")
9798
.antMatchers("/").permitAll();
9899
http.formLogin().loginPage("/login").permitAll();
99100
http.sessionManagement().maximumSessions(2).sessionRegistry(sessionRegistry());
@@ -182,7 +183,7 @@ public AuthenticationSuccessHandler authSuccessHandler() {
182183
@Bean
183184
public AuthenticationFailureHandler authFailureHandler() {
184185
WISEAuthenticationFailureHandler handler = new WISEAuthenticationFailureHandler();
185-
handler.setAuthenticationFailureUrl("/legacy/login?failed=true");
186+
handler.setAuthenticationFailureUrl("/login?failed=true");
186187
return handler;
187188
}
188189

0 commit comments

Comments
 (0)