* Generate API key in settings
* Check x-api-key for GraphQL API requests
* Don't fallback to cookie if x-api-key header was provided
* Select all session fields
* Fix error if API key not found
* Fix style in settings via form-label className
---------
Co-authored-by: Keyan <34140557+huumn@users.noreply.github.com>
* Allow founders to transfer territories
* Log territory transfers in new AuditLog table
* Add territory transfer notifications
* Use polymorphic AuditEvent table
* Add setting for territory transfer notifications
* Add push notification
* Rename label from user to stacker
* More space between cancel and confirm button
* Remove AuditEvent table
The audit table is not necessary for territory transfers and only adds complexity and unrelated discussion to this PR.
Thinking about a future-proof schema for territory transfers and how/what to audit at the same time made my head spin.
Some thoughts I had:
1. Maybe using polymorphism for an audit log / audit events is not a good idea
Using polymorphism as is currently used in the code base (user wallets) means that every generic event must map to exactly one specialized event.
Is this a good requirement/assumption? It already didn't work well for naive auditing of territory transfers since we want events to be indexable by user (no array column) so every event needs to point to a single user but a territory transfer involves multiple users.
This made me wonder: Do we even need a table? Maybe the audit log for a user can be implemented using a view? This would also mean no data denormalization.
2. What to audit and how and why?
Most actions are already tracked in some way by necessity: zaps, items, mutes, payments, ...
In that case: what is the benefit of tracking these things individually in a separate table?
Denormalize simply for convenience or performance? Why no view (see previous point)? Use case needs to be more clearly defined before speccing out a schema.
* Fix territory transfer notification id conflict
* Use include instead of two separate queries
* Drop territory transfer setting
* Remove trigger usage
* Prevent transfers to yourself
* Territory notifications
* Migrate old setting to new table
* Auto subscribe founders to their territories on creation
* Fix (un)subscribe not shown to founder
* Rename to toggleSubSubscription
* Fix inconsistency between toggleSubSubscription and toggleMuteSub
* Add dedicated button in header for following territories
* Don't drop noteTerritoryPosts column
* Fix db dip in Sub.meSubscription resolver
* Move territory subscribe to new territory context menu
* Decrease space between share icon and mute button
* Fix eslint
* add poll expires at column to Item table
* update upsertPoll mutation for pollExpiresAt param
* use pollExpiresAt to show time left for poll
* correctly pluralize days for timeLeft
* correctly update pollExpiresAt when item is updated to remove poll expiration
* add DateTimePicker and DateTimeInput components to select datetimes
* update pollExpiresAt to be nullable and more than 1 day in the future
* hide time left text if poll has no expiration
* initialize pollExpiresAt with current value or default of 25 hours in the future
we add a one hour time buffer so that the user doesn't get a validation error
for pollExpiresAt if they post their poll within an hour from creation. there's
still a chance they'll hit the validation error but they should see the error
message toast
* add DateTimeInput into the options part of the poll form
add right padding to make room for the "clear" button.
allow field to be cleared (i.e. null pollExpiresAt) to allow
non-ending polls.
---------
Co-authored-by: Keyan <34140557+huumn@users.noreply.github.com>
* add nsfw column to sub
* add nsfw boolean to territorySchema
* save nsfw value in upsertSub mutation
* return nsfw value from Sub query for correct value in edit territory form
* add nsfw checkbox to territory form
* add nsfw badge to territory header
* add nsfwMode to user
* show nsfw badge next to item territory
* exclude nsfw sub from items query
* show nsfw mode checkbox on settings page
* fix nsfw badge formatting
* separate user from current, signed in user
* update relationClause to join with sub table
* refactor to simplify hide nsfw sql
* filter nsfw items when viewing user items
* hide nsfw posts for logged out users
* filter nsfw subs based on user preference
* show nsfw sub name if logged out user is viewing the page
* show current sub at the top of the list instead of bottom
* always join item with sub to check nsfw
* check for sub presence before showing nsfw badge on item
* skip manually adding sub to select if sub is null
* fix relationClause to join with root item
* move moderation and nsfw into accordion
---------
Co-authored-by: Keyan <34140557+huumn@users.noreply.github.com>
* Use parallel invoice subscriptions
* Fix missing idempotency
* Log error
* Use cursor for invoice subscription
* Subscribe to outgoing payments for withdrawals
* Add TODO comments regarding migration to LND subscriptions
* Also use isPoll variable in checkInvoice
* Queue status check of pending withdrawals
* Use for loop to check pending withdrawals
* Reconnect to LND gRPC API on error
* Fix hash modified of applied migrations
* Separate wallet code from worker index
* refactor subscription code some more
* remove unnecessary subWrapper abstraction
* move all wallet related code into worker/wallet.js such that only a single import is needed in worker/index.js
* Migrate from polling to LND subscriptions
* Remove unnecessary reconnect code
* Add FIXME
* Add listener for HODL invoice updates
* Remove obsolete comment
* Update README
* Add job to cancel hodl invoice if expired
* Fix missing else
* small bug fixes and readability enhancements
* refine and add periodic redundant deposit/withdrawal checks
---------
Co-authored-by: ekzyis <ek@stacker.news>
Co-authored-by: Keyan <34140557+huumn@users.noreply.github.com>
Co-authored-by: keyan <keyan.kousha+huumn@gmail.com>
* Add nostr event id field to items
* crosspost-item
* crosspost old items, update with nEventId
* Updating noteId encoding, cleaning up a little
* Fixing item-info condition, cleaning up
* Linting
* Spacing nit
* Add createdAt variable back
* Change instances of eventId to noteId
* Adding upsertNoteId mutation
* Cleaning up updateItem, using toasts to communivate success/failure in crosspost-item
* Linting
* Fix type
* Move crosspost to share button, make sure only OP can crosspost
* Lint
* Simplify conditions
* user might have no nostr extension installed
Co-authored-by: ekzyis <27162016+ekzyis@users.noreply.github.com>
* change upsertNoteId to updateNoteID for resolver and mutations, change isOp to mine, remove unused noteId params
* Use nostr.com for linking out with noteId
* lint
* add noopener to window.open call
* Simplify condition, throw GraphQLError
---------
Co-authored-by: Keyan <34140557+huumn@users.noreply.github.com>
Co-authored-by: ekzyis <27162016+ekzyis@users.noreply.github.com>
* Add icon to add images
* Open file explorer to select image
* Upload images to S3 on selection
* Show uploaded images below text input
* Link and remove image
* Fetch unsubmitted images from database
* Mark S3 images as submitted in imgproxy job
* Add margin-top
* Mark images as submitted on client after successful mutation
* Also delete objects in S3
* Allow items to have multiple uploads linked
* Overwrite old avatar
* Add fees for presigned URLs
* Use Github style upload
* removed upfront fees
* removed images provider since we no longer need to keep track of unsubmitted images on the client
* removed User.images resolver
* removed deleteImage mutation
* use Github style upload where it shows ![Uploading <filename>...]() first and then replaces that with ![<filename>](<url>) after successful upload
* Add Upload.paid boolean column
One item can have multiple images linked to it, but an image can also be used in multiple items (many-to-many relation).
Since we don't really care to which item an image is linked and vice versa, we just use a boolean column to mark if an image was already paid for.
This makes fee calculation easier since no JOINs are required.
* Add image fees during item creation/update
* we calculate image fees during item creation and update now
* function imageFees returns queries which deduct fees from user and mark images as paid + fees
* queries need to be run inside same transaction as item creation/update
* Allow anons to get presigned URLs
* Add comments regarding avatar upload
* Use megabytes in error message
* Remove unnecessary avatar check during image fees calculation
* Show image fees in frontend
* Also update image fees on blur
This makes sure that the images fees reflect the current state. For example, if an image was removed.
We could also add debounced requests.
* Show amount of unpaid images in receipt
* Fix fees in sats deducted from msats
* Fix algebraic order of fees
Spam fees must come immediately after the base fee since it multiplies the base fee.
* Fix image fees in edit receipt
* Fix stale fees shown
If we pay for an image and then want to edit the comment, the cache might return stale date; suggesting we didn't pay for the existing image yet.
* Add 0 base fee in edit receipt
* Remove 's' from 'image fees' in receipts
* Remove unnecessary async
* Remove 'Uploading <name>...' from text input on error
* Support upload of multiple files at once
* Add schedule to delete unused images
* Fix image fee display in receipts
* Use Drag and Drop API for image upload
* Remove dragOver style on drop
* Increase max upload size to 10MB to allow HQ camera pictures
* Fix free upload quota
* Fix stale image fees served
* Fix bad image fee return statements
* Fix multiplication with feesPerImage
* Fix NULL returned for size24h, sizeNow
* Remove unnecessary text field in query
* refactor: Unify <ImageUpload> and <Upload> component
* Add avatar cache busting using random query param
* Calculate image fee info in postgres function
* we now calculate image fee info in a postgres function which is much cleaner
* we use this function inside `create_item` and `update_item`: image fees are now deducted in the same transaction as creating/updating the item!
* reversed changes in `serializeInvoiceable`
* Fix line break in receipt
* Update upload limits
* Add comment about `e.target.value = null`
* Use debounce instead of onBlur to update image fees info
* Fix invoice amount
* Refactor avatar upload control flow
* Update image fees in onChange
* Fix rescheduling of other jobs
* also update schedule from every minute to every hour
* Add image fees in calling context
* keep item ids on uploads
* Fix incompatible onSubmit signature
* Revert "keep item ids on uploads"
This reverts commit 4688962abc.
* many2many item uploads
* pretty subdomain for images
* handle upload conditions for profile images and job logos
---------
Co-authored-by: ekzyis <ek@ekzyis.com>
Co-authored-by: ekzyis <ek@stacker.news>
* Crossposting discussion function, crossposting setting migration
* Passing in id, adding relays to test
* Adding checkbox setting for crossposting enabled
* Adding paramaterized event fields to crosspostDiscussion, successfully crossposting discussions
* Cleaning up for rebase
* Removing nostrRelays
* Retry crosspost toast
* Adding nostrCrossposting to settings, fixing migration
* Full flow is working with error surfacing, retries, and skips for a retry
* Updates to error handling/retries for crossposting, fixing settings for crossposting
* Allowing recursive retries for crossposting to specific relays
* Fixing / syncing crossposting settings, cleaning up and seperating out nostr functions
* Cleaning up
* Running linter
* make nostr crossposter a hook
---------
Co-authored-by: Austin <austin@pop-os.localdomain>
Co-authored-by: plebdev <plebdev@plebdevs-MacBook-Pro.local>
Co-authored-by: Keyan <34140557+huumn@users.noreply.github.com>
Co-authored-by: keyan <keyan.kousha+huumn@gmail.com>
* first pass of LUD-18 support
* Various LUD-18 updates
* don't cache the well-known response, since it includes randomly generated single use values
* validate k1 from well-known response to pay URL
* only keep k1's for 10 minutes if they go unused
* fix validation logic to make auth object optional
* Various LUD18 updates
* move k1 cache to database
* store payer data in invoice db table
* show payer data in invoices on satistics page
* show comments and payer data on invoice page
* Show lud18 data in invoice notification
* PayerData component for easier display of info in invoice, notification, wallet history
* `payerData` -> `invoicePayerData` in fact schema
* Merge prisma migrations
* lint fixes
* worker job to clear out unused lnurlp requests after 30 minutes
* More linting
* Move migration to older
* WIP review
* enhance lud-18
* refine notification ui
---------
Co-authored-by: Keyan <34140557+huumn@users.noreply.github.com>
Co-authored-by: keyan <keyan.kousha+huumn@gmail.com>
* Remove outdated comments about srcSet value
We no longer distinguish between `undefined` and `null` for `srcSet`.
* Fix misleading URL shown
* Update/fix comments in <ImageOriginal>
* Simplify condition when to show image
I think this is not required since `showImage` will always stay false if tab !== 'preview' or me?.clickToLoadImg are true.
* Rename to imgproxyOnly
* Add info to imgproxyOnly setting
* Fix text of markdown links not used on imgproxy errors
* Fix rendering markdown links with text as images
---------
Co-authored-by: ekzyis <ek@stacker.news>
* Prototype implementing LUD-12 comments on payRequest in LNURLP Lightning Address flow
* Support sending comment when withdrawing to ln addr (LUD-12)
* Prevent `initialError` from being toasted informs multiple times
* delete the old create_invoice function
* improve lightning addr withdrawal styling
* allow lnaddr comment to show up in notifications
* enhance satistics
---------
Co-authored-by: keyan <keyan.kousha+huumn@gmail.com>
* Add diagnostics settings & endpoint
Stackers can now help us to identify and fix bugs by enabling diagnostics.
This will send anonymized data to us.
For now, this is only used to send events around push notifications.
* Send diagnostics to slack
* Detect OS
* Diagnostics data is only pseudonymous, not anonymous
It's only pseudonymous since with additional knowledge (which stacker uses which fancy name), we could trace the events back to individual stackers.
Data is only anonymous if this is not possible - it must be irreversible.
* Check if window.navigator is defined
* Use Slack SDK
* Catch errors of slack requests
---------
Co-authored-by: ekzyis <ek@stacker.news>
Co-authored-by: Keyan <34140557+huumn@users.noreply.github.com>
* Subscribe to user posts and comments independently
* Track when comments and posts subscriptions are set to filter out old items
* Only send push notification to subscribed user if posts/comments enabled
* Remove `posts` and `comments` boolean fields on UserSub, rely solely on timestamps
* Hide wallet balance on long press
* Use setting to hide wallet balance
* Fix layout shift on hover
* Fix SSR warning about useLayoutEffect
See https://reactjs.org/link/uselayouteffect-ssr
* Also hide balance in wallet
---------
Co-authored-by: ekzyis <ek@stacker.news>
* Notifications for when you are forwarded sats from a post
Support notifications when a post for which you are forwarded gets zapped
This is controlled by a new boolean flag in user settings
* Send push notifications to forwarded users when they get forwarded sats
* Add `Promise.allSettled` per PR feedback
* Remove `FEE` act type when building forwarded zaps notifications
Don't include `FEE` actions, only `TIP` actions to avoid "0 sats forwarded" notifications
---------
Co-authored-by: Keyan <34140557+huumn@users.noreply.github.com>
* Use HODL invoices
* Fix expiry check comparing string with Date
* Fix unconfirmed user balance for HODL invoices
This is done by syncing the data from LND to the Invoice table.
If the columns is_held and msatsReceived are set, the frontend is told that we're ready to execute the action.
We then update the user balance in the same tx as the action.
We need to still keep checking the invoice for expiration though.
* Fix worker acting upon deleted invoices
* Prevent usage of invoice after expiration
* Use onComplete from <Countdown> to show expired status
* Remove unused lnd argument
* Fix item destructuring from query
* Fix balance added to every stacker
* Fix hmac required
* Fix invoices not used when logged in
* refactor: move invoiceable code into form
* renamed invoiceHash, invoiceHmac to hash, hmac since it's less verbose all over the place
* form now supports `invoiceable` in its props
* form then wraps `onSubmit` with `useInvoiceable` and passes optional invoice options
* Show expired if expired and canceled
* Also use useCallback for zapping
* Always expire modal invoices after 3m
* little styling thing
---------
Co-authored-by: ekzyis <ek@stacker.news>
Co-authored-by: keyan <keyan.kousha+huumn@gmail.com>
Co-authored-by: Keyan <34140557+huumn@users.noreply.github.com>
* First pass of user subscriptions
* add new db model to track subscriptions
* update user typedef and api resolver for subscription state
* add subscribe action to user profile page
* add mutation to subscribe to a user
* Update notifications queries, hasNewNotes queries for FollowActivity note type
* Only show items that have been created since subscribing to the user
* Send push notifications to user subscribers for posts and comments
* Rename item dropdown to action dropdown and re-use for item info and user actions
* Don't allow self-follows
* Add index on followee for faster lookups
* Don't show subscribe action if not logged in
* small style enhance
---------
Co-authored-by: Keyan <34140557+huumn@users.noreply.github.com>
Co-authored-by: keyan <keyan.kousha+huumn@gmail.com>
* multiple forwards on a post
first phase of the multi-forward support
* update the graphql mutation for discussion posts to accept and validate multiple forwards
* update the discussion form to allow multiple forwards in the UI
* start working on db schema changes
* uncomment db schema, add migration to create the new model, and update create_item, update_item
stored procedures
* Propagate updates from discussion to poll, link, and bounty forms
Update the create, update poll sql functions for multi forward support
* Update gql, typedefs, and resolver to return forwarded users in items responses
* UI changes to show multiple forward recipients, and conditional upvote logic changes
* Update notification text to reflect multiple forwards upon vote action
* Disallow duplicate stacker entries
* reduce duplication in populating adv-post-form initial values
* Update item_act sql function to implement multi-way forwarding
* Update referral functions to scale referral bonuses for forwarded users
* Update notification text to reflect non-100% forwarded sats cases
* Update wallet history sql queries to accommodate multi-forward use cases
* Block zaps for posts you are forwarded zaps at the API layer, in addition
to in the UI
* Delete fwdUserId column from Item table as part of migration
* Fix how we calculate stacked sats after partial forwards in wallet history
* Exclude entries from wallet history that are 0 stacked sats from posts with 100% forwarded to other users
* Fix wallet history query for forwarded stacked sats to be scaled by the fwd pct
* Reduce duplication in adv post form, and do some style tweaks for better layout
* Use MAX_FORWARDS constants
* Address various PR feedback
* first enhancement pass
* enhancement pass too
---------
Co-authored-by: keyan <keyan.kousha+huumn@gmail.com>
Co-authored-by: Keyan <34140557+huumn@users.noreply.github.com>