Skip to content
This repository was archived by the owner on Jun 3, 2025. It is now read-only.

Commit b57e35c

Browse files
author
Irene
committed
Disable logging in if already logged in
Also refactored logging in and added notification for untraced "no oauth token" problem which occurs sometimes when logging in Must be logged in to run config Add prompt for sending analytics
1 parent 8700e76 commit b57e35c

36 files changed

Lines changed: 209 additions & 159 deletions

docs/MANUAL.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,8 @@ List of configurable settings:
206206
blue, purple, cyan, white, none. Stored in properties.
207207
* *send-diagnostics*
208208
Allow sending crash reports and analytics for client development. Stored with account.
209+
* *send-analytics*
210+
Allow sending analytics data of commands run. Stored in account.
209211
* *server-address*
210212
Address to fetch courses from and submit to. Defaults to `https://tmc.mooc.fi`. Stored with account
211213

src/main/java/fi/helsinki/cs/tmc/cli/Application.java

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
package fi.helsinki.cs.tmc.cli;
22

33
import fi.helsinki.cs.tmc.cli.analytics.AnalyticsFacade;
4-
import fi.helsinki.cs.tmc.cli.analytics.AnalyticsSettings;
54
import fi.helsinki.cs.tmc.cli.analytics.TimeTracker;
65
import fi.helsinki.cs.tmc.cli.backend.Settings;
76
import fi.helsinki.cs.tmc.cli.command.SubmitCommand;
@@ -205,9 +204,8 @@ public static void main(String[] args) {
205204
Settings settings = new Settings();
206205
TaskExecutor tmcLangs = new TaskExecutorImpl();
207206
TmcCore core = new TmcCore(settings, tmcLangs);
208-
AnalyticsSettings analyticsSettings = new AnalyticsSettings();
209-
EventSendBuffer eventSendBuffer = new EventSendBuffer(analyticsSettings, new EventStore());
210-
AnalyticsFacade analyticsFacade = new AnalyticsFacade(analyticsSettings, eventSendBuffer);
207+
EventSendBuffer eventSendBuffer = new EventSendBuffer(settings, new EventStore());
208+
AnalyticsFacade analyticsFacade = new AnalyticsFacade(settings, eventSendBuffer);
211209
Application app = new Application(new CliContext(null, core, new WorkDir(), settings, analyticsFacade));
212210
app.run(args);
213211
}

src/main/java/fi/helsinki/cs/tmc/cli/analytics/AnalyticsFacade.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import fi.helsinki.cs.tmc.spyware.EventSendBuffer;
88
import fi.helsinki.cs.tmc.spyware.EventStore;
99
import fi.helsinki.cs.tmc.spyware.LoggableEvent;
10+
import fi.helsinki.cs.tmc.spyware.SpywareSettings;
1011

1112
import java.awt.*;
1213
import java.util.List;
@@ -16,10 +17,10 @@
1617

