GithubHelp home page GithubHelp logo

stakwork / sphinx-kotlin Goto Github PK

View Code? Open in Web Editor NEW
18.0 9.0 11.0 1.6 GB

License: MIT License

Kotlin 90.63% Shell 0.06% Java 9.10% JavaScript 0.11% HTML 0.11%
bitcoin bounty btc foss kotlin kotlin-android lightning-network open-source

sphinx-kotlin's Introduction

sphinx-kotlin

Cloning

This repository uses git submodules (for the time being). When cloning the repository, run:

git clone --recursive https://github.com/stakwork/sphinx-kotlin.git

If you've already cloned the repository, run:

git checkout master
git pull
git submodule update --init

In order to keep the submodules updated when pulling the latest code, run:

git pull --recurse-submodules

To update only the submodules, run:

git submodule update

Building The App

See HERE to enable building Sphinx with FirebaseMessaging
See HERE to enable building Sphinx with the Giphy SDK See HERE to enable building Sphinx with the YouTube Player API

Checkout branch master:

git checkout master
git pull --recurse-submodule

The Application module to build is located at sphinx/application/sphinx. To Build, you can either:

  • Use Android Studio
  • From command line via: ./gradlew :sphinx:application:sphinx:build

For more detailed instructions, see HERE

sphinx-kotlin's People

Contributors

05nelsonm avatar alejandrocordon avatar ardevd avatar ariel10aguero avatar gonzaloaune avatar jimbeauxdibbs avatar kevkevinpal avatar kngako avatar kotlingeekdev avatar mouawiahammo avatar toadlybroodle avatar tomastiminskas avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

sphinx-kotlin's Issues

Repository's SocketIO listener not checking Chat's current latest message DateTime before updating table

The SphinxRepository's socketIO listener logic when receiving a SphinxSocketIOMessage.Type.MessageType is modifying the DB's chatDbo Table and setting the incoming message as it's latest_message. It is not verifying the current latest_message's DateTime to see if it is in fact the latest message for the given chat.

This will also require modifying the networkRefreshMessages() method to perform the same check before updating the table.

Process Death Restoration

Restoring application State after OS kills the application (ex: after being idle in the recent apps tray for too long) needs to be implemented:

  • Insetter values
  • Authentication
  • Navigation BackStack
  • Any forms or data filled out by user on the particular screen

OnBoard String Value Spec

Could use some clarification on the string values that are used on the splash screen when on-boarding a user.

  • Import Existing Keys keys::

    • Base64 decode to utf-8 string
    • split ::
      • arg0: keys
      • arg1: encrypted data
        • Base64 decode
        • decrypt with password (PIN)
        • format? ->>> looks to be <priv-key>::<pub-key>::<relay-url>::<auth-token>
  • Import IP ip::

    • Base64 decode to utf-8 string
    • split ::
      • arg0: ip
      • arg1: password (not used right now, but should be used to authenticate in the first request to the server -> generateToken endpoint)
  • Invite Code

    • 40 characters
    • Invite string generated on HUB and used by invitee to ping HUB and get assigned node IP. crypto.randomBytes(20).toString('hex')

SocketIO new message from deleted contact not showing

After User A deletes contact User B, and then User B sends a message to User A, that message is not propagating to the Dashboard because Relay is only dispatching the new message via SocketIO and not the contact for which it came.

For now, the networkRefresh call from Dashboard is working properly, but additional logic within the SphinxRepository's SocketIO listener is needed to handle such an event.

Paying for invite

If the wallet balance is too low (<2000 sats), and the user tries to pay for the invite, instead of an error, the UI says "Payment sent. Waiting confirmation"

NetworkRefresh locks up on Dashboard

If you send a message from a chat and immediately navigate back to the dashboard, the network refresh call locks up. This is attributed to the order of lock acquisition within the repository when a message is sent, as it releases the message lock after inserting the transitory message into the DB and then reaquires it after the network call completes (in order to replace the transitory message with the response from Relay).

`NetworkQueryInvite.finishInvite` method returns error instead of actual relay response

The current implementation for onboarding a new user in the OnBoardReadyViewModel calls finishInvite and, upon a response of either error or success, will proceed to the next step. This is attributed to an improper use of the NetworkRelayCall.relayPost method which, in the event Relay returns success = true whilst the response field required by the RelayResponse class is null, throws an exception upon validation.

