Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[ID-1117] Add fence_account_key and distributed_lock tables to db #174

Merged
merged 14 commits into from
Mar 6, 2024

Conversation

samanehsan
Copy link
Contributor

@samanehsan samanehsan commented Feb 28, 2024

Jira: https://broadworkbench.atlassian.net/browse/ID-1117

What:

  • Add a new fence_account_key table that is equivalent to the one in Bond and a distributed_lock table to store the lock information about fence tokens (or eventually passports).

Why:
The Identiteam is moving Bond's functionality to authenticate with fence account providers into ECM, so ECM needs to store information about fence account keys.

How:

  • Add a new changeset to the liquibase change log.
  • Added corresponding model and DAO classes

Testing:
I ran the ECM server locally and confirmed that the new table was created.

This will be used for Bond providers
@samanehsan samanehsan requested a review from a team as a code owner February 28, 2024 21:47
@samanehsan samanehsan force-pushed the se/ID-1117-add-fence-account-key-table branch from 264ec0a to 73d5f55 Compare February 29, 2024 17:39
@samanehsan samanehsan force-pushed the se/ID-1117-add-fence-account-key-table branch from 73d5f55 to 6c996e9 Compare February 29, 2024 17:51
import org.immutables.value.Value;

@Value.Immutable
public interface DistributedLock {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
public interface DistributedLock {
public interface DistributedLock extends WithDistributedLock {

This, along with ./gradlew assemble, will let you uncomment the builder.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh! I had to add extends WithDistributedLock first and then run ./gradlew assemble in order to generate that interface

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm I'm still getting an error about the builder being final 🤔

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh ./gradlew assemble fixed the error!

import org.immutables.value.Value;

@Value.Immutable
public interface FenceAccountKey {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as above

@samanehsan samanehsan force-pushed the se/ID-1117-add-fence-account-key-table branch from 8ee3aac to 5b99a70 Compare February 29, 2024 21:38
author: sehsan
changes:
- createTable:
tableName: fence_account_key
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we also need a foreign key to the user's linked_account record, so that we can retrieve a user's fence account key by user_id and provider (similar to ga4gh_passport). Does that make sense @tlangs?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That does make sense!

@samanehsan samanehsan changed the title [ID-1117] Add fence_account_key table to db [DRAFT][ID-1117] Add fence_account_key table to db Feb 29, 2024
@samanehsan samanehsan force-pushed the se/ID-1117-add-fence-account-key-table branch from 4a0cebf to d1bef70 Compare February 29, 2024 22:55
Needed to locate a key based on the user and
provider name.
@samanehsan samanehsan force-pushed the se/ID-1117-add-fence-account-key-table branch from d1bef70 to 09c2d11 Compare March 4, 2024 16:42

@Value.Immutable
public interface FenceAccountKey extends WithFenceAccountKey {
Optional<Integer> getId();
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FYI this is optional because when we pass a FenceAccountKey object to insertFenceAccountKey, it won't have an id at that point.

@samanehsan samanehsan changed the title [DRAFT][ID-1117] Add fence_account_key table to db [ID-1117] Add fence_account_key table to db Mar 4, 2024
@samanehsan samanehsan changed the title [ID-1117] Add fence_account_key table to db [ID-1117] Add fence_account_key and distributed_lock tables to db Mar 4, 2024
references: linked_account(id)
foreignKeyName: fk_linked_account_id
- column:
name: key_json
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: maybe this should be called key_json_base64?

Copy link
Contributor

@Ghost-in-a-Jar Ghost-in-a-Jar left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good overall, just some small changes requested

public Optional<DistributedLock> getDistributedLock(String lockName, String userId) {
var namedParameters =
new MapSqlParameterSource().addValue("lockName", lockName).addValue("userId", userId);
var query = "SELECT * FROM distributed_lock WHERE lock_name = :lockName AND user_id = :userId";
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is nitpicky but I think it is best to name each column in a DAO query.

var namedParameters =
new MapSqlParameterSource("userId", userId).addValue("providerName", providerName);
var query =
"SELECT p.* FROM fence_account_key p"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same comment as above I would name each column instead of using *.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

also nitpicky but I would use something more descriptive than 'p' for fence_account_key's alias, maybe 'fence' or 'fak'. Just to make the query easier to read.

var generatedKeyHolder = new GeneratedKeyHolder();
jdbcTemplate.update(query, namedParameters, generatedKeyHolder);

return fenceAccountKey.withId(Objects.requireNonNull(generatedKeyHolder.getKey()).intValue());
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I love that you can get the id back from the insert query, there are limitations on this in scala libs that I have used.

@@ -29,3 +29,6 @@ databaseChangeLog:
- include:
file: changesets/20220412_add_last_encrypt_timestamp_to_ssh_key_pair_table.yaml
relativeToChangelogFile: true
- include:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's a merge conflict here. Make sure this changeset comes after the just-merged changeset.

new FenceAccountKey.Builder()
.id(rs.getInt("id"))
.linkedAccountId(rs.getInt("linked_account_id"))
.keyJson(base64Decode(rs.getString("key_json")))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So, I looked at the Bond code, and its storing the keys as raw json instead of base64. I thought it about it a little bit more, and storing the keys as JSON or JSONB might actually be better, since we could then query into the keys to find info. That may be useful for debugging or analysis.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Apologies for the whiplash...

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No worries! That's a good point about search-ability

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

im confused i thought it was storing the keys as b64?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bond stores them as plain text.

primaryKey: true
nullable: false
- column:
name: linked_account_id
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh! Can we make this cascade on delete? That way, if someone deletes their linked account, the key will automatically get deleted too.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh I assumed that was the default behavior 😅 I'll double check!

}

@WithSpan
public FenceAccountKey insertFenceAccountKey(FenceAccountKey fenceAccountKey) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we rename this upsertFenceAccountKey and do the same ON CONFLICT logic?

Copy link
Contributor Author

@samanehsan samanehsan Mar 6, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it just when there is a conflict on the id and linked_account_id?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah I had to add a unique constraint on the linked_account_id in order to use is as the conflict criteria


String getUserId();

Timestamp getExpiresAt();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should probably use java.time.Instant here instead of the SQL Timestamp.

Copy link

sonarqubecloud bot commented Mar 6, 2024

@samanehsan samanehsan merged commit b54bb7d into dev Mar 6, 2024
10 checks passed
@samanehsan samanehsan deleted the se/ID-1117-add-fence-account-key-table branch March 6, 2024 18:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants