-
-
Notifications
You must be signed in to change notification settings - Fork 184
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
[Feature] Transfer project ownership #4743
Merged
noliveleger
merged 162 commits into
release/2.024.09
from
feature/transfer-project-ownership
Mar 22, 2024
Merged
Changes from all commits
Commits
Show all changes
162 commits
Select commit
Hold shift + click to select a range
d7e92cd
WIP new button on share page
duvld afcaba2
WIP django app
noliveleger b942c12
Merge branch 'feature/transfer-project-ownership' of github.com:kobot…
noliveleger 5ea4928
Remove useless print
noliveleger 6ef6680
Get rid of deployment backend identifier
noliveleger f143937
Updates to transfer section
duvld 78e3303
Merge branch 'feature/transfer-project-ownership' of https://github.c…
duvld 599d63f
WIP modal almost done
duvld 2f4dd77
Transfer project synchronously and submissions asynchronously
noliveleger ff408f9
Status update mechanism
noliveleger 3359894
Cleaning
noliveleger a166997
Handle S3 not found file
noliveleger c8fe296
Refactor status mechanism
noliveleger a02eddf
Fix mongo rewrite
noliveleger 92f5b6d
Add background tasks
noliveleger 72e8907
Use shadow model to move KC media files
noliveleger 2e6e682
Fix typos for scheduled tasks
noliveleger b30cbf1
Merge branch 'feature/transfer-project-ownership' of github.com:kobot…
noliveleger c8e8e80
WIP transfer invite modal added
duvld bbed7a1
Merge branch 'feature/transfer-project-ownership' of https://github.c…
duvld ffd7f55
Update viewset and serializer
noliveleger 91ceb08
Merge branch 'feature/transfer-project-ownership' of github.com:kobot…
noliveleger dbbde26
Improve viewsets and serializers
noliveleger 004ea19
Rename fields
noliveleger 2955af0
Rename attachments on the file
noliveleger b7e464f
Fix KC permissions on transfer
noliveleger 630da82
Merge app urls with main appurls - (fix namespace issues)
noliveleger 8b91bbf
Add constance variable to auto accept invites
noliveleger f0df842
Use constance variable in serializer, fix namespaced reverse calls
noliveleger 42a6490
Merge branch 'beta' into feature/transfer-project-ownership
noliveleger 3550aac
Merge routers
noliveleger 10109f8
Merge branch 'feature/transfer-project-ownership' of https://github.c…
duvld 270fbbd
Merge branch 'feature/transfer-project-ownership' of https://github.c…
duvld c82ba95
Remove useless try/except
noliveleger c10d348
Add open_rosa_url to environment endpoint
noliveleger 66d5aa2
Add comment for JS change
noliveleger 71f5d58
Merge branch 'feature/transfer-project-ownership' of https://github.c…
duvld 10579aa
removed check for deployment__identifier in DATA tab
duvld da319af
Fix crash when submissions as not attachments
noliveleger 4969001
Provide project ownership info in asset serializer
noliveleger 05fb0f5
API doc
noliveleger 87ac176
Make "/transfers" a nested endpoint
noliveleger fe020ea
Merge branch 'beta' into feature/transfer-project-ownership
noliveleger 3682fd5
Fix asset endpoint error
noliveleger 9faa9cf
Merge branch 'beta' into feature/transfer-project-ownership
noliveleger 7709d91
Optimize relationship querysets
noliveleger e0660af
WIP hooking up api
06b353d
Sent in-app messages to users with whom transfer project is shared
noliveleger fcf6105
Merge branch 'feature/transfer-project-ownership' of github.com:kobot…
noliveleger ae34af7
Allow re-invite after cancellation
noliveleger 4879193
Fix file mispelled
noliveleger 79fd5f2
Send/cancel in sharing page
duvld d416953
Improve validation error message with bulk transfer
noliveleger 1fd4e80
Merge branch 'feature/transfer-project-ownership' of github.com:kobot…
noliveleger d71063d
Update initial form layout and styling
jamesrkiger 9d4f6b4
Update modal layout
jamesrkiger d1b1318
Remove function
jamesrkiger 70968c3
*WIP* frontend check for proper invite
906528e
*WIP* invite checking fixes
9c8ca8a
Invite expire, new mailer utility
noliveleger 3dd0b3c
Avoid sending empty emails
noliveleger fbd8129
Send emails: new, declined, expired
noliveleger 2cf77b7
Merge branch 'feature/transfer-project-ownership' of github.com:kobot…
noliveleger 5fc74dd
do not send in-app messages to old and new owner
noliveleger ce094c5
Allow expired invite to be resent
noliveleger 5c0ba62
Email: Add Accepted invite, fix text typos
noliveleger 0e218a9
Add forgotten templates
noliveleger 415d5aa
Handle single project transfer in templates
noliveleger 8d0e2f5
Add invitation acceptance modal styling
jamesrkiger 4eea34f
Fix header color
jamesrkiger f292f6a
Merge branch 'feature/transfer-project-ownership' into transfer-proje…
jamesrkiger 2d1238e
Merge branch 'beta' into feature/transfer-project-ownership
noliveleger 2ab55c8
Fix wrong default value with constance
noliveleger 1f2e087
Handle bad requests, improve username input ui
jamesrkiger 54f072d
Send failure reports to admin
noliveleger 2ffcfac
Unit tests skeleton
noliveleger 1ec7e41
Fix unit tests with api v2 namespace
noliveleger 16f48ae
APi v2 structure
noliveleger f2c0154
Merge branch 'require-auth-at-project-level' into feature/transfer-pr…
noliveleger af28b99
Fix merge conflict
noliveleger 6d8e32e
Merge branch 'feature/transfer-project-ownership' into transfer-proje…
duvld e7a9d4d
Merge pull request #4773 from kobotoolbox/transfer-project-ownership-…
duvld a3f3af9
Fix 500 on create invite
noliveleger e0c39d0
Review periodic tasks
noliveleger 2f48dc7
Add missing documentation
noliveleger 4b2f35e
Draft - Unit tests
noliveleger a8c0557
Merge branch 'feature/transfer-project-ownership' of github.com:kobot…
noliveleger c379675
Fix bad copy/paste in API doc
noliveleger aaa1db1
Update unit tests
noliveleger 1ebcad4
Accepting/Declining invite and WIP {name} replace
duvld c81feed
Add sender and asset__name to API response
noliveleger 086403d
Merge branch 'feature/transfer-project-ownership' of https://github.c…
duvld c8d32c5
Bugfixes
noliveleger 805b33e
Python 3.8 annotations bugfix
noliveleger 3e1f7b2
Update unit tests
noliveleger 59cce48
Add FIXME, and fix typos
noliveleger d96a473
Invite expiry threshold fix
noliveleger 222a71b
Merge branch 'feature/transfer-project-ownership' into catch-invalid-…
jamesrkiger 3a59567
Show pending ownership for users with existing permissions
jamesrkiger 40d2f3d
Add row for users without permissions
jamesrkiger 56b28ad
String interpolation for project and invite recipient names.
jamesrkiger ce5474f
Merge pull request #4777 from kobotoolbox/catch-invalid-username
duvld 3bf93e6
Added some error handling, needs to be cleaned up
721ae97
Use permissions row component
jamesrkiger a8803e3
Merge pull request #4785 from kobotoolbox/show-perms-row-pending-owne…
duvld c73e801
Add unit tests, some broken
jamesrkiger ad5f43d
Merge branch 'feature/transfer-project-ownership' of github.com:kobot…
jamesrkiger 782146c
Skip broken tests
jamesrkiger 4db27b9
Fix in-app-messages being sent to everyone
jamesrkiger 158e277
Added banners for accepting/declining invites
82eab70
Merge branch 'feature/transfer-project-ownership' of https://github.c…
c62d641
Add some working email tests
jamesrkiger d90d915
Merge branch 'feature/transfer-project-ownership' of github.com:kobot…
jamesrkiger cb60d4b
Fix test/email recipient
jamesrkiger c08fa65
Finish email tests
jamesrkiger 28e3b5b
Frontend check for self transfer, improves warning
c0a5e42
Disable FF autocomplete
jamesrkiger e61dcf8
Linting
jamesrkiger d150e37
Same as 8a945e. Fixed unabled to remove all perms
9d54ec8
Link 'Learn more' to sharing permissions article
f766e69
Fix scoping of anonymousSubmission CSS
bda7a8d
Linting - 80 chars max
noliveleger e6a8e8f
Cancel invites on asset deletion
noliveleger ac6215e
Merge branch 'feature/transfer-project-ownership' of github.com:kobot…
noliveleger 6420f3a
WIP test service usage on transfer
noliveleger 62f0dd6
Merge branch 'require-auth-at-project-level' into feature/transfer-pr…
noliveleger 2d90a7c
Use django_redis instead of redis client
noliveleger b33198b
Merge branch 'beta' into feature/transfer-project-ownership
noliveleger b26b3a1
Fix bad merge
noliveleger 5526981
Remove search params on accept/decline invite and add loading state
jamesrkiger f90534f
Add unit tests for data transfer
noliveleger 6188be9
Merge branch 'feature/transfer-project-ownership' of github.com:kobot…
noliveleger 33b36d4
Add unit test for ExtendedFileField.move() method
noliveleger 05ee69a
Merge branch 'beta' into feature/transfer-project-ownership
noliveleger acf23f2
Fix bad merge
noliveleger c0c2dc8
Delete temporary files in ExtendedFileField.move() unit test
noliveleger ddd6482
Fix move file with local storage
noliveleger 6fee370
Move soft deleted attachments as well
noliveleger fc749ce
Merge branch 'release/2.024.04' into feature/transfer-project-ownership
noliveleger d164d3f
Do not use kobocat ref in basedeploymentbackend
noliveleger 97fa9ad
Fix unit tests after merge conflicts
noliveleger 2d4b092
Fix duplicate CSS from merge
duvld ed74342
Merge branch 'feature/transfer-project-ownership' of https://github.c…
duvld 470c452
Fix forgotten property decorator
noliveleger 4bac4cf
Merge branch 'release/2.024.05' into feature/transfer-project-ownership
noliveleger 224b158
Merge branch 'release/2.024.05' into feature/transfer-project-ownership
noliveleger c02e6bd
Remove "- KoboToolbox" from in-app message
noliveleger c552481
Merge branch 'release/2.024.07' into feature/transfer-project-ownership
noliveleger 4697bd8
Merge branch 'release/2.024.07' into feature/transfer-project-ownership
noliveleger ff0c698
Most PR changes. TODO: better translation strings
duvld b397e5f
Merge branch 'feature/transfer-project-ownership' of https://github.c…
duvld b42b862
Merge branch 'release/2.024.07' into feature/transfer-project-ownership
noliveleger 00b28ee
Merge branch 'feature/transfer-project-ownership' of github.com:kobot…
noliveleger f021dcd
Move test_question_xpaths logic to API unit test
noliveleger c7bd54f
Merge branch 'refactor-counter-shadow-models' into feature/transfer-p…
noliveleger 0637f2c
Merge branch 'refactor-api-v2-urls' into feature/transfer-project-own…
noliveleger e3ed7ff
Merge branch 'lint-format-pre-transfer-project-ownership' into featur…
noliveleger 4ca0037
Pr changes: translation string & organizing files
duvld 582806d
Add missing refactored folder, new comment for inv
duvld 76d21ef
Merge branch 'release/2.024.09' into feature/transfer-project-ownership
duvld 9e239d7
Apply requested changes for PR#4743
noliveleger 834ec51
Fix draft project transfers
noliveleger File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
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
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
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
203 changes: 203 additions & 0 deletions
203
jsapp/js/components/permissions/transferProjects/transferProjects.api.ts
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,203 @@ | ||
import {FailResponse, PaginatedResponse} from 'js/dataInterface'; | ||
import {fetchGet, fetchPost, fetchPatch} from 'jsapp/js/api'; | ||
import sessionStore from 'js/stores/session'; | ||
import {buildUserUrl, getUsernameFromUrl} from 'js/users/utils'; | ||
import {notify} from 'js/utils'; | ||
import {handleApiFail} from 'js/api'; | ||
|
||
const INVITE_URL = '/api/v2/project-ownership/invites/'; | ||
|
||
/** | ||
* The status of a project transfer. | ||
*/ | ||
export enum TransferStatuses { | ||
/**Sender sent the invite but recipient hasn't responded yet.*/ | ||
Pending = 'pending', | ||
/**Sender sent the invite but cancelled it before the recipient could respond.*/ | ||
Cancelled = 'cancelled', | ||
/**Recipient has declined the invite.*/ | ||
Declined = 'declined', | ||
/**Recipient has accepted the invite but transfer process has not started yet*/ | ||
Accepted = 'accepted', | ||
/**Recipient has accepted and the transfer process has begun.*/ | ||
InProgress = 'in_progress', | ||
/**Recipient has accepted and transfer has completed successfully.*/ | ||
Complete = 'complete', | ||
/**Recipient has accepted and process went south.*/ | ||
Failed = 'failed', | ||
} | ||
|
||
/**Detail about a single asset's transfer. This is listed in the invite detail.*/ | ||
export interface ProjectTransfer { | ||
url: string; | ||
asset: string; | ||
asset__name: string; | ||
status: TransferStatuses; | ||
error: any; | ||
date_modified: string; | ||
} | ||
|
||
/**Detail about current asset's transfer. This is listed in the asset detail.*/ | ||
export interface ProjectTransferAssetDetail { | ||
invite: string; | ||
sender: string; | ||
recipient: string; | ||
status: TransferStatuses; | ||
} | ||
|
||
export interface InvitesResponse { | ||
url: string; | ||
sender: string; | ||
recipient: string; | ||
status: TransferStatuses; | ||
date_created: string; | ||
date_modified: string; | ||
/** | ||
* Backend is written such that invites can have multiple | ||
* projects per transfer. This is not supported by the UI right now. | ||
*/ | ||
transfers: ProjectTransfer[]; | ||
} | ||
|
||
export async function sendInvite(username: string, assetUid: string) { | ||
return fetchPost<InvitesResponse>(INVITE_URL, { | ||
recipient: buildUserUrl(username), | ||
assets: [assetUid], | ||
}); | ||
} | ||
|
||
// Note: the following invite actions are seperated to make it clearer when using in | ||
// the JSX code. | ||
|
||
export async function cancelInvite(inviteUrl: string) { | ||
let response; | ||
try { | ||
response = await fetchPatch<InvitesResponse>( | ||
inviteUrl, | ||
{ | ||
status: TransferStatuses.Cancelled, | ||
}, | ||
{prependRootUrl: false, notifyAboutError: false} | ||
); | ||
} catch (error) { | ||
handleApiFail( | ||
error as FailResponse, | ||
t( | ||
'Failed to cancel transfer. The transfer may be declined or accpeted already. Please check your email.' | ||
) | ||
); | ||
} | ||
|
||
return response; | ||
} | ||
|
||
export async function acceptInvite(inviteUid: string) { | ||
let response; | ||
try { | ||
response = await fetchPatch<InvitesResponse>( | ||
INVITE_URL + inviteUid + '/', | ||
{ | ||
status: TransferStatuses.Accepted, | ||
}, | ||
{prependRootUrl: false, notifyAboutError: false} | ||
); | ||
} catch (error) { | ||
handleApiFail( | ||
error as FailResponse, | ||
t( | ||
'Failed to accept invite.' | ||
) | ||
); | ||
} | ||
|
||
return response; | ||
} | ||
|
||
export async function declineInvite(inviteUid: string) { | ||
let response; | ||
try { | ||
response = await fetchPatch<InvitesResponse>( | ||
INVITE_URL + inviteUid + '/', | ||
{ | ||
status: TransferStatuses.Declined, | ||
}, | ||
{prependRootUrl: false, notifyAboutError: false} | ||
); | ||
} catch (error) { | ||
handleApiFail( | ||
error as FailResponse, | ||
t( | ||
'Failed to decline invite' | ||
) | ||
); | ||
} | ||
return response; | ||
} | ||
|
||
/**Returns *all invites* the current user sent or recieved.*/ | ||
export async function getAllInvites() { | ||
let invites; | ||
try { | ||
invites = await fetchGet<PaginatedResponse<InvitesResponse>>(INVITE_URL, {notifyAboutError: false}); | ||
} catch (error) { | ||
handleApiFail( | ||
error as FailResponse, | ||
); | ||
} | ||
|
||
return invites; | ||
} | ||
|
||
/** | ||
* Returns detail for a single invite. | ||
* | ||
* Note: backend is written such that invites can have multiple | ||
* projects per transfer. This is not supported by the UI right now. | ||
*/ | ||
export async function getInviteDetail(inviteUid: string) { | ||
return fetchGet<InvitesResponse>(INVITE_URL + inviteUid, {notifyAboutError: false}); | ||
} | ||
|
||
/** Check if the invite is meant for the currently logged in user. */ | ||
export async function isInviteForLoggedInUser(inviteUid: string) { | ||
let inviteIsCorrect = false; | ||
try { | ||
await getInviteDetail(inviteUid).then((data) => { | ||
// Only bother with the check if it's in the `pending` state. | ||
if (data.status !== TransferStatuses.Pending) { | ||
notify.warning(t('Invite has been cancelled or expired')); | ||
return; | ||
} | ||
|
||
inviteIsCorrect = | ||
sessionStore.currentAccount.username === | ||
getUsernameFromUrl(data.recipient); | ||
}); | ||
} catch (error) { | ||
handleApiFail( | ||
error as FailResponse, | ||
t( | ||
'Invite is invaild.' | ||
) | ||
); | ||
} | ||
|
||
return inviteIsCorrect; | ||
} | ||
|
||
export async function getAssetFromInviteUid(inviteUid: string) { | ||
let displayDetails = null; | ||
try { | ||
await getInviteDetail(inviteUid).then((data) => { | ||
displayDetails = { | ||
assetName: data.transfers[0].asset__name, | ||
assetOwner: getUsernameFromUrl(data.sender), | ||
}; | ||
}); | ||
} catch (error) { | ||
handleApiFail( | ||
error as FailResponse, | ||
); | ||
} | ||
return displayDetails; | ||
} |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we create Notion task for this?