Skip to content

Commit fca96d4

Browse files
authored
Merge pull request #131 from etalab/migration/api-entreprise
Migration/api entreprise
2 parents 0e11cb8 + 07ff017 commit fca96d4

36 files changed

+1288
-52
lines changed

.gitignore

+2
Original file line numberDiff line numberDiff line change
@@ -45,10 +45,12 @@ sandbox
4545
coverage/
4646

4747
app/migration/.pgpassword
48+
app/migration/.ovh.yml
4849
app/migration/dumps/*.csv
4950
app/migration/dumps/*.sql
5051

5152
/config/credentials/staging.key
5253

5354
# Ignore local Redis snapshots
5455
/dump.rdb
56+
app/migration/dumps/data.db

Gemfile

+1
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ gem 'rails-i18n', '~> 7.0.9'
3333
gem 'redis', '>= 4.0.1'
3434
gem 'sentry-ruby'
3535
gem 'sentry-rails'
36+
gem 'sqlite3'
3637
gem 'state_machines-activerecord'
3738
gem 'stimulus-rails'
3839
gem 'turbo-rails'

Gemfile.lock

+4
Original file line numberDiff line numberDiff line change
@@ -533,6 +533,9 @@ GEM
533533
snaky_hash (2.0.1)
534534
hashie
535535
version_gem (~> 1.1, >= 1.1.1)
536+
sqlite3 (1.7.3-aarch64-linux)
537+
sqlite3 (1.7.3-arm64-darwin)
538+
sqlite3 (1.7.3-x86_64-linux)
536539
state_machines (0.6.0)
537540
state_machines-activemodel (0.9.0)
538541
activemodel (>= 6.0)
@@ -647,6 +650,7 @@ DEPENDENCIES
647650
sentry-rails
648651
sentry-ruby
649652
simplecov
653+
sqlite3
650654
state_machines-activerecord
651655
stimulus-rails
652656
turbo-rails

app/decorators/authorization_request_event_decorator.rb

+19-2
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,8 @@ def changelog_builder(diffs)
5757
diffs.map { |attribute, values|
5858
if attribute == 'scopes'
5959
build_scopes_change(values)
60+
elsif attribute == 'applicant_id'
61+
h.content_tag(:li, build_applicant_change(attribute, values))
6062
else
6163
h.content_tag(:li, build_attribute_change(attribute, values))
6264
end
@@ -73,8 +75,8 @@ def changelog_diffs_without_blank_values
7375
end
7476

7577
def build_scopes_change(values)
76-
new_scopes = values[0] - values[1]
77-
removed_scopes = values[1] - values[0]
78+
new_scopes = values[1] - values[0]
79+
removed_scopes = values[0] - values[1]
7880

7981
[
8082
new_scopes.map do |scope|
@@ -111,6 +113,21 @@ def build_attribute_change_with_values(attribute, values)
111113
).html_safe
112114
end
113115

116+
def build_applicant_change(attribute, values)
117+
from_user, to_user = values.map { |id| User.find_by(id:) }
118+
119+
if from_user && to_user
120+
t(
121+
'authorization_request_event.changelog_entry_applicant',
122+
attribute: object.authorization_request.class.human_attribute_name(attribute),
123+
old_value: from_user.email,
124+
new_value: to_user.email,
125+
).html_safe
126+
else
127+
t('authorization_request_event.changelog_entry_applicant_with_missing_data')
128+
end
129+
end
130+
114131
def initial_submit?
115132
object.authorization_request.events.where(name: 'submit').order(created_at: :asc).first == object
116133
end

app/mailers/application_mailer.rb

+2-2
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,11 @@ def extract_host
1212
def current_host
1313
case Rails.env
1414
when 'production'
15-
'https://v2.datapass.api.gouv.fr'
15+
'https://api-entreprise.v2.datapass.api.gouv.fr'
1616
when 'test', 'development'
1717
'http://localhost:3000'
1818
else
19-
"https://#{Rails.env}.v2.datapass.api.gouv.fr"
19+
"https://#{Rails.env}.api-entreprise.v2.datapass.api.gouv.fr"
2020
end
2121
end
2222
end

app/migration/README.md

+13
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@
1212
Executez la commande: `./app/migration/local_import.sh`
1313
Cette commande est idempotent.
1414

15+
Executez la commande: `./app/migration/local_build_db.sh`.
16+
Il faut penser à supprimer la db local si besoin
17+
1518
Pour clean la db locale: `./app/migration/clean_local_db.sh`
1619

1720
Il possible d'effectuer des filtrages sur les données importées (via les options
@@ -29,6 +32,16 @@ situé dans le dossier [`app/migration/import/authorization_requests/`](./import
2932
cela permet de simplifier les traitements. La classe
3033
`Import::AuthorizationRequests` s'occupe des attributs communs.
3134

35+
Pour l'import final il faure les creds d'OVH S3 dans le fichier `.ovh.yml` sous le format suivant:
36+
37+
```yaml
38+
---
39+
OVH_BUCKET: OVH_BUCKET
40+
OVH_ACCESS_KEY_ID: OVH_ACCESS_KEY_ID
41+
OVH_SECRET_ACCESS_KEY: OVH_SECRET_ACCESS_KEY
42+
OVH_REGION: reg
43+
```
44+
3245
### 2.1 Ajout d'un nouveau type d'habilitation.
3346
3447
1. Ajouter le mapping dans `Import::AuthorizationRequests#from_target_api_to_type`

app/migration/alter_sequence_ids.sh

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
#!/bin/bash
2+
3+
bundle exec rails runner "
4+
ActiveRecord::Base.connection.execute(\"select setval('authorization_requests_id_seq', 87000, true);\")
5+
"

app/migration/clean_local_db.sh

-3
This file was deleted.

app/migration/clear_bucket.rb

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
class ClearBucket
2+
def perform
3+
s3_client.list_objects(bucket: bucket_name).contents.each do |object|
4+
s3_client.delete_object(bucket: bucket_name, key: object.key)
5+
end
6+
end
7+
8+
private
9+
10+
def s3_client
11+
@s3_client ||= Aws::S3::Client.new(
12+
endpoint: "https://s3.#{Rails.application.credentials.dig(:ovh_region)}.io.cloud.ovh.net/",
13+
credentials: Aws::Credentials.new(Rails.application.credentials.dig(:ovh_access_key_id), Rails.application.credentials.dig(:ovh_secret_key)),
14+
region: Rails.application.credentials.dig(:ovh_region).downcase,
15+
)
16+
end
17+
18+
def bucket_name
19+
"datapass-v2-#{Rails.env}"
20+
end
21+
end
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
module LocalDatabaseUtils
2+
def database
3+
@database ||= SQLite3::Database.new(db_path)
4+
end
5+
6+
def db_path
7+
Rails.root.join('app', 'migration', 'dumps', 'data.db')
8+
end
9+
end
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
module UserLegacyUtils
2+
extend ActiveSupport::Concern
3+
4+
include LocalDatabaseUtils
5+
6+
def all_legacy_users_id_to_email
7+
@all_legacy_users_id_to_email ||= database.execute('select id, email from users').to_h
8+
end
9+
10+
def all_users_email_to_id
11+
@all_users_email_to_id ||= User.pluck(:email, :id).to_h
12+
end
13+
14+
def legacy_user_id_to_user_id(legacy_id)
15+
all_users_email_to_id[all_legacy_users_id_to_email[legacy_id.to_i]]
16+
end
17+
end
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
class CreateAuthorizationFromSnapshot
2+
include LocalDatabaseUtils
3+
4+
attr_reader :authorization_request, :event_row
5+
6+
def initialize(authorization_request, event_row)
7+
@authorization_request = authorization_request
8+
@event_row = event_row
9+
end
10+
11+
def perform
12+
snapshot = find_closest_snapshot
13+
14+
# XXX Cas où il y a eu une révocation récente (dunno why ?)
15+
if snapshot.blank?
16+
data = authorization_request.data
17+
else
18+
snapshot_items = find_snapshot_items(snapshot)
19+
data = build_data(snapshot_items)
20+
end
21+
22+
authorization = Authorization.create!(
23+
request_id: authorization_request.id,
24+
applicant: authorization_request.applicant,
25+
data: build_data(snapshot_items),
26+
created_at: event_datetime,
27+
)
28+
29+
authorization_request.class.documents.each do |document_identifier|
30+
storage_file_model = authorization_request.public_send(document_identifier)
31+
next if storage_file_model.blank?
32+
33+
document = authorization.documents.create!(
34+
identifier: document_identifier,
35+
)
36+
document.file.attach(storage_file_model.blob)
37+
end
38+
39+
authorization
40+
end
41+
42+
private
43+
44+
def find_closest_snapshot
45+
if event_datetime.to_date <= initial_creation_date
46+
data = database.execute(
47+
'select * from snapshots where enrollment_id = ? order by created_at limit 1',
48+
authorization_request.id,
49+
)
50+
else
51+
data = database.execute(
52+
'select * from snapshots where enrollment_id = ? and date(created_at) = ? order by created_at limit 1',
53+
authorization_request.id,
54+
event_datetime.to_date.to_s,
55+
)
56+
end
57+
58+
return if data.empty?
59+
60+
JSON.parse(data[0][-1]).to_h
61+
end
62+
63+
def find_snapshot_items(snapshot)
64+
database.execute('select * from snapshot_items where snapshot_id = ?', snapshot['id'])
65+
end
66+
67+
# FIXME que 26 raws clairement ça va se faire à la main je pense
68+
def build_data(snapshot_items)
69+
authorization_request.data
70+
end
71+
72+
def event_datetime
73+
@event_datetime ||= DateTime.parse(event_row['created_at'])
74+
end
75+
76+
def initial_creation_date
77+
@initial_creation_date ||= Date.new(2024, 2, 21)
78+
end
79+
end

0 commit comments

Comments
 (0)