The finish invite endpoint will only return success = t/f, thus a regular post (not relayPost) should be utilized along with a stand alone DTO model for the response.

This is a 1 off network request to relay prior to it being setup, and is not quite right for utilizing the NetworkRelayCall helper methods.

Creating invoice from Dashboard

Use payment-receive module to implement ability to create invoice from Dashboard. As on payment-send module, this feature needs to be implemented on dashboard and inside chat: On dashboard it just creates an invoice and shows it on the QRCode view, in the other hand, if you tap the + button on chat and then select Receive option, you will create an invoice that will be sent inside the chat as a message.

FOR NOW WE WILL IMPLEMENT IT JUST ON DASHBOARD, since we didn't work on the invoice rows on chat yet (but it's good to consider that when building the feature. SendPayment class is used for both cases on payment-send and this is why it contains contactId and chatId as well)

So for now we will allow user to set amount and memo and request the endpoint that will return the invoice string.

POST /invoices

Params: 
- amount (max amount 1000000)
- memo (max bytes length 639)
- 
Response: 
{
     success: true,
     response: {
          invoice: invoiceString
     }
}

Simulator Screen Shot - iPhone 12 - 2021-07-12 at 13 03 51

Once invoiceString is returned from relay, we should show QRCode view. This fragment supports 2 arguments (one for the string to be shown in the QR, and one for the title which in this case should be "PAYMENT REQUEST")

Finally on the QRCode view let's add a label above the QR code image to show the invoice amount on this case (screenshot attached). We may need to add one more arg on this fragment to receive the amount (this is optional since on other uses of this view there is no amount. Example: tapping on QR code icon on your own Profile to share your pub key).

Simulator Screen Shot - iPhone 12 - 2021-07-12 at 12 59 27

Layout issue when keyboard is open

The layout breaks when the keyboard is activated when sending a msg in a chat.

  • On the latest develop branch.
  • tap into any chat
  • tap into the text field to send a msg
  • the keyboard opens and pushes the chat content + header out of view

IMG_6542

Loading Giphy images

Giphy images are sent as normal text message on Sphinx (using same message type 0), but the text has a specific format we use to identify them. This could be check when fetching messages from relay (getMessages endpoint) or when receiving them trough socket and saving a new type on the app db object, or just check for the format when rendering the message on the chat view (as we are doing on iOS). I would go with the first option, so the logic to identify a Giphy is done when message is inserted in app db.

Format:

  • giphy::base64EncodedString if it starts with "giphy::" and it's base 64 encoded, then it's a Giphy message
  • Once prefix is removed and the rest of the string is decoded we will get a json object with the following format:
{
     "aspect_ratio" : "2.051282051282051",
     "url" : "https://media0.giphy.com/media/xWps1M74kSDOUpqbzO/giphy.gif?cid=d7a0fde9u222zli1x5zzh9189ykuevhuckl8aoi9zw017dhj&rid=giphy.gif&ct=g",
     "id" : "xWps1M74kSDOUpqbzO",
     "text" : null
}
  • aspect_ratio: will contain a value representing the ratio between width and height for the gif. That is used on iOS to calculate row height, but I don't think it will be needed on android, since most of the views adapt to their content
  • url: the url of the image to download and show
  • id: the Giphy library image id
  • text the text to show as normal text message if user included it when sending the gif

When getting a Giphy message and downloading it to show it on the chat we are replacing "giphy.gif" by "200w.gif" on the url, so we get a small version of the image. When tapping on the row and showing it on full screen, we are using the original url.

On iOS we are using the Giphy library which builds the view to search for Giphy. On MacOS we have implemented the search manually, using the API KEY and the endpoints provided by Giphy for developers. We will need to research to see if there's available libraries that can be used on our android/kotlin project. Otherwise we will need to build the requests and views. But that would be a second steps, since initially we want to show Giphy objects on chat, instead of allowing to send them.

DB Tables limited to 22 columns

Kotlin Language bug whereby inline classes throw a ClassCastException when passed in a method containing 23 or more arguments. This limits DB tables for the time being to 22 columns or less.

SQLDelight: cashapp/sqldelight#2266
JetBrains YouTrack: https://youtrack.jetbrains.com/issue/KT-45084

This currently affects the Message table only.

