Skip to content

Commit 4911903

Browse files
sddiouldeSaliou Diallo
and
Saliou Diallo
authored
[PAY-487] DN - Handle premium track access for track apis (#3783)
* Add has_current_user_unlocked and premium_content_signature to premium tracks in populate_track_metadata * Extract populate premium track metadata method * Add premium content logic to get_single_track flow * Exclude premium tracks from public api latest track * Handle premium track fitler for v1 track routes * Grant premium track access to owner of that track * Handle premium tracks in search api flows * Improve popuplate premium track metadata logic * Filter out premium tracks in public playlist apis * Rename filter_premium to exclude_premium for clarity * Refactor track_dsl with premium filter * Fix lint * Rename premium content constants file * Temporarily comment out premium access check in social features and user library * Fix circular dependency * Fix populate premium track metadata * Fix get_feed_es integration test * Update premium content access checker and handle reposts and saves * Address PR comments * Fix get_feed_es merge issue * Update es track indexer * Filter out premium tracks from feed * Check premium content access for social features * Move social feature functions to social_features.py * Implement premium content access check for one entity * Update tests * Fix tests * Update comment * Move social features premium access check to validation fn * Update generated types for premium content * Update generate_signature use * Exlude premium tracks from recommended tracks Co-authored-by: Saliou Diallo <[email protected]>
1 parent 9171f7b commit 4911903

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

42 files changed

+848
-181
lines changed

discovery-provider/es-indexer/src/indexNames.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,6 @@ export const indexNames = {
22
playlists: 'playlists7',
33
reposts: 'reposts2',
44
saves: 'saves2',
5-
tracks: 'tracks7',
5+
tracks: 'tracks8',
66
users: 'users7',
77
}

discovery-provider/es-indexer/src/indexers/TrackIndexer.ts

+1
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ export class TrackIndexer extends BaseIndexer<TrackDoc> {
6767
mood: { type: 'keyword' },
6868
is_delete: { type: 'boolean' },
6969
is_unlisted: { type: 'boolean' },
70+
is_premium: { type: 'boolean' },
7071
downloadable: { type: 'boolean' },
7172

7273
// saves
Original file line numberDiff line numberDiff line change
@@ -1,80 +1,181 @@
11
from integration_tests.utils import populate_mock_db
2+
from src.models.tracks.track import Track
23
from src.premium_content.premium_content_access_checker import (
34
PremiumContentAccessChecker,
45
)
56
from src.utils.db_session import get_db_read_replica
67

78

8-
def test_track_access(app):
9+
def test_access(app):
10+
non_premium_track_entity = {
11+
"track_id": 1,
12+
"owner_id": 3,
13+
"is_premium": False,
14+
"premium_conditions": None,
15+
}
16+
premium_track_entity_1 = {
17+
"track_id": 2,
18+
"owner_id": 3,
19+
"is_premium": True,
20+
"premium_conditions": {"nft-collection": "some-nft-collection"},
21+
}
22+
premium_track_entity_2 = {
23+
"track_id": 3,
24+
"owner_id": 2,
25+
"is_premium": True,
26+
"premium_conditions": {"nft-collection": "some-nft-collection"},
27+
}
28+
track_entities = [
29+
non_premium_track_entity,
30+
premium_track_entity_1,
31+
premium_track_entity_2,
32+
]
33+
tracks = []
34+
for entity in track_entities:
35+
tracks.append(
36+
Track(
37+
blockhash=hex(0),
38+
blocknumber=0,
39+
txhash=str(0),
40+
track_id=entity.get("track_id"),
41+
owner_id=entity.get("owner_id", 1),
42+
is_premium=entity.get("is_premium", False),
43+
premium_conditions=entity.get("premium_conditions", None),
44+
is_current=True,
45+
is_delete=False,
46+
)
47+
)
48+
49+
premium_content_access_checker = PremiumContentAccessChecker()
50+
51+
# test non-premium content
52+
result = premium_content_access_checker.check_access(
53+
user_id=1,
54+
premium_content_id=non_premium_track_entity["track_id"],
55+
premium_content_type="track",
56+
premium_content_entity=tracks[0],
57+
)
58+
assert not result["is_premium"] and result["does_user_have_access"]
59+
60+
# test premium content with user who has access
61+
result = premium_content_access_checker.check_access(
62+
user_id=2,
63+
premium_content_id=premium_track_entity_1["track_id"],
64+
premium_content_type="track",
65+
premium_content_entity=tracks[1],
66+
)
67+
assert result["is_premium"] and result["does_user_have_access"]
68+
69+
# test premium content with user who owns the track
70+
result = premium_content_access_checker.check_access(
71+
user_id=2,
72+
premium_content_id=premium_track_entity_2["track_id"],
73+
premium_content_type="track",
74+
premium_content_entity=tracks[2],
75+
)
76+
assert result["is_premium"] and result["does_user_have_access"]
77+
78+
# todo: test premium content with user who has no access
79+
# after we implement nft infexing
80+
81+
82+
def test_batch_access(app):
983
with app.app_context():
1084
db = get_db_read_replica()
1185

1286
user_entity_1 = {"user_id": 1}
1387
user_entity_2 = {"user_id": 2}
14-
user_entities = [user_entity_1, user_entity_2]
88+
user_entity_3 = {"user_id": 3}
89+
user_entities = [user_entity_1, user_entity_2, user_entity_3]
90+
91+
non_exisent_track_id = 1
1592

1693
non_premium_track_entity = {
17-
"track_id": 1,
94+
"track_id": 2,
1895
"is_premium": False,
1996
"premium_conditions": None,
2097
}
21-
premium_track_entity = {
22-
"track_id": 2,
98+
premium_track_entity_1 = {
99+
"track_id": 3,
100+
"is_premium": True,
101+
"premium_conditions": {"nft-collection": "some-nft-collection"},
102+
}
103+
premium_track_entity_2 = {
104+
"track_id": 4,
105+
"owner_id": user_entity_3["user_id"],
23106
"is_premium": True,
24107
"premium_conditions": {"nft-collection": "some-nft-collection"},
25108
}
26-
track_entities = [non_premium_track_entity, premium_track_entity]
109+
track_entities = [
110+
non_premium_track_entity,
111+
premium_track_entity_1,
112+
premium_track_entity_2,
113+
]
27114

28115
entities = {"users": user_entities, "tracks": track_entities}
29116

30117
populate_mock_db(db, entities)
31118

32119
premium_content_access_checker = PremiumContentAccessChecker()
33120

34-
non_exisent_track_id = 3
35-
36-
result = premium_content_access_checker.check_access_for_batch(
37-
[
38-
{
39-
"user_id": user_entity_1["user_id"],
40-
"premium_content_id": non_exisent_track_id,
41-
"premium_content_type": "track",
42-
},
43-
{
44-
"user_id": user_entity_2["user_id"],
45-
"premium_content_id": non_premium_track_entity["track_id"],
46-
"premium_content_type": "track",
47-
},
48-
{
49-
"user_id": user_entity_2["user_id"],
50-
"premium_content_id": premium_track_entity["track_id"],
51-
"premium_content_type": "track",
52-
},
53-
]
54-
)
121+
with db.scoped_session() as session:
122+
result = premium_content_access_checker.check_access_for_batch(
123+
session,
124+
[
125+
{
126+
"user_id": user_entity_1["user_id"],
127+
"premium_content_id": non_exisent_track_id,
128+
"premium_content_type": "track",
129+
},
130+
{
131+
"user_id": user_entity_2["user_id"],
132+
"premium_content_id": non_premium_track_entity["track_id"],
133+
"premium_content_type": "track",
134+
},
135+
{
136+
"user_id": user_entity_2["user_id"],
137+
"premium_content_id": premium_track_entity_1["track_id"],
138+
"premium_content_type": "track",
139+
},
140+
{
141+
"user_id": user_entity_3["user_id"],
142+
"premium_content_id": premium_track_entity_2["track_id"],
143+
"premium_content_type": "track",
144+
},
145+
],
146+
)
55147

56-
track_access_result = result["track"]
148+
track_access_result = result["track"]
57149

58-
# test non-existent track
59-
assert user_entity_1["user_id"] not in track_access_result
150+
# test non-existent track
151+
assert user_entity_1["user_id"] not in track_access_result
60152

61-
# test non-premium track
62-
user_2_non_premium_track_access_result = track_access_result[
63-
user_entity_2["user_id"]
64-
][non_premium_track_entity["track_id"]]
65-
assert (
66-
not user_2_non_premium_track_access_result["is_premium"]
67-
and user_2_non_premium_track_access_result["does_user_have_access"]
68-
)
153+
# test non-premium track
154+
user_2_non_premium_track_access_result = track_access_result[
155+
user_entity_2["user_id"]
156+
][non_premium_track_entity["track_id"]]
157+
assert (
158+
not user_2_non_premium_track_access_result["is_premium"]
159+
and user_2_non_premium_track_access_result["does_user_have_access"]
160+
)
69161

70-
# test premium track with user who has access
71-
user_2_premium_track_access_result = track_access_result[
72-
user_entity_2["user_id"]
73-
][premium_track_entity["track_id"]]
74-
assert (
75-
user_2_premium_track_access_result["is_premium"]
76-
and user_2_premium_track_access_result["does_user_have_access"]
77-
)
162+
# test premium track with user who has access
163+
user_2_premium_track_access_result = track_access_result[
164+
user_entity_2["user_id"]
165+
][premium_track_entity_1["track_id"]]
166+
assert (
167+
user_2_premium_track_access_result["is_premium"]
168+
and user_2_premium_track_access_result["does_user_have_access"]
169+
)
170+
171+
# test premium track with user who owns the track
172+
user_3_premium_track_access_result = track_access_result[
173+
user_entity_3["user_id"]
174+
][premium_track_entity_2["track_id"]]
175+
assert (
176+
user_3_premium_track_access_result["is_premium"]
177+
and user_3_premium_track_access_result["does_user_have_access"]
178+
)
78179

79-
# todo: test premium track with user who has no access
80-
# after we implement nft infexing
180+
# todo: test premium track with user who has no access
181+
# after we implement nft infexing

discovery-provider/integration_tests/queries/test_populate_track_metadata.py

+8-4
Original file line numberDiff line numberDiff line change
@@ -54,9 +54,9 @@ def test_populate_track_metadata(app):
5454
with db.scoped_session() as session:
5555
track_ids = [1, 2, 3]
5656
tracks = [
57-
{"track_id": 1},
58-
{"track_id": 2},
59-
{"track_id": 3},
57+
{"track_id": 1, "is_premium": False},
58+
{"track_id": 2, "is_premium": False},
59+
{"track_id": 3, "is_premium": False},
6060
]
6161

6262
tracks = populate_track_metadata(session, track_ids, tracks, None)
@@ -78,7 +78,11 @@ def test_populate_track_metadata(app):
7878
assert tracks[2][response_name_constants.play_count] == 0
7979

8080
curr_track_ids = [1, 2, 3]
81-
curr_tracks = [{"track_id": 1}, {"track_id": 2}, {"track_id": 3}]
81+
curr_tracks = [
82+
{"track_id": 1, "is_premium": False},
83+
{"track_id": 2, "is_premium": False},
84+
{"track_id": 3, "is_premium": False},
85+
]
8286

8387
tracks = populate_track_metadata(session, curr_track_ids, curr_tracks, 1)
8488
assert len(tracks) == 3

discovery-provider/integration_tests/tasks/entity_manager/test_social_feature_entity_manager.py

+2-4
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,6 @@ def get_events_side_effect(_, tx_receipt):
139139
side_effect=get_events_side_effect,
140140
autospec=True,
141141
)
142-
test_metadata = {}
143142

144143
entities = {
145144
"users": [
@@ -163,7 +162,7 @@ def get_events_side_effect(_, tx_receipt):
163162
block_number=1,
164163
block_timestamp=1585336422,
165164
block_hash=0,
166-
ipfs_metadata=test_metadata,
165+
ipfs_metadata={},
167166
)
168167

169168
# Verify follows
@@ -298,7 +297,6 @@ def get_events_side_effect(_, tx_receipt):
298297
side_effect=get_events_side_effect,
299298
autospec=True,
300299
)
301-
test_metadata = {}
302300

303301
entities = {
304302
"users": [
@@ -322,7 +320,7 @@ def get_events_side_effect(_, tx_receipt):
322320
block_number=1,
323321
block_timestamp=1585336422,
324322
block_hash=0,
325-
ipfs_metadata=test_metadata,
323+
ipfs_metadata={},
326324
)
327325

328326
# Verify follows

discovery-provider/integration_tests/tasks/entity_manager/test_track_entity_manager.py

+6
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,8 @@ def get_events_side_effect(_, tx_receipt):
129129
"has_current_user_reposted": False,
130130
"is_current": True,
131131
"is_unlisted": False,
132+
"is_premium": False,
133+
"premium_conditions": None,
132134
"field_visibility": {
133135
"mood": True,
134136
"tags": True,
@@ -171,6 +173,8 @@ def get_events_side_effect(_, tx_receipt):
171173
"has_current_user_reposted": False,
172174
"is_current": True,
173175
"is_unlisted": False,
176+
"is_premium": False,
177+
"premium_conditions": None,
174178
"field_visibility": {
175179
"genre": True,
176180
"mood": True,
@@ -211,6 +215,8 @@ def get_events_side_effect(_, tx_receipt):
211215
"has_current_user_reposted": False,
212216
"is_current": True,
213217
"is_unlisted": False,
218+
"is_premium": False,
219+
"premium_conditions": None,
214220
"field_visibility": {
215221
"mood": True,
216222
"tags": True,

discovery-provider/integration_tests/tasks/test_get_feed_es.py

+7-6
Original file line numberDiff line numberDiff line change
@@ -71,10 +71,11 @@ def test_get_feed_es(app):
7171
assert len(search_res) == 8
7272

7373
# test feed
74-
feed_results = get_feed_es({"user_id": "1"})
75-
assert feed_results[0]["playlist_id"] == 1
76-
assert feed_results[0]["save_count"] == 1
77-
assert len(feed_results[0]["followee_reposts"]) == 1
74+
with app.app_context():
75+
feed_results = get_feed_es({"user_id": "1"})
76+
assert feed_results[0]["playlist_id"] == 1
77+
assert feed_results[0]["save_count"] == 1
78+
assert len(feed_results[0]["followee_reposts"]) == 1
7879

79-
assert feed_results[1]["track_id"] == 1
80-
assert feed_results[1]["save_count"] == 1
80+
assert feed_results[1]["track_id"] == 1
81+
assert feed_results[1]["save_count"] == 1

discovery-provider/src/api/v1/models/tracks.py

+8
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,12 @@
7070
"remixes": fields.Boolean,
7171
},
7272
)
73+
premium_conditions = ns.model(
74+
"premium_conditions",
75+
{
76+
"nft-collection": fields.String,
77+
},
78+
)
7379
track = ns.model(
7480
"Track",
7581
{
@@ -125,6 +131,8 @@
125131
"cover_art": fields.String,
126132
"remix_of": fields.Nested(full_remix_parent),
127133
"is_available": fields.Boolean,
134+
"is_premium": fields.Boolean,
135+
"premium_conditions": fields.Nested(premium_conditions),
128136
},
129137
)
130138

discovery-provider/src/api/v1/playlists.py

+3-2
Original file line numberDiff line numberDiff line change
@@ -86,13 +86,14 @@ def get_playlist(playlist_id, current_user_id):
8686
return None
8787

8888

89-
def get_tracks_for_playlist(playlist_id, current_user_id=None):
89+
def get_tracks_for_playlist(playlist_id, current_user_id=None, exclude_premium=False):
9090
db = get_db_read_replica()
9191
with db.scoped_session() as session:
9292
args = {
9393
"playlist_ids": [playlist_id],
9494
"populate_tracks": True,
9595
"current_user_id": current_user_id,
96+
"exclude_premium": exclude_premium,
9697
}
9798
playlist_tracks_map = get_playlist_tracks(session, args)
9899
playlist_tracks = playlist_tracks_map[playlist_id]
@@ -164,7 +165,7 @@ class PlaylistTracks(Resource):
164165
@cache(ttl_sec=5)
165166
def get(self, playlist_id):
166167
decoded_id = decode_with_abort(playlist_id, ns)
167-
tracks = get_tracks_for_playlist(decoded_id)
168+
tracks = get_tracks_for_playlist(playlist_id=decoded_id, exclude_premium=True)
168169
return success_response(tracks)
169170

170171

0 commit comments

Comments
 (0)