Skip to content

Commit

Permalink
SDK adds signature query param to uploads (#10381)
Browse files Browse the repository at this point in the history
  • Loading branch information
stereosteve authored Nov 12, 2024
1 parent c75d0b4 commit 3ac2a0d
Show file tree
Hide file tree
Showing 9 changed files with 61 additions and 23 deletions.
12 changes: 8 additions & 4 deletions packages/sdk/src/sdk/api/playlists/PlaylistsApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,8 @@ export class PlaylistsApi extends GeneratedPlaylistsApi {
await this.storage.uploadFile({
file: coverArtFile,
onProgress,
template: 'img_square'
template: 'img_square',
auth: this.auth
}),
(e) => {
this.logger.info('Retrying uploadPlaylistCoverArt', e)
Expand Down Expand Up @@ -461,7 +462,8 @@ export class PlaylistsApi extends GeneratedPlaylistsApi {
await this.storage.uploadFile({
file: coverArtFile,
onProgress,
template: 'img_square'
template: 'img_square',
auth: this.auth
}),
(e) => {
this.logger.info('Retrying uploadPlaylistCoverArt', e)
Expand All @@ -477,7 +479,8 @@ export class PlaylistsApi extends GeneratedPlaylistsApi {
template: 'audio',
options: this.trackUploadHelper.extractMediorumUploadOptions(
trackMetadatas[idx]!
)
),
auth: this.auth
}),
(e) => {
this.logger.info('Retrying uploadTrackAudio', e)
Expand Down Expand Up @@ -591,7 +594,8 @@ export class PlaylistsApi extends GeneratedPlaylistsApi {
await this.storage.uploadFile({
file: coverArtFile,
onProgress,
template: 'img_square'
template: 'img_square',
auth: this.auth
}),
(e) => {
this.logger.info('Retrying uploadPlaylistCoverArt', e)
Expand Down
9 changes: 6 additions & 3 deletions packages/sdk/src/sdk/api/tracks/TracksApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,8 @@ export class TracksApi extends GeneratedTracksApi {
await this.storage.uploadFile({
file: coverArtFile,
onProgress,
template: 'img_square'
template: 'img_square',
auth: this.auth
}),
(e) => {
this.logger.info('Retrying uploadTrackCoverArt', e)
Expand All @@ -141,7 +142,8 @@ export class TracksApi extends GeneratedTracksApi {
onProgress,
template: 'audio',
options:
this.trackUploadHelper.extractMediorumUploadOptions(metadata)
this.trackUploadHelper.extractMediorumUploadOptions(metadata),
auth: this.auth
}),
(e) => {
this.logger.info('Retrying uploadTrackAudio', e)
Expand Down Expand Up @@ -211,7 +213,8 @@ export class TracksApi extends GeneratedTracksApi {
await this.storage.uploadFile({
file: coverArtFile,
onProgress,
template: 'img_square'
template: 'img_square',
auth: this.auth
}),
(e) => {
this.logger.info('Retrying uploadTrackCoverArt', e)
Expand Down
6 changes: 4 additions & 2 deletions packages/sdk/src/sdk/api/users/UsersApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,8 @@ export class UsersApi extends GeneratedUsersApi {
await this.storage.uploadFile({
file: profilePictureFile,
onProgress,
template: 'img_square'
template: 'img_square',
auth: this.auth
}),
(e) => {
this.logger.info('Retrying uploadProfilePicture', e)
Expand All @@ -82,7 +83,8 @@ export class UsersApi extends GeneratedUsersApi {
await this.storage.uploadFile({
file: coverArtFile,
onProgress,
template: 'img_backdrop'
template: 'img_backdrop',
auth: this.auth
}),
(e) => {
this.logger.info('Retrying uploadProfileCoverArt', e)
Expand Down
10 changes: 8 additions & 2 deletions packages/sdk/src/sdk/services/Auth/UserAuth.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { GetFn, Hedgehog, SetAuthFn, SetUserFn } from '@audius/hedgehog'
import { personalSign } from '@metamask/eth-sig-util'
import { keccak_256 } from '@noble/hashes/sha3'
import * as secp from '@noble/secp256k1'
import { EIP712TypedData, MessageData, signTypedData } from 'eth-sig-util'
Expand Down Expand Up @@ -138,8 +139,13 @@ export class UserAuth implements AuthService {
})
}

hashAndSign: (data: string) => Promise<string> = () => {
throw new Error('hashAndSign not initialized')
hashAndSign: (data: string) => Promise<string> = async (data) => {
const wallet = this.hedgehog.getWallet()
if (!wallet) throw new Error('No wallet')
return personalSign({
privateKey: wallet.getPrivateKey(),
data: keccak_256(data)
})
}

signTransaction: (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ export class EntityManager implements EntityManagerService {
)
} else {
throw new Error(
`Error making relay request${
`Error making relay request ${response.status} ${
jsonResponse?.error?.message ? `: ${jsonResponse.error.message}` : '.'
}`
)
Expand Down
23 changes: 18 additions & 5 deletions packages/sdk/src/sdk/services/Storage/Storage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,15 +60,15 @@ export class Storage implements StorageService {
auth: AuthService
}) {
// Generate signature

const signatureData = {
upload_id: uploadId,
timestamp: Date.now()
}
const signature = await auth.hashAndSign(
JSON.stringify(sortObjectKeys(signatureData))
)
const sigJson = JSON.stringify(sortObjectKeys(signatureData))
const signature = await auth.hashAndSign(sigJson)
const signatureEnvelope = {
data: JSON.stringify(signatureData),
data: sigJson,
signature
}

Expand Down Expand Up @@ -107,12 +107,14 @@ export class Storage implements StorageService {
file,
onProgress,
template,
options = {}
options = {},
auth
}: {
file: File
onProgress?: ProgressCB
template: FileTemplate
options?: { [key: string]: string }
auth: AuthService
}) {
const formData: FormData = new FormData()
formData.append('template', template)
Expand All @@ -125,13 +127,24 @@ export class Storage implements StorageService {
file.name ?? 'blob'
)

const signatureData = {
timestamp: Date.now()
}
const sigJson = JSON.stringify(sortObjectKeys(signatureData))
const signature = await auth.hashAndSign(sigJson)
const signatureEnvelope = {
data: sigJson,
signature
}

// Using axios for now because it supports upload progress,
// and Node doesn't support XmlHttpRequest
let response: AxiosResponse<any> | null = null
const request: AxiosRequestConfig = {
method: 'post',
maxContentLength: Infinity,
data: formData,
params: { signature: JSON.stringify(signatureEnvelope) },
headers: formData.getBoundary
? {
'Content-Type': `multipart/form-data; boundary=${formData.getBoundary()}`
Expand Down
4 changes: 3 additions & 1 deletion packages/sdk/src/sdk/services/Storage/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,14 @@ export type StorageService = {
file,
onProgress,
template,
options
options,
auth
}: {
file: File
onProgress?: ProgressCB
template: FileTemplate
options?: { [key: string]: string }
auth: AuthService
}) => Promise<UploadResponse>
editFile: ({
uploadId,
Expand Down
16 changes: 12 additions & 4 deletions pkg/mediorum/server/serve_upload.go
Original file line number Diff line number Diff line change
Expand Up @@ -127,14 +127,22 @@ func (ss *MediorumServer) postUpload(c echo.Context) error {
return c.String(http.StatusServiceUnavailable, "disk is too full to accept new uploads")
}

// Parse X-User-Wallet header
userWalletHeader := c.Request().Header.Get("X-User-Wallet-Addr")
// read user wallet from ?signature query string
// ... fall back to (legacy) X-User-Wallet header
userWallet := sql.NullString{Valid: false}
if userWalletHeader != "" {
if signerWallet, ok := c.Get("signer-wallet").(string); ok {
userWallet = sql.NullString{
String: userWalletHeader,
String: signerWallet,
Valid: true,
}
} else {
userWalletHeader := c.Request().Header.Get("X-User-Wallet-Addr")
if userWalletHeader != "" {
userWallet = sql.NullString{
String: userWalletHeader,
Valid: true,
}
}
}

// Multipart form
Expand Down
2 changes: 1 addition & 1 deletion pkg/mediorum/server/server_basic_auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ func (ss *MediorumServer) requireUserSignature(next echo.HandlerFunc) echo.Handl
})
} else {
// check it is for this upload id
if sig.Data.UploadID != id {
if id != "" && sig.Data.UploadID != id {
return c.JSON(401, map[string]string{
"error": "signature contains incorrect ID",
"detail": fmt.Sprintf("url: %s, signature %s", id, sig.Data.UploadID),
Expand Down

0 comments on commit 3ac2a0d

Please sign in to comment.