I've made an extension table (MessageMedia) for Messages of type 5 & 6 (DirectPayment & Attachment, respectively). A 2nd query to retrieve the data and attach it to the Message Presenter object is made when pulling those types, as a JOIN will throw the exception as well.

@tomastiminskas or @Evanfeenstra , can you confirm that only those MessageTypes contain media data?

Will leave this open until JetBrains pushes a fix.

Crash if message being decrypted is a space

Repository is decrypting the message content and then converting if from an UnencryptedByteArray to an UnencryptedString. In doing so, the extension function for .toUnencryptedString is calling .trim() on the string value. If the decrypted content is a single or double space, wrapping it with the MessageContentDecrypted class throws an IllegalArgumentException, resulting in a crash coming from the SphinxRepository.mapMessageDboAndDecryptContentIfNeeded method call.

Sending images on chat

The chat actions menu is built and push to branch with name tt/feature/chat-actions-menu so you should start from there.
In ChatViewModel.kt - showActionsMenu() (Line 410) is the place to handle each menu item tap.

Logic

Once the image is taken and you have the Data for that image, we are creating a random string with a length of 32 and using some specific letter (same logic we use to generate the auth token but with different length) and using it to encrypt the data symmetrically using that key.

At this point we are creating the provisional message record so the row shows on chat:

https://github.com/stakwork/sphinx/blob/8d16f84c829792ef72485231f99978f47be0e184/sphinx/Core%20Data/TransactionMessage/TransactionMessage%2BCoreDataClass.swift#L343

Once we have the encrypted data and the key we are uploading encrypted data to memes-server using the following endpoint:

POST "https://memes.sphinx.chat/file"
- HTTPHeader "Authorization": "Bearer $token"
- MultipartFormData 
       1. "image" withName: "name"
       2. ImageEncryptedData withName: "file", fileName: "image.jpg", mimeType: "image/jpg"
- Response: fileJson with some information about the file that will be used to create sendAttachment params

Once upload finishes, a new request needs to be done to:
- POST relayURL/attachment with same params as on sendMessage request and some other media params details on this link

https://github.com/stakwork/sphinx/blob/8d16f84c829792ef72485231f99978f47be0e184/sphinx/Core%20Data/TransactionMessage/TransactionMessageParamsExtension.swift#L96

- "media_key_map": encrypted media key using the same logic as on "remote_text_map" on text message.
- "media_type" : "mime" value from fileJson returned on upload request
- "muid" : "muid" value from fileJson returned on upload request

Flow screenshots

IMG_0519

When selecting Camera option it should take user to camera

IMG_0520

After image is taken, it will move to image preview where user can set a PRICE and a MESSAGE. We can disabled price for now.

IMG_0521

Finally image row is inserted into chat and on iOS we are showing an uploaded progress label on the row header.

IMG_0522

New tribe messages missing

There are two new messages in the planet sphinx tribe that don't appear in the chat, even though 3rd message that was written after the 2 missing messages does appear. Force quitting and restarting the app doesn't resolve the issue.

Screen Shot 2021-07-09 at 9 20 07 AM

Dashboard: Show Account Balance

  • Retrieve from the /balance endpoint the user's account balance and persist to device.
  • Observe any balance changes from the view to update the Dashboard's header, and navigation drawer header with new balance information.

App crash loading dashboard

I'm loading the sphinx_support user that may have thousands of contacts. After entering the pin, the balance is correct, and the contacts start to list on the dashboard. the app crashes after 5 seconds

2021-05-15 09:28:22.517 5522-5522/chat.sphinx.debug E/AndroidRuntime: FATAL EXCEPTION: main
Process: chat.sphinx.debug, PID: 5522
java.lang.IllegalArgumentException: ContactId must be greater than or equal 0
at chat.sphinx.wrapper_common.contact.ContactId.constructor-impl(ContactId.kt:5)
at chat.sphinx.feature_repository.util.ExtensionsKt.upsertMessage(Extensions.kt:180)
at chat.sphinx.feature_repository.SphinxRepository$networkRefreshMessages$2$1$invokeSuspend$$inlined$collect$1$lambda$1$1.invoke(SphinxRepository.kt:993)
at chat.sphinx.feature_repository.SphinxRepository$networkRefreshMessages$2$1$invokeSuspend$$inlined$collect$1$lambda$1$1.invoke(SphinxRepository.kt:72)
at com.squareup.sqldelight.TransacterImpl.transactionWithWrapper(Transacter.kt:218)
at com.squareup.sqldelight.TransacterImpl.transaction(Transacter.kt:197)
at com.squareup.sqldelight.Transacter$DefaultImpls.transaction$default(Transacter.kt:82)
at chat.sphinx.feature_repository.SphinxRepository$networkRefreshMessages$2$1$invokeSuspend$$inlined$collect$1$lambda$1.invokeSuspend(SphinxRepository.kt:973)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:106)
at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:571)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.executeTask(CoroutineScheduler.kt:750)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.runWorker(CoroutineScheduler.kt:678)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:665)