1718
public class AnalyticsFacade {
1819
private EventSendBuffer eventSendBuffer;
19-
private AnalyticsSettings settings;
20+
private SpywareSettings settings;
2021
private static final Logger log = Logger.getLogger(AnalyticsFacade.class.getName());
2122

22-
public AnalyticsFacade(AnalyticsSettings settings, EventSendBuffer eventSendBuffer) {
23+
public AnalyticsFacade(SpywareSettings settings, EventSendBuffer eventSendBuffer) {
2324
this.settings = settings;
2425
this.eventSendBuffer = eventSendBuffer;
2526
}

src/main/java/fi/helsinki/cs/tmc/cli/analytics/AnalyticsSettings.java

Lines changed: 0 additions & 27 deletions
This file was deleted.

src/main/java/fi/helsinki/cs/tmc/cli/analytics/TimeTracker.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,11 @@ public void restart() {
2121
}
2222

2323
public boolean anHourHasPassedSinceLastSubmit() {
24-
long startTime = Long.parseLong(SettingsIo.loadProperties().get(PROPERTY_KEY));
24+
String submitProperty = SettingsIo.loadProperties().get(PROPERTY_KEY);
25+
if (submitProperty == null) {
26+
return false;
27+
}
28+
long startTime = Long.parseLong(submitProperty);
2529
long endTime = System.nanoTime();
2630
long elapsedTime = endTime - startTime;
2731
long hoursPassed = TimeUnit.HOURS.convert(elapsedTime, TimeUnit.NANOSECONDS);

src/main/java/fi/helsinki/cs/tmc/cli/backend/Account.java

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ public class Account {
1919
private String token;
2020
private Organization organization;
2121
private boolean sendDiagnostics;
22+
private boolean sendAnalytics;
23+
private boolean sendDetailedAnalytics;
2224
private static final String DEFAULT_SERVER = "https://tmc.mooc.fi/staging";
2325

2426
// for gson
@@ -88,12 +90,12 @@ public void setPassword(Optional<String> password) {
8890
this.password = null;
8991
}
9092

91-
public Optional<String> getoAuthToken() {
92-
return Optional.of(this.token);
93+
public Optional<String> getOauthToken() {
94+
return Optional.fromNullable(this.token);
9395
}
9496

95-
public void setoAuthToken(Optional<String> token) {
96-
this.token= token.orNull();
97+
public void setOauthToken(Optional<String> token) {
98+
this.token = token.orNull();
9799
}
98100

99101
public Optional<Course> getCurrentCourse() {
@@ -119,4 +121,20 @@ public void setSendDiagnostics(boolean value) {
119121
public boolean getSendDiagnostics() {
120122
return this.sendDiagnostics;
121123
}
124+
125+
public boolean getSendAnalytics() {
126+
return this.sendAnalytics;
127+
}
128+
129+
public void setSendAnalytics(boolean sendAnalytics) {
130+
this.sendAnalytics = sendAnalytics;
131+
}
132+
133+
public boolean getSendDetailedAnalytics() {
134+
return false;
135+
}
136+
137+
public void setSendDetailedAnalytics(boolean sendDetailedAnalytics) {
138+
this.sendDetailedAnalytics = false;
139+
}
122140
}

src/main/java/fi/helsinki/cs/tmc/cli/backend/Settings.java

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,13 @@
99
import com.google.common.base.Optional;
1010
import fi.helsinki.cs.tmc.core.domain.OauthCredentials;
1111
import fi.helsinki.cs.tmc.core.domain.Organization;
12+
import fi.helsinki.cs.tmc.spyware.SpywareSettings;
1213
import org.apache.http.impl.conn.SystemDefaultRoutePlanner;
1314

1415
import java.nio.file.Path;
1516
import java.util.Locale;
1617

17-
public class Settings implements TmcSettings {
18+
public class Settings implements TmcSettings, SpywareSettings {
1819

1920
private WorkDir workDir;
2021
private Account account;
@@ -148,12 +149,12 @@ public void setOauthCredentials(Optional<OauthCredentials> credentials) {
148149

149150
@Override
150151
public void setToken(Optional<String> token) {
151-
account.setoAuthToken(token);
152+
account.setOauthToken(token);
152153
}
153154

154155
@Override
155156
public Optional<String> getToken() {
156-
return account.getoAuthToken();
157+
return account.getOauthToken();
157158
}
158159

159160
@Override
@@ -166,7 +167,21 @@ public void setOrganization(Optional<Organization> organization) {
166167
account.setOrganization(organization);
167168
}
168169

169-
public void setCourse(Course course) {
170-
account.setCurrentCourse(Optional.of(course));
170+
@Override
171+
public boolean isSpywareEnabled() {
172+
return account.getSendAnalytics();
173+
}
174+
175+
public void setSpywareEnabled(boolean spywareEnabled) {
176+
account.setSendAnalytics(spywareEnabled);
177+
}
178+
179+
@Override
180+
public boolean isDetailedSpywareEnabled() {
181+
return account.getSendDetailedAnalytics();
182+
}
183+
184+
public void setDetailedSpywareEnabled(boolean detailedSpywareEnabled) {
185+
account.setSendDetailedAnalytics(detailedSpywareEnabled);
171186
}
172187
}

src/main/java/fi/helsinki/cs/tmc/cli/backend/TmcUtil.java

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818

1919
import org.apache.commons.compress.archivers.sevenz.CLI;
2020
import org.apache.oltu.oauth2.common.exception.OAuthProblemException;
21+
import org.apache.oltu.oauth2.common.exception.OAuthSystemException;
2122
import org.slf4j.Logger;
2223
import org.slf4j.LoggerFactory;
2324

@@ -236,7 +237,7 @@ private static void handleTmcExceptions(CliContext ctx, Exception exception) {
236237

237238
if (exception instanceof IllegalArgumentException) {
238239
logger.error("Invalid arguments", exception);
239-
io.errorln("Please give server, username and password in valid form.");
240+
io.errorln("Please give server, username and password in valid forms.");
240241
return;
241242
}
242243

@@ -259,11 +260,17 @@ private static void handleTmcExceptions(CliContext ctx, Exception exception) {
259260
return;
260261
}
261262

263+
if (cause instanceof OAuthSystemException) {
264+
io.errorln("There was a problem with authentication.\nPlease try logging in again.");
265+
return;
266+
}
267+
262268
if (cause != null && cause.getCause() instanceof UnknownHostException) {
263269
logger.error("No internet connection");
264270
io.errorln("You have no internet connection.");
265271
return;
266272
}
273+
267274
logger.error("Command failed in tmc-core", exception);
268275
//TODO we seem to write twice error message; here and in the commands.
269276
io.errorln("Command failed, check tmc-cli.log file for more info");

src/main/java/fi/helsinki/cs/tmc/cli/command/ConfigCommand.java

Lines changed: 35 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package fi.helsinki.cs.tmc.cli.command;
22

3+
import com.google.common.base.Optional;
34
import fi.helsinki.cs.tmc.cli.backend.SettingsIo;
45
import fi.helsinki.cs.tmc.cli.core.AbstractCommand;
56
import fi.helsinki.cs.tmc.cli.core.CliContext;
@@ -17,10 +18,8 @@
1718
import java.util.HashMap;
1819
import java.util.Map;
1920
import java.util.Set;
20-
import java.util.ArrayList;
2121
import java.util.Arrays;
2222
import java.util.HashSet;
23-
import java.util.Collections;
2423

2524
@Command(name = "config", desc = "Set/unset TMC-CLI properties")
2625
public class ConfigCommand extends AbstractCommand {
@@ -43,15 +42,15 @@ private void configureAllowedKeys() {
4342
// add new possible config options here
4443
// each key has a BiConsumer function which validates the value and saves it in settings or properties
4544
ALLOWED_KEYS.put("send-diagnostics", (key, value) -> {
46-
String newVal = (String) value;
47-
if (!newVal.trim().toLowerCase().equals("true") && !newVal.trim().toLowerCase().equals("false")) {
48-
throw new BadValueTypeException("Please write either true or false");
49-
}
50-
boolean send = Boolean.parseBoolean(newVal);
45+
boolean send = getBooleanSendValue((String) value);
5146
context.getSettings().setSendDiagnostics(send);
5247
SettingsIo.saveCurrentSettingsToAccountList(context.getSettings());
5348
});
54-
49+
ALLOWED_KEYS.put("send-analytics", (key, value) -> {
50+
boolean send = getBooleanSendValue((String) value);
51+
context.getSettings().setSpywareEnabled(send);
52+
SettingsIo.saveCurrentSettingsToAccountList(context.getSettings());
53+
});
5554
ALLOWED_KEYS.put("server-address", (key, address) -> {
5655
String addr = (String) address;
5756
if (!addr.matches("^https?://.*")) {
@@ -64,18 +63,29 @@ private void configureAllowedKeys() {
6463
}
6564
SettingsIo.saveCurrentSettingsToAccountList(context.getSettings());
6665
});
67-
6866
ALLOWED_KEYS.put("update-date", (key, value) -> {
6967
String date = (String) value;
7068
if (!date.matches("[0-9]+")) {
7169
throw new BadValueTypeException("Please insert the date as a number");
7270
}
7371
properties.put("update-date", date);
7472
});
75-
ALLOWED_KEYS.put("testresults-right", this::addToProperties);
76-
ALLOWED_KEYS.put("testresults-left", this::addToProperties);
77-
ALLOWED_KEYS.put("progressbar-left", this::addToProperties);
78-
ALLOWED_KEYS.put("progressbar-right", this::addToProperties);
73+
ALLOWED_KEYS.put("testresults-right", this::addBarColorToProperties);
74+
ALLOWED_KEYS.put("testresults-left", this::addBarColorToProperties);
75+
ALLOWED_KEYS.put("progressbar-left", this::addBarColorToProperties);
76+
ALLOWED_KEYS.put("progressbar-right", this::addBarColorToProperties);
77+
}
78+
79+
private boolean getBooleanSendValue(String value) throws BadValueTypeException {
80+
String newVal = value;
81+
isBooleanValue(newVal);
82+
return Boolean.parseBoolean(newVal);
83+
}
84+
85+
private void isBooleanValue(String newVal) throws BadValueTypeException {
86+
if (!newVal.trim().toLowerCase().equals("true") && !newVal.trim().toLowerCase().equals("false")) {
87+
throw new BadValueTypeException("Not a boolean value");
88+
}
7989
}
8090

8191
@Override
@@ -109,12 +119,13 @@ public void run(CliContext context, CommandLine args) {
109119
arguments = Arrays.stream(arguments).filter(o -> !o.trim().isEmpty()).toArray(String[]::new);
110120
this.properties = context.getProperties();
111121

112-
if (this.context.getSettings().getUsername().isPresent()) {
113-
this.context.getAnalyticsFacade().saveAnalytics(this.context.getSettings().getUsername().get(), "config");
114-
} else {
115-
this.context.getAnalyticsFacade().saveAnalytics("config");
122+
if (!this.context.checkIsLoggedIn(false)) {
123+
return;
116124
}
117125

126+
Optional<String> username = this.context.getSettings().getUsername();
127+
this.context.getAnalyticsFacade().saveAnalytics(username.isPresent() ? username.get() : "", "config");
128+
118129
if ((get ? 1 : 0) + (listing ? 1 : 0) + (delete ? 1 : 0) > 1) {
119130
io.errorln("Only one of the --get or --list or --delete options can "
120131
+ "be used at same time.");
@@ -155,12 +166,12 @@ public void run(CliContext context, CommandLine args) {
155166
}
156167

157168
private void printAllProperties() {
158-
ArrayList<String> array = new ArrayList<>(properties.keySet());
159-
Collections.sort(array);
169+
// how to handle that some values are stored in settings and some in properties?
170+
ALLOWED_KEYS.keySet().stream().sorted().forEach(k -> {
171+
String property = properties.get(k);
172+
io.println(k + "=" + (property != null ? property : "<not set>"));
173+
});
160174

161-
for (String key : array) {
162-
io.println(key + "=" + properties.get(key));
163-
}
164175
}
165176

166177
private void deleteProperties(String[] keys) {
@@ -256,13 +267,13 @@ private boolean checkIfAllowedKey(String key) {
256267
if (!ALLOWED_KEYS.keySet().contains(key)) {
257268
io.println("\"" + key + "\" is not an allowed key.");
258269
io.println("Allowed keys are: ");
259-
ALLOWED_KEYS.keySet().stream().forEach(k -> io.print(" " + k + '\n'));
270+
ALLOWED_KEYS.keySet().forEach(k -> io.print(" " + k + '\n'));
260271
return false;
261272
}
262273
return true;
263274
}
264275

265-
private void addToProperties(String key, Object value) throws BadValueTypeException {
276+
private void addBarColorToProperties(String key, Object value) throws BadValueTypeException {
266277
String color = (String) value;
267278
if (!PROGRESS_BAR_COLORS.contains(color)) {
268279
throw new BadValueTypeException("Color " + value + " not supported.");

src/main/java/fi/helsinki/cs/tmc/cli/command/DownloadExercisesCommand.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ public void run(CliContext context, CommandLine args) {
5959
ctx = context;
6060
showAll = args.hasOption("a");
6161

62-
if (!ctx.checkIsLoggedIn()) {
62+
if (!ctx.checkIsLoggedIn(false)) {
6363
return;
6464
}
6565

0 commit comments

Comments
 (0)