-
Notifications
You must be signed in to change notification settings - Fork 44
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #460 from sam-glendenning/mfa-db-migrations
Persistence layer migrations for MFA support #419
- Loading branch information
Showing
13 changed files
with
474 additions
and
8 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
53 changes: 53 additions & 0 deletions
53
...login-service/src/test/java/it/infn/mw/iam/test/repository/IamTotpMfaRepositoryTests.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
/** | ||
* Copyright (c) Istituto Nazionale di Fisica Nucleare (INFN). 2016-2021 | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
package it.infn.mw.iam.test.repository; | ||
|
||
import static org.junit.Assert.assertNotNull; | ||
|
||
import org.junit.Test; | ||
import org.junit.runner.RunWith; | ||
import org.springframework.beans.factory.annotation.Autowired; | ||
import org.springframework.test.context.junit4.SpringRunner; | ||
|
||
import it.infn.mw.iam.persistence.model.IamAccount; | ||
import it.infn.mw.iam.persistence.model.IamTotpMfa; | ||
import it.infn.mw.iam.persistence.repository.IamAccountRepository; | ||
import it.infn.mw.iam.persistence.repository.IamTotpMfaRepository; | ||
import it.infn.mw.iam.test.util.annotation.IamNoMvcTest; | ||
|
||
@RunWith(SpringRunner.class) | ||
@IamNoMvcTest | ||
public class IamTotpMfaRepositoryTests { | ||
|
||
@Autowired | ||
private IamTotpMfaRepository totpMfaRepo; | ||
|
||
@Autowired | ||
private IamAccountRepository accountRepo; | ||
|
||
@Test | ||
public void testAccountIdResolutionWorksAsExpected() { | ||
|
||
IamAccount testAccount = accountRepo.findByUsername("test-with-mfa") | ||
.orElseThrow(() -> new AssertionError("Expected 'test-with-mfa' user not found")); | ||
|
||
IamTotpMfa totpMfa = totpMfaRepo.findByAccount(testAccount) | ||
.orElseThrow(() -> new AssertionError("Expected totp mfa secret not found")); | ||
|
||
assertNotNull(totpMfa); | ||
} | ||
|
||
} |
177 changes: 177 additions & 0 deletions
177
iam-persistence/src/main/java/it/infn/mw/iam/persistence/model/IamTotpMfa.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,177 @@ | ||
/** | ||
* Copyright (c) Istituto Nazionale di Fisica Nucleare (INFN). 2016-2021 | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
package it.infn.mw.iam.persistence.model; | ||
|
||
import java.io.Serializable; | ||
import java.util.Date; | ||
import java.util.HashSet; | ||
import java.util.Set; | ||
|
||
import javax.persistence.CascadeType; | ||
import javax.persistence.Column; | ||
import javax.persistence.Entity; | ||
import javax.persistence.FetchType; | ||
import javax.persistence.GeneratedValue; | ||
import javax.persistence.GenerationType; | ||
import javax.persistence.Id; | ||
import javax.persistence.OneToMany; | ||
import javax.persistence.OneToOne; | ||
import javax.persistence.Table; | ||
import javax.persistence.Temporal; | ||
import javax.persistence.TemporalType; | ||
|
||
@Entity | ||
@Table(name = "iam_totp_mfa") | ||
public class IamTotpMfa implements Serializable { | ||
|
||
private static final long serialVersionUID = 1L; | ||
|
||
@Id | ||
@GeneratedValue(strategy = GenerationType.IDENTITY) | ||
private Long id; | ||
|
||
@OneToOne() | ||
private IamAccount account; | ||
|
||
@Column(name = "secret", nullable = false) | ||
private String secret; | ||
|
||
@Column(name = "active", nullable = false) | ||
private boolean active; | ||
|
||
@Temporal(TemporalType.TIMESTAMP) | ||
@Column(name = "creation_time", nullable = false) | ||
private Date creationTime; | ||
|
||
@Temporal(TemporalType.TIMESTAMP) | ||
@Column(name = "last_update_time", nullable = false) | ||
private Date lastUpdateTime; | ||
|
||
@OneToMany(mappedBy = "totpMfa", cascade = CascadeType.ALL, fetch = FetchType.EAGER, | ||
orphanRemoval = true) | ||
private Set<IamTotpRecoveryCode> recoveryCodes = new HashSet<>(); | ||
|
||
public IamTotpMfa() { | ||
Date now = new Date(); | ||
setCreationTime(now); | ||
setLastUpdateTime(now); | ||
} | ||
|
||
public IamTotpMfa(IamAccount account) { | ||
this.account = account; | ||
Date now = new Date(); | ||
setCreationTime(now); | ||
setLastUpdateTime(now); | ||
} | ||
|
||
public Long getId() { | ||
return id; | ||
} | ||
|
||
public void setId(Long id) { | ||
this.id = id; | ||
} | ||
|
||
public IamAccount getAccount() { | ||
return account; | ||
} | ||
|
||
public void setAccount(final IamAccount account) { | ||
this.account = account; | ||
} | ||
|
||
public String getSecret() { | ||
return secret; | ||
} | ||
|
||
public void setSecret(final String secret) { | ||
this.secret = secret; | ||
} | ||
|
||
public boolean isActive() { | ||
|
||
return active; | ||
} | ||
|
||
public void setActive(final boolean active) { | ||
|
||
this.active = active; | ||
} | ||
|
||
public Date getCreationTime() { | ||
|
||
return creationTime; | ||
} | ||
|
||
public void setCreationTime(final Date creationTime) { | ||
|
||
this.creationTime = creationTime; | ||
} | ||
|
||
public Date getLastUpdateTime() { | ||
|
||
return lastUpdateTime; | ||
} | ||
|
||
public void setLastUpdateTime(final Date lastUpdateTime) { | ||
|
||
this.lastUpdateTime = lastUpdateTime; | ||
} | ||
|
||
public void touch() { | ||
|
||
setLastUpdateTime(new Date()); | ||
} | ||
|
||
public Set<IamTotpRecoveryCode> getRecoveryCodes() { | ||
return recoveryCodes; | ||
} | ||
|
||
public void setRecoveryCodes(final Set<IamTotpRecoveryCode> recoveryCodes) { | ||
this.recoveryCodes.clear(); | ||
this.recoveryCodes.addAll(recoveryCodes); | ||
} | ||
|
||
@Override | ||
public String toString() { | ||
return "IamTotpMfa [active=" + active + ", id=" + id + ", secret=" + secret + "]"; | ||
} | ||
|
||
@Override | ||
public int hashCode() { | ||
final int prime = 31; | ||
int result = 1; | ||
result = prime * result + ((secret == null) ? 0 : secret.hashCode()); | ||
return result; | ||
} | ||
|
||
@Override | ||
public boolean equals(Object obj) { | ||
if (this == obj) | ||
return true; | ||
if (obj == null) | ||
return false; | ||
if (getClass() != obj.getClass()) | ||
return false; | ||
IamTotpMfa other = (IamTotpMfa) obj; | ||
if (secret == null) { | ||
if (other.secret != null) | ||
return false; | ||
} else if (!secret.equals(other.secret)) | ||
return false; | ||
return true; | ||
} | ||
} |
118 changes: 118 additions & 0 deletions
118
iam-persistence/src/main/java/it/infn/mw/iam/persistence/model/IamTotpRecoveryCode.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,118 @@ | ||
/** | ||
* Copyright (c) Istituto Nazionale di Fisica Nucleare (INFN). 2016-2021 | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
package it.infn.mw.iam.persistence.model; | ||
|
||
import java.io.Serializable; | ||
|
||
import javax.persistence.Column; | ||
import javax.persistence.Entity; | ||
import javax.persistence.FetchType; | ||
import javax.persistence.GeneratedValue; | ||
import javax.persistence.GenerationType; | ||
import javax.persistence.Id; | ||
import javax.persistence.JoinColumn; | ||
import javax.persistence.ManyToOne; | ||
import javax.persistence.Table; | ||
|
||
@Entity | ||
@Table(name = "iam_totp_recovery_code") | ||
public class IamTotpRecoveryCode implements Serializable { | ||
|
||
private static final long serialVersionUID = 1L; | ||
|
||
@Id | ||
@GeneratedValue(strategy = GenerationType.IDENTITY) | ||
private Long id; | ||
|
||
@Column(name = "code") | ||
private String code; | ||
|
||
@ManyToOne(fetch = FetchType.EAGER) | ||
@JoinColumn(referencedColumnName = "id", nullable = false, name = "totp_mfa_id") | ||
private IamTotpMfa totpMfa; | ||
|
||
public IamTotpRecoveryCode() {} | ||
|
||
public IamTotpRecoveryCode(IamTotpMfa totpMfa) { | ||
this.totpMfa = totpMfa; | ||
} | ||
|
||
public Long getId() { | ||
return id; | ||
} | ||
|
||
public void setId(Long id) { | ||
this.id = id; | ||
} | ||
|
||
public IamTotpMfa getTotpMfa() { | ||
return totpMfa; | ||
} | ||
|
||
public void setTotpMfa(final IamTotpMfa totpMfa) { | ||
this.totpMfa = totpMfa; | ||
} | ||
|
||
public String getCode() { | ||
return code; | ||
} | ||
|
||
public void setCode(final String code) { | ||
this.code = code; | ||
} | ||
|
||
@Override | ||
public String toString() { | ||
return "IamTotpRecoveryCode [code=" + code + ", id=" + id + "]"; | ||
} | ||
|
||
@Override | ||
public int hashCode() { | ||
final int prime = 31; | ||
int result = 1; | ||
result = prime * result + ((code == null) ? 0 : code.hashCode()); | ||
result = prime * result + ((id == null) ? 0 : id.hashCode()); | ||
result = prime * result + ((totpMfa == null) ? 0 : totpMfa.hashCode()); | ||
return result; | ||
} | ||
|
||
@Override | ||
public boolean equals(Object obj) { | ||
if (this == obj) | ||
return true; | ||
if (obj == null) | ||
return false; | ||
if (getClass() != obj.getClass()) | ||
return false; | ||
IamTotpRecoveryCode other = (IamTotpRecoveryCode) obj; | ||
if (code == null) { | ||
if (other.code != null) | ||
return false; | ||
} else if (!code.equals(other.code)) | ||
return false; | ||
if (id == null) { | ||
if (other.id != null) | ||
return false; | ||
} else if (!id.equals(other.id)) | ||
return false; | ||
if (totpMfa == null) { | ||
if (other.totpMfa != null) | ||
return false; | ||
} else if (!totpMfa.equals(other.totpMfa)) | ||
return false; | ||
return true; | ||
} | ||
} |
Oops, something went wrong.