Podcast

Every time user enters a tribe chat, we are getting the updated info of that tribe from tribes server (using the host of the chat object). If feedUrl is not empty on that tribe info coming from tribes server host, then we should get the podcast feed data requesting a new endpoint:

GET https://${chat.host}/podcast?url=${tribe.feed_url} - with no body params

The response will be a json object containing information about podcast, episodes and payments destinations. Here is an example with just one episode to make it shorter:

{
	"id": 226249,
	"title": "Tales from the Crypt: A Bitcoin Podcast",
	"url": "https://anchor.fm/s/558f520/podcast/rss",
	"description": "Tales from the Crypt is a podcast hosted by Marty Bent about Bitcoin. Join Marty, Editor in Chief of \"the best newsletter in Bitcoin\", as he sits down to discuss Bitcoin with interesting people.",
	"author": "Marty Bent",
	"image": "https://d3t3ozftmdmh3i.cloudfront.net/production/podcast_uploaded_nologo/797160/797160-1579811341935-88e5cd5024bf9.jpg",
	"link": "https://anchor.fm/tales-from-the-crypt",
	"lastUpdateTime": 1622662235,
	"contentType": "application/rss+xml; charset=utf-8",
	"language": "en-us",
	"episodes": [{
		"id": 2541203462,
		"title": "#258: The morality of ESG with Untapped Growth",
		"description": "\u003cp\u003eJoin Marty as he sits down with Untapped Growth to discuss:\u003c/p\u003e\n\u003cp\u003e- ESG\u003c/p\u003e\n\u003cp\u003e- Is it moral?\u003c/p\u003e\n\u003cp\u003e- Can it be leveraged to speculative attack the fiat standard?\u003c/p\u003e\n\u003cp\u003e- How can Bitcoin lead to better culture\u003c/p\u003e\n\u003cp\u003e- Seeking objective truth\u003c/p\u003e\n\u003cp\u003e- much more\u003c/p\u003e\n\u003cp\u003eFollow Untapped Growth on Twitter\u003c/p\u003e\n\u003cp\u003eShoutout to this week's sponsors.\u003c/p\u003e\n\u003cp\u003eCash App. Start #stackingsats today. Use the promo code: \"stackingsats\" to receive $10 and contribute $10 to OWLS Lacrosse when you download the app.\u003c/p\u003e\n\u003cp\u003eLend at Hodl Hodl...",
		"datePublished": 1622638800,
		"enclosureUrl": "https://anchor.fm/s/558f520/podcast/play/34682465/https%3A%2F%2Fd3ctxlq1ktw2nl.cloudfront.net%2Fstaging%2F2021-5-2%2F192649643-44100-2-c36483521f93a.m4a",
		"enclosureType": "audio/x-m4a",
		"enclosureLength": 121008979,
		"image": "https://d3t3ozftmdmh3i.cloudfront.net/production/podcast_uploaded_nologo/797160/797160-1579811341935-88e5cd5024bf9.jpg",
		"link": "https://anchor.fm/tales-from-the-crypt/episodes/258-The-morality-of-ESG-with-Untapped-Growth-e120u51"
	}],
	"value": {
		"model": {
			"type": "lightning",
			"suggested": "0.00000005000"
		},
		"destinations": [{
			"address": "02c6aa9067f0b31be4abc5fd811a93266f1f4bf4c4b57d4663fe5b7e3ed1a9860b",
			"split": 100,
			"type": "node"
		}, {
			"address": "03ae9f91a0cb8ff43840e3c322c4c61f019d8c1c3cea15a25cfc425ac605e61a4a",
			"split": 1,
			"type": "node"
		}]
	}
}

