diff --git a/Mage.Client/src/main/java/mage/client/dialog/RegisterUserDialog.form b/Mage.Client/src/main/java/mage/client/dialog/RegisterUserDialog.form
index 5f99dece42..1b343dc991 100644
--- a/Mage.Client/src/main/java/mage/client/dialog/RegisterUserDialog.form
+++ b/Mage.Client/src/main/java/mage/client/dialog/RegisterUserDialog.form
@@ -24,36 +24,39 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
+
-
+
@@ -80,14 +83,26 @@
-
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
-
+
@@ -157,5 +172,48 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Mage.Client/src/main/java/mage/client/dialog/RegisterUserDialog.java b/Mage.Client/src/main/java/mage/client/dialog/RegisterUserDialog.java
index 38d0756820..e6e989da65 100644
--- a/Mage.Client/src/main/java/mage/client/dialog/RegisterUserDialog.java
+++ b/Mage.Client/src/main/java/mage/client/dialog/RegisterUserDialog.java
@@ -56,6 +56,12 @@ public class RegisterUserDialog extends MageDialog {
lblStatus = new javax.swing.JLabel();
txtServer = new javax.swing.JTextField();
txtPort = new javax.swing.JTextField();
+ txtEmail = new javax.swing.JTextField();
+ lblPasswordConfirmation = new javax.swing.JLabel();
+ txtPasswordConfirmation = new javax.swing.JPasswordField();
+ lblEmail = new javax.swing.JLabel();
+ lblPasswordConfirmationReasoning = new javax.swing.JLabel();
+ lblEmailReasoning = new javax.swing.JLabel();
setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
setTitle("Register");
@@ -94,34 +100,53 @@ public class RegisterUserDialog extends MageDialog {
lblStatus.setToolTipText("");
+ lblPasswordConfirmation.setLabelFor(txtPasswordConfirmation);
+ lblPasswordConfirmation.setText("Password:");
+
+ lblEmail.setLabelFor(txtEmail);
+ lblEmail.setText("Email:");
+
+ lblPasswordConfirmationReasoning.setFont(new java.awt.Font("Lucida Grande", 0, 10)); // NOI18N
+ lblPasswordConfirmationReasoning.setLabelFor(txtPasswordConfirmation);
+ lblPasswordConfirmationReasoning.setText("(confirmation)");
+
+ lblEmailReasoning.setFont(new java.awt.Font("Lucida Grande", 0, 10)); // NOI18N
+ lblEmailReasoning.setLabelFor(txtEmail);
+ lblEmailReasoning.setText("(used for password reset)");
+ lblEmailReasoning.setToolTipText("");
+
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
getContentPane().setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
- .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
- .addGroup(layout.createSequentialGroup()
- .addGap(14, 14, 14)
- .addComponent(lblUserName))
- .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
- .addContainerGap()
- .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
- .addComponent(lblPassword, javax.swing.GroupLayout.Alignment.TRAILING)
- .addComponent(lblPort, javax.swing.GroupLayout.Alignment.TRAILING)
- .addComponent(lblServer, javax.swing.GroupLayout.Alignment.TRAILING))))
- .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
- .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
- .addComponent(lblStatus, javax.swing.GroupLayout.PREFERRED_SIZE, 292, javax.swing.GroupLayout.PREFERRED_SIZE)
- .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false)
+ .addContainerGap()
+ .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
+ .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
+ .addComponent(lblPasswordConfirmationReasoning)
+ .addGroup(layout.createSequentialGroup()
+ .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
+ .addComponent(lblServer)
+ .addComponent(lblUserName)
+ .addComponent(lblPort)
+ .addComponent(lblPassword)
+ .addComponent(lblPasswordConfirmation)
+ .addComponent(lblEmail))
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addComponent(txtServer, javax.swing.GroupLayout.PREFERRED_SIZE, 292, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addComponent(txtPort, javax.swing.GroupLayout.PREFERRED_SIZE, 292, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addComponent(txtUserName, javax.swing.GroupLayout.PREFERRED_SIZE, 292, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addComponent(txtPassword, javax.swing.GroupLayout.PREFERRED_SIZE, 292, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addComponent(txtPasswordConfirmation, javax.swing.GroupLayout.PREFERRED_SIZE, 292, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addComponent(txtEmail, javax.swing.GroupLayout.PREFERRED_SIZE, 292, javax.swing.GroupLayout.PREFERRED_SIZE)))
+ .addComponent(lblEmailReasoning)
.addGroup(layout.createSequentialGroup()
.addComponent(btnRegister)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
- .addComponent(btnCancel))
- .addComponent(txtUserName, javax.swing.GroupLayout.Alignment.LEADING)
- .addComponent(txtPassword, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, 292, Short.MAX_VALUE)
- .addComponent(txtServer, javax.swing.GroupLayout.Alignment.LEADING))
- .addComponent(txtPort, javax.swing.GroupLayout.PREFERRED_SIZE, 292, javax.swing.GroupLayout.PREFERRED_SIZE))
- .addContainerGap(16, Short.MAX_VALUE))
+ .addComponent(btnCancel)))
+ .addComponent(lblStatus, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
+ .addContainerGap(22, Short.MAX_VALUE))
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
@@ -142,13 +167,24 @@ public class RegisterUserDialog extends MageDialog {
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(lblPassword)
.addComponent(txtPassword, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
- .addGap(18, 18, 18)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
+ .addComponent(txtPasswordConfirmation, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addComponent(lblPasswordConfirmation))
+ .addComponent(lblPasswordConfirmationReasoning)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
+ .addComponent(lblEmail)
+ .addComponent(txtEmail, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addComponent(lblEmailReasoning)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(lblStatus, javax.swing.GroupLayout.PREFERRED_SIZE, 28, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
- .addComponent(btnRegister)
- .addComponent(btnCancel))
- .addContainerGap(14, Short.MAX_VALUE))
+ .addComponent(btnCancel)
+ .addComponent(btnRegister))
+ .addContainerGap())
);
pack();
@@ -163,11 +199,16 @@ public class RegisterUserDialog extends MageDialog {
}//GEN-LAST:event_btnCancelActionPerformed
private void btnRegisterActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnRegisterActionPerformed
+ if (!this.txtPassword.getText().equals(this.txtPasswordConfirmation.getText())) {
+ MageFrame.getInstance().showError("Passwords don't match.");
+ return;
+ }
connection = new Connection();
connection.setHost(this.txtServer.getText().trim());
connection.setPort(Integer.valueOf(this.txtPort.getText().trim()));
connection.setUsername(this.txtUserName.getText().trim());
connection.setPassword(this.txtPassword.getText().trim());
+ connection.setEmail(this.txtEmail.getText().trim());
PreferencesDialog.setProxyInformation(connection);
task = new ConnectTask();
task.execute();
@@ -218,12 +259,18 @@ public class RegisterUserDialog extends MageDialog {
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JButton btnCancel;
private javax.swing.JButton btnRegister;
+ private javax.swing.JLabel lblEmail;
+ private javax.swing.JLabel lblEmailReasoning;
private javax.swing.JLabel lblPassword;
+ private javax.swing.JLabel lblPasswordConfirmation;
+ private javax.swing.JLabel lblPasswordConfirmationReasoning;
private javax.swing.JLabel lblPort;
private javax.swing.JLabel lblServer;
private javax.swing.JLabel lblStatus;
private javax.swing.JLabel lblUserName;
+ private javax.swing.JTextField txtEmail;
private javax.swing.JPasswordField txtPassword;
+ private javax.swing.JPasswordField txtPasswordConfirmation;
private javax.swing.JTextField txtPort;
private javax.swing.JTextField txtServer;
private javax.swing.JTextField txtUserName;
diff --git a/Mage.Common/src/mage/remote/Connection.java b/Mage.Common/src/mage/remote/Connection.java
index 4b68eb2560..818ef0b46f 100644
--- a/Mage.Common/src/mage/remote/Connection.java
+++ b/Mage.Common/src/mage/remote/Connection.java
@@ -45,6 +45,7 @@ public class Connection {
private int port;
private String username;
private String password;
+ private String email;
private String adminPassword;
private ProxyType proxyType;
private String proxyHost;
@@ -173,6 +174,14 @@ public class Connection {
this.password = password;
}
+ public String getEmail() {
+ return email;
+ }
+
+ public void setEmail(String email) {
+ this.email = email;
+ }
+
public String getAdminPassword() {
return adminPassword;
}
diff --git a/Mage.Common/src/mage/remote/SessionImpl.java b/Mage.Common/src/mage/remote/SessionImpl.java
index ddc6b99d87..5a5d393218 100644
--- a/Mage.Common/src/mage/remote/SessionImpl.java
+++ b/Mage.Common/src/mage/remote/SessionImpl.java
@@ -195,7 +195,7 @@ public class SessionImpl implements Session {
public boolean run() throws Throwable {
logger.info("Trying to register as " + getUserName() + " to XMAGE server at " + connection.getHost() + ":" + connection.getPort());
boolean registerResult = server.registerUser(sessionId, connection.getUsername(),
- connection.getPassword(), "");
+ connection.getPassword(), connection.getEmail());
if (registerResult) {
logger.info("Registered as " + getUserName() + " to MAGE server at " + connection.getHost() + ":" + connection.getPort());
}
diff --git a/Mage.Server/config/config.xml b/Mage.Server/config/config.xml
index e2f7d4b11a..4070d1a7ea 100644
--- a/Mage.Server/config/config.xml
+++ b/Mage.Server/config/config.xml
@@ -35,6 +35,8 @@
userNamePattern="[^a-z0-9_]"
maxAiOpponents="15"
saveGameActivated="false"
+ authenticationActivated="false"
+ googleAccount=""
/>
diff --git a/Mage.Server/pom.xml b/Mage.Server/pom.xml
index 80916da83e..a46f67e394 100644
--- a/Mage.Server/pom.xml
+++ b/Mage.Server/pom.xml
@@ -154,6 +154,36 @@
1.2.4
jar
+
+ com.google.api-client
+ google-api-client
+ 1.21.0
+ jar
+
+
+ com.google.apis
+ google-api-services-gmail
+ v1-rev35-1.21.0
+ jar
+
+
+ com.google.oauth-client
+ google-oauth-client-java6
+ 1.19.0
+ jar
+
+
+ com.google.oauth-client
+ google-oauth-client-jetty
+ 1.19.0
+ jar
+
+
+ javax.mail
+ mail
+ 1.4.2
+ jar
+
diff --git a/Mage.Server/src/main/java/mage/server/GmailClient.java b/Mage.Server/src/main/java/mage/server/GmailClient.java
new file mode 100644
index 0000000000..45ef28225b
--- /dev/null
+++ b/Mage.Server/src/main/java/mage/server/GmailClient.java
@@ -0,0 +1,86 @@
+package mage.server;
+
+import com.google.api.client.auth.oauth2.Credential;
+import com.google.api.client.extensions.java6.auth.oauth2.AuthorizationCodeInstalledApp;
+import com.google.api.client.extensions.jetty.auth.oauth2.LocalServerReceiver;
+import com.google.api.client.googleapis.auth.oauth2.GoogleAuthorizationCodeFlow;
+import com.google.api.client.googleapis.auth.oauth2.GoogleClientSecrets;
+import com.google.api.client.googleapis.javanet.GoogleNetHttpTransport;
+import com.google.api.client.http.HttpTransport;
+import com.google.api.client.json.JsonFactory;
+import com.google.api.client.json.jackson2.JacksonFactory;
+import com.google.api.client.util.Base64;
+import com.google.api.client.util.store.FileDataStoreFactory;
+import com.google.api.services.gmail.Gmail;
+import com.google.api.services.gmail.Gmail.Builder;
+import com.google.api.services.gmail.GmailScopes;
+import com.google.api.services.gmail.model.Message;
+import java.io.ByteArrayOutputStream;
+import java.io.FileReader;
+import java.io.IOException;
+import javax.mail.Session;
+import java.security.GeneralSecurityException;
+import java.util.Collections;
+import java.util.Properties;
+import javax.mail.MessagingException;
+import javax.mail.internet.InternetAddress;
+import javax.mail.internet.MimeMessage;
+import mage.server.util.ConfigSettings;
+import org.apache.log4j.Logger;
+
+public class GmailClient {
+
+ private static final Logger logger = Logger.getLogger(Main.class);
+ private static final JsonFactory JSON_FACTORY = JacksonFactory.getDefaultInstance();
+ private static final java.io.File DATA_STORE_DIR = new java.io.File(System.getProperty("user.home"), ".store/xmage");
+ private static FileDataStoreFactory dataStoreFactory;
+ private static HttpTransport httpTransport;
+ private static Credential credential;
+
+ public static boolean initilize() {
+ try {
+ dataStoreFactory = new FileDataStoreFactory(DATA_STORE_DIR);
+ httpTransport = GoogleNetHttpTransport.newTrustedTransport();
+
+ GoogleClientSecrets clientSecrets = GoogleClientSecrets.load(JSON_FACTORY, new FileReader("client_secrets.json"));
+ if (clientSecrets.getDetails().getClientId().startsWith("Enter")
+ || clientSecrets.getDetails().getClientSecret().startsWith("Enter ")) {
+ logger.error("client_secrets.json not found");
+ return false;
+ }
+
+ GoogleAuthorizationCodeFlow flow = new GoogleAuthorizationCodeFlow.Builder(
+ httpTransport, JSON_FACTORY, clientSecrets,
+ Collections.singleton(GmailScopes.GMAIL_COMPOSE)).setDataStoreFactory(
+ dataStoreFactory).build();
+
+ credential = new AuthorizationCodeInstalledApp(flow, new LocalServerReceiver()).authorize("user");
+ return true;
+ } catch (IOException | GeneralSecurityException ex) {
+ logger.error("Error initializing GmailClient", ex);
+ }
+ return false;
+ }
+
+ public static boolean sendMessage(String email, String subject, String text) {
+ try {
+ Gmail gmail = new Builder(httpTransport, JSON_FACTORY, credential).setApplicationName("XMage Server").build();
+
+ MimeMessage mimeMessage = new MimeMessage(Session.getDefaultInstance(new Properties()));
+ mimeMessage.addRecipient(javax.mail.Message.RecipientType.TO, new InternetAddress(email));
+ mimeMessage.setSubject(subject);
+ mimeMessage.setText(text);
+
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ mimeMessage.writeTo(baos);
+ Message message = new Message();
+ message.setRaw(Base64.encodeBase64URLSafeString(baos.toByteArray()));
+
+ gmail.users().messages().send(ConfigSettings.getInstance().getGoogleAccount() + "@gmail.com", message).execute();
+ return true;
+ } catch (MessagingException | IOException ex) {
+ logger.error("Error sending message", ex);
+ }
+ return false;
+ }
+}
diff --git a/Mage.Server/src/main/java/mage/server/Main.java b/Mage.Server/src/main/java/mage/server/Main.java
index 7e83044274..781eb01281 100644
--- a/Mage.Server/src/main/java/mage/server/Main.java
+++ b/Mage.Server/src/main/java/mage/server/Main.java
@@ -107,7 +107,18 @@ public class Main {
fastDbMode = Boolean.valueOf(arg.replace(fastDBModeArg, ""));
}
}
-
+
+ ConfigSettings config = ConfigSettings.getInstance();
+ if (config.isAuthenticationActivated()) {
+ logger.info("Initializing GmailClient. This will open up a tab in your browser to ask for an OAuth access token.");
+ if (GmailClient.initilize()) {
+ logger.info("GmailClient initilized successfully.");
+ } else {
+ logger.fatal("GmailClient initialization failed.");
+ return;
+ }
+ }
+
logger.info("Loading cards...");
if (fastDbMode) {
CardScanner.scanned = true;
@@ -117,7 +128,6 @@ public class Main {
logger.info("Done.");
deleteSavedGames();
- ConfigSettings config = ConfigSettings.getInstance();
for (GamePlugin plugin: config.getGameTypes()) {
GameFactory.getInstance().addGameType(plugin.getName(), loadGameType(plugin), loadPlugin(plugin));
}
diff --git a/Mage.Server/src/main/java/mage/server/Session.java b/Mage.Server/src/main/java/mage/server/Session.java
index d57d710fc9..9bddf546bd 100644
--- a/Mage.Server/src/main/java/mage/server/Session.java
+++ b/Mage.Server/src/main/java/mage/server/Session.java
@@ -87,6 +87,12 @@ public class Session {
return returnMessage;
}
AuthorizedUserRepository.instance.add(userName, password, email);
+ if (GmailClient.sendMessage(email, "XMage Registration Completed",
+ "You are successfully registered as " + userName + ".")) {
+ logger.info("Sent a registration confirmation email to " + email + " for " + userName);
+ } else {
+ logger.error("Failed sending a registration confirmation email to " + email + " for " + userName);
+ }
return null;
}
}
diff --git a/Mage.Server/src/main/java/mage/server/util/ConfigSettings.java b/Mage.Server/src/main/java/mage/server/util/ConfigSettings.java
index cee5d5bdee..c85f97c257 100644
--- a/Mage.Server/src/main/java/mage/server/util/ConfigSettings.java
+++ b/Mage.Server/src/main/java/mage/server/util/ConfigSettings.java
@@ -94,7 +94,7 @@ public class ConfigSettings {
public int getBacklogSize() {
return config.getServer().getBacklogSize().intValue();
}
-
+
public int getMaxGameThreads() {
return config.getServer().getMaxGameThreads().intValue();
}
@@ -114,14 +114,22 @@ public class ConfigSettings {
public String getUserNamePattern() {
return config.getServer().getUserNamePattern();
}
-
+
public String getMaxAiOpponents() {
return config.getServer().getMaxAiOpponents();
}
public Boolean isSaveGameActivated() {
- return config.getServer().isSaveGameActivated();
-}
+ return config.getServer().isSaveGameActivated();
+ }
+
+ public Boolean isAuthenticationActivated() {
+ return config.getServer().isAuthenticationActivated();
+ }
+
+ public String getGoogleAccount() {
+ return config.getServer().getGoogleAccount();
+ }
public List getPlayerTypes() {
return config.getPlayerTypes().getPlayerType();
diff --git a/Mage.Server/src/main/xml-resources/jaxb/Config/Config.xsd b/Mage.Server/src/main/xml-resources/jaxb/Config/Config.xsd
index 8e57894338..25adcc1e0e 100644
--- a/Mage.Server/src/main/xml-resources/jaxb/Config/Config.xsd
+++ b/Mage.Server/src/main/xml-resources/jaxb/Config/Config.xsd
@@ -2,19 +2,19 @@
-
+
-
+
-
+
@@ -22,16 +22,18 @@
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
@@ -56,7 +58,7 @@
-
+