feat: track oauth new-user result

This commit is contained in:
Tim
2025-08-18 01:11:16 +08:00
parent 923854bbc6
commit 62d12ad2a7
20 changed files with 315 additions and 64 deletions

View File

@@ -29,6 +29,7 @@ public class AuthController {
private final RegisterModeService registerModeService;
private final NotificationService notificationService;
private final UserRepository userRepository;
private final InviteService inviteService;
@Value("${app.captcha.enabled:false}")
@@ -45,6 +46,25 @@ public class AuthController {
if (captchaEnabled && registerCaptchaEnabled && !captchaService.verify(req.getCaptcha())) {
return ResponseEntity.badRequest().body(Map.of("error", "Invalid captcha"));
}
if (req.getInviteToken() != null && !req.getInviteToken().isEmpty()) {
if (!inviteService.validate(req.getInviteToken())) {
return ResponseEntity.badRequest().body(Map.of("error", "Invalid invite token"));
}
try {
User user = userService.registerWithInvite(
req.getUsername(), req.getEmail(), req.getPassword());
inviteService.consume(req.getInviteToken());
return ResponseEntity.ok(Map.of(
"token", jwtService.generateToken(user.getUsername()),
"reason_code", "INVITE_APPROVED"
));
} catch (FieldException e) {
return ResponseEntity.badRequest().body(Map.of(
"field", e.getField(),
"error", e.getMessage()
));
}
}
User user = userService.register(
req.getUsername(), req.getEmail(), req.getPassword(), "", registerModeService.getRegisterMode());
emailService.sendEmail(user.getEmail(), "在网站填写验证码以验证", "您的验证码是 " + user.getVerificationCode());
@@ -106,27 +126,42 @@ public class AuthController {
@PostMapping("/google")
public ResponseEntity<?> loginWithGoogle(@RequestBody GoogleLoginRequest req) {
Optional<User> user = googleAuthService.authenticate(req.getIdToken(), registerModeService.getRegisterMode());
if (user.isPresent()) {
if (RegisterMode.DIRECT.equals(registerModeService.getRegisterMode())) {
return ResponseEntity.ok(Map.of("token", jwtService.generateToken(user.get().getUsername())));
boolean viaInvite = req.getInviteToken() != null && !req.getInviteToken().isEmpty();
if (viaInvite && !inviteService.validate(req.getInviteToken())) {
return ResponseEntity.badRequest().body(Map.of("error", "Invalid invite token"));
}
Optional<AuthResult> resultOpt = googleAuthService.authenticate(
req.getIdToken(),
registerModeService.getRegisterMode(),
viaInvite);
if (resultOpt.isPresent()) {
AuthResult result = resultOpt.get();
if (viaInvite && result.isNewUser()) {
inviteService.consume(req.getInviteToken());
return ResponseEntity.ok(Map.of(
"token", jwtService.generateToken(result.getUser().getUsername()),
"reason_code", "INVITE_APPROVED"
));
}
if (!user.get().isApproved()) {
if (user.get().getRegisterReason() != null && !user.get().getRegisterReason().isEmpty()) {
if (RegisterMode.DIRECT.equals(registerModeService.getRegisterMode())) {
return ResponseEntity.ok(Map.of("token", jwtService.generateToken(result.getUser().getUsername())));
}
if (!result.getUser().isApproved()) {
if (result.getUser().getRegisterReason() != null && !result.getUser().getRegisterReason().isEmpty()) {
return ResponseEntity.badRequest().body(Map.of(
"error", "Account awaiting approval",
"reason_code", "IS_APPROVING",
"token", jwtService.generateReasonToken(user.get().getUsername())
"token", jwtService.generateReasonToken(result.getUser().getUsername())
));
}
return ResponseEntity.badRequest().body(Map.of(
"error", "Account awaiting approval",
"reason_code", "NOT_APPROVED",
"token", jwtService.generateReasonToken(user.get().getUsername())
"token", jwtService.generateReasonToken(result.getUser().getUsername())
));
}
return ResponseEntity.ok(Map.of("token", jwtService.generateToken(user.get().getUsername())));
return ResponseEntity.ok(Map.of("token", jwtService.generateToken(result.getUser().getUsername())));
}
return ResponseEntity.badRequest().body(Map.of(
"error", "Invalid google token",
@@ -165,28 +200,44 @@ public class AuthController {
@PostMapping("/github")
public ResponseEntity<?> loginWithGithub(@RequestBody GithubLoginRequest req) {
Optional<User> user = githubAuthService.authenticate(req.getCode(), registerModeService.getRegisterMode(), req.getRedirectUri());
if (user.isPresent()) {
if (RegisterMode.DIRECT.equals(registerModeService.getRegisterMode())) {
return ResponseEntity.ok(Map.of("token", jwtService.generateToken(user.get().getUsername())));
boolean viaInvite = req.getInviteToken() != null && !req.getInviteToken().isEmpty();
if (viaInvite && !inviteService.validate(req.getInviteToken())) {
return ResponseEntity.badRequest().body(Map.of("error", "Invalid invite token"));
}
Optional<AuthResult> resultOpt = githubAuthService.authenticate(
req.getCode(),
registerModeService.getRegisterMode(),
req.getRedirectUri(),
viaInvite);
if (resultOpt.isPresent()) {
AuthResult result = resultOpt.get();
if (viaInvite && result.isNewUser()) {
inviteService.consume(req.getInviteToken());
return ResponseEntity.ok(Map.of(
"token", jwtService.generateToken(result.getUser().getUsername()),
"reason_code", "INVITE_APPROVED"
));
}
if (!user.get().isApproved()) {
if (user.get().getRegisterReason() != null && !user.get().getRegisterReason().isEmpty()) {
if (RegisterMode.DIRECT.equals(registerModeService.getRegisterMode())) {
return ResponseEntity.ok(Map.of("token", jwtService.generateToken(result.getUser().getUsername())));
}
if (!result.getUser().isApproved()) {
if (result.getUser().getRegisterReason() != null && !result.getUser().getRegisterReason().isEmpty()) {
// 已填写注册理由
return ResponseEntity.badRequest().body(Map.of(
"error", "Account awaiting approval",
"reason_code", "IS_APPROVING",
"token", jwtService.generateReasonToken(user.get().getUsername())
"token", jwtService.generateReasonToken(result.getUser().getUsername())
));
}
return ResponseEntity.badRequest().body(Map.of(
"error", "Account awaiting approval",
"reason_code", "NOT_APPROVED",
"token", jwtService.generateReasonToken(user.get().getUsername())
"token", jwtService.generateReasonToken(result.getUser().getUsername())
));
}
return ResponseEntity.ok(Map.of("token", jwtService.generateToken(user.get().getUsername())));
return ResponseEntity.ok(Map.of("token", jwtService.generateToken(result.getUser().getUsername())));
}
return ResponseEntity.badRequest().body(Map.of(
"error", "Invalid github code",
@@ -196,27 +247,43 @@ public class AuthController {
@PostMapping("/discord")
public ResponseEntity<?> loginWithDiscord(@RequestBody DiscordLoginRequest req) {
Optional<User> user = discordAuthService.authenticate(req.getCode(), registerModeService.getRegisterMode(), req.getRedirectUri());
if (user.isPresent()) {
if (RegisterMode.DIRECT.equals(registerModeService.getRegisterMode())) {
return ResponseEntity.ok(Map.of("token", jwtService.generateToken(user.get().getUsername())));
boolean viaInvite = req.getInviteToken() != null && !req.getInviteToken().isEmpty();
if (viaInvite && !inviteService.validate(req.getInviteToken())) {
return ResponseEntity.badRequest().body(Map.of("error", "Invalid invite token"));
}
Optional<AuthResult> resultOpt = discordAuthService.authenticate(
req.getCode(),
registerModeService.getRegisterMode(),
req.getRedirectUri(),
viaInvite);
if (resultOpt.isPresent()) {
AuthResult result = resultOpt.get();
if (viaInvite && result.isNewUser()) {
inviteService.consume(req.getInviteToken());
return ResponseEntity.ok(Map.of(
"token", jwtService.generateToken(result.getUser().getUsername()),
"reason_code", "INVITE_APPROVED"
));
}
if (!user.get().isApproved()) {
if (user.get().getRegisterReason() != null && !user.get().getRegisterReason().isEmpty()) {
if (RegisterMode.DIRECT.equals(registerModeService.getRegisterMode())) {
return ResponseEntity.ok(Map.of("token", jwtService.generateToken(result.getUser().getUsername())));
}
if (!result.getUser().isApproved()) {
if (result.getUser().getRegisterReason() != null && !result.getUser().getRegisterReason().isEmpty()) {
return ResponseEntity.badRequest().body(Map.of(
"error", "Account awaiting approval",
"reason_code", "IS_APPROVING",
"token", jwtService.generateReasonToken(user.get().getUsername())
"token", jwtService.generateReasonToken(result.getUser().getUsername())
));
}
return ResponseEntity.badRequest().body(Map.of(
"error", "Account awaiting approval",
"reason_code", "NOT_APPROVED",
"token", jwtService.generateReasonToken(user.get().getUsername())
"token", jwtService.generateReasonToken(result.getUser().getUsername())
));
}
return ResponseEntity.ok(Map.of("token", jwtService.generateToken(user.get().getUsername())));
return ResponseEntity.ok(Map.of("token", jwtService.generateToken(result.getUser().getUsername())));
}
return ResponseEntity.badRequest().body(Map.of(
"error", "Invalid discord code",
@@ -226,31 +293,44 @@ public class AuthController {
@PostMapping("/twitter")
public ResponseEntity<?> loginWithTwitter(@RequestBody TwitterLoginRequest req) {
Optional<User> user = twitterAuthService.authenticate(
boolean viaInvite = req.getInviteToken() != null && !req.getInviteToken().isEmpty();
if (viaInvite && !inviteService.validate(req.getInviteToken())) {
return ResponseEntity.badRequest().body(Map.of("error", "Invalid invite token"));
}
Optional<AuthResult> resultOpt = twitterAuthService.authenticate(
req.getCode(),
req.getCodeVerifier(),
registerModeService.getRegisterMode(),
req.getRedirectUri());
if (user.isPresent()) {
if (RegisterMode.DIRECT.equals(registerModeService.getRegisterMode())) {
return ResponseEntity.ok(Map.of("token", jwtService.generateToken(user.get().getUsername())));
req.getRedirectUri(),
viaInvite);
if (resultOpt.isPresent()) {
AuthResult result = resultOpt.get();
if (viaInvite && result.isNewUser()) {
inviteService.consume(req.getInviteToken());
return ResponseEntity.ok(Map.of(
"token", jwtService.generateToken(result.getUser().getUsername()),
"reason_code", "INVITE_APPROVED"
));
}
if (!user.get().isApproved()) {
if (user.get().getRegisterReason() != null && !user.get().getRegisterReason().isEmpty()) {
if (RegisterMode.DIRECT.equals(registerModeService.getRegisterMode())) {
return ResponseEntity.ok(Map.of("token", jwtService.generateToken(result.getUser().getUsername())));
}
if (!result.getUser().isApproved()) {
if (result.getUser().getRegisterReason() != null && !result.getUser().getRegisterReason().isEmpty()) {
return ResponseEntity.badRequest().body(Map.of(
"error", "Account awaiting approval",
"reason_code", "IS_APPROVING",
"token", jwtService.generateReasonToken(user.get().getUsername())
"token", jwtService.generateReasonToken(result.getUser().getUsername())
));
}
return ResponseEntity.badRequest().body(Map.of(
"error", "Account awaiting approval",
"reason_code", "NOT_APPROVED",
"token", jwtService.generateReasonToken(user.get().getUsername())
"token", jwtService.generateReasonToken(result.getUser().getUsername())
));
}
return ResponseEntity.ok(Map.of("token", jwtService.generateToken(user.get().getUsername())));
return ResponseEntity.ok(Map.of("token", jwtService.generateToken(result.getUser().getUsername())));
}
return ResponseEntity.badRequest().body(Map.of(
"error", "Invalid twitter code",

View File

@@ -0,0 +1,23 @@
package com.openisle.controller;
import com.openisle.service.InviteService;
import lombok.RequiredArgsConstructor;
import org.springframework.security.core.Authentication;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.Map;
@RestController
@RequestMapping("/api/invite")
@RequiredArgsConstructor
public class InviteController {
private final InviteService inviteService;
@PostMapping("/generate")
public Map<String, String> generate(Authentication auth) {
String token = inviteService.generate(auth.getName());
return Map.of("token", token);
}
}

View File

@@ -7,4 +7,5 @@ import lombok.Data;
public class DiscordLoginRequest {
private String code;
private String redirectUri;
private String inviteToken;
}

View File

@@ -7,4 +7,5 @@ import lombok.Data;
public class GithubLoginRequest {
private String code;
private String redirectUri;
private String inviteToken;
}

View File

@@ -6,4 +6,5 @@ import lombok.Data;
@Data
public class GoogleLoginRequest {
private String idToken;
private String inviteToken;
}

View File

@@ -9,4 +9,5 @@ public class RegisterRequest {
private String email;
private String password;
private String captcha;
private String inviteToken;
}

View File

@@ -8,4 +8,5 @@ public class TwitterLoginRequest {
private String code;
private String redirectUri;
private String codeVerifier;
private String inviteToken;
}

View File

@@ -0,0 +1,23 @@
package com.openisle.model;
import jakarta.persistence.*;
import lombok.Data;
import java.time.LocalDate;
/**
* Invite token entity tracking usage counts.
*/
@Data
@Entity
public class InviteToken {
@Id
private String token;
@ManyToOne
private User inviter;
private LocalDate createdDate;
private int usageCount;
}

View File

@@ -0,0 +1,12 @@
package com.openisle.repository;
import com.openisle.model.InviteToken;
import com.openisle.model.User;
import org.springframework.data.jpa.repository.JpaRepository;
import java.time.LocalDate;
import java.util.Optional;
public interface InviteTokenRepository extends JpaRepository<InviteToken, String> {
Optional<InviteToken> findByInviterAndCreatedDate(User inviter, LocalDate createdDate);
}

View File

@@ -0,0 +1,12 @@
package com.openisle.service;
import com.openisle.model.User;
import lombok.Value;
/** Result for OAuth authentication indicating whether a new user was created. */
@Value
public class AuthResult {
User user;
boolean newUser;
}

View File

@@ -26,7 +26,7 @@ public class DiscordAuthService {
@Value("${discord.client-secret:}")
private String clientSecret;
public Optional<User> authenticate(String code, com.openisle.model.RegisterMode mode, String redirectUri) {
public Optional<AuthResult> authenticate(String code, com.openisle.model.RegisterMode mode, String redirectUri, boolean viaInvite) {
try {
String tokenUrl = "https://discord.com/api/oauth2/token";
HttpHeaders headers = new HttpHeaders();
@@ -67,13 +67,13 @@ public class DiscordAuthService {
if (email == null) {
email = (username != null ? username : id) + "@users.noreply.discord.com";
}
return Optional.of(processUser(email, username, avatar, mode));
return Optional.of(processUser(email, username, avatar, mode, viaInvite));
} catch (Exception e) {
return Optional.empty();
}
}
private User processUser(String email, String username, String avatar, com.openisle.model.RegisterMode mode) {
private AuthResult processUser(String email, String username, String avatar, com.openisle.model.RegisterMode mode, boolean viaInvite) {
Optional<User> existing = userRepository.findByEmail(email);
if (existing.isPresent()) {
User user = existing.get();
@@ -82,7 +82,7 @@ public class DiscordAuthService {
user.setVerificationCode(null);
userRepository.save(user);
}
return user;
return new AuthResult(user, false);
}
String baseUsername = username != null ? username : email.split("@")[0];
String finalUsername = baseUsername;
@@ -96,12 +96,12 @@ public class DiscordAuthService {
user.setPassword("");
user.setRole(Role.USER);
user.setVerified(true);
user.setApproved(mode == com.openisle.model.RegisterMode.DIRECT);
user.setApproved(mode == com.openisle.model.RegisterMode.DIRECT || viaInvite);
if (avatar != null) {
user.setAvatar(avatar);
} else {
user.setAvatar("https://cdn.discordapp.com/embed/avatars/0.png");
}
return userRepository.save(user);
return new AuthResult(userRepository.save(user), true);
}
}

View File

@@ -30,7 +30,7 @@ public class GithubAuthService {
@Value("${github.client-secret:}")
private String clientSecret;
public Optional<User> authenticate(String code, com.openisle.model.RegisterMode mode, String redirectUri) {
public Optional<AuthResult> authenticate(String code, com.openisle.model.RegisterMode mode, String redirectUri, boolean viaInvite) {
try {
String tokenUrl = "https://github.com/login/oauth/access_token";
HttpHeaders headers = new HttpHeaders();
@@ -86,13 +86,13 @@ public class GithubAuthService {
if (email == null) {
email = username + "@users.noreply.github.com";
}
return Optional.of(processUser(email, username, avatarUrl, mode));
return Optional.of(processUser(email, username, avatarUrl, mode, viaInvite));
} catch (Exception e) {
return Optional.empty();
}
}
private User processUser(String email, String username, String avatar, com.openisle.model.RegisterMode mode) {
private AuthResult processUser(String email, String username, String avatar, com.openisle.model.RegisterMode mode, boolean viaInvite) {
Optional<User> existing = userRepository.findByEmail(email);
if (existing.isPresent()) {
User user = existing.get();
@@ -101,7 +101,7 @@ public class GithubAuthService {
user.setVerificationCode(null);
userRepository.save(user);
}
return user;
return new AuthResult(user, false);
}
String baseUsername = username != null ? username : email.split("@")[0];
String finalUsername = baseUsername;
@@ -115,12 +115,12 @@ public class GithubAuthService {
user.setPassword("");
user.setRole(Role.USER);
user.setVerified(true);
user.setApproved(mode == com.openisle.model.RegisterMode.DIRECT);
user.setApproved(mode == com.openisle.model.RegisterMode.DIRECT || viaInvite);
if (avatar != null) {
user.setAvatar(avatar);
} else {
user.setAvatar(avatarGenerator.generate(finalUsername));
}
return userRepository.save(user);
return new AuthResult(userRepository.save(user), true);
}
}

View File

@@ -25,7 +25,7 @@ public class GoogleAuthService {
@Value("${google.client-id:}")
private String clientId;
public Optional<User> authenticate(String idTokenString, com.openisle.model.RegisterMode mode) {
public Optional<AuthResult> authenticate(String idTokenString, com.openisle.model.RegisterMode mode, boolean viaInvite) {
GoogleIdTokenVerifier verifier = new GoogleIdTokenVerifier.Builder(new NetHttpTransport(), new JacksonFactory())
.setAudience(Collections.singletonList(clientId))
.build();
@@ -38,13 +38,13 @@ public class GoogleAuthService {
String email = payload.getEmail();
String name = (String) payload.get("name");
String picture = (String) payload.get("picture");
return Optional.of(processUser(email, name, picture, mode));
return Optional.of(processUser(email, name, picture, mode, viaInvite));
} catch (Exception e) {
return Optional.empty();
}
}
private User processUser(String email, String name, String avatar, com.openisle.model.RegisterMode mode) {
private AuthResult processUser(String email, String name, String avatar, com.openisle.model.RegisterMode mode, boolean viaInvite) {
Optional<User> existing = userRepository.findByEmail(email);
if (existing.isPresent()) {
User user = existing.get();
@@ -53,8 +53,7 @@ public class GoogleAuthService {
user.setVerificationCode(null);
userRepository.save(user);
}
return user;
return new AuthResult(user, false);
}
User user = new User();
String baseUsername = email.split("@")[0];
@@ -68,12 +67,12 @@ public class GoogleAuthService {
user.setPassword("");
user.setRole(Role.USER);
user.setVerified(true);
user.setApproved(mode == com.openisle.model.RegisterMode.DIRECT);
user.setApproved(mode == com.openisle.model.RegisterMode.DIRECT || viaInvite);
if (avatar != null) {
user.setAvatar(avatar);
} else {
user.setAvatar(avatarGenerator.generate(username));
}
return userRepository.save(user);
return new AuthResult(userRepository.save(user), true);
}
}

View File

@@ -0,0 +1,54 @@
package com.openisle.service;
import com.openisle.model.InviteToken;
import com.openisle.model.User;
import com.openisle.repository.InviteTokenRepository;
import com.openisle.repository.UserRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import java.time.LocalDate;
import java.util.Optional;
@Service
@RequiredArgsConstructor
public class InviteService {
private final InviteTokenRepository inviteTokenRepository;
private final UserRepository userRepository;
private final JwtService jwtService;
private final PointService pointService;
public String generate(String username) {
User inviter = userRepository.findByUsername(username).orElseThrow();
LocalDate today = LocalDate.now();
Optional<InviteToken> existing = inviteTokenRepository.findByInviterAndCreatedDate(inviter, today);
if (existing.isPresent()) {
return existing.get().getToken();
}
String token = jwtService.generateInviteToken(username);
InviteToken inviteToken = new InviteToken();
inviteToken.setToken(token);
inviteToken.setInviter(inviter);
inviteToken.setCreatedDate(today);
inviteToken.setUsageCount(0);
inviteTokenRepository.save(inviteToken);
return token;
}
public boolean validate(String token) {
try {
jwtService.validateAndGetSubjectForInvite(token);
} catch (Exception e) {
return false;
}
InviteToken invite = inviteTokenRepository.findById(token).orElse(null);
return invite != null && invite.getUsageCount() < 3;
}
public void consume(String token) {
InviteToken invite = inviteTokenRepository.findById(token).orElseThrow();
invite.setUsageCount(invite.getUsageCount() + 1);
inviteTokenRepository.save(invite);
pointService.awardForInvite(invite.getInviter().getUsername());
}
}

View File

@@ -24,6 +24,9 @@ public class JwtService {
@Value("${app.jwt.reset-secret}")
private String resetSecret;
@Value("${app.jwt.invite-secret}")
private String inviteSecret;
@Value("${app.jwt.expiration}")
private long expiration;
@@ -70,6 +73,17 @@ public class JwtService {
.compact();
}
public String generateInviteToken(String subject) {
Date now = new Date();
Date expiryDate = new Date(now.getTime() + expiration);
return Jwts.builder()
.setSubject(subject)
.setIssuedAt(now)
.setExpiration(expiryDate)
.signWith(getSigningKeyForSecret(inviteSecret))
.compact();
}
public String validateAndGetSubject(String token) {
Claims claims = Jwts.parserBuilder()
.setSigningKey(getSigningKeyForSecret(secret))
@@ -96,4 +110,13 @@ public class JwtService {
.getBody();
return claims.getSubject();
}
public String validateAndGetSubjectForInvite(String token) {
Claims claims = Jwts.parserBuilder()
.setSigningKey(getSigningKeyForSecret(inviteSecret))
.build()
.parseClaimsJws(token)
.getBody();
return claims.getSubject();
}
}

View File

@@ -26,6 +26,11 @@ public class PointService {
return addPoint(user, 30);
}
public int awardForInvite(String userName) {
User user = userRepository.findByUsername(userName).orElseThrow();
return addPoint(user, 500);
}
private PointLog getTodayLog(User user) {
LocalDate today = LocalDate.now();
return pointLogRepository.findByUserAndLogDate(user, today)

View File

@@ -33,11 +33,12 @@ public class TwitterAuthService {
@Value("${twitter.client-secret:}")
private String clientSecret;
public Optional<User> authenticate(
public Optional<AuthResult> authenticate(
String code,
String codeVerifier,
RegisterMode mode,
String redirectUri) {
String redirectUri,
boolean viaInvite) {
logger.debug("Starting authentication with code {} and verifier {}", code, codeVerifier);
@@ -106,10 +107,10 @@ public class TwitterAuthService {
// Twitter v2 默认拿不到 email如果你申请到 email.scope可改用 /2/users/:id?user.fields=email
String email = username + "@twitter.com";
logger.debug("Processing user {} with email {}", username, email);
return Optional.of(processUser(email, username, avatar, mode));
return Optional.of(processUser(email, username, avatar, mode, viaInvite));
}
private User processUser(String email, String username, String avatar, com.openisle.model.RegisterMode mode) {
private AuthResult processUser(String email, String username, String avatar, com.openisle.model.RegisterMode mode, boolean viaInvite) {
Optional<User> existing = userRepository.findByEmail(email);
if (existing.isPresent()) {
User user = existing.get();
@@ -119,7 +120,7 @@ public class TwitterAuthService {
userRepository.save(user);
}
logger.debug("Existing user {} authenticated", user.getUsername());
return user;
return new AuthResult(user, false);
}
String baseUsername = username != null ? username : email.split("@")[0];
String finalUsername = baseUsername;
@@ -133,13 +134,13 @@ public class TwitterAuthService {
user.setPassword("");
user.setRole(Role.USER);
user.setVerified(true);
user.setApproved(mode == com.openisle.model.RegisterMode.DIRECT);
user.setApproved(mode == com.openisle.model.RegisterMode.DIRECT || viaInvite);
if (avatar != null) {
user.setAvatar(avatar);
} else {
user.setAvatar("https://twitter.com/" + finalUsername + "/profile_image");
}
logger.debug("Creating new user {}", finalUsername);
return userRepository.save(user);
return new AuthResult(userRepository.save(user), true);
}
}

View File

@@ -74,6 +74,13 @@ public class UserService {
return userRepository.save(user);
}
public User registerWithInvite(String username, String email, String password) {
User user = register(username, email, password, "", com.openisle.model.RegisterMode.DIRECT);
user.setVerified(true);
user.setVerificationCode(null);
return userRepository.save(user);
}
private String genCode() {
return String.format("%06d", new Random().nextInt(1000000));
}