On iOS we are not storing this permanently on db since it will be fetched every time you go into the chat, and it should just show the player if feed_url is not empty on tribe at that time, and if episodes array contains at least 1 episode. The enclosureUrl of each episode points to the audio file that should be played.

In addition, to be in sync between platform we are sending to relay the information about current podcast state using the updateChat endpoint:

PUT /chats/${chat.id}

Params:

  • "meta": {"itemID": currentEpisode.id, "sats_per_minute": satsPerMinute, "ts": currentTimestamp, "speed": speed}

This endpoint is hit when playing or pausing an episode, when finishing moving on timestamp slider, and when an episode ends.

In the other hand, on every chats fetch, we are getting the "meta" of each chat and storing it on UserDefaults so then it can be used to set the player controls on the latest state on other platforms. I think it's ok to store all this information in UserDefaults since it's not sensitive information.

Podcast player stops after device goes into Doze Mode

While a podcast is playing and the device is locked, after a while the phone enters Doze Mode. The MediaPlayer running in the Service is acquiring a WakeLock for this purpose, but it is being released (at least for Android API 30).

Recommendation: put service into foreground immediately upon starting. Drawback is that the Notification (for now) will not be able to be swiped away to stop playback. We can temporarily provide a Stop button on the Notification until we build out a MediaPlaybackNotification that is more flexible with ForegroundService requirements.

Detail Screen swipe behavior memory leak

When a Detail Screen is showing, swiping it down to exit causes a memory leak.

The navigation request to pop the DetailDriver's backstack is firing off and returning true as executed, but the Fragments (and thus, ViewModels) are not being destroyed. This is attributed to the MainActivity's detail_fragment_host not being visible, thus the androidx.navigation.NavController not executing the request (even though the request returns true).

Disabling the swipe behavior for now until this can be resolved.

Add repository coroutine scope

Add a supervisor scope for SphinxRepository such that in the event a calling screen's scope is cancelled, critical operations can be offloaded from the caller's scope to the uncancelable scope to complete properly.

This is especially needed in low connectivity/slow connection situations, such as when the user is connecting to Relay over Tor.

Error Notifications

Need a way to notify the user when there is an error such that they can be informed in the event something goes wrong.

Example: Their network connection is slow. They create a new contact and navigate back to the Dashboard. The network request for creating a new contact completes with exception. They're no longer on the "new contact" screen and have no way of knowing if it was created or not.

Concept: Create a repository-error-handler interface and implement in SphinxRepository where by the Activity can observe a BroadcastChannel and post up errors to the screen by toggling an ErrorViewState that requires user to select OK (just like the iOS app).

Backup keys from Profile

When tapping on Backup Keys from Profile, user is asked for his PIN, so it can be used to encrypt the keys generating the long restore string. Ideally when presenting the PIN view, it should include a subtitle there with the following text (check iOS for reference):

Enter your PIN to encrypt your keys. You will need it when restoring account on other device.

Once user entered the PIN, and just if it's the right standard PIN for the user, the restore string will be generated following these steps:

  • Get RSA key pair
  • Get relay URL
  • Get relay Auth Token
  • Generate a string with the following format: "privateRSAKey::publicRSAKey::RelayURL::AuthToken"
  • Encrypt that string symmetrically using the PIN (check message encryption on tribes using group_key for symmetric encryption reference on kotlin project)
  • Prepend "keys::" to the encrypted string resulting in "keys::EncryptedString"
  • Encode in base 64 the entire string in previous step

Once you have the restore string, ask the user for confirmation with an prompt alert before copying it to the clipboard and use the following text:

Your keys will be copied to the clipboard. Save this string & remember your pin before deleting the app or all data will be lost.

Finally if user confirms show a Toast with the following text:

Export keys copied to clipboard

App crashes when message is selected

When a message is selected (to pull up the message menu, to boost for example), and the application goes to the background, moving the application to the foreground again causes a crash.

Relay Version Peg

Peg app usage to a minimum relay version.

The best location to do this is in the DashboardViewModel.networkRefresh such that an error is produced and the version number is set as a static variable which will inhibit any other network requests from occurring.

This feature will also need to be implemented into the Profile advanced settings in the event a user restores keys, they can update their relay url to a BE that is above the min version and the app will then begin to process requests.

Command Line Build tests fail

For macOS commandline build fails due to kotlin-android 's k-openssl module's tests (requires openssl to be installed and available at /usr/bin/openssl, otherwise an exception is thrown.

[Question] MediaType definitions

Have a few questions regarding what string values are passed for the media_type field coming off the wire.

I am seeing the following, but I know there are more:

  • video/mp4
  • sphinx/text
  • image/png
  • image/jpg
  • image/jpeg
  • image/gif
  • audio/wav
  • audio/mp4
  • audio/m4a
  • application/pdf
  • application/octet-stream

Is there a specified set of string values that are passed to relay by the client(s)?

What I'd like to do:

inline fun String.toMediatype(): MediaType =
   when (this) {
        VIDEO_MP4 -> {
            MediaType.VideoMP4
        }
        SPHINX_TEXT -> {
            MediaType.SphinxText
        }
        // ... more
        else -> {
            MediaType.Unknown(this)
        }
    }

sealed class MediaType {

    companion object {
        const val VIDEO_MP4 = "video/mp4"
        const val SPHINX_TEXT = "sphinx/text
        // ... more
    }

    abstract val value: String

    object VideoMP4: MediaType() {
        override val value: String
            get() = VIDEO_MP4
    }

    object SphinxText: MediaType() {
        override val value: String
            get() = SPHINX_TEXT
    }

    // .... more

    class Unknown(override val value: String): MediaType()
}

Cant change server URL.

Expected: Profile -> advanced -> server URL upon tap it shall allow to change server URL.

Actual: upon tap nothing happens.

Delete messages

Add DELETE option on message options menu that appears on message bubble long press. Delete option should be red (badgeRed color).

IMG_0612

MenuItemState might need to be modified to support specific color for each option.

DELETE option should only be available for OUTGOING messages or OUTGOING/INCOMING messages on a tribe you are admin of (to know if you are admin of a tribe you should compare owner.nodePubKey with chat.ownerPubKey)

If message.id < 0 (which means message failed and was not sent at all), then request is skipped and message is just deleted from device db (it will disappear from chat)

Example here:

If message.id > 0, then request needs to be done to soft delete message on server and message local record should be updated from request response (which will update status making message to show as deleted on chat)

Delete message endpoint needs to be implemented in NetworkQueryMessage. Response will be same as on sendMessage. Upserting message from endpoint response should be enough for the view to refresh and show the message as deleted since we are listening for changes on each message object in the chat.

DELETE /message/$messageId

Reference of message upserting:

Chat Images attachments

To download or upload any file from/to memes-server, it's needed to include an authentication token as HTTP Header.

GET ATTACHMENTS SERVER TOKEN

request.addValue("Bearer \(token)", forHTTPHeaderField: "Authorization")

To get that token a sequence of requests needs to be done:

- GET https://memes.sphinx.chat/ask RESPONSE: id, challenge
- GET relay_url/signer/$challenge RESPONSE: sign
- POST https://memes.sphinx.chat/verify?id=$id&sig=$sig&pubkey=$ownerPubKey RESPONSE: token

Token expires every 7 days after it has been created. With that token you can download the data of file from memes-server.

DOWNLOAD DATA FOR FILE

File data URL:

https://$host/file/$mediaToken

Where host is accessed from mediaToken of the message:

  • Split media token by "." character (omitting empty)
  • Get element at index 0
  • Base 64 decode

DECRYPT DATA

  • Data needs to be decrypted using the mediaKey attribute of the message

File attachment type ca be identified using the mediaType attribute of the message ("image/jpg")

Add Tor

Implement TorOnionProxyLibrary-Android. This is a Work In Progress (WIP) list of tasks to implement the feature.

  • TOPL Tasks:
    • Build and publish latest Tor binaries
    • Update dependencies
  • Sphinx Tasks:
    • Kotlin concept module for TorController
      • As TOPL-Android is not multiplatform (on my todo list!!!) and are AndroidLibraries,
        Kotlin wrapper classes are needed for the various Android specific TOPL apis to be utilized
        in other Kotlin only modules.
    • Android feature module for concept implementation
    • "Tor Required" logic for RelayDataHandler class
    • Link network-client module to Tor's state depending if RelayDataHandler requires Tor
      • Temporary for the time being.
      • Clearing clients and rebuilding them with new proxy info depending on Tor Network state

Tribe pricing information

We can remove this popup alert (or at minimum show it 1x). Currently it shows every time you enter a the tribe chat and covers the text field. It's present when the person joins the tribe.

Close Detail Screen navigation animation

Closing of a detail screen that has more than 1 Fragment on its backstack animates the screen down and to the right of the screen. This behavior should be downward only and seems to be attributed to the navigation to the blank fragment that has default nav options set as it's the starting destination for the detail nav graph.

Restore Account From xxx date

Add ability to restore account from a user specified date, and then pull from Relay any messages before that restore date when scrolling in the chat.

Command line build failure

./gradlew build currently fails while building the project with FirebaseMessaging module included. This is attributed to the package name for module :sphinx:service:features:notifications:feature-service-notification-firebase being the same as :sphinx:application:sphinx. Failure is due to the same package name BuildConfig is generated.

Signup Refactor

We will move the set PIN step to the very beginning after token is generated. That way we can prevent storing IP and Token on SharedPreferences and just store it securely once the authentication with PIN has been done. So PIN view will be presented from SplashFragment, and just after PIN was set it will move to Inviter welcome message screen.

ProfilePicture fragment needs to be added after onboard-name view (this view is missing in current implementation). The layouts are already built on layout_signup_profile_picture.xml (logic to upload and update profile photo url is the same we implemented in Profile View)

Finally we should implement some way of tracking signup steps so if user closes the app during the signup, app will take user to specific step when opening it again. iOS steps can't be used as reference here since we are changing the order on kotlin signup.

Profile Picture Upload

When tapping on Profile picture ImageView, we should allow user to select between camera and Photo Library. Here is a reference from iOS.

IMG_0597

The process of uploading the profile picture to memes server is similar to the one when uploading images to be sent on a chat, but there are a few minor differences:

POST "https://memes.sphinx.chat/public"
- HTTPHeader "Authorization": "Bearer $token"
- MultipartFormData 
       1. "image" withName: "name"
       2. ImageData withName: "file", fileName: "image.jpg", mimeType: "image/jpg"
- Response: fileJson with some information about the file that will be used to create sendAttachment params

Once uploaded the url is built with this format:

  • "$AttachmentsServerUrl/public/$muid"

And profile is updated using that url as photo_url

PUT /contacts/$owner_id 
Params: "photo_url" : photoUrl

Address Book not updating properly if contact is re-added

If User A deletes User B from contacts, and User B messages User A again while they are still on the Address Book screen, User B is re-added to the list, as they should be. When this occurs though, the list is not properly updating as it seems to take the place of another contact.

Adding new contact

I added my hosted sphinx contact to my kotlin app (Add Friend > Already on Sphinx).
The contact saves, but when I try to send a msg, nothing shows in the chat and no message is received.

Export Key Custom Password Functionality

Currently Exporting of Keys (as well as other necessary data) to setup Sphinx on a different device encrypts the output string with the User's PIN.

6 character length of character pool of 10x chars using 10_000 hash iterations of PBKDF2WithHmacSHA1 is very vulnerable if the string value (which is sent to the clipboard, a known threat vector) lands in the wrong hands.

Analyzing chain of custody of the exported string value shows that it touches many different interfaces while the User migrates it over to their other device; interfaces that other applications have access to.

2nd order impacts of this string value being decrypted are loss of funds, exposing private chat messages, etc. etc.

Ideally, if still utilizing the user's PIN to encrypt/decrypt, hash Iterations would be best bumped up to something extremely high (250k - 500k) which would offset the low combination.

Alternatively, pre-generating a strong password via SecureRandom, Base32 encoding, and adding tacs (-) every 5 characters would allow for a lower hash iteration count, make the exported string value far less vulnerable to maliciousness, and promote best practices.

Slow Network Refresh [No GooglePlay Services]

The Dashboard's call to network refresh includes updating of the push notification token. If the device does not have GooglePlay Services that push notification token retrieval runs until it times out before continuing with the rest of the network refresh.

Refactor RelayDataHandler to handle insecure connection information

Relay Connection Information:

  • AuthorizationToken
  • RelayUrl

Currently there is no logic in the RelayDataHandler class to check the RelayUrl for secure connections. Sending the AuthorizationToken in the header over http should never be a thing.

Exception to the rule:

  • Tor (.onion addresses)

Task:

  • Implement logic in the RelayDataHandler for persisting a RelayUrl such that it will fail if the scheme is http unless it is a .onion